aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwqueue/hwqueue_core.c')
-rw-r--r--drivers/hwqueue/hwqueue_core.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/drivers/hwqueue/hwqueue_core.c b/drivers/hwqueue/hwqueue_core.c
index c6d3d54e31e..204c8391d4d 100644
--- a/drivers/hwqueue/hwqueue_core.c
+++ b/drivers/hwqueue/hwqueue_core.c
@@ -134,6 +134,7 @@ int hwqueue_device_register(struct hwqueue_device *hdev)
134 setup_timer(&inst->poll_timer, __hwqueue_poll, 134 setup_timer(&inst->poll_timer, __hwqueue_poll,
135 (unsigned long)inst); 135 (unsigned long)inst);
136 init_waitqueue_head(&inst->wait); 136 init_waitqueue_head(&inst->wait);
137 spin_lock_init(&inst->lock);
137 } 138 }
138 139
139 list_add(&hdev->list, &hwqueue_devices); 140 list_add(&hdev->list, &hwqueue_devices);
@@ -492,6 +493,7 @@ int hwqueue_enable_notifier(struct hwqueue *qh)
492 struct hwqueue_instance *inst = qh->inst; 493 struct hwqueue_instance *inst = qh->inst;
493 struct hwqueue_device *hdev = inst->hdev; 494 struct hwqueue_device *hdev = inst->hdev;
494 bool first; 495 bool first;
496 unsigned long flags;
495 497
496 if (!hwqueue_is_readable(qh)) 498 if (!hwqueue_is_readable(qh))
497 return -EINVAL; 499 return -EINVAL;
@@ -499,16 +501,21 @@ int hwqueue_enable_notifier(struct hwqueue *qh)
499 if (WARN_ON(!qh->notifier_fn)) 501 if (WARN_ON(!qh->notifier_fn))
500 return -EINVAL; 502 return -EINVAL;
501 503
504 /* Protect against interrupt delivery */
505 spin_lock_irqsave(&inst->lock, flags);
506
502 /* Adjust the per handle notifier count */ 507 /* Adjust the per handle notifier count */
503 first = (atomic_inc_return(&qh->notifier_enabled) == 1); 508 first = (atomic_inc_return(&qh->notifier_enabled) == 1);
504 if (!first) 509 if (!first)
505 return 0; /* nothing to do */ 510 goto unlock; /* nothing to do */
506 511
507 /* Now adjust the per instance notifier count */ 512 /* Now adjust the per instance notifier count */
508 first = (atomic_inc_return(&inst->num_notifiers) == 1); 513 first = (atomic_inc_return(&inst->num_notifiers) == 1);
509 if (first) 514 if (first)
510 hdev->ops->set_notify(inst, true); 515 hdev->ops->set_notify(inst, true);
511 516
517unlock:
518 spin_unlock_irqrestore(&inst->lock, flags);
512 return 0; 519 return 0;
513} 520}
514EXPORT_SYMBOL(hwqueue_enable_notifier); 521EXPORT_SYMBOL(hwqueue_enable_notifier);
@@ -524,18 +531,24 @@ int hwqueue_disable_notifier(struct hwqueue *qh)
524 struct hwqueue_instance *inst = qh->inst; 531 struct hwqueue_instance *inst = qh->inst;
525 struct hwqueue_device *hdev = inst->hdev; 532 struct hwqueue_device *hdev = inst->hdev;
526 bool last; 533 bool last;
534 unsigned long flags;
527 535
528 if (!hwqueue_is_readable(qh)) 536 if (!hwqueue_is_readable(qh))
529 return -EINVAL; 537 return -EINVAL;
530 538
539 /* Protect against interrupt delivery */
540 spin_lock_irqsave(&inst->lock, flags);
541
531 last = (atomic_dec_return(&qh->notifier_enabled) == 0); 542 last = (atomic_dec_return(&qh->notifier_enabled) == 0);
532 if (!last) 543 if (!last)
533 return 0; /* nothing to do */ 544 goto unlock; /* nothing to do */
534 545
535 last = (atomic_dec_return(&inst->num_notifiers) == 0); 546 last = (atomic_dec_return(&inst->num_notifiers) == 0);
536 if (last) 547 if (last)
537 hdev->ops->set_notify(inst, false); 548 hdev->ops->set_notify(inst, false);
538 549
550unlock:
551 spin_unlock_irqrestore(&inst->lock, flags);
539 return 0; 552 return 0;
540} 553}
541EXPORT_SYMBOL(hwqueue_disable_notifier); 554EXPORT_SYMBOL(hwqueue_disable_notifier);
@@ -619,11 +632,18 @@ EXPORT_SYMBOL(__hwqueue_pop_slow);
619void hwqueue_notify(struct hwqueue_instance *inst) 632void hwqueue_notify(struct hwqueue_instance *inst)
620{ 633{
621 struct hwqueue *qh; 634 struct hwqueue *qh;
635 unsigned long flags;
636 bool enabled;
622 637
623 rcu_read_lock(); 638 rcu_read_lock();
624 639
625 for_each_handle_rcu(qh, inst) { 640 for_each_handle_rcu(qh, inst) {
626 if (atomic_read(&qh->notifier_enabled) <= 0) 641 /* Synchronize against enable/disable notifier */
642 spin_lock_irqsave(&inst->lock, flags);
643 enabled = atomic_read(&qh->notifier_enabled) > 0;
644 spin_unlock_irqrestore(&inst->lock, flags);
645
646 if (!enabled)
627 continue; 647 continue;
628 if (WARN_ON(!qh->notifier_fn)) 648 if (WARN_ON(!qh->notifier_fn))
629 continue; 649 continue;