Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/ps3: Convert half completion to rcuwait

The PS3 notification interrupt and kthread use a hacked up completion to
communicate. Since we're wanting to change the completion implementation and
this is abuse anyway, replace it with a simple rcuwait since there is only ever
the one waiter.

AFAICT the kthread uses TASK_INTERRUPTIBLE to not increase loadavg, kthreads
cannot receive signals by default and this one doesn't look different. Use
TASK_IDLE instead.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/20200321113241.930037873@linutronix.de

+9 -9
+9 -9
arch/powerpc/platforms/ps3/device-init.c
··· 13 13 #include <linux/init.h> 14 14 #include <linux/slab.h> 15 15 #include <linux/reboot.h> 16 + #include <linux/rcuwait.h> 16 17 17 18 #include <asm/firmware.h> 18 19 #include <asm/lv1call.h> ··· 671 670 spinlock_t lock; 672 671 u64 tag; 673 672 u64 lv1_status; 674 - struct completion done; 673 + struct rcuwait wait; 674 + bool done; 675 675 }; 676 676 677 677 enum ps3_notify_type { ··· 714 712 pr_debug("%s:%u: completed, status 0x%llx\n", __func__, 715 713 __LINE__, status); 716 714 dev->lv1_status = status; 717 - complete(&dev->done); 715 + dev->done = true; 716 + rcuwait_wake_up(&dev->wait); 718 717 } 719 718 spin_unlock(&dev->lock); 720 719 return IRQ_HANDLED; ··· 728 725 unsigned long flags; 729 726 int res; 730 727 731 - init_completion(&dev->done); 732 728 spin_lock_irqsave(&dev->lock, flags); 733 729 res = write ? lv1_storage_write(dev->sbd.dev_id, 0, 0, 1, 0, lpar, 734 730 &dev->tag) 735 731 : lv1_storage_read(dev->sbd.dev_id, 0, 0, 1, 0, lpar, 736 732 &dev->tag); 733 + dev->done = false; 737 734 spin_unlock_irqrestore(&dev->lock, flags); 738 735 if (res) { 739 736 pr_err("%s:%u: %s failed %d\n", __func__, __LINE__, op, res); ··· 741 738 } 742 739 pr_debug("%s:%u: notification %s issued\n", __func__, __LINE__, op); 743 740 744 - res = wait_event_interruptible(dev->done.wait, 745 - dev->done.done || kthread_should_stop()); 741 + rcuwait_wait_event(&dev->wait, dev->done || kthread_should_stop(), TASK_IDLE); 742 + 746 743 if (kthread_should_stop()) 747 744 res = -EINTR; 748 - if (res) { 749 - pr_debug("%s:%u: interrupted %s\n", __func__, __LINE__, op); 750 - return res; 751 - } 752 745 753 746 if (dev->lv1_status) { 754 747 pr_err("%s:%u: %s not completed, status 0x%llx\n", __func__, ··· 809 810 } 810 811 811 812 spin_lock_init(&dev.lock); 813 + rcuwait_init(&dev.wait); 812 814 813 815 res = request_irq(irq, ps3_notification_interrupt, 0, 814 816 "ps3_notification", &dev);