diff options
Diffstat (limited to 'net/nfc/llcp/llcp.c')
-rw-r--r-- | net/nfc/llcp/llcp.c | 131 |
1 files changed, 70 insertions, 61 deletions
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index 82f0f7588b46..c12c5ef3d036 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c | |||
@@ -56,7 +56,7 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) | |||
56 | sk_for_each_safe(sk, node, tmp, &local->sockets.head) { | 56 | sk_for_each_safe(sk, node, tmp, &local->sockets.head) { |
57 | llcp_sock = nfc_llcp_sock(sk); | 57 | llcp_sock = nfc_llcp_sock(sk); |
58 | 58 | ||
59 | lock_sock(sk); | 59 | bh_lock_sock(sk); |
60 | 60 | ||
61 | if (sk->sk_state == LLCP_CONNECTED) | 61 | if (sk->sk_state == LLCP_CONNECTED) |
62 | nfc_put_device(llcp_sock->dev); | 62 | nfc_put_device(llcp_sock->dev); |
@@ -68,26 +68,26 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) | |||
68 | list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue, | 68 | list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue, |
69 | accept_queue) { | 69 | accept_queue) { |
70 | accept_sk = &lsk->sk; | 70 | accept_sk = &lsk->sk; |
71 | lock_sock(accept_sk); | 71 | bh_lock_sock(accept_sk); |
72 | 72 | ||
73 | nfc_llcp_accept_unlink(accept_sk); | 73 | nfc_llcp_accept_unlink(accept_sk); |
74 | 74 | ||
75 | accept_sk->sk_state = LLCP_CLOSED; | 75 | accept_sk->sk_state = LLCP_CLOSED; |
76 | 76 | ||
77 | release_sock(accept_sk); | 77 | bh_unlock_sock(accept_sk); |
78 | 78 | ||
79 | sock_orphan(accept_sk); | 79 | sock_orphan(accept_sk); |
80 | } | 80 | } |
81 | 81 | ||
82 | if (listen == true) { | 82 | if (listen == true) { |
83 | release_sock(sk); | 83 | bh_unlock_sock(sk); |
84 | continue; | 84 | continue; |
85 | } | 85 | } |
86 | } | 86 | } |
87 | 87 | ||
88 | sk->sk_state = LLCP_CLOSED; | 88 | sk->sk_state = LLCP_CLOSED; |
89 | 89 | ||
90 | release_sock(sk); | 90 | bh_unlock_sock(sk); |
91 | 91 | ||
92 | sock_orphan(sk); | 92 | sock_orphan(sk); |
93 | 93 | ||
@@ -114,9 +114,9 @@ static void local_release(struct kref *ref) | |||
114 | nfc_llcp_socket_release(local, false); | 114 | nfc_llcp_socket_release(local, false); |
115 | del_timer_sync(&local->link_timer); | 115 | del_timer_sync(&local->link_timer); |
116 | skb_queue_purge(&local->tx_queue); | 116 | skb_queue_purge(&local->tx_queue); |
117 | destroy_workqueue(local->tx_wq); | 117 | cancel_work_sync(&local->tx_work); |
118 | destroy_workqueue(local->rx_wq); | 118 | cancel_work_sync(&local->rx_work); |
119 | destroy_workqueue(local->timeout_wq); | 119 | cancel_work_sync(&local->timeout_work); |
120 | kfree_skb(local->rx_pending); | 120 | kfree_skb(local->rx_pending); |
121 | kfree(local); | 121 | kfree(local); |
122 | } | 122 | } |
@@ -181,7 +181,7 @@ static void nfc_llcp_symm_timer(unsigned long data) | |||
181 | 181 | ||
182 | pr_err("SYMM timeout\n"); | 182 | pr_err("SYMM timeout\n"); |
183 | 183 | ||
184 | queue_work(local->timeout_wq, &local->timeout_work); | 184 | queue_work(system_nrt_wq, &local->timeout_work); |
185 | } | 185 | } |
186 | 186 | ||
187 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) | 187 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) |
@@ -426,6 +426,7 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local) | |||
426 | u8 *miux_tlv, miux_length; | 426 | u8 *miux_tlv, miux_length; |
427 | __be16 miux; | 427 | __be16 miux; |
428 | u8 gb_len = 0; | 428 | u8 gb_len = 0; |
429 | int ret = 0; | ||
429 | 430 | ||
430 | version = LLCP_VERSION_11; | 431 | version = LLCP_VERSION_11; |
431 | version_tlv = nfc_llcp_build_tlv(LLCP_TLV_VERSION, &version, | 432 | version_tlv = nfc_llcp_build_tlv(LLCP_TLV_VERSION, &version, |
@@ -450,8 +451,8 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local) | |||
450 | gb_len += ARRAY_SIZE(llcp_magic); | 451 | gb_len += ARRAY_SIZE(llcp_magic); |
451 | 452 | ||
452 | if (gb_len > NFC_MAX_GT_LEN) { | 453 | if (gb_len > NFC_MAX_GT_LEN) { |
453 | kfree(version_tlv); | 454 | ret = -EINVAL; |
454 | return -EINVAL; | 455 | goto out; |
455 | } | 456 | } |
456 | 457 | ||
457 | gb_cur = local->gb; | 458 | gb_cur = local->gb; |
@@ -471,12 +472,15 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local) | |||
471 | memcpy(gb_cur, miux_tlv, miux_length); | 472 | memcpy(gb_cur, miux_tlv, miux_length); |
472 | gb_cur += miux_length; | 473 | gb_cur += miux_length; |
473 | 474 | ||
475 | local->gb_len = gb_len; | ||
476 | |||
477 | out: | ||
474 | kfree(version_tlv); | 478 | kfree(version_tlv); |
475 | kfree(lto_tlv); | 479 | kfree(lto_tlv); |
480 | kfree(wks_tlv); | ||
481 | kfree(miux_tlv); | ||
476 | 482 | ||
477 | local->gb_len = gb_len; | 483 | return ret; |
478 | |||
479 | return 0; | ||
480 | } | 484 | } |
481 | 485 | ||
482 | u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len) | 486 | u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len) |
@@ -554,6 +558,46 @@ static void nfc_llcp_set_nrns(struct nfc_llcp_sock *sock, struct sk_buff *pdu) | |||
554 | sock->recv_ack_n = (sock->recv_n - 1) % 16; | 558 | sock->recv_ack_n = (sock->recv_n - 1) % 16; |
555 | } | 559 | } |
556 | 560 | ||
561 | void nfc_llcp_send_to_raw_sock(struct nfc_llcp_local *local, | ||
562 | struct sk_buff *skb, u8 direction) | ||
563 | { | ||
564 | struct hlist_node *node; | ||
565 | struct sk_buff *skb_copy = NULL, *nskb; | ||
566 | struct sock *sk; | ||
567 | u8 *data; | ||
568 | |||
569 | read_lock(&local->raw_sockets.lock); | ||
570 | |||
571 | sk_for_each(sk, node, &local->raw_sockets.head) { | ||
572 | if (sk->sk_state != LLCP_BOUND) | ||
573 | continue; | ||
574 | |||
575 | if (skb_copy == NULL) { | ||
576 | skb_copy = __pskb_copy(skb, NFC_LLCP_RAW_HEADER_SIZE, | ||
577 | GFP_ATOMIC); | ||
578 | |||
579 | if (skb_copy == NULL) | ||
580 | continue; | ||
581 | |||
582 | data = skb_push(skb_copy, NFC_LLCP_RAW_HEADER_SIZE); | ||
583 | |||
584 | data[0] = local->dev ? local->dev->idx : 0xFF; | ||
585 | data[1] = direction; | ||
586 | } | ||
587 | |||
588 | nskb = skb_clone(skb_copy, GFP_ATOMIC); | ||
589 | if (!nskb) | ||
590 | continue; | ||
591 | |||
592 | if (sock_queue_rcv_skb(sk, nskb)) | ||
593 | kfree_skb(nskb); | ||
594 | } | ||
595 | |||
596 | read_unlock(&local->raw_sockets.lock); | ||
597 | |||
598 | kfree_skb(skb_copy); | ||
599 | } | ||
600 | |||
557 | static void nfc_llcp_tx_work(struct work_struct *work) | 601 | static void nfc_llcp_tx_work(struct work_struct *work) |
558 | { | 602 | { |
559 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, | 603 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, |
@@ -574,6 +618,9 @@ static void nfc_llcp_tx_work(struct work_struct *work) | |||
574 | DUMP_PREFIX_OFFSET, 16, 1, | 618 | DUMP_PREFIX_OFFSET, 16, 1, |
575 | skb->data, skb->len, true); | 619 | skb->data, skb->len, true); |
576 | 620 | ||
621 | nfc_llcp_send_to_raw_sock(local, skb, | ||
622 | NFC_LLCP_DIRECTION_TX); | ||
623 | |||
577 | ret = nfc_data_exchange(local->dev, local->target_idx, | 624 | ret = nfc_data_exchange(local->dev, local->target_idx, |
578 | skb, nfc_llcp_recv, local); | 625 | skb, nfc_llcp_recv, local); |
579 | 626 | ||
@@ -1018,6 +1065,8 @@ static void nfc_llcp_rx_work(struct work_struct *work) | |||
1018 | print_hex_dump(KERN_DEBUG, "LLCP Rx: ", DUMP_PREFIX_OFFSET, | 1065 | print_hex_dump(KERN_DEBUG, "LLCP Rx: ", DUMP_PREFIX_OFFSET, |
1019 | 16, 1, skb->data, skb->len, true); | 1066 | 16, 1, skb->data, skb->len, true); |
1020 | 1067 | ||
1068 | nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_RX); | ||
1069 | |||
1021 | switch (ptype) { | 1070 | switch (ptype) { |
1022 | case LLCP_PDU_SYMM: | 1071 | case LLCP_PDU_SYMM: |
1023 | pr_debug("SYMM\n"); | 1072 | pr_debug("SYMM\n"); |
@@ -1052,7 +1101,7 @@ static void nfc_llcp_rx_work(struct work_struct *work) | |||
1052 | 1101 | ||
1053 | } | 1102 | } |
1054 | 1103 | ||
1055 | queue_work(local->tx_wq, &local->tx_work); | 1104 | queue_work(system_nrt_wq, &local->tx_work); |
1056 | kfree_skb(local->rx_pending); | 1105 | kfree_skb(local->rx_pending); |
1057 | local->rx_pending = NULL; | 1106 | local->rx_pending = NULL; |
1058 | 1107 | ||
@@ -1071,7 +1120,7 @@ void nfc_llcp_recv(void *data, struct sk_buff *skb, int err) | |||
1071 | 1120 | ||
1072 | local->rx_pending = skb_get(skb); | 1121 | local->rx_pending = skb_get(skb); |
1073 | del_timer(&local->link_timer); | 1122 | del_timer(&local->link_timer); |
1074 | queue_work(local->rx_wq, &local->rx_work); | 1123 | queue_work(system_nrt_wq, &local->rx_work); |
1075 | 1124 | ||
1076 | return; | 1125 | return; |
1077 | } | 1126 | } |
@@ -1086,7 +1135,7 @@ int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb) | |||
1086 | 1135 | ||
1087 | local->rx_pending = skb_get(skb); | 1136 | local->rx_pending = skb_get(skb); |
1088 | del_timer(&local->link_timer); | 1137 | del_timer(&local->link_timer); |
1089 | queue_work(local->rx_wq, &local->rx_work); | 1138 | queue_work(system_nrt_wq, &local->rx_work); |
1090 | 1139 | ||
1091 | return 0; | 1140 | return 0; |
1092 | } | 1141 | } |
@@ -1121,7 +1170,7 @@ void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, | |||
1121 | if (rf_mode == NFC_RF_INITIATOR) { | 1170 | if (rf_mode == NFC_RF_INITIATOR) { |
1122 | pr_debug("Queueing Tx work\n"); | 1171 | pr_debug("Queueing Tx work\n"); |
1123 | 1172 | ||
1124 | queue_work(local->tx_wq, &local->tx_work); | 1173 | queue_work(system_nrt_wq, &local->tx_work); |
1125 | } else { | 1174 | } else { |
1126 | mod_timer(&local->link_timer, | 1175 | mod_timer(&local->link_timer, |
1127 | jiffies + msecs_to_jiffies(local->remote_lto)); | 1176 | jiffies + msecs_to_jiffies(local->remote_lto)); |
@@ -1130,10 +1179,7 @@ void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, | |||
1130 | 1179 | ||
1131 | int nfc_llcp_register_device(struct nfc_dev *ndev) | 1180 | int nfc_llcp_register_device(struct nfc_dev *ndev) |
1132 | { | 1181 | { |
1133 | struct device *dev = &ndev->dev; | ||
1134 | struct nfc_llcp_local *local; | 1182 | struct nfc_llcp_local *local; |
1135 | char name[32]; | ||
1136 | int err; | ||
1137 | 1183 | ||
1138 | local = kzalloc(sizeof(struct nfc_llcp_local), GFP_KERNEL); | 1184 | local = kzalloc(sizeof(struct nfc_llcp_local), GFP_KERNEL); |
1139 | if (local == NULL) | 1185 | if (local == NULL) |
@@ -1149,41 +1195,15 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) | |||
1149 | 1195 | ||
1150 | skb_queue_head_init(&local->tx_queue); | 1196 | skb_queue_head_init(&local->tx_queue); |
1151 | INIT_WORK(&local->tx_work, nfc_llcp_tx_work); | 1197 | INIT_WORK(&local->tx_work, nfc_llcp_tx_work); |
1152 | snprintf(name, sizeof(name), "%s_llcp_tx_wq", dev_name(dev)); | ||
1153 | local->tx_wq = | ||
1154 | alloc_workqueue(name, | ||
1155 | WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, | ||
1156 | 1); | ||
1157 | if (local->tx_wq == NULL) { | ||
1158 | err = -ENOMEM; | ||
1159 | goto err_local; | ||
1160 | } | ||
1161 | 1198 | ||
1162 | local->rx_pending = NULL; | 1199 | local->rx_pending = NULL; |
1163 | INIT_WORK(&local->rx_work, nfc_llcp_rx_work); | 1200 | INIT_WORK(&local->rx_work, nfc_llcp_rx_work); |
1164 | snprintf(name, sizeof(name), "%s_llcp_rx_wq", dev_name(dev)); | ||
1165 | local->rx_wq = | ||
1166 | alloc_workqueue(name, | ||
1167 | WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, | ||
1168 | 1); | ||
1169 | if (local->rx_wq == NULL) { | ||
1170 | err = -ENOMEM; | ||
1171 | goto err_tx_wq; | ||
1172 | } | ||
1173 | 1201 | ||
1174 | INIT_WORK(&local->timeout_work, nfc_llcp_timeout_work); | 1202 | INIT_WORK(&local->timeout_work, nfc_llcp_timeout_work); |
1175 | snprintf(name, sizeof(name), "%s_llcp_timeout_wq", dev_name(dev)); | ||
1176 | local->timeout_wq = | ||
1177 | alloc_workqueue(name, | ||
1178 | WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, | ||
1179 | 1); | ||
1180 | if (local->timeout_wq == NULL) { | ||
1181 | err = -ENOMEM; | ||
1182 | goto err_rx_wq; | ||
1183 | } | ||
1184 | 1203 | ||
1185 | local->sockets.lock = __RW_LOCK_UNLOCKED(local->sockets.lock); | 1204 | rwlock_init(&local->sockets.lock); |
1186 | local->connecting_sockets.lock = __RW_LOCK_UNLOCKED(local->connecting_sockets.lock); | 1205 | rwlock_init(&local->connecting_sockets.lock); |
1206 | rwlock_init(&local->raw_sockets.lock); | ||
1187 | 1207 | ||
1188 | nfc_llcp_build_gb(local); | 1208 | nfc_llcp_build_gb(local); |
1189 | 1209 | ||
@@ -1193,17 +1213,6 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) | |||
1193 | list_add(&llcp_devices, &local->list); | 1213 | list_add(&llcp_devices, &local->list); |
1194 | 1214 | ||
1195 | return 0; | 1215 | return 0; |
1196 | |||
1197 | err_rx_wq: | ||
1198 | destroy_workqueue(local->rx_wq); | ||
1199 | |||
1200 | err_tx_wq: | ||
1201 | destroy_workqueue(local->tx_wq); | ||
1202 | |||
1203 | err_local: | ||
1204 | kfree(local); | ||
1205 | |||
1206 | return 0; | ||
1207 | } | 1216 | } |
1208 | 1217 | ||
1209 | void nfc_llcp_unregister_device(struct nfc_dev *dev) | 1218 | void nfc_llcp_unregister_device(struct nfc_dev *dev) |