aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/nfc/core.c')
-rw-r--r--net/nfc/core.c112
1 files changed, 85 insertions, 27 deletions
diff --git a/net/nfc/core.c b/net/nfc/core.c
index 3192c3f589ee..9f6ce011d35d 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -97,7 +97,7 @@ int nfc_dev_down(struct nfc_dev *dev)
97 goto error; 97 goto error;
98 } 98 }
99 99
100 if (dev->polling || dev->activated_target_idx != NFC_TARGET_IDX_NONE) { 100 if (dev->polling || dev->active_target) {
101 rc = -EBUSY; 101 rc = -EBUSY;
102 goto error; 102 goto error;
103 } 103 }
@@ -183,11 +183,27 @@ error:
183 return rc; 183 return rc;
184} 184}
185 185
186static struct nfc_target *nfc_find_target(struct nfc_dev *dev, u32 target_idx)
187{
188 int i;
189
190 if (dev->n_targets == 0)
191 return NULL;
192
193 for (i = 0; i < dev->n_targets ; i++) {
194 if (dev->targets[i].idx == target_idx)
195 return &dev->targets[i];
196 }
197
198 return NULL;
199}
200
186int nfc_dep_link_up(struct nfc_dev *dev, int target_index, u8 comm_mode) 201int nfc_dep_link_up(struct nfc_dev *dev, int target_index, u8 comm_mode)
187{ 202{
188 int rc = 0; 203 int rc = 0;
189 u8 *gb; 204 u8 *gb;
190 size_t gb_len; 205 size_t gb_len;
206 struct nfc_target *target;
191 207
192 pr_debug("dev_name=%s comm %d\n", dev_name(&dev->dev), comm_mode); 208 pr_debug("dev_name=%s comm %d\n", dev_name(&dev->dev), comm_mode);
193 209
@@ -212,9 +228,15 @@ int nfc_dep_link_up(struct nfc_dev *dev, int target_index, u8 comm_mode)
212 goto error; 228 goto error;
213 } 229 }
214 230
215 rc = dev->ops->dep_link_up(dev, target_index, comm_mode, gb, gb_len); 231 target = nfc_find_target(dev, target_index);
232 if (target == NULL) {
233 rc = -ENOTCONN;
234 goto error;
235 }
236
237 rc = dev->ops->dep_link_up(dev, target, comm_mode, gb, gb_len);
216 if (!rc) 238 if (!rc)
217 dev->activated_target_idx = target_index; 239 dev->active_target = target;
218 240
219error: 241error:
220 device_unlock(&dev->dev); 242 device_unlock(&dev->dev);
@@ -250,7 +272,7 @@ int nfc_dep_link_down(struct nfc_dev *dev)
250 rc = dev->ops->dep_link_down(dev); 272 rc = dev->ops->dep_link_down(dev);
251 if (!rc) { 273 if (!rc) {
252 dev->dep_link_up = false; 274 dev->dep_link_up = false;
253 dev->activated_target_idx = NFC_TARGET_IDX_NONE; 275 dev->active_target = NULL;
254 nfc_llcp_mac_is_down(dev); 276 nfc_llcp_mac_is_down(dev);
255 nfc_genl_dep_link_down_event(dev); 277 nfc_genl_dep_link_down_event(dev);
256 } 278 }
@@ -282,6 +304,7 @@ EXPORT_SYMBOL(nfc_dep_link_is_up);
282int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol) 304int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol)
283{ 305{
284 int rc; 306 int rc;
307 struct nfc_target *target;
285 308
286 pr_debug("dev_name=%s target_idx=%u protocol=%u\n", 309 pr_debug("dev_name=%s target_idx=%u protocol=%u\n",
287 dev_name(&dev->dev), target_idx, protocol); 310 dev_name(&dev->dev), target_idx, protocol);
@@ -293,9 +316,20 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol)
293 goto error; 316 goto error;
294 } 317 }
295 318
296 rc = dev->ops->activate_target(dev, target_idx, protocol); 319 if (dev->active_target) {
320 rc = -EBUSY;
321 goto error;
322 }
323
324 target = nfc_find_target(dev, target_idx);
325 if (target == NULL) {
326 rc = -ENOTCONN;
327 goto error;
328 }
329
330 rc = dev->ops->activate_target(dev, target, protocol);
297 if (!rc) { 331 if (!rc) {
298 dev->activated_target_idx = target_idx; 332 dev->active_target = target;
299 333
300 if (dev->ops->check_presence) 334 if (dev->ops->check_presence)
301 mod_timer(&dev->check_pres_timer, jiffies + 335 mod_timer(&dev->check_pres_timer, jiffies +
@@ -327,11 +361,21 @@ int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx)
327 goto error; 361 goto error;
328 } 362 }
329 363
364 if (dev->active_target == NULL) {
365 rc = -ENOTCONN;
366 goto error;
367 }
368
369 if (dev->active_target->idx != target_idx) {
370 rc = -ENOTCONN;
371 goto error;
372 }
373
330 if (dev->ops->check_presence) 374 if (dev->ops->check_presence)
331 del_timer_sync(&dev->check_pres_timer); 375 del_timer_sync(&dev->check_pres_timer);
332 376
333 dev->ops->deactivate_target(dev, target_idx); 377 dev->ops->deactivate_target(dev, dev->active_target);
334 dev->activated_target_idx = NFC_TARGET_IDX_NONE; 378 dev->active_target = NULL;
335 379
336error: 380error:
337 device_unlock(&dev->dev); 381 device_unlock(&dev->dev);
@@ -365,13 +409,13 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb,
365 goto error; 409 goto error;
366 } 410 }
367 411
368 if (dev->activated_target_idx == NFC_TARGET_IDX_NONE) { 412 if (dev->active_target == NULL) {
369 rc = -ENOTCONN; 413 rc = -ENOTCONN;
370 kfree_skb(skb); 414 kfree_skb(skb);
371 goto error; 415 goto error;
372 } 416 }
373 417
374 if (target_idx != dev->activated_target_idx) { 418 if (dev->active_target->idx != target_idx) {
375 rc = -EADDRNOTAVAIL; 419 rc = -EADDRNOTAVAIL;
376 kfree_skb(skb); 420 kfree_skb(skb);
377 goto error; 421 goto error;
@@ -380,7 +424,8 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb,
380 if (dev->ops->check_presence) 424 if (dev->ops->check_presence)
381 del_timer_sync(&dev->check_pres_timer); 425 del_timer_sync(&dev->check_pres_timer);
382 426
383 rc = dev->ops->data_exchange(dev, target_idx, skb, cb, cb_context); 427 rc = dev->ops->data_exchange(dev, dev->active_target, skb, cb,
428 cb_context);
384 429
385 if (!rc && dev->ops->check_presence) 430 if (!rc && dev->ops->check_presence)
386 mod_timer(&dev->check_pres_timer, jiffies + 431 mod_timer(&dev->check_pres_timer, jiffies +
@@ -456,6 +501,9 @@ EXPORT_SYMBOL(nfc_alloc_recv_skb);
456 * The device driver must call this function when one or many nfc targets 501 * The device driver must call this function when one or many nfc targets
457 * are found. After calling this function, the device driver must stop 502 * are found. After calling this function, the device driver must stop
458 * polling for targets. 503 * polling for targets.
504 * IMPORTANT: this function must not be called from an atomic context.
505 * In addition, it must also not be called from a context that would prevent
506 * the NFC Core to call other nfc ops entry point concurrently.
459 */ 507 */
460int nfc_targets_found(struct nfc_dev *dev, 508int nfc_targets_found(struct nfc_dev *dev,
461 struct nfc_target *targets, int n_targets) 509 struct nfc_target *targets, int n_targets)
@@ -469,7 +517,7 @@ int nfc_targets_found(struct nfc_dev *dev,
469 for (i = 0; i < n_targets; i++) 517 for (i = 0; i < n_targets; i++)
470 targets[i].idx = dev->target_next_idx++; 518 targets[i].idx = dev->target_next_idx++;
471 519
472 spin_lock_bh(&dev->targets_lock); 520 device_lock(&dev->dev);
473 521
474 dev->targets_generation++; 522 dev->targets_generation++;
475 523
@@ -479,12 +527,12 @@ int nfc_targets_found(struct nfc_dev *dev,
479 527
480 if (!dev->targets) { 528 if (!dev->targets) {
481 dev->n_targets = 0; 529 dev->n_targets = 0;
482 spin_unlock_bh(&dev->targets_lock); 530 device_unlock(&dev->dev);
483 return -ENOMEM; 531 return -ENOMEM;
484 } 532 }
485 533
486 dev->n_targets = n_targets; 534 dev->n_targets = n_targets;
487 spin_unlock_bh(&dev->targets_lock); 535 device_unlock(&dev->dev);
488 536
489 nfc_genl_targets_found(dev); 537 nfc_genl_targets_found(dev);
490 538
@@ -492,6 +540,18 @@ int nfc_targets_found(struct nfc_dev *dev,
492} 540}
493EXPORT_SYMBOL(nfc_targets_found); 541EXPORT_SYMBOL(nfc_targets_found);
494 542
543/**
544 * nfc_target_lost - inform that an activated target went out of field
545 *
546 * @dev: The nfc device that had the activated target in field
547 * @target_idx: the nfc index of the target
548 *
549 * The device driver must call this function when the activated target
550 * goes out of the field.
551 * IMPORTANT: this function must not be called from an atomic context.
552 * In addition, it must also not be called from a context that would prevent
553 * the NFC Core to call other nfc ops entry point concurrently.
554 */
495int nfc_target_lost(struct nfc_dev *dev, u32 target_idx) 555int nfc_target_lost(struct nfc_dev *dev, u32 target_idx)
496{ 556{
497 struct nfc_target *tg; 557 struct nfc_target *tg;
@@ -499,7 +559,7 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx)
499 559
500 pr_debug("dev_name %s n_target %d\n", dev_name(&dev->dev), target_idx); 560 pr_debug("dev_name %s n_target %d\n", dev_name(&dev->dev), target_idx);
501 561
502 spin_lock_bh(&dev->targets_lock); 562 device_lock(&dev->dev);
503 563
504 for (i = 0; i < dev->n_targets; i++) { 564 for (i = 0; i < dev->n_targets; i++) {
505 tg = &dev->targets[i]; 565 tg = &dev->targets[i];
@@ -508,13 +568,13 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx)
508 } 568 }
509 569
510 if (i == dev->n_targets) { 570 if (i == dev->n_targets) {
511 spin_unlock_bh(&dev->targets_lock); 571 device_unlock(&dev->dev);
512 return -EINVAL; 572 return -EINVAL;
513 } 573 }
514 574
515 dev->targets_generation++; 575 dev->targets_generation++;
516 dev->n_targets--; 576 dev->n_targets--;
517 dev->activated_target_idx = NFC_TARGET_IDX_NONE; 577 dev->active_target = NULL;
518 578
519 if (dev->n_targets) { 579 if (dev->n_targets) {
520 memcpy(&dev->targets[i], &dev->targets[i + 1], 580 memcpy(&dev->targets[i], &dev->targets[i + 1],
@@ -524,7 +584,7 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx)
524 dev->targets = NULL; 584 dev->targets = NULL;
525 } 585 }
526 586
527 spin_unlock_bh(&dev->targets_lock); 587 device_unlock(&dev->dev);
528 588
529 nfc_genl_target_lost(dev, target_idx); 589 nfc_genl_target_lost(dev, target_idx);
530 590
@@ -556,15 +616,16 @@ static void nfc_check_pres_work(struct work_struct *work)
556 616
557 device_lock(&dev->dev); 617 device_lock(&dev->dev);
558 618
559 if (dev->activated_target_idx != NFC_TARGET_IDX_NONE && 619 if (dev->active_target && timer_pending(&dev->check_pres_timer) == 0) {
560 timer_pending(&dev->check_pres_timer) == 0) { 620 rc = dev->ops->check_presence(dev, dev->active_target);
561 rc = dev->ops->check_presence(dev, dev->activated_target_idx);
562 if (!rc) { 621 if (!rc) {
563 mod_timer(&dev->check_pres_timer, jiffies + 622 mod_timer(&dev->check_pres_timer, jiffies +
564 msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); 623 msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS));
565 } else { 624 } else {
566 nfc_target_lost(dev, dev->activated_target_idx); 625 u32 active_target_idx = dev->active_target->idx;
567 dev->activated_target_idx = NFC_TARGET_IDX_NONE; 626 device_unlock(&dev->dev);
627 nfc_target_lost(dev, active_target_idx);
628 return;
568 } 629 }
569 } 630 }
570 631
@@ -637,14 +698,12 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
637 dev->tx_headroom = tx_headroom; 698 dev->tx_headroom = tx_headroom;
638 dev->tx_tailroom = tx_tailroom; 699 dev->tx_tailroom = tx_tailroom;
639 700
640 spin_lock_init(&dev->targets_lock);
641 nfc_genl_data_init(&dev->genl_data); 701 nfc_genl_data_init(&dev->genl_data);
642 702
703
643 /* first generation must not be 0 */ 704 /* first generation must not be 0 */
644 dev->targets_generation = 1; 705 dev->targets_generation = 1;
645 706
646 dev->activated_target_idx = NFC_TARGET_IDX_NONE;
647
648 if (ops->check_presence) { 707 if (ops->check_presence) {
649 char name[32]; 708 char name[32];
650 init_timer(&dev->check_pres_timer); 709 init_timer(&dev->check_pres_timer);
@@ -662,7 +721,6 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
662 } 721 }
663 } 722 }
664 723
665
666 return dev; 724 return dev;
667} 725}
668EXPORT_SYMBOL(nfc_allocate_device); 726EXPORT_SYMBOL(nfc_allocate_device);