| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * PS3 device registration routines. |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2007 Sony Computer Entertainment Inc. |
|---|
| 5 | 6 | * Copyright 2007 Sony Corp. |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 8 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 9 | | - * the Free Software Foundation; version 2 of the License. |
|---|
| 10 | | - * |
|---|
| 11 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 12 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 13 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 14 | | - * GNU General Public License for more details. |
|---|
| 15 | | - * |
|---|
| 16 | | - * You should have received a copy of the GNU General Public License |
|---|
| 17 | | - * along with this program; if not, write to the Free Software |
|---|
| 18 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 19 | 7 | */ |
|---|
| 20 | 8 | |
|---|
| 21 | 9 | #include <linux/delay.h> |
|---|
| .. | .. |
|---|
| 25 | 13 | #include <linux/init.h> |
|---|
| 26 | 14 | #include <linux/slab.h> |
|---|
| 27 | 15 | #include <linux/reboot.h> |
|---|
| 16 | +#include <linux/rcuwait.h> |
|---|
| 28 | 17 | |
|---|
| 29 | 18 | #include <asm/firmware.h> |
|---|
| 30 | 19 | #include <asm/lv1call.h> |
|---|
| .. | .. |
|---|
| 354 | 343 | repo->dev_index, repo->dev_type, port, blk_size, num_blocks, |
|---|
| 355 | 344 | num_regions); |
|---|
| 356 | 345 | |
|---|
| 357 | | - p = kzalloc(sizeof(struct ps3_storage_device) + |
|---|
| 358 | | - num_regions * sizeof(struct ps3_storage_region), |
|---|
| 359 | | - GFP_KERNEL); |
|---|
| 346 | + p = kzalloc(struct_size(p, regions, num_regions), GFP_KERNEL); |
|---|
| 360 | 347 | if (!p) { |
|---|
| 361 | 348 | result = -ENOMEM; |
|---|
| 362 | 349 | goto fail_malloc; |
|---|
| .. | .. |
|---|
| 684 | 671 | spinlock_t lock; |
|---|
| 685 | 672 | u64 tag; |
|---|
| 686 | 673 | u64 lv1_status; |
|---|
| 687 | | - struct completion done; |
|---|
| 674 | + struct rcuwait wait; |
|---|
| 675 | + bool done; |
|---|
| 688 | 676 | }; |
|---|
| 689 | 677 | |
|---|
| 690 | 678 | enum ps3_notify_type { |
|---|
| .. | .. |
|---|
| 726 | 714 | pr_debug("%s:%u: completed, status 0x%llx\n", __func__, |
|---|
| 727 | 715 | __LINE__, status); |
|---|
| 728 | 716 | dev->lv1_status = status; |
|---|
| 729 | | - complete(&dev->done); |
|---|
| 717 | + dev->done = true; |
|---|
| 718 | + rcuwait_wake_up(&dev->wait); |
|---|
| 730 | 719 | } |
|---|
| 731 | 720 | spin_unlock(&dev->lock); |
|---|
| 732 | 721 | return IRQ_HANDLED; |
|---|
| .. | .. |
|---|
| 739 | 728 | unsigned long flags; |
|---|
| 740 | 729 | int res; |
|---|
| 741 | 730 | |
|---|
| 742 | | - init_completion(&dev->done); |
|---|
| 743 | 731 | spin_lock_irqsave(&dev->lock, flags); |
|---|
| 744 | 732 | res = write ? lv1_storage_write(dev->sbd.dev_id, 0, 0, 1, 0, lpar, |
|---|
| 745 | 733 | &dev->tag) |
|---|
| 746 | 734 | : lv1_storage_read(dev->sbd.dev_id, 0, 0, 1, 0, lpar, |
|---|
| 747 | 735 | &dev->tag); |
|---|
| 736 | + dev->done = false; |
|---|
| 748 | 737 | spin_unlock_irqrestore(&dev->lock, flags); |
|---|
| 749 | 738 | if (res) { |
|---|
| 750 | 739 | pr_err("%s:%u: %s failed %d\n", __func__, __LINE__, op, res); |
|---|
| .. | .. |
|---|
| 752 | 741 | } |
|---|
| 753 | 742 | pr_debug("%s:%u: notification %s issued\n", __func__, __LINE__, op); |
|---|
| 754 | 743 | |
|---|
| 755 | | - res = swait_event_interruptible_exclusive(dev->done.wait, |
|---|
| 756 | | - dev->done.done || kthread_should_stop()); |
|---|
| 744 | + rcuwait_wait_event(&dev->wait, dev->done || kthread_should_stop(), TASK_IDLE); |
|---|
| 745 | + |
|---|
| 757 | 746 | if (kthread_should_stop()) |
|---|
| 758 | 747 | res = -EINTR; |
|---|
| 759 | | - if (res) { |
|---|
| 760 | | - pr_debug("%s:%u: interrupted %s\n", __func__, __LINE__, op); |
|---|
| 761 | | - return res; |
|---|
| 762 | | - } |
|---|
| 763 | 748 | |
|---|
| 764 | 749 | if (dev->lv1_status) { |
|---|
| 765 | 750 | pr_err("%s:%u: %s not completed, status 0x%llx\n", __func__, |
|---|
| .. | .. |
|---|
| 824 | 809 | } |
|---|
| 825 | 810 | |
|---|
| 826 | 811 | spin_lock_init(&dev.lock); |
|---|
| 812 | + rcuwait_init(&dev.wait); |
|---|
| 827 | 813 | |
|---|
| 828 | 814 | res = request_irq(irq, ps3_notification_interrupt, 0, |
|---|
| 829 | 815 | "ps3_notification", &dev); |
|---|