aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMat Martineau <mathewm@codeaurora.org>2012-10-23 18:24:11 -0400
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2012-10-23 22:12:04 -0400
commit32b32735ca1439e2ead658dd63234c0c380af8ac (patch)
treeea400cb0ba20d8c105ff33911a39e115f545572a
parent02b0fbb92dbb0e3c50f1c955547444e3997c80e3 (diff)
Bluetooth: Add new ERTM receive states for channel move
Two new states are required to implement channel moves with the ERTM receive state machine. The "WAIT_P" state is used by a move responder to wait for a "poll" flag after a move is completed (success or failure). "WAIT_F" is similarly used by a move initiator to wait for a "final" flag when the move is completing. In either state, the reqseq value in the poll/final frame tells the state machine exactly which frame should be expected next. Signed-off-by: Mat Martineau <mathewm@codeaurora.org> Acked-by: Marcel Holtmann <marcel@holtmann.org> Acked-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
-rw-r--r--net/bluetooth/l2cap_core.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 24729f54bfd0..b9a91bf3d95e 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -4713,6 +4713,12 @@ static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
4713 return err; 4713 return err;
4714} 4714}
4715 4715
4716static int l2cap_resegment(struct l2cap_chan *chan)
4717{
4718 /* Placeholder */
4719 return 0;
4720}
4721
4716void l2cap_chan_busy(struct l2cap_chan *chan, int busy) 4722void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
4717{ 4723{
4718 u8 event; 4724 u8 event;
@@ -5218,6 +5224,96 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
5218 return err; 5224 return err;
5219} 5225}
5220 5226
5227static int l2cap_finish_move(struct l2cap_chan *chan)
5228{
5229 BT_DBG("chan %p", chan);
5230
5231 chan->rx_state = L2CAP_RX_STATE_RECV;
5232
5233 if (chan->hs_hcon)
5234 chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
5235 else
5236 chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
5237
5238 return l2cap_resegment(chan);
5239}
5240
5241static int l2cap_rx_state_wait_p(struct l2cap_chan *chan,
5242 struct l2cap_ctrl *control,
5243 struct sk_buff *skb, u8 event)
5244{
5245 int err;
5246
5247 BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
5248 event);
5249
5250 if (!control->poll)
5251 return -EPROTO;
5252
5253 l2cap_process_reqseq(chan, control->reqseq);
5254
5255 if (!skb_queue_empty(&chan->tx_q))
5256 chan->tx_send_head = skb_peek(&chan->tx_q);
5257 else
5258 chan->tx_send_head = NULL;
5259
5260 /* Rewind next_tx_seq to the point expected
5261 * by the receiver.
5262 */
5263 chan->next_tx_seq = control->reqseq;
5264 chan->unacked_frames = 0;
5265
5266 err = l2cap_finish_move(chan);
5267 if (err)
5268 return err;
5269
5270 set_bit(CONN_SEND_FBIT, &chan->conn_state);
5271 l2cap_send_i_or_rr_or_rnr(chan);
5272
5273 if (event == L2CAP_EV_RECV_IFRAME)
5274 return -EPROTO;
5275
5276 return l2cap_rx_state_recv(chan, control, NULL, event);
5277}
5278
5279static int l2cap_rx_state_wait_f(struct l2cap_chan *chan,
5280 struct l2cap_ctrl *control,
5281 struct sk_buff *skb, u8 event)
5282{
5283 int err;
5284
5285 if (!control->final)
5286 return -EPROTO;
5287
5288 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
5289
5290 chan->rx_state = L2CAP_RX_STATE_RECV;
5291 l2cap_process_reqseq(chan, control->reqseq);
5292
5293 if (!skb_queue_empty(&chan->tx_q))
5294 chan->tx_send_head = skb_peek(&chan->tx_q);
5295 else
5296 chan->tx_send_head = NULL;
5297
5298 /* Rewind next_tx_seq to the point expected
5299 * by the receiver.
5300 */
5301 chan->next_tx_seq = control->reqseq;
5302 chan->unacked_frames = 0;
5303
5304 if (chan->hs_hcon)
5305 chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
5306 else
5307 chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
5308
5309 err = l2cap_resegment(chan);
5310
5311 if (!err)
5312 err = l2cap_rx_state_recv(chan, control, skb, event);
5313
5314 return err;
5315}
5316
5221static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq) 5317static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq)
5222{ 5318{
5223 /* Make sure reqseq is for a packet that has been sent but not acked */ 5319 /* Make sure reqseq is for a packet that has been sent but not acked */
@@ -5244,6 +5340,12 @@ static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
5244 err = l2cap_rx_state_srej_sent(chan, control, skb, 5340 err = l2cap_rx_state_srej_sent(chan, control, skb,
5245 event); 5341 event);
5246 break; 5342 break;
5343 case L2CAP_RX_STATE_WAIT_P:
5344 err = l2cap_rx_state_wait_p(chan, control, skb, event);
5345 break;
5346 case L2CAP_RX_STATE_WAIT_F:
5347 err = l2cap_rx_state_wait_f(chan, control, skb, event);
5348 break;
5247 default: 5349 default:
5248 /* shut it down */ 5350 /* shut it down */
5249 break; 5351 break;