| .. | .. |
|---|
| 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"); |
|---|