Pull request: bluetooth-next-2.6 2010-05-10
Subsystems (4)
Marcel Holtmann
maintainerHi 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
Marcel Holtmann
maintainerPATCH 1/64 Bluetooth: Fix return value when bt_skb_alloc fails
From: Gustavo F. Padovan <[email protected]>
Set the proper error(ENOMEM), instead of just return 0.
--- drivers/bluetooth/hci_h4.c | 2 +- drivers/bluetooth/hci_ll.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/bluetooth/hci_h4.c +1 -1
@@ -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;
drivers/bluetooth/hci_ll.c +1 -1
@@ -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;
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 2/64 Bluetooth: Use the proper function cast to get hdr data
From: Gustavo F. Padovan <[email protected]>
--- drivers/bluetooth/hci_ll.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
drivers/bluetooth/hci_ll.c +3 -3
@@ -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);
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 3/64 Bluetooth: Fix wrong packet type count increment
From: Gustavo F. Padovan <[email protected]>
--- drivers/bluetooth/hci_vhci.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/bluetooth/hci_vhci.c +1 -1
@@ -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 ; };
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 4/64 Bluetooth: Make hci_send_sco() void
From: Gustavo F. Padovan <[email protected]>
It also removes an unneeded check for the MTU. The check is done before on sco_send_frame()
--- 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(-)
include/net/bluetooth/hci_core.h +1 -1
@@ -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);
net/bluetooth/hci_core.c +1 -8
@@ -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);
net/bluetooth/sco.c +1 -2
@@ -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;
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 5/64 Bluetooth: Trivial clean ups to SCO
From: Gustavo F. Padovan <[email protected]>
Remove extra braces and labels, break over column 80 lines, etc
--- net/bluetooth/sco.c | 23 +++++++++++------------ 1 files changed, 11 insertions(+), 12 deletions(-)
net/bluetooth/sco.c +11 -12
@@ -165,11 +165,11 @@ static inline int sco_chan_add(struct sco_conn *conn, struct sock *sk, struct soint 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;
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 6/64 Bluetooth: Move specific Basic Mode code to the right place
From: Gustavo F. Padovan <[email protected]>
Inside "case L2CAP_MODE_BASIC:" we don't need to check for sk_type and L2CAP mode. So only the length check is fine.
--- net/bluetooth/l2cap.c | 11 ++++++----- 1 files changed, 6 insertions(+), 5 deletions(-)
net/bluetooth/l2cap.c +6 -5
@@ -1611,11 +1611,6 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msif (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 msswitch (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)) {
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 7/64 Bluetooth: Fix memory leak of S-frames into L2CAP
From: Gustavo F. Padovan <[email protected]>
l2cap_data_channel do not free the S-frame, so we free it here.
--- net/bluetooth/l2cap.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
net/bluetooth/l2cap.c +1 -0
@@ -3522,6 +3522,7 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, strbreak ; } +kfree_skb (skb);return 0 ; }
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 8/64 Bluetooth: Fix expected_tx_seq calculation on L2CAP
From: Gustavo F. Padovan <[email protected]>
All operation related to the txWindow should be modulo 64.
--- net/bluetooth/l2cap.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
net/bluetooth/l2cap.c +1 -1
@@ -3611,7 +3611,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct skif (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);
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 9/64 Bluetooth: Fix ACL MTU issue
From: Gustavo F. Padovan <[email protected]>
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.
--- net/bluetooth/l2cap.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
net/bluetooth/l2cap.c +4 -0
@@ -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);
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 10/64 Bluetooth: Use a l2cap_pinfo struct instead l2cap_pi() macro
From: Gustavo F. Padovan <[email protected]>
Trivial clean up.
--- net/bluetooth/l2cap.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-)
net/bluetooth/l2cap.c +6 -6
@@ -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 ; }
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 11/64 Bluetooth: Implement 'Send IorRRorRNR' event
From: Gustavo F. Padovan <[email protected]>
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.
--- include/net/bluetooth/l2cap.h | 20 ++++++++++-------- net/bluetooth/l2cap.c | 43 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 13 deletions(-)
include/net/bluetooth/l2cap.h +11 -9
@@ -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));
net/bluetooth/l2cap.c +39 -4
73 lines not on this page · raw message
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 12/64 Bluetooth: Support case with F bit set under WAIT_F state.
From: Gustavo F. Padovan <[email protected]>
On receipt of a F=1 under WAIT_F state ERTM shall stop monitor timer and start retransmission timer (if there are unacked frames).
--- net/bluetooth/l2cap.c | 22 ++++++++++++++-------- 1 files changed, 14 insertions(+), 8 deletions(-)
net/bluetooth/l2cap.c +14 -8
@@ -3364,6 +3364,13 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, strBT_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, strBT_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, strl2cap_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);
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 13/64 Bluetooth: Check the minimum {I,S}-frame size into L2CAP
From: Gustavo F. Padovan <[email protected]>
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.
--- net/bluetooth/l2cap.c | 14 +++++++++++--- 1 files changed, 11 insertions(+), 3 deletions(-)
net/bluetooth/l2cap.c +11 -3
@@ -3627,10 +3627,17 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct skif (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 skif (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))
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 14/64 Bluetooth: Check if SDU size is greater than MTU on L2CAP
From: Gustavo F. Padovan <[email protected]>
After reassembly the SDU we need to check his size. It can't overflow the MTU size.
--- net/bluetooth/l2cap.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-)
net/bluetooth/l2cap.c +5 -1
@@ -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 ; }
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 15/64 Bluetooth: Implement SendAck() Action on ERTM.
From: Gustavo F. Padovan <[email protected]>
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.
--- net/bluetooth/l2cap.c | 41 +++++++++++++++++++++++++++++------------ 1 files changed, 29 insertions(+), 12 deletions(-)
net/bluetooth/l2cap.c +29 -12
@@ -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 mselse 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, strstruct 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 ; }
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 16/64 Bluetooth: Move set of P-bit to l2cap_send_sframe()
From: Gustavo F. Padovan <[email protected]>
Abstract the send of of P-bit and avoids code duplication like we did with the setting of F-bit.
--- net/bluetooth/l2cap.c | 9 +++++---- 1 files changed, 5 insertions(+), 4 deletions(-)
net/bluetooth/l2cap.c +5 -4
@@ -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 );
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 17/64 Bluetooth: Add Recv RR (P=0)(F=0) for SREJ_SENT state on ERTM
From: Gustavo F. Padovan <[email protected]>
This finishes the implementation of Recv RR (P=0)(F=0) for the Enhanced Retransmission Mode on L2CAP.
--- net/bluetooth/l2cap.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-)
net/bluetooth/l2cap.c +4 -1
@@ -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 ;
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 18/64 Bluetooth: Split l2cap_data_channel_sframe()
From: Gustavo F. Padovan <[email protected]>
Create a function for each type fo S-frame and avoid a lot of nested code.
--- net/bluetooth/l2cap.c | 204 +++++++++++++++++++++++++++--------------------- 1 files changed, 115 insertions(+), 89 deletions(-)
net/bluetooth/l2cap.c +115 -89
@@ -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 ; }
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 19/64 Bluetooth: Handle all cases of receipt of RNR-frames into L2CAP
From: Gustavo F. Padovan <[email protected]>
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.
--- net/bluetooth/l2cap.c | 32 ++++++++++++++++++++++++++++---- 1 files changed, 28 insertions(+), 4 deletions(-)
net/bluetooth/l2cap.c +28 -4
@@ -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)
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 20/64 Bluetooth: Group the ack of I-frames into l2cap_data_channel_rrframe()
From: Gustavo F. Padovan <[email protected]>
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.
--- net/bluetooth/l2cap.c | 9 +++------ 1 files changed, 3 insertions(+), 6 deletions(-)
net/bluetooth/l2cap.c +3 -6
@@ -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 ();
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 21/64 Bluetooth: Remove duplicate use of __get_reqseq() macro on L2CAP
From: Gustavo F. Padovan <[email protected]>
tx_seq var already has the value of __get_reqseq().
--- net/bluetooth/l2cap.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
net/bluetooth/l2cap.c +1 -1
@@ -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 ) {
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 22/64 Bluetooth: Finish implementation for Rec RR (P=1) on ERTM
From: Gustavo F. Padovan <[email protected]>
Now the code handles the case under SREJ_SENT state.
--- net/bluetooth/l2cap.c | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-)
net/bluetooth/l2cap.c +11 -2
@@ -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 ;
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 23/64 Bluetooth: Add timer to Acknowledge I-frames
From: Gustavo F. Padovan <[email protected]>
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.
--- include/net/bluetooth/l2cap.h | 4 ++++ net/bluetooth/l2cap.c | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 0 deletions(-)
include/net/bluetooth/l2cap.h +4 -0
@@ -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) {
net/bluetooth/l2cap.c +15 -0
@@ -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_cmdskb_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_cmdskb_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);
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 24/64 Bluetooth: Ignore Tx Window value with Streaming mode
From: Gustavo F. Padovan <[email protected]>
Tx Window value shall not be used with Streaming Mode and the receiver of the config Request shall ignore its value.
--- net/bluetooth/l2cap.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
net/bluetooth/l2cap.c +0 -1
@@ -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 ;
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 25/64 Bluetooth: Read RFC conf option on a successful Conf RSP
From: Gustavo F. Padovan <[email protected]>
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.
--- net/bluetooth/l2cap.c | 39 ++++++++++++++++++++++++++++++++++++++- 1 files changed, 38 insertions(+), 1 deletions(-)
net/bluetooth/l2cap.c +38 -1
@@ -2602,6 +2602,42 @@ static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flareturn 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_hdrstruct 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_hdrswitch (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 )) {
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 26/64 Bluetooth: Fix configuration of the MPS value
From: Gustavo F. Padovan <[email protected]>
We were accepting values bigger than we can accept. This was leading ERTM to drop packets because of wrong FCS checks.
--- include/net/bluetooth/l2cap.h | 3 ++- net/bluetooth/l2cap.c | 36 ++++++++++++++++++++---------------- 2 files changed, 22 insertions(+), 17 deletions(-)
include/net/bluetooth/l2cap.h +2 -1
@@ -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;
net/bluetooth/l2cap.c +20 -16
@@ -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 mscase 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 skif (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))
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 27/64 Bluetooth: Add le16 macro to Retransmission and Monitor Timeouts values
From: Gustavo F. Padovan <[email protected]>
Fix a possible problem with Big Endian machines.
--- net/bluetooth/l2cap.c | 14 ++++++++------ 1 files changed, 8 insertions(+), 6 deletions(-)
net/bluetooth/l2cap.c +8 -6
@@ -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 :
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 28/64 Bluetooth: Check the SDU size against the MTU value
From: Gustavo F. Padovan <[email protected]>
If the SDU size is greater than the MTU something is wrong, so report an error.
--- net/bluetooth/l2cap.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
net/bluetooth/l2cap.c +5 -0
@@ -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 ;
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 29/64 Bluetooth: Send Ack after clear the SREJ list
From: Gustavo F. Padovan <[email protected]>
As specified by Bluetooth 3.0 spec we shall send an acknowledgment using the Send-Ack() after clear the SREJ list.
--- net/bluetooth/l2cap.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
net/bluetooth/l2cap.c +1 -0
@@ -3493,6 +3493,7 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, strif (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;
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 30/64 Bluetooth: Add sockopt configuration for txWindow on L2CAP
From: Gustavo F. Padovan <[email protected]>
Now we can set/get Transmission Window size via sockopt.
--- include/net/bluetooth/l2cap.h | 2 ++ net/bluetooth/l2cap.c | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletions(-)
include/net/bluetooth/l2cap.h +2 -0
@@ -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;
net/bluetooth/l2cap.c +6 -1
@@ -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 __usl2cap_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 ;
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 31/64 Bluetooth: Change acknowledgement to use the value of txWindow
From: Gustavo F. Padovan <[email protected]>
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.
--- include/net/bluetooth/l2cap.h | 3 +-- net/bluetooth/l2cap.c | 7 ++++--- 2 files changed, 5 insertions(+), 5 deletions(-)
include/net/bluetooth/l2cap.h +1 -2
@@ -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;
net/bluetooth/l2cap.c +4 -3
@@ -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, stru8 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 ;
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 32/64 Bluetooth: Add module parameter for txWindow size on L2CAP
From: Gustavo F. Padovan <[email protected]>
Very useful for testing purposes.
--- net/bluetooth/l2cap.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-)
net/bluetooth/l2cap.c +5 -1
@@ -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 <[email protected]>" );MODULE_DESCRIPTION ("Bluetooth L2CAP ver " VERSION );MODULE_VERSION (VERSION );
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 33/64 Bluetooth: Enable option to configure Max Transmission value via sockopt
From: Gustavo F. Padovan <[email protected]>
With the sockopt extension we can set a per-channel MaxTx value.
--- include/net/bluetooth/l2cap.h | 2 ++ net/bluetooth/l2cap.c | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletions(-)
include/net/bluetooth/l2cap.h +2 -0
@@ -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;
net/bluetooth/l2cap.c +6 -1
@@ -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 __usl2cap_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 );
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 34/64 Bluetooth: Fix bug when retransmitting I-frames
From: Gustavo F. Padovan <[email protected]>
If there is no frames to retransmit l2cap was crashing the kernel, now we check if the queue is empty first.
--- net/bluetooth/l2cap.c | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-)
net/bluetooth/l2cap.c +8 -4
@@ -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);
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 35/64 Bluetooth: Fix crash when monitor timeout expires
From: Gustavo F. Padovan <[email protected]>
The code was crashing due to a invalid access to hci_conn after the channel disconnect.
--- net/bluetooth/l2cap.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
net/bluetooth/l2cap.c +3 -0
@@ -1568,6 +1568,9 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *mBT_DBG ("sk %p len %d" , sk, (int )len); +if (!conn) +return ERR_PTR (-ENOTCONN ); +if (sdulen) hlen +=2 ;
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 36/64 Bluetooth: Fix drop of acked packets on ERTM
From: Gustavo F. Padovan <[email protected]>
l2cap_drop_acked_frames() was droping not sent packets, causing them to be not transmitted.
--- net/bluetooth/l2cap.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
net/bluetooth/l2cap.c +2 -1
@@ -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 ;
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 37/64 Bluetooth: Optimize SREJ_QUEUE append
From: Gustavo F. Padovan <[email protected]>
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).
--- net/bluetooth/l2cap.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
net/bluetooth/l2cap.c +3 -1
@@ -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 ; }
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 38/64 Bluetooth: Add Kconfig option for L2CAP Extended Features
From: Gustavo F. Padovan <[email protected]>
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).
--- net/bluetooth/Kconfig | 13 +++++++++++++ net/bluetooth/l2cap.c | 4 ++++ 2 files changed, 17 insertions(+), 0 deletions(-)
net/bluetooth/Kconfig +13 -0
@@ -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
net/bluetooth/l2cap.c +4 -0
@@ -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 ;
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 39/64 Bluetooth: Add SOCK_STREAM support to L2CAP
From: Gustavo F. Padovan <[email protected]>
if enable_ertm is true and we have SOCK_STREAM the default mode will be ERTM, otherwise Basic Mode.
--- net/bluetooth/l2cap.c | 40 ++++++++++++++++++++++++++-------------- 1 files changed, 26 insertions(+), 14 deletions(-)
net/bluetooth/l2cap.c +26 -14
@@ -224,7 +224,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sol2cap_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 allock_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, chswitch (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, chswitch (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 ) {
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 40/64 Bluetooth: Check if mode is supported on getsockopt
From: João Paulo Rechi Vita <[email protected]>
Add this check to getsockopt makes possible to fail early instead of waiting until listen / connect.
--- net/bluetooth/l2cap.c | 15 ++++++++++++++- 1 files changed, 14 insertions(+), 1 deletions(-)
net/bluetooth/l2cap.c +14 -1
@@ -1814,9 +1814,22 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __usbreak ; } +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;
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 41/64 Bluetooth: Fix SDU reassembly under SREJ
From: Gustavo F. Padovan <[email protected]>
The code was reusing the control var without its reinitialization.
--- net/bluetooth/l2cap.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
net/bluetooth/l2cap.c +2 -2
@@ -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 ;
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 42/64 Bluetooth: Close L2CAP channel on invalid ReqSeq
From: João Paulo Rechi Vita <[email protected]>
--- net/bluetooth/l2cap.c | 18 +++++++++++++++++- 1 files changed, 17 insertions(+), 1 deletions(-)
net/bluetooth/l2cap.c +17 -1
@@ -3772,7 +3772,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct skstruct 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 skif (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;
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 43/64 Bluetooth: Don't set control bits to zero first
From: Gustavo F. Padovan <[email protected]>
We can set the SAR bits in the control field directly.
--- net/bluetooth/l2cap.c | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-)
net/bluetooth/l2cap.c +2 -4
@@ -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 )
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 44/64 Bluetooth: Fix errors reported by checkpatch.pl
From: Gustavo F. Padovan <[email protected]>
--- net/bluetooth/l2cap.c | 11 +++++------ 1 files changed, 5 insertions(+), 6 deletions(-)
net/bluetooth/l2cap.c +5 -6
@@ -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, instruct 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);
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 45/64 Bluetooth: Remove set of SrejSaveReqSeq under receipt of REJ frame
From: Gustavo F. Padovan <[email protected]>
That action is not specified by the ERTM spec, so removing it.
--- net/bluetooth/l2cap.c | 4 +--- 1 files changed, 1 insertions(+), 3 deletions(-)
net/bluetooth/l2cap.c +1 -3
@@ -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)
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 46/64 Bluetooth: Remove unneeded control vars
From: Gustavo F. Padovan <[email protected]>
Trivial clean up.
--- net/bluetooth/l2cap.c | 14 ++++---------- 1 files changed, 4 insertions(+), 10 deletions(-)
net/bluetooth/l2cap.c +4 -10
@@ -1239,7 +1239,6 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *lstatic 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 ; }
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 47/64 Bluetooth: Check if we really are in WAIT_F when F bit comes
From: Gustavo F. Padovan <[email protected]>
F-bit set should be processed only if we are in the WAIT_F state.
--- net/bluetooth/l2cap.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-)
net/bluetooth/l2cap.c +4 -2
@@ -3503,7 +3503,8 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, strBT_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 ();
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 48/64 Bluetooth: Fix lockdep annotation on ERTM
From: Gustavo F. Padovan <[email protected]>
A spin_lock_init() call was missing. :)
--- net/bluetooth/l2cap.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
net/bluetooth/l2cap.c +1 -1
@@ -1622,7 +1622,7 @@ static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, sizu16 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))
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 49/64 Bluetooth: Make hci_send_acl() void
From: Gustavo F. Padovan <[email protected]>
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.
--- 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(-)
include/net/bluetooth/hci_core.h +1 -1
@@ -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);
net/bluetooth/hci_core.c +2 -2
@@ -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);
net/bluetooth/l2cap.c +27 -46
191 lines not on this page · raw message
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 50/64 Bluetooth: Refactor l2cap_retransmit_frame()
From: Gustavo F. Padovan <[email protected]>
Make the code flow cleaner and changes the function to void. It also fixes a potential NULL dereference with skb.
--- net/bluetooth/l2cap.c | 53 +++++++++++++++++++++++++------------------------ 1 files changed, 27 insertions(+), 26 deletions(-)
net/bluetooth/l2cap.c +27 -26
@@ -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)
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 51/64 Bluetooth: Implement missing parts of the Invalid Frame Detection
From: Gustavo F. Padovan <[email protected]>
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.
--- net/bluetooth/l2cap.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 112 insertions(+), 7 deletions(-)
net/bluetooth/l2cap.c +112 -7
@@ -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 skelse pi->expected_tx_seq = (tx_seq +1 ) %64 ; -l2cap_sar_reassembly_sdu (sk, skb, control); +l2cap_streaming_reassembly_sdu (sk, skb, control); goto done;
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 52/64 Bluetooth: Completes the I-frame tx_seq check logic on RECV
From: João Paulo Rechi Vita <[email protected]>
Add checks for invalid tx_seq and fixes the duplicated tx_seq check.
--- net/bluetooth/l2cap.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 files changed, 36 insertions(+), 4 deletions(-)
net/bluetooth/l2cap.c +36 -4
@@ -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, stru8 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, strif (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, strl2cap_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)
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 53/64 Bluetooth: Implement Local Busy Condition handling
From: Gustavo F. Padovan <[email protected]>
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.
--- include/net/bluetooth/l2cap.h | 6 ++ net/bluetooth/l2cap.c | 187 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 172 insertions(+), 21 deletions(-)
include/net/bluetooth/l2cap.h +6 -0
@@ -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));
net/bluetooth/l2cap.c +166 -21
313 lines not on this page · raw message
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 54/64 Bluetooth: Add wait_queue to wait ack of all sent packets
From: Gustavo F. Padovan <[email protected]>
To guarantee that all packets we sent were received we need to wait for theirs ack before shutdown the socket.
--- net/bluetooth/l2cap.c | 34 ++++++++++++++++++++++++++++++++++ 1 files changed, 34 insertions(+), 0 deletions(-)
net/bluetooth/l2cap.c +34 -0
@@ -1242,6 +1242,37 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *lreturn 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 );
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 55/64 Bluetooth: Fix race condition on l2cap_ertm_send()
From: Gustavo F. Padovan <[email protected]>
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
--- include/net/bluetooth/l2cap.h | 1 + net/bluetooth/l2cap.c | 99 +++++++++++++++++++++++++++-------------- 2 files changed, 67 insertions(+), 33 deletions(-)
include/net/bluetooth/l2cap.h +1 -0
@@ -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;
net/bluetooth/l2cap.c +66 -33
200 lines not on this page · raw message
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 56/64 Bluetooth: Prevents buffer overflow on l2cap_ertm_reassembly_sdu()
From: Gustavo F. Padovan <[email protected]>
The checks should be done before the the memcpy to avoid buffer overflow.
--- net/bluetooth/l2cap.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-)
net/bluetooth/l2cap.c +4 -4
@@ -3470,12 +3470,12 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 cif (!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 cif (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 );
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 57/64 Bluetooth: Fix spec error in the RemoteBusy Logic
From: Gustavo F. Padovan <[email protected]>
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.
--- net/bluetooth/l2cap.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
net/bluetooth/l2cap.c +2 -1
@@ -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 ) {
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 58/64 Bluetooth: Create per controller workqueue
Instead of having a global workqueue for all controllers, it makes more sense to have a workqueue per controller.
--- 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(-)
include/net/bluetooth/hci_core.h +2 -0
@@ -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;
net/bluetooth/hci_core.c +14 -0
@@ -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 ;
net/bluetooth/hci_sysfs.c +3 -13
@@ -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); }
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 59/64 Bluetooth: Fix storing negative values as unsigned char
From: Dan Carpenter <[email protected]>
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.
--- drivers/bluetooth/btmrvl_main.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/bluetooth/btmrvl_main.c +1 -1
@@ -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 ) {
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 60/64 Bluetooth: Decode btmrvl MODULE_BRINGUP_REG response correctly
From: Bing Zhao <[email protected]>
The MODULE_BRINGUP_REQ command response returns success with either 0x00 or 0x0c.
--- drivers/bluetooth/btmrvl_drv.h | 5 ++++- drivers/bluetooth/btmrvl_main.c | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-)
drivers/bluetooth/btmrvl_drv.h +4 -1
@@ -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
drivers/bluetooth/btmrvl_main.c +4 -2
@@ -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]) ?
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 61/64 Bluetooth: Separate btmrvl_register_hdev() from btmrvl_add_card()
From: Bing Zhao <[email protected]>
Move btmrvl hdev registration code out of btmrvl_add_card(). New function btmrvl_register_hdev() is added.
--- 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(-)
drivers/bluetooth/btmrvl_drv.h +1 -0
@@ -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);
drivers/bluetooth/btmrvl_main.c +43 -32
112 lines not on this page · raw message
drivers/bluetooth/btmrvl_sdio.c +6 -1
@@ -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);
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 62/64 Bluetooth: Set hdev->dev_type based on Marvell device type
From: Bing Zhao <[email protected]>
Get the device type from MODULE_BRINGUP_REQ command response.
--- drivers/bluetooth/btmrvl_drv.h | 2 ++ drivers/bluetooth/btmrvl_main.c | 9 +++++++++ 2 files changed, 11 insertions(+), 0 deletions(-)
drivers/bluetooth/btmrvl_drv.h +2 -0
@@ -42,6 +42,8 @@ struct btmrvl_device {void *card;struct hci_dev *hcidev; +u8 dev_type; +u8 tx_dnld_rdy;u8 psmode;
drivers/bluetooth/btmrvl_main.c +9 -0
@@ -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" );
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 63/64 Bluetooth: Use strict_strtoul instead of simple_strtoul
From: Tomas Winkler <[email protected]>
Use strict_strtoul as suggested by checkpatch.pl for more strict input checking.
--- net/bluetooth/hci_sysfs.c | 18 ++++++------------ 1 files changed, 6 insertions(+), 12 deletions(-)
net/bluetooth/hci_sysfs.c +6 -12
@@ -281,11 +281,9 @@ static ssize_t show_idle_timeout(struct device *dev, struct device_attribute *atstatic 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_attribustatic 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_attribustatic 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 )
Signature · 1 line
1.6.6.1
Marcel Holtmann
maintainerPATCH 64/64 Bluetooth: Fix issues where sk_sleep() helper is needed now
There were some left-overs that used sk->sk_sleep instead of the new sk_sleep() helper.
--- net/bluetooth/l2cap.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-)
net/bluetooth/l2cap.c +4 -4
@@ -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); }
Signature · 1 line
1.6.6.1
David Miller
maintainerFrom: Marcel Holtmann <[email protected]>
Date: Mon, 10 May 2010 11:36:50 +0200
Quoted 2 lines
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.
Marcel Holtmann
maintainerHi Dave,
Quoted 11 lines
Quoted 2 lines
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
David Miller
maintainerFrom: Marcel Holtmann <[email protected]>
Date: Mon, 10 May 2010 12:41:09 +0200
Quoted 8 lines
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.
Quoted 4 lines
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.
Quoted 1 line
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.
David Miller
maintainerOk, 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.
Marcel Holtmann
maintainerHi Dave,
Quoted 5 lines
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.
Quoted 8 lines
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
David Miller
maintainerMore 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.
David Miller
maintainerBT_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.