aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorGustavo F. Padovan <padovan@profusion.mobi>2011-04-27 17:26:32 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-05-05 12:47:45 -0400
commit23691d75cdc69c3b285211b4d77746aa20a17d18 (patch)
tree32aa0e3e59dce0226242659a83698bafd6c98fc5 /net/bluetooth
parent73b2ec18532f45e9028ce4c7bc8d7f8818eabd2a (diff)
Bluetooth: Remove l2cap_sk_list
A new list was added to replace the socket based one. This new list doesn't depent on sock and then fits better inside l2cap_core.c code. It also rename l2cap_chan_alloc() to l2cap_chan_create() and l2cap_chan_free() to l2cap_chan_destroy) Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/l2cap_core.c165
-rw-r--r--net/bluetooth/l2cap_sock.c6
2 files changed, 92 insertions, 79 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 9e3f64f05d49..d0769a83cb58 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -62,9 +62,8 @@ static u8 l2cap_fixed_chan[8] = { 0x02, };
62 62
63static struct workqueue_struct *_busy_wq; 63static struct workqueue_struct *_busy_wq;
64 64
65struct bt_sock_list l2cap_sk_list = { 65LIST_HEAD(chan_list);
66 .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) 66DEFINE_RWLOCK(chan_list_lock);
67};
68 67
69static void l2cap_busy_work(struct work_struct *work); 68static void l2cap_busy_work(struct work_struct *work);
70 69
@@ -135,29 +134,27 @@ static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn
135 return c; 134 return c;
136} 135}
137 136
138static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src) 137static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
139{ 138{
140 struct sock *sk; 139 struct l2cap_chan *c;
141 struct hlist_node *node;
142 sk_for_each(sk, node, &l2cap_sk_list.head) {
143 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
144 140
145 if (chan->sport == psm && !bacmp(&bt_sk(sk)->src, src)) 141 list_for_each_entry(c, &chan_list, global_l) {
142 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
146 goto found; 143 goto found;
147 } 144 }
148 145
149 sk = NULL; 146 c = NULL;
150found: 147found:
151 return sk; 148 return c;
152} 149}
153 150
154int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) 151int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
155{ 152{
156 int err; 153 int err;
157 154
158 write_lock_bh(&l2cap_sk_list.lock); 155 write_lock_bh(&chan_list_lock);
159 156
160 if (psm && __l2cap_get_sock_by_addr(psm, src)) { 157 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
161 err = -EADDRINUSE; 158 err = -EADDRINUSE;
162 goto done; 159 goto done;
163 } 160 }
@@ -171,7 +168,7 @@ int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
171 168
172 err = -EINVAL; 169 err = -EINVAL;
173 for (p = 0x1001; p < 0x1100; p += 2) 170 for (p = 0x1001; p < 0x1100; p += 2)
174 if (!__l2cap_get_sock_by_addr(cpu_to_le16(p), src)) { 171 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
175 chan->psm = cpu_to_le16(p); 172 chan->psm = cpu_to_le16(p);
176 chan->sport = cpu_to_le16(p); 173 chan->sport = cpu_to_le16(p);
177 err = 0; 174 err = 0;
@@ -180,17 +177,17 @@ int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
180 } 177 }
181 178
182done: 179done:
183 write_unlock_bh(&l2cap_sk_list.lock); 180 write_unlock_bh(&chan_list_lock);
184 return err; 181 return err;
185} 182}
186 183
187int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) 184int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
188{ 185{
189 write_lock_bh(&l2cap_sk_list.lock); 186 write_lock_bh(&chan_list_lock);
190 187
191 chan->scid = scid; 188 chan->scid = scid;
192 189
193 write_unlock_bh(&l2cap_sk_list.lock); 190 write_unlock_bh(&chan_list_lock);
194 191
195 return 0; 192 return 0;
196} 193}
@@ -207,7 +204,7 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
207 return 0; 204 return 0;
208} 205}
209 206
210struct l2cap_chan *l2cap_chan_alloc(struct sock *sk) 207struct l2cap_chan *l2cap_chan_create(struct sock *sk)
211{ 208{
212 struct l2cap_chan *chan; 209 struct l2cap_chan *chan;
213 210
@@ -217,11 +214,19 @@ struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
217 214
218 chan->sk = sk; 215 chan->sk = sk;
219 216
217 write_lock_bh(&chan_list_lock);
218 list_add(&chan->global_l, &chan_list);
219 write_unlock_bh(&chan_list_lock);
220
220 return chan; 221 return chan;
221} 222}
222 223
223void l2cap_chan_free(struct l2cap_chan *chan) 224void l2cap_chan_destroy(struct l2cap_chan *chan)
224{ 225{
226 write_lock_bh(&chan_list_lock);
227 list_del(&chan->global_l);
228 write_unlock_bh(&chan_list_lock);
229
225 kfree(chan); 230 kfree(chan);
226} 231}
227 232
@@ -651,48 +656,51 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
651/* Find socket with cid and source bdaddr. 656/* Find socket with cid and source bdaddr.
652 * Returns closest match, locked. 657 * Returns closest match, locked.
653 */ 658 */
654static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src) 659static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
655{ 660{
656 struct sock *sk = NULL, *sk1 = NULL; 661 struct l2cap_chan *c, *c1 = NULL;
657 struct hlist_node *node;
658 662
659 read_lock(&l2cap_sk_list.lock); 663 read_lock(&chan_list_lock);
660 664
661 sk_for_each(sk, node, &l2cap_sk_list.head) { 665 list_for_each_entry(c, &chan_list, global_l) {
662 struct l2cap_chan *chan = l2cap_pi(sk)->chan; 666 struct sock *sk = c->sk;
663 667
664 if (state && sk->sk_state != state) 668 if (state && sk->sk_state != state)
665 continue; 669 continue;
666 670
667 if (chan->scid == cid) { 671 if (c->scid == cid) {
668 /* Exact match. */ 672 /* Exact match. */
669 if (!bacmp(&bt_sk(sk)->src, src)) 673 if (!bacmp(&bt_sk(sk)->src, src)) {
670 break; 674 read_unlock(&chan_list_lock);
675 return c;
676 }
671 677
672 /* Closest match */ 678 /* Closest match */
673 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) 679 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
674 sk1 = sk; 680 c1 = c;
675 } 681 }
676 } 682 }
677 683
678 read_unlock(&l2cap_sk_list.lock); 684 read_unlock(&chan_list_lock);
679 685
680 return node ? sk : sk1; 686 return c1;
681} 687}
682 688
683static void l2cap_le_conn_ready(struct l2cap_conn *conn) 689static void l2cap_le_conn_ready(struct l2cap_conn *conn)
684{ 690{
685 struct sock *parent, *sk; 691 struct sock *parent, *sk;
686 struct l2cap_chan *chan; 692 struct l2cap_chan *chan, *pchan;
687 693
688 BT_DBG(""); 694 BT_DBG("");
689 695
690 /* Check if we have socket listening on cid */ 696 /* Check if we have socket listening on cid */
691 parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA, 697 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
692 conn->src); 698 conn->src);
693 if (!parent) 699 if (!pchan)
694 return; 700 return;
695 701
702 parent = pchan->sk;
703
696 bh_lock_sock(parent); 704 bh_lock_sock(parent);
697 705
698 /* Check for backlog size */ 706 /* Check for backlog size */
@@ -705,7 +713,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
705 if (!sk) 713 if (!sk)
706 goto clean; 714 goto clean;
707 715
708 chan = l2cap_chan_alloc(sk); 716 chan = l2cap_chan_create(sk);
709 if (!chan) { 717 if (!chan) {
710 l2cap_sock_kill(sk); 718 l2cap_sock_kill(sk);
711 goto clean; 719 goto clean;
@@ -883,33 +891,34 @@ static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *ch
883/* Find socket with psm and source bdaddr. 891/* Find socket with psm and source bdaddr.
884 * Returns closest match. 892 * Returns closest match.
885 */ 893 */
886static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src) 894static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
887{ 895{
888 struct sock *sk = NULL, *sk1 = NULL; 896 struct l2cap_chan *c, *c1 = NULL;
889 struct hlist_node *node;
890 897
891 read_lock(&l2cap_sk_list.lock); 898 read_lock(&chan_list_lock);
892 899
893 sk_for_each(sk, node, &l2cap_sk_list.head) { 900 list_for_each_entry(c, &chan_list, global_l) {
894 struct l2cap_chan *chan = l2cap_pi(sk)->chan; 901 struct sock *sk = c->sk;
895 902
896 if (state && sk->sk_state != state) 903 if (state && sk->sk_state != state)
897 continue; 904 continue;
898 905
899 if (chan->psm == psm) { 906 if (c->psm == psm) {
900 /* Exact match. */ 907 /* Exact match. */
901 if (!bacmp(&bt_sk(sk)->src, src)) 908 if (!bacmp(&bt_sk(sk)->src, src)) {
902 break; 909 read_unlock_bh(&chan_list_lock);
910 return c;
911 }
903 912
904 /* Closest match */ 913 /* Closest match */
905 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) 914 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
906 sk1 = sk; 915 c1 = c;
907 } 916 }
908 } 917 }
909 918
910 read_unlock(&l2cap_sk_list.lock); 919 read_unlock(&chan_list_lock);
911 920
912 return node ? sk : sk1; 921 return c1;
913} 922}
914 923
915int l2cap_chan_connect(struct l2cap_chan *chan) 924int l2cap_chan_connect(struct l2cap_chan *chan)
@@ -2079,22 +2088,26 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
2079{ 2088{
2080 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; 2089 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2081 struct l2cap_conn_rsp rsp; 2090 struct l2cap_conn_rsp rsp;
2082 struct l2cap_chan *chan = NULL; 2091 struct l2cap_chan *chan = NULL, *pchan;
2083 struct sock *parent, *sk = NULL; 2092 struct sock *parent, *sk = NULL;
2084 int result, status = L2CAP_CS_NO_INFO; 2093 int result, status = L2CAP_CS_NO_INFO;
2085 2094
2086 u16 dcid = 0, scid = __le16_to_cpu(req->scid); 2095 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
2087 __le16 psm = req->psm; 2096 __le16 psm = req->psm;
2088 2097
2089 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid); 2098 BT_ERR("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2090 2099
2091 /* Check if we have socket listening on psm */ 2100 /* Check if we have socket listening on psm */
2092 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src); 2101 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2093 if (!parent) { 2102 if (!pchan) {
2094 result = L2CAP_CR_BAD_PSM; 2103 result = L2CAP_CR_BAD_PSM;
2095 goto sendresp; 2104 goto sendresp;
2096 } 2105 }
2097 2106
2107 BT_ERR("%p 0x%2.2x", pchan, pchan->psm);
2108
2109 parent = pchan->sk;
2110
2098 bh_lock_sock(parent); 2111 bh_lock_sock(parent);
2099 2112
2100 /* Check if the ACL is secure enough (if not SDP) */ 2113 /* Check if the ACL is secure enough (if not SDP) */
@@ -2117,7 +2130,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
2117 if (!sk) 2130 if (!sk)
2118 goto response; 2131 goto response;
2119 2132
2120 chan = l2cap_chan_alloc(sk); 2133 chan = l2cap_chan_create(sk);
2121 if (!chan) { 2134 if (!chan) {
2122 l2cap_sock_kill(sk); 2135 l2cap_sock_kill(sk);
2123 goto response; 2136 goto response;
@@ -3745,11 +3758,14 @@ done:
3745static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb) 3758static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
3746{ 3759{
3747 struct sock *sk; 3760 struct sock *sk;
3761 struct l2cap_chan *chan;
3748 3762
3749 sk = l2cap_get_sock_by_psm(0, psm, conn->src); 3763 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3750 if (!sk) 3764 if (!chan)
3751 goto drop; 3765 goto drop;
3752 3766
3767 sk = chan->sk;
3768
3753 bh_lock_sock(sk); 3769 bh_lock_sock(sk);
3754 3770
3755 BT_DBG("sk %p, len %d", sk, skb->len); 3771 BT_DBG("sk %p, len %d", sk, skb->len);
@@ -3775,11 +3791,14 @@ done:
3775static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb) 3791static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3776{ 3792{
3777 struct sock *sk; 3793 struct sock *sk;
3794 struct l2cap_chan *chan;
3778 3795
3779 sk = l2cap_get_sock_by_scid(0, cid, conn->src); 3796 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
3780 if (!sk) 3797 if (!chan)
3781 goto drop; 3798 goto drop;
3782 3799
3800 sk = chan->sk;
3801
3783 bh_lock_sock(sk); 3802 bh_lock_sock(sk);
3784 3803
3785 BT_DBG("sk %p, len %d", sk, skb->len); 3804 BT_DBG("sk %p, len %d", sk, skb->len);
@@ -3846,8 +3865,7 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3846static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) 3865static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3847{ 3866{
3848 int exact = 0, lm1 = 0, lm2 = 0; 3867 int exact = 0, lm1 = 0, lm2 = 0;
3849 register struct sock *sk; 3868 struct l2cap_chan *c;
3850 struct hlist_node *node;
3851 3869
3852 if (type != ACL_LINK) 3870 if (type != ACL_LINK)
3853 return -EINVAL; 3871 return -EINVAL;
@@ -3855,25 +3873,25 @@ static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3855 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); 3873 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3856 3874
3857 /* Find listening sockets and check their link_mode */ 3875 /* Find listening sockets and check their link_mode */
3858 read_lock(&l2cap_sk_list.lock); 3876 read_lock(&chan_list_lock);
3859 sk_for_each(sk, node, &l2cap_sk_list.head) { 3877 list_for_each_entry(c, &chan_list, global_l) {
3860 struct l2cap_chan *chan = l2cap_pi(sk)->chan; 3878 struct sock *sk = c->sk;
3861 3879
3862 if (sk->sk_state != BT_LISTEN) 3880 if (sk->sk_state != BT_LISTEN)
3863 continue; 3881 continue;
3864 3882
3865 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { 3883 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
3866 lm1 |= HCI_LM_ACCEPT; 3884 lm1 |= HCI_LM_ACCEPT;
3867 if (chan->role_switch) 3885 if (c->role_switch)
3868 lm1 |= HCI_LM_MASTER; 3886 lm1 |= HCI_LM_MASTER;
3869 exact++; 3887 exact++;
3870 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { 3888 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3871 lm2 |= HCI_LM_ACCEPT; 3889 lm2 |= HCI_LM_ACCEPT;
3872 if (chan->role_switch) 3890 if (c->role_switch)
3873 lm2 |= HCI_LM_MASTER; 3891 lm2 |= HCI_LM_MASTER;
3874 } 3892 }
3875 } 3893 }
3876 read_unlock(&l2cap_sk_list.lock); 3894 read_unlock(&chan_list_lock);
3877 3895
3878 return exact ? lm1 : lm2; 3896 return exact ? lm1 : lm2;
3879} 3897}
@@ -4126,25 +4144,22 @@ drop:
4126 4144
4127static int l2cap_debugfs_show(struct seq_file *f, void *p) 4145static int l2cap_debugfs_show(struct seq_file *f, void *p)
4128{ 4146{
4129 struct sock *sk; 4147 struct l2cap_chan *c;
4130 struct hlist_node *node;
4131 4148
4132 read_lock_bh(&l2cap_sk_list.lock); 4149 read_lock_bh(&chan_list_lock);
4133 4150
4134 sk_for_each(sk, node, &l2cap_sk_list.head) { 4151 list_for_each_entry(c, &chan_list, global_l) {
4135 struct l2cap_pinfo *pi = l2cap_pi(sk); 4152 struct sock *sk = c->sk;
4136 struct l2cap_chan *chan = pi->chan;
4137 4153
4138 seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", 4154 seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
4139 batostr(&bt_sk(sk)->src), 4155 batostr(&bt_sk(sk)->src),
4140 batostr(&bt_sk(sk)->dst), 4156 batostr(&bt_sk(sk)->dst),
4141 sk->sk_state, __le16_to_cpu(chan->psm), 4157 sk->sk_state, __le16_to_cpu(c->psm),
4142 chan->scid, chan->dcid, 4158 c->scid, c->dcid, c->imtu, c->omtu,
4143 chan->imtu, chan->omtu, chan->sec_level, 4159 c->sec_level, c->mode);
4144 chan->mode);
4145 } 4160 }
4146 4161
4147 read_unlock_bh(&l2cap_sk_list.lock); 4162 read_unlock_bh(&chan_list_lock);
4148 4163
4149 return 0; 4164 return 0;
4150} 4165}
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index aca99cd5377d..c98360d40b84 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -808,8 +808,7 @@ void l2cap_sock_kill(struct sock *sk)
808 808
809 /* Kill poor orphan */ 809 /* Kill poor orphan */
810 810
811 l2cap_chan_free(l2cap_pi(sk)->chan); 811 l2cap_chan_destroy(l2cap_pi(sk)->chan);
812 bt_sock_unlink(&l2cap_sk_list, sk);
813 sock_set_flag(sk, SOCK_DEAD); 812 sock_set_flag(sk, SOCK_DEAD);
814 sock_put(sk); 813 sock_put(sk);
815} 814}
@@ -1025,7 +1024,6 @@ struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, g
1025 1024
1026 setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk); 1025 setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk);
1027 1026
1028 bt_sock_link(&l2cap_sk_list, sk);
1029 return sk; 1027 return sk;
1030} 1028}
1031 1029
@@ -1052,7 +1050,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
1052 if (!sk) 1050 if (!sk)
1053 return -ENOMEM; 1051 return -ENOMEM;
1054 1052
1055 chan = l2cap_chan_alloc(sk); 1053 chan = l2cap_chan_create(sk);
1056 if (!chan) { 1054 if (!chan) {
1057 l2cap_sock_kill(sk); 1055 l2cap_sock_kill(sk);
1058 return -ENOMEM; 1056 return -ENOMEM;