Lines Matching refs:shdlc
126 static struct sk_buff *llc_shdlc_alloc_skb(const struct llc_shdlc *shdlc, in llc_shdlc_alloc_skb() argument
131 skb = alloc_skb(shdlc->tx_headroom + SHDLC_LLC_HEAD_ROOM + in llc_shdlc_alloc_skb()
132 shdlc->tx_tailroom + payload_len, GFP_KERNEL); in llc_shdlc_alloc_skb()
134 skb_reserve(skb, shdlc->tx_headroom + SHDLC_LLC_HEAD_ROOM); in llc_shdlc_alloc_skb()
140 static int llc_shdlc_send_s_frame(const struct llc_shdlc *shdlc, in llc_shdlc_send_s_frame() argument
148 skb = llc_shdlc_alloc_skb(shdlc, 0); in llc_shdlc_send_s_frame()
154 r = shdlc->xmit_to_drv(shdlc->hdev, skb); in llc_shdlc_send_s_frame()
162 static int llc_shdlc_send_u_frame(const struct llc_shdlc *shdlc, in llc_shdlc_send_u_frame() argument
172 r = shdlc->xmit_to_drv(shdlc->hdev, skb); in llc_shdlc_send_u_frame()
183 static void llc_shdlc_reset_t2(struct llc_shdlc *shdlc, int y_nr) in llc_shdlc_reset_t2() argument
186 int dnr = shdlc->dnr; /* MUST initially be < y_nr */ in llc_shdlc_reset_t2()
193 skb = skb_dequeue(&shdlc->ack_pending_q); in llc_shdlc_reset_t2()
199 if (skb_queue_empty(&shdlc->ack_pending_q)) { in llc_shdlc_reset_t2()
200 if (shdlc->t2_active) { in llc_shdlc_reset_t2()
201 del_timer_sync(&shdlc->t2_timer); in llc_shdlc_reset_t2()
202 shdlc->t2_active = false; in llc_shdlc_reset_t2()
208 skb = skb_peek(&shdlc->ack_pending_q); in llc_shdlc_reset_t2()
210 mod_timer(&shdlc->t2_timer, *(unsigned long *)skb->cb + in llc_shdlc_reset_t2()
212 shdlc->t2_active = true; in llc_shdlc_reset_t2()
223 static void llc_shdlc_rcv_i_frame(struct llc_shdlc *shdlc, in llc_shdlc_rcv_i_frame() argument
231 if (shdlc->state != SHDLC_CONNECTED) in llc_shdlc_rcv_i_frame()
234 if (x_ns != shdlc->nr) { in llc_shdlc_rcv_i_frame()
235 llc_shdlc_send_s_frame(shdlc, S_FRAME_REJ, shdlc->nr); in llc_shdlc_rcv_i_frame()
239 if (!shdlc->t1_active) { in llc_shdlc_rcv_i_frame()
240 shdlc->t1_active = true; in llc_shdlc_rcv_i_frame()
241 mod_timer(&shdlc->t1_timer, jiffies + in llc_shdlc_rcv_i_frame()
242 msecs_to_jiffies(SHDLC_T1_VALUE_MS(shdlc->w))); in llc_shdlc_rcv_i_frame()
247 shdlc->rcv_to_hci(shdlc->hdev, skb); in llc_shdlc_rcv_i_frame()
251 shdlc->nr = (shdlc->nr + 1) % 8; in llc_shdlc_rcv_i_frame()
253 if (llc_shdlc_x_lt_y_lteq_z(shdlc->dnr, y_nr, shdlc->ns)) { in llc_shdlc_rcv_i_frame()
254 llc_shdlc_reset_t2(shdlc, y_nr); in llc_shdlc_rcv_i_frame()
256 shdlc->dnr = y_nr; in llc_shdlc_rcv_i_frame()
263 static void llc_shdlc_rcv_ack(struct llc_shdlc *shdlc, int y_nr) in llc_shdlc_rcv_ack() argument
267 if (llc_shdlc_x_lt_y_lteq_z(shdlc->dnr, y_nr, shdlc->ns)) { in llc_shdlc_rcv_ack()
268 llc_shdlc_reset_t2(shdlc, y_nr); in llc_shdlc_rcv_ack()
269 shdlc->dnr = y_nr; in llc_shdlc_rcv_ack()
273 static void llc_shdlc_requeue_ack_pending(struct llc_shdlc *shdlc) in llc_shdlc_requeue_ack_pending() argument
277 pr_debug("ns reset to %d\n", shdlc->dnr); in llc_shdlc_requeue_ack_pending()
279 while ((skb = skb_dequeue_tail(&shdlc->ack_pending_q))) { in llc_shdlc_requeue_ack_pending()
281 skb_queue_head(&shdlc->send_q, skb); in llc_shdlc_requeue_ack_pending()
283 shdlc->ns = shdlc->dnr; in llc_shdlc_requeue_ack_pending()
286 static void llc_shdlc_rcv_rej(struct llc_shdlc *shdlc, int y_nr) in llc_shdlc_rcv_rej() argument
292 if (llc_shdlc_x_lteq_y_lt_z(shdlc->dnr, y_nr, shdlc->ns)) { in llc_shdlc_rcv_rej()
293 if (shdlc->t2_active) { in llc_shdlc_rcv_rej()
294 del_timer_sync(&shdlc->t2_timer); in llc_shdlc_rcv_rej()
295 shdlc->t2_active = false; in llc_shdlc_rcv_rej()
299 if (shdlc->dnr != y_nr) { in llc_shdlc_rcv_rej()
300 while ((shdlc->dnr = ((shdlc->dnr + 1) % 8)) != y_nr) { in llc_shdlc_rcv_rej()
301 skb = skb_dequeue(&shdlc->ack_pending_q); in llc_shdlc_rcv_rej()
306 llc_shdlc_requeue_ack_pending(shdlc); in llc_shdlc_rcv_rej()
311 static void llc_shdlc_rcv_s_frame(struct llc_shdlc *shdlc, in llc_shdlc_rcv_s_frame() argument
316 if (shdlc->state != SHDLC_CONNECTED) in llc_shdlc_rcv_s_frame()
321 llc_shdlc_rcv_ack(shdlc, nr); in llc_shdlc_rcv_s_frame()
322 if (shdlc->rnr == true) { /* see SHDLC 10.7.7 */ in llc_shdlc_rcv_s_frame()
323 shdlc->rnr = false; in llc_shdlc_rcv_s_frame()
324 if (shdlc->send_q.qlen == 0) { in llc_shdlc_rcv_s_frame()
325 skb = llc_shdlc_alloc_skb(shdlc, 0); in llc_shdlc_rcv_s_frame()
327 skb_queue_tail(&shdlc->send_q, skb); in llc_shdlc_rcv_s_frame()
332 llc_shdlc_rcv_rej(shdlc, nr); in llc_shdlc_rcv_s_frame()
335 llc_shdlc_rcv_ack(shdlc, nr); in llc_shdlc_rcv_s_frame()
336 shdlc->rnr = true; in llc_shdlc_rcv_s_frame()
343 static void llc_shdlc_connect_complete(struct llc_shdlc *shdlc, int r) in llc_shdlc_connect_complete() argument
347 del_timer_sync(&shdlc->connect_timer); in llc_shdlc_connect_complete()
350 shdlc->ns = 0; in llc_shdlc_connect_complete()
351 shdlc->nr = 0; in llc_shdlc_connect_complete()
352 shdlc->dnr = 0; in llc_shdlc_connect_complete()
354 shdlc->state = SHDLC_HALF_CONNECTED; in llc_shdlc_connect_complete()
356 shdlc->state = SHDLC_DISCONNECTED; in llc_shdlc_connect_complete()
359 shdlc->connect_result = r; in llc_shdlc_connect_complete()
361 wake_up(shdlc->connect_wq); in llc_shdlc_connect_complete()
364 static int llc_shdlc_connect_initiate(const struct llc_shdlc *shdlc) in llc_shdlc_connect_initiate() argument
370 skb = llc_shdlc_alloc_skb(shdlc, 2); in llc_shdlc_connect_initiate()
377 return llc_shdlc_send_u_frame(shdlc, skb, U_FRAME_RSET); in llc_shdlc_connect_initiate()
380 static int llc_shdlc_connect_send_ua(const struct llc_shdlc *shdlc) in llc_shdlc_connect_send_ua() argument
386 skb = llc_shdlc_alloc_skb(shdlc, 0); in llc_shdlc_connect_send_ua()
390 return llc_shdlc_send_u_frame(shdlc, skb, U_FRAME_UA); in llc_shdlc_connect_send_ua()
393 static void llc_shdlc_rcv_u_frame(struct llc_shdlc *shdlc, in llc_shdlc_rcv_u_frame() argument
405 switch (shdlc->state) { in llc_shdlc_rcv_u_frame()
421 shdlc->w = w; in llc_shdlc_rcv_u_frame()
422 shdlc->srej_support = srej_support; in llc_shdlc_rcv_u_frame()
423 r = llc_shdlc_connect_send_ua(shdlc); in llc_shdlc_rcv_u_frame()
424 llc_shdlc_connect_complete(shdlc, r); in llc_shdlc_rcv_u_frame()
438 shdlc->hard_fault = -ECONNRESET; in llc_shdlc_rcv_u_frame()
445 if ((shdlc->state == SHDLC_CONNECTING && in llc_shdlc_rcv_u_frame()
446 shdlc->connect_tries > 0) || in llc_shdlc_rcv_u_frame()
447 (shdlc->state == SHDLC_NEGOTIATING)) { in llc_shdlc_rcv_u_frame()
448 llc_shdlc_connect_complete(shdlc, 0); in llc_shdlc_rcv_u_frame()
449 shdlc->state = SHDLC_CONNECTED; in llc_shdlc_rcv_u_frame()
459 static void llc_shdlc_handle_rcv_queue(struct llc_shdlc *shdlc) in llc_shdlc_handle_rcv_queue() argument
468 if (shdlc->rcv_q.qlen) in llc_shdlc_handle_rcv_queue()
469 pr_debug("rcvQlen=%d\n", shdlc->rcv_q.qlen); in llc_shdlc_handle_rcv_queue()
471 while ((skb = skb_dequeue(&shdlc->rcv_q)) != NULL) { in llc_shdlc_handle_rcv_queue()
477 if (shdlc->state == SHDLC_HALF_CONNECTED) in llc_shdlc_handle_rcv_queue()
478 shdlc->state = SHDLC_CONNECTED; in llc_shdlc_handle_rcv_queue()
482 llc_shdlc_rcv_i_frame(shdlc, skb, ns, nr); in llc_shdlc_handle_rcv_queue()
485 if (shdlc->state == SHDLC_HALF_CONNECTED) in llc_shdlc_handle_rcv_queue()
486 shdlc->state = SHDLC_CONNECTED; in llc_shdlc_handle_rcv_queue()
490 llc_shdlc_rcv_s_frame(shdlc, s_frame_type, nr); in llc_shdlc_handle_rcv_queue()
495 llc_shdlc_rcv_u_frame(shdlc, skb, u_frame_modifier); in llc_shdlc_handle_rcv_queue()
518 static void llc_shdlc_handle_send_queue(struct llc_shdlc *shdlc) in llc_shdlc_handle_send_queue() argument
524 if (shdlc->send_q.qlen) in llc_shdlc_handle_send_queue()
527 shdlc->send_q.qlen, shdlc->ns, shdlc->dnr, in llc_shdlc_handle_send_queue()
528 shdlc->rnr == false ? "false" : "true", in llc_shdlc_handle_send_queue()
529 shdlc->w - llc_shdlc_w_used(shdlc->ns, shdlc->dnr), in llc_shdlc_handle_send_queue()
530 shdlc->ack_pending_q.qlen); in llc_shdlc_handle_send_queue()
532 while (shdlc->send_q.qlen && shdlc->ack_pending_q.qlen < shdlc->w && in llc_shdlc_handle_send_queue()
533 (shdlc->rnr == false)) { in llc_shdlc_handle_send_queue()
535 if (shdlc->t1_active) { in llc_shdlc_handle_send_queue()
536 del_timer_sync(&shdlc->t1_timer); in llc_shdlc_handle_send_queue()
537 shdlc->t1_active = false; in llc_shdlc_handle_send_queue()
541 skb = skb_dequeue(&shdlc->send_q); in llc_shdlc_handle_send_queue()
543 *(u8 *)skb_push(skb, 1) = SHDLC_CONTROL_HEAD_I | (shdlc->ns << 3) | in llc_shdlc_handle_send_queue()
544 shdlc->nr; in llc_shdlc_handle_send_queue()
546 pr_debug("Sending I-Frame %d, waiting to rcv %d\n", shdlc->ns, in llc_shdlc_handle_send_queue()
547 shdlc->nr); in llc_shdlc_handle_send_queue()
550 r = shdlc->xmit_to_drv(shdlc->hdev, skb); in llc_shdlc_handle_send_queue()
552 shdlc->hard_fault = r; in llc_shdlc_handle_send_queue()
556 shdlc->ns = (shdlc->ns + 1) % 8; in llc_shdlc_handle_send_queue()
561 skb_queue_tail(&shdlc->ack_pending_q, skb); in llc_shdlc_handle_send_queue()
563 if (shdlc->t2_active == false) { in llc_shdlc_handle_send_queue()
564 shdlc->t2_active = true; in llc_shdlc_handle_send_queue()
565 mod_timer(&shdlc->t2_timer, time_sent + in llc_shdlc_handle_send_queue()
574 struct llc_shdlc *shdlc = from_timer(shdlc, t, connect_timer); in llc_shdlc_connect_timeout() local
578 schedule_work(&shdlc->sm_work); in llc_shdlc_connect_timeout()
583 struct llc_shdlc *shdlc = from_timer(shdlc, t, t1_timer); in llc_shdlc_t1_timeout() local
587 schedule_work(&shdlc->sm_work); in llc_shdlc_t1_timeout()
592 struct llc_shdlc *shdlc = from_timer(shdlc, t, t2_timer); in llc_shdlc_t2_timeout() local
596 schedule_work(&shdlc->sm_work); in llc_shdlc_t2_timeout()
601 struct llc_shdlc *shdlc = container_of(work, struct llc_shdlc, sm_work); in llc_shdlc_sm_work() local
606 mutex_lock(&shdlc->state_mutex); in llc_shdlc_sm_work()
608 switch (shdlc->state) { in llc_shdlc_sm_work()
610 skb_queue_purge(&shdlc->rcv_q); in llc_shdlc_sm_work()
611 skb_queue_purge(&shdlc->send_q); in llc_shdlc_sm_work()
612 skb_queue_purge(&shdlc->ack_pending_q); in llc_shdlc_sm_work()
615 if (shdlc->hard_fault) { in llc_shdlc_sm_work()
616 llc_shdlc_connect_complete(shdlc, shdlc->hard_fault); in llc_shdlc_sm_work()
620 if (shdlc->connect_tries++ < 5) in llc_shdlc_sm_work()
621 r = llc_shdlc_connect_initiate(shdlc); in llc_shdlc_sm_work()
625 llc_shdlc_connect_complete(shdlc, r); in llc_shdlc_sm_work()
627 mod_timer(&shdlc->connect_timer, jiffies + in llc_shdlc_sm_work()
630 shdlc->state = SHDLC_NEGOTIATING; in llc_shdlc_sm_work()
634 if (timer_pending(&shdlc->connect_timer) == 0) { in llc_shdlc_sm_work()
635 shdlc->state = SHDLC_CONNECTING; in llc_shdlc_sm_work()
636 schedule_work(&shdlc->sm_work); in llc_shdlc_sm_work()
639 llc_shdlc_handle_rcv_queue(shdlc); in llc_shdlc_sm_work()
641 if (shdlc->hard_fault) { in llc_shdlc_sm_work()
642 llc_shdlc_connect_complete(shdlc, shdlc->hard_fault); in llc_shdlc_sm_work()
648 llc_shdlc_handle_rcv_queue(shdlc); in llc_shdlc_sm_work()
649 llc_shdlc_handle_send_queue(shdlc); in llc_shdlc_sm_work()
651 if (shdlc->t1_active && timer_pending(&shdlc->t1_timer) == 0) { in llc_shdlc_sm_work()
655 shdlc->t1_active = false; in llc_shdlc_sm_work()
656 r = llc_shdlc_send_s_frame(shdlc, S_FRAME_RR, in llc_shdlc_sm_work()
657 shdlc->nr); in llc_shdlc_sm_work()
659 shdlc->hard_fault = r; in llc_shdlc_sm_work()
662 if (shdlc->t2_active && timer_pending(&shdlc->t2_timer) == 0) { in llc_shdlc_sm_work()
666 shdlc->t2_active = false; in llc_shdlc_sm_work()
668 llc_shdlc_requeue_ack_pending(shdlc); in llc_shdlc_sm_work()
669 llc_shdlc_handle_send_queue(shdlc); in llc_shdlc_sm_work()
672 if (shdlc->hard_fault) in llc_shdlc_sm_work()
673 shdlc->llc_failure(shdlc->hdev, shdlc->hard_fault); in llc_shdlc_sm_work()
678 mutex_unlock(&shdlc->state_mutex); in llc_shdlc_sm_work()
685 static int llc_shdlc_connect(struct llc_shdlc *shdlc) in llc_shdlc_connect() argument
691 mutex_lock(&shdlc->state_mutex); in llc_shdlc_connect()
693 shdlc->state = SHDLC_CONNECTING; in llc_shdlc_connect()
694 shdlc->connect_wq = &connect_wq; in llc_shdlc_connect()
695 shdlc->connect_tries = 0; in llc_shdlc_connect()
696 shdlc->connect_result = 1; in llc_shdlc_connect()
698 mutex_unlock(&shdlc->state_mutex); in llc_shdlc_connect()
700 schedule_work(&shdlc->sm_work); in llc_shdlc_connect()
702 wait_event(connect_wq, shdlc->connect_result != 1); in llc_shdlc_connect()
704 return shdlc->connect_result; in llc_shdlc_connect()
707 static void llc_shdlc_disconnect(struct llc_shdlc *shdlc) in llc_shdlc_disconnect() argument
711 mutex_lock(&shdlc->state_mutex); in llc_shdlc_disconnect()
713 shdlc->state = SHDLC_DISCONNECTED; in llc_shdlc_disconnect()
715 mutex_unlock(&shdlc->state_mutex); in llc_shdlc_disconnect()
717 schedule_work(&shdlc->sm_work); in llc_shdlc_disconnect()
725 static void llc_shdlc_recv_frame(struct llc_shdlc *shdlc, struct sk_buff *skb) in llc_shdlc_recv_frame() argument
729 shdlc->hard_fault = -EREMOTEIO; in llc_shdlc_recv_frame()
732 skb_queue_tail(&shdlc->rcv_q, skb); in llc_shdlc_recv_frame()
735 schedule_work(&shdlc->sm_work); in llc_shdlc_recv_frame()
743 struct llc_shdlc *shdlc; in llc_shdlc_init() local
748 shdlc = kzalloc(sizeof(struct llc_shdlc), GFP_KERNEL); in llc_shdlc_init()
749 if (shdlc == NULL) in llc_shdlc_init()
752 mutex_init(&shdlc->state_mutex); in llc_shdlc_init()
753 shdlc->state = SHDLC_DISCONNECTED; in llc_shdlc_init()
755 timer_setup(&shdlc->connect_timer, llc_shdlc_connect_timeout, 0); in llc_shdlc_init()
756 timer_setup(&shdlc->t1_timer, llc_shdlc_t1_timeout, 0); in llc_shdlc_init()
757 timer_setup(&shdlc->t2_timer, llc_shdlc_t2_timeout, 0); in llc_shdlc_init()
759 shdlc->w = SHDLC_MAX_WINDOW; in llc_shdlc_init()
760 shdlc->srej_support = SHDLC_SREJ_SUPPORT; in llc_shdlc_init()
762 skb_queue_head_init(&shdlc->rcv_q); in llc_shdlc_init()
763 skb_queue_head_init(&shdlc->send_q); in llc_shdlc_init()
764 skb_queue_head_init(&shdlc->ack_pending_q); in llc_shdlc_init()
766 INIT_WORK(&shdlc->sm_work, llc_shdlc_sm_work); in llc_shdlc_init()
768 shdlc->hdev = hdev; in llc_shdlc_init()
769 shdlc->xmit_to_drv = xmit_to_drv; in llc_shdlc_init()
770 shdlc->rcv_to_hci = rcv_to_hci; in llc_shdlc_init()
771 shdlc->tx_headroom = tx_headroom; in llc_shdlc_init()
772 shdlc->tx_tailroom = tx_tailroom; in llc_shdlc_init()
773 shdlc->llc_failure = llc_failure; in llc_shdlc_init()
775 return shdlc; in llc_shdlc_init()
780 struct llc_shdlc *shdlc = nfc_llc_get_data(llc); in llc_shdlc_deinit() local
782 skb_queue_purge(&shdlc->rcv_q); in llc_shdlc_deinit()
783 skb_queue_purge(&shdlc->send_q); in llc_shdlc_deinit()
784 skb_queue_purge(&shdlc->ack_pending_q); in llc_shdlc_deinit()
786 kfree(shdlc); in llc_shdlc_deinit()
791 struct llc_shdlc *shdlc = nfc_llc_get_data(llc); in llc_shdlc_start() local
793 return llc_shdlc_connect(shdlc); in llc_shdlc_start()
798 struct llc_shdlc *shdlc = nfc_llc_get_data(llc); in llc_shdlc_stop() local
800 llc_shdlc_disconnect(shdlc); in llc_shdlc_stop()
807 struct llc_shdlc *shdlc = nfc_llc_get_data(llc); in llc_shdlc_rcv_from_drv() local
809 llc_shdlc_recv_frame(shdlc, skb); in llc_shdlc_rcv_from_drv()
814 struct llc_shdlc *shdlc = nfc_llc_get_data(llc); in llc_shdlc_xmit_from_hci() local
816 skb_queue_tail(&shdlc->send_q, skb); in llc_shdlc_xmit_from_hci()
818 schedule_work(&shdlc->sm_work); in llc_shdlc_xmit_from_hci()