diff options
author | Samuel Ortiz <sameo@linux.intel.com> | 2012-05-04 11:04:19 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-06-04 15:34:28 -0400 |
commit | a69f32af86e389dd232b1bb2269e202c1bfcc60f (patch) | |
tree | 8639421ba70c67ac09f72323a4e5dca2b71e37e7 /net | |
parent | c7aa12252f5142b9eee2f6e34ca8870a8e7e048c (diff) |
NFC: Socket linked list
Simplify the LLCP sockets structure by putting all the connected ones
into a single linked list.
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/nfc/llcp/llcp.c | 249 | ||||
-rw-r--r-- | net/nfc/llcp/llcp.h | 12 | ||||
-rw-r--r-- | net/nfc/llcp/sock.c | 32 |
3 files changed, 158 insertions, 135 deletions
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index 0f6dd3a53dca..262aa827fd7f 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c | |||
@@ -31,45 +31,41 @@ static u8 llcp_magic[3] = {0x46, 0x66, 0x6d}; | |||
31 | 31 | ||
32 | static struct list_head llcp_devices; | 32 | static struct list_head llcp_devices; |
33 | 33 | ||
34 | static void nfc_llcp_socket_release(struct nfc_llcp_local *local) | 34 | void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *sk) |
35 | { | 35 | { |
36 | struct nfc_llcp_sock *parent, *s, *n; | 36 | write_lock(&l->lock); |
37 | struct sock *sk, *parent_sk; | 37 | sk_add_node(sk, &l->head); |
38 | int i; | 38 | write_unlock(&l->lock); |
39 | 39 | } | |
40 | mutex_lock(&local->socket_lock); | ||
41 | |||
42 | for (i = 0; i < LLCP_MAX_SAP; i++) { | ||
43 | parent = local->sockets[i]; | ||
44 | if (parent == NULL) | ||
45 | continue; | ||
46 | |||
47 | /* Release all child sockets */ | ||
48 | list_for_each_entry_safe(s, n, &parent->list, list) { | ||
49 | list_del_init(&s->list); | ||
50 | sk = &s->sk; | ||
51 | |||
52 | lock_sock(sk); | ||
53 | 40 | ||
54 | if (sk->sk_state == LLCP_CONNECTED) | 41 | void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *sk) |
55 | nfc_put_device(s->dev); | 42 | { |
43 | write_lock(&l->lock); | ||
44 | sk_del_node_init(sk); | ||
45 | write_unlock(&l->lock); | ||
46 | } | ||
56 | 47 | ||
57 | sk->sk_state = LLCP_CLOSED; | 48 | static void nfc_llcp_socket_release(struct nfc_llcp_local *local) |
49 | { | ||
50 | struct sock *sk; | ||
51 | struct hlist_node *node, *tmp; | ||
52 | struct nfc_llcp_sock *llcp_sock; | ||
58 | 53 | ||
59 | release_sock(sk); | 54 | write_lock(&local->sockets.lock); |
60 | 55 | ||
61 | sock_orphan(sk); | 56 | sk_for_each_safe(sk, node, tmp, &local->sockets.head) { |
62 | } | 57 | llcp_sock = nfc_llcp_sock(sk); |
63 | 58 | ||
64 | parent_sk = &parent->sk; | 59 | lock_sock(sk); |
65 | 60 | ||
66 | lock_sock(parent_sk); | 61 | if (sk->sk_state == LLCP_CONNECTED) |
62 | nfc_put_device(llcp_sock->dev); | ||
67 | 63 | ||
68 | if (parent_sk->sk_state == LLCP_LISTEN) { | 64 | if (sk->sk_state == LLCP_LISTEN) { |
69 | struct nfc_llcp_sock *lsk, *n; | 65 | struct nfc_llcp_sock *lsk, *n; |
70 | struct sock *accept_sk; | 66 | struct sock *accept_sk; |
71 | 67 | ||
72 | list_for_each_entry_safe(lsk, n, &parent->accept_queue, | 68 | list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue, |
73 | accept_queue) { | 69 | accept_queue) { |
74 | accept_sk = &lsk->sk; | 70 | accept_sk = &lsk->sk; |
75 | lock_sock(accept_sk); | 71 | lock_sock(accept_sk); |
@@ -84,17 +80,16 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local) | |||
84 | } | 80 | } |
85 | } | 81 | } |
86 | 82 | ||
87 | if (parent_sk->sk_state == LLCP_CONNECTED) | 83 | sk->sk_state = LLCP_CLOSED; |
88 | nfc_put_device(parent->dev); | ||
89 | 84 | ||
90 | parent_sk->sk_state = LLCP_CLOSED; | 85 | release_sock(sk); |
91 | 86 | ||
92 | release_sock(parent_sk); | 87 | sock_orphan(sk); |
93 | 88 | ||
94 | sock_orphan(parent_sk); | 89 | sk_del_node_init(sk); |
95 | } | 90 | } |
96 | 91 | ||
97 | mutex_unlock(&local->socket_lock); | 92 | write_unlock(&local->sockets.lock); |
98 | } | 93 | } |
99 | 94 | ||
100 | struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) | 95 | struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) |
@@ -122,6 +117,11 @@ static void local_release(struct kref *ref) | |||
122 | 117 | ||
123 | int nfc_llcp_local_put(struct nfc_llcp_local *local) | 118 | int nfc_llcp_local_put(struct nfc_llcp_local *local) |
124 | { | 119 | { |
120 | WARN_ON(local == NULL); | ||
121 | |||
122 | if (local == NULL) | ||
123 | return 0; | ||
124 | |||
125 | return kref_put(&local->ref, local_release); | 125 | return kref_put(&local->ref, local_release); |
126 | } | 126 | } |
127 | 127 | ||
@@ -465,46 +465,107 @@ static void nfc_llcp_set_nrns(struct nfc_llcp_sock *sock, struct sk_buff *pdu) | |||
465 | sock->recv_ack_n = (sock->recv_n - 1) % 16; | 465 | sock->recv_ack_n = (sock->recv_n - 1) % 16; |
466 | } | 466 | } |
467 | 467 | ||
468 | static struct nfc_llcp_sock *nfc_llcp_connecting_sock_get(struct nfc_llcp_local *local, | ||
469 | u8 ssap) | ||
470 | { | ||
471 | struct sock *sk; | ||
472 | struct nfc_llcp_sock *llcp_sock; | ||
473 | struct hlist_node *node; | ||
474 | |||
475 | read_lock(&local->connecting_sockets.lock); | ||
476 | |||
477 | sk_for_each(sk, node, &local->connecting_sockets.head) { | ||
478 | llcp_sock = nfc_llcp_sock(sk); | ||
479 | |||
480 | if (llcp_sock->ssap == ssap) | ||
481 | goto out; | ||
482 | } | ||
483 | |||
484 | llcp_sock = NULL; | ||
485 | |||
486 | out: | ||
487 | read_unlock(&local->connecting_sockets.lock); | ||
488 | |||
489 | sock_hold(&llcp_sock->sk); | ||
490 | |||
491 | return llcp_sock; | ||
492 | } | ||
493 | |||
468 | static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, | 494 | static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, |
469 | u8 ssap, u8 dsap) | 495 | u8 ssap, u8 dsap) |
470 | { | 496 | { |
471 | struct nfc_llcp_sock *sock, *llcp_sock, *n; | 497 | struct sock *sk; |
498 | struct hlist_node *node; | ||
499 | struct nfc_llcp_sock *llcp_sock; | ||
472 | 500 | ||
473 | pr_debug("ssap dsap %d %d\n", ssap, dsap); | 501 | pr_debug("ssap dsap %d %d\n", ssap, dsap); |
474 | 502 | ||
475 | if (ssap == 0 && dsap == 0) | 503 | if (ssap == 0 && dsap == 0) |
476 | return NULL; | 504 | return NULL; |
477 | 505 | ||
478 | mutex_lock(&local->socket_lock); | 506 | read_lock(&local->sockets.lock); |
479 | sock = local->sockets[ssap]; | 507 | |
480 | if (sock == NULL) { | 508 | llcp_sock = NULL; |
481 | mutex_unlock(&local->socket_lock); | ||
482 | return NULL; | ||
483 | } | ||
484 | 509 | ||
485 | pr_debug("root dsap %d (%d)\n", sock->dsap, dsap); | 510 | sk_for_each(sk, node, &local->sockets.head) { |
511 | llcp_sock = nfc_llcp_sock(sk); | ||
486 | 512 | ||
487 | if (sock->dsap == dsap) { | 513 | if (llcp_sock->ssap == ssap && |
488 | sock_hold(&sock->sk); | 514 | llcp_sock->dsap == dsap) |
489 | mutex_unlock(&local->socket_lock); | 515 | break; |
490 | return sock; | ||
491 | } | 516 | } |
492 | 517 | ||
493 | list_for_each_entry_safe(llcp_sock, n, &sock->list, list) { | 518 | read_unlock(&local->sockets.lock); |
494 | pr_debug("llcp_sock %p sk %p dsap %d\n", llcp_sock, | 519 | |
495 | &llcp_sock->sk, llcp_sock->dsap); | 520 | if (llcp_sock == NULL) |
496 | if (llcp_sock->dsap == dsap) { | 521 | return NULL; |
497 | sock_hold(&llcp_sock->sk); | 522 | |
498 | mutex_unlock(&local->socket_lock); | 523 | sock_hold(&llcp_sock->sk); |
499 | return llcp_sock; | 524 | |
500 | } | 525 | return llcp_sock; |
526 | } | ||
527 | |||
528 | static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local, | ||
529 | u8 *sn, size_t sn_len) | ||
530 | { | ||
531 | struct sock *sk; | ||
532 | struct hlist_node *node; | ||
533 | struct nfc_llcp_sock *llcp_sock; | ||
534 | |||
535 | pr_debug("sn %zd\n", sn_len); | ||
536 | |||
537 | if (sn == NULL || sn_len == 0) | ||
538 | return NULL; | ||
539 | |||
540 | read_lock(&local->sockets.lock); | ||
541 | |||
542 | llcp_sock = NULL; | ||
543 | |||
544 | sk_for_each(sk, node, &local->sockets.head) { | ||
545 | llcp_sock = nfc_llcp_sock(sk); | ||
546 | |||
547 | if (llcp_sock->sk.sk_state != LLCP_LISTEN) | ||
548 | continue; | ||
549 | |||
550 | if (llcp_sock->service_name == NULL || | ||
551 | llcp_sock->service_name_len == 0) | ||
552 | continue; | ||
553 | |||
554 | if (llcp_sock->service_name_len != sn_len) | ||
555 | continue; | ||
556 | |||
557 | if (memcmp(sn, llcp_sock->service_name, sn_len) == 0) | ||
558 | break; | ||
501 | } | 559 | } |
502 | 560 | ||
503 | pr_err("Could not find socket for %d %d\n", ssap, dsap); | 561 | read_unlock(&local->sockets.lock); |
504 | 562 | ||
505 | mutex_unlock(&local->socket_lock); | 563 | if (llcp_sock == NULL) |
564 | return NULL; | ||
506 | 565 | ||
507 | return NULL; | 566 | sock_hold(&llcp_sock->sk); |
567 | |||
568 | return llcp_sock; | ||
508 | } | 569 | } |
509 | 570 | ||
510 | static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock) | 571 | static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock) |
@@ -540,7 +601,7 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | |||
540 | { | 601 | { |
541 | struct sock *new_sk, *parent; | 602 | struct sock *new_sk, *parent; |
542 | struct nfc_llcp_sock *sock, *new_sock; | 603 | struct nfc_llcp_sock *sock, *new_sock; |
543 | u8 dsap, ssap, bound_sap, reason; | 604 | u8 dsap, ssap, reason; |
544 | 605 | ||
545 | dsap = nfc_llcp_dsap(skb); | 606 | dsap = nfc_llcp_dsap(skb); |
546 | ssap = nfc_llcp_ssap(skb); | 607 | ssap = nfc_llcp_ssap(skb); |
@@ -551,24 +612,11 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | |||
551 | skb->len - LLCP_HEADER_SIZE); | 612 | skb->len - LLCP_HEADER_SIZE); |
552 | 613 | ||
553 | if (dsap != LLCP_SAP_SDP) { | 614 | if (dsap != LLCP_SAP_SDP) { |
554 | bound_sap = dsap; | 615 | sock = nfc_llcp_sock_get(local, dsap, LLCP_SAP_SDP); |
555 | 616 | if (sock == NULL || sock->sk.sk_state != LLCP_LISTEN) { | |
556 | mutex_lock(&local->socket_lock); | ||
557 | sock = local->sockets[dsap]; | ||
558 | if (sock == NULL) { | ||
559 | mutex_unlock(&local->socket_lock); | ||
560 | reason = LLCP_DM_NOBOUND; | 617 | reason = LLCP_DM_NOBOUND; |
561 | goto fail; | 618 | goto fail; |
562 | } | 619 | } |
563 | |||
564 | sock_hold(&sock->sk); | ||
565 | mutex_unlock(&local->socket_lock); | ||
566 | |||
567 | lock_sock(&sock->sk); | ||
568 | |||
569 | if (sock->dsap == LLCP_SAP_SDP && | ||
570 | sock->sk.sk_state == LLCP_LISTEN) | ||
571 | goto enqueue; | ||
572 | } else { | 620 | } else { |
573 | u8 *sn; | 621 | u8 *sn; |
574 | size_t sn_len; | 622 | size_t sn_len; |
@@ -581,40 +629,15 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | |||
581 | 629 | ||
582 | pr_debug("Service name length %zu\n", sn_len); | 630 | pr_debug("Service name length %zu\n", sn_len); |
583 | 631 | ||
584 | mutex_lock(&local->socket_lock); | 632 | sock = nfc_llcp_sock_get_sn(local, sn, sn_len); |
585 | for (bound_sap = 0; bound_sap < LLCP_LOCAL_SAP_OFFSET; | 633 | if (sock == NULL) { |
586 | bound_sap++) { | 634 | reason = LLCP_DM_NOBOUND; |
587 | sock = local->sockets[bound_sap]; | 635 | goto fail; |
588 | if (sock == NULL) | ||
589 | continue; | ||
590 | |||
591 | if (sock->service_name == NULL || | ||
592 | sock->service_name_len == 0) | ||
593 | continue; | ||
594 | |||
595 | if (sock->service_name_len != sn_len) | ||
596 | continue; | ||
597 | |||
598 | if (sock->dsap == LLCP_SAP_SDP && | ||
599 | sock->sk.sk_state == LLCP_LISTEN && | ||
600 | !memcmp(sn, sock->service_name, sn_len)) { | ||
601 | pr_debug("Found service name at SAP %d\n", | ||
602 | bound_sap); | ||
603 | sock_hold(&sock->sk); | ||
604 | mutex_unlock(&local->socket_lock); | ||
605 | |||
606 | lock_sock(&sock->sk); | ||
607 | |||
608 | goto enqueue; | ||
609 | } | ||
610 | } | 636 | } |
611 | mutex_unlock(&local->socket_lock); | ||
612 | } | 637 | } |
613 | 638 | ||
614 | reason = LLCP_DM_NOBOUND; | 639 | lock_sock(&sock->sk); |
615 | goto fail; | ||
616 | 640 | ||
617 | enqueue: | ||
618 | parent = &sock->sk; | 641 | parent = &sock->sk; |
619 | 642 | ||
620 | if (sk_acceptq_is_full(parent)) { | 643 | if (sk_acceptq_is_full(parent)) { |
@@ -636,13 +659,13 @@ enqueue: | |||
636 | new_sock->dev = local->dev; | 659 | new_sock->dev = local->dev; |
637 | new_sock->local = nfc_llcp_local_get(local); | 660 | new_sock->local = nfc_llcp_local_get(local); |
638 | new_sock->nfc_protocol = sock->nfc_protocol; | 661 | new_sock->nfc_protocol = sock->nfc_protocol; |
639 | new_sock->ssap = bound_sap; | 662 | new_sock->ssap = sock->ssap; |
640 | new_sock->dsap = ssap; | 663 | new_sock->dsap = ssap; |
641 | new_sock->parent = parent; | 664 | new_sock->parent = parent; |
642 | 665 | ||
643 | pr_debug("new sock %p sk %p\n", new_sock, &new_sock->sk); | 666 | pr_debug("new sock %p sk %p\n", new_sock, &new_sock->sk); |
644 | 667 | ||
645 | list_add_tail(&new_sock->list, &sock->list); | 668 | nfc_llcp_sock_link(&local->sockets, new_sk); |
646 | 669 | ||
647 | nfc_llcp_accept_enqueue(&sock->sk, new_sk); | 670 | nfc_llcp_accept_enqueue(&sock->sk, new_sk); |
648 | 671 | ||
@@ -813,11 +836,7 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb) | |||
813 | dsap = nfc_llcp_dsap(skb); | 836 | dsap = nfc_llcp_dsap(skb); |
814 | ssap = nfc_llcp_ssap(skb); | 837 | ssap = nfc_llcp_ssap(skb); |
815 | 838 | ||
816 | llcp_sock = nfc_llcp_sock_get(local, dsap, ssap); | 839 | llcp_sock = nfc_llcp_connecting_sock_get(local, dsap); |
817 | |||
818 | if (llcp_sock == NULL) | ||
819 | llcp_sock = nfc_llcp_sock_get(local, dsap, LLCP_SAP_SDP); | ||
820 | |||
821 | if (llcp_sock == NULL) { | 840 | if (llcp_sock == NULL) { |
822 | pr_err("Invalid CC\n"); | 841 | pr_err("Invalid CC\n"); |
823 | nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN); | 842 | nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN); |
@@ -825,9 +844,13 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb) | |||
825 | return; | 844 | return; |
826 | } | 845 | } |
827 | 846 | ||
828 | llcp_sock->dsap = ssap; | ||
829 | sk = &llcp_sock->sk; | 847 | sk = &llcp_sock->sk; |
830 | 848 | ||
849 | /* Unlink from connecting and link to the client array */ | ||
850 | nfc_llcp_sock_unlink(&local->connecting_sockets, sk); | ||
851 | nfc_llcp_sock_link(&local->sockets, sk); | ||
852 | llcp_sock->dsap = ssap; | ||
853 | |||
831 | nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE], | 854 | nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE], |
832 | skb->len - LLCP_HEADER_SIZE); | 855 | skb->len - LLCP_HEADER_SIZE); |
833 | 856 | ||
@@ -967,7 +990,6 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) | |||
967 | INIT_LIST_HEAD(&local->list); | 990 | INIT_LIST_HEAD(&local->list); |
968 | kref_init(&local->ref); | 991 | kref_init(&local->ref); |
969 | mutex_init(&local->sdp_lock); | 992 | mutex_init(&local->sdp_lock); |
970 | mutex_init(&local->socket_lock); | ||
971 | init_timer(&local->link_timer); | 993 | init_timer(&local->link_timer); |
972 | local->link_timer.data = (unsigned long) local; | 994 | local->link_timer.data = (unsigned long) local; |
973 | local->link_timer.function = nfc_llcp_symm_timer; | 995 | local->link_timer.function = nfc_llcp_symm_timer; |
@@ -1007,6 +1029,9 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) | |||
1007 | goto err_rx_wq; | 1029 | goto err_rx_wq; |
1008 | } | 1030 | } |
1009 | 1031 | ||
1032 | local->sockets.lock = __RW_LOCK_UNLOCKED(local->sockets.lock); | ||
1033 | local->connecting_sockets.lock = __RW_LOCK_UNLOCKED(local->connecting_sockets.lock); | ||
1034 | |||
1010 | nfc_llcp_build_gb(local); | 1035 | nfc_llcp_build_gb(local); |
1011 | 1036 | ||
1012 | local->remote_miu = LLCP_DEFAULT_MIU; | 1037 | local->remote_miu = LLCP_DEFAULT_MIU; |
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h index bc619553821b..705330470062 100644 --- a/net/nfc/llcp/llcp.h +++ b/net/nfc/llcp/llcp.h | |||
@@ -40,6 +40,11 @@ enum llcp_state { | |||
40 | 40 | ||
41 | struct nfc_llcp_sock; | 41 | struct nfc_llcp_sock; |
42 | 42 | ||
43 | struct llcp_sock_list { | ||
44 | struct hlist_head head; | ||
45 | rwlock_t lock; | ||
46 | }; | ||
47 | |||
43 | struct nfc_llcp_local { | 48 | struct nfc_llcp_local { |
44 | struct list_head list; | 49 | struct list_head list; |
45 | struct nfc_dev *dev; | 50 | struct nfc_dev *dev; |
@@ -47,7 +52,6 @@ struct nfc_llcp_local { | |||
47 | struct kref ref; | 52 | struct kref ref; |
48 | 53 | ||
49 | struct mutex sdp_lock; | 54 | struct mutex sdp_lock; |
50 | struct mutex socket_lock; | ||
51 | 55 | ||
52 | struct timer_list link_timer; | 56 | struct timer_list link_timer; |
53 | struct sk_buff_head tx_queue; | 57 | struct sk_buff_head tx_queue; |
@@ -82,12 +86,12 @@ struct nfc_llcp_local { | |||
82 | u8 remote_rw; | 86 | u8 remote_rw; |
83 | 87 | ||
84 | /* sockets array */ | 88 | /* sockets array */ |
85 | struct nfc_llcp_sock *sockets[LLCP_MAX_SAP]; | 89 | struct llcp_sock_list sockets; |
90 | struct llcp_sock_list connecting_sockets; | ||
86 | }; | 91 | }; |
87 | 92 | ||
88 | struct nfc_llcp_sock { | 93 | struct nfc_llcp_sock { |
89 | struct sock sk; | 94 | struct sock sk; |
90 | struct list_head list; | ||
91 | struct nfc_dev *dev; | 95 | struct nfc_dev *dev; |
92 | struct nfc_llcp_local *local; | 96 | struct nfc_llcp_local *local; |
93 | u32 target_idx; | 97 | u32 target_idx; |
@@ -166,6 +170,8 @@ struct nfc_llcp_sock { | |||
166 | #define LLCP_DM_REJ 0x03 | 170 | #define LLCP_DM_REJ 0x03 |
167 | 171 | ||
168 | 172 | ||
173 | void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *s); | ||
174 | void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *s); | ||
169 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); | 175 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); |
170 | struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local); | 176 | struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local); |
171 | int nfc_llcp_local_put(struct nfc_llcp_local *local); | 177 | int nfc_llcp_local_put(struct nfc_llcp_local *local); |
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index 9ac397b17718..8a60b53579b9 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c | |||
@@ -124,7 +124,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
124 | if (llcp_sock->ssap == LLCP_MAX_SAP) | 124 | if (llcp_sock->ssap == LLCP_MAX_SAP) |
125 | goto put_dev; | 125 | goto put_dev; |
126 | 126 | ||
127 | local->sockets[llcp_sock->ssap] = llcp_sock; | 127 | nfc_llcp_sock_link(&local->sockets, sk); |
128 | 128 | ||
129 | pr_debug("Socket bound to SAP %d\n", llcp_sock->ssap); | 129 | pr_debug("Socket bound to SAP %d\n", llcp_sock->ssap); |
130 | 130 | ||
@@ -379,15 +379,6 @@ static int llcp_sock_release(struct socket *sock) | |||
379 | goto out; | 379 | goto out; |
380 | } | 380 | } |
381 | 381 | ||
382 | mutex_lock(&local->socket_lock); | ||
383 | |||
384 | if (llcp_sock == local->sockets[llcp_sock->ssap]) | ||
385 | local->sockets[llcp_sock->ssap] = NULL; | ||
386 | else | ||
387 | list_del_init(&llcp_sock->list); | ||
388 | |||
389 | mutex_unlock(&local->socket_lock); | ||
390 | |||
391 | lock_sock(sk); | 382 | lock_sock(sk); |
392 | 383 | ||
393 | /* Send a DISC */ | 384 | /* Send a DISC */ |
@@ -412,14 +403,12 @@ static int llcp_sock_release(struct socket *sock) | |||
412 | } | 403 | } |
413 | } | 404 | } |
414 | 405 | ||
415 | /* Freeing the SAP */ | 406 | nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); |
416 | if ((sk->sk_state == LLCP_CONNECTED | ||
417 | && llcp_sock->ssap > LLCP_LOCAL_SAP_OFFSET) || | ||
418 | sk->sk_state == LLCP_BOUND || sk->sk_state == LLCP_LISTEN) | ||
419 | nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); | ||
420 | 407 | ||
421 | release_sock(sk); | 408 | release_sock(sk); |
422 | 409 | ||
410 | nfc_llcp_sock_unlink(&local->sockets, sk); | ||
411 | |||
423 | out: | 412 | out: |
424 | sock_orphan(sk); | 413 | sock_orphan(sk); |
425 | sock_put(sk); | 414 | sock_put(sk); |
@@ -505,21 +494,26 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, | |||
505 | llcp_sock->service_name_len, | 494 | llcp_sock->service_name_len, |
506 | GFP_KERNEL); | 495 | GFP_KERNEL); |
507 | 496 | ||
508 | local->sockets[llcp_sock->ssap] = llcp_sock; | 497 | nfc_llcp_sock_link(&local->connecting_sockets, sk); |
509 | 498 | ||
510 | ret = nfc_llcp_send_connect(llcp_sock); | 499 | ret = nfc_llcp_send_connect(llcp_sock); |
511 | if (ret) | 500 | if (ret) |
512 | goto put_dev; | 501 | goto sock_unlink; |
513 | 502 | ||
514 | ret = sock_wait_state(sk, LLCP_CONNECTED, | 503 | ret = sock_wait_state(sk, LLCP_CONNECTED, |
515 | sock_sndtimeo(sk, flags & O_NONBLOCK)); | 504 | sock_sndtimeo(sk, flags & O_NONBLOCK)); |
516 | if (ret) | 505 | if (ret) |
517 | goto put_dev; | 506 | goto sock_unlink; |
518 | 507 | ||
519 | release_sock(sk); | 508 | release_sock(sk); |
520 | 509 | ||
521 | return 0; | 510 | return 0; |
522 | 511 | ||
512 | sock_unlink: | ||
513 | nfc_llcp_put_ssap(local, llcp_sock->ssap); | ||
514 | |||
515 | nfc_llcp_sock_unlink(&local->connecting_sockets, sk); | ||
516 | |||
523 | put_dev: | 517 | put_dev: |
524 | nfc_put_device(dev); | 518 | nfc_put_device(dev); |
525 | 519 | ||
@@ -690,7 +684,6 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp) | |||
690 | skb_queue_head_init(&llcp_sock->tx_queue); | 684 | skb_queue_head_init(&llcp_sock->tx_queue); |
691 | skb_queue_head_init(&llcp_sock->tx_pending_queue); | 685 | skb_queue_head_init(&llcp_sock->tx_pending_queue); |
692 | skb_queue_head_init(&llcp_sock->tx_backlog_queue); | 686 | skb_queue_head_init(&llcp_sock->tx_backlog_queue); |
693 | INIT_LIST_HEAD(&llcp_sock->list); | ||
694 | INIT_LIST_HEAD(&llcp_sock->accept_queue); | 687 | INIT_LIST_HEAD(&llcp_sock->accept_queue); |
695 | 688 | ||
696 | if (sock != NULL) | 689 | if (sock != NULL) |
@@ -708,7 +701,6 @@ void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) | |||
708 | skb_queue_purge(&sock->tx_backlog_queue); | 701 | skb_queue_purge(&sock->tx_backlog_queue); |
709 | 702 | ||
710 | list_del_init(&sock->accept_queue); | 703 | list_del_init(&sock->accept_queue); |
711 | list_del_init(&sock->list); | ||
712 | 704 | ||
713 | sock->parent = NULL; | 705 | sock->parent = NULL; |
714 | 706 | ||