aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMat Martineau <mathewm@codeaurora.org>2012-05-17 23:53:35 -0400
committerJohan Hedberg <johan.hedberg@intel.com>2012-06-04 23:34:02 -0400
commita67d7f6fca776317bb478c96f25196972c05d173 (patch)
treeb4e6f2f2304673775915c23e14646bee7fa1a987
parent18a48e76640c590a14b0286c9da5fde6ac146cc2 (diff)
Bluetooth: Refactor l2cap_send_sframe
The new implementation uses struct l2cap_ctrl to set up the sframe fields, and also reduces duplicate acks by canceling the ack timer whenever an RR or RNR frame is sent. sframe PDU generation is also split in to a separate function to separate it from the logic related to the connection state and sframe type. Signed-off-by: Mat Martineau <mathewm@codeaurora.org> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
-rw-r--r--net/bluetooth/l2cap_core.c87
1 files changed, 51 insertions, 36 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 429a67ea47d0..c7bf613294cc 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -848,15 +848,12 @@ static inline void __pack_control(struct l2cap_chan *chan,
848 } 848 }
849} 849}
850 850
851static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control) 851static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan,
852 u32 control)
852{ 853{
853 struct sk_buff *skb; 854 struct sk_buff *skb;
854 struct l2cap_hdr *lh; 855 struct l2cap_hdr *lh;
855 struct l2cap_conn *conn = chan->conn; 856 int hlen;
856 int count, hlen;
857
858 if (chan->state != BT_CONNECTED)
859 return;
860 857
861 if (test_bit(FLAG_EXT_CTRL, &chan->flags)) 858 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
862 hlen = L2CAP_EXT_HDR_SIZE; 859 hlen = L2CAP_EXT_HDR_SIZE;
@@ -866,35 +863,65 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
866 if (chan->fcs == L2CAP_FCS_CRC16) 863 if (chan->fcs == L2CAP_FCS_CRC16)
867 hlen += L2CAP_FCS_SIZE; 864 hlen += L2CAP_FCS_SIZE;
868 865
869 BT_DBG("chan %p, control 0x%8.8x", chan, control); 866 skb = bt_skb_alloc(hlen, GFP_KERNEL);
870
871 count = min_t(unsigned int, conn->mtu, hlen);
872
873 control |= __set_sframe(chan);
874
875 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
876 control |= __set_ctrl_final(chan);
877
878 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
879 control |= __set_ctrl_poll(chan);
880 867
881 skb = bt_skb_alloc(count, GFP_ATOMIC);
882 if (!skb) 868 if (!skb)
883 return; 869 return ERR_PTR(-ENOMEM);
884 870
885 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 871 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
886 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); 872 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
887 lh->cid = cpu_to_le16(chan->dcid); 873 lh->cid = cpu_to_le16(chan->dcid);
888 874
889 __put_control(chan, control, skb_put(skb, __ctrl_size(chan))); 875 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
876 put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
877 else
878 put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
890 879
891 if (chan->fcs == L2CAP_FCS_CRC16) { 880 if (chan->fcs == L2CAP_FCS_CRC16) {
892 u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE); 881 u16 fcs = crc16(0, (u8 *)skb->data, skb->len);
893 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 882 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
894 } 883 }
895 884
896 skb->priority = HCI_PRIO_MAX; 885 skb->priority = HCI_PRIO_MAX;
897 l2cap_do_send(chan, skb); 886 return skb;
887}
888
889static void l2cap_send_sframe(struct l2cap_chan *chan,
890 struct l2cap_ctrl *control)
891{
892 struct sk_buff *skb;
893 u32 control_field;
894
895 BT_DBG("chan %p, control %p", chan, control);
896
897 if (!control->sframe)
898 return;
899
900 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) &&
901 !control->poll)
902 control->final = 1;
903
904 if (control->super == L2CAP_SUPER_RR)
905 clear_bit(CONN_RNR_SENT, &chan->conn_state);
906 else if (control->super == L2CAP_SUPER_RNR)
907 set_bit(CONN_RNR_SENT, &chan->conn_state);
908
909 if (control->super != L2CAP_SUPER_SREJ) {
910 chan->last_acked_seq = control->reqseq;
911 __clear_ack_timer(chan);
912 }
913
914 BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq,
915 control->final, control->poll, control->super);
916
917 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
918 control_field = __pack_extended_control(control);
919 else
920 control_field = __pack_enhanced_control(control);
921
922 skb = l2cap_create_sframe_pdu(chan, control_field);
923 if (!IS_ERR(skb))
924 l2cap_do_send(chan, skb);
898} 925}
899 926
900static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control) 927static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
@@ -906,8 +933,6 @@ static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
906 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 933 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
907 934
908 control |= __set_reqseq(chan, chan->buffer_seq); 935 control |= __set_reqseq(chan, chan->buffer_seq);
909
910 l2cap_send_sframe(chan, control);
911} 936}
912 937
913static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) 938static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
@@ -1826,7 +1851,6 @@ static void __l2cap_send_ack(struct l2cap_chan *chan)
1826 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 1851 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
1827 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); 1852 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
1828 set_bit(CONN_RNR_SENT, &chan->conn_state); 1853 set_bit(CONN_RNR_SENT, &chan->conn_state);
1829 l2cap_send_sframe(chan, control);
1830 return; 1854 return;
1831 } 1855 }
1832 1856
@@ -1834,7 +1858,6 @@ static void __l2cap_send_ack(struct l2cap_chan *chan)
1834 return; 1858 return;
1835 1859
1836 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 1860 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
1837 l2cap_send_sframe(chan, control);
1838} 1861}
1839 1862
1840static void l2cap_send_ack(struct l2cap_chan *chan) 1863static void l2cap_send_ack(struct l2cap_chan *chan)
@@ -1853,8 +1876,6 @@ static void l2cap_send_srejtail(struct l2cap_chan *chan)
1853 1876
1854 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list); 1877 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
1855 control |= __set_reqseq(chan, tail->tx_seq); 1878 control |= __set_reqseq(chan, tail->tx_seq);
1856
1857 l2cap_send_sframe(chan, control);
1858} 1879}
1859 1880
1860static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, 1881static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
@@ -2259,7 +2280,7 @@ static int l2cap_tx_state_xmit(struct l2cap_chan *chan,
2259 local_control.super = L2CAP_SUPER_RR; 2280 local_control.super = L2CAP_SUPER_RR;
2260 local_control.poll = 1; 2281 local_control.poll = 1;
2261 local_control.reqseq = chan->buffer_seq; 2282 local_control.reqseq = chan->buffer_seq;
2262 l2cap_send_sframe(chan, 0); 2283 l2cap_send_sframe(chan, &local_control);
2263 2284
2264 chan->retry_count = 1; 2285 chan->retry_count = 1;
2265 __set_monitor_timer(chan); 2286 __set_monitor_timer(chan);
@@ -2333,7 +2354,7 @@ static int l2cap_tx_state_wait_f(struct l2cap_chan *chan,
2333 local_control.super = L2CAP_SUPER_RR; 2354 local_control.super = L2CAP_SUPER_RR;
2334 local_control.poll = 1; 2355 local_control.poll = 1;
2335 local_control.reqseq = chan->buffer_seq; 2356 local_control.reqseq = chan->buffer_seq;
2336 l2cap_send_sframe(chan, 0); 2357 l2cap_send_sframe(chan, &local_control);
2337 2358
2338 chan->retry_count = 1; 2359 chan->retry_count = 1;
2339 __set_monitor_timer(chan); 2360 __set_monitor_timer(chan);
@@ -4233,7 +4254,6 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
4233 4254
4234 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 4255 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4235 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); 4256 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
4236 l2cap_send_sframe(chan, control);
4237 set_bit(CONN_RNR_SENT, &chan->conn_state); 4257 set_bit(CONN_RNR_SENT, &chan->conn_state);
4238 } 4258 }
4239 4259
@@ -4245,7 +4265,6 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
4245 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 4265 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
4246 chan->frames_sent == 0) { 4266 chan->frames_sent == 0) {
4247 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 4267 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
4248 l2cap_send_sframe(chan, control);
4249 } 4268 }
4250} 4269}
4251 4270
@@ -4404,7 +4423,6 @@ static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
4404 control = __set_reqseq(chan, chan->buffer_seq); 4423 control = __set_reqseq(chan, chan->buffer_seq);
4405 control |= __set_ctrl_poll(chan); 4424 control |= __set_ctrl_poll(chan);
4406 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 4425 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
4407 l2cap_send_sframe(chan, control);
4408 chan->retry_count = 1; 4426 chan->retry_count = 1;
4409 4427
4410 __clear_retrans_timer(chan); 4428 __clear_retrans_timer(chan);
@@ -4468,7 +4486,6 @@ static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
4468 } 4486 }
4469 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ); 4487 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
4470 control |= __set_reqseq(chan, l->tx_seq); 4488 control |= __set_reqseq(chan, l->tx_seq);
4471 l2cap_send_sframe(chan, control);
4472 list_del(&l->list); 4489 list_del(&l->list);
4473 list_add_tail(&l->list, &chan->srej_l); 4490 list_add_tail(&l->list, &chan->srej_l);
4474 } 4491 }
@@ -4483,7 +4500,6 @@ static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
4483 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ); 4500 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
4484 control |= __set_reqseq(chan, chan->expected_tx_seq); 4501 control |= __set_reqseq(chan, chan->expected_tx_seq);
4485 l2cap_seq_list_append(&chan->srej_list, chan->expected_tx_seq); 4502 l2cap_seq_list_append(&chan->srej_list, chan->expected_tx_seq);
4486 l2cap_send_sframe(chan, control);
4487 4503
4488 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); 4504 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
4489 if (!new) 4505 if (!new)
@@ -4767,7 +4783,6 @@ static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_c
4767 l2cap_send_srejtail(chan); 4783 l2cap_send_srejtail(chan);
4768 } else { 4784 } else {
4769 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR); 4785 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
4770 l2cap_send_sframe(chan, rx_control);
4771 } 4786 }
4772} 4787}
4773 4788