* Pull request: bluetooth-next-2.6 2010-05-10 @ 2010-05-10 9:36 Marcel Holtmann 2010-05-10 9:36 ` [PATCH 01/64] Bluetooth: Fix return value when bt_skb_alloc fails Marcel Holtmann ` (2 more replies) 0 siblings, 3 replies; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:36 UTC (permalink / raw) To: David Miller; +Cc: netdev [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: text/plain, Size: 4797 bytes --] Hi Dave, this is the big merge for the L2CAP Enhanced Retransmission support work done by Gustavo F. Padovan. All other changes are small cleanups. Regards Marcel Please pull from git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluetooth-next-2.6.git master This will update the following files: drivers/bluetooth/btmrvl_drv.h | 8 +- drivers/bluetooth/btmrvl_main.c | 92 ++-- drivers/bluetooth/btmrvl_sdio.c | 7 +- drivers/bluetooth/hci_h4.c | 2 +- drivers/bluetooth/hci_ll.c | 8 +- drivers/bluetooth/hci_vhci.c | 2 +- include/net/bluetooth/hci_core.h | 6 +- include/net/bluetooth/l2cap.h | 41 +- net/bluetooth/Kconfig | 13 + net/bluetooth/hci_core.c | 27 +- net/bluetooth/hci_sysfs.c | 34 +- net/bluetooth/l2cap.c | 1108 +++++++++++++++++++++++++++++--------- net/bluetooth/sco.c | 26 +- 13 files changed, 1010 insertions(+), 364 deletions(-) through these ChangeSets: Bing Zhao (3): Bluetooth: Decode btmrvl MODULE_BRINGUP_REG response correctly Bluetooth: Separate btmrvl_register_hdev() from btmrvl_add_card() Bluetooth: Set hdev->dev_type based on Marvell device type Dan Carpenter (1): Bluetooth: Fix storing negative values as unsigned char Gustavo F. Padovan (54): Bluetooth: Fix return value when bt_skb_alloc fails Bluetooth: Use the proper function cast to get hdr data Bluetooth: Fix wrong packet type count increment Bluetooth: Make hci_send_sco() void Bluetooth: Trivial clean ups to SCO Bluetooth: Move specific Basic Mode code to the right place Bluetooth: Fix memory leak of S-frames into L2CAP Bluetooth: Fix expected_tx_seq calculation on L2CAP Bluetooth: Fix ACL MTU issue Bluetooth: Use a l2cap_pinfo struct instead l2cap_pi() macro Bluetooth: Implement 'Send IorRRorRNR' event Bluetooth: Support case with F bit set under WAIT_F state. Bluetooth: Check the minimum {I,S}-frame size into L2CAP Bluetooth: Check if SDU size is greater than MTU on L2CAP Bluetooth: Implement SendAck() Action on ERTM. Bluetooth: Move set of P-bit to l2cap_send_sframe() Bluetooth: Add Recv RR (P=0)(F=0) for SREJ_SENT state on ERTM Bluetooth: Split l2cap_data_channel_sframe() Bluetooth: Handle all cases of receipt of RNR-frames into L2CAP Bluetooth: Group the ack of I-frames into l2cap_data_channel_rrframe() Bluetooth: Remove duplicate use of __get_reqseq() macro on L2CAP Bluetooth: Finish implementation for Rec RR (P=1) on ERTM Bluetooth: Add timer to Acknowledge I-frames Bluetooth: Ignore Tx Window value with Streaming mode Bluetooth: Read RFC conf option on a successful Conf RSP Bluetooth: Fix configuration of the MPS value Bluetooth: Add le16 macro to Retransmission and Monitor Timeouts values Bluetooth: Check the SDU size against the MTU value Bluetooth: Send Ack after clear the SREJ list Bluetooth: Add sockopt configuration for txWindow on L2CAP Bluetooth: Change acknowledgement to use the value of txWindow Bluetooth: Add module parameter for txWindow size on L2CAP Bluetooth: Enable option to configure Max Transmission value via Bluetooth: Fix bug when retransmitting I-frames Bluetooth: Fix crash when monitor timeout expires Bluetooth: Fix drop of acked packets on ERTM Bluetooth: Optimize SREJ_QUEUE append Bluetooth: Add Kconfig option for L2CAP Extended Features Bluetooth: Add SOCK_STREAM support to L2CAP Bluetooth: Fix SDU reassembly under SREJ Bluetooth: Don't set control bits to zero first Bluetooth: Fix errors reported by checkpatch.pl Bluetooth: Remove set of SrejSaveReqSeq under receipt of REJ frame Bluetooth: Remove unneeded control vars Bluetooth: Check if we really are in WAIT_F when F bit comes Bluetooth: Fix lockdep annotation on ERTM Bluetooth: Make hci_send_acl() void Bluetooth: Refactor l2cap_retransmit_frame() Bluetooth: Implement missing parts of the Invalid Frame Detection Bluetooth: Implement Local Busy Condition handling Bluetooth: Add wait_queue to wait ack of all sent packets Bluetooth: Fix race condition on l2cap_ertm_send() Bluetooth: Prevents buffer overflow on l2cap_ertm_reassembly_sdu() Bluetooth: Fix spec error in the RemoteBusy Logic João Paulo Rechi Vita (3): Bluetooth: Check if mode is supported on getsockopt Bluetooth: Close L2CAP channel on invalid ReqSeq Bluetooth: Completes the I-frame tx_seq check logic on RECV Marcel Holtmann (2): Bluetooth: Create per controller workqueue Bluetooth: Fix issues where sk_sleep() helper is needed now Tomas Winkler (1): Bluetooth: Use strict_strtoul instead of simple_strtoul ^ permalink raw reply [flat|nested] 72+ messages in thread
* [PATCH 01/64] Bluetooth: Fix return value when bt_skb_alloc fails 2010-05-10 9:36 Pull request: bluetooth-next-2.6 2010-05-10 Marcel Holtmann @ 2010-05-10 9:36 ` Marcel Holtmann 2010-05-10 9:36 ` [PATCH 02/64] Bluetooth: Use the proper function cast to get hdr data Marcel Holtmann 2010-05-10 9:47 ` Pull request: bluetooth-next-2.6 2010-05-10 David Miller 2010-05-10 11:20 ` David Miller 2 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:36 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> Set the proper error(ENOMEM), instead of just return 0. Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> --- drivers/bluetooth/hci_h4.c | 2 +- drivers/bluetooth/hci_ll.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c index c0ce813..3f038f5 100644 --- a/drivers/bluetooth/hci_h4.c +++ b/drivers/bluetooth/hci_h4.c @@ -246,7 +246,7 @@ static int h4_recv(struct hci_uart *hu, void *data, int count) BT_ERR("Can't allocate mem for new packet"); h4->rx_state = H4_W4_PACKET_TYPE; h4->rx_count = 0; - return 0; + return -ENOMEM; } h4->rx_skb->dev = (void *) hu->hdev; diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index 5c65014..91e44df 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -491,7 +491,7 @@ static int ll_recv(struct hci_uart *hu, void *data, int count) BT_ERR("Can't allocate mem for new packet"); ll->rx_state = HCILL_W4_PACKET_TYPE; ll->rx_count = 0; - return 0; + return -ENOMEM; } ll->rx_skb->dev = (void *) hu->hdev; -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 02/64] Bluetooth: Use the proper function cast to get hdr data 2010-05-10 9:36 ` [PATCH 01/64] Bluetooth: Fix return value when bt_skb_alloc fails Marcel Holtmann @ 2010-05-10 9:36 ` Marcel Holtmann 2010-05-10 9:36 ` [PATCH 03/64] Bluetooth: Fix wrong packet type count increment Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:36 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> --- drivers/bluetooth/hci_ll.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index 91e44df..fb8445c 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -402,7 +402,7 @@ static int ll_recv(struct hci_uart *hu, void *data, int count) continue; case HCILL_W4_EVENT_HDR: - eh = (struct hci_event_hdr *) ll->rx_skb->data; + eh = hci_event_hdr(ll->rx_skb); BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen); @@ -410,7 +410,7 @@ static int ll_recv(struct hci_uart *hu, void *data, int count) continue; case HCILL_W4_ACL_HDR: - ah = (struct hci_acl_hdr *) ll->rx_skb->data; + ah = hci_acl_hdr(ll->rx_skb); dlen = __le16_to_cpu(ah->dlen); BT_DBG("ACL header: dlen %d", dlen); @@ -419,7 +419,7 @@ static int ll_recv(struct hci_uart *hu, void *data, int count) continue; case HCILL_W4_SCO_HDR: - sh = (struct hci_sco_hdr *) ll->rx_skb->data; + sh = hci_sco_hdr(ll->rx_skb); BT_DBG("SCO header: dlen %d", sh->dlen); -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 03/64] Bluetooth: Fix wrong packet type count increment 2010-05-10 9:36 ` [PATCH 02/64] Bluetooth: Use the proper function cast to get hdr data Marcel Holtmann @ 2010-05-10 9:36 ` Marcel Holtmann 2010-05-10 9:36 ` [PATCH 04/64] Bluetooth: Make hci_send_sco() void Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:36 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> --- drivers/bluetooth/hci_vhci.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index bb0aefd..3aa7b2a 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -157,7 +157,7 @@ static inline ssize_t vhci_put_user(struct vhci_data *data, break; case HCI_SCODATA_PKT: - data->hdev->stat.cmd_tx++; + data->hdev->stat.sco_tx++; break; }; -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 04/64] Bluetooth: Make hci_send_sco() void 2010-05-10 9:36 ` [PATCH 03/64] Bluetooth: Fix wrong packet type count increment Marcel Holtmann @ 2010-05-10 9:36 ` Marcel Holtmann 2010-05-10 9:36 ` [PATCH 05/64] Bluetooth: Trivial clean ups to SCO Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:36 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> It also removes an unneeded check for the MTU. The check is done before on sco_send_frame() 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> --- include/net/bluetooth/hci_core.h | 2 +- net/bluetooth/hci_core.c | 9 +-------- net/bluetooth/sco.c | 3 +-- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index ce3c99e..9830a88 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -637,7 +637,7 @@ 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); -int 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); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 4ad2319..1c9aef9 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1308,18 +1308,13 @@ int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags) EXPORT_SYMBOL(hci_send_acl); /* Send SCO data */ -int hci_send_sco(struct hci_conn *conn, struct sk_buff *skb) +void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb) { struct hci_dev *hdev = conn->hdev; struct hci_sco_hdr hdr; BT_DBG("%s len %d", hdev->name, skb->len); - if (skb->len > hdev->sco_mtu) { - kfree_skb(skb); - return -EINVAL; - } - hdr.handle = cpu_to_le16(conn->handle); hdr.dlen = skb->len; @@ -1332,8 +1327,6 @@ int hci_send_sco(struct hci_conn *conn, struct sk_buff *skb) skb_queue_tail(&conn->data_q, skb); tasklet_schedule(&hdev->tx_task); - - return 0; } EXPORT_SYMBOL(hci_send_sco); diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index b406d3e..541b26e 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -249,8 +249,7 @@ static inline int sco_send_frame(struct sock *sk, struct msghdr *msg, int len) goto fail; } - if ((err = hci_send_sco(conn->hcon, skb)) < 0) - return err; + hci_send_sco(conn->hcon, skb); return count; -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 05/64] Bluetooth: Trivial clean ups to SCO 2010-05-10 9:36 ` [PATCH 04/64] Bluetooth: Make hci_send_sco() void Marcel Holtmann @ 2010-05-10 9:36 ` Marcel Holtmann 2010-05-10 9:36 ` [PATCH 06/64] Bluetooth: Move specific Basic Mode code to the right place Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:36 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> Remove extra braces and labels, break over column 80 lines, etc Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> --- net/bluetooth/sco.c | 23 +++++++++++------------ 1 files changed, 11 insertions(+), 12 deletions(-) diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 541b26e..4767928 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -165,11 +165,11 @@ static inline int sco_chan_add(struct sco_conn *conn, struct sock *sk, struct so int err = 0; sco_conn_lock(conn); - if (conn->sk) { + if (conn->sk) err = -EBUSY; - } else { + else __sco_chan_add(conn, sk, parent); - } + sco_conn_unlock(conn); return err; } @@ -241,21 +241,19 @@ static inline int sco_send_frame(struct sock *sk, struct msghdr *msg, int len) BT_DBG("sk %p len %d", sk, len); count = min_t(unsigned int, conn->mtu, len); - if (!(skb = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err))) + skb = bt_skb_send_alloc(sk, count, + msg->msg_flags & MSG_DONTWAIT, &err); + if (!skb) return err; if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) { - err = -EFAULT; - goto fail; + kfree_skb(skb); + return -EFAULT; } hci_send_sco(conn->hcon, skb); return count; - -fail: - kfree_skb(skb); - return err; } static inline void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) @@ -625,7 +623,7 @@ static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len) { struct sock *sk = sock->sk; - int err = 0; + int err; BT_DBG("sock %p, sk %p", sock, sk); @@ -850,7 +848,8 @@ static void sco_conn_ready(struct sco_conn *conn) bh_lock_sock(parent); - sk = sco_sock_alloc(sock_net(parent), NULL, BTPROTO_SCO, GFP_ATOMIC); + sk = sco_sock_alloc(sock_net(parent), NULL, + BTPROTO_SCO, GFP_ATOMIC); if (!sk) { bh_unlock_sock(parent); goto done; -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 06/64] Bluetooth: Move specific Basic Mode code to the right place 2010-05-10 9:36 ` [PATCH 05/64] Bluetooth: Trivial clean ups to SCO Marcel Holtmann @ 2010-05-10 9:36 ` Marcel Holtmann 2010-05-10 9:36 ` [PATCH 07/64] Bluetooth: Fix memory leak of S-frames into L2CAP Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:36 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> Inside "case L2CAP_MODE_BASIC:" we don't need to check for sk_type and L2CAP mode. So only the length check is fine. 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> --- net/bluetooth/l2cap.c | 11 ++++++----- 1 files changed, 6 insertions(+), 5 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 864c76f..c9a848d 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1611,11 +1611,6 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms if (msg->msg_flags & MSG_OOB) return -EOPNOTSUPP; - /* Check outgoing MTU */ - if (sk->sk_type == SOCK_SEQPACKET && pi->mode == L2CAP_MODE_BASIC && - len > pi->omtu) - return -EINVAL; - lock_sock(sk); if (sk->sk_state != BT_CONNECTED) { @@ -1635,6 +1630,12 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms switch (pi->mode) { case L2CAP_MODE_BASIC: + /* Check outgoing MTU */ + if (len > pi->omtu) { + err = -EINVAL; + goto done; + } + /* Create a basic PDU */ skb = l2cap_create_basic_pdu(sk, msg, len); if (IS_ERR(skb)) { -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 07/64] Bluetooth: Fix memory leak of S-frames into L2CAP 2010-05-10 9:36 ` [PATCH 06/64] Bluetooth: Move specific Basic Mode code to the right place Marcel Holtmann @ 2010-05-10 9:36 ` Marcel Holtmann 2010-05-10 9:36 ` [PATCH 08/64] Bluetooth: Fix expected_tx_seq calculation on L2CAP Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:36 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> l2cap_data_channel do not free the S-frame, so we free it here. 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> --- net/bluetooth/l2cap.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index c9a848d..46f2264 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3522,6 +3522,7 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str break; } + kfree_skb(skb); return 0; } -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 08/64] Bluetooth: Fix expected_tx_seq calculation on L2CAP 2010-05-10 9:36 ` [PATCH 07/64] Bluetooth: Fix memory leak of S-frames into L2CAP Marcel Holtmann @ 2010-05-10 9:36 ` Marcel Holtmann 2010-05-10 9:36 ` [PATCH 09/64] Bluetooth: Fix ACL MTU issue Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:36 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> All operation related to the txWindow should be modulo 64. 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> --- net/bluetooth/l2cap.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 46f2264..401011a 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3611,7 +3611,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk if (pi->expected_tx_seq == tx_seq) pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; else - pi->expected_tx_seq = tx_seq + 1; + pi->expected_tx_seq = (tx_seq + 1) % 64; l2cap_sar_reassembly_sdu(sk, skb, control); -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 09/64] Bluetooth: Fix ACL MTU issue 2010-05-10 9:36 ` [PATCH 08/64] Bluetooth: Fix expected_tx_seq calculation on L2CAP Marcel Holtmann @ 2010-05-10 9:36 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 10/64] Bluetooth: Use a l2cap_pinfo struct instead l2cap_pi() macro Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:36 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> ERTM and Streaming Modes was having problems when the ACL MTU is lower than MPS. The 'minus 10' is to take in account the header and fcs lenghts. 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> --- net/bluetooth/l2cap.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 401011a..99cf177 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -2267,6 +2267,8 @@ done: rfc.retrans_timeout = 0; rfc.monitor_timeout = 0; rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE); + if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10) + rfc.max_pdu_size = pi->conn->mtu - 10; l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), (unsigned long) &rfc); @@ -2288,6 +2290,8 @@ done: rfc.retrans_timeout = 0; rfc.monitor_timeout = 0; rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE); + if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10) + rfc.max_pdu_size = pi->conn->mtu - 10; l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), (unsigned long) &rfc); -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 10/64] Bluetooth: Use a l2cap_pinfo struct instead l2cap_pi() macro 2010-05-10 9:36 ` [PATCH 09/64] Bluetooth: Fix ACL MTU issue Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 11/64] Bluetooth: Implement 'Send IorRRorRNR' event Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> Trivial clean up. 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> --- net/bluetooth/l2cap.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 99cf177..a9c152a 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1291,7 +1291,7 @@ static int l2cap_streaming_send(struct sock *sk) control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT; put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); - if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16) { + if (pi->fcs == L2CAP_FCS_CRC16) { fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2); put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2); } @@ -1344,7 +1344,7 @@ static int l2cap_retransmit_frame(struct sock *sk, u8 tx_seq) | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); - if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16) { + if (pi->fcs == L2CAP_FCS_CRC16) { fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2); put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2); } @@ -1388,7 +1388,7 @@ static int l2cap_ertm_send(struct sock *sk) put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); - if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16) { + if (pi->fcs == L2CAP_FCS_CRC16) { fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2); put_unaligned_le16(fcs, skb->data + tx_skb->len - 2); } @@ -3518,10 +3518,10 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str pi->expected_ack_seq = tx_seq; l2cap_drop_acked_frames(sk); - del_timer(&l2cap_pi(sk)->retrans_timer); + del_timer(&pi->retrans_timer); if (rx_control & L2CAP_CTRL_POLL) { u16 control = L2CAP_CTRL_FINAL; - l2cap_send_rr_or_rnr(l2cap_pi(sk), control); + l2cap_send_rr_or_rnr(pi, control); } break; } @@ -3622,7 +3622,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk goto done; default: - BT_DBG("sk %p: bad mode 0x%2.2x", sk, l2cap_pi(sk)->mode); + BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode); break; } -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 11/64] Bluetooth: Implement 'Send IorRRorRNR' event 2010-05-10 9:37 ` [PATCH 10/64] Bluetooth: Use a l2cap_pinfo struct instead l2cap_pi() macro Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 12/64] Bluetooth: Support case with F bit set under WAIT_F state Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> After receive a RR with P bit set ERTM shall use this funcion to choose what type of frame to reply with F bit = 1. 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> --- include/net/bluetooth/l2cap.h | 20 ++++++++++-------- net/bluetooth/l2cap.c | 43 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 13 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 17a689f..d9c20c3 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -320,7 +320,7 @@ struct l2cap_pinfo { __u8 conf_req[64]; __u8 conf_len; __u8 conf_state; - __u8 conn_state; + __u16 conn_state; __u8 next_tx_seq; __u8 expected_ack_seq; @@ -328,6 +328,7 @@ struct l2cap_pinfo { __u8 buffer_seq; __u8 buffer_seq_srej; __u8 srej_save_reqseq; + __u8 frames_sent; __u8 unacked_frames; __u8 retry_count; __u8 num_to_ack; @@ -367,14 +368,15 @@ struct l2cap_pinfo { #define L2CAP_CONF_MAX_CONF_REQ 2 #define L2CAP_CONF_MAX_CONF_RSP 2 -#define L2CAP_CONN_SAR_SDU 0x01 -#define L2CAP_CONN_SREJ_SENT 0x02 -#define L2CAP_CONN_WAIT_F 0x04 -#define L2CAP_CONN_SREJ_ACT 0x08 -#define L2CAP_CONN_SEND_PBIT 0x10 -#define L2CAP_CONN_REMOTE_BUSY 0x20 -#define L2CAP_CONN_LOCAL_BUSY 0x40 -#define L2CAP_CONN_REJ_ACT 0x80 +#define L2CAP_CONN_SAR_SDU 0x0001 +#define L2CAP_CONN_SREJ_SENT 0x0002 +#define L2CAP_CONN_WAIT_F 0x0004 +#define L2CAP_CONN_SREJ_ACT 0x0008 +#define L2CAP_CONN_SEND_PBIT 0x0010 +#define L2CAP_CONN_REMOTE_BUSY 0x0020 +#define L2CAP_CONN_LOCAL_BUSY 0x0040 +#define L2CAP_CONN_REJ_ACT 0x0080 +#define L2CAP_CONN_SEND_FBIT 0x0100 #define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \ jiffies + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO)); diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index a9c152a..06687e2 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1383,6 +1383,10 @@ static int l2cap_ertm_send(struct sock *sk) bt_cb(skb)->retries++; control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); + if (pi->conn_state & L2CAP_CONN_SEND_FBIT) { + control |= L2CAP_CTRL_FINAL; + pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; + } control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); @@ -1404,6 +1408,7 @@ static int l2cap_ertm_send(struct sock *sk) pi->next_tx_seq = (pi->next_tx_seq + 1) % 64; pi->unacked_frames++; + pi->frames_sent++; if (skb_queue_is_last(TX_QUEUE(sk), skb)) sk->sk_send_head = NULL; @@ -2191,6 +2196,7 @@ static inline void l2cap_ertm_init(struct sock *sk) l2cap_pi(sk)->unacked_frames = 0; l2cap_pi(sk)->buffer_seq = 0; l2cap_pi(sk)->num_to_ack = 0; + l2cap_pi(sk)->frames_sent = 0; setup_timer(&l2cap_pi(sk)->retrans_timer, l2cap_retrans_timeout, (unsigned long) sk); @@ -3148,6 +3154,38 @@ static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb) return 0; } +static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk) +{ + struct l2cap_pinfo *pi = l2cap_pi(sk); + u16 control = 0; + + pi->frames_sent = 0; + pi->conn_state |= L2CAP_CONN_SEND_FBIT; + + control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; + + if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { + control |= L2CAP_SUPER_RCV_NOT_READY | L2CAP_CTRL_FINAL; + l2cap_send_sframe(pi, control); + pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; + } + + if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY && pi->unacked_frames > 0) + __mod_retrans_timer(); + + l2cap_ertm_send(sk); + + if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) && + pi->frames_sent == 0) { + control |= L2CAP_SUPER_RCV_READY; + if (pi->conn_state & L2CAP_CONN_SEND_FBIT) { + control |= L2CAP_CTRL_FINAL; + pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; + } + l2cap_send_sframe(pi, control); + } +} + static void l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar) { struct sk_buff *next_skb; @@ -3418,10 +3456,7 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str switch (rx_control & L2CAP_CTRL_SUPERVISE) { case L2CAP_SUPER_RCV_READY: if (rx_control & L2CAP_CTRL_POLL) { - u16 control = L2CAP_CTRL_FINAL; - control |= L2CAP_SUPER_RCV_READY | - (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT); - l2cap_send_sframe(l2cap_pi(sk), control); + l2cap_send_i_or_rr_or_rnr(sk); pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; } else if (rx_control & L2CAP_CTRL_FINAL) { -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 12/64] Bluetooth: Support case with F bit set under WAIT_F state. 2010-05-10 9:37 ` [PATCH 11/64] Bluetooth: Implement 'Send IorRRorRNR' event Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 13/64] Bluetooth: Check the minimum {I,S}-frame size into L2CAP Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> On receipt of a F=1 under WAIT_F state ERTM shall stop monitor timer and start retransmission timer (if there are unacked frames). 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> --- net/bluetooth/l2cap.c | 22 ++++++++++++++-------- 1 files changed, 14 insertions(+), 8 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 06687e2..36cd4e4 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3364,6 +3364,13 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len); + if (L2CAP_CTRL_FINAL & rx_control) { + del_timer(&pi->monitor_timer); + if (pi->unacked_frames > 0) + __mod_retrans_timer(); + pi->conn_state &= ~L2CAP_CONN_WAIT_F; + } + pi->expected_ack_seq = req_seq; l2cap_drop_acked_frames(sk); @@ -3453,6 +3460,13 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len); + if (L2CAP_CTRL_FINAL & rx_control) { + del_timer(&pi->monitor_timer); + if (pi->unacked_frames > 0) + __mod_retrans_timer(); + pi->conn_state &= ~L2CAP_CONN_WAIT_F; + } + switch (rx_control & L2CAP_CTRL_SUPERVISE) { case L2CAP_SUPER_RCV_READY: if (rx_control & L2CAP_CTRL_POLL) { @@ -3472,14 +3486,6 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str l2cap_ertm_send(sk); } - if (!(pi->conn_state & L2CAP_CONN_WAIT_F)) - break; - - pi->conn_state &= ~L2CAP_CONN_WAIT_F; - del_timer(&pi->monitor_timer); - - if (pi->unacked_frames > 0) - __mod_retrans_timer(); } else { pi->expected_ack_seq = tx_seq; l2cap_drop_acked_frames(sk); -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 13/64] Bluetooth: Check the minimum {I,S}-frame size into L2CAP 2010-05-10 9:37 ` [PATCH 12/64] Bluetooth: Support case with F bit set under WAIT_F state Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 14/64] Bluetooth: Check if SDU size is greater than MTU on L2CAP Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> All packets with size fewer than the minimum specified is dropped. Note that the size of the l2cap basic header, FCS and SAR fields are already subtracted of len at the moment of the size check. 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> --- net/bluetooth/l2cap.c | 14 +++++++++++--- 1 files changed, 11 insertions(+), 3 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 36cd4e4..ac00f5f 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3627,10 +3627,17 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk if (l2cap_check_fcs(pi, skb)) goto drop; - if (__is_iframe(control)) + if (__is_iframe(control)) { + if (len < 4) + goto drop; + l2cap_data_channel_iframe(sk, control, skb); - else + } else { + if (len != 0) + goto drop; + l2cap_data_channel_sframe(sk, control, skb); + } goto done; @@ -3645,7 +3652,8 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk if (pi->fcs == L2CAP_FCS_CRC16) len -= 2; - if (len > L2CAP_DEFAULT_MAX_PDU_SIZE || __is_sframe(control)) + if (len > L2CAP_DEFAULT_MAX_PDU_SIZE || len < 4 + || __is_sframe(control)) goto drop; if (l2cap_check_fcs(pi, skb)) -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 14/64] Bluetooth: Check if SDU size is greater than MTU on L2CAP 2010-05-10 9:37 ` [PATCH 13/64] Bluetooth: Check the minimum {I,S}-frame size into L2CAP Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 15/64] Bluetooth: Implement SendAck() Action on ERTM Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> After reassembly the SDU we need to check his size. It can't overflow the MTU size. 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> --- net/bluetooth/l2cap.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index ac00f5f..2e354d2 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3277,15 +3277,19 @@ static int l2cap_sar_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 co pi->conn_state &= ~L2CAP_CONN_SAR_SDU; pi->partial_sdu_len += skb->len; + if (pi->partial_sdu_len > pi->imtu) + goto drop; + if (pi->partial_sdu_len == pi->sdu_len) { _skb = skb_clone(pi->sdu, GFP_ATOMIC); err = sock_queue_rcv_skb(sk, _skb); if (err < 0) kfree_skb(_skb); } - kfree_skb(pi->sdu); err = 0; +drop: + kfree_skb(pi->sdu); break; } -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 15/64] Bluetooth: Implement SendAck() Action on ERTM. 2010-05-10 9:37 ` [PATCH 14/64] Bluetooth: Check if SDU size is greater than MTU on L2CAP Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 16/64] Bluetooth: Move set of P-bit to l2cap_send_sframe() Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> Shall be used to ack received frames, It must decide type of acknowledgment between a RR frame, a RNR frame or transmission of pending I-frames. It also modifies l2cap_ertm_send() to report the number of frames sent. 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> --- net/bluetooth/l2cap.c | 41 +++++++++++++++++++++++++++++------------ 1 files changed, 29 insertions(+), 12 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 2e354d2..0a739ef 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -352,6 +352,11 @@ static inline int l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) count = min_t(unsigned int, conn->mtu, hlen); control |= L2CAP_CTRL_FRAME_TYPE; + if (pi->conn_state & L2CAP_CONN_SEND_FBIT) { + control |= L2CAP_CTRL_FINAL; + pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; + } + skb = bt_skb_alloc(count, GFP_ATOMIC); if (!skb) return -ENOMEM; @@ -1364,7 +1369,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; + int err, nsent = 0; if (pi->conn_state & L2CAP_CONN_WAIT_F) return 0; @@ -1414,8 +1419,27 @@ static int l2cap_ertm_send(struct sock *sk) sk->sk_send_head = NULL; else sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb); + + nsent++; } + return nsent; +} + +static int l2cap_send_ack(struct l2cap_pinfo *pi) +{ + struct sock *sk = (struct sock *)pi; + u16 control = 0; + + control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; + + if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { + control |= L2CAP_SUPER_RCV_NOT_READY; + return l2cap_send_sframe(pi, control); + } else if (l2cap_ertm_send(sk) == 0) { + control |= L2CAP_SUPER_RCV_READY; + return l2cap_send_sframe(pi, control); + } return 0; } @@ -1678,7 +1702,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms else err = l2cap_ertm_send(sk); - if (!err) + if (err >= 0) err = len; break; @@ -3178,10 +3202,6 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk) if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) && pi->frames_sent == 0) { control |= L2CAP_SUPER_RCV_READY; - if (pi->conn_state & L2CAP_CONN_SEND_FBIT) { - control |= L2CAP_CTRL_FINAL; - pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; - } l2cap_send_sframe(pi, control); } } @@ -3362,7 +3382,6 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str struct l2cap_pinfo *pi = l2cap_pi(sk); u8 tx_seq = __get_txseq(rx_control); u8 req_seq = __get_reqseq(rx_control); - u16 tx_control = 0; u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT; int err = 0; @@ -3449,11 +3468,9 @@ expected: return err; pi->num_to_ack = (pi->num_to_ack + 1) % L2CAP_DEFAULT_NUM_TO_ACK; - if (pi->num_to_ack == L2CAP_DEFAULT_NUM_TO_ACK - 1) { - tx_control |= L2CAP_SUPER_RCV_READY; - tx_control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; - l2cap_send_sframe(pi, tx_control); - } + if (pi->num_to_ack == L2CAP_DEFAULT_NUM_TO_ACK - 1) + l2cap_send_ack(pi); + return 0; } -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 16/64] Bluetooth: Move set of P-bit to l2cap_send_sframe() 2010-05-10 9:37 ` [PATCH 15/64] Bluetooth: Implement SendAck() Action on ERTM Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 17/64] Bluetooth: Add Recv RR (P=0)(F=0) for SREJ_SENT state on ERTM Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> Abstract the send of of P-bit and avoids code duplication like we did with the setting of F-bit. 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> --- net/bluetooth/l2cap.c | 9 +++++---- 1 files changed, 5 insertions(+), 4 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 0a739ef..852c140 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -357,6 +357,11 @@ static inline int l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; } + if (pi->conn_state & L2CAP_CONN_SEND_PBIT) { + control |= L2CAP_CTRL_POLL; + pi->conn_state &= ~L2CAP_CONN_SEND_PBIT; + } + skb = bt_skb_alloc(count, GFP_ATOMIC); if (!skb) return -ENOMEM; @@ -3364,10 +3369,6 @@ static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq) while (tx_seq != pi->expected_tx_seq) { control = L2CAP_SUPER_SELECT_REJECT; control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; - if (pi->conn_state & L2CAP_CONN_SEND_PBIT) { - control |= L2CAP_CTRL_POLL; - pi->conn_state &= ~L2CAP_CONN_SEND_PBIT; - } l2cap_send_sframe(pi, control); new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 17/64] Bluetooth: Add Recv RR (P=0)(F=0) for SREJ_SENT state on ERTM 2010-05-10 9:37 ` [PATCH 16/64] Bluetooth: Move set of P-bit to l2cap_send_sframe() Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 18/64] Bluetooth: Split l2cap_data_channel_sframe() Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> This finishes the implementation of Recv RR (P=0)(F=0) for the Enhanced Retransmission Mode on L2CAP. 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> --- net/bluetooth/l2cap.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 852c140..e5cd64a 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3517,7 +3517,10 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str __mod_retrans_timer(); pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; - l2cap_ertm_send(sk); + if (pi->conn_state & L2CAP_CONN_SREJ_SENT) + l2cap_send_ack(pi); + else + l2cap_ertm_send(sk); } break; -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 18/64] Bluetooth: Split l2cap_data_channel_sframe() 2010-05-10 9:37 ` [PATCH 17/64] Bluetooth: Add Recv RR (P=0)(F=0) for SREJ_SENT state on ERTM Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 19/64] Bluetooth: Handle all cases of receipt of RNR-frames into L2CAP Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> Create a function for each type fo S-frame and avoid a lot of nested code. 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> --- net/bluetooth/l2cap.c | 204 +++++++++++++++++++++++++++--------------------- 1 files changed, 115 insertions(+), 89 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index e5cd64a..068edf7 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3475,120 +3475,146 @@ expected: return 0; } -static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb) +static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control) { struct l2cap_pinfo *pi = l2cap_pi(sk); u8 tx_seq = __get_reqseq(rx_control); - BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len); - - if (L2CAP_CTRL_FINAL & rx_control) { - del_timer(&pi->monitor_timer); - if (pi->unacked_frames > 0) - __mod_retrans_timer(); - pi->conn_state &= ~L2CAP_CONN_WAIT_F; - } + if (rx_control & L2CAP_CTRL_POLL) { + l2cap_send_i_or_rr_or_rnr(sk); + pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; - switch (rx_control & L2CAP_CTRL_SUPERVISE) { - case L2CAP_SUPER_RCV_READY: - if (rx_control & L2CAP_CTRL_POLL) { - l2cap_send_i_or_rr_or_rnr(sk); - pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; - - } else if (rx_control & L2CAP_CTRL_FINAL) { - pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; - pi->expected_ack_seq = tx_seq; - l2cap_drop_acked_frames(sk); - - if (pi->conn_state & L2CAP_CONN_REJ_ACT) - pi->conn_state &= ~L2CAP_CONN_REJ_ACT; - else { - sk->sk_send_head = TX_QUEUE(sk)->next; - pi->next_tx_seq = pi->expected_ack_seq; - l2cap_ertm_send(sk); - } + } else if (rx_control & L2CAP_CTRL_FINAL) { + pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + pi->expected_ack_seq = tx_seq; + l2cap_drop_acked_frames(sk); - } else { - pi->expected_ack_seq = tx_seq; - l2cap_drop_acked_frames(sk); + if (pi->conn_state & L2CAP_CONN_REJ_ACT) + pi->conn_state &= ~L2CAP_CONN_REJ_ACT; + else { + sk->sk_send_head = TX_QUEUE(sk)->next; + pi->next_tx_seq = pi->expected_ack_seq; + l2cap_ertm_send(sk); + } - if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) && - (pi->unacked_frames > 0)) - __mod_retrans_timer(); + } else { + pi->expected_ack_seq = tx_seq; + l2cap_drop_acked_frames(sk); - pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; - if (pi->conn_state & L2CAP_CONN_SREJ_SENT) - l2cap_send_ack(pi); - else - l2cap_ertm_send(sk); - } - break; + if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) && + (pi->unacked_frames > 0)) + __mod_retrans_timer(); - case L2CAP_SUPER_REJECT: pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + if (pi->conn_state & L2CAP_CONN_SREJ_SENT) + l2cap_send_ack(pi); + else + l2cap_ertm_send(sk); + } +} - pi->expected_ack_seq = __get_reqseq(rx_control); - l2cap_drop_acked_frames(sk); +static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control) +{ + struct l2cap_pinfo *pi = l2cap_pi(sk); + u8 tx_seq = __get_reqseq(rx_control); - if (rx_control & L2CAP_CTRL_FINAL) { - if (pi->conn_state & L2CAP_CONN_REJ_ACT) - pi->conn_state &= ~L2CAP_CONN_REJ_ACT; - else { - sk->sk_send_head = TX_QUEUE(sk)->next; - pi->next_tx_seq = pi->expected_ack_seq; - l2cap_ertm_send(sk); - } - } else { + pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + + pi->expected_ack_seq = __get_reqseq(rx_control); + l2cap_drop_acked_frames(sk); + + if (rx_control & L2CAP_CTRL_FINAL) { + if (pi->conn_state & L2CAP_CONN_REJ_ACT) + pi->conn_state &= ~L2CAP_CONN_REJ_ACT; + else { sk->sk_send_head = TX_QUEUE(sk)->next; pi->next_tx_seq = pi->expected_ack_seq; l2cap_ertm_send(sk); - - if (pi->conn_state & L2CAP_CONN_WAIT_F) { - pi->srej_save_reqseq = tx_seq; - pi->conn_state |= L2CAP_CONN_REJ_ACT; - } } + } else { + sk->sk_send_head = TX_QUEUE(sk)->next; + pi->next_tx_seq = pi->expected_ack_seq; + l2cap_ertm_send(sk); - break; + if (pi->conn_state & L2CAP_CONN_WAIT_F) { + pi->srej_save_reqseq = tx_seq; + pi->conn_state |= L2CAP_CONN_REJ_ACT; + } + } +} +static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control) +{ + struct l2cap_pinfo *pi = l2cap_pi(sk); + u8 tx_seq = __get_reqseq(rx_control); - case L2CAP_SUPER_SELECT_REJECT: - pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; - if (rx_control & L2CAP_CTRL_POLL) { - pi->expected_ack_seq = tx_seq; - l2cap_drop_acked_frames(sk); - l2cap_retransmit_frame(sk, tx_seq); - l2cap_ertm_send(sk); - if (pi->conn_state & L2CAP_CONN_WAIT_F) { - pi->srej_save_reqseq = tx_seq; - pi->conn_state |= L2CAP_CONN_SREJ_ACT; - } - } else if (rx_control & L2CAP_CTRL_FINAL) { - if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) && - pi->srej_save_reqseq == tx_seq) - pi->conn_state &= ~L2CAP_CONN_SREJ_ACT; - else - l2cap_retransmit_frame(sk, tx_seq); + if (rx_control & L2CAP_CTRL_POLL) { + pi->expected_ack_seq = tx_seq; + l2cap_drop_acked_frames(sk); + l2cap_retransmit_frame(sk, tx_seq); + l2cap_ertm_send(sk); + if (pi->conn_state & L2CAP_CONN_WAIT_F) { + pi->srej_save_reqseq = tx_seq; + pi->conn_state |= L2CAP_CONN_SREJ_ACT; } - else { + } else if (rx_control & L2CAP_CTRL_FINAL) { + if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) && + pi->srej_save_reqseq == tx_seq) + pi->conn_state &= ~L2CAP_CONN_SREJ_ACT; + else l2cap_retransmit_frame(sk, tx_seq); - if (pi->conn_state & L2CAP_CONN_WAIT_F) { - pi->srej_save_reqseq = tx_seq; - pi->conn_state |= L2CAP_CONN_SREJ_ACT; - } + } else { + l2cap_retransmit_frame(sk, tx_seq); + if (pi->conn_state & L2CAP_CONN_WAIT_F) { + pi->srej_save_reqseq = tx_seq; + pi->conn_state |= L2CAP_CONN_SREJ_ACT; } + } +} + +static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control) +{ + struct l2cap_pinfo *pi = l2cap_pi(sk); + u8 tx_seq = __get_reqseq(rx_control); + + pi->conn_state |= L2CAP_CONN_REMOTE_BUSY; + pi->expected_ack_seq = tx_seq; + l2cap_drop_acked_frames(sk); + + del_timer(&pi->retrans_timer); + if (rx_control & L2CAP_CTRL_POLL) { + u16 control = L2CAP_CTRL_FINAL; + l2cap_send_rr_or_rnr(pi, control); + } +} + +static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb) +{ + BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len); + + if (L2CAP_CTRL_FINAL & rx_control) { + del_timer(&l2cap_pi(sk)->monitor_timer); + if (l2cap_pi(sk)->unacked_frames > 0) + __mod_retrans_timer(); + l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F; + } + + switch (rx_control & L2CAP_CTRL_SUPERVISE) { + case L2CAP_SUPER_RCV_READY: + l2cap_data_channel_rrframe(sk, rx_control); break; - case L2CAP_SUPER_RCV_NOT_READY: - pi->conn_state |= L2CAP_CONN_REMOTE_BUSY; - pi->expected_ack_seq = tx_seq; - l2cap_drop_acked_frames(sk); + case L2CAP_SUPER_REJECT: + l2cap_data_channel_rejframe(sk, rx_control); + break; - del_timer(&pi->retrans_timer); - if (rx_control & L2CAP_CTRL_POLL) { - u16 control = L2CAP_CTRL_FINAL; - l2cap_send_rr_or_rnr(pi, control); - } + case L2CAP_SUPER_SELECT_REJECT: + l2cap_data_channel_srejframe(sk, rx_control); + break; + + case L2CAP_SUPER_RCV_NOT_READY: + l2cap_data_channel_rnrframe(sk, rx_control); break; } -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 19/64] Bluetooth: Handle all cases of receipt of RNR-frames into L2CAP 2010-05-10 9:37 ` [PATCH 18/64] Bluetooth: Split l2cap_data_channel_sframe() Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 20/64] Bluetooth: Group the ack of I-frames into l2cap_data_channel_rrframe() Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> We weren't handling the receipt under SREJ_SENT state table. It also introduce l2cap_send_srejtail(). It will be used in the nexts commits too. 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> --- net/bluetooth/l2cap.c | 32 ++++++++++++++++++++++++++++---- 1 files changed, 28 insertions(+), 4 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 068edf7..8937a84 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1448,6 +1448,22 @@ static int l2cap_send_ack(struct l2cap_pinfo *pi) return 0; } +static int l2cap_send_srejtail(struct sock *sk) +{ + struct srej_list *tail; + u16 control; + + control = L2CAP_SUPER_SELECT_REJECT; + control |= L2CAP_CTRL_FINAL; + + tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list); + 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) { struct l2cap_conn *conn = l2cap_pi(sk)->conn; @@ -3582,11 +3598,19 @@ static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control) pi->expected_ack_seq = tx_seq; l2cap_drop_acked_frames(sk); - del_timer(&pi->retrans_timer); - if (rx_control & L2CAP_CTRL_POLL) { - u16 control = L2CAP_CTRL_FINAL; - l2cap_send_rr_or_rnr(pi, control); + if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) { + del_timer(&pi->retrans_timer); + if (rx_control & L2CAP_CTRL_POLL) { + u16 control = L2CAP_CTRL_FINAL; + l2cap_send_rr_or_rnr(pi, control); + } + return; } + + if (rx_control & L2CAP_CTRL_POLL) + l2cap_send_srejtail(sk); + else + l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY); } static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb) -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 20/64] Bluetooth: Group the ack of I-frames into l2cap_data_channel_rrframe() 2010-05-10 9:37 ` [PATCH 19/64] Bluetooth: Handle all cases of receipt of RNR-frames into L2CAP Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 21/64] Bluetooth: Remove duplicate use of __get_reqseq() macro on L2CAP Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> It also fix a bug: we weren't acknowledging I-frames when P=1. Note that when F=1 we are acknowledging packets before setting RemoteBusy to False. The spec says we should do that in the opposite order, but acknowledment of packets doesn't care about RemoteBusy flag so we can do that in the order we want. 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> --- net/bluetooth/l2cap.c | 9 +++------ 1 files changed, 3 insertions(+), 6 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 8937a84..d096c7c 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3494,7 +3494,9 @@ expected: static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control) { struct l2cap_pinfo *pi = l2cap_pi(sk); - u8 tx_seq = __get_reqseq(rx_control); + + pi->expected_ack_seq = __get_reqseq(rx_control); + l2cap_drop_acked_frames(sk); if (rx_control & L2CAP_CTRL_POLL) { l2cap_send_i_or_rr_or_rnr(sk); @@ -3502,8 +3504,6 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control) } else if (rx_control & L2CAP_CTRL_FINAL) { pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; - pi->expected_ack_seq = tx_seq; - l2cap_drop_acked_frames(sk); if (pi->conn_state & L2CAP_CONN_REJ_ACT) pi->conn_state &= ~L2CAP_CONN_REJ_ACT; @@ -3514,9 +3514,6 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control) } } else { - pi->expected_ack_seq = tx_seq; - l2cap_drop_acked_frames(sk); - if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) && (pi->unacked_frames > 0)) __mod_retrans_timer(); -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 21/64] Bluetooth: Remove duplicate use of __get_reqseq() macro on L2CAP 2010-05-10 9:37 ` [PATCH 20/64] Bluetooth: Group the ack of I-frames into l2cap_data_channel_rrframe() Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 22/64] Bluetooth: Finish implementation for Rec RR (P=1) on ERTM Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> tx_seq var already has the value of __get_reqseq(). 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> --- net/bluetooth/l2cap.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index d096c7c..e9ac9fb 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3533,7 +3533,7 @@ static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control) pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; - pi->expected_ack_seq = __get_reqseq(rx_control); + pi->expected_ack_seq = tx_seq; l2cap_drop_acked_frames(sk); if (rx_control & L2CAP_CTRL_FINAL) { -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 22/64] Bluetooth: Finish implementation for Rec RR (P=1) on ERTM 2010-05-10 9:37 ` [PATCH 21/64] Bluetooth: Remove duplicate use of __get_reqseq() macro on L2CAP Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 23/64] Bluetooth: Add timer to Acknowledge I-frames Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> Now the code handles the case under SREJ_SENT state. 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> --- net/bluetooth/l2cap.c | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index e9ac9fb..f386985 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3499,8 +3499,17 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control) l2cap_drop_acked_frames(sk); if (rx_control & L2CAP_CTRL_POLL) { - l2cap_send_i_or_rr_or_rnr(sk); - pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { + if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) && + (pi->unacked_frames > 0)) + __mod_retrans_timer(); + + pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + l2cap_send_srejtail(sk); + } else { + l2cap_send_i_or_rr_or_rnr(sk); + pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + } } else if (rx_control & L2CAP_CTRL_FINAL) { pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 23/64] Bluetooth: Add timer to Acknowledge I-frames 2010-05-10 9:37 ` [PATCH 22/64] Bluetooth: Finish implementation for Rec RR (P=1) on ERTM Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 24/64] Bluetooth: Ignore Tx Window value with Streaming mode Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> We ack I-frames on each txWindow/5 I-frames received, but if the sender stop to send I-frames and it's not a txWindow multiple we can leave some frames unacked. So I added a timer to ack I-frames on this case. The timer expires in 200ms. 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> --- include/net/bluetooth/l2cap.h | 4 ++++ net/bluetooth/l2cap.c | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 0 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index d9c20c3..48f10f4 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -35,6 +35,7 @@ #define L2CAP_DEFAULT_RETRANS_TO 1000 /* 1 second */ #define L2CAP_DEFAULT_MONITOR_TO 12000 /* 12 seconds */ #define L2CAP_DEFAULT_MAX_PDU_SIZE 672 +#define L2CAP_DEFAULT_ACK_TO 200 #define L2CAP_CONN_TIMEOUT (40000) /* 40 seconds */ #define L2CAP_INFO_TIMEOUT (4000) /* 4 seconds */ @@ -348,6 +349,7 @@ struct l2cap_pinfo { struct timer_list retrans_timer; struct timer_list monitor_timer; + struct timer_list ack_timer; struct sk_buff_head tx_queue; struct sk_buff_head srej_queue; struct srej_list srej_l; @@ -382,6 +384,8 @@ struct l2cap_pinfo { jiffies + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO)); #define __mod_monitor_timer() mod_timer(&l2cap_pi(sk)->monitor_timer, \ jiffies + msecs_to_jiffies(L2CAP_DEFAULT_MONITOR_TO)); +#define __mod_ack_timer() mod_timer(&l2cap_pi(sk)->ack_timer, \ + jiffies + msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO)); static inline int l2cap_tx_window_full(struct sock *sk) { diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index f386985..0300656 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -2235,6 +2235,15 @@ static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) *ptr += L2CAP_CONF_OPT_SIZE + len; } +static void l2cap_ack_timeout(unsigned long arg) +{ + struct sock *sk = (void *) arg; + + bh_lock_sock(sk); + l2cap_send_ack(l2cap_pi(sk)); + bh_unlock_sock(sk); +} + static inline void l2cap_ertm_init(struct sock *sk) { l2cap_pi(sk)->expected_ack_seq = 0; @@ -2247,6 +2256,8 @@ static inline void l2cap_ertm_init(struct sock *sk) l2cap_retrans_timeout, (unsigned long) sk); setup_timer(&l2cap_pi(sk)->monitor_timer, l2cap_monitor_timeout, (unsigned long) sk); + setup_timer(&l2cap_pi(sk)->ack_timer, + l2cap_ack_timeout, (unsigned long) sk); __skb_queue_head_init(SREJ_QUEUE(sk)); } @@ -2975,6 +2986,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd skb_queue_purge(SREJ_QUEUE(sk)); del_timer(&l2cap_pi(sk)->retrans_timer); del_timer(&l2cap_pi(sk)->monitor_timer); + del_timer(&l2cap_pi(sk)->ack_timer); } l2cap_chan_del(sk, ECONNRESET); @@ -3005,6 +3017,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd skb_queue_purge(SREJ_QUEUE(sk)); del_timer(&l2cap_pi(sk)->retrans_timer); del_timer(&l2cap_pi(sk)->monitor_timer); + del_timer(&l2cap_pi(sk)->ack_timer); } l2cap_chan_del(sk, 0); @@ -3484,6 +3497,8 @@ expected: if (err < 0) return err; + __mod_ack_timer(); + pi->num_to_ack = (pi->num_to_ack + 1) % L2CAP_DEFAULT_NUM_TO_ACK; if (pi->num_to_ack == L2CAP_DEFAULT_NUM_TO_ACK - 1) l2cap_send_ack(pi); -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 24/64] Bluetooth: Ignore Tx Window value with Streaming mode 2010-05-10 9:37 ` [PATCH 23/64] Bluetooth: Add timer to Acknowledge I-frames Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 25/64] Bluetooth: Read RFC conf option on a successful Conf RSP Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> Tx Window value shall not be used with Streaming Mode and the receiver of the config Request shall ignore its value. 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> --- net/bluetooth/l2cap.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 0300656..f604405 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -2495,7 +2495,6 @@ done: break; case L2CAP_MODE_STREAMING: - pi->remote_tx_win = rfc.txwin_size; pi->max_pdu_size = rfc.max_pdu_size; pi->conf_state |= L2CAP_CONF_MODE_DONE; -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 25/64] Bluetooth: Read RFC conf option on a successful Conf RSP 2010-05-10 9:37 ` [PATCH 24/64] Bluetooth: Ignore Tx Window value with Streaming mode Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 26/64] Bluetooth: Fix configuration of the MPS value Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> On Enhanced Retransmission Mode and Streaming Mode a entity can send, on a successful Conf RSP, new values for the RFC fields. For example, the entity can send txWindow and MPS values less than the value received on a Conf REQ. 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> --- net/bluetooth/l2cap.c | 39 ++++++++++++++++++++++++++++++++++++++- 1 files changed, 38 insertions(+), 1 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index f604405..c50c057 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -2602,6 +2602,42 @@ static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 fla return ptr - data; } +static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len) +{ + struct l2cap_pinfo *pi = l2cap_pi(sk); + int type, olen; + unsigned long val; + struct l2cap_conf_rfc rfc; + + BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len); + + if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING)) + return; + + while (len >= L2CAP_CONF_OPT_SIZE) { + len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); + + switch (type) { + case L2CAP_CONF_RFC: + if (olen == sizeof(rfc)) + memcpy(&rfc, (void *)val, olen); + goto done; + } + } + +done: + switch (rfc.mode) { + case L2CAP_MODE_ERTM: + pi->remote_tx_win = rfc.txwin_size; + pi->retrans_timeout = rfc.retrans_timeout; + pi->monitor_timeout = rfc.monitor_timeout; + pi->mps = le16_to_cpu(rfc.max_pdu_size); + break; + case L2CAP_MODE_STREAMING: + pi->mps = le16_to_cpu(rfc.max_pdu_size); + } +} + static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) { struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data; @@ -2881,6 +2917,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; u16 scid, flags, result; struct sock *sk; + int len = cmd->len - sizeof(*rsp); scid = __le16_to_cpu(rsp->scid); flags = __le16_to_cpu(rsp->flags); @@ -2895,11 +2932,11 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr switch (result) { case L2CAP_CONF_SUCCESS: + l2cap_conf_rfc_get(sk, rsp->data, len); break; case L2CAP_CONF_UNACCEPT: if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { - int len = cmd->len - sizeof(*rsp); char req[64]; if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 26/64] Bluetooth: Fix configuration of the MPS value 2010-05-10 9:37 ` [PATCH 25/64] Bluetooth: Read RFC conf option on a successful Conf RSP Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 27/64] Bluetooth: Add le16 macro to Retransmission and Monitor Timeouts values Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> We were accepting values bigger than we can accept. This was leading ERTM to drop packets because of wrong FCS checks. 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> --- include/net/bluetooth/l2cap.h | 3 ++- net/bluetooth/l2cap.c | 36 ++++++++++++++++++++---------------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 48f10f4..0f4e423 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -343,7 +343,8 @@ struct l2cap_pinfo { __u8 remote_max_tx; __u16 retrans_timeout; __u16 monitor_timeout; - __u16 max_pdu_size; + __u16 remote_mps; + __u16 mps; __le16 sport; diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index c50c057..94be5db 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1606,21 +1606,21 @@ static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, siz __skb_queue_head_init(&sar_queue); control = L2CAP_SDU_START; - skb = l2cap_create_iframe_pdu(sk, msg, pi->max_pdu_size, control, len); + skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len); if (IS_ERR(skb)) return PTR_ERR(skb); __skb_queue_tail(&sar_queue, skb); - len -= pi->max_pdu_size; - size +=pi->max_pdu_size; + len -= pi->remote_mps; + size += pi->remote_mps; control = 0; while (len > 0) { size_t buflen; - if (len > pi->max_pdu_size) { + if (len > pi->remote_mps) { control |= L2CAP_SDU_CONTINUE; - buflen = pi->max_pdu_size; + buflen = pi->remote_mps; } else { control |= L2CAP_SDU_END; buflen = len; @@ -1701,7 +1701,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms case L2CAP_MODE_ERTM: case L2CAP_MODE_STREAMING: /* Entire SDU fits into one PDU */ - if (len <= pi->max_pdu_size) { + if (len <= pi->remote_mps) { control = L2CAP_SDU_UNSEGMENTED; skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0); if (IS_ERR(skb)) { @@ -2330,7 +2330,7 @@ done: rfc.monitor_timeout = 0; rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE); if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10) - rfc.max_pdu_size = pi->conn->mtu - 10; + rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), (unsigned long) &rfc); @@ -2353,7 +2353,7 @@ done: rfc.monitor_timeout = 0; rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE); if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10) - rfc.max_pdu_size = pi->conn->mtu - 10; + rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), (unsigned long) &rfc); @@ -2482,7 +2482,10 @@ done: case L2CAP_MODE_ERTM: pi->remote_tx_win = rfc.txwin_size; pi->remote_max_tx = rfc.max_transmit; - pi->max_pdu_size = rfc.max_pdu_size; + if (rfc.max_pdu_size > pi->conn->mtu - 10) + rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10); + + pi->remote_mps = le16_to_cpu(rfc.max_pdu_size); rfc.retrans_timeout = L2CAP_DEFAULT_RETRANS_TO; rfc.monitor_timeout = L2CAP_DEFAULT_MONITOR_TO; @@ -2495,7 +2498,10 @@ done: break; case L2CAP_MODE_STREAMING: - pi->max_pdu_size = rfc.max_pdu_size; + if (rfc.max_pdu_size > pi->conn->mtu - 10) + rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10); + + pi->remote_mps = le16_to_cpu(rfc.max_pdu_size); pi->conf_state |= L2CAP_CONF_MODE_DONE; @@ -2574,11 +2580,10 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, pi->remote_tx_win = rfc.txwin_size; pi->retrans_timeout = rfc.retrans_timeout; pi->monitor_timeout = rfc.monitor_timeout; - pi->max_pdu_size = le16_to_cpu(rfc.max_pdu_size); + pi->mps = le16_to_cpu(rfc.max_pdu_size); break; case L2CAP_MODE_STREAMING: - pi->max_pdu_size = le16_to_cpu(rfc.max_pdu_size); - break; + pi->mps = le16_to_cpu(rfc.max_pdu_size); } } @@ -3753,7 +3758,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk * Receiver will miss it and start proper recovery * procedures and ask retransmission. */ - if (len > L2CAP_DEFAULT_MAX_PDU_SIZE) + if (len > pi->mps) goto drop; if (l2cap_check_fcs(pi, skb)) @@ -3784,8 +3789,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk if (pi->fcs == L2CAP_FCS_CRC16) len -= 2; - if (len > L2CAP_DEFAULT_MAX_PDU_SIZE || len < 4 - || __is_sframe(control)) + if (len > pi->mps || len < 4 || __is_sframe(control)) goto drop; if (l2cap_check_fcs(pi, skb)) -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 27/64] Bluetooth: Add le16 macro to Retransmission and Monitor Timeouts values 2010-05-10 9:37 ` [PATCH 26/64] Bluetooth: Fix configuration of the MPS value Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 28/64] Bluetooth: Check the SDU size against the MTU value Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> Fix a possible problem with Big Endian machines. 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> --- net/bluetooth/l2cap.c | 14 ++++++++------ 1 files changed, 8 insertions(+), 6 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 94be5db..0889949 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -2487,8 +2487,10 @@ done: pi->remote_mps = le16_to_cpu(rfc.max_pdu_size); - rfc.retrans_timeout = L2CAP_DEFAULT_RETRANS_TO; - rfc.monitor_timeout = L2CAP_DEFAULT_MONITOR_TO; + rfc.retrans_timeout = + le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO); + rfc.monitor_timeout = + le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO); pi->conf_state |= L2CAP_CONF_MODE_DONE; @@ -2578,8 +2580,8 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, switch (rfc.mode) { case L2CAP_MODE_ERTM: pi->remote_tx_win = rfc.txwin_size; - pi->retrans_timeout = rfc.retrans_timeout; - pi->monitor_timeout = rfc.monitor_timeout; + pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); + pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); pi->mps = le16_to_cpu(rfc.max_pdu_size); break; case L2CAP_MODE_STREAMING: @@ -2634,8 +2636,8 @@ done: switch (rfc.mode) { case L2CAP_MODE_ERTM: pi->remote_tx_win = rfc.txwin_size; - pi->retrans_timeout = rfc.retrans_timeout; - pi->monitor_timeout = rfc.monitor_timeout; + pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); + pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); pi->mps = le16_to_cpu(rfc.max_pdu_size); break; case L2CAP_MODE_STREAMING: -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 28/64] Bluetooth: Check the SDU size against the MTU value 2010-05-10 9:37 ` [PATCH 27/64] Bluetooth: Add le16 macro to Retransmission and Monitor Timeouts values Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 29/64] Bluetooth: Send Ack after clear the SREJ list Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> If the SDU size is greater than the MTU something is wrong, so report an error. Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi> [jprvita@profusion.mobi: set err to appropriate errno value] Signed-off-by: João Paulo Rechi Vita <jprvita@profusion.mobi> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> --- net/bluetooth/l2cap.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 0889949..e936913 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3338,6 +3338,11 @@ static int l2cap_sar_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 co pi->sdu_len = get_unaligned_le16(skb->data); skb_pull(skb, 2); + if (pi->sdu_len > pi->imtu) { + err = -EMSGSIZE; + break; + } + pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC); if (!pi->sdu) { err = -ENOMEM; -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 29/64] Bluetooth: Send Ack after clear the SREJ list 2010-05-10 9:37 ` [PATCH 28/64] Bluetooth: Check the SDU size against the MTU value Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 30/64] Bluetooth: Add sockopt configuration for txWindow on L2CAP Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> As specified by Bluetooth 3.0 spec we shall send an acknowledgment using the Send-Ack() after clear the SREJ list. 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> --- net/bluetooth/l2cap.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index e936913..c6bc1b9 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3493,6 +3493,7 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str if (list_empty(SREJ_LIST(sk))) { pi->buffer_seq = pi->buffer_seq_srej; pi->conn_state &= ~L2CAP_CONN_SREJ_SENT; + l2cap_send_ack(pi); } } else { struct srej_list *l; -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 30/64] Bluetooth: Add sockopt configuration for txWindow on L2CAP 2010-05-10 9:37 ` [PATCH 29/64] Bluetooth: Send Ack after clear the SREJ list Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 31/64] Bluetooth: Change acknowledgement to use the value of txWindow Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> Now we can set/get Transmission Window size via sockopt. 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> --- include/net/bluetooth/l2cap.h | 2 ++ net/bluetooth/l2cap.c | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 0f4e423..07ae4cc 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -56,6 +56,7 @@ struct l2cap_options { __u16 flush_to; __u8 mode; __u8 fcs; + __u16 txwin_size; }; #define L2CAP_CONNINFO 0x02 @@ -339,6 +340,7 @@ struct l2cap_pinfo { __u8 ident; + __u8 tx_win; __u8 remote_tx_win; __u8 remote_max_tx; __u16 retrans_timeout; diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index c6bc1b9..5300796 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -782,6 +782,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) pi->omtu = l2cap_pi(parent)->omtu; pi->mode = l2cap_pi(parent)->mode; pi->fcs = l2cap_pi(parent)->fcs; + pi->tx_win = l2cap_pi(parent)->tx_win; pi->sec_level = l2cap_pi(parent)->sec_level; pi->role_switch = l2cap_pi(parent)->role_switch; pi->force_reliable = l2cap_pi(parent)->force_reliable; @@ -790,6 +791,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) pi->omtu = 0; pi->mode = L2CAP_MODE_BASIC; pi->fcs = L2CAP_FCS_CRC16; + pi->tx_win = L2CAP_DEFAULT_TX_WINDOW; pi->sec_level = BT_SECURITY_LOW; pi->role_switch = 0; pi->force_reliable = 0; @@ -1782,6 +1784,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us opts.flush_to = l2cap_pi(sk)->flush_to; opts.mode = l2cap_pi(sk)->mode; opts.fcs = l2cap_pi(sk)->fcs; + opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win; len = min_t(unsigned int, sizeof(opts), optlen); if (copy_from_user((char *) &opts, optval, len)) { @@ -1793,6 +1796,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us l2cap_pi(sk)->omtu = opts.omtu; l2cap_pi(sk)->mode = opts.mode; l2cap_pi(sk)->fcs = opts.fcs; + l2cap_pi(sk)->tx_win = (__u8)opts.txwin_size; break; case L2CAP_LM: @@ -1907,6 +1911,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us opts.flush_to = l2cap_pi(sk)->flush_to; opts.mode = l2cap_pi(sk)->mode; opts.fcs = l2cap_pi(sk)->fcs; + opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win; len = min_t(unsigned int, len, sizeof(opts)); if (copy_to_user(optval, (char *) &opts, len)) @@ -2324,7 +2329,7 @@ done: case L2CAP_MODE_ERTM: rfc.mode = L2CAP_MODE_ERTM; - rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; + rfc.txwin_size = pi->tx_win; rfc.max_transmit = max_transmit; rfc.retrans_timeout = 0; rfc.monitor_timeout = 0; -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 31/64] Bluetooth: Change acknowledgement to use the value of txWindow 2010-05-10 9:37 ` [PATCH 30/64] Bluetooth: Add sockopt configuration for txWindow on L2CAP Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 32/64] Bluetooth: Add module parameter for txWindow size on L2CAP Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> Now that we can set the txWindow we need to change the acknowledgement procedure to ack after each (pi->txWindow/6 + 1). The plus 1 is to avoid the zero value. It also renames pi->num_to_ack to a better name: pi->num_acked. 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> --- include/net/bluetooth/l2cap.h | 3 +-- net/bluetooth/l2cap.c | 7 ++++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 07ae4cc..059260b 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -30,7 +30,6 @@ #define L2CAP_DEFAULT_MIN_MTU 48 #define L2CAP_DEFAULT_FLUSH_TO 0xffff #define L2CAP_DEFAULT_TX_WINDOW 63 -#define L2CAP_DEFAULT_NUM_TO_ACK (L2CAP_DEFAULT_TX_WINDOW/5) #define L2CAP_DEFAULT_MAX_TX 3 #define L2CAP_DEFAULT_RETRANS_TO 1000 /* 1 second */ #define L2CAP_DEFAULT_MONITOR_TO 12000 /* 12 seconds */ @@ -333,7 +332,7 @@ struct l2cap_pinfo { __u8 frames_sent; __u8 unacked_frames; __u8 retry_count; - __u8 num_to_ack; + __u8 num_acked; __u16 sdu_len; __u16 partial_sdu_len; struct sk_buff *sdu; diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 5300796..0b0b237 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -2254,7 +2254,7 @@ static inline void l2cap_ertm_init(struct sock *sk) l2cap_pi(sk)->expected_ack_seq = 0; l2cap_pi(sk)->unacked_frames = 0; l2cap_pi(sk)->buffer_seq = 0; - l2cap_pi(sk)->num_to_ack = 0; + l2cap_pi(sk)->num_acked = 0; l2cap_pi(sk)->frames_sent = 0; setup_timer(&l2cap_pi(sk)->retrans_timer, @@ -3466,6 +3466,7 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str u8 tx_seq = __get_txseq(rx_control); u8 req_seq = __get_reqseq(rx_control); u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT; + int num_to_ack = (pi->tx_win/6) + 1; int err = 0; BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len); @@ -3553,8 +3554,8 @@ expected: __mod_ack_timer(); - pi->num_to_ack = (pi->num_to_ack + 1) % L2CAP_DEFAULT_NUM_TO_ACK; - if (pi->num_to_ack == L2CAP_DEFAULT_NUM_TO_ACK - 1) + pi->num_acked = (pi->num_acked + 1) % num_to_ack; + if (pi->num_acked == num_to_ack - 1) l2cap_send_ack(pi); return 0; -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 32/64] Bluetooth: Add module parameter for txWindow size on L2CAP 2010-05-10 9:37 ` [PATCH 31/64] Bluetooth: Change acknowledgement to use the value of txWindow Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 33/64] Bluetooth: Enable option to configure Max Transmission value via sockopt Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> Very useful for testing purposes. Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi> [jprvita@profusion.mobi: improved parameter description] Signed-off-by: João Paulo Rechi Vita <jprvita@profusion.mobi> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> --- net/bluetooth/l2cap.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 0b0b237..ff1466b 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -57,6 +57,7 @@ static int enable_ertm = 0; static int max_transmit = L2CAP_DEFAULT_MAX_TX; +static int tx_window = L2CAP_DEFAULT_TX_WINDOW; static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; static u8 l2cap_fixed_chan[8] = { 0x02, }; @@ -791,7 +792,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) pi->omtu = 0; pi->mode = L2CAP_MODE_BASIC; pi->fcs = L2CAP_FCS_CRC16; - pi->tx_win = L2CAP_DEFAULT_TX_WINDOW; + pi->tx_win = tx_window; pi->sec_level = BT_SECURITY_LOW; pi->role_switch = 0; pi->force_reliable = 0; @@ -4296,6 +4297,9 @@ MODULE_PARM_DESC(enable_ertm, "Enable enhanced retransmission mode"); module_param(max_transmit, uint, 0644); MODULE_PARM_DESC(max_transmit, "Max transmit value (default = 3)"); +module_param(tx_window, uint, 0644); +MODULE_PARM_DESC(tx_window, "Transmission window size value (default = 63)"); + MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION); MODULE_VERSION(VERSION); -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 33/64] Bluetooth: Enable option to configure Max Transmission value via sockopt 2010-05-10 9:37 ` [PATCH 32/64] Bluetooth: Add module parameter for txWindow size on L2CAP Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 34/64] Bluetooth: Fix bug when retransmitting I-frames Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> With the sockopt extension we can set a per-channel MaxTx value. 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> --- include/net/bluetooth/l2cap.h | 2 ++ net/bluetooth/l2cap.c | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 059260b..8942c2f 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -55,6 +55,7 @@ struct l2cap_options { __u16 flush_to; __u8 mode; __u8 fcs; + __u8 max_tx; __u16 txwin_size; }; @@ -340,6 +341,7 @@ struct l2cap_pinfo { __u8 ident; __u8 tx_win; + __u8 max_tx; __u8 remote_tx_win; __u8 remote_max_tx; __u16 retrans_timeout; diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index ff1466b..f9e4da2 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -783,6 +783,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) pi->omtu = l2cap_pi(parent)->omtu; pi->mode = l2cap_pi(parent)->mode; pi->fcs = l2cap_pi(parent)->fcs; + pi->max_tx = l2cap_pi(parent)->max_tx; pi->tx_win = l2cap_pi(parent)->tx_win; pi->sec_level = l2cap_pi(parent)->sec_level; pi->role_switch = l2cap_pi(parent)->role_switch; @@ -791,6 +792,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) pi->imtu = L2CAP_DEFAULT_MTU; pi->omtu = 0; pi->mode = L2CAP_MODE_BASIC; + pi->max_tx = max_transmit; pi->fcs = L2CAP_FCS_CRC16; pi->tx_win = tx_window; pi->sec_level = BT_SECURITY_LOW; @@ -1785,6 +1787,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us opts.flush_to = l2cap_pi(sk)->flush_to; opts.mode = l2cap_pi(sk)->mode; opts.fcs = l2cap_pi(sk)->fcs; + opts.max_tx = l2cap_pi(sk)->max_tx; opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win; len = min_t(unsigned int, sizeof(opts), optlen); @@ -1797,6 +1800,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us l2cap_pi(sk)->omtu = opts.omtu; l2cap_pi(sk)->mode = opts.mode; l2cap_pi(sk)->fcs = opts.fcs; + l2cap_pi(sk)->max_tx = opts.max_tx; l2cap_pi(sk)->tx_win = (__u8)opts.txwin_size; break; @@ -1912,6 +1916,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us opts.flush_to = l2cap_pi(sk)->flush_to; opts.mode = l2cap_pi(sk)->mode; opts.fcs = l2cap_pi(sk)->fcs; + opts.max_tx = l2cap_pi(sk)->max_tx; opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win; len = min_t(unsigned int, len, sizeof(opts)); @@ -2331,7 +2336,7 @@ done: case L2CAP_MODE_ERTM: rfc.mode = L2CAP_MODE_ERTM; rfc.txwin_size = pi->tx_win; - rfc.max_transmit = max_transmit; + rfc.max_transmit = pi->max_tx; rfc.retrans_timeout = 0; rfc.monitor_timeout = 0; rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE); -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 34/64] Bluetooth: Fix bug when retransmitting I-frames 2010-05-10 9:37 ` [PATCH 33/64] Bluetooth: Enable option to configure Max Transmission value via sockopt Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 35/64] Bluetooth: Fix crash when monitor timeout expires Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> If there is no frames to retransmit l2cap was crashing the kernel, now we check if the queue is empty first. 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> --- net/bluetooth/l2cap.c | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index f9e4da2..4c7b2d2 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3546,7 +3546,8 @@ expected: if (pi->conn_state & L2CAP_CONN_REJ_ACT) pi->conn_state &= ~L2CAP_CONN_REJ_ACT; else { - sk->sk_send_head = TX_QUEUE(sk)->next; + if (!skb_queue_empty(TX_QUEUE(sk))) + sk->sk_send_head = TX_QUEUE(sk)->next; pi->next_tx_seq = pi->expected_ack_seq; l2cap_ertm_send(sk); } @@ -3593,7 +3594,8 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control) if (pi->conn_state & L2CAP_CONN_REJ_ACT) pi->conn_state &= ~L2CAP_CONN_REJ_ACT; else { - sk->sk_send_head = TX_QUEUE(sk)->next; + if (!skb_queue_empty(TX_QUEUE(sk))) + sk->sk_send_head = TX_QUEUE(sk)->next; pi->next_tx_seq = pi->expected_ack_seq; l2cap_ertm_send(sk); } @@ -3625,12 +3627,14 @@ static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control) if (pi->conn_state & L2CAP_CONN_REJ_ACT) pi->conn_state &= ~L2CAP_CONN_REJ_ACT; else { - sk->sk_send_head = TX_QUEUE(sk)->next; + if (!skb_queue_empty(TX_QUEUE(sk))) + sk->sk_send_head = TX_QUEUE(sk)->next; pi->next_tx_seq = pi->expected_ack_seq; l2cap_ertm_send(sk); } } else { - sk->sk_send_head = TX_QUEUE(sk)->next; + if (!skb_queue_empty(TX_QUEUE(sk))) + sk->sk_send_head = TX_QUEUE(sk)->next; pi->next_tx_seq = pi->expected_ack_seq; l2cap_ertm_send(sk); -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 35/64] Bluetooth: Fix crash when monitor timeout expires 2010-05-10 9:37 ` [PATCH 34/64] Bluetooth: Fix bug when retransmitting I-frames Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 36/64] Bluetooth: Fix drop of acked packets on ERTM Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> The code was crashing due to a invalid access to hci_conn after the channel disconnect. 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> --- net/bluetooth/l2cap.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 4c7b2d2..2f9bbad 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1568,6 +1568,9 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *m BT_DBG("sk %p len %d", sk, (int)len); + if (!conn) + return ERR_PTR(-ENOTCONN); + if (sdulen) hlen += 2; -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 36/64] Bluetooth: Fix drop of acked packets on ERTM 2010-05-10 9:37 ` [PATCH 35/64] Bluetooth: Fix crash when monitor timeout expires Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 37/64] Bluetooth: Optimize SREJ_QUEUE append Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> l2cap_drop_acked_frames() was droping not sent packets, causing them to be not transmitted. 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> --- net/bluetooth/l2cap.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 2f9bbad..042fd96 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1262,7 +1262,8 @@ static void l2cap_drop_acked_frames(struct sock *sk) { struct sk_buff *skb; - while ((skb = skb_peek(TX_QUEUE(sk)))) { + while ((skb = skb_peek(TX_QUEUE(sk))) && + l2cap_pi(sk)->unacked_frames) { if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq) break; -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 37/64] Bluetooth: Optimize SREJ_QUEUE append 2010-05-10 9:37 ` [PATCH 36/64] Bluetooth: Fix drop of acked packets on ERTM Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 38/64] Bluetooth: Add Kconfig option for L2CAP Extended Features Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> When the I-frame received is the expected, i.e., its tx_seq is equal to expected_tx_seq and we are under a SREJ, we can just add it to the tail of the list. Doing that we change the complexity from O(n) to O(1). 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> --- net/bluetooth/l2cap.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 042fd96..187f46d 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3542,7 +3542,9 @@ expected: pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { - l2cap_add_to_srej_queue(sk, skb, tx_seq, sar); + bt_cb(skb)->tx_seq = tx_seq; + bt_cb(skb)->sar = sar; + __skb_queue_tail(SREJ_QUEUE(sk), skb); return 0; } -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 38/64] Bluetooth: Add Kconfig option for L2CAP Extended Features 2010-05-10 9:37 ` [PATCH 37/64] Bluetooth: Optimize SREJ_QUEUE append Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 39/64] Bluetooth: Add SOCK_STREAM support to L2CAP Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> The L2CAP Extended Features are still unstable and under development, so we are adding them under the EXPERIMENTAL flag to get more feedback on them. L2CAP Extended Features includes the Enhanced Retransmission and Streaming Modes, Frame Check Sequence (FCS), and Segmentation and Reassemby (SAR). 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> --- net/bluetooth/Kconfig | 13 +++++++++++++ net/bluetooth/l2cap.c | 4 ++++ 2 files changed, 17 insertions(+), 0 deletions(-) diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig index ed37168..ee3b304 100644 --- a/net/bluetooth/Kconfig +++ b/net/bluetooth/Kconfig @@ -43,6 +43,19 @@ config BT_L2CAP Say Y here to compile L2CAP support into the kernel or say M to compile it as module (l2cap). +config BT_L2CAP_EXT_FEATURES + bool "L2CAP Extended Features support (EXPERIMENTAL)" + depends on BT_L2CAP && EXPERIMENTAL + help + This option enables the L2CAP Extended Features support. These + new features include the Enhanced Retransmission and Streaming + Modes, the Frame Check Sequence (FCS), and Segmentation and + Reassembly (SAR) for L2CAP packets. They are a required for the + new Alternate MAC/PHY and the Bluetooth Medical Profile. + + You should say N unless you know what you are doing. Note that + this is in an experimental state yet. + config BT_SCO tristate "SCO links support" depends on BT diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 187f46d..4c00720 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -55,7 +55,11 @@ #define VERSION "2.14" +#ifdef CONFIG_BT_L2CAP_EXT_FEATURES +static int enable_ertm = 1; +#else static int enable_ertm = 0; +#endif static int max_transmit = L2CAP_DEFAULT_MAX_TX; static int tx_window = L2CAP_DEFAULT_TX_WINDOW; -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 39/64] Bluetooth: Add SOCK_STREAM support to L2CAP 2010-05-10 9:37 ` [PATCH 38/64] Bluetooth: Add Kconfig option for L2CAP Extended Features Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 40/64] Bluetooth: Check if mode is supported on getsockopt Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> if enable_ertm is true and we have SOCK_STREAM the default mode will be ERTM, otherwise Basic Mode. 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> --- net/bluetooth/l2cap.c | 40 ++++++++++++++++++++++++++-------------- 1 files changed, 26 insertions(+), 14 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 4c00720..1a32562 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -224,7 +224,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct so l2cap_pi(sk)->conn = conn; - if (sk->sk_type == SOCK_SEQPACKET) { + if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) { /* Alloc CID for connection-oriented socket */ l2cap_pi(sk)->scid = l2cap_alloc_cid(l); } else if (sk->sk_type == SOCK_DGRAM) { @@ -452,7 +452,8 @@ static void l2cap_conn_start(struct l2cap_conn *conn) for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { bh_lock_sock(sk); - if (sk->sk_type != SOCK_SEQPACKET) { + if (sk->sk_type != SOCK_SEQPACKET && + sk->sk_type != SOCK_STREAM) { bh_unlock_sock(sk); continue; } @@ -512,7 +513,8 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { bh_lock_sock(sk); - if (sk->sk_type != SOCK_SEQPACKET) { + if (sk->sk_type != SOCK_SEQPACKET && + sk->sk_type != SOCK_STREAM) { l2cap_sock_clear_timer(sk); sk->sk_state = BT_CONNECTED; sk->sk_state_change(sk); @@ -721,7 +723,8 @@ static void __l2cap_sock_close(struct sock *sk, int reason) case BT_CONNECTED: case BT_CONFIG: - if (sk->sk_type == SOCK_SEQPACKET) { + if (sk->sk_type == SOCK_SEQPACKET || + sk->sk_type == SOCK_STREAM) { struct l2cap_conn *conn = l2cap_pi(sk)->conn; sk->sk_state = BT_DISCONN; @@ -732,7 +735,8 @@ static void __l2cap_sock_close(struct sock *sk, int reason) break; case BT_CONNECT2: - if (sk->sk_type == SOCK_SEQPACKET) { + if (sk->sk_type == SOCK_SEQPACKET || + sk->sk_type == SOCK_STREAM) { struct l2cap_conn *conn = l2cap_pi(sk)->conn; struct l2cap_conn_rsp rsp; __u16 result; @@ -795,7 +799,10 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) } else { pi->imtu = L2CAP_DEFAULT_MTU; pi->omtu = 0; - pi->mode = L2CAP_MODE_BASIC; + if (enable_ertm && sk->sk_type == SOCK_STREAM) + pi->mode = L2CAP_MODE_ERTM; + else + pi->mode = L2CAP_MODE_BASIC; pi->max_tx = max_transmit; pi->fcs = L2CAP_FCS_CRC16; pi->tx_win = tx_window; @@ -852,7 +859,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, sock->state = SS_UNCONNECTED; - if (sock->type != SOCK_SEQPACKET && + if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM && sock->type != SOCK_DGRAM && sock->type != SOCK_RAW) return -ESOCKTNOSUPPORT; @@ -1000,7 +1007,8 @@ static int l2cap_do_connect(struct sock *sk) l2cap_sock_set_timer(sk, sk->sk_sndtimeo); if (hcon->state == BT_CONNECTED) { - if (sk->sk_type != SOCK_SEQPACKET) { + if (sk->sk_type != SOCK_SEQPACKET && + sk->sk_type != SOCK_STREAM) { l2cap_sock_clear_timer(sk); sk->sk_state = BT_CONNECTED; } else @@ -1034,7 +1042,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al lock_sock(sk); - if (sk->sk_type == SOCK_SEQPACKET && !la.l2_psm) { + if ((sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) + && !la.l2_psm) { err = -EINVAL; goto done; } @@ -1098,7 +1107,8 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) lock_sock(sk); - if (sk->sk_state != BT_BOUND || sock->type != SOCK_SEQPACKET) { + if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM) + || sk->sk_state != BT_BOUND) { err = -EBADFD; goto done; } @@ -1857,7 +1867,8 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch switch (optname) { case BT_SECURITY: - if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_RAW) { + if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM + && sk->sk_type != SOCK_RAW) { err = -EINVAL; break; } @@ -2007,7 +2018,8 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch switch (optname) { case BT_SECURITY: - if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_RAW) { + if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM + && sk->sk_type != SOCK_RAW) { err = -EINVAL; break; } @@ -2314,7 +2326,7 @@ static int l2cap_build_conf_req(struct sock *sk, void *data) { struct l2cap_pinfo *pi = l2cap_pi(sk); struct l2cap_conf_req *req = data; - struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; + struct l2cap_conf_rfc rfc = { .mode = pi->mode }; void *ptr = req->data; BT_DBG("sk %p", sk); @@ -3997,7 +4009,7 @@ static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt) { - if (sk->sk_type != SOCK_SEQPACKET) + if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM) return; if (encrypt == 0x00) { -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 40/64] Bluetooth: Check if mode is supported on getsockopt 2010-05-10 9:37 ` [PATCH 39/64] Bluetooth: Add SOCK_STREAM support to L2CAP Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 41/64] Bluetooth: Fix SDU reassembly under SREJ Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: João Paulo Rechi Vita <jprvita@profusion.mobi> Add this check to getsockopt makes possible to fail early instead of waiting until listen / connect. Signed-off-by: João Paulo Rechi Vita <jprvita@profusion.mobi> Acked-by: Gustavo F. Padovan <padovan@profusion.mobi> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> --- net/bluetooth/l2cap.c | 15 ++++++++++++++- 1 files changed, 14 insertions(+), 1 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 1a32562..bf5bb7d 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1814,9 +1814,22 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us break; } + l2cap_pi(sk)->mode = opts.mode; + switch (l2cap_pi(sk)->mode) { + case L2CAP_MODE_BASIC: + break; + case L2CAP_MODE_ERTM: + case L2CAP_MODE_STREAMING: + if (enable_ertm) + break; + /* fall through */ + default: + err = -EINVAL; + break; + } + l2cap_pi(sk)->imtu = opts.imtu; l2cap_pi(sk)->omtu = opts.omtu; - l2cap_pi(sk)->mode = opts.mode; l2cap_pi(sk)->fcs = opts.fcs; l2cap_pi(sk)->max_tx = opts.max_tx; l2cap_pi(sk)->tx_win = (__u8)opts.txwin_size; -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 41/64] Bluetooth: Fix SDU reassembly under SREJ 2010-05-10 9:37 ` [PATCH 40/64] Bluetooth: Check if mode is supported on getsockopt Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 42/64] Bluetooth: Close L2CAP channel on invalid ReqSeq Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> The code was reusing the control var without its reinitialization. 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> --- net/bluetooth/l2cap.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index bf5bb7d..478def7 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3446,14 +3446,14 @@ drop: static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq) { struct sk_buff *skb; - u16 control = 0; + u16 control; while((skb = skb_peek(SREJ_QUEUE(sk)))) { if (bt_cb(skb)->tx_seq != tx_seq) break; skb = skb_dequeue(SREJ_QUEUE(sk)); - control |= bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; + control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; l2cap_sar_reassembly_sdu(sk, skb, control); l2cap_pi(sk)->buffer_seq_srej = (l2cap_pi(sk)->buffer_seq_srej + 1) % 64; -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 42/64] Bluetooth: Close L2CAP channel on invalid ReqSeq 2010-05-10 9:37 ` [PATCH 41/64] Bluetooth: Fix SDU reassembly under SREJ Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 43/64] Bluetooth: Don't set control bits to zero first Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: João Paulo Rechi Vita <jprvita@profusion.mobi> Signed-off-by: João Paulo Rechi Vita <jprvita@profusion.mobi> Acked-by: Gustavo F. Padovan <padovan@profusion.mobi> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> --- net/bluetooth/l2cap.c | 18 +++++++++++++++++- 1 files changed, 17 insertions(+), 1 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 478def7..31514d8 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3772,7 +3772,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk struct sock *sk; struct l2cap_pinfo *pi; u16 control, len; - u8 tx_seq; + u8 tx_seq, req_seq, next_tx_seq_offset, req_seq_offset; sk = l2cap_get_chan_by_scid(&conn->chan_list, cid); if (!sk) { @@ -3823,6 +3823,22 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk if (l2cap_check_fcs(pi, skb)) goto drop; + req_seq = __get_reqseq(control); + req_seq_offset = (req_seq - pi->expected_ack_seq) % 64; + if (req_seq_offset < 0) + req_seq_offset += 64; + + next_tx_seq_offset = + (pi->next_tx_seq - pi->expected_ack_seq) % 64; + if (next_tx_seq_offset < 0) + next_tx_seq_offset += 64; + + /* check for invalid req-seq */ + if (req_seq_offset > next_tx_seq_offset) { + l2cap_send_disconn_req(pi->conn, sk); + goto drop; + } + if (__is_iframe(control)) { if (len < 4) goto drop; -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 43/64] Bluetooth: Don't set control bits to zero first 2010-05-10 9:37 ` [PATCH 42/64] Bluetooth: Close L2CAP channel on invalid ReqSeq Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 44/64] Bluetooth: Fix errors reported by checkpatch.pl Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> We can set the SAR bits in the control field directly. 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> --- net/bluetooth/l2cap.c | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 31514d8..cfb18cd 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1636,16 +1636,15 @@ static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, siz __skb_queue_tail(&sar_queue, skb); len -= pi->remote_mps; size += pi->remote_mps; - control = 0; while (len > 0) { size_t buflen; if (len > pi->remote_mps) { - control |= L2CAP_SDU_CONTINUE; + control = L2CAP_SDU_CONTINUE; buflen = pi->remote_mps; } else { - control |= L2CAP_SDU_END; + control = L2CAP_SDU_END; buflen = len; } @@ -1658,7 +1657,6 @@ static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, siz __skb_queue_tail(&sar_queue, skb); len -= buflen; size += buflen; - control = 0; } skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk)); if (sk->sk_send_head == NULL) -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 44/64] Bluetooth: Fix errors reported by checkpatch.pl 2010-05-10 9:37 ` [PATCH 43/64] Bluetooth: Don't set control bits to zero first Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 45/64] Bluetooth: Remove set of SrejSaveReqSeq under receipt of REJ frame Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> 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> --- net/bluetooth/l2cap.c | 11 +++++------ 1 files changed, 5 insertions(+), 6 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index cfb18cd..2a981de 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1400,7 +1400,7 @@ static int l2cap_ertm_send(struct sock *sk) return 0; while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk)) && - !(pi->conn_state & L2CAP_CONN_REMOTE_BUSY)) { + !(pi->conn_state & L2CAP_CONN_REMOTE_BUSY)) { if (pi->remote_max_tx && bt_cb(skb)->retries == pi->remote_max_tx) { @@ -1490,9 +1490,8 @@ static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, in struct sk_buff **frag; int err, sent = 0; - if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) { + if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) return -EFAULT; - } sent += count; len -= count; @@ -3347,7 +3346,7 @@ static void l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_ if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb)) break; - } while((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb))); + } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb))); __skb_queue_tail(SREJ_QUEUE(sk), skb); } @@ -3446,7 +3445,7 @@ static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq) struct sk_buff *skb; u16 control; - while((skb = skb_peek(SREJ_QUEUE(sk)))) { + while ((skb = skb_peek(SREJ_QUEUE(sk)))) { if (bt_cb(skb)->tx_seq != tx_seq) break; @@ -3465,7 +3464,7 @@ static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq) struct srej_list *l, *tmp; u16 control; - list_for_each_entry_safe(l,tmp, SREJ_LIST(sk), list) { + list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) { if (l->tx_seq == tx_seq) { list_del(&l->list); kfree(l); -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 45/64] Bluetooth: Remove set of SrejSaveReqSeq under receipt of REJ frame 2010-05-10 9:37 ` [PATCH 44/64] Bluetooth: Fix errors reported by checkpatch.pl Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 46/64] Bluetooth: Remove unneeded control vars Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> That action is not specified by the ERTM spec, so removing it. 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> --- net/bluetooth/l2cap.c | 4 +--- 1 files changed, 1 insertions(+), 3 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 2a981de..d0d0330 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3670,10 +3670,8 @@ static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control) pi->next_tx_seq = pi->expected_ack_seq; l2cap_ertm_send(sk); - if (pi->conn_state & L2CAP_CONN_WAIT_F) { - pi->srej_save_reqseq = tx_seq; + if (pi->conn_state & L2CAP_CONN_WAIT_F) pi->conn_state |= L2CAP_CONN_REJ_ACT; - } } } static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control) -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 46/64] Bluetooth: Remove unneeded control vars 2010-05-10 9:37 ` [PATCH 45/64] Bluetooth: Remove set of SrejSaveReqSeq under receipt of REJ frame Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 47/64] Bluetooth: Check if we really are in WAIT_F when F bit comes Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> Trivial clean up. 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> --- net/bluetooth/l2cap.c | 14 ++++---------- 1 files changed, 4 insertions(+), 10 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index d0d0330..5a5203f 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1239,7 +1239,6 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l static void l2cap_monitor_timeout(unsigned long arg) { struct sock *sk = (void *) arg; - u16 control; bh_lock_sock(sk); if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) { @@ -1251,15 +1250,13 @@ static void l2cap_monitor_timeout(unsigned long arg) l2cap_pi(sk)->retry_count++; __mod_monitor_timer(); - control = L2CAP_CTRL_POLL; - l2cap_send_rr_or_rnr(l2cap_pi(sk), control); + l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL); bh_unlock_sock(sk); } static void l2cap_retrans_timeout(unsigned long arg) { struct sock *sk = (void *) arg; - u16 control; bh_lock_sock(sk); l2cap_pi(sk)->retry_count = 1; @@ -1267,8 +1264,7 @@ static void l2cap_retrans_timeout(unsigned long arg) l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F; - control = L2CAP_CTRL_POLL; - l2cap_send_rr_or_rnr(l2cap_pi(sk), control); + l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL); bh_unlock_sock(sk); } @@ -3716,10 +3712,8 @@ static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control) if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) { del_timer(&pi->retrans_timer); - if (rx_control & L2CAP_CTRL_POLL) { - u16 control = L2CAP_CTRL_FINAL; - l2cap_send_rr_or_rnr(pi, control); - } + if (rx_control & L2CAP_CTRL_POLL) + l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL); return; } -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 47/64] Bluetooth: Check if we really are in WAIT_F when F bit comes 2010-05-10 9:37 ` [PATCH 46/64] Bluetooth: Remove unneeded control vars Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 48/64] Bluetooth: Fix lockdep annotation on ERTM Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> F-bit set should be processed only if we are in the WAIT_F state. 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> --- net/bluetooth/l2cap.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 5a5203f..eb5cb29 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3503,7 +3503,8 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len); - if (L2CAP_CTRL_FINAL & rx_control) { + if (L2CAP_CTRL_FINAL & rx_control && + l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) { del_timer(&pi->monitor_timer); if (pi->unacked_frames > 0) __mod_retrans_timer(); @@ -3727,7 +3728,8 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str { BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len); - if (L2CAP_CTRL_FINAL & rx_control) { + if (L2CAP_CTRL_FINAL & rx_control && + l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) { del_timer(&l2cap_pi(sk)->monitor_timer); if (l2cap_pi(sk)->unacked_frames > 0) __mod_retrans_timer(); -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 48/64] Bluetooth: Fix lockdep annotation on ERTM 2010-05-10 9:37 ` [PATCH 47/64] Bluetooth: Check if we really are in WAIT_F when F bit comes Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 49/64] Bluetooth: Make hci_send_acl() void Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> A spin_lock_init() call was missing. :) 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> --- net/bluetooth/l2cap.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index eb5cb29..6b08f4d 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1622,7 +1622,7 @@ static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, siz u16 control; size_t size = 0; - __skb_queue_head_init(&sar_queue); + skb_queue_head_init(&sar_queue); control = L2CAP_SDU_START; skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len); if (IS_ERR(skb)) -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 49/64] Bluetooth: Make hci_send_acl() void 2010-05-10 9:37 ` [PATCH 48/64] Bluetooth: Fix lockdep annotation on ERTM Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 50/64] Bluetooth: Refactor l2cap_retransmit_frame() Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> 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> --- include/net/bluetooth/hci_core.h | 2 +- net/bluetooth/hci_core.c | 4 +- net/bluetooth/l2cap.c | 73 ++++++++++++++------------------------ 3 files changed, 30 insertions(+), 49 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 9830a88..4511df2 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -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); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 1c9aef9..904f1e8 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -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; @@ -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); diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 6b08f4d..7e74d5b 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -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; @@ -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); @@ -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; @@ -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) @@ -1289,18 +1289,13 @@ 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) @@ -1308,7 +1303,6 @@ 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); @@ -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; @@ -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 { @@ -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; @@ -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; @@ -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; @@ -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; @@ -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; @@ -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) @@ -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; } @@ -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: -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 50/64] Bluetooth: Refactor l2cap_retransmit_frame() 2010-05-10 9:37 ` [PATCH 49/64] Bluetooth: Make hci_send_acl() void Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 51/64] Bluetooth: Implement missing parts of the Invalid Frame Detection Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> Make the code flow cleaner and changes the function to void. It also fixes a potential NULL dereference with skb. 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> --- net/bluetooth/l2cap.c | 53 +++++++++++++++++++++++++------------------------ 1 files changed, 27 insertions(+), 26 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 7e74d5b..1c35c32 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1331,43 +1331,44 @@ static int l2cap_streaming_send(struct sock *sk) return 0; } -static int l2cap_retransmit_frame(struct sock *sk, u8 tx_seq) +static void 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; skb = skb_peek(TX_QUEUE(sk)); - do { - if (bt_cb(skb)->tx_seq != tx_seq) { - if (skb_queue_is_last(TX_QUEUE(sk), skb)) - break; - skb = skb_queue_next(TX_QUEUE(sk), skb); - continue; - } + if (!skb) + return; - if (pi->remote_max_tx && - bt_cb(skb)->retries == pi->remote_max_tx) { - l2cap_send_disconn_req(pi->conn, sk); + do { + if (bt_cb(skb)->tx_seq == tx_seq) break; - } - tx_skb = skb_clone(skb, GFP_ATOMIC); - bt_cb(skb)->retries++; - control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); - control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) - | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); - put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); + if (skb_queue_is_last(TX_QUEUE(sk), skb)) + return; - if (pi->fcs == L2CAP_FCS_CRC16) { - fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2); - put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2); - } + } while ((skb = skb_queue_next(TX_QUEUE(sk), skb))); - l2cap_do_send(sk, tx_skb); - break; - } while(1); - return 0; + if (pi->remote_max_tx && + bt_cb(skb)->retries == pi->remote_max_tx) { + l2cap_send_disconn_req(pi->conn, sk); + return; + } + + tx_skb = skb_clone(skb, GFP_ATOMIC); + bt_cb(skb)->retries++; + control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); + control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) + | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); + put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); + + if (pi->fcs == L2CAP_FCS_CRC16) { + fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2); + put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2); + } + + l2cap_do_send(sk, tx_skb); } static int l2cap_ertm_send(struct sock *sk) -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 51/64] Bluetooth: Implement missing parts of the Invalid Frame Detection 2010-05-10 9:37 ` [PATCH 50/64] Bluetooth: Refactor l2cap_retransmit_frame() Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 52/64] Bluetooth: Completes the I-frame tx_seq check logic on RECV Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> There is a plenty of situation where ERTM shall close the channel, this commit treats the cases regarding Invalid Frame Detection. It create one reassembly SDU function for ERTM and other for Streaming Mode to make the Invalid Frame Detection handling less complex. 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> --- net/bluetooth/l2cap.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 112 insertions(+), 7 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 1c35c32..cfd6724 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3329,12 +3329,111 @@ static void l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_ __skb_queue_tail(SREJ_QUEUE(sk), skb); } -static int l2cap_sar_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control) +static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control) +{ + struct l2cap_pinfo *pi = l2cap_pi(sk); + struct sk_buff *_skb; + int err = 0; + + switch (control & L2CAP_CTRL_SAR) { + case L2CAP_SDU_UNSEGMENTED: + if (pi->conn_state & L2CAP_CONN_SAR_SDU) + goto drop; + + err = sock_queue_rcv_skb(sk, skb); + if (!err) + return err; + + break; + + case L2CAP_SDU_START: + if (pi->conn_state & L2CAP_CONN_SAR_SDU) + goto drop; + + pi->sdu_len = get_unaligned_le16(skb->data); + skb_pull(skb, 2); + + if (pi->sdu_len > pi->imtu) + goto disconnect; + + pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC); + if (!pi->sdu) { + err = -ENOMEM; + break; + } + + memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); + + pi->conn_state |= L2CAP_CONN_SAR_SDU; + pi->partial_sdu_len = skb->len; + break; + + case L2CAP_SDU_CONTINUE: + if (!(pi->conn_state & L2CAP_CONN_SAR_SDU)) + goto disconnect; + + if (!pi->sdu) + goto disconnect; + + memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); + + pi->partial_sdu_len += skb->len; + if (pi->partial_sdu_len > pi->sdu_len) + goto drop; + + break; + + case L2CAP_SDU_END: + if (!(pi->conn_state & L2CAP_CONN_SAR_SDU)) + goto disconnect; + + if (!pi->sdu) + goto disconnect; + + memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); + + pi->conn_state &= ~L2CAP_CONN_SAR_SDU; + pi->partial_sdu_len += skb->len; + + if (pi->partial_sdu_len > pi->imtu) + goto drop; + + if (pi->partial_sdu_len != pi->sdu_len) + goto drop; + + _skb = skb_clone(pi->sdu, GFP_ATOMIC); + err = sock_queue_rcv_skb(sk, _skb); + if (err < 0) + kfree_skb(_skb); + + kfree_skb(pi->sdu); + break; + } + + kfree_skb(skb); + return err; + +drop: + kfree_skb(pi->sdu); + pi->sdu = NULL; + +disconnect: + l2cap_send_disconn_req(pi->conn, sk); + kfree_skb(skb); + return 0; +} + +static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control) { struct l2cap_pinfo *pi = l2cap_pi(sk); struct sk_buff *_skb; int err = -EINVAL; + /* + * TODO: We have to notify the userland if some data is lost with the + * Streaming Mode. + */ + switch (control & L2CAP_CTRL_SAR) { case L2CAP_SDU_UNSEGMENTED: if (pi->conn_state & L2CAP_CONN_SAR_SDU) { @@ -3429,7 +3528,7 @@ static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq) skb = skb_dequeue(SREJ_QUEUE(sk)); control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; - l2cap_sar_reassembly_sdu(sk, skb, control); + l2cap_ertm_reassembly_sdu(sk, skb, control); l2cap_pi(sk)->buffer_seq_srej = (l2cap_pi(sk)->buffer_seq_srej + 1) % 64; tx_seq++; @@ -3566,7 +3665,7 @@ expected: pi->buffer_seq = (pi->buffer_seq + 1) % 64; - err = l2cap_sar_reassembly_sdu(sk, skb, rx_control); + err = l2cap_ertm_reassembly_sdu(sk, skb, rx_control); if (err < 0) return err; @@ -3790,8 +3889,10 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk * Receiver will miss it and start proper recovery * procedures and ask retransmission. */ - if (len > pi->mps) + if (len > pi->mps) { + l2cap_send_disconn_req(pi->conn, sk); goto drop; + } if (l2cap_check_fcs(pi, skb)) goto drop; @@ -3813,13 +3914,17 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk } if (__is_iframe(control)) { - if (len < 4) + if (len < 4) { + l2cap_send_disconn_req(pi->conn, sk); goto drop; + } l2cap_data_channel_iframe(sk, control, skb); } else { - if (len != 0) + if (len != 0) { + l2cap_send_disconn_req(pi->conn, sk); goto drop; + } l2cap_data_channel_sframe(sk, control, skb); } @@ -3850,7 +3955,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk else pi->expected_tx_seq = (tx_seq + 1) % 64; - l2cap_sar_reassembly_sdu(sk, skb, control); + l2cap_streaming_reassembly_sdu(sk, skb, control); goto done; -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 52/64] Bluetooth: Completes the I-frame tx_seq check logic on RECV 2010-05-10 9:37 ` [PATCH 51/64] Bluetooth: Implement missing parts of the Invalid Frame Detection Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 53/64] Bluetooth: Implement Local Busy Condition handling Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: João Paulo Rechi Vita <jprvita@profusion.mobi> Add checks for invalid tx_seq and fixes the duplicated tx_seq check. Signed-off-by: João Paulo Rechi Vita <jprvita@profusion.mobi> Acked-by: Gustavo F. Padovan <padovan@profusion.mobi> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> --- net/bluetooth/l2cap.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 files changed, 36 insertions(+), 4 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index cfd6724..481cec2 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3302,7 +3302,7 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk) } } -static void l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar) +static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar) { struct sk_buff *next_skb; @@ -3312,13 +3312,16 @@ static void l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_ next_skb = skb_peek(SREJ_QUEUE(sk)); if (!next_skb) { __skb_queue_tail(SREJ_QUEUE(sk), skb); - return; + return 0; } do { + if (bt_cb(next_skb)->tx_seq == tx_seq) + return -EINVAL; + if (bt_cb(next_skb)->tx_seq > tx_seq) { __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb); - return; + return 0; } if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb)) @@ -3327,6 +3330,8 @@ static void l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_ } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb))); __skb_queue_tail(SREJ_QUEUE(sk), skb); + + return 0; } static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control) @@ -3579,6 +3584,7 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str u8 tx_seq = __get_txseq(rx_control); u8 req_seq = __get_reqseq(rx_control); u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT; + u8 tx_seq_offset, expected_tx_seq_offset; int num_to_ack = (pi->tx_win/6) + 1; int err = 0; @@ -3598,6 +3604,16 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str if (tx_seq == pi->expected_tx_seq) goto expected; + tx_seq_offset = (tx_seq - pi->buffer_seq) % 64; + if (tx_seq_offset < 0) + tx_seq_offset += 64; + + /* invalid tx_seq */ + if (tx_seq_offset >= pi->tx_win) { + l2cap_send_disconn_req(pi->conn, sk); + goto drop; + } + if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { struct srej_list *first; @@ -3617,7 +3633,10 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str } } else { struct srej_list *l; - l2cap_add_to_srej_queue(sk, skb, tx_seq, sar); + + /* duplicated tx_seq */ + if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0) + goto drop; list_for_each_entry(l, SREJ_LIST(sk), list) { if (l->tx_seq == tx_seq) { @@ -3628,6 +3647,15 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str l2cap_send_srejframe(sk, tx_seq); } } else { + expected_tx_seq_offset = + (pi->expected_tx_seq - pi->buffer_seq) % 64; + if (expected_tx_seq_offset < 0) + expected_tx_seq_offset += 64; + + /* duplicated tx_seq */ + if (tx_seq_offset < expected_tx_seq_offset) + goto drop; + pi->conn_state |= L2CAP_CONN_SREJ_SENT; INIT_LIST_HEAD(SREJ_LIST(sk)); @@ -3676,6 +3704,10 @@ expected: l2cap_send_ack(pi); return 0; + +drop: + kfree_skb(skb); + return 0; } static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control) -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 53/64] Bluetooth: Implement Local Busy Condition handling 2010-05-10 9:37 ` [PATCH 52/64] Bluetooth: Completes the I-frame tx_seq check logic on RECV Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 54/64] Bluetooth: Add wait_queue to wait ack of all sent packets Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> Supports Local Busy condition handling through a waitqueue that wake ups each 200ms and try to push the packets to the upper layer. If it can push all the queue then it leaves the Local Busy state. The patch modifies the behaviour of l2cap_ertm_reassembly_sdu() to support retry of the push operation. 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> --- include/net/bluetooth/l2cap.h | 6 ++ net/bluetooth/l2cap.c | 187 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 172 insertions(+), 21 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 8942c2f..d0185cc 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -35,6 +35,7 @@ #define L2CAP_DEFAULT_MONITOR_TO 12000 /* 12 seconds */ #define L2CAP_DEFAULT_MAX_PDU_SIZE 672 #define L2CAP_DEFAULT_ACK_TO 200 +#define L2CAP_LOCAL_BUSY_TRIES 12 #define L2CAP_CONN_TIMEOUT (40000) /* 40 seconds */ #define L2CAP_INFO_TIMEOUT (4000) /* 4 seconds */ @@ -294,6 +295,7 @@ struct l2cap_conn { #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) #define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue) #define SREJ_QUEUE(sk) (&l2cap_pi(sk)->srej_queue) +#define BUSY_QUEUE(sk) (&l2cap_pi(sk)->busy_queue) #define SREJ_LIST(sk) (&l2cap_pi(sk)->srej_l.list) struct srej_list { @@ -356,6 +358,8 @@ struct l2cap_pinfo { struct timer_list ack_timer; struct sk_buff_head tx_queue; struct sk_buff_head srej_queue; + struct sk_buff_head busy_queue; + struct work_struct busy_work; struct srej_list srej_l; struct l2cap_conn *conn; struct sock *next_c; @@ -383,6 +387,8 @@ struct l2cap_pinfo { #define L2CAP_CONN_LOCAL_BUSY 0x0040 #define L2CAP_CONN_REJ_ACT 0x0080 #define L2CAP_CONN_SEND_FBIT 0x0100 +#define L2CAP_CONN_RNR_SENT 0x0200 +#define L2CAP_CONN_SAR_RETRY 0x0400 #define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \ jiffies + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO)); diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 481cec2..103e4b5 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -68,10 +68,14 @@ static u8 l2cap_fixed_chan[8] = { 0x02, }; static const struct proto_ops l2cap_sock_ops; +static struct workqueue_struct *_busy_wq; + static struct bt_sock_list l2cap_sk_list = { .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) }; +static void l2cap_busy_work(struct work_struct *work); + static void __l2cap_sock_close(struct sock *sk, int reason); static void l2cap_sock_close(struct sock *sk); static void l2cap_sock_kill(struct sock *sk); @@ -386,9 +390,10 @@ static inline void l2cap_send_sframe(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; - else + pi->conn_state |= L2CAP_CONN_RNR_SENT; + } else control |= L2CAP_SUPER_RCV_READY; control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; @@ -816,6 +821,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) pi->flush_to = L2CAP_DEFAULT_FLUSH_TO; skb_queue_head_init(TX_QUEUE(sk)); skb_queue_head_init(SREJ_QUEUE(sk)); + skb_queue_head_init(BUSY_QUEUE(sk)); INIT_LIST_HEAD(SREJ_LIST(sk)); } @@ -1439,6 +1445,7 @@ static void l2cap_send_ack(struct l2cap_pinfo *pi) if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { control |= L2CAP_SUPER_RCV_NOT_READY; + pi->conn_state |= L2CAP_CONN_RNR_SENT; l2cap_send_sframe(pi, control); return; } else if (l2cap_ertm_send(sk) == 0) { @@ -2279,6 +2286,9 @@ static inline void l2cap_ertm_init(struct sock *sk) l2cap_ack_timeout, (unsigned long) sk); __skb_queue_head_init(SREJ_QUEUE(sk)); + __skb_queue_head_init(BUSY_QUEUE(sk)); + + INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work); } static int l2cap_mode_supported(__u8 mode, __u32 feat_mask) @@ -3046,6 +3056,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { skb_queue_purge(SREJ_QUEUE(sk)); + skb_queue_purge(BUSY_QUEUE(sk)); del_timer(&l2cap_pi(sk)->retrans_timer); del_timer(&l2cap_pi(sk)->monitor_timer); del_timer(&l2cap_pi(sk)->ack_timer); @@ -3077,6 +3088,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { skb_queue_purge(SREJ_QUEUE(sk)); + skb_queue_purge(BUSY_QUEUE(sk)); del_timer(&l2cap_pi(sk)->retrans_timer); del_timer(&l2cap_pi(sk)->monitor_timer); del_timer(&l2cap_pi(sk)->ack_timer); @@ -3287,6 +3299,7 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk) if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { control |= L2CAP_SUPER_RCV_NOT_READY | L2CAP_CTRL_FINAL; l2cap_send_sframe(pi, control); + pi->conn_state |= L2CAP_CONN_RNR_SENT; pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; } @@ -3338,7 +3351,7 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c { struct l2cap_pinfo *pi = l2cap_pi(sk); struct sk_buff *_skb; - int err = 0; + int err; switch (control & L2CAP_CTRL_SAR) { case L2CAP_SDU_UNSEGMENTED: @@ -3356,16 +3369,18 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c goto drop; pi->sdu_len = get_unaligned_le16(skb->data); - skb_pull(skb, 2); if (pi->sdu_len > pi->imtu) goto disconnect; pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC); - if (!pi->sdu) { - err = -ENOMEM; - break; - } + if (!pi->sdu) + return -ENOMEM; + + /* pull sdu_len bytes only after alloc, because of Local Busy + * condition we have to be sure that this will be executed + * only once, i.e., when alloc does not fail */ + skb_pull(skb, 2); memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); @@ -3395,28 +3410,40 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c if (!pi->sdu) goto disconnect; - memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); + if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) { + memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); - pi->conn_state &= ~L2CAP_CONN_SAR_SDU; - pi->partial_sdu_len += skb->len; + pi->partial_sdu_len += skb->len; - if (pi->partial_sdu_len > pi->imtu) - goto drop; + if (pi->partial_sdu_len > pi->imtu) + goto drop; - if (pi->partial_sdu_len != pi->sdu_len) - goto drop; + if (pi->partial_sdu_len != pi->sdu_len) + goto drop; + } _skb = skb_clone(pi->sdu, GFP_ATOMIC); + if (!_skb) { + pi->conn_state |= L2CAP_CONN_SAR_RETRY; + return -ENOMEM; + } + err = sock_queue_rcv_skb(sk, _skb); - if (err < 0) + if (err < 0) { kfree_skb(_skb); + pi->conn_state |= L2CAP_CONN_SAR_RETRY; + return err; + } + + pi->conn_state &= ~L2CAP_CONN_SAR_RETRY; + pi->conn_state &= ~L2CAP_CONN_SAR_SDU; kfree_skb(pi->sdu); break; } kfree_skb(skb); - return err; + return 0; drop: kfree_skb(pi->sdu); @@ -3428,6 +3455,115 @@ disconnect: return 0; } +static void l2cap_busy_work(struct work_struct *work) +{ + DECLARE_WAITQUEUE(wait, current); + struct l2cap_pinfo *pi = + container_of(work, struct l2cap_pinfo, busy_work); + struct sock *sk = (struct sock *)pi; + int n_tries = 0, timeo = HZ/5, err; + struct sk_buff *skb; + u16 control; + + lock_sock(sk); + + add_wait_queue(sk->sk_sleep, &wait); + while ((skb = skb_peek(BUSY_QUEUE(sk)))) { + set_current_state(TASK_INTERRUPTIBLE); + + if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) { + err = -EBUSY; + l2cap_send_disconn_req(pi->conn, sk); + goto done; + } + + if (!timeo) + timeo = HZ/5; + + if (signal_pending(current)) { + err = sock_intr_errno(timeo); + goto done; + } + + release_sock(sk); + timeo = schedule_timeout(timeo); + lock_sock(sk); + + err = sock_error(sk); + if (err) + goto done; + + while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) { + control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; + err = l2cap_ertm_reassembly_sdu(sk, skb, control); + if (err < 0) { + skb_queue_head(BUSY_QUEUE(sk), skb); + break; + } + + pi->buffer_seq = (pi->buffer_seq + 1) % 64; + } + + if (!skb) + break; + } + + if (!(pi->conn_state & L2CAP_CONN_RNR_SENT)) + goto done; + + control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; + control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL; + l2cap_send_sframe(pi, control); + l2cap_pi(sk)->retry_count = 1; + + del_timer(&pi->retrans_timer); + __mod_monitor_timer(); + + l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F; + +done: + pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY; + pi->conn_state &= ~L2CAP_CONN_RNR_SENT; + + set_current_state(TASK_RUNNING); + remove_wait_queue(sk->sk_sleep, &wait); + + release_sock(sk); +} + +static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control) +{ + struct l2cap_pinfo *pi = l2cap_pi(sk); + int sctrl, err; + + if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { + bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; + __skb_queue_tail(BUSY_QUEUE(sk), skb); + return -EBUSY; + } + + err = l2cap_ertm_reassembly_sdu(sk, skb, control); + if (err >= 0) { + pi->buffer_seq = (pi->buffer_seq + 1) % 64; + return err; + } + + /* Busy Condition */ + pi->conn_state |= L2CAP_CONN_LOCAL_BUSY; + bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; + __skb_queue_tail(BUSY_QUEUE(sk), skb); + + sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; + sctrl |= L2CAP_SUPER_RCV_NOT_READY; + l2cap_send_sframe(pi, sctrl); + + pi->conn_state |= L2CAP_CONN_RNR_SENT; + + queue_work(_busy_wq, &pi->busy_work); + + return err; +} + static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control) { struct l2cap_pinfo *pi = l2cap_pi(sk); @@ -3614,6 +3750,9 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str goto drop; } + if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY) + goto drop; + if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { struct srej_list *first; @@ -3662,6 +3801,7 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str pi->buffer_seq_srej = pi->buffer_seq; __skb_queue_head_init(SREJ_QUEUE(sk)); + __skb_queue_head_init(BUSY_QUEUE(sk)); l2cap_add_to_srej_queue(sk, skb, tx_seq, sar); pi->conn_state |= L2CAP_CONN_SEND_PBIT; @@ -3691,11 +3831,9 @@ expected: } } - pi->buffer_seq = (pi->buffer_seq + 1) % 64; - - err = l2cap_ertm_reassembly_sdu(sk, skb, rx_control); + err = l2cap_push_rx_skb(sk, skb, rx_control); if (err < 0) - return err; + return 0; __mod_ack_timer(); @@ -4406,6 +4544,10 @@ static int __init l2cap_init(void) if (err < 0) return err; + _busy_wq = create_singlethread_workqueue("l2cap"); + if (!_busy_wq) + goto error; + err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops); if (err < 0) { BT_ERR("L2CAP socket registration failed"); @@ -4440,6 +4582,9 @@ static void __exit l2cap_exit(void) { debugfs_remove(l2cap_debugfs); + flush_workqueue(_busy_wq); + destroy_workqueue(_busy_wq); + if (bt_sock_unregister(BTPROTO_L2CAP) < 0) BT_ERR("L2CAP socket unregistration failed"); -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 54/64] Bluetooth: Add wait_queue to wait ack of all sent packets 2010-05-10 9:37 ` [PATCH 53/64] Bluetooth: Implement Local Busy Condition handling Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 55/64] Bluetooth: Fix race condition on l2cap_ertm_send() Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> To guarantee that all packets we sent were received we need to wait for theirs ack before shutdown the socket. 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> --- net/bluetooth/l2cap.c | 34 ++++++++++++++++++++++++++++++++++ 1 files changed, 34 insertions(+), 0 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 103e4b5..9d514f9 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1242,6 +1242,37 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l return 0; } +static int __l2cap_wait_ack(struct sock *sk) +{ + DECLARE_WAITQUEUE(wait, current); + int err = 0; + int timeo = HZ/5; + + add_wait_queue(sk->sk_sleep, &wait); + while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) { + set_current_state(TASK_INTERRUPTIBLE); + + if (!timeo) + timeo = HZ/5; + + if (signal_pending(current)) { + err = sock_intr_errno(timeo); + break; + } + + release_sock(sk); + timeo = schedule_timeout(timeo); + lock_sock(sk); + + err = sock_error(sk); + if (err) + break; + } + set_current_state(TASK_RUNNING); + remove_wait_queue(sk->sk_sleep, &wait); + return err; +} + static void l2cap_monitor_timeout(unsigned long arg) { struct sock *sk = (void *) arg; @@ -2059,6 +2090,9 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) lock_sock(sk); if (!sk->sk_shutdown) { + if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) + err = __l2cap_wait_ack(sk); + sk->sk_shutdown = SHUTDOWN_MASK; l2cap_sock_clear_timer(sk); __l2cap_sock_close(sk, 0); -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 55/64] Bluetooth: Fix race condition on l2cap_ertm_send() 2010-05-10 9:37 ` [PATCH 54/64] Bluetooth: Add wait_queue to wait ack of all sent packets Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 56/64] Bluetooth: Prevents buffer overflow on l2cap_ertm_reassembly_sdu() Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> l2cap_ertm_send() can be called both from user context and bottom half context. The socket locks for that contexts are different, the user context uses a mutex(which can sleep) and the second one uses a spinlock_bh. That creates a race condition when we have interruptions on both contexts at the same time. The better way to solve this is to add a new spinlock to lock l2cap_ertm_send() and the vars it access. The other solution was to defer l2cap_ertm_send() with a workqueue, but we the sending process already has one defer on the hci layer. It's not a good idea add another one. The patch refactor the code to create l2cap_retransmit_frames(), then we encapulate the lock of l2cap_ertm_send() for some call. It also changes l2cap_retransmit_frame() to l2cap_retransmit_one_frame() to avoid confusion 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> --- include/net/bluetooth/l2cap.h | 1 + net/bluetooth/l2cap.c | 99 +++++++++++++++++++++++++++-------------- 2 files changed, 67 insertions(+), 33 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index d0185cc..7c695bf 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -353,6 +353,7 @@ struct l2cap_pinfo { __le16 sport; + spinlock_t send_lock; struct timer_list retrans_timer; struct timer_list monitor_timer; struct timer_list ack_timer; diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 9d514f9..fe663e9 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1368,7 +1368,7 @@ static int l2cap_streaming_send(struct sock *sk) return 0; } -static void l2cap_retransmit_frame(struct sock *sk, u8 tx_seq) +static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq) { struct l2cap_pinfo *pi = l2cap_pi(sk); struct sk_buff *skb, *tx_skb; @@ -1467,10 +1467,29 @@ static int l2cap_ertm_send(struct sock *sk) return nsent; } +static int l2cap_retransmit_frames(struct sock *sk) +{ + struct l2cap_pinfo *pi = l2cap_pi(sk); + int ret; + + spin_lock_bh(&pi->send_lock); + + if (!skb_queue_empty(TX_QUEUE(sk))) + sk->sk_send_head = TX_QUEUE(sk)->next; + + pi->next_tx_seq = pi->expected_ack_seq; + ret = l2cap_ertm_send(sk); + + spin_unlock_bh(&pi->send_lock); + + return ret; +} + static void l2cap_send_ack(struct l2cap_pinfo *pi) { struct sock *sk = (struct sock *)pi; u16 control = 0; + int nframes; control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; @@ -1479,10 +1498,17 @@ static void l2cap_send_ack(struct l2cap_pinfo *pi) pi->conn_state |= L2CAP_CONN_RNR_SENT; l2cap_send_sframe(pi, control); return; - } else if (l2cap_ertm_send(sk) == 0) { - control |= L2CAP_SUPER_RCV_READY; - l2cap_send_sframe(pi, control); } + + spin_lock_bh(&pi->send_lock); + nframes = l2cap_ertm_send(sk); + spin_unlock_bh(&pi->send_lock); + + if (nframes > 0) + return; + + control |= L2CAP_SUPER_RCV_READY; + l2cap_send_sframe(pi, control); } static void l2cap_send_srejtail(struct sock *sk) @@ -1673,8 +1699,10 @@ static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, siz size += buflen; } skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk)); + spin_lock_bh(&pi->send_lock); if (sk->sk_send_head == NULL) sk->sk_send_head = sar_queue.next; + spin_unlock_bh(&pi->send_lock); return size; } @@ -1745,8 +1773,15 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms goto done; } __skb_queue_tail(TX_QUEUE(sk), skb); + + if (pi->mode == L2CAP_MODE_ERTM) + spin_lock_bh(&pi->send_lock); + if (sk->sk_send_head == NULL) sk->sk_send_head = skb; + + if (pi->mode == L2CAP_MODE_ERTM) + spin_unlock_bh(&pi->send_lock); } else { /* Segment SDU into multiples PDUs */ err = l2cap_sar_segment_sdu(sk, msg, len); @@ -1754,10 +1789,13 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms goto done; } - if (pi->mode == L2CAP_MODE_STREAMING) + if (pi->mode == L2CAP_MODE_STREAMING) { err = l2cap_streaming_send(sk); - else + } else { + spin_lock_bh(&pi->send_lock); err = l2cap_ertm_send(sk); + spin_unlock_bh(&pi->send_lock); + } if (err >= 0) err = len; @@ -2321,6 +2359,7 @@ static inline void l2cap_ertm_init(struct sock *sk) __skb_queue_head_init(SREJ_QUEUE(sk)); __skb_queue_head_init(BUSY_QUEUE(sk)); + spin_lock_init(&l2cap_pi(sk)->send_lock); INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work); } @@ -3340,7 +3379,9 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk) if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY && pi->unacked_frames > 0) __mod_retrans_timer(); + spin_lock_bh(&pi->send_lock); l2cap_ertm_send(sk); + spin_unlock_bh(&pi->send_lock); if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) && pi->frames_sent == 0) { @@ -3857,12 +3898,8 @@ expected: if (rx_control & L2CAP_CTRL_FINAL) { if (pi->conn_state & L2CAP_CONN_REJ_ACT) pi->conn_state &= ~L2CAP_CONN_REJ_ACT; - else { - if (!skb_queue_empty(TX_QUEUE(sk))) - sk->sk_send_head = TX_QUEUE(sk)->next; - pi->next_tx_seq = pi->expected_ack_seq; - l2cap_ertm_send(sk); - } + else + l2cap_retransmit_frames(sk); } err = l2cap_push_rx_skb(sk, skb, rx_control); @@ -3907,12 +3944,8 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control) if (pi->conn_state & L2CAP_CONN_REJ_ACT) pi->conn_state &= ~L2CAP_CONN_REJ_ACT; - else { - if (!skb_queue_empty(TX_QUEUE(sk))) - sk->sk_send_head = TX_QUEUE(sk)->next; - pi->next_tx_seq = pi->expected_ack_seq; - l2cap_ertm_send(sk); - } + else + l2cap_retransmit_frames(sk); } else { if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) && @@ -3920,10 +3953,13 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control) __mod_retrans_timer(); pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; - if (pi->conn_state & L2CAP_CONN_SREJ_SENT) + if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { l2cap_send_ack(pi); - else + } else { + spin_lock_bh(&pi->send_lock); l2cap_ertm_send(sk); + spin_unlock_bh(&pi->send_lock); + } } } @@ -3940,17 +3976,10 @@ static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control) if (rx_control & L2CAP_CTRL_FINAL) { if (pi->conn_state & L2CAP_CONN_REJ_ACT) pi->conn_state &= ~L2CAP_CONN_REJ_ACT; - else { - if (!skb_queue_empty(TX_QUEUE(sk))) - sk->sk_send_head = TX_QUEUE(sk)->next; - pi->next_tx_seq = pi->expected_ack_seq; - l2cap_ertm_send(sk); - } + else + l2cap_retransmit_frames(sk); } else { - if (!skb_queue_empty(TX_QUEUE(sk))) - sk->sk_send_head = TX_QUEUE(sk)->next; - pi->next_tx_seq = pi->expected_ack_seq; - l2cap_ertm_send(sk); + l2cap_retransmit_frames(sk); if (pi->conn_state & L2CAP_CONN_WAIT_F) pi->conn_state |= L2CAP_CONN_REJ_ACT; @@ -3966,8 +3995,12 @@ static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control) if (rx_control & L2CAP_CTRL_POLL) { pi->expected_ack_seq = tx_seq; l2cap_drop_acked_frames(sk); - l2cap_retransmit_frame(sk, tx_seq); + l2cap_retransmit_one_frame(sk, tx_seq); + + spin_lock_bh(&pi->send_lock); l2cap_ertm_send(sk); + spin_unlock_bh(&pi->send_lock); + if (pi->conn_state & L2CAP_CONN_WAIT_F) { pi->srej_save_reqseq = tx_seq; pi->conn_state |= L2CAP_CONN_SREJ_ACT; @@ -3977,9 +4010,9 @@ static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control) pi->srej_save_reqseq == tx_seq) pi->conn_state &= ~L2CAP_CONN_SREJ_ACT; else - l2cap_retransmit_frame(sk, tx_seq); + l2cap_retransmit_one_frame(sk, tx_seq); } else { - l2cap_retransmit_frame(sk, tx_seq); + l2cap_retransmit_one_frame(sk, tx_seq); if (pi->conn_state & L2CAP_CONN_WAIT_F) { pi->srej_save_reqseq = tx_seq; pi->conn_state |= L2CAP_CONN_SREJ_ACT; -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 56/64] Bluetooth: Prevents buffer overflow on l2cap_ertm_reassembly_sdu() 2010-05-10 9:37 ` [PATCH 55/64] Bluetooth: Fix race condition on l2cap_ertm_send() Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 57/64] Bluetooth: Fix spec error in the RemoteBusy Logic Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> The checks should be done before the the memcpy to avoid buffer overflow. Reported-by: João Paulo Rechi Vita <jprvita@profusion.mobi> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> --- net/bluetooth/l2cap.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index fe663e9..9ef01c3 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3470,12 +3470,12 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c if (!pi->sdu) goto disconnect; - memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); - pi->partial_sdu_len += skb->len; if (pi->partial_sdu_len > pi->sdu_len) goto drop; + memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); + break; case L2CAP_SDU_END: @@ -3486,8 +3486,6 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c goto disconnect; if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) { - memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); - pi->partial_sdu_len += skb->len; if (pi->partial_sdu_len > pi->imtu) @@ -3495,6 +3493,8 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c if (pi->partial_sdu_len != pi->sdu_len) goto drop; + + memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); } _skb = skb_clone(pi->sdu, GFP_ATOMIC); -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 57/64] Bluetooth: Fix spec error in the RemoteBusy Logic 2010-05-10 9:37 ` [PATCH 56/64] Bluetooth: Prevents buffer overflow on l2cap_ertm_reassembly_sdu() Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 58/64] Bluetooth: Create per controller workqueue Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Gustavo F. Padovan <padovan@profusion.mobi> On the receipt of an RR(P=1) under RemoteBusy set to TRUE(on the RECV state table) we have to call sendIorRRorRNR(F=1) and just after set RemoteBusy to False. This leads to a freeze in the sending process since it's not allowed send data with RemoteBusy set to true and no one call SendPending-I-Frames after set RemoteBusy to false(The last action for that event). Actually sendIorRRorRNR() calls SendPending-I-Frames but at that moment RemoteBusy is still True and we cannot send any frame, after, no one calls SendPending-I-Frames again and the sending process stops. The solution here is to set RemoteBusy to false inside SendPending-I-Frames just before call SendPending-I-Frames. That will make SendPending-I-Frames able to send frames. This solution is similar to what RR(P=0)(F=0) on the RECV table and RR(P=1) on the SREJ_SENT table do. Actually doesn't make any sense call SendPending-I-Frames if we can send any frame, i. e., RemoteBusy is True. Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> --- net/bluetooth/l2cap.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 9ef01c3..ba49f9a 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3379,6 +3379,8 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk) if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY && pi->unacked_frames > 0) __mod_retrans_timer(); + pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + spin_lock_bh(&pi->send_lock); l2cap_ertm_send(sk); spin_unlock_bh(&pi->send_lock); @@ -3936,7 +3938,6 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control) l2cap_send_srejtail(sk); } else { l2cap_send_i_or_rr_or_rnr(sk); - pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; } } else if (rx_control & L2CAP_CTRL_FINAL) { -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 58/64] Bluetooth: Create per controller workqueue 2010-05-10 9:37 ` [PATCH 57/64] Bluetooth: Fix spec error in the RemoteBusy Logic Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 59/64] Bluetooth: Fix storing negative values as unsigned char Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev Instead of having a global workqueue for all controllers, it makes more sense to have a workqueue per controller. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> --- include/net/bluetooth/hci_core.h | 2 ++ net/bluetooth/hci_core.c | 14 ++++++++++++++ net/bluetooth/hci_sysfs.c | 16 +++------------- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 4511df2..e42f6ed 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -107,6 +107,8 @@ struct hci_dev { unsigned long acl_last_tx; unsigned long sco_last_tx; + struct workqueue_struct *workqueue; + struct tasklet_struct cmd_task; struct tasklet_struct rx_task; struct tasklet_struct tx_task; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 904f1e8..5e83f8e 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -37,6 +37,7 @@ #include <linux/fcntl.h> #include <linux/init.h> #include <linux/skbuff.h> +#include <linux/workqueue.h> #include <linux/interrupt.h> #include <linux/notifier.h> #include <linux/rfkill.h> @@ -928,6 +929,10 @@ int hci_register_dev(struct hci_dev *hdev) write_unlock_bh(&hci_dev_list_lock); + hdev->workqueue = create_singlethread_workqueue(hdev->name); + if (!hdev->workqueue) + goto nomem; + hci_register_sysfs(hdev); hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev, @@ -942,6 +947,13 @@ int hci_register_dev(struct hci_dev *hdev) hci_notify(hdev, HCI_DEV_REG); return id; + +nomem: + write_lock_bh(&hci_dev_list_lock); + list_del(&hdev->list); + write_unlock_bh(&hci_dev_list_lock); + + return -ENOMEM; } EXPORT_SYMBOL(hci_register_dev); @@ -970,6 +982,8 @@ int hci_unregister_dev(struct hci_dev *hdev) hci_unregister_sysfs(hdev); + destroy_workqueue(hdev->workqueue); + __hci_dev_put(hdev); return 0; diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 0e8e1a5..a978449 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -14,8 +14,6 @@ static struct class *bt_class; struct dentry *bt_debugfs = NULL; EXPORT_SYMBOL_GPL(bt_debugfs); -static struct workqueue_struct *bt_workq; - static inline char *link_typetostr(int type) { switch (type) { @@ -161,14 +159,14 @@ void hci_conn_add_sysfs(struct hci_conn *conn) { BT_DBG("conn %p", conn); - queue_work(bt_workq, &conn->work_add); + queue_work(conn->hdev->workqueue, &conn->work_add); } void hci_conn_del_sysfs(struct hci_conn *conn) { BT_DBG("conn %p", conn); - queue_work(bt_workq, &conn->work_del); + queue_work(conn->hdev->workqueue, &conn->work_del); } static inline char *host_bustostr(int bus) @@ -487,17 +485,11 @@ void hci_unregister_sysfs(struct hci_dev *hdev) int __init bt_sysfs_init(void) { - bt_workq = create_singlethread_workqueue("bluetooth"); - if (!bt_workq) - return -ENOMEM; - bt_debugfs = debugfs_create_dir("bluetooth", NULL); bt_class = class_create(THIS_MODULE, "bluetooth"); - if (IS_ERR(bt_class)) { - destroy_workqueue(bt_workq); + if (IS_ERR(bt_class)) return PTR_ERR(bt_class); - } return 0; } @@ -507,6 +499,4 @@ void bt_sysfs_cleanup(void) class_destroy(bt_class); debugfs_remove_recursive(bt_debugfs); - - destroy_workqueue(bt_workq); } -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 59/64] Bluetooth: Fix storing negative values as unsigned char 2010-05-10 9:37 ` [PATCH 58/64] Bluetooth: Create per controller workqueue Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 60/64] Bluetooth: Decode btmrvl MODULE_BRINGUP_REG response correctly Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Dan Carpenter <error27@gmail.com> This is mostly cleanup. There is only one caller and it just checks for non-zero return values. Still "ret" should be int because we want to return -EINVAL on errors. Signed-off-by: Dan Carpenter <error27@gmail.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> --- drivers/bluetooth/btmrvl_main.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index 53a43ad..49ec89c 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -66,7 +66,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) { struct btmrvl_adapter *adapter = priv->adapter; struct btmrvl_event *event; - u8 ret = 0; + int ret = 0; event = (struct btmrvl_event *) skb->data; if (event->ec != 0xff) { -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 60/64] Bluetooth: Decode btmrvl MODULE_BRINGUP_REG response correctly 2010-05-10 9:37 ` [PATCH 59/64] Bluetooth: Fix storing negative values as unsigned char Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 61/64] Bluetooth: Separate btmrvl_register_hdev() from btmrvl_add_card() Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Bing Zhao <bzhao@marvell.com> The MODULE_BRINGUP_REQ command response returns success with either 0x00 or 0x0c. Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> --- drivers/bluetooth/btmrvl_drv.h | 5 ++++- drivers/bluetooth/btmrvl_main.c | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h index 2047275..da68c62 100644 --- a/drivers/bluetooth/btmrvl_drv.h +++ b/drivers/bluetooth/btmrvl_drv.h @@ -88,8 +88,11 @@ struct btmrvl_private { #define BT_CMD_HOST_SLEEP_ENABLE 0x5A #define BT_CMD_MODULE_CFG_REQ 0x5B -/* Sub-commands: Module Bringup/Shutdown Request */ +/* Sub-commands: Module Bringup/Shutdown Request/Response */ #define MODULE_BRINGUP_REQ 0xF1 +#define MODULE_BROUGHT_UP 0x00 +#define MODULE_ALREADY_UP 0x0C + #define MODULE_SHUTDOWN_REQ 0xF2 #define BT_EVENT_POWER_STATE 0x20 diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index 49ec89c..87d0d3d 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -112,8 +112,10 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) case BT_CMD_MODULE_CFG_REQ: if (priv->btmrvl_dev.sendcmdflag && event->data[1] == MODULE_BRINGUP_REQ) { - BT_DBG("EVENT:%s", (event->data[2]) ? - "Bring-up failed" : "Bring-up succeed"); + BT_DBG("EVENT:%s", + ((event->data[2] == MODULE_BROUGHT_UP) || + (event->data[2] == MODULE_ALREADY_UP)) ? + "Bring-up succeed" : "Bring-up failed"); } else if (priv->btmrvl_dev.sendcmdflag && event->data[1] == MODULE_SHUTDOWN_REQ) { BT_DBG("EVENT:%s", (event->data[2]) ? -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 61/64] Bluetooth: Separate btmrvl_register_hdev() from btmrvl_add_card() 2010-05-10 9:37 ` [PATCH 60/64] Bluetooth: Decode btmrvl MODULE_BRINGUP_REG response correctly Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 62/64] Bluetooth: Set hdev->dev_type based on Marvell device type Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Bing Zhao <bzhao@marvell.com> Move btmrvl hdev registration code out of btmrvl_add_card(). New function btmrvl_register_hdev() is added. Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> --- drivers/bluetooth/btmrvl_drv.h | 1 + drivers/bluetooth/btmrvl_main.c | 75 ++++++++++++++++++++++---------------- drivers/bluetooth/btmrvl_sdio.c | 7 +++- 3 files changed, 50 insertions(+), 33 deletions(-) diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h index da68c62..bf6d54f 100644 --- a/drivers/bluetooth/btmrvl_drv.h +++ b/drivers/bluetooth/btmrvl_drv.h @@ -126,6 +126,7 @@ struct btmrvl_event { /* Prototype of global function */ +int btmrvl_register_hdev(struct btmrvl_private *priv); struct btmrvl_private *btmrvl_add_card(void *card); int btmrvl_remove_card(struct btmrvl_private *priv); diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index 87d0d3d..ec48bfe 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -524,47 +524,20 @@ static int btmrvl_service_main_thread(void *data) return 0; } -struct btmrvl_private *btmrvl_add_card(void *card) +int btmrvl_register_hdev(struct btmrvl_private *priv) { struct hci_dev *hdev = NULL; - struct btmrvl_private *priv; int ret; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) { - BT_ERR("Can not allocate priv"); - goto err_priv; - } - - priv->adapter = kzalloc(sizeof(*priv->adapter), GFP_KERNEL); - if (!priv->adapter) { - BT_ERR("Allocate buffer for btmrvl_adapter failed!"); - goto err_adapter; - } - - btmrvl_init_adapter(priv); - hdev = hci_alloc_dev(); if (!hdev) { BT_ERR("Can not allocate HCI device"); goto err_hdev; } - BT_DBG("Starting kthread..."); - priv->main_thread.priv = priv; - spin_lock_init(&priv->driver_lock); - - init_waitqueue_head(&priv->main_thread.wait_q); - priv->main_thread.task = kthread_run(btmrvl_service_main_thread, - &priv->main_thread, "btmrvl_main_service"); - priv->btmrvl_dev.hcidev = hdev; - priv->btmrvl_dev.card = card; - hdev->driver_data = priv; - priv->btmrvl_dev.tx_dnld_rdy = true; - hdev->bus = HCI_SDIO; hdev->open = btmrvl_open; hdev->close = btmrvl_close; @@ -574,6 +547,8 @@ struct btmrvl_private *btmrvl_add_card(void *card) hdev->ioctl = btmrvl_ioctl; hdev->owner = THIS_MODULE; + btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ); + ret = hci_register_dev(hdev); if (ret < 0) { BT_ERR("Can not register HCI device"); @@ -584,16 +559,52 @@ struct btmrvl_private *btmrvl_add_card(void *card) btmrvl_debugfs_init(hdev); #endif - return priv; + return 0; err_hci_register_dev: - /* Stop the thread servicing the interrupts */ - kthread_stop(priv->main_thread.task); - hci_free_dev(hdev); err_hdev: + /* Stop the thread servicing the interrupts */ + kthread_stop(priv->main_thread.task); + btmrvl_free_adapter(priv); + kfree(priv); + + return -ENOMEM; +} +EXPORT_SYMBOL_GPL(btmrvl_register_hdev); + +struct btmrvl_private *btmrvl_add_card(void *card) +{ + struct btmrvl_private *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) { + BT_ERR("Can not allocate priv"); + goto err_priv; + } + + priv->adapter = kzalloc(sizeof(*priv->adapter), GFP_KERNEL); + if (!priv->adapter) { + BT_ERR("Allocate buffer for btmrvl_adapter failed!"); + goto err_adapter; + } + + btmrvl_init_adapter(priv); + + BT_DBG("Starting kthread..."); + priv->main_thread.priv = priv; + spin_lock_init(&priv->driver_lock); + + init_waitqueue_head(&priv->main_thread.wait_q); + priv->main_thread.task = kthread_run(btmrvl_service_main_thread, + &priv->main_thread, "btmrvl_main_service"); + + priv->btmrvl_dev.card = card; + priv->btmrvl_dev.tx_dnld_rdy = true; + + return priv; err_adapter: kfree(priv); diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 0dba76a..df0773e 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -931,7 +931,12 @@ static int btmrvl_sdio_probe(struct sdio_func *func, priv->hw_host_to_card = btmrvl_sdio_host_to_card; priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw; - btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ); + if (btmrvl_register_hdev(priv)) { + BT_ERR("Register hdev failed!"); + ret = -ENODEV; + goto disable_host_int; + } + priv->btmrvl_dev.psmode = 1; btmrvl_enable_ps(priv); -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 62/64] Bluetooth: Set hdev->dev_type based on Marvell device type 2010-05-10 9:37 ` [PATCH 61/64] Bluetooth: Separate btmrvl_register_hdev() from btmrvl_add_card() Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 63/64] Bluetooth: Use strict_strtoul instead of simple_strtoul Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Bing Zhao <bzhao@marvell.com> Get the device type from MODULE_BRINGUP_REQ command response. Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> --- drivers/bluetooth/btmrvl_drv.h | 2 ++ drivers/bluetooth/btmrvl_main.c | 9 +++++++++ 2 files changed, 11 insertions(+), 0 deletions(-) diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h index bf6d54f..bed0ba6 100644 --- a/drivers/bluetooth/btmrvl_drv.h +++ b/drivers/bluetooth/btmrvl_drv.h @@ -42,6 +42,8 @@ struct btmrvl_device { void *card; struct hci_dev *hcidev; + u8 dev_type; + u8 tx_dnld_rdy; u8 psmode; diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index ec48bfe..ee37ef0 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -116,6 +116,13 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) ((event->data[2] == MODULE_BROUGHT_UP) || (event->data[2] == MODULE_ALREADY_UP)) ? "Bring-up succeed" : "Bring-up failed"); + + if (event->length > 3) + priv->btmrvl_dev.dev_type = event->data[3]; + else + priv->btmrvl_dev.dev_type = HCI_BREDR; + + BT_DBG("dev_type: %d", priv->btmrvl_dev.dev_type); } else if (priv->btmrvl_dev.sendcmdflag && event->data[1] == MODULE_SHUTDOWN_REQ) { BT_DBG("EVENT:%s", (event->data[2]) ? @@ -549,6 +556,8 @@ int btmrvl_register_hdev(struct btmrvl_private *priv) btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ); + hdev->dev_type = priv->btmrvl_dev.dev_type; + ret = hci_register_dev(hdev); if (ret < 0) { BT_ERR("Can not register HCI device"); -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 63/64] Bluetooth: Use strict_strtoul instead of simple_strtoul 2010-05-10 9:37 ` [PATCH 62/64] Bluetooth: Set hdev->dev_type based on Marvell device type Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 2010-05-10 9:37 ` [PATCH 64/64] Bluetooth: Fix issues where sk_sleep() helper is needed now Marcel Holtmann 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev From: Tomas Winkler <tomas.winkler@intel.com> Use strict_strtoul as suggested by checkpatch.pl for more strict input checking. Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> --- net/bluetooth/hci_sysfs.c | 18 ++++++------------ 1 files changed, 6 insertions(+), 12 deletions(-) diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index a978449..463ffa4 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -281,11 +281,9 @@ static ssize_t show_idle_timeout(struct device *dev, struct device_attribute *at static ssize_t store_idle_timeout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct hci_dev *hdev = dev_get_drvdata(dev); - char *ptr; - __u32 val; + unsigned long val; - val = simple_strtoul(buf, &ptr, 10); - if (ptr == buf) + if (strict_strtoul(buf, 0, &val) < 0) return -EINVAL; if (val != 0 && (val < 500 || val > 3600000)) @@ -305,11 +303,9 @@ static ssize_t show_sniff_max_interval(struct device *dev, struct device_attribu static ssize_t store_sniff_max_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct hci_dev *hdev = dev_get_drvdata(dev); - char *ptr; - __u16 val; + unsigned long val; - val = simple_strtoul(buf, &ptr, 10); - if (ptr == buf) + if (strict_strtoul(buf, 0, &val) < 0) return -EINVAL; if (val < 0x0002 || val > 0xFFFE || val % 2) @@ -332,11 +328,9 @@ static ssize_t show_sniff_min_interval(struct device *dev, struct device_attribu static ssize_t store_sniff_min_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct hci_dev *hdev = dev_get_drvdata(dev); - char *ptr; - __u16 val; + unsigned long val; - val = simple_strtoul(buf, &ptr, 10); - if (ptr == buf) + if (strict_strtoul(buf, 0, &val) < 0) return -EINVAL; if (val < 0x0002 || val > 0xFFFE || val % 2) -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH 64/64] Bluetooth: Fix issues where sk_sleep() helper is needed now 2010-05-10 9:37 ` [PATCH 63/64] Bluetooth: Use strict_strtoul instead of simple_strtoul Marcel Holtmann @ 2010-05-10 9:37 ` Marcel Holtmann 0 siblings, 0 replies; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw) To: David Miller; +Cc: netdev There were some left-overs that used sk->sk_sleep instead of the new sk_sleep() helper. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> --- net/bluetooth/l2cap.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index ba49f9a..673a368 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1248,7 +1248,7 @@ static int __l2cap_wait_ack(struct sock *sk) int err = 0; int timeo = HZ/5; - add_wait_queue(sk->sk_sleep, &wait); + add_wait_queue(sk_sleep(sk), &wait); while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) { set_current_state(TASK_INTERRUPTIBLE); @@ -1269,7 +1269,7 @@ static int __l2cap_wait_ack(struct sock *sk) break; } set_current_state(TASK_RUNNING); - remove_wait_queue(sk->sk_sleep, &wait); + remove_wait_queue(sk_sleep(sk), &wait); return err; } @@ -3544,7 +3544,7 @@ static void l2cap_busy_work(struct work_struct *work) lock_sock(sk); - add_wait_queue(sk->sk_sleep, &wait); + add_wait_queue(sk_sleep(sk), &wait); while ((skb = skb_peek(BUSY_QUEUE(sk)))) { set_current_state(TASK_INTERRUPTIBLE); @@ -3603,7 +3603,7 @@ done: pi->conn_state &= ~L2CAP_CONN_RNR_SENT; set_current_state(TASK_RUNNING); - remove_wait_queue(sk->sk_sleep, &wait); + remove_wait_queue(sk_sleep(sk), &wait); release_sock(sk); } -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* Re: Pull request: bluetooth-next-2.6 2010-05-10 2010-05-10 9:36 Pull request: bluetooth-next-2.6 2010-05-10 Marcel Holtmann 2010-05-10 9:36 ` [PATCH 01/64] Bluetooth: Fix return value when bt_skb_alloc fails Marcel Holtmann @ 2010-05-10 9:47 ` David Miller 2010-05-10 10:41 ` Marcel Holtmann 2010-05-10 11:20 ` David Miller 2 siblings, 1 reply; 72+ messages in thread From: David Miller @ 2010-05-10 9:47 UTC (permalink / raw) To: marcel; +Cc: netdev From: Marcel Holtmann <marcel@holtmann.org> Date: Mon, 10 May 2010 11:36:50 +0200 > this is the big merge for the L2CAP Enhanced Retransmission support work > done by Gustavo F. Padovan. All other changes are small cleanups. Yeah, "big", as in "too big". Please sync with me more often so you don't have to obliterate the list with unacceptable 64 posting patch bombs. Nobody is going to really review such a huge patch set in any serious manner, which makes posting those patches almost worthless. Anything more than about 10 or 20 at a time is way too much. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: Pull request: bluetooth-next-2.6 2010-05-10 2010-05-10 9:47 ` Pull request: bluetooth-next-2.6 2010-05-10 David Miller @ 2010-05-10 10:41 ` Marcel Holtmann 2010-05-10 11:08 ` David Miller 0 siblings, 1 reply; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 10:41 UTC (permalink / raw) To: David Miller; +Cc: netdev Hi Dave, > > this is the big merge for the L2CAP Enhanced Retransmission support work > > done by Gustavo F. Padovan. All other changes are small cleanups. > > Yeah, "big", as in "too big". > > Please sync with me more often so you don't have to obliterate the > list with unacceptable 64 posting patch bombs. Nobody is going to > really review such a huge patch set in any serious manner, which > makes posting those patches almost worthless. > > Anything more than about 10 or 20 at a time is way too much. normally we don't have any big changes in the Bluetooth kernel side. This is the first one that adds a big set of features. And it is limited to the L2CAP layer. I took it out of last kernel release since it was incomplete and would not have been useful. Right now it is in a stage where it becomes usable. Only new profiles like the Health Medical stuff is making use of these features for now. However in the future more and more profile will requires support for it. The number of patches are not getting smaller. Except I arbitrarily merge them together. I am not planning to do that since I think it is not a good idea at all. And the patches have been reviewed by João Paulo Rechi Vita who worked with Gustavo on these changes. So do you want to postpone this for 2.6.35 merge window? Regards Marcel ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: Pull request: bluetooth-next-2.6 2010-05-10 2010-05-10 10:41 ` Marcel Holtmann @ 2010-05-10 11:08 ` David Miller 0 siblings, 0 replies; 72+ messages in thread From: David Miller @ 2010-05-10 11:08 UTC (permalink / raw) To: marcel; +Cc: netdev From: Marcel Holtmann <marcel@holtmann.org> Date: Mon, 10 May 2010 12:41:09 +0200 > normally we don't have any big changes in the Bluetooth kernel side. > This is the first one that adds a big set of features. And it is limited > to the L2CAP layer. I took it out of last kernel release since it was > incomplete and would not have been useful. Right now it is in a stage > where it becomes usable. Only new profiles like the Health Medical stuff > is making use of these features for now. However in the future more and > more profile will requires support for it. > > The number of patches are not getting smaller. Except I arbitrarily > merge them together. I am not planning to do that since I think it is > not a good idea at all. And the patches have been reviewed by João Paulo > Rechi Vita who worked with Gustavo on these changes. It is your problem if you don't think there is any value to people reviewing the stuff you're asking me to merge into the tree. > So do you want to postpone this for 2.6.35 merge window? I'll pull this stuff into net-next-2.6 after I give it a glance over but you can't operate like this in the future. Once you have about 10 commits ready in your tree, just push it to me, don't delay. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: Pull request: bluetooth-next-2.6 2010-05-10 2010-05-10 9:36 Pull request: bluetooth-next-2.6 2010-05-10 Marcel Holtmann 2010-05-10 9:36 ` [PATCH 01/64] Bluetooth: Fix return value when bt_skb_alloc fails Marcel Holtmann 2010-05-10 9:47 ` Pull request: bluetooth-next-2.6 2010-05-10 David Miller @ 2010-05-10 11:20 ` David Miller 2010-05-10 11:26 ` Marcel Holtmann 2010-05-10 11:28 ` David Miller 2 siblings, 2 replies; 72+ messages in thread From: David Miller @ 2010-05-10 11:20 UTC (permalink / raw) To: marcel; +Cc: netdev Ok, I pulled this. But patch #32 needs to be fixed. That TX window thing is, if anything, a socket option not some obscure module load parameter. Doing it with a module parameter means that you can't make it so that only some sockets (or some network paths) use a certain TX window value and other's not. Another alternative is to, as implied, make it a route metric or similar. Anything but a module option is appropriate for this. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: Pull request: bluetooth-next-2.6 2010-05-10 2010-05-10 11:20 ` David Miller @ 2010-05-10 11:26 ` Marcel Holtmann 2010-05-10 11:28 ` David Miller 1 sibling, 0 replies; 72+ messages in thread From: Marcel Holtmann @ 2010-05-10 11:26 UTC (permalink / raw) To: David Miller; +Cc: netdev Hi Dave, > Ok, I pulled this. > > But patch #32 needs to be fixed. That TX window thing is, if > anything, a socket option not some obscure module load parameter. > > Doing it with a module parameter means that you can't make it so that > only some sockets (or some network paths) use a certain TX window > value and other's not. > > Another alternative is to, as implied, make it a route metric or > similar. > > Anything but a module option is appropriate for this. actually that was only a module option so we can easily test this at an UnPlugFest. I think it can be removed all together now. We don't need it anymore. I check with Gustavo. Regards Marcel ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: Pull request: bluetooth-next-2.6 2010-05-10 2010-05-10 11:20 ` David Miller 2010-05-10 11:26 ` Marcel Holtmann @ 2010-05-10 11:28 ` David Miller 2010-05-10 11:32 ` David Miller 1 sibling, 1 reply; 72+ messages in thread From: David Miller @ 2010-05-10 11:28 UTC (permalink / raw) To: marcel; +Cc: netdev More problems. In the future, don't fix things like you did in: "Bluetooth: Fix issues where sk_sleep() helper is needed now" That's something you take care of inside of the merge which causes the build problems. It's even trivial: bash$ cd bluetooth-next-2.6 bash$ git pull .../net-next-2.6/.git bash$ make ... build fails because sk_sleep() stuff ... bash$ emacs ... bash$ make ... build succeeds now ... bash$ git commit --amend file1.c file2.c ... and add some mention in the amended merge commit about what you did to take care of the sk_sleep() stuff. That final commit command will update the merge commit so that it has the build fix included in it and therefore at any particular commit the tree does not fail to build. Otherwise you create a situation where the tree is not bisectable at all, if someone bisects to the commit before the sk_sleep() fix the tree won't build, and this makes bug hunting more painful than it needs to be. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: Pull request: bluetooth-next-2.6 2010-05-10 2010-05-10 11:28 ` David Miller @ 2010-05-10 11:32 ` David Miller 0 siblings, 0 replies; 72+ messages in thread From: David Miller @ 2010-05-10 11:32 UTC (permalink / raw) To: marcel; +Cc: netdev BT_L2CAP_EXT_FEATURES makes no sense at all... If someone can rebuild their kernel, they can just as equally add an entry to /etc/sysctl.conf to turn that thing on early in the boot process. It's not like you're going to get distributions to enable this kernel config option by default to get "wider coverage" for testing this new feature. Please just toss this thing, and please don't post so much of this kind of stuff in one go ever again, this way problems like this and the other one's can be caught early, rather than my having to pick apart several problematic changes in one huge pass. :-/ Thanks. ^ permalink raw reply [flat|nested] 72+ messages in thread
end of thread, other threads:[~2010-05-10 11:32 UTC | newest] Thread overview: 72+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-05-10 9:36 Pull request: bluetooth-next-2.6 2010-05-10 Marcel Holtmann 2010-05-10 9:36 ` [PATCH 01/64] Bluetooth: Fix return value when bt_skb_alloc fails Marcel Holtmann 2010-05-10 9:36 ` [PATCH 02/64] Bluetooth: Use the proper function cast to get hdr data Marcel Holtmann 2010-05-10 9:36 ` [PATCH 03/64] Bluetooth: Fix wrong packet type count increment Marcel Holtmann 2010-05-10 9:36 ` [PATCH 04/64] Bluetooth: Make hci_send_sco() void Marcel Holtmann 2010-05-10 9:36 ` [PATCH 05/64] Bluetooth: Trivial clean ups to SCO Marcel Holtmann 2010-05-10 9:36 ` [PATCH 06/64] Bluetooth: Move specific Basic Mode code to the right place Marcel Holtmann 2010-05-10 9:36 ` [PATCH 07/64] Bluetooth: Fix memory leak of S-frames into L2CAP Marcel Holtmann 2010-05-10 9:36 ` [PATCH 08/64] Bluetooth: Fix expected_tx_seq calculation on L2CAP Marcel Holtmann 2010-05-10 9:36 ` [PATCH 09/64] Bluetooth: Fix ACL MTU issue Marcel Holtmann 2010-05-10 9:37 ` [PATCH 10/64] Bluetooth: Use a l2cap_pinfo struct instead l2cap_pi() macro Marcel Holtmann 2010-05-10 9:37 ` [PATCH 11/64] Bluetooth: Implement 'Send IorRRorRNR' event Marcel Holtmann 2010-05-10 9:37 ` [PATCH 12/64] Bluetooth: Support case with F bit set under WAIT_F state Marcel Holtmann 2010-05-10 9:37 ` [PATCH 13/64] Bluetooth: Check the minimum {I,S}-frame size into L2CAP Marcel Holtmann 2010-05-10 9:37 ` [PATCH 14/64] Bluetooth: Check if SDU size is greater than MTU on L2CAP Marcel Holtmann 2010-05-10 9:37 ` [PATCH 15/64] Bluetooth: Implement SendAck() Action on ERTM Marcel Holtmann 2010-05-10 9:37 ` [PATCH 16/64] Bluetooth: Move set of P-bit to l2cap_send_sframe() Marcel Holtmann 2010-05-10 9:37 ` [PATCH 17/64] Bluetooth: Add Recv RR (P=0)(F=0) for SREJ_SENT state on ERTM Marcel Holtmann 2010-05-10 9:37 ` [PATCH 18/64] Bluetooth: Split l2cap_data_channel_sframe() Marcel Holtmann 2010-05-10 9:37 ` [PATCH 19/64] Bluetooth: Handle all cases of receipt of RNR-frames into L2CAP Marcel Holtmann 2010-05-10 9:37 ` [PATCH 20/64] Bluetooth: Group the ack of I-frames into l2cap_data_channel_rrframe() Marcel Holtmann 2010-05-10 9:37 ` [PATCH 21/64] Bluetooth: Remove duplicate use of __get_reqseq() macro on L2CAP Marcel Holtmann 2010-05-10 9:37 ` [PATCH 22/64] Bluetooth: Finish implementation for Rec RR (P=1) on ERTM Marcel Holtmann 2010-05-10 9:37 ` [PATCH 23/64] Bluetooth: Add timer to Acknowledge I-frames Marcel Holtmann 2010-05-10 9:37 ` [PATCH 24/64] Bluetooth: Ignore Tx Window value with Streaming mode Marcel Holtmann 2010-05-10 9:37 ` [PATCH 25/64] Bluetooth: Read RFC conf option on a successful Conf RSP Marcel Holtmann 2010-05-10 9:37 ` [PATCH 26/64] Bluetooth: Fix configuration of the MPS value Marcel Holtmann 2010-05-10 9:37 ` [PATCH 27/64] Bluetooth: Add le16 macro to Retransmission and Monitor Timeouts values Marcel Holtmann 2010-05-10 9:37 ` [PATCH 28/64] Bluetooth: Check the SDU size against the MTU value Marcel Holtmann 2010-05-10 9:37 ` [PATCH 29/64] Bluetooth: Send Ack after clear the SREJ list Marcel Holtmann 2010-05-10 9:37 ` [PATCH 30/64] Bluetooth: Add sockopt configuration for txWindow on L2CAP Marcel Holtmann 2010-05-10 9:37 ` [PATCH 31/64] Bluetooth: Change acknowledgement to use the value of txWindow Marcel Holtmann 2010-05-10 9:37 ` [PATCH 32/64] Bluetooth: Add module parameter for txWindow size on L2CAP Marcel Holtmann 2010-05-10 9:37 ` [PATCH 33/64] Bluetooth: Enable option to configure Max Transmission value via sockopt Marcel Holtmann 2010-05-10 9:37 ` [PATCH 34/64] Bluetooth: Fix bug when retransmitting I-frames Marcel Holtmann 2010-05-10 9:37 ` [PATCH 35/64] Bluetooth: Fix crash when monitor timeout expires Marcel Holtmann 2010-05-10 9:37 ` [PATCH 36/64] Bluetooth: Fix drop of acked packets on ERTM Marcel Holtmann 2010-05-10 9:37 ` [PATCH 37/64] Bluetooth: Optimize SREJ_QUEUE append Marcel Holtmann 2010-05-10 9:37 ` [PATCH 38/64] Bluetooth: Add Kconfig option for L2CAP Extended Features Marcel Holtmann 2010-05-10 9:37 ` [PATCH 39/64] Bluetooth: Add SOCK_STREAM support to L2CAP Marcel Holtmann 2010-05-10 9:37 ` [PATCH 40/64] Bluetooth: Check if mode is supported on getsockopt Marcel Holtmann 2010-05-10 9:37 ` [PATCH 41/64] Bluetooth: Fix SDU reassembly under SREJ Marcel Holtmann 2010-05-10 9:37 ` [PATCH 42/64] Bluetooth: Close L2CAP channel on invalid ReqSeq Marcel Holtmann 2010-05-10 9:37 ` [PATCH 43/64] Bluetooth: Don't set control bits to zero first Marcel Holtmann 2010-05-10 9:37 ` [PATCH 44/64] Bluetooth: Fix errors reported by checkpatch.pl Marcel Holtmann 2010-05-10 9:37 ` [PATCH 45/64] Bluetooth: Remove set of SrejSaveReqSeq under receipt of REJ frame Marcel Holtmann 2010-05-10 9:37 ` [PATCH 46/64] Bluetooth: Remove unneeded control vars Marcel Holtmann 2010-05-10 9:37 ` [PATCH 47/64] Bluetooth: Check if we really are in WAIT_F when F bit comes Marcel Holtmann 2010-05-10 9:37 ` [PATCH 48/64] Bluetooth: Fix lockdep annotation on ERTM Marcel Holtmann 2010-05-10 9:37 ` [PATCH 49/64] Bluetooth: Make hci_send_acl() void Marcel Holtmann 2010-05-10 9:37 ` [PATCH 50/64] Bluetooth: Refactor l2cap_retransmit_frame() Marcel Holtmann 2010-05-10 9:37 ` [PATCH 51/64] Bluetooth: Implement missing parts of the Invalid Frame Detection Marcel Holtmann 2010-05-10 9:37 ` [PATCH 52/64] Bluetooth: Completes the I-frame tx_seq check logic on RECV Marcel Holtmann 2010-05-10 9:37 ` [PATCH 53/64] Bluetooth: Implement Local Busy Condition handling Marcel Holtmann 2010-05-10 9:37 ` [PATCH 54/64] Bluetooth: Add wait_queue to wait ack of all sent packets Marcel Holtmann 2010-05-10 9:37 ` [PATCH 55/64] Bluetooth: Fix race condition on l2cap_ertm_send() Marcel Holtmann 2010-05-10 9:37 ` [PATCH 56/64] Bluetooth: Prevents buffer overflow on l2cap_ertm_reassembly_sdu() Marcel Holtmann 2010-05-10 9:37 ` [PATCH 57/64] Bluetooth: Fix spec error in the RemoteBusy Logic Marcel Holtmann 2010-05-10 9:37 ` [PATCH 58/64] Bluetooth: Create per controller workqueue Marcel Holtmann 2010-05-10 9:37 ` [PATCH 59/64] Bluetooth: Fix storing negative values as unsigned char Marcel Holtmann 2010-05-10 9:37 ` [PATCH 60/64] Bluetooth: Decode btmrvl MODULE_BRINGUP_REG response correctly Marcel Holtmann 2010-05-10 9:37 ` [PATCH 61/64] Bluetooth: Separate btmrvl_register_hdev() from btmrvl_add_card() Marcel Holtmann 2010-05-10 9:37 ` [PATCH 62/64] Bluetooth: Set hdev->dev_type based on Marvell device type Marcel Holtmann 2010-05-10 9:37 ` [PATCH 63/64] Bluetooth: Use strict_strtoul instead of simple_strtoul Marcel Holtmann 2010-05-10 9:37 ` [PATCH 64/64] Bluetooth: Fix issues where sk_sleep() helper is needed now Marcel Holtmann 2010-05-10 9:47 ` Pull request: bluetooth-next-2.6 2010-05-10 David Miller 2010-05-10 10:41 ` Marcel Holtmann 2010-05-10 11:08 ` David Miller 2010-05-10 11:20 ` David Miller 2010-05-10 11:26 ` Marcel Holtmann 2010-05-10 11:28 ` David Miller 2010-05-10 11:32 ` David Miller
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).