.. | .. |
---|
17 | 17 | static u8 llcp_magic[3] = {0x46, 0x66, 0x6d}; |
---|
18 | 18 | |
---|
19 | 19 | static LIST_HEAD(llcp_devices); |
---|
| 20 | +/* Protects llcp_devices list */ |
---|
| 21 | +static DEFINE_SPINLOCK(llcp_devices_lock); |
---|
20 | 22 | |
---|
21 | 23 | static void nfc_llcp_rx_skb(struct nfc_llcp_local *local, struct sk_buff *skb); |
---|
22 | 24 | |
---|
.. | .. |
---|
143 | 145 | write_unlock(&local->raw_sockets.lock); |
---|
144 | 146 | } |
---|
145 | 147 | |
---|
146 | | -struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) |
---|
| 148 | +static struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) |
---|
147 | 149 | { |
---|
148 | 150 | kref_get(&local->ref); |
---|
149 | 151 | |
---|
.. | .. |
---|
159 | 161 | cancel_work_sync(&local->rx_work); |
---|
160 | 162 | cancel_work_sync(&local->timeout_work); |
---|
161 | 163 | kfree_skb(local->rx_pending); |
---|
| 164 | + local->rx_pending = NULL; |
---|
162 | 165 | del_timer_sync(&local->sdreq_timer); |
---|
163 | 166 | cancel_work_sync(&local->sdreq_timeout_work); |
---|
164 | 167 | nfc_llcp_free_sdp_tlv_list(&local->pending_sdreqs); |
---|
.. | .. |
---|
170 | 173 | |
---|
171 | 174 | local = container_of(ref, struct nfc_llcp_local, ref); |
---|
172 | 175 | |
---|
173 | | - list_del(&local->list); |
---|
174 | 176 | local_cleanup(local); |
---|
175 | 177 | kfree(local); |
---|
176 | 178 | } |
---|
.. | .. |
---|
283 | 285 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) |
---|
284 | 286 | { |
---|
285 | 287 | struct nfc_llcp_local *local; |
---|
| 288 | + struct nfc_llcp_local *res = NULL; |
---|
286 | 289 | |
---|
| 290 | + spin_lock(&llcp_devices_lock); |
---|
287 | 291 | list_for_each_entry(local, &llcp_devices, list) |
---|
288 | | - if (local->dev == dev) |
---|
289 | | - return local; |
---|
| 292 | + if (local->dev == dev) { |
---|
| 293 | + res = nfc_llcp_local_get(local); |
---|
| 294 | + break; |
---|
| 295 | + } |
---|
| 296 | + spin_unlock(&llcp_devices_lock); |
---|
290 | 297 | |
---|
291 | | - pr_debug("No device found\n"); |
---|
| 298 | + return res; |
---|
| 299 | +} |
---|
| 300 | + |
---|
| 301 | +static struct nfc_llcp_local *nfc_llcp_remove_local(struct nfc_dev *dev) |
---|
| 302 | +{ |
---|
| 303 | + struct nfc_llcp_local *local, *tmp; |
---|
| 304 | + |
---|
| 305 | + spin_lock(&llcp_devices_lock); |
---|
| 306 | + list_for_each_entry_safe(local, tmp, &llcp_devices, list) |
---|
| 307 | + if (local->dev == dev) { |
---|
| 308 | + list_del(&local->list); |
---|
| 309 | + spin_unlock(&llcp_devices_lock); |
---|
| 310 | + return local; |
---|
| 311 | + } |
---|
| 312 | + spin_unlock(&llcp_devices_lock); |
---|
| 313 | + |
---|
| 314 | + pr_warn("Shutting down device not found\n"); |
---|
292 | 315 | |
---|
293 | 316 | return NULL; |
---|
294 | 317 | } |
---|
.. | .. |
---|
301 | 324 | "urn:nfc:sn:snep", |
---|
302 | 325 | }; |
---|
303 | 326 | |
---|
304 | | -static int nfc_llcp_wks_sap(char *service_name, size_t service_name_len) |
---|
| 327 | +static int nfc_llcp_wks_sap(const char *service_name, size_t service_name_len) |
---|
305 | 328 | { |
---|
306 | 329 | int sap, num_wks; |
---|
307 | 330 | |
---|
.. | .. |
---|
325 | 348 | |
---|
326 | 349 | static |
---|
327 | 350 | struct nfc_llcp_sock *nfc_llcp_sock_from_sn(struct nfc_llcp_local *local, |
---|
328 | | - u8 *sn, size_t sn_len) |
---|
| 351 | + const u8 *sn, size_t sn_len) |
---|
329 | 352 | { |
---|
330 | 353 | struct sock *sk; |
---|
331 | 354 | struct nfc_llcp_sock *llcp_sock, *tmp_sock; |
---|
.. | .. |
---|
522 | 545 | { |
---|
523 | 546 | u8 *gb_cur, version, version_length; |
---|
524 | 547 | u8 lto_length, wks_length, miux_length; |
---|
525 | | - u8 *version_tlv = NULL, *lto_tlv = NULL, |
---|
| 548 | + const u8 *version_tlv = NULL, *lto_tlv = NULL, |
---|
526 | 549 | *wks_tlv = NULL, *miux_tlv = NULL; |
---|
527 | 550 | __be16 wks = cpu_to_be16(local->local_wks); |
---|
528 | 551 | u8 gb_len = 0; |
---|
.. | .. |
---|
609 | 632 | |
---|
610 | 633 | *general_bytes_len = local->gb_len; |
---|
611 | 634 | |
---|
| 635 | + nfc_llcp_local_put(local); |
---|
| 636 | + |
---|
612 | 637 | return local->gb; |
---|
613 | 638 | } |
---|
614 | 639 | |
---|
615 | | -int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) |
---|
| 640 | +int nfc_llcp_set_remote_gb(struct nfc_dev *dev, const u8 *gb, u8 gb_len) |
---|
616 | 641 | { |
---|
617 | 642 | struct nfc_llcp_local *local; |
---|
| 643 | + int err; |
---|
618 | 644 | |
---|
619 | 645 | if (gb_len < 3 || gb_len > NFC_MAX_GT_LEN) |
---|
620 | 646 | return -EINVAL; |
---|
.. | .. |
---|
631 | 657 | |
---|
632 | 658 | if (memcmp(local->remote_gb, llcp_magic, 3)) { |
---|
633 | 659 | pr_err("MAC does not support LLCP\n"); |
---|
634 | | - return -EINVAL; |
---|
| 660 | + err = -EINVAL; |
---|
| 661 | + goto out; |
---|
635 | 662 | } |
---|
636 | 663 | |
---|
637 | | - return nfc_llcp_parse_gb_tlv(local, |
---|
| 664 | + err = nfc_llcp_parse_gb_tlv(local, |
---|
638 | 665 | &local->remote_gb[3], |
---|
639 | 666 | local->remote_gb_len - 3); |
---|
| 667 | +out: |
---|
| 668 | + nfc_llcp_local_put(local); |
---|
| 669 | + return err; |
---|
640 | 670 | } |
---|
641 | 671 | |
---|
642 | | -static u8 nfc_llcp_dsap(struct sk_buff *pdu) |
---|
| 672 | +static u8 nfc_llcp_dsap(const struct sk_buff *pdu) |
---|
643 | 673 | { |
---|
644 | 674 | return (pdu->data[0] & 0xfc) >> 2; |
---|
645 | 675 | } |
---|
646 | 676 | |
---|
647 | | -static u8 nfc_llcp_ptype(struct sk_buff *pdu) |
---|
| 677 | +static u8 nfc_llcp_ptype(const struct sk_buff *pdu) |
---|
648 | 678 | { |
---|
649 | 679 | return ((pdu->data[0] & 0x03) << 2) | ((pdu->data[1] & 0xc0) >> 6); |
---|
650 | 680 | } |
---|
651 | 681 | |
---|
652 | | -static u8 nfc_llcp_ssap(struct sk_buff *pdu) |
---|
| 682 | +static u8 nfc_llcp_ssap(const struct sk_buff *pdu) |
---|
653 | 683 | { |
---|
654 | 684 | return pdu->data[1] & 0x3f; |
---|
655 | 685 | } |
---|
656 | 686 | |
---|
657 | | -static u8 nfc_llcp_ns(struct sk_buff *pdu) |
---|
| 687 | +static u8 nfc_llcp_ns(const struct sk_buff *pdu) |
---|
658 | 688 | { |
---|
659 | 689 | return pdu->data[2] >> 4; |
---|
660 | 690 | } |
---|
661 | 691 | |
---|
662 | | -static u8 nfc_llcp_nr(struct sk_buff *pdu) |
---|
| 692 | +static u8 nfc_llcp_nr(const struct sk_buff *pdu) |
---|
663 | 693 | { |
---|
664 | 694 | return pdu->data[2] & 0xf; |
---|
665 | 695 | } |
---|
.. | .. |
---|
801 | 831 | } |
---|
802 | 832 | |
---|
803 | 833 | static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local, |
---|
804 | | - u8 *sn, size_t sn_len) |
---|
| 834 | + const u8 *sn, size_t sn_len) |
---|
805 | 835 | { |
---|
806 | 836 | struct nfc_llcp_sock *llcp_sock; |
---|
807 | 837 | |
---|
.. | .. |
---|
815 | 845 | return llcp_sock; |
---|
816 | 846 | } |
---|
817 | 847 | |
---|
818 | | -static u8 *nfc_llcp_connect_sn(struct sk_buff *skb, size_t *sn_len) |
---|
| 848 | +static const u8 *nfc_llcp_connect_sn(const struct sk_buff *skb, size_t *sn_len) |
---|
819 | 849 | { |
---|
820 | | - u8 *tlv = &skb->data[2], type, length; |
---|
| 850 | + u8 type, length; |
---|
| 851 | + const u8 *tlv = &skb->data[2]; |
---|
821 | 852 | size_t tlv_array_len = skb->len - LLCP_HEADER_SIZE, offset = 0; |
---|
822 | 853 | |
---|
823 | 854 | while (offset < tlv_array_len) { |
---|
.. | .. |
---|
875 | 906 | } |
---|
876 | 907 | |
---|
877 | 908 | static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, |
---|
878 | | - struct sk_buff *skb) |
---|
| 909 | + const struct sk_buff *skb) |
---|
879 | 910 | { |
---|
880 | 911 | struct sock *new_sk, *parent; |
---|
881 | 912 | struct nfc_llcp_sock *sock, *new_sock; |
---|
.. | .. |
---|
893 | 924 | goto fail; |
---|
894 | 925 | } |
---|
895 | 926 | } else { |
---|
896 | | - u8 *sn; |
---|
| 927 | + const u8 *sn; |
---|
897 | 928 | size_t sn_len; |
---|
898 | 929 | |
---|
899 | 930 | sn = nfc_llcp_connect_sn(skb, &sn_len); |
---|
.. | .. |
---|
1112 | 1143 | } |
---|
1113 | 1144 | |
---|
1114 | 1145 | static void nfc_llcp_recv_disc(struct nfc_llcp_local *local, |
---|
1115 | | - struct sk_buff *skb) |
---|
| 1146 | + const struct sk_buff *skb) |
---|
1116 | 1147 | { |
---|
1117 | 1148 | struct nfc_llcp_sock *llcp_sock; |
---|
1118 | 1149 | struct sock *sk; |
---|
.. | .. |
---|
1155 | 1186 | nfc_llcp_sock_put(llcp_sock); |
---|
1156 | 1187 | } |
---|
1157 | 1188 | |
---|
1158 | | -static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb) |
---|
| 1189 | +static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, |
---|
| 1190 | + const struct sk_buff *skb) |
---|
1159 | 1191 | { |
---|
1160 | 1192 | struct nfc_llcp_sock *llcp_sock; |
---|
1161 | 1193 | struct sock *sk; |
---|
.. | .. |
---|
1188 | 1220 | nfc_llcp_sock_put(llcp_sock); |
---|
1189 | 1221 | } |
---|
1190 | 1222 | |
---|
1191 | | -static void nfc_llcp_recv_dm(struct nfc_llcp_local *local, struct sk_buff *skb) |
---|
| 1223 | +static void nfc_llcp_recv_dm(struct nfc_llcp_local *local, |
---|
| 1224 | + const struct sk_buff *skb) |
---|
1192 | 1225 | { |
---|
1193 | 1226 | struct nfc_llcp_sock *llcp_sock; |
---|
1194 | 1227 | struct sock *sk; |
---|
.. | .. |
---|
1226 | 1259 | } |
---|
1227 | 1260 | |
---|
1228 | 1261 | static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, |
---|
1229 | | - struct sk_buff *skb) |
---|
| 1262 | + const struct sk_buff *skb) |
---|
1230 | 1263 | { |
---|
1231 | 1264 | struct nfc_llcp_sock *llcp_sock; |
---|
1232 | | - u8 dsap, ssap, *tlv, type, length, tid, sap; |
---|
| 1265 | + u8 dsap, ssap, type, length, tid, sap; |
---|
| 1266 | + const u8 *tlv; |
---|
1233 | 1267 | u16 tlv_len, offset; |
---|
1234 | | - char *service_name; |
---|
| 1268 | + const char *service_name; |
---|
1235 | 1269 | size_t service_name_len; |
---|
1236 | 1270 | struct nfc_llcp_sdp_tlv *sdp; |
---|
1237 | 1271 | HLIST_HEAD(llc_sdres_list); |
---|
.. | .. |
---|
1522 | 1556 | |
---|
1523 | 1557 | __nfc_llcp_recv(local, skb); |
---|
1524 | 1558 | |
---|
| 1559 | + nfc_llcp_local_put(local); |
---|
| 1560 | + |
---|
1525 | 1561 | return 0; |
---|
1526 | 1562 | } |
---|
1527 | 1563 | |
---|
.. | .. |
---|
1538 | 1574 | |
---|
1539 | 1575 | /* Close and purge all existing sockets */ |
---|
1540 | 1576 | nfc_llcp_socket_release(local, true, 0); |
---|
| 1577 | + |
---|
| 1578 | + nfc_llcp_local_put(local); |
---|
1541 | 1579 | } |
---|
1542 | 1580 | |
---|
1543 | 1581 | void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, |
---|
.. | .. |
---|
1563 | 1601 | mod_timer(&local->link_timer, |
---|
1564 | 1602 | jiffies + msecs_to_jiffies(local->remote_lto)); |
---|
1565 | 1603 | } |
---|
| 1604 | + |
---|
| 1605 | + nfc_llcp_local_put(local); |
---|
1566 | 1606 | } |
---|
1567 | 1607 | |
---|
1568 | 1608 | int nfc_llcp_register_device(struct nfc_dev *ndev) |
---|
.. | .. |
---|
1606 | 1646 | timer_setup(&local->sdreq_timer, nfc_llcp_sdreq_timer, 0); |
---|
1607 | 1647 | INIT_WORK(&local->sdreq_timeout_work, nfc_llcp_sdreq_timeout_work); |
---|
1608 | 1648 | |
---|
| 1649 | + spin_lock(&llcp_devices_lock); |
---|
1609 | 1650 | list_add(&local->list, &llcp_devices); |
---|
| 1651 | + spin_unlock(&llcp_devices_lock); |
---|
1610 | 1652 | |
---|
1611 | 1653 | return 0; |
---|
1612 | 1654 | } |
---|
1613 | 1655 | |
---|
1614 | 1656 | void nfc_llcp_unregister_device(struct nfc_dev *dev) |
---|
1615 | 1657 | { |
---|
1616 | | - struct nfc_llcp_local *local = nfc_llcp_find_local(dev); |
---|
| 1658 | + struct nfc_llcp_local *local = nfc_llcp_remove_local(dev); |
---|
1617 | 1659 | |
---|
1618 | 1660 | if (local == NULL) { |
---|
1619 | 1661 | pr_debug("No such device\n"); |
---|