+++ /dev/null
-From 2ccd42b959aaf490333dbd3b9b102eaf295c036a Mon Sep 17 00:00:00 2001
-From: David Hildenbrand <david@redhat.com>
-Date: Wed, 2 Apr 2025 22:36:21 +0200
-Subject: s390/virtio_ccw: Don't allocate/assign airqs for non-existing queues
-
-From: David Hildenbrand <david@redhat.com>
-
-commit 2ccd42b959aaf490333dbd3b9b102eaf295c036a upstream.
-
-If we finds a vq without a name in our input array in
-virtio_ccw_find_vqs(), we treat it as "non-existing" and set the vq pointer
-to NULL; we will not call virtio_ccw_setup_vq() to allocate/setup a vq.
-
-Consequently, we create only a queue if it actually exists (name != NULL)
-and assign an incremental queue index to each such existing queue.
-
-However, in virtio_ccw_register_adapter_ind()->get_airq_indicator() we
-will not ignore these "non-existing queues", but instead assign an airq
-indicator to them.
-
-Besides never releasing them in virtio_ccw_drop_indicators() (because
-there is no virtqueue), the bigger issue seems to be that there will be a
-disagreement between the device and the Linux guest about the airq
-indicator to be used for notifying a queue, because the indicator bit
-for adapter I/O interrupt is derived from the queue index.
-
-The virtio spec states under "Setting Up Two-Stage Queue Indicators":
-
- ... indicator contains the guest address of an area wherein the
- indicators for the devices are contained, starting at bit_nr, one
- bit per virtqueue of the device.
-
-And further in "Notification via Adapter I/O Interrupts":
-
- For notifying the driver of virtqueue buffers, the device sets the
- bit in the guest-provided indicator area at the corresponding
- offset.
-
-For example, QEMU uses in virtio_ccw_notify() the queue index (passed as
-"vector") to select the relevant indicator bit. If a queue does not exist,
-it does not have a corresponding indicator bit assigned, because it
-effectively doesn't have a queue index.
-
-Using a virtio-balloon-ccw device under QEMU with free-page-hinting
-disabled ("free-page-hint=off") but free-page-reporting enabled
-("free-page-reporting=on") will result in free page reporting
-not working as expected: in the virtio_balloon driver, we'll be stuck
-forever in virtballoon_free_page_report()->wait_event(), because the
-waitqueue will not be woken up as the notification from the device is
-lost: it would use the wrong indicator bit.
-
-Free page reporting stops working and we get splats (when configured to
-detect hung wqs) like:
-
- INFO: task kworker/1:3:463 blocked for more than 61 seconds.
- Not tainted 6.14.0 #4
- "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
- task:kworker/1:3 [...]
- Workqueue: events page_reporting_process
- Call Trace:
- [<000002f404e6dfb2>] __schedule+0x402/0x1640
- [<000002f404e6f22e>] schedule+0x3e/0xe0
- [<000002f3846a88fa>] virtballoon_free_page_report+0xaa/0x110 [virtio_balloon]
- [<000002f40435c8a4>] page_reporting_process+0x2e4/0x740
- [<000002f403fd3ee2>] process_one_work+0x1c2/0x400
- [<000002f403fd4b96>] worker_thread+0x296/0x420
- [<000002f403fe10b4>] kthread+0x124/0x290
- [<000002f403f4e0dc>] __ret_from_fork+0x3c/0x60
- [<000002f404e77272>] ret_from_fork+0xa/0x38
-
-There was recently a discussion [1] whether the "holes" should be
-treated differently again, effectively assigning also non-existing
-queues a queue index: that should also fix the issue, but requires other
-workarounds to not break existing setups.
-
-Let's fix it without affecting existing setups for now by properly ignoring
-the non-existing queues, so the indicator bits will match the queue
-indexes.
-
-[1] https://lore.kernel.org/all/cover.1720611677.git.mst@redhat.com/
-
-Fixes: a229989d975e ("virtio: don't allocate vqs when names[i] = NULL")
-Reported-by: Chandra Merla <cmerla@redhat.com>
-Cc: stable@vger.kernel.org
-Signed-off-by: David Hildenbrand <david@redhat.com>
-Tested-by: Thomas Huth <thuth@redhat.com>
-Reviewed-by: Thomas Huth <thuth@redhat.com>
-Reviewed-by: Cornelia Huck <cohuck@redhat.com>
-Acked-by: Michael S. Tsirkin <mst@redhat.com>
-Acked-by: Christian Borntraeger <borntraeger@linux.ibm.com>
-Link: https://lore.kernel.org/r/20250402203621.940090-1-david@redhat.com
-Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
-Signed-off-by: David Hildenbrand <david@redhat.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/s390/virtio/virtio_ccw.c | 16 ++++++++++++----
- 1 file changed, 12 insertions(+), 4 deletions(-)
-
---- a/drivers/s390/virtio/virtio_ccw.c
-+++ b/drivers/s390/virtio/virtio_ccw.c
-@@ -261,11 +261,17 @@ static struct airq_info *new_airq_info(i
- static unsigned long get_airq_indicator(struct virtqueue *vqs[], int nvqs,
- u64 *first, void **airq_info)
- {
-- int i, j;
-+ int i, j, queue_idx, highest_queue_idx = -1;
- struct airq_info *info;
- unsigned long indicator_addr = 0;
- unsigned long bit, flags;
-
-+ /* Array entries without an actual queue pointer must be ignored. */
-+ for (i = 0; i < nvqs; i++) {
-+ if (vqs[i])
-+ highest_queue_idx++;
-+ }
-+
- for (i = 0; i < MAX_AIRQ_AREAS && !indicator_addr; i++) {
- mutex_lock(&airq_areas_lock);
- if (!airq_areas[i])
-@@ -275,7 +281,7 @@ static unsigned long get_airq_indicator(
- if (!info)
- return 0;
- write_lock_irqsave(&info->lock, flags);
-- bit = airq_iv_alloc(info->aiv, nvqs);
-+ bit = airq_iv_alloc(info->aiv, highest_queue_idx + 1);
- if (bit == -1UL) {
- /* Not enough vacancies. */
- write_unlock_irqrestore(&info->lock, flags);
-@@ -284,8 +290,10 @@ static unsigned long get_airq_indicator(
- *first = bit;
- *airq_info = info;
- indicator_addr = (unsigned long)info->aiv->vector;
-- for (j = 0; j < nvqs; j++) {
-- airq_iv_set_ptr(info->aiv, bit + j,
-+ for (j = 0, queue_idx = 0; j < nvqs; j++) {
-+ if (!vqs[j])
-+ continue;
-+ airq_iv_set_ptr(info->aiv, bit + queue_idx++,
- (unsigned long)vqs[j]);
- }
- write_unlock_irqrestore(&info->lock, flags);
ext4-make-block-validity-check-resistent-to-sb-bh-co.patch
scsi-pm80xx-set-phy_attached-to-zero-when-device-is-.patch
md-raid1-add-check-for-missing-source-disk-in-proces.patch
-s390-virtio_ccw-don-t-allocate-assign-airqs-for-non-existing-queues.patch
comedi-jr3_pci-fix-synchronous-deletion-of-timer.patch
crypto-atmel-sha204a-set-hwrng-quality-to-lowest-possible.patch
xdp-reset-bpf_redirect_info-before-running-a-xdp-s-bpf-prog.patch
+++ /dev/null
-From 2ccd42b959aaf490333dbd3b9b102eaf295c036a Mon Sep 17 00:00:00 2001
-From: David Hildenbrand <david@redhat.com>
-Date: Wed, 2 Apr 2025 22:36:21 +0200
-Subject: s390/virtio_ccw: Don't allocate/assign airqs for non-existing queues
-
-From: David Hildenbrand <david@redhat.com>
-
-commit 2ccd42b959aaf490333dbd3b9b102eaf295c036a upstream.
-
-If we finds a vq without a name in our input array in
-virtio_ccw_find_vqs(), we treat it as "non-existing" and set the vq pointer
-to NULL; we will not call virtio_ccw_setup_vq() to allocate/setup a vq.
-
-Consequently, we create only a queue if it actually exists (name != NULL)
-and assign an incremental queue index to each such existing queue.
-
-However, in virtio_ccw_register_adapter_ind()->get_airq_indicator() we
-will not ignore these "non-existing queues", but instead assign an airq
-indicator to them.
-
-Besides never releasing them in virtio_ccw_drop_indicators() (because
-there is no virtqueue), the bigger issue seems to be that there will be a
-disagreement between the device and the Linux guest about the airq
-indicator to be used for notifying a queue, because the indicator bit
-for adapter I/O interrupt is derived from the queue index.
-
-The virtio spec states under "Setting Up Two-Stage Queue Indicators":
-
- ... indicator contains the guest address of an area wherein the
- indicators for the devices are contained, starting at bit_nr, one
- bit per virtqueue of the device.
-
-And further in "Notification via Adapter I/O Interrupts":
-
- For notifying the driver of virtqueue buffers, the device sets the
- bit in the guest-provided indicator area at the corresponding
- offset.
-
-For example, QEMU uses in virtio_ccw_notify() the queue index (passed as
-"vector") to select the relevant indicator bit. If a queue does not exist,
-it does not have a corresponding indicator bit assigned, because it
-effectively doesn't have a queue index.
-
-Using a virtio-balloon-ccw device under QEMU with free-page-hinting
-disabled ("free-page-hint=off") but free-page-reporting enabled
-("free-page-reporting=on") will result in free page reporting
-not working as expected: in the virtio_balloon driver, we'll be stuck
-forever in virtballoon_free_page_report()->wait_event(), because the
-waitqueue will not be woken up as the notification from the device is
-lost: it would use the wrong indicator bit.
-
-Free page reporting stops working and we get splats (when configured to
-detect hung wqs) like:
-
- INFO: task kworker/1:3:463 blocked for more than 61 seconds.
- Not tainted 6.14.0 #4
- "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
- task:kworker/1:3 [...]
- Workqueue: events page_reporting_process
- Call Trace:
- [<000002f404e6dfb2>] __schedule+0x402/0x1640
- [<000002f404e6f22e>] schedule+0x3e/0xe0
- [<000002f3846a88fa>] virtballoon_free_page_report+0xaa/0x110 [virtio_balloon]
- [<000002f40435c8a4>] page_reporting_process+0x2e4/0x740
- [<000002f403fd3ee2>] process_one_work+0x1c2/0x400
- [<000002f403fd4b96>] worker_thread+0x296/0x420
- [<000002f403fe10b4>] kthread+0x124/0x290
- [<000002f403f4e0dc>] __ret_from_fork+0x3c/0x60
- [<000002f404e77272>] ret_from_fork+0xa/0x38
-
-There was recently a discussion [1] whether the "holes" should be
-treated differently again, effectively assigning also non-existing
-queues a queue index: that should also fix the issue, but requires other
-workarounds to not break existing setups.
-
-Let's fix it without affecting existing setups for now by properly ignoring
-the non-existing queues, so the indicator bits will match the queue
-indexes.
-
-[1] https://lore.kernel.org/all/cover.1720611677.git.mst@redhat.com/
-
-Fixes: a229989d975e ("virtio: don't allocate vqs when names[i] = NULL")
-Reported-by: Chandra Merla <cmerla@redhat.com>
-Cc: stable@vger.kernel.org
-Signed-off-by: David Hildenbrand <david@redhat.com>
-Tested-by: Thomas Huth <thuth@redhat.com>
-Reviewed-by: Thomas Huth <thuth@redhat.com>
-Reviewed-by: Cornelia Huck <cohuck@redhat.com>
-Acked-by: Michael S. Tsirkin <mst@redhat.com>
-Acked-by: Christian Borntraeger <borntraeger@linux.ibm.com>
-Link: https://lore.kernel.org/r/20250402203621.940090-1-david@redhat.com
-Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
-Signed-off-by: David Hildenbrand <david@redhat.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/s390/virtio/virtio_ccw.c | 16 ++++++++++++----
- 1 file changed, 12 insertions(+), 4 deletions(-)
-
---- a/drivers/s390/virtio/virtio_ccw.c
-+++ b/drivers/s390/virtio/virtio_ccw.c
-@@ -261,11 +261,17 @@ static struct airq_info *new_airq_info(i
- static unsigned long get_airq_indicator(struct virtqueue *vqs[], int nvqs,
- u64 *first, void **airq_info)
- {
-- int i, j;
-+ int i, j, queue_idx, highest_queue_idx = -1;
- struct airq_info *info;
- unsigned long indicator_addr = 0;
- unsigned long bit, flags;
-
-+ /* Array entries without an actual queue pointer must be ignored. */
-+ for (i = 0; i < nvqs; i++) {
-+ if (vqs[i])
-+ highest_queue_idx++;
-+ }
-+
- for (i = 0; i < MAX_AIRQ_AREAS && !indicator_addr; i++) {
- mutex_lock(&airq_areas_lock);
- if (!airq_areas[i])
-@@ -275,7 +281,7 @@ static unsigned long get_airq_indicator(
- if (!info)
- return 0;
- write_lock_irqsave(&info->lock, flags);
-- bit = airq_iv_alloc(info->aiv, nvqs);
-+ bit = airq_iv_alloc(info->aiv, highest_queue_idx + 1);
- if (bit == -1UL) {
- /* Not enough vacancies. */
- write_unlock_irqrestore(&info->lock, flags);
-@@ -284,8 +290,10 @@ static unsigned long get_airq_indicator(
- *first = bit;
- *airq_info = info;
- indicator_addr = (unsigned long)info->aiv->vector;
-- for (j = 0; j < nvqs; j++) {
-- airq_iv_set_ptr(info->aiv, bit + j,
-+ for (j = 0, queue_idx = 0; j < nvqs; j++) {
-+ if (!vqs[j])
-+ continue;
-+ airq_iv_set_ptr(info->aiv, bit + queue_idx++,
- (unsigned long)vqs[j]);
- }
- write_unlock_irqrestore(&info->lock, flags);
loop-aio-inherit-the-ioprio-of-original-request.patch
ubsan-fix-panic-from-test_ubsan_out_of_bounds.patch
md-raid1-add-check-for-missing-source-disk-in-proces.patch
-s390-virtio_ccw-don-t-allocate-assign-airqs-for-non-existing-queues.patch
jfs-define-xtree-root-and-page-independently.patch
comedi-jr3_pci-fix-synchronous-deletion-of-timer.patch
crypto-atmel-sha204a-set-hwrng-quality-to-lowest-possible.patch
+++ /dev/null
-From 2ccd42b959aaf490333dbd3b9b102eaf295c036a Mon Sep 17 00:00:00 2001
-From: David Hildenbrand <david@redhat.com>
-Date: Wed, 2 Apr 2025 22:36:21 +0200
-Subject: s390/virtio_ccw: Don't allocate/assign airqs for non-existing queues
-
-From: David Hildenbrand <david@redhat.com>
-
-commit 2ccd42b959aaf490333dbd3b9b102eaf295c036a upstream.
-
-If we finds a vq without a name in our input array in
-virtio_ccw_find_vqs(), we treat it as "non-existing" and set the vq pointer
-to NULL; we will not call virtio_ccw_setup_vq() to allocate/setup a vq.
-
-Consequently, we create only a queue if it actually exists (name != NULL)
-and assign an incremental queue index to each such existing queue.
-
-However, in virtio_ccw_register_adapter_ind()->get_airq_indicator() we
-will not ignore these "non-existing queues", but instead assign an airq
-indicator to them.
-
-Besides never releasing them in virtio_ccw_drop_indicators() (because
-there is no virtqueue), the bigger issue seems to be that there will be a
-disagreement between the device and the Linux guest about the airq
-indicator to be used for notifying a queue, because the indicator bit
-for adapter I/O interrupt is derived from the queue index.
-
-The virtio spec states under "Setting Up Two-Stage Queue Indicators":
-
- ... indicator contains the guest address of an area wherein the
- indicators for the devices are contained, starting at bit_nr, one
- bit per virtqueue of the device.
-
-And further in "Notification via Adapter I/O Interrupts":
-
- For notifying the driver of virtqueue buffers, the device sets the
- bit in the guest-provided indicator area at the corresponding
- offset.
-
-For example, QEMU uses in virtio_ccw_notify() the queue index (passed as
-"vector") to select the relevant indicator bit. If a queue does not exist,
-it does not have a corresponding indicator bit assigned, because it
-effectively doesn't have a queue index.
-
-Using a virtio-balloon-ccw device under QEMU with free-page-hinting
-disabled ("free-page-hint=off") but free-page-reporting enabled
-("free-page-reporting=on") will result in free page reporting
-not working as expected: in the virtio_balloon driver, we'll be stuck
-forever in virtballoon_free_page_report()->wait_event(), because the
-waitqueue will not be woken up as the notification from the device is
-lost: it would use the wrong indicator bit.
-
-Free page reporting stops working and we get splats (when configured to
-detect hung wqs) like:
-
- INFO: task kworker/1:3:463 blocked for more than 61 seconds.
- Not tainted 6.14.0 #4
- "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
- task:kworker/1:3 [...]
- Workqueue: events page_reporting_process
- Call Trace:
- [<000002f404e6dfb2>] __schedule+0x402/0x1640
- [<000002f404e6f22e>] schedule+0x3e/0xe0
- [<000002f3846a88fa>] virtballoon_free_page_report+0xaa/0x110 [virtio_balloon]
- [<000002f40435c8a4>] page_reporting_process+0x2e4/0x740
- [<000002f403fd3ee2>] process_one_work+0x1c2/0x400
- [<000002f403fd4b96>] worker_thread+0x296/0x420
- [<000002f403fe10b4>] kthread+0x124/0x290
- [<000002f403f4e0dc>] __ret_from_fork+0x3c/0x60
- [<000002f404e77272>] ret_from_fork+0xa/0x38
-
-There was recently a discussion [1] whether the "holes" should be
-treated differently again, effectively assigning also non-existing
-queues a queue index: that should also fix the issue, but requires other
-workarounds to not break existing setups.
-
-Let's fix it without affecting existing setups for now by properly ignoring
-the non-existing queues, so the indicator bits will match the queue
-indexes.
-
-[1] https://lore.kernel.org/all/cover.1720611677.git.mst@redhat.com/
-
-Fixes: a229989d975e ("virtio: don't allocate vqs when names[i] = NULL")
-Reported-by: Chandra Merla <cmerla@redhat.com>
-Cc: stable@vger.kernel.org
-Signed-off-by: David Hildenbrand <david@redhat.com>
-Tested-by: Thomas Huth <thuth@redhat.com>
-Reviewed-by: Thomas Huth <thuth@redhat.com>
-Reviewed-by: Cornelia Huck <cohuck@redhat.com>
-Acked-by: Michael S. Tsirkin <mst@redhat.com>
-Acked-by: Christian Borntraeger <borntraeger@linux.ibm.com>
-Link: https://lore.kernel.org/r/20250402203621.940090-1-david@redhat.com
-Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
-Signed-off-by: David Hildenbrand <david@redhat.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/s390/virtio/virtio_ccw.c | 16 ++++++++++++----
- 1 file changed, 12 insertions(+), 4 deletions(-)
-
---- a/drivers/s390/virtio/virtio_ccw.c
-+++ b/drivers/s390/virtio/virtio_ccw.c
-@@ -261,11 +261,17 @@ static struct airq_info *new_airq_info(i
- static unsigned long get_airq_indicator(struct virtqueue *vqs[], int nvqs,
- u64 *first, void **airq_info)
- {
-- int i, j;
-+ int i, j, queue_idx, highest_queue_idx = -1;
- struct airq_info *info;
- unsigned long indicator_addr = 0;
- unsigned long bit, flags;
-
-+ /* Array entries without an actual queue pointer must be ignored. */
-+ for (i = 0; i < nvqs; i++) {
-+ if (vqs[i])
-+ highest_queue_idx++;
-+ }
-+
- for (i = 0; i < MAX_AIRQ_AREAS && !indicator_addr; i++) {
- mutex_lock(&airq_areas_lock);
- if (!airq_areas[i])
-@@ -275,7 +281,7 @@ static unsigned long get_airq_indicator(
- if (!info)
- return 0;
- write_lock_irqsave(&info->lock, flags);
-- bit = airq_iv_alloc(info->aiv, nvqs);
-+ bit = airq_iv_alloc(info->aiv, highest_queue_idx + 1);
- if (bit == -1UL) {
- /* Not enough vacancies. */
- write_unlock_irqrestore(&info->lock, flags);
-@@ -284,8 +290,10 @@ static unsigned long get_airq_indicator(
- *first = bit;
- *airq_info = info;
- indicator_addr = (unsigned long)info->aiv->vector;
-- for (j = 0; j < nvqs; j++) {
-- airq_iv_set_ptr(info->aiv, bit + j,
-+ for (j = 0, queue_idx = 0; j < nvqs; j++) {
-+ if (!vqs[j])
-+ continue;
-+ airq_iv_set_ptr(info->aiv, bit + queue_idx++,
- (unsigned long)vqs[j]);
- }
- write_unlock_irqrestore(&info->lock, flags);
x86-bugs-don-t-fill-rsb-on-vmexit-with-eibrs-retpoli.patch
scsi-pm80xx-set-phy_attached-to-zero-when-device-is-.patch
md-raid1-add-check-for-missing-source-disk-in-proces.patch
-s390-virtio_ccw-don-t-allocate-assign-airqs-for-non-existing-queues.patch
comedi-jr3_pci-fix-synchronous-deletion-of-timer.patch
crypto-atmel-sha204a-set-hwrng-quality-to-lowest-possible.patch
mips-cm-fix-warning-if-mips_cm-is-disabled.patch
+++ /dev/null
-From d254d444ebcd0fc1d68b88dfc8516ff09d26cef5 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 13 Dec 2024 14:47:28 +0100
-Subject: s390/pci: Report PCI error recovery results via SCLP
-
-From: Niklas Schnelle <schnelle@linux.ibm.com>
-
-[ Upstream commit 4ec6054e7321dc24ebccaa08b3af0d590f5666e6 ]
-
-Add a mechanism with which the status of PCI error recovery runs
-is reported to the platform. Together with the status supply additional
-information that may aid in problem determination.
-
-Reviewed-by: Halil Pasic <pasic@linux.ibm.com>
-Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
-Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
-Stable-dep-of: aa9f168d55dc ("s390/pci: Support mmap() of PCI resources except for ISM devices")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- arch/s390/include/asm/sclp.h | 33 +++++++++++
- arch/s390/pci/Makefile | 2 +-
- arch/s390/pci/pci_event.c | 21 +++++--
- arch/s390/pci/pci_report.c | 111 +++++++++++++++++++++++++++++++++++
- arch/s390/pci/pci_report.h | 16 +++++
- drivers/s390/char/sclp.h | 14 -----
- drivers/s390/char/sclp_pci.c | 19 ------
- 7 files changed, 178 insertions(+), 38 deletions(-)
- create mode 100644 arch/s390/pci/pci_report.c
- create mode 100644 arch/s390/pci/pci_report.h
-
-diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h
-index 9d4c7f71e070f..e64dac00e7bf7 100644
---- a/arch/s390/include/asm/sclp.h
-+++ b/arch/s390/include/asm/sclp.h
-@@ -16,6 +16,11 @@
- /* 24 + 16 * SCLP_MAX_CORES */
- #define EXT_SCCB_READ_CPU (3 * PAGE_SIZE)
-
-+#define SCLP_ERRNOTIFY_AQ_RESET 0
-+#define SCLP_ERRNOTIFY_AQ_REPAIR 1
-+#define SCLP_ERRNOTIFY_AQ_INFO_LOG 2
-+#define SCLP_ERRNOTIFY_AQ_OPTICS_DATA 3
-+
- #ifndef __ASSEMBLY__
- #include <linux/uio.h>
- #include <asm/chpid.h>
-@@ -107,6 +112,34 @@ struct sclp_info {
- };
- extern struct sclp_info sclp;
-
-+struct sccb_header {
-+ u16 length;
-+ u8 function_code;
-+ u8 control_mask[3];
-+ u16 response_code;
-+} __packed;
-+
-+struct evbuf_header {
-+ u16 length;
-+ u8 type;
-+ u8 flags;
-+ u16 _reserved;
-+} __packed;
-+
-+struct err_notify_evbuf {
-+ struct evbuf_header header;
-+ u8 action;
-+ u8 atype;
-+ u32 fh;
-+ u32 fid;
-+ u8 data[];
-+} __packed;
-+
-+struct err_notify_sccb {
-+ struct sccb_header header;
-+ struct err_notify_evbuf evbuf;
-+} __packed;
-+
- struct zpci_report_error_header {
- u8 version; /* Interface version byte */
- u8 action; /* Action qualifier byte
-diff --git a/arch/s390/pci/Makefile b/arch/s390/pci/Makefile
-index 5ae31ca9dd441..eeef68901a15c 100644
---- a/arch/s390/pci/Makefile
-+++ b/arch/s390/pci/Makefile
-@@ -5,5 +5,5 @@
-
- obj-$(CONFIG_PCI) += pci.o pci_irq.o pci_dma.o pci_clp.o pci_sysfs.o \
- pci_event.o pci_debug.o pci_insn.o pci_mmio.o \
-- pci_bus.o pci_kvm_hook.o
-+ pci_bus.o pci_kvm_hook.o pci_report.o
- obj-$(CONFIG_PCI_IOV) += pci_iov.o
-diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c
-index b3961f1016ea0..ed8c7f61e642b 100644
---- a/arch/s390/pci/pci_event.c
-+++ b/arch/s390/pci/pci_event.c
-@@ -16,6 +16,7 @@
- #include <asm/sclp.h>
-
- #include "pci_bus.h"
-+#include "pci_report.h"
-
- /* Content Code Description for PCI Function Error */
- struct zpci_ccdf_err {
-@@ -162,6 +163,8 @@ static pci_ers_result_t zpci_event_do_reset(struct pci_dev *pdev,
- static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
- {
- pci_ers_result_t ers_res = PCI_ERS_RESULT_DISCONNECT;
-+ struct zpci_dev *zdev = to_zpci(pdev);
-+ char *status_str = "success";
- struct pci_driver *driver;
-
- /*
-@@ -179,29 +182,37 @@ static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
- if (is_passed_through(to_zpci(pdev))) {
- pr_info("%s: Cannot be recovered in the host because it is a pass-through device\n",
- pci_name(pdev));
-+ status_str = "failed (pass-through)";
- goto out_unlock;
- }
-
- driver = to_pci_driver(pdev->dev.driver);
- if (!is_driver_supported(driver)) {
-- if (!driver)
-+ if (!driver) {
- pr_info("%s: Cannot be recovered because no driver is bound to the device\n",
- pci_name(pdev));
-- else
-+ status_str = "failed (no driver)";
-+ } else {
- pr_info("%s: The %s driver bound to the device does not support error recovery\n",
- pci_name(pdev),
- driver->name);
-+ status_str = "failed (no driver support)";
-+ }
- goto out_unlock;
- }
-
- ers_res = zpci_event_notify_error_detected(pdev, driver);
-- if (ers_result_indicates_abort(ers_res))
-+ if (ers_result_indicates_abort(ers_res)) {
-+ status_str = "failed (abort on detection)";
- goto out_unlock;
-+ }
-
- if (ers_res == PCI_ERS_RESULT_CAN_RECOVER) {
- ers_res = zpci_event_do_error_state_clear(pdev, driver);
-- if (ers_result_indicates_abort(ers_res))
-+ if (ers_result_indicates_abort(ers_res)) {
-+ status_str = "failed (abort on MMIO enable)";
- goto out_unlock;
-+ }
- }
-
- if (ers_res == PCI_ERS_RESULT_NEED_RESET)
-@@ -210,6 +221,7 @@ static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
- if (ers_res != PCI_ERS_RESULT_RECOVERED) {
- pr_err("%s: Automatic recovery failed; operator intervention is required\n",
- pci_name(pdev));
-+ status_str = "failed (driver can't recover)";
- goto out_unlock;
- }
-
-@@ -218,6 +230,7 @@ static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
- driver->err_handler->resume(pdev);
- out_unlock:
- pci_dev_unlock(pdev);
-+ zpci_report_status(zdev, "recovery", status_str);
-
- return ers_res;
- }
-diff --git a/arch/s390/pci/pci_report.c b/arch/s390/pci/pci_report.c
-new file mode 100644
-index 0000000000000..2754c9c161f5b
---- /dev/null
-+++ b/arch/s390/pci/pci_report.c
-@@ -0,0 +1,111 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Copyright IBM Corp. 2024
-+ *
-+ * Author(s):
-+ * Niklas Schnelle <schnelle@linux.ibm.com>
-+ *
-+ */
-+
-+#define KMSG_COMPONENT "zpci"
-+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-+
-+#include <linux/kernel.h>
-+#include <linux/sprintf.h>
-+#include <linux/pci.h>
-+
-+#include <asm/sclp.h>
-+
-+#include "pci_report.h"
-+
-+#define ZPCI_ERR_LOG_ID_KERNEL_REPORT 0x4714
-+
-+struct zpci_report_error_data {
-+ u64 timestamp;
-+ u64 err_log_id;
-+ char log_data[];
-+} __packed;
-+
-+#define ZPCI_REPORT_SIZE (PAGE_SIZE - sizeof(struct err_notify_sccb))
-+#define ZPCI_REPORT_DATA_SIZE (ZPCI_REPORT_SIZE - sizeof(struct zpci_report_error_data))
-+
-+struct zpci_report_error {
-+ struct zpci_report_error_header header;
-+ struct zpci_report_error_data data;
-+} __packed;
-+
-+static const char *zpci_state_str(pci_channel_state_t state)
-+{
-+ switch (state) {
-+ case pci_channel_io_normal:
-+ return "normal";
-+ case pci_channel_io_frozen:
-+ return "frozen";
-+ case pci_channel_io_perm_failure:
-+ return "permanent-failure";
-+ default:
-+ return "invalid";
-+ };
-+}
-+
-+/**
-+ * zpci_report_status - Report the status of operations on a PCI device
-+ * @zdev: The PCI device for which to report status
-+ * @operation: A string representing the operation reported
-+ * @status: A string representing the status of the operation
-+ *
-+ * This function creates a human readable report about an operation such as
-+ * PCI device recovery and forwards this to the platform using the SCLP Write
-+ * Event Data mechanism. Besides the operation and status strings the report
-+ * also contains additional information about the device deemed useful for
-+ * debug such as the currently bound device driver, if any, and error state.
-+ *
-+ * Return: 0 on success an error code < 0 otherwise.
-+ */
-+int zpci_report_status(struct zpci_dev *zdev, const char *operation, const char *status)
-+{
-+ struct zpci_report_error *report;
-+ struct pci_driver *driver = NULL;
-+ struct pci_dev *pdev = NULL;
-+ char *buf, *end;
-+ int ret;
-+
-+ if (!zdev || !zdev->zbus)
-+ return -ENODEV;
-+
-+ /* Protected virtualization hosts get nothing from us */
-+ if (prot_virt_guest)
-+ return -ENODATA;
-+
-+ report = (void *)get_zeroed_page(GFP_KERNEL);
-+ if (!report)
-+ return -ENOMEM;
-+ if (zdev->zbus->bus)
-+ pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn);
-+ if (pdev)
-+ driver = to_pci_driver(pdev->dev.driver);
-+
-+ buf = report->data.log_data;
-+ end = report->data.log_data + ZPCI_REPORT_DATA_SIZE;
-+ buf += scnprintf(buf, end - buf, "report: %s\n", operation);
-+ buf += scnprintf(buf, end - buf, "status: %s\n", status);
-+ buf += scnprintf(buf, end - buf, "state: %s\n",
-+ (pdev) ? zpci_state_str(pdev->error_state) : "n/a");
-+ buf += scnprintf(buf, end - buf, "driver: %s\n", (driver) ? driver->name : "n/a");
-+
-+ report->header.version = 1;
-+ report->header.action = SCLP_ERRNOTIFY_AQ_INFO_LOG;
-+ report->header.length = buf - (char *)&report->data;
-+ report->data.timestamp = ktime_get_clocktai_seconds();
-+ report->data.err_log_id = ZPCI_ERR_LOG_ID_KERNEL_REPORT;
-+
-+ ret = sclp_pci_report(&report->header, zdev->fh, zdev->fid);
-+ if (ret)
-+ pr_err("Reporting PCI status failed with code %d\n", ret);
-+ else
-+ pr_info("Reported PCI device status\n");
-+
-+ free_page((unsigned long)report);
-+
-+ return ret;
-+}
-diff --git a/arch/s390/pci/pci_report.h b/arch/s390/pci/pci_report.h
-new file mode 100644
-index 0000000000000..e08003d51a972
---- /dev/null
-+++ b/arch/s390/pci/pci_report.h
-@@ -0,0 +1,16 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright IBM Corp. 2024
-+ *
-+ * Author(s):
-+ * Niklas Schnelle <schnelle@linux.ibm.com>
-+ *
-+ */
-+#ifndef __S390_PCI_REPORT_H
-+#define __S390_PCI_REPORT_H
-+
-+struct zpci_dev;
-+
-+int zpci_report_status(struct zpci_dev *zdev, const char *operation, const char *status);
-+
-+#endif /* __S390_PCI_REPORT_H */
-diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
-index 86dd2cde0f78b..805f0a1ca687f 100644
---- a/drivers/s390/char/sclp.h
-+++ b/drivers/s390/char/sclp.h
-@@ -84,13 +84,6 @@ typedef unsigned int sclp_cmdw_t;
-
- typedef u64 sccb_mask_t;
-
--struct sccb_header {
-- u16 length;
-- u8 function_code;
-- u8 control_mask[3];
-- u16 response_code;
--} __attribute__((packed));
--
- struct init_sccb {
- struct sccb_header header;
- u16 _reserved;
-@@ -237,13 +230,6 @@ struct gds_vector {
- u16 gds_id;
- } __attribute__((packed));
-
--struct evbuf_header {
-- u16 length;
-- u8 type;
-- u8 flags;
-- u16 _reserved;
--} __attribute__((packed));
--
- struct sclp_req {
- struct list_head list; /* list_head for request queueing. */
- sclp_cmdw_t command; /* sclp command to execute */
-diff --git a/drivers/s390/char/sclp_pci.c b/drivers/s390/char/sclp_pci.c
-index c3466a8c56bb5..56400886f7fca 100644
---- a/drivers/s390/char/sclp_pci.c
-+++ b/drivers/s390/char/sclp_pci.c
-@@ -24,30 +24,11 @@
-
- #define SCLP_ATYPE_PCI 2
-
--#define SCLP_ERRNOTIFY_AQ_RESET 0
--#define SCLP_ERRNOTIFY_AQ_REPAIR 1
--#define SCLP_ERRNOTIFY_AQ_INFO_LOG 2
--#define SCLP_ERRNOTIFY_AQ_OPTICS_DATA 3
--
- static DEFINE_MUTEX(sclp_pci_mutex);
- static struct sclp_register sclp_pci_event = {
- .send_mask = EVTYP_ERRNOTIFY_MASK,
- };
-
--struct err_notify_evbuf {
-- struct evbuf_header header;
-- u8 action;
-- u8 atype;
-- u32 fh;
-- u32 fid;
-- u8 data[];
--} __packed;
--
--struct err_notify_sccb {
-- struct sccb_header header;
-- struct err_notify_evbuf evbuf;
--} __packed;
--
- struct pci_cfg_sccb {
- struct sccb_header header;
- u8 atype; /* adapter type */
---
-2.39.5
-
+++ /dev/null
-From fef357f4fd69df1dd912eb0caf083d0ca75a85a4 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 26 Feb 2025 13:07:47 +0100
-Subject: s390/pci: Support mmap() of PCI resources except for ISM devices
-
-From: Niklas Schnelle <schnelle@linux.ibm.com>
-
-[ Upstream commit aa9f168d55dc47c0de564f7dfe0e90467c9fee71 ]
-
-So far s390 does not allow mmap() of PCI resources to user-space via the
-usual mechanisms, though it does use it for RDMA. For the PCI sysfs
-resource files and /proc/bus/pci it defines neither HAVE_PCI_MMAP nor
-ARCH_GENERIC_PCI_MMAP_RESOURCE. For vfio-pci s390 previously relied on
-disabled VFIO_PCI_MMAP and now relies on setting pdev->non_mappable_bars
-for all devices.
-
-This is partly because access to mapped PCI resources from user-space
-requires special PCI load/store memory-I/O (MIO) instructions, or the
-special MMIO syscalls when these are not available. Still, such access is
-possible and useful not just for RDMA, in fact not being able to mmap() PCI
-resources has previously caused extra work when testing devices.
-
-One thing that doesn't work with PCI resources mapped to user-space though
-is the s390 specific virtual ISM device. Not only because the BAR size of
-256 TiB prevents mapping the whole BAR but also because access requires use
-of the legacy PCI instructions which are not accessible to user-space on
-systems with the newer MIO PCI instructions.
-
-Now with the pdev->non_mappable_bars flag ISM can be excluded from mapping
-its resources while making this functionality available for all other PCI
-devices. To this end introduce a minimal implementation of PCI_QUIRKS and
-use that to set pdev->non_mappable_bars for ISM devices only. Then also set
-ARCH_GENERIC_PCI_MMAP_RESOURCE to take advantage of the generic
-implementation of pci_mmap_resource_range() enabling only the newer sysfs
-mmap() interface. This follows the recommendation in
-Documentation/PCI/sysfs-pci.rst.
-
-Link: https://lore.kernel.org/r/20250226-vfio_pci_mmap-v7-3-c5c0f1d26efd@linux.ibm.com
-Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
-Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- arch/s390/Kconfig | 4 +---
- arch/s390/include/asm/pci.h | 3 +++
- arch/s390/pci/Makefile | 2 +-
- arch/s390/pci/pci_fixup.c | 23 +++++++++++++++++++++++
- drivers/s390/net/ism_drv.c | 1 -
- include/linux/pci_ids.h | 1 +
- 6 files changed, 29 insertions(+), 5 deletions(-)
- create mode 100644 arch/s390/pci/pci_fixup.c
-
-diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
-index de575af02ffea..50a4a878bae6d 100644
---- a/arch/s390/Kconfig
-+++ b/arch/s390/Kconfig
-@@ -38,9 +38,6 @@ config AUDIT_ARCH
- config NO_IOPORT_MAP
- def_bool y
-
--config PCI_QUIRKS
-- def_bool n
--
- config ARCH_SUPPORTS_UPROBES
- def_bool y
-
-@@ -213,6 +210,7 @@ config S390
- select PCI_DOMAINS if PCI
- select PCI_MSI if PCI
- select PCI_MSI_ARCH_FALLBACKS if PCI_MSI
-+ select PCI_QUIRKS if PCI
- select SPARSE_IRQ
- select SWIOTLB
- select SYSCTL_EXCEPTION_TRACE
-diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
-index 108e732d7b140..a4e9a6ecbd437 100644
---- a/arch/s390/include/asm/pci.h
-+++ b/arch/s390/include/asm/pci.h
-@@ -11,6 +11,9 @@
- #include <asm/pci_insn.h>
- #include <asm/sclp.h>
-
-+#define ARCH_GENERIC_PCI_MMAP_RESOURCE 1
-+#define arch_can_pci_mmap_wc() 1
-+
- #define PCIBIOS_MIN_IO 0x1000
- #define PCIBIOS_MIN_MEM 0x10000000
-
-diff --git a/arch/s390/pci/Makefile b/arch/s390/pci/Makefile
-index eeef68901a15c..2f8dd3f688391 100644
---- a/arch/s390/pci/Makefile
-+++ b/arch/s390/pci/Makefile
-@@ -5,5 +5,5 @@
-
- obj-$(CONFIG_PCI) += pci.o pci_irq.o pci_dma.o pci_clp.o pci_sysfs.o \
- pci_event.o pci_debug.o pci_insn.o pci_mmio.o \
-- pci_bus.o pci_kvm_hook.o pci_report.o
-+ pci_bus.o pci_kvm_hook.o pci_report.o pci_fixup.o
- obj-$(CONFIG_PCI_IOV) += pci_iov.o
-diff --git a/arch/s390/pci/pci_fixup.c b/arch/s390/pci/pci_fixup.c
-new file mode 100644
-index 0000000000000..35688b6450983
---- /dev/null
-+++ b/arch/s390/pci/pci_fixup.c
-@@ -0,0 +1,23 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Exceptions for specific devices,
-+ *
-+ * Copyright IBM Corp. 2025
-+ *
-+ * Author(s):
-+ * Niklas Schnelle <schnelle@linux.ibm.com>
-+ */
-+#include <linux/pci.h>
-+
-+static void zpci_ism_bar_no_mmap(struct pci_dev *pdev)
-+{
-+ /*
-+ * ISM's BAR is special. Drivers written for ISM know
-+ * how to handle this but others need to be aware of their
-+ * special nature e.g. to prevent attempts to mmap() it.
-+ */
-+ pdev->non_mappable_bars = 1;
-+}
-+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_IBM,
-+ PCI_DEVICE_ID_IBM_ISM,
-+ zpci_ism_bar_no_mmap);
-diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c
-index d34bb6ec1490f..c0e94e3fd6995 100644
---- a/drivers/s390/net/ism_drv.c
-+++ b/drivers/s390/net/ism_drv.c
-@@ -24,7 +24,6 @@
- MODULE_DESCRIPTION("ISM driver for s390");
- MODULE_LICENSE("GPL");
-
--#define PCI_DEVICE_ID_IBM_ISM 0x04ED
- #define DRV_NAME "ism"
-
- static const struct pci_device_id ism_device_table[] = {
-diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
-index 9d7fb137bd939..db9f01db0ce8d 100644
---- a/include/linux/pci_ids.h
-+++ b/include/linux/pci_ids.h
-@@ -509,6 +509,7 @@
- #define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM 0x0251
- #define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM_PCIE 0x0361
- #define PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL 0x252
-+#define PCI_DEVICE_ID_IBM_ISM 0x04ed
-
- #define PCI_SUBVENDOR_ID_IBM 0x1014
- #define PCI_SUBDEVICE_ID_IBM_SATURN_SERIAL_ONE_PORT 0x03d4
---
-2.39.5
-
+++ /dev/null
-From b4978abba91d51e4fb7d5564561dc1c066003825 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 1 Oct 2024 15:07:27 +0200
-Subject: s390/sclp: Allow user-space to provide PCI reports for optical
- modules
-
-From: Niklas Schnelle <schnelle@linux.ibm.com>
-
-[ Upstream commit e9ab04490667249633fb397be17db46a8fa6d130 ]
-
-The new SCLP action qualifier 3 is used by user-space code to provide
-optical module monitoring data to the platform.
-
-Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
-Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
-Stable-dep-of: aa9f168d55dc ("s390/pci: Support mmap() of PCI resources except for ISM devices")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/s390/char/sclp_pci.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/drivers/s390/char/sclp_pci.c b/drivers/s390/char/sclp_pci.c
-index a3e5a5fb0c1e7..c3466a8c56bb5 100644
---- a/drivers/s390/char/sclp_pci.c
-+++ b/drivers/s390/char/sclp_pci.c
-@@ -27,6 +27,7 @@
- #define SCLP_ERRNOTIFY_AQ_RESET 0
- #define SCLP_ERRNOTIFY_AQ_REPAIR 1
- #define SCLP_ERRNOTIFY_AQ_INFO_LOG 2
-+#define SCLP_ERRNOTIFY_AQ_OPTICS_DATA 3
-
- static DEFINE_MUTEX(sclp_pci_mutex);
- static struct sclp_register sclp_pci_event = {
-@@ -116,6 +117,7 @@ static int sclp_pci_check_report(struct zpci_report_error_header *report)
- case SCLP_ERRNOTIFY_AQ_RESET:
- case SCLP_ERRNOTIFY_AQ_REPAIR:
- case SCLP_ERRNOTIFY_AQ_INFO_LOG:
-+ case SCLP_ERRNOTIFY_AQ_OPTICS_DATA:
- break;
- default:
- return -EINVAL;
---
-2.39.5
-
+++ /dev/null
-From 09b30c7c08325e0ff85e19885726b2274dd33d74 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 29 Jan 2021 12:29:06 +0100
-Subject: s390/virtio: sort out physical vs virtual pointers usage
-
-From: Alexander Gordeev <agordeev@linux.ibm.com>
-
-[ Upstream commit 5fc5b94a273655128159186c87662105db8afeb5 ]
-
-This does not fix a real bug, since virtual addresses
-are currently indentical to physical ones.
-
-Reviewed-by: Nico Boehr <nrb@linux.ibm.com>
-Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
-Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
-Stable-dep-of: 2ccd42b959aa ("s390/virtio_ccw: Don't allocate/assign airqs for non-existing queues")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/s390/virtio/virtio_ccw.c | 46 +++++++++++++++++---------------
- 1 file changed, 24 insertions(+), 22 deletions(-)
-
-diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
-index a10dbe632ef9b..954fc31b4bc74 100644
---- a/drivers/s390/virtio/virtio_ccw.c
-+++ b/drivers/s390/virtio/virtio_ccw.c
-@@ -363,7 +363,7 @@ static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev,
- thinint_area->isc = VIRTIO_AIRQ_ISC;
- ccw->cmd_code = CCW_CMD_SET_IND_ADAPTER;
- ccw->count = sizeof(*thinint_area);
-- ccw->cda = (__u32)(unsigned long) thinint_area;
-+ ccw->cda = (__u32)virt_to_phys(thinint_area);
- } else {
- /* payload is the address of the indicators */
- indicatorp = ccw_device_dma_zalloc(vcdev->cdev,
-@@ -373,7 +373,7 @@ static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev,
- *indicatorp = 0;
- ccw->cmd_code = CCW_CMD_SET_IND;
- ccw->count = sizeof(indicators(vcdev));
-- ccw->cda = (__u32)(unsigned long) indicatorp;
-+ ccw->cda = (__u32)virt_to_phys(indicatorp);
- }
- /* Deregister indicators from host. */
- *indicators(vcdev) = 0;
-@@ -417,7 +417,7 @@ static int virtio_ccw_read_vq_conf(struct virtio_ccw_device *vcdev,
- ccw->cmd_code = CCW_CMD_READ_VQ_CONF;
- ccw->flags = 0;
- ccw->count = sizeof(struct vq_config_block);
-- ccw->cda = (__u32)(unsigned long)(&vcdev->dma_area->config_block);
-+ ccw->cda = (__u32)virt_to_phys(&vcdev->dma_area->config_block);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_VQ_CONF);
- if (ret)
- return ret;
-@@ -454,7 +454,7 @@ static void virtio_ccw_del_vq(struct virtqueue *vq, struct ccw1 *ccw)
- }
- ccw->cmd_code = CCW_CMD_SET_VQ;
- ccw->flags = 0;
-- ccw->cda = (__u32)(unsigned long)(info->info_block);
-+ ccw->cda = (__u32)virt_to_phys(info->info_block);
- ret = ccw_io_helper(vcdev, ccw,
- VIRTIO_CCW_DOING_SET_VQ | index);
- /*
-@@ -556,7 +556,7 @@ static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev,
- }
- ccw->cmd_code = CCW_CMD_SET_VQ;
- ccw->flags = 0;
-- ccw->cda = (__u32)(unsigned long)(info->info_block);
-+ ccw->cda = (__u32)virt_to_phys(info->info_block);
- err = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_VQ | i);
- if (err) {
- dev_warn(&vcdev->cdev->dev, "SET_VQ failed\n");
-@@ -590,6 +590,7 @@ static int virtio_ccw_register_adapter_ind(struct virtio_ccw_device *vcdev,
- {
- int ret;
- struct virtio_thinint_area *thinint_area = NULL;
-+ unsigned long indicator_addr;
- struct airq_info *info;
-
- thinint_area = ccw_device_dma_zalloc(vcdev->cdev,
-@@ -599,21 +600,22 @@ static int virtio_ccw_register_adapter_ind(struct virtio_ccw_device *vcdev,
- goto out;
- }
- /* Try to get an indicator. */
-- thinint_area->indicator = get_airq_indicator(vqs, nvqs,
-- &thinint_area->bit_nr,
-- &vcdev->airq_info);
-- if (!thinint_area->indicator) {
-+ indicator_addr = get_airq_indicator(vqs, nvqs,
-+ &thinint_area->bit_nr,
-+ &vcdev->airq_info);
-+ if (!indicator_addr) {
- ret = -ENOSPC;
- goto out;
- }
-+ thinint_area->indicator = virt_to_phys((void *)indicator_addr);
- info = vcdev->airq_info;
- thinint_area->summary_indicator =
-- (unsigned long) get_summary_indicator(info);
-+ virt_to_phys(get_summary_indicator(info));
- thinint_area->isc = VIRTIO_AIRQ_ISC;
- ccw->cmd_code = CCW_CMD_SET_IND_ADAPTER;
- ccw->flags = CCW_FLAG_SLI;
- ccw->count = sizeof(*thinint_area);
-- ccw->cda = (__u32)(unsigned long)thinint_area;
-+ ccw->cda = (__u32)virt_to_phys(thinint_area);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_IND_ADAPTER);
- if (ret) {
- if (ret == -EOPNOTSUPP) {
-@@ -686,7 +688,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
- ccw->cmd_code = CCW_CMD_SET_IND;
- ccw->flags = 0;
- ccw->count = sizeof(indicators(vcdev));
-- ccw->cda = (__u32)(unsigned long) indicatorp;
-+ ccw->cda = (__u32)virt_to_phys(indicatorp);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_IND);
- if (ret)
- goto out;
-@@ -697,7 +699,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
- ccw->cmd_code = CCW_CMD_SET_CONF_IND;
- ccw->flags = 0;
- ccw->count = sizeof(indicators2(vcdev));
-- ccw->cda = (__u32)(unsigned long) indicatorp;
-+ ccw->cda = (__u32)virt_to_phys(indicatorp);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_CONF_IND);
- if (ret)
- goto out;
-@@ -759,7 +761,7 @@ static u64 virtio_ccw_get_features(struct virtio_device *vdev)
- ccw->cmd_code = CCW_CMD_READ_FEAT;
- ccw->flags = 0;
- ccw->count = sizeof(*features);
-- ccw->cda = (__u32)(unsigned long)features;
-+ ccw->cda = (__u32)virt_to_phys(features);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_FEAT);
- if (ret) {
- rc = 0;
-@@ -776,7 +778,7 @@ static u64 virtio_ccw_get_features(struct virtio_device *vdev)
- ccw->cmd_code = CCW_CMD_READ_FEAT;
- ccw->flags = 0;
- ccw->count = sizeof(*features);
-- ccw->cda = (__u32)(unsigned long)features;
-+ ccw->cda = (__u32)virt_to_phys(features);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_FEAT);
- if (ret == 0)
- rc |= (u64)le32_to_cpu(features->features) << 32;
-@@ -829,7 +831,7 @@ static int virtio_ccw_finalize_features(struct virtio_device *vdev)
- ccw->cmd_code = CCW_CMD_WRITE_FEAT;
- ccw->flags = 0;
- ccw->count = sizeof(*features);
-- ccw->cda = (__u32)(unsigned long)features;
-+ ccw->cda = (__u32)virt_to_phys(features);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT);
- if (ret)
- goto out_free;
-@@ -843,7 +845,7 @@ static int virtio_ccw_finalize_features(struct virtio_device *vdev)
- ccw->cmd_code = CCW_CMD_WRITE_FEAT;
- ccw->flags = 0;
- ccw->count = sizeof(*features);
-- ccw->cda = (__u32)(unsigned long)features;
-+ ccw->cda = (__u32)virt_to_phys(features);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT);
-
- out_free:
-@@ -875,7 +877,7 @@ static void virtio_ccw_get_config(struct virtio_device *vdev,
- ccw->cmd_code = CCW_CMD_READ_CONF;
- ccw->flags = 0;
- ccw->count = offset + len;
-- ccw->cda = (__u32)(unsigned long)config_area;
-+ ccw->cda = (__u32)virt_to_phys(config_area);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_CONFIG);
- if (ret)
- goto out_free;
-@@ -922,7 +924,7 @@ static void virtio_ccw_set_config(struct virtio_device *vdev,
- ccw->cmd_code = CCW_CMD_WRITE_CONF;
- ccw->flags = 0;
- ccw->count = offset + len;
-- ccw->cda = (__u32)(unsigned long)config_area;
-+ ccw->cda = (__u32)virt_to_phys(config_area);
- ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_CONFIG);
-
- out_free:
-@@ -946,7 +948,7 @@ static u8 virtio_ccw_get_status(struct virtio_device *vdev)
- ccw->cmd_code = CCW_CMD_READ_STATUS;
- ccw->flags = 0;
- ccw->count = sizeof(vcdev->dma_area->status);
-- ccw->cda = (__u32)(unsigned long)&vcdev->dma_area->status;
-+ ccw->cda = (__u32)virt_to_phys(&vcdev->dma_area->status);
- ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_STATUS);
- /*
- * If the channel program failed (should only happen if the device
-@@ -975,7 +977,7 @@ static void virtio_ccw_set_status(struct virtio_device *vdev, u8 status)
- ccw->cmd_code = CCW_CMD_WRITE_STATUS;
- ccw->flags = 0;
- ccw->count = sizeof(status);
-- ccw->cda = (__u32)(unsigned long)&vcdev->dma_area->status;
-+ ccw->cda = (__u32)virt_to_phys(&vcdev->dma_area->status);
- /* We use ssch for setting the status which is a serializing
- * instruction that guarantees the memory writes have
- * completed before ssch.
-@@ -1274,7 +1276,7 @@ static int virtio_ccw_set_transport_rev(struct virtio_ccw_device *vcdev)
- ccw->cmd_code = CCW_CMD_SET_VIRTIO_REV;
- ccw->flags = 0;
- ccw->count = sizeof(*rev);
-- ccw->cda = (__u32)(unsigned long)rev;
-+ ccw->cda = (__u32)virt_to_phys(rev);
-
- vcdev->revision = VIRTIO_CCW_REV_MAX;
- do {
---
-2.39.5
-
+++ /dev/null
-From 3557152649172140e721e26ce539250133ce4a93 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 2 Apr 2025 22:36:21 +0200
-Subject: s390/virtio_ccw: Don't allocate/assign airqs for non-existing queues
-
-From: David Hildenbrand <david@redhat.com>
-
-[ Upstream commit 2ccd42b959aaf490333dbd3b9b102eaf295c036a ]
-
-If we finds a vq without a name in our input array in
-virtio_ccw_find_vqs(), we treat it as "non-existing" and set the vq pointer
-to NULL; we will not call virtio_ccw_setup_vq() to allocate/setup a vq.
-
-Consequently, we create only a queue if it actually exists (name != NULL)
-and assign an incremental queue index to each such existing queue.
-
-However, in virtio_ccw_register_adapter_ind()->get_airq_indicator() we
-will not ignore these "non-existing queues", but instead assign an airq
-indicator to them.
-
-Besides never releasing them in virtio_ccw_drop_indicators() (because
-there is no virtqueue), the bigger issue seems to be that there will be a
-disagreement between the device and the Linux guest about the airq
-indicator to be used for notifying a queue, because the indicator bit
-for adapter I/O interrupt is derived from the queue index.
-
-The virtio spec states under "Setting Up Two-Stage Queue Indicators":
-
- ... indicator contains the guest address of an area wherein the
- indicators for the devices are contained, starting at bit_nr, one
- bit per virtqueue of the device.
-
-And further in "Notification via Adapter I/O Interrupts":
-
- For notifying the driver of virtqueue buffers, the device sets the
- bit in the guest-provided indicator area at the corresponding
- offset.
-
-For example, QEMU uses in virtio_ccw_notify() the queue index (passed as
-"vector") to select the relevant indicator bit. If a queue does not exist,
-it does not have a corresponding indicator bit assigned, because it
-effectively doesn't have a queue index.
-
-Using a virtio-balloon-ccw device under QEMU with free-page-hinting
-disabled ("free-page-hint=off") but free-page-reporting enabled
-("free-page-reporting=on") will result in free page reporting
-not working as expected: in the virtio_balloon driver, we'll be stuck
-forever in virtballoon_free_page_report()->wait_event(), because the
-waitqueue will not be woken up as the notification from the device is
-lost: it would use the wrong indicator bit.
-
-Free page reporting stops working and we get splats (when configured to
-detect hung wqs) like:
-
- INFO: task kworker/1:3:463 blocked for more than 61 seconds.
- Not tainted 6.14.0 #4
- "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
- task:kworker/1:3 [...]
- Workqueue: events page_reporting_process
- Call Trace:
- [<000002f404e6dfb2>] __schedule+0x402/0x1640
- [<000002f404e6f22e>] schedule+0x3e/0xe0
- [<000002f3846a88fa>] virtballoon_free_page_report+0xaa/0x110 [virtio_balloon]
- [<000002f40435c8a4>] page_reporting_process+0x2e4/0x740
- [<000002f403fd3ee2>] process_one_work+0x1c2/0x400
- [<000002f403fd4b96>] worker_thread+0x296/0x420
- [<000002f403fe10b4>] kthread+0x124/0x290
- [<000002f403f4e0dc>] __ret_from_fork+0x3c/0x60
- [<000002f404e77272>] ret_from_fork+0xa/0x38
-
-There was recently a discussion [1] whether the "holes" should be
-treated differently again, effectively assigning also non-existing
-queues a queue index: that should also fix the issue, but requires other
-workarounds to not break existing setups.
-
-Let's fix it without affecting existing setups for now by properly ignoring
-the non-existing queues, so the indicator bits will match the queue
-indexes.
-
-[1] https://lore.kernel.org/all/cover.1720611677.git.mst@redhat.com/
-
-Fixes: a229989d975e ("virtio: don't allocate vqs when names[i] = NULL")
-Reported-by: Chandra Merla <cmerla@redhat.com>
-Cc: stable@vger.kernel.org
-Signed-off-by: David Hildenbrand <david@redhat.com>
-Tested-by: Thomas Huth <thuth@redhat.com>
-Reviewed-by: Thomas Huth <thuth@redhat.com>
-Reviewed-by: Cornelia Huck <cohuck@redhat.com>
-Acked-by: Michael S. Tsirkin <mst@redhat.com>
-Acked-by: Christian Borntraeger <borntraeger@linux.ibm.com>
-Link: https://lore.kernel.org/r/20250402203621.940090-1-david@redhat.com
-Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/s390/virtio/virtio_ccw.c | 16 ++++++++++++----
- 1 file changed, 12 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
-index f2d54c7015de4..dab743724a982 100644
---- a/drivers/s390/virtio/virtio_ccw.c
-+++ b/drivers/s390/virtio/virtio_ccw.c
-@@ -264,11 +264,17 @@ static struct airq_info *new_airq_info(int index)
- static unsigned long *get_airq_indicator(struct virtqueue *vqs[], int nvqs,
- u64 *first, void **airq_info)
- {
-- int i, j;
-+ int i, j, queue_idx, highest_queue_idx = -1;
- struct airq_info *info;
- unsigned long *indicator_addr = NULL;
- unsigned long bit, flags;
-
-+ /* Array entries without an actual queue pointer must be ignored. */
-+ for (i = 0; i < nvqs; i++) {
-+ if (vqs[i])
-+ highest_queue_idx++;
-+ }
-+
- for (i = 0; i < MAX_AIRQ_AREAS && !indicator_addr; i++) {
- mutex_lock(&airq_areas_lock);
- if (!airq_areas[i])
-@@ -278,7 +284,7 @@ static unsigned long *get_airq_indicator(struct virtqueue *vqs[], int nvqs,
- if (!info)
- return NULL;
- write_lock_irqsave(&info->lock, flags);
-- bit = airq_iv_alloc(info->aiv, nvqs);
-+ bit = airq_iv_alloc(info->aiv, highest_queue_idx + 1);
- if (bit == -1UL) {
- /* Not enough vacancies. */
- write_unlock_irqrestore(&info->lock, flags);
-@@ -287,8 +293,10 @@ static unsigned long *get_airq_indicator(struct virtqueue *vqs[], int nvqs,
- *first = bit;
- *airq_info = info;
- indicator_addr = info->aiv->vector;
-- for (j = 0; j < nvqs; j++) {
-- airq_iv_set_ptr(info->aiv, bit + j,
-+ for (j = 0, queue_idx = 0; j < nvqs; j++) {
-+ if (!vqs[j])
-+ continue;
-+ airq_iv_set_ptr(info->aiv, bit + queue_idx++,
- (unsigned long)vqs[j]);
- }
- write_unlock_irqrestore(&info->lock, flags);
---
-2.39.5
-
+++ /dev/null
-From f558381e2515aa14b943fbf184de6ac0c9342887 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 7 Mar 2024 13:28:07 +0100
-Subject: s390/virtio_ccw: fix virtual vs physical address confusion
-
-From: Halil Pasic <pasic@linux.ibm.com>
-
-[ Upstream commit d5cc41686990fa522ce573e5c6c7a619f10c3fd1 ]
-
-Fix virtual vs physical address confusion and use new dma types and helper
-functions to allow for type checking. This does not fix a bug since virtual
-and physical address spaces are currently the same.
-
-Signed-off-by: Halil Pasic <pasic@linux.ibm.com>
-Reviewed-by: Eric Farman <farman@linux.ibm.com>
-Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
-Stable-dep-of: 2ccd42b959aa ("s390/virtio_ccw: Don't allocate/assign airqs for non-existing queues")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/s390/virtio/virtio_ccw.c | 78 ++++++++++++++++----------------
- 1 file changed, 39 insertions(+), 39 deletions(-)
-
-diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
-index 954fc31b4bc74..f2d54c7015de4 100644
---- a/drivers/s390/virtio/virtio_ccw.c
-+++ b/drivers/s390/virtio/virtio_ccw.c
-@@ -85,19 +85,19 @@ static inline unsigned long *indicators2(struct virtio_ccw_device *vcdev)
- }
-
- struct vq_info_block_legacy {
-- __u64 queue;
-+ dma64_t queue;
- __u32 align;
- __u16 index;
- __u16 num;
- } __packed;
-
- struct vq_info_block {
-- __u64 desc;
-+ dma64_t desc;
- __u32 res0;
- __u16 index;
- __u16 num;
-- __u64 avail;
-- __u64 used;
-+ dma64_t avail;
-+ dma64_t used;
- } __packed;
-
- struct virtio_feature_desc {
-@@ -106,8 +106,8 @@ struct virtio_feature_desc {
- } __packed;
-
- struct virtio_thinint_area {
-- unsigned long summary_indicator;
-- unsigned long indicator;
-+ dma64_t summary_indicator;
-+ dma64_t indicator;
- u64 bit_nr;
- u8 isc;
- } __packed;
-@@ -261,12 +261,12 @@ static struct airq_info *new_airq_info(int index)
- return info;
- }
-
--static unsigned long get_airq_indicator(struct virtqueue *vqs[], int nvqs,
-- u64 *first, void **airq_info)
-+static unsigned long *get_airq_indicator(struct virtqueue *vqs[], int nvqs,
-+ u64 *first, void **airq_info)
- {
- int i, j;
- struct airq_info *info;
-- unsigned long indicator_addr = 0;
-+ unsigned long *indicator_addr = NULL;
- unsigned long bit, flags;
-
- for (i = 0; i < MAX_AIRQ_AREAS && !indicator_addr; i++) {
-@@ -276,7 +276,7 @@ static unsigned long get_airq_indicator(struct virtqueue *vqs[], int nvqs,
- info = airq_areas[i];
- mutex_unlock(&airq_areas_lock);
- if (!info)
-- return 0;
-+ return NULL;
- write_lock_irqsave(&info->lock, flags);
- bit = airq_iv_alloc(info->aiv, nvqs);
- if (bit == -1UL) {
-@@ -286,7 +286,7 @@ static unsigned long get_airq_indicator(struct virtqueue *vqs[], int nvqs,
- }
- *first = bit;
- *airq_info = info;
-- indicator_addr = (unsigned long)info->aiv->vector;
-+ indicator_addr = info->aiv->vector;
- for (j = 0; j < nvqs; j++) {
- airq_iv_set_ptr(info->aiv, bit + j,
- (unsigned long)vqs[j]);
-@@ -359,11 +359,11 @@ static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev,
- if (!thinint_area)
- return;
- thinint_area->summary_indicator =
-- (unsigned long) get_summary_indicator(airq_info);
-+ virt_to_dma64(get_summary_indicator(airq_info));
- thinint_area->isc = VIRTIO_AIRQ_ISC;
- ccw->cmd_code = CCW_CMD_SET_IND_ADAPTER;
- ccw->count = sizeof(*thinint_area);
-- ccw->cda = (__u32)virt_to_phys(thinint_area);
-+ ccw->cda = virt_to_dma32(thinint_area);
- } else {
- /* payload is the address of the indicators */
- indicatorp = ccw_device_dma_zalloc(vcdev->cdev,
-@@ -373,7 +373,7 @@ static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev,
- *indicatorp = 0;
- ccw->cmd_code = CCW_CMD_SET_IND;
- ccw->count = sizeof(indicators(vcdev));
-- ccw->cda = (__u32)virt_to_phys(indicatorp);
-+ ccw->cda = virt_to_dma32(indicatorp);
- }
- /* Deregister indicators from host. */
- *indicators(vcdev) = 0;
-@@ -417,7 +417,7 @@ static int virtio_ccw_read_vq_conf(struct virtio_ccw_device *vcdev,
- ccw->cmd_code = CCW_CMD_READ_VQ_CONF;
- ccw->flags = 0;
- ccw->count = sizeof(struct vq_config_block);
-- ccw->cda = (__u32)virt_to_phys(&vcdev->dma_area->config_block);
-+ ccw->cda = virt_to_dma32(&vcdev->dma_area->config_block);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_VQ_CONF);
- if (ret)
- return ret;
-@@ -454,7 +454,7 @@ static void virtio_ccw_del_vq(struct virtqueue *vq, struct ccw1 *ccw)
- }
- ccw->cmd_code = CCW_CMD_SET_VQ;
- ccw->flags = 0;
-- ccw->cda = (__u32)virt_to_phys(info->info_block);
-+ ccw->cda = virt_to_dma32(info->info_block);
- ret = ccw_io_helper(vcdev, ccw,
- VIRTIO_CCW_DOING_SET_VQ | index);
- /*
-@@ -541,22 +541,22 @@ static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev,
- /* Register it with the host. */
- queue = virtqueue_get_desc_addr(vq);
- if (vcdev->revision == 0) {
-- info->info_block->l.queue = queue;
-+ info->info_block->l.queue = u64_to_dma64(queue);
- info->info_block->l.align = KVM_VIRTIO_CCW_RING_ALIGN;
- info->info_block->l.index = i;
- info->info_block->l.num = info->num;
- ccw->count = sizeof(info->info_block->l);
- } else {
-- info->info_block->s.desc = queue;
-+ info->info_block->s.desc = u64_to_dma64(queue);
- info->info_block->s.index = i;
- info->info_block->s.num = info->num;
-- info->info_block->s.avail = (__u64)virtqueue_get_avail_addr(vq);
-- info->info_block->s.used = (__u64)virtqueue_get_used_addr(vq);
-+ info->info_block->s.avail = u64_to_dma64(virtqueue_get_avail_addr(vq));
-+ info->info_block->s.used = u64_to_dma64(virtqueue_get_used_addr(vq));
- ccw->count = sizeof(info->info_block->s);
- }
- ccw->cmd_code = CCW_CMD_SET_VQ;
- ccw->flags = 0;
-- ccw->cda = (__u32)virt_to_phys(info->info_block);
-+ ccw->cda = virt_to_dma32(info->info_block);
- err = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_VQ | i);
- if (err) {
- dev_warn(&vcdev->cdev->dev, "SET_VQ failed\n");
-@@ -590,7 +590,7 @@ static int virtio_ccw_register_adapter_ind(struct virtio_ccw_device *vcdev,
- {
- int ret;
- struct virtio_thinint_area *thinint_area = NULL;
-- unsigned long indicator_addr;
-+ unsigned long *indicator_addr;
- struct airq_info *info;
-
- thinint_area = ccw_device_dma_zalloc(vcdev->cdev,
-@@ -607,15 +607,15 @@ static int virtio_ccw_register_adapter_ind(struct virtio_ccw_device *vcdev,
- ret = -ENOSPC;
- goto out;
- }
-- thinint_area->indicator = virt_to_phys((void *)indicator_addr);
-+ thinint_area->indicator = virt_to_dma64(indicator_addr);
- info = vcdev->airq_info;
- thinint_area->summary_indicator =
-- virt_to_phys(get_summary_indicator(info));
-+ virt_to_dma64(get_summary_indicator(info));
- thinint_area->isc = VIRTIO_AIRQ_ISC;
- ccw->cmd_code = CCW_CMD_SET_IND_ADAPTER;
- ccw->flags = CCW_FLAG_SLI;
- ccw->count = sizeof(*thinint_area);
-- ccw->cda = (__u32)virt_to_phys(thinint_area);
-+ ccw->cda = virt_to_dma32(thinint_area);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_IND_ADAPTER);
- if (ret) {
- if (ret == -EOPNOTSUPP) {
-@@ -643,7 +643,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
- struct irq_affinity *desc)
- {
- struct virtio_ccw_device *vcdev = to_vc_device(vdev);
-- unsigned long *indicatorp = NULL;
-+ dma64_t *indicatorp = NULL;
- int ret, i, queue_idx = 0;
- struct ccw1 *ccw;
-
-@@ -675,7 +675,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
- sizeof(indicators(vcdev)));
- if (!indicatorp)
- goto out;
-- *indicatorp = (unsigned long) indicators(vcdev);
-+ *indicatorp = virt_to_dma64(indicators(vcdev));
- if (vcdev->is_thinint) {
- ret = virtio_ccw_register_adapter_ind(vcdev, vqs, nvqs, ccw);
- if (ret)
-@@ -688,18 +688,18 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
- ccw->cmd_code = CCW_CMD_SET_IND;
- ccw->flags = 0;
- ccw->count = sizeof(indicators(vcdev));
-- ccw->cda = (__u32)virt_to_phys(indicatorp);
-+ ccw->cda = virt_to_dma32(indicatorp);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_IND);
- if (ret)
- goto out;
- }
- /* Register indicators2 with host for config changes */
-- *indicatorp = (unsigned long) indicators2(vcdev);
-+ *indicatorp = virt_to_dma64(indicators2(vcdev));
- *indicators2(vcdev) = 0;
- ccw->cmd_code = CCW_CMD_SET_CONF_IND;
- ccw->flags = 0;
- ccw->count = sizeof(indicators2(vcdev));
-- ccw->cda = (__u32)virt_to_phys(indicatorp);
-+ ccw->cda = virt_to_dma32(indicatorp);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_CONF_IND);
- if (ret)
- goto out;
-@@ -761,7 +761,7 @@ static u64 virtio_ccw_get_features(struct virtio_device *vdev)
- ccw->cmd_code = CCW_CMD_READ_FEAT;
- ccw->flags = 0;
- ccw->count = sizeof(*features);
-- ccw->cda = (__u32)virt_to_phys(features);
-+ ccw->cda = virt_to_dma32(features);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_FEAT);
- if (ret) {
- rc = 0;
-@@ -778,7 +778,7 @@ static u64 virtio_ccw_get_features(struct virtio_device *vdev)
- ccw->cmd_code = CCW_CMD_READ_FEAT;
- ccw->flags = 0;
- ccw->count = sizeof(*features);
-- ccw->cda = (__u32)virt_to_phys(features);
-+ ccw->cda = virt_to_dma32(features);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_FEAT);
- if (ret == 0)
- rc |= (u64)le32_to_cpu(features->features) << 32;
-@@ -831,7 +831,7 @@ static int virtio_ccw_finalize_features(struct virtio_device *vdev)
- ccw->cmd_code = CCW_CMD_WRITE_FEAT;
- ccw->flags = 0;
- ccw->count = sizeof(*features);
-- ccw->cda = (__u32)virt_to_phys(features);
-+ ccw->cda = virt_to_dma32(features);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT);
- if (ret)
- goto out_free;
-@@ -845,7 +845,7 @@ static int virtio_ccw_finalize_features(struct virtio_device *vdev)
- ccw->cmd_code = CCW_CMD_WRITE_FEAT;
- ccw->flags = 0;
- ccw->count = sizeof(*features);
-- ccw->cda = (__u32)virt_to_phys(features);
-+ ccw->cda = virt_to_dma32(features);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT);
-
- out_free:
-@@ -877,7 +877,7 @@ static void virtio_ccw_get_config(struct virtio_device *vdev,
- ccw->cmd_code = CCW_CMD_READ_CONF;
- ccw->flags = 0;
- ccw->count = offset + len;
-- ccw->cda = (__u32)virt_to_phys(config_area);
-+ ccw->cda = virt_to_dma32(config_area);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_CONFIG);
- if (ret)
- goto out_free;
-@@ -924,7 +924,7 @@ static void virtio_ccw_set_config(struct virtio_device *vdev,
- ccw->cmd_code = CCW_CMD_WRITE_CONF;
- ccw->flags = 0;
- ccw->count = offset + len;
-- ccw->cda = (__u32)virt_to_phys(config_area);
-+ ccw->cda = virt_to_dma32(config_area);
- ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_CONFIG);
-
- out_free:
-@@ -948,7 +948,7 @@ static u8 virtio_ccw_get_status(struct virtio_device *vdev)
- ccw->cmd_code = CCW_CMD_READ_STATUS;
- ccw->flags = 0;
- ccw->count = sizeof(vcdev->dma_area->status);
-- ccw->cda = (__u32)virt_to_phys(&vcdev->dma_area->status);
-+ ccw->cda = virt_to_dma32(&vcdev->dma_area->status);
- ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_STATUS);
- /*
- * If the channel program failed (should only happen if the device
-@@ -977,11 +977,11 @@ static void virtio_ccw_set_status(struct virtio_device *vdev, u8 status)
- ccw->cmd_code = CCW_CMD_WRITE_STATUS;
- ccw->flags = 0;
- ccw->count = sizeof(status);
-- ccw->cda = (__u32)virt_to_phys(&vcdev->dma_area->status);
- /* We use ssch for setting the status which is a serializing
- * instruction that guarantees the memory writes have
- * completed before ssch.
- */
-+ ccw->cda = virt_to_dma32(&vcdev->dma_area->status);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_STATUS);
- /* Write failed? We assume status is unchanged. */
- if (ret)
-@@ -1276,7 +1276,7 @@ static int virtio_ccw_set_transport_rev(struct virtio_ccw_device *vcdev)
- ccw->cmd_code = CCW_CMD_SET_VIRTIO_REV;
- ccw->flags = 0;
- ccw->count = sizeof(*rev);
-- ccw->cda = (__u32)virt_to_phys(rev);
-+ ccw->cda = virt_to_dma32(rev);
-
- vcdev->revision = VIRTIO_CCW_REV_MAX;
- do {
---
-2.39.5
-
of-resolver-fix-device-node-refcount-leakage-in-of_r.patch
pci-assign-pci-domain-ids-by-ida_alloc.patch
pci-fix-reference-leak-in-pci_register_host_bridge.patch
-s390-virtio-sort-out-physical-vs-virtual-pointers-us.patch
-s390-virtio_ccw-fix-virtual-vs-physical-address-conf.patch
-s390-virtio_ccw-don-t-allocate-assign-airqs-for-non-.patch
phy-freescale-imx8m-pcie-add-i.mx8mp-pcie-phy-suppor.patch
phy-freescale-imx8m-pcie-assert-phy-reset-and-perst-.patch
-s390-sclp-allow-user-space-to-provide-pci-reports-fo.patch
-s390-pci-report-pci-error-recovery-results-via-sclp.patch
-s390-pci-support-mmap-of-pci-resources-except-for-is.patch
asoc-qcom-q6dsp-add-support-to-more-display-ports.patch
asoc-qcom-fix-sc7280-lpass-potential-buffer-overflow.patch
selftests-mm-generate-a-temporary-mountpoint-for-cgr.patch
+++ /dev/null
-From acc18c553ae5cd60d8e08151c2ed613a47c666aa Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 13 Dec 2024 14:47:28 +0100
-Subject: s390/pci: Report PCI error recovery results via SCLP
-
-From: Niklas Schnelle <schnelle@linux.ibm.com>
-
-[ Upstream commit 4ec6054e7321dc24ebccaa08b3af0d590f5666e6 ]
-
-Add a mechanism with which the status of PCI error recovery runs
-is reported to the platform. Together with the status supply additional
-information that may aid in problem determination.
-
-Reviewed-by: Halil Pasic <pasic@linux.ibm.com>
-Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
-Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
-Stable-dep-of: aa9f168d55dc ("s390/pci: Support mmap() of PCI resources except for ISM devices")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- arch/s390/include/asm/sclp.h | 33 +++++++++++
- arch/s390/pci/Makefile | 2 +-
- arch/s390/pci/pci_event.c | 21 +++++--
- arch/s390/pci/pci_report.c | 111 +++++++++++++++++++++++++++++++++++
- arch/s390/pci/pci_report.h | 16 +++++
- drivers/s390/char/sclp.h | 14 -----
- drivers/s390/char/sclp_pci.c | 19 ------
- 7 files changed, 178 insertions(+), 38 deletions(-)
- create mode 100644 arch/s390/pci/pci_report.c
- create mode 100644 arch/s390/pci/pci_report.h
-
-diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h
-index ad17d91ad2e66..0efd6ab4473dd 100644
---- a/arch/s390/include/asm/sclp.h
-+++ b/arch/s390/include/asm/sclp.h
-@@ -16,6 +16,11 @@
- /* 24 + 16 * SCLP_MAX_CORES */
- #define EXT_SCCB_READ_CPU (3 * PAGE_SIZE)
-
-+#define SCLP_ERRNOTIFY_AQ_RESET 0
-+#define SCLP_ERRNOTIFY_AQ_REPAIR 1
-+#define SCLP_ERRNOTIFY_AQ_INFO_LOG 2
-+#define SCLP_ERRNOTIFY_AQ_OPTICS_DATA 3
-+
- #ifndef __ASSEMBLY__
- #include <linux/uio.h>
- #include <asm/chpid.h>
-@@ -111,6 +116,34 @@ struct sclp_info {
- };
- extern struct sclp_info sclp;
-
-+struct sccb_header {
-+ u16 length;
-+ u8 function_code;
-+ u8 control_mask[3];
-+ u16 response_code;
-+} __packed;
-+
-+struct evbuf_header {
-+ u16 length;
-+ u8 type;
-+ u8 flags;
-+ u16 _reserved;
-+} __packed;
-+
-+struct err_notify_evbuf {
-+ struct evbuf_header header;
-+ u8 action;
-+ u8 atype;
-+ u32 fh;
-+ u32 fid;
-+ u8 data[];
-+} __packed;
-+
-+struct err_notify_sccb {
-+ struct sccb_header header;
-+ struct err_notify_evbuf evbuf;
-+} __packed;
-+
- struct zpci_report_error_header {
- u8 version; /* Interface version byte */
- u8 action; /* Action qualifier byte
-diff --git a/arch/s390/pci/Makefile b/arch/s390/pci/Makefile
-index 2c21f0394c9ab..df73c5182990a 100644
---- a/arch/s390/pci/Makefile
-+++ b/arch/s390/pci/Makefile
-@@ -5,6 +5,6 @@
-
- obj-$(CONFIG_PCI) += pci.o pci_irq.o pci_clp.o \
- pci_event.o pci_debug.o pci_insn.o pci_mmio.o \
-- pci_bus.o pci_kvm_hook.o
-+ pci_bus.o pci_kvm_hook.o pci_report.o
- obj-$(CONFIG_PCI_IOV) += pci_iov.o
- obj-$(CONFIG_SYSFS) += pci_sysfs.o
-diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c
-index 7f7b732b3f3ef..7bd7721c1239a 100644
---- a/arch/s390/pci/pci_event.c
-+++ b/arch/s390/pci/pci_event.c
-@@ -16,6 +16,7 @@
- #include <asm/sclp.h>
-
- #include "pci_bus.h"
-+#include "pci_report.h"
-
- /* Content Code Description for PCI Function Error */
- struct zpci_ccdf_err {
-@@ -169,6 +170,8 @@ static pci_ers_result_t zpci_event_do_reset(struct pci_dev *pdev,
- static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
- {
- pci_ers_result_t ers_res = PCI_ERS_RESULT_DISCONNECT;
-+ struct zpci_dev *zdev = to_zpci(pdev);
-+ char *status_str = "success";
- struct pci_driver *driver;
-
- /*
-@@ -186,29 +189,37 @@ static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
- if (is_passed_through(pdev)) {
- pr_info("%s: Cannot be recovered in the host because it is a pass-through device\n",
- pci_name(pdev));
-+ status_str = "failed (pass-through)";
- goto out_unlock;
- }
-
- driver = to_pci_driver(pdev->dev.driver);
- if (!is_driver_supported(driver)) {
-- if (!driver)
-+ if (!driver) {
- pr_info("%s: Cannot be recovered because no driver is bound to the device\n",
- pci_name(pdev));
-- else
-+ status_str = "failed (no driver)";
-+ } else {
- pr_info("%s: The %s driver bound to the device does not support error recovery\n",
- pci_name(pdev),
- driver->name);
-+ status_str = "failed (no driver support)";
-+ }
- goto out_unlock;
- }
-
- ers_res = zpci_event_notify_error_detected(pdev, driver);
-- if (ers_result_indicates_abort(ers_res))
-+ if (ers_result_indicates_abort(ers_res)) {
-+ status_str = "failed (abort on detection)";
- goto out_unlock;
-+ }
-
- if (ers_res == PCI_ERS_RESULT_CAN_RECOVER) {
- ers_res = zpci_event_do_error_state_clear(pdev, driver);
-- if (ers_result_indicates_abort(ers_res))
-+ if (ers_result_indicates_abort(ers_res)) {
-+ status_str = "failed (abort on MMIO enable)";
- goto out_unlock;
-+ }
- }
-
- if (ers_res == PCI_ERS_RESULT_NEED_RESET)
-@@ -217,6 +228,7 @@ static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
- if (ers_res != PCI_ERS_RESULT_RECOVERED) {
- pr_err("%s: Automatic recovery failed; operator intervention is required\n",
- pci_name(pdev));
-+ status_str = "failed (driver can't recover)";
- goto out_unlock;
- }
-
-@@ -225,6 +237,7 @@ static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
- driver->err_handler->resume(pdev);
- out_unlock:
- pci_dev_unlock(pdev);
-+ zpci_report_status(zdev, "recovery", status_str);
-
- return ers_res;
- }
-diff --git a/arch/s390/pci/pci_report.c b/arch/s390/pci/pci_report.c
-new file mode 100644
-index 0000000000000..2754c9c161f5b
---- /dev/null
-+++ b/arch/s390/pci/pci_report.c
-@@ -0,0 +1,111 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Copyright IBM Corp. 2024
-+ *
-+ * Author(s):
-+ * Niklas Schnelle <schnelle@linux.ibm.com>
-+ *
-+ */
-+
-+#define KMSG_COMPONENT "zpci"
-+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-+
-+#include <linux/kernel.h>
-+#include <linux/sprintf.h>
-+#include <linux/pci.h>
-+
-+#include <asm/sclp.h>
-+
-+#include "pci_report.h"
-+
-+#define ZPCI_ERR_LOG_ID_KERNEL_REPORT 0x4714
-+
-+struct zpci_report_error_data {
-+ u64 timestamp;
-+ u64 err_log_id;
-+ char log_data[];
-+} __packed;
-+
-+#define ZPCI_REPORT_SIZE (PAGE_SIZE - sizeof(struct err_notify_sccb))
-+#define ZPCI_REPORT_DATA_SIZE (ZPCI_REPORT_SIZE - sizeof(struct zpci_report_error_data))
-+
-+struct zpci_report_error {
-+ struct zpci_report_error_header header;
-+ struct zpci_report_error_data data;
-+} __packed;
-+
-+static const char *zpci_state_str(pci_channel_state_t state)
-+{
-+ switch (state) {
-+ case pci_channel_io_normal:
-+ return "normal";
-+ case pci_channel_io_frozen:
-+ return "frozen";
-+ case pci_channel_io_perm_failure:
-+ return "permanent-failure";
-+ default:
-+ return "invalid";
-+ };
-+}
-+
-+/**
-+ * zpci_report_status - Report the status of operations on a PCI device
-+ * @zdev: The PCI device for which to report status
-+ * @operation: A string representing the operation reported
-+ * @status: A string representing the status of the operation
-+ *
-+ * This function creates a human readable report about an operation such as
-+ * PCI device recovery and forwards this to the platform using the SCLP Write
-+ * Event Data mechanism. Besides the operation and status strings the report
-+ * also contains additional information about the device deemed useful for
-+ * debug such as the currently bound device driver, if any, and error state.
-+ *
-+ * Return: 0 on success an error code < 0 otherwise.
-+ */
-+int zpci_report_status(struct zpci_dev *zdev, const char *operation, const char *status)
-+{
-+ struct zpci_report_error *report;
-+ struct pci_driver *driver = NULL;
-+ struct pci_dev *pdev = NULL;
-+ char *buf, *end;
-+ int ret;
-+
-+ if (!zdev || !zdev->zbus)
-+ return -ENODEV;
-+
-+ /* Protected virtualization hosts get nothing from us */
-+ if (prot_virt_guest)
-+ return -ENODATA;
-+
-+ report = (void *)get_zeroed_page(GFP_KERNEL);
-+ if (!report)
-+ return -ENOMEM;
-+ if (zdev->zbus->bus)
-+ pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn);
-+ if (pdev)
-+ driver = to_pci_driver(pdev->dev.driver);
-+
-+ buf = report->data.log_data;
-+ end = report->data.log_data + ZPCI_REPORT_DATA_SIZE;
-+ buf += scnprintf(buf, end - buf, "report: %s\n", operation);
-+ buf += scnprintf(buf, end - buf, "status: %s\n", status);
-+ buf += scnprintf(buf, end - buf, "state: %s\n",
-+ (pdev) ? zpci_state_str(pdev->error_state) : "n/a");
-+ buf += scnprintf(buf, end - buf, "driver: %s\n", (driver) ? driver->name : "n/a");
-+
-+ report->header.version = 1;
-+ report->header.action = SCLP_ERRNOTIFY_AQ_INFO_LOG;
-+ report->header.length = buf - (char *)&report->data;
-+ report->data.timestamp = ktime_get_clocktai_seconds();
-+ report->data.err_log_id = ZPCI_ERR_LOG_ID_KERNEL_REPORT;
-+
-+ ret = sclp_pci_report(&report->header, zdev->fh, zdev->fid);
-+ if (ret)
-+ pr_err("Reporting PCI status failed with code %d\n", ret);
-+ else
-+ pr_info("Reported PCI device status\n");
-+
-+ free_page((unsigned long)report);
-+
-+ return ret;
-+}
-diff --git a/arch/s390/pci/pci_report.h b/arch/s390/pci/pci_report.h
-new file mode 100644
-index 0000000000000..e08003d51a972
---- /dev/null
-+++ b/arch/s390/pci/pci_report.h
-@@ -0,0 +1,16 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright IBM Corp. 2024
-+ *
-+ * Author(s):
-+ * Niklas Schnelle <schnelle@linux.ibm.com>
-+ *
-+ */
-+#ifndef __S390_PCI_REPORT_H
-+#define __S390_PCI_REPORT_H
-+
-+struct zpci_dev;
-+
-+int zpci_report_status(struct zpci_dev *zdev, const char *operation, const char *status);
-+
-+#endif /* __S390_PCI_REPORT_H */
-diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
-index 6a23ec286c702..25fd4d8547483 100644
---- a/drivers/s390/char/sclp.h
-+++ b/drivers/s390/char/sclp.h
-@@ -84,13 +84,6 @@ typedef unsigned int sclp_cmdw_t;
-
- typedef u64 sccb_mask_t;
-
--struct sccb_header {
-- u16 length;
-- u8 function_code;
-- u8 control_mask[3];
-- u16 response_code;
--} __attribute__((packed));
--
- struct init_sccb {
- struct sccb_header header;
- u16 _reserved;
-@@ -237,13 +230,6 @@ struct gds_vector {
- u16 gds_id;
- } __attribute__((packed));
-
--struct evbuf_header {
-- u16 length;
-- u8 type;
-- u8 flags;
-- u16 _reserved;
--} __attribute__((packed));
--
- struct sclp_req {
- struct list_head list; /* list_head for request queueing. */
- sclp_cmdw_t command; /* sclp command to execute */
-diff --git a/drivers/s390/char/sclp_pci.c b/drivers/s390/char/sclp_pci.c
-index c3466a8c56bb5..56400886f7fca 100644
---- a/drivers/s390/char/sclp_pci.c
-+++ b/drivers/s390/char/sclp_pci.c
-@@ -24,30 +24,11 @@
-
- #define SCLP_ATYPE_PCI 2
-
--#define SCLP_ERRNOTIFY_AQ_RESET 0
--#define SCLP_ERRNOTIFY_AQ_REPAIR 1
--#define SCLP_ERRNOTIFY_AQ_INFO_LOG 2
--#define SCLP_ERRNOTIFY_AQ_OPTICS_DATA 3
--
- static DEFINE_MUTEX(sclp_pci_mutex);
- static struct sclp_register sclp_pci_event = {
- .send_mask = EVTYP_ERRNOTIFY_MASK,
- };
-
--struct err_notify_evbuf {
-- struct evbuf_header header;
-- u8 action;
-- u8 atype;
-- u32 fh;
-- u32 fid;
-- u8 data[];
--} __packed;
--
--struct err_notify_sccb {
-- struct sccb_header header;
-- struct err_notify_evbuf evbuf;
--} __packed;
--
- struct pci_cfg_sccb {
- struct sccb_header header;
- u8 atype; /* adapter type */
---
-2.39.5
-
+++ /dev/null
-From ea19bdc1c71f24fd0df0c5ffafd28301e47414b4 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 26 Feb 2025 13:07:47 +0100
-Subject: s390/pci: Support mmap() of PCI resources except for ISM devices
-
-From: Niklas Schnelle <schnelle@linux.ibm.com>
-
-[ Upstream commit aa9f168d55dc47c0de564f7dfe0e90467c9fee71 ]
-
-So far s390 does not allow mmap() of PCI resources to user-space via the
-usual mechanisms, though it does use it for RDMA. For the PCI sysfs
-resource files and /proc/bus/pci it defines neither HAVE_PCI_MMAP nor
-ARCH_GENERIC_PCI_MMAP_RESOURCE. For vfio-pci s390 previously relied on
-disabled VFIO_PCI_MMAP and now relies on setting pdev->non_mappable_bars
-for all devices.
-
-This is partly because access to mapped PCI resources from user-space
-requires special PCI load/store memory-I/O (MIO) instructions, or the
-special MMIO syscalls when these are not available. Still, such access is
-possible and useful not just for RDMA, in fact not being able to mmap() PCI
-resources has previously caused extra work when testing devices.
-
-One thing that doesn't work with PCI resources mapped to user-space though
-is the s390 specific virtual ISM device. Not only because the BAR size of
-256 TiB prevents mapping the whole BAR but also because access requires use
-of the legacy PCI instructions which are not accessible to user-space on
-systems with the newer MIO PCI instructions.
-
-Now with the pdev->non_mappable_bars flag ISM can be excluded from mapping
-its resources while making this functionality available for all other PCI
-devices. To this end introduce a minimal implementation of PCI_QUIRKS and
-use that to set pdev->non_mappable_bars for ISM devices only. Then also set
-ARCH_GENERIC_PCI_MMAP_RESOURCE to take advantage of the generic
-implementation of pci_mmap_resource_range() enabling only the newer sysfs
-mmap() interface. This follows the recommendation in
-Documentation/PCI/sysfs-pci.rst.
-
-Link: https://lore.kernel.org/r/20250226-vfio_pci_mmap-v7-3-c5c0f1d26efd@linux.ibm.com
-Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
-Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- arch/s390/Kconfig | 4 +---
- arch/s390/include/asm/pci.h | 3 +++
- arch/s390/pci/Makefile | 2 +-
- arch/s390/pci/pci_fixup.c | 23 +++++++++++++++++++++++
- drivers/s390/net/ism_drv.c | 1 -
- include/linux/pci_ids.h | 1 +
- 6 files changed, 29 insertions(+), 5 deletions(-)
- create mode 100644 arch/s390/pci/pci_fixup.c
-
-diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
-index 62f2c9e8e05f7..b9f70927c1ed8 100644
---- a/arch/s390/Kconfig
-+++ b/arch/s390/Kconfig
-@@ -41,9 +41,6 @@ config AUDIT_ARCH
- config NO_IOPORT_MAP
- def_bool y
-
--config PCI_QUIRKS
-- def_bool n
--
- config ARCH_SUPPORTS_UPROBES
- def_bool y
-
-@@ -237,6 +234,7 @@ config S390
- select PCI_DOMAINS if PCI
- select PCI_MSI if PCI
- select PCI_MSI_ARCH_FALLBACKS if PCI_MSI
-+ select PCI_QUIRKS if PCI
- select SPARSE_IRQ
- select SWIOTLB
- select SYSCTL_EXCEPTION_TRACE
-diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
-index 83789e39d1d5e..8b11d37fd0349 100644
---- a/arch/s390/include/asm/pci.h
-+++ b/arch/s390/include/asm/pci.h
-@@ -11,6 +11,9 @@
- #include <asm/pci_insn.h>
- #include <asm/sclp.h>
-
-+#define ARCH_GENERIC_PCI_MMAP_RESOURCE 1
-+#define arch_can_pci_mmap_wc() 1
-+
- #define PCIBIOS_MIN_IO 0x1000
- #define PCIBIOS_MIN_MEM 0x10000000
-
-diff --git a/arch/s390/pci/Makefile b/arch/s390/pci/Makefile
-index df73c5182990a..1810e0944a4ed 100644
---- a/arch/s390/pci/Makefile
-+++ b/arch/s390/pci/Makefile
-@@ -5,6 +5,6 @@
-
- obj-$(CONFIG_PCI) += pci.o pci_irq.o pci_clp.o \
- pci_event.o pci_debug.o pci_insn.o pci_mmio.o \
-- pci_bus.o pci_kvm_hook.o pci_report.o
-+ pci_bus.o pci_kvm_hook.o pci_report.o pci_fixup.o
- obj-$(CONFIG_PCI_IOV) += pci_iov.o
- obj-$(CONFIG_SYSFS) += pci_sysfs.o
-diff --git a/arch/s390/pci/pci_fixup.c b/arch/s390/pci/pci_fixup.c
-new file mode 100644
-index 0000000000000..35688b6450983
---- /dev/null
-+++ b/arch/s390/pci/pci_fixup.c
-@@ -0,0 +1,23 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Exceptions for specific devices,
-+ *
-+ * Copyright IBM Corp. 2025
-+ *
-+ * Author(s):
-+ * Niklas Schnelle <schnelle@linux.ibm.com>
-+ */
-+#include <linux/pci.h>
-+
-+static void zpci_ism_bar_no_mmap(struct pci_dev *pdev)
-+{
-+ /*
-+ * ISM's BAR is special. Drivers written for ISM know
-+ * how to handle this but others need to be aware of their
-+ * special nature e.g. to prevent attempts to mmap() it.
-+ */
-+ pdev->non_mappable_bars = 1;
-+}
-+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_IBM,
-+ PCI_DEVICE_ID_IBM_ISM,
-+ zpci_ism_bar_no_mmap);
-diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c
-index 2f34761e64135..60ed70a39d2cc 100644
---- a/drivers/s390/net/ism_drv.c
-+++ b/drivers/s390/net/ism_drv.c
-@@ -20,7 +20,6 @@
- MODULE_DESCRIPTION("ISM driver for s390");
- MODULE_LICENSE("GPL");
-
--#define PCI_DEVICE_ID_IBM_ISM 0x04ED
- #define DRV_NAME "ism"
-
- static const struct pci_device_id ism_device_table[] = {
-diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
-index c395b3c5c05cf..89896e82e40d8 100644
---- a/include/linux/pci_ids.h
-+++ b/include/linux/pci_ids.h
-@@ -517,6 +517,7 @@
- #define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM 0x0251
- #define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM_PCIE 0x0361
- #define PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL 0x252
-+#define PCI_DEVICE_ID_IBM_ISM 0x04ed
-
- #define PCI_SUBVENDOR_ID_IBM 0x1014
- #define PCI_SUBDEVICE_ID_IBM_SATURN_SERIAL_ONE_PORT 0x03d4
---
-2.39.5
-
+++ /dev/null
-From b0f229580e52d4cbf0c613fb65ddb70ba7be826c Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 1 Oct 2024 15:07:27 +0200
-Subject: s390/sclp: Allow user-space to provide PCI reports for optical
- modules
-
-From: Niklas Schnelle <schnelle@linux.ibm.com>
-
-[ Upstream commit e9ab04490667249633fb397be17db46a8fa6d130 ]
-
-The new SCLP action qualifier 3 is used by user-space code to provide
-optical module monitoring data to the platform.
-
-Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
-Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
-Stable-dep-of: aa9f168d55dc ("s390/pci: Support mmap() of PCI resources except for ISM devices")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/s390/char/sclp_pci.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/drivers/s390/char/sclp_pci.c b/drivers/s390/char/sclp_pci.c
-index a3e5a5fb0c1e7..c3466a8c56bb5 100644
---- a/drivers/s390/char/sclp_pci.c
-+++ b/drivers/s390/char/sclp_pci.c
-@@ -27,6 +27,7 @@
- #define SCLP_ERRNOTIFY_AQ_RESET 0
- #define SCLP_ERRNOTIFY_AQ_REPAIR 1
- #define SCLP_ERRNOTIFY_AQ_INFO_LOG 2
-+#define SCLP_ERRNOTIFY_AQ_OPTICS_DATA 3
-
- static DEFINE_MUTEX(sclp_pci_mutex);
- static struct sclp_register sclp_pci_event = {
-@@ -116,6 +117,7 @@ static int sclp_pci_check_report(struct zpci_report_error_header *report)
- case SCLP_ERRNOTIFY_AQ_RESET:
- case SCLP_ERRNOTIFY_AQ_REPAIR:
- case SCLP_ERRNOTIFY_AQ_INFO_LOG:
-+ case SCLP_ERRNOTIFY_AQ_OPTICS_DATA:
- break;
- default:
- return -EINVAL;
---
-2.39.5
-
of-resolver-simplify-of_resolve_phandles-using-__fre.patch
of-resolver-fix-device-node-refcount-leakage-in-of_r.patch
scsi-ufs-qcom-fix-dev-reference-leaked-through-of_qc.patch
-s390-sclp-allow-user-space-to-provide-pci-reports-fo.patch
-s390-pci-report-pci-error-recovery-results-via-sclp.patch
-s390-pci-support-mmap-of-pci-resources-except-for-is.patch
pci-msi-convert-pci_msi_ignore_mask-to-per-msi-domai.patch
pci-msi-handle-the-nomask-flag-correctly-for-all-pci.patch
pci-msi-add-an-option-to-write-msix-entry_data-befor.patch
+++ /dev/null
-From d04b275636d31a1ff5237a9df364ee69693d75f1 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 26 Feb 2025 13:07:47 +0100
-Subject: s390/pci: Support mmap() of PCI resources except for ISM devices
-
-From: Niklas Schnelle <schnelle@linux.ibm.com>
-
-[ Upstream commit aa9f168d55dc47c0de564f7dfe0e90467c9fee71 ]
-
-So far s390 does not allow mmap() of PCI resources to user-space via the
-usual mechanisms, though it does use it for RDMA. For the PCI sysfs
-resource files and /proc/bus/pci it defines neither HAVE_PCI_MMAP nor
-ARCH_GENERIC_PCI_MMAP_RESOURCE. For vfio-pci s390 previously relied on
-disabled VFIO_PCI_MMAP and now relies on setting pdev->non_mappable_bars
-for all devices.
-
-This is partly because access to mapped PCI resources from user-space
-requires special PCI load/store memory-I/O (MIO) instructions, or the
-special MMIO syscalls when these are not available. Still, such access is
-possible and useful not just for RDMA, in fact not being able to mmap() PCI
-resources has previously caused extra work when testing devices.
-
-One thing that doesn't work with PCI resources mapped to user-space though
-is the s390 specific virtual ISM device. Not only because the BAR size of
-256 TiB prevents mapping the whole BAR but also because access requires use
-of the legacy PCI instructions which are not accessible to user-space on
-systems with the newer MIO PCI instructions.
-
-Now with the pdev->non_mappable_bars flag ISM can be excluded from mapping
-its resources while making this functionality available for all other PCI
-devices. To this end introduce a minimal implementation of PCI_QUIRKS and
-use that to set pdev->non_mappable_bars for ISM devices only. Then also set
-ARCH_GENERIC_PCI_MMAP_RESOURCE to take advantage of the generic
-implementation of pci_mmap_resource_range() enabling only the newer sysfs
-mmap() interface. This follows the recommendation in
-Documentation/PCI/sysfs-pci.rst.
-
-Link: https://lore.kernel.org/r/20250226-vfio_pci_mmap-v7-3-c5c0f1d26efd@linux.ibm.com
-Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
-Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- arch/s390/Kconfig | 4 +---
- arch/s390/include/asm/pci.h | 3 +++
- arch/s390/pci/Makefile | 2 +-
- arch/s390/pci/pci_fixup.c | 23 +++++++++++++++++++++++
- drivers/s390/net/ism_drv.c | 1 -
- include/linux/pci_ids.h | 1 +
- 6 files changed, 29 insertions(+), 5 deletions(-)
- create mode 100644 arch/s390/pci/pci_fixup.c
-
-diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
-index 9c9ec08d78c71..e48741e001476 100644
---- a/arch/s390/Kconfig
-+++ b/arch/s390/Kconfig
-@@ -41,9 +41,6 @@ config AUDIT_ARCH
- config NO_IOPORT_MAP
- def_bool y
-
--config PCI_QUIRKS
-- def_bool n
--
- config ARCH_SUPPORTS_UPROBES
- def_bool y
-
-@@ -258,6 +255,7 @@ config S390
- select PCI_DOMAINS if PCI
- select PCI_MSI if PCI
- select PCI_MSI_ARCH_FALLBACKS if PCI_MSI
-+ select PCI_QUIRKS if PCI
- select SPARSE_IRQ
- select SWIOTLB
- select SYSCTL_EXCEPTION_TRACE
-diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
-index 474e1f8d1d3c2..d2086af3434c0 100644
---- a/arch/s390/include/asm/pci.h
-+++ b/arch/s390/include/asm/pci.h
-@@ -11,6 +11,9 @@
- #include <asm/pci_insn.h>
- #include <asm/sclp.h>
-
-+#define ARCH_GENERIC_PCI_MMAP_RESOURCE 1
-+#define arch_can_pci_mmap_wc() 1
-+
- #define PCIBIOS_MIN_IO 0x1000
- #define PCIBIOS_MIN_MEM 0x10000000
-
-diff --git a/arch/s390/pci/Makefile b/arch/s390/pci/Makefile
-index df73c5182990a..1810e0944a4ed 100644
---- a/arch/s390/pci/Makefile
-+++ b/arch/s390/pci/Makefile
-@@ -5,6 +5,6 @@
-
- obj-$(CONFIG_PCI) += pci.o pci_irq.o pci_clp.o \
- pci_event.o pci_debug.o pci_insn.o pci_mmio.o \
-- pci_bus.o pci_kvm_hook.o pci_report.o
-+ pci_bus.o pci_kvm_hook.o pci_report.o pci_fixup.o
- obj-$(CONFIG_PCI_IOV) += pci_iov.o
- obj-$(CONFIG_SYSFS) += pci_sysfs.o
-diff --git a/arch/s390/pci/pci_fixup.c b/arch/s390/pci/pci_fixup.c
-new file mode 100644
-index 0000000000000..35688b6450983
---- /dev/null
-+++ b/arch/s390/pci/pci_fixup.c
-@@ -0,0 +1,23 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Exceptions for specific devices,
-+ *
-+ * Copyright IBM Corp. 2025
-+ *
-+ * Author(s):
-+ * Niklas Schnelle <schnelle@linux.ibm.com>
-+ */
-+#include <linux/pci.h>
-+
-+static void zpci_ism_bar_no_mmap(struct pci_dev *pdev)
-+{
-+ /*
-+ * ISM's BAR is special. Drivers written for ISM know
-+ * how to handle this but others need to be aware of their
-+ * special nature e.g. to prevent attempts to mmap() it.
-+ */
-+ pdev->non_mappable_bars = 1;
-+}
-+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_IBM,
-+ PCI_DEVICE_ID_IBM_ISM,
-+ zpci_ism_bar_no_mmap);
-diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c
-index 2f34761e64135..60ed70a39d2cc 100644
---- a/drivers/s390/net/ism_drv.c
-+++ b/drivers/s390/net/ism_drv.c
-@@ -20,7 +20,6 @@
- MODULE_DESCRIPTION("ISM driver for s390");
- MODULE_LICENSE("GPL");
-
--#define PCI_DEVICE_ID_IBM_ISM 0x04ED
- #define DRV_NAME "ism"
-
- static const struct pci_device_id ism_device_table[] = {
-diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
-index 2a9ca3dbaa0e9..5bd122a9afdc6 100644
---- a/include/linux/pci_ids.h
-+++ b/include/linux/pci_ids.h
-@@ -518,6 +518,7 @@
- #define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM 0x0251
- #define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM_PCIE 0x0361
- #define PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL 0x252
-+#define PCI_DEVICE_ID_IBM_ISM 0x04ed
-
- #define PCI_SUBVENDOR_ID_IBM 0x1014
- #define PCI_SUBDEVICE_ID_IBM_SATURN_SERIAL_ONE_PORT 0x03d4
---
-2.39.5
-
of-resolver-simplify-of_resolve_phandles-using-__fre.patch
of-resolver-fix-device-node-refcount-leakage-in-of_r.patch
scsi-ufs-qcom-fix-dev-reference-leaked-through-of_qc.patch
-s390-pci-support-mmap-of-pci-resources-except-for-is.patch
pci-msi-convert-pci_msi_ignore_mask-to-per-msi-domai.patch
pci-msi-handle-the-nomask-flag-correctly-for-all-pci.patch
pci-msi-add-an-option-to-write-msix-entry_data-befor.patch
+++ /dev/null
-From bc44df3dd096499912449d45aadf335fcb507754 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 13 Dec 2024 14:47:28 +0100
-Subject: s390/pci: Report PCI error recovery results via SCLP
-
-From: Niklas Schnelle <schnelle@linux.ibm.com>
-
-[ Upstream commit 4ec6054e7321dc24ebccaa08b3af0d590f5666e6 ]
-
-Add a mechanism with which the status of PCI error recovery runs
-is reported to the platform. Together with the status supply additional
-information that may aid in problem determination.
-
-Reviewed-by: Halil Pasic <pasic@linux.ibm.com>
-Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
-Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
-Stable-dep-of: aa9f168d55dc ("s390/pci: Support mmap() of PCI resources except for ISM devices")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- arch/s390/include/asm/sclp.h | 33 +++++++++++
- arch/s390/pci/Makefile | 2 +-
- arch/s390/pci/pci_event.c | 21 +++++--
- arch/s390/pci/pci_report.c | 111 +++++++++++++++++++++++++++++++++++
- arch/s390/pci/pci_report.h | 16 +++++
- drivers/s390/char/sclp.h | 14 -----
- drivers/s390/char/sclp_pci.c | 19 ------
- 7 files changed, 178 insertions(+), 38 deletions(-)
- create mode 100644 arch/s390/pci/pci_report.c
- create mode 100644 arch/s390/pci/pci_report.h
-
-diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h
-index 5742d23bba137..d4a7a178e3584 100644
---- a/arch/s390/include/asm/sclp.h
-+++ b/arch/s390/include/asm/sclp.h
-@@ -16,6 +16,11 @@
- /* 24 + 16 * SCLP_MAX_CORES */
- #define EXT_SCCB_READ_CPU (3 * PAGE_SIZE)
-
-+#define SCLP_ERRNOTIFY_AQ_RESET 0
-+#define SCLP_ERRNOTIFY_AQ_REPAIR 1
-+#define SCLP_ERRNOTIFY_AQ_INFO_LOG 2
-+#define SCLP_ERRNOTIFY_AQ_OPTICS_DATA 3
-+
- #ifndef __ASSEMBLY__
- #include <linux/uio.h>
- #include <asm/chpid.h>
-@@ -109,6 +114,34 @@ struct sclp_info {
- };
- extern struct sclp_info sclp;
-
-+struct sccb_header {
-+ u16 length;
-+ u8 function_code;
-+ u8 control_mask[3];
-+ u16 response_code;
-+} __packed;
-+
-+struct evbuf_header {
-+ u16 length;
-+ u8 type;
-+ u8 flags;
-+ u16 _reserved;
-+} __packed;
-+
-+struct err_notify_evbuf {
-+ struct evbuf_header header;
-+ u8 action;
-+ u8 atype;
-+ u32 fh;
-+ u32 fid;
-+ u8 data[];
-+} __packed;
-+
-+struct err_notify_sccb {
-+ struct sccb_header header;
-+ struct err_notify_evbuf evbuf;
-+} __packed;
-+
- struct zpci_report_error_header {
- u8 version; /* Interface version byte */
- u8 action; /* Action qualifier byte
-diff --git a/arch/s390/pci/Makefile b/arch/s390/pci/Makefile
-index 5ae31ca9dd441..eeef68901a15c 100644
---- a/arch/s390/pci/Makefile
-+++ b/arch/s390/pci/Makefile
-@@ -5,5 +5,5 @@
-
- obj-$(CONFIG_PCI) += pci.o pci_irq.o pci_dma.o pci_clp.o pci_sysfs.o \
- pci_event.o pci_debug.o pci_insn.o pci_mmio.o \
-- pci_bus.o pci_kvm_hook.o
-+ pci_bus.o pci_kvm_hook.o pci_report.o
- obj-$(CONFIG_PCI_IOV) += pci_iov.o
-diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c
-index b3961f1016ea0..ed8c7f61e642b 100644
---- a/arch/s390/pci/pci_event.c
-+++ b/arch/s390/pci/pci_event.c
-@@ -16,6 +16,7 @@
- #include <asm/sclp.h>
-
- #include "pci_bus.h"
-+#include "pci_report.h"
-
- /* Content Code Description for PCI Function Error */
- struct zpci_ccdf_err {
-@@ -162,6 +163,8 @@ static pci_ers_result_t zpci_event_do_reset(struct pci_dev *pdev,
- static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
- {
- pci_ers_result_t ers_res = PCI_ERS_RESULT_DISCONNECT;
-+ struct zpci_dev *zdev = to_zpci(pdev);
-+ char *status_str = "success";
- struct pci_driver *driver;
-
- /*
-@@ -179,29 +182,37 @@ static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
- if (is_passed_through(to_zpci(pdev))) {
- pr_info("%s: Cannot be recovered in the host because it is a pass-through device\n",
- pci_name(pdev));
-+ status_str = "failed (pass-through)";
- goto out_unlock;
- }
-
- driver = to_pci_driver(pdev->dev.driver);
- if (!is_driver_supported(driver)) {
-- if (!driver)
-+ if (!driver) {
- pr_info("%s: Cannot be recovered because no driver is bound to the device\n",
- pci_name(pdev));
-- else
-+ status_str = "failed (no driver)";
-+ } else {
- pr_info("%s: The %s driver bound to the device does not support error recovery\n",
- pci_name(pdev),
- driver->name);
-+ status_str = "failed (no driver support)";
-+ }
- goto out_unlock;
- }
-
- ers_res = zpci_event_notify_error_detected(pdev, driver);
-- if (ers_result_indicates_abort(ers_res))
-+ if (ers_result_indicates_abort(ers_res)) {
-+ status_str = "failed (abort on detection)";
- goto out_unlock;
-+ }
-
- if (ers_res == PCI_ERS_RESULT_CAN_RECOVER) {
- ers_res = zpci_event_do_error_state_clear(pdev, driver);
-- if (ers_result_indicates_abort(ers_res))
-+ if (ers_result_indicates_abort(ers_res)) {
-+ status_str = "failed (abort on MMIO enable)";
- goto out_unlock;
-+ }
- }
-
- if (ers_res == PCI_ERS_RESULT_NEED_RESET)
-@@ -210,6 +221,7 @@ static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
- if (ers_res != PCI_ERS_RESULT_RECOVERED) {
- pr_err("%s: Automatic recovery failed; operator intervention is required\n",
- pci_name(pdev));
-+ status_str = "failed (driver can't recover)";
- goto out_unlock;
- }
-
-@@ -218,6 +230,7 @@ static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
- driver->err_handler->resume(pdev);
- out_unlock:
- pci_dev_unlock(pdev);
-+ zpci_report_status(zdev, "recovery", status_str);
-
- return ers_res;
- }
-diff --git a/arch/s390/pci/pci_report.c b/arch/s390/pci/pci_report.c
-new file mode 100644
-index 0000000000000..2754c9c161f5b
---- /dev/null
-+++ b/arch/s390/pci/pci_report.c
-@@ -0,0 +1,111 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Copyright IBM Corp. 2024
-+ *
-+ * Author(s):
-+ * Niklas Schnelle <schnelle@linux.ibm.com>
-+ *
-+ */
-+
-+#define KMSG_COMPONENT "zpci"
-+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-+
-+#include <linux/kernel.h>
-+#include <linux/sprintf.h>
-+#include <linux/pci.h>
-+
-+#include <asm/sclp.h>
-+
-+#include "pci_report.h"
-+
-+#define ZPCI_ERR_LOG_ID_KERNEL_REPORT 0x4714
-+
-+struct zpci_report_error_data {
-+ u64 timestamp;
-+ u64 err_log_id;
-+ char log_data[];
-+} __packed;
-+
-+#define ZPCI_REPORT_SIZE (PAGE_SIZE - sizeof(struct err_notify_sccb))
-+#define ZPCI_REPORT_DATA_SIZE (ZPCI_REPORT_SIZE - sizeof(struct zpci_report_error_data))
-+
-+struct zpci_report_error {
-+ struct zpci_report_error_header header;
-+ struct zpci_report_error_data data;
-+} __packed;
-+
-+static const char *zpci_state_str(pci_channel_state_t state)
-+{
-+ switch (state) {
-+ case pci_channel_io_normal:
-+ return "normal";
-+ case pci_channel_io_frozen:
-+ return "frozen";
-+ case pci_channel_io_perm_failure:
-+ return "permanent-failure";
-+ default:
-+ return "invalid";
-+ };
-+}
-+
-+/**
-+ * zpci_report_status - Report the status of operations on a PCI device
-+ * @zdev: The PCI device for which to report status
-+ * @operation: A string representing the operation reported
-+ * @status: A string representing the status of the operation
-+ *
-+ * This function creates a human readable report about an operation such as
-+ * PCI device recovery and forwards this to the platform using the SCLP Write
-+ * Event Data mechanism. Besides the operation and status strings the report
-+ * also contains additional information about the device deemed useful for
-+ * debug such as the currently bound device driver, if any, and error state.
-+ *
-+ * Return: 0 on success an error code < 0 otherwise.
-+ */
-+int zpci_report_status(struct zpci_dev *zdev, const char *operation, const char *status)
-+{
-+ struct zpci_report_error *report;
-+ struct pci_driver *driver = NULL;
-+ struct pci_dev *pdev = NULL;
-+ char *buf, *end;
-+ int ret;
-+
-+ if (!zdev || !zdev->zbus)
-+ return -ENODEV;
-+
-+ /* Protected virtualization hosts get nothing from us */
-+ if (prot_virt_guest)
-+ return -ENODATA;
-+
-+ report = (void *)get_zeroed_page(GFP_KERNEL);
-+ if (!report)
-+ return -ENOMEM;
-+ if (zdev->zbus->bus)
-+ pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn);
-+ if (pdev)
-+ driver = to_pci_driver(pdev->dev.driver);
-+
-+ buf = report->data.log_data;
-+ end = report->data.log_data + ZPCI_REPORT_DATA_SIZE;
-+ buf += scnprintf(buf, end - buf, "report: %s\n", operation);
-+ buf += scnprintf(buf, end - buf, "status: %s\n", status);
-+ buf += scnprintf(buf, end - buf, "state: %s\n",
-+ (pdev) ? zpci_state_str(pdev->error_state) : "n/a");
-+ buf += scnprintf(buf, end - buf, "driver: %s\n", (driver) ? driver->name : "n/a");
-+
-+ report->header.version = 1;
-+ report->header.action = SCLP_ERRNOTIFY_AQ_INFO_LOG;
-+ report->header.length = buf - (char *)&report->data;
-+ report->data.timestamp = ktime_get_clocktai_seconds();
-+ report->data.err_log_id = ZPCI_ERR_LOG_ID_KERNEL_REPORT;
-+
-+ ret = sclp_pci_report(&report->header, zdev->fh, zdev->fid);
-+ if (ret)
-+ pr_err("Reporting PCI status failed with code %d\n", ret);
-+ else
-+ pr_info("Reported PCI device status\n");
-+
-+ free_page((unsigned long)report);
-+
-+ return ret;
-+}
-diff --git a/arch/s390/pci/pci_report.h b/arch/s390/pci/pci_report.h
-new file mode 100644
-index 0000000000000..e08003d51a972
---- /dev/null
-+++ b/arch/s390/pci/pci_report.h
-@@ -0,0 +1,16 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright IBM Corp. 2024
-+ *
-+ * Author(s):
-+ * Niklas Schnelle <schnelle@linux.ibm.com>
-+ *
-+ */
-+#ifndef __S390_PCI_REPORT_H
-+#define __S390_PCI_REPORT_H
-+
-+struct zpci_dev;
-+
-+int zpci_report_status(struct zpci_dev *zdev, const char *operation, const char *status);
-+
-+#endif /* __S390_PCI_REPORT_H */
-diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
-index 6a23ec286c702..25fd4d8547483 100644
---- a/drivers/s390/char/sclp.h
-+++ b/drivers/s390/char/sclp.h
-@@ -84,13 +84,6 @@ typedef unsigned int sclp_cmdw_t;
-
- typedef u64 sccb_mask_t;
-
--struct sccb_header {
-- u16 length;
-- u8 function_code;
-- u8 control_mask[3];
-- u16 response_code;
--} __attribute__((packed));
--
- struct init_sccb {
- struct sccb_header header;
- u16 _reserved;
-@@ -237,13 +230,6 @@ struct gds_vector {
- u16 gds_id;
- } __attribute__((packed));
-
--struct evbuf_header {
-- u16 length;
-- u8 type;
-- u8 flags;
-- u16 _reserved;
--} __attribute__((packed));
--
- struct sclp_req {
- struct list_head list; /* list_head for request queueing. */
- sclp_cmdw_t command; /* sclp command to execute */
-diff --git a/drivers/s390/char/sclp_pci.c b/drivers/s390/char/sclp_pci.c
-index c3466a8c56bb5..56400886f7fca 100644
---- a/drivers/s390/char/sclp_pci.c
-+++ b/drivers/s390/char/sclp_pci.c
-@@ -24,30 +24,11 @@
-
- #define SCLP_ATYPE_PCI 2
-
--#define SCLP_ERRNOTIFY_AQ_RESET 0
--#define SCLP_ERRNOTIFY_AQ_REPAIR 1
--#define SCLP_ERRNOTIFY_AQ_INFO_LOG 2
--#define SCLP_ERRNOTIFY_AQ_OPTICS_DATA 3
--
- static DEFINE_MUTEX(sclp_pci_mutex);
- static struct sclp_register sclp_pci_event = {
- .send_mask = EVTYP_ERRNOTIFY_MASK,
- };
-
--struct err_notify_evbuf {
-- struct evbuf_header header;
-- u8 action;
-- u8 atype;
-- u32 fh;
-- u32 fid;
-- u8 data[];
--} __packed;
--
--struct err_notify_sccb {
-- struct sccb_header header;
-- struct err_notify_evbuf evbuf;
--} __packed;
--
- struct pci_cfg_sccb {
- struct sccb_header header;
- u8 atype; /* adapter type */
---
-2.39.5
-
+++ /dev/null
-From bb8589b36d58725be67b9d983251d9a9b1437f2f Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 26 Feb 2025 13:07:47 +0100
-Subject: s390/pci: Support mmap() of PCI resources except for ISM devices
-
-From: Niklas Schnelle <schnelle@linux.ibm.com>
-
-[ Upstream commit aa9f168d55dc47c0de564f7dfe0e90467c9fee71 ]
-
-So far s390 does not allow mmap() of PCI resources to user-space via the
-usual mechanisms, though it does use it for RDMA. For the PCI sysfs
-resource files and /proc/bus/pci it defines neither HAVE_PCI_MMAP nor
-ARCH_GENERIC_PCI_MMAP_RESOURCE. For vfio-pci s390 previously relied on
-disabled VFIO_PCI_MMAP and now relies on setting pdev->non_mappable_bars
-for all devices.
-
-This is partly because access to mapped PCI resources from user-space
-requires special PCI load/store memory-I/O (MIO) instructions, or the
-special MMIO syscalls when these are not available. Still, such access is
-possible and useful not just for RDMA, in fact not being able to mmap() PCI
-resources has previously caused extra work when testing devices.
-
-One thing that doesn't work with PCI resources mapped to user-space though
-is the s390 specific virtual ISM device. Not only because the BAR size of
-256 TiB prevents mapping the whole BAR but also because access requires use
-of the legacy PCI instructions which are not accessible to user-space on
-systems with the newer MIO PCI instructions.
-
-Now with the pdev->non_mappable_bars flag ISM can be excluded from mapping
-its resources while making this functionality available for all other PCI
-devices. To this end introduce a minimal implementation of PCI_QUIRKS and
-use that to set pdev->non_mappable_bars for ISM devices only. Then also set
-ARCH_GENERIC_PCI_MMAP_RESOURCE to take advantage of the generic
-implementation of pci_mmap_resource_range() enabling only the newer sysfs
-mmap() interface. This follows the recommendation in
-Documentation/PCI/sysfs-pci.rst.
-
-Link: https://lore.kernel.org/r/20250226-vfio_pci_mmap-v7-3-c5c0f1d26efd@linux.ibm.com
-Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
-Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- arch/s390/Kconfig | 4 +---
- arch/s390/include/asm/pci.h | 3 +++
- arch/s390/pci/Makefile | 2 +-
- arch/s390/pci/pci_fixup.c | 23 +++++++++++++++++++++++
- drivers/s390/net/ism_drv.c | 1 -
- include/linux/pci_ids.h | 1 +
- 6 files changed, 29 insertions(+), 5 deletions(-)
- create mode 100644 arch/s390/pci/pci_fixup.c
-
-diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
-index bd4782f23f66d..0882016af57c0 100644
---- a/arch/s390/Kconfig
-+++ b/arch/s390/Kconfig
-@@ -38,9 +38,6 @@ config AUDIT_ARCH
- config NO_IOPORT_MAP
- def_bool y
-
--config PCI_QUIRKS
-- def_bool n
--
- config ARCH_SUPPORTS_UPROBES
- def_bool y
-
-@@ -229,6 +226,7 @@ config S390
- select PCI_DOMAINS if PCI
- select PCI_MSI if PCI
- select PCI_MSI_ARCH_FALLBACKS if PCI_MSI
-+ select PCI_QUIRKS if PCI
- select SPARSE_IRQ
- select SWIOTLB
- select SYSCTL_EXCEPTION_TRACE
-diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
-index b248694e00247..211c69cd1f9c9 100644
---- a/arch/s390/include/asm/pci.h
-+++ b/arch/s390/include/asm/pci.h
-@@ -11,6 +11,9 @@
- #include <asm/pci_insn.h>
- #include <asm/sclp.h>
-
-+#define ARCH_GENERIC_PCI_MMAP_RESOURCE 1
-+#define arch_can_pci_mmap_wc() 1
-+
- #define PCIBIOS_MIN_IO 0x1000
- #define PCIBIOS_MIN_MEM 0x10000000
-
-diff --git a/arch/s390/pci/Makefile b/arch/s390/pci/Makefile
-index eeef68901a15c..2f8dd3f688391 100644
---- a/arch/s390/pci/Makefile
-+++ b/arch/s390/pci/Makefile
-@@ -5,5 +5,5 @@
-
- obj-$(CONFIG_PCI) += pci.o pci_irq.o pci_dma.o pci_clp.o pci_sysfs.o \
- pci_event.o pci_debug.o pci_insn.o pci_mmio.o \
-- pci_bus.o pci_kvm_hook.o pci_report.o
-+ pci_bus.o pci_kvm_hook.o pci_report.o pci_fixup.o
- obj-$(CONFIG_PCI_IOV) += pci_iov.o
-diff --git a/arch/s390/pci/pci_fixup.c b/arch/s390/pci/pci_fixup.c
-new file mode 100644
-index 0000000000000..35688b6450983
---- /dev/null
-+++ b/arch/s390/pci/pci_fixup.c
-@@ -0,0 +1,23 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Exceptions for specific devices,
-+ *
-+ * Copyright IBM Corp. 2025
-+ *
-+ * Author(s):
-+ * Niklas Schnelle <schnelle@linux.ibm.com>
-+ */
-+#include <linux/pci.h>
-+
-+static void zpci_ism_bar_no_mmap(struct pci_dev *pdev)
-+{
-+ /*
-+ * ISM's BAR is special. Drivers written for ISM know
-+ * how to handle this but others need to be aware of their
-+ * special nature e.g. to prevent attempts to mmap() it.
-+ */
-+ pdev->non_mappable_bars = 1;
-+}
-+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_IBM,
-+ PCI_DEVICE_ID_IBM_ISM,
-+ zpci_ism_bar_no_mmap);
-diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c
-index af0d90beba638..390ebd4d7f3bc 100644
---- a/drivers/s390/net/ism_drv.c
-+++ b/drivers/s390/net/ism_drv.c
-@@ -20,7 +20,6 @@
- MODULE_DESCRIPTION("ISM driver for s390");
- MODULE_LICENSE("GPL");
-
--#define PCI_DEVICE_ID_IBM_ISM 0x04ED
- #define DRV_NAME "ism"
-
- static const struct pci_device_id ism_device_table[] = {
-diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
-index 3dce2be622e74..dcb9d5ac06937 100644
---- a/include/linux/pci_ids.h
-+++ b/include/linux/pci_ids.h
-@@ -517,6 +517,7 @@
- #define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM 0x0251
- #define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM_PCIE 0x0361
- #define PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL 0x252
-+#define PCI_DEVICE_ID_IBM_ISM 0x04ed
-
- #define PCI_SUBVENDOR_ID_IBM 0x1014
- #define PCI_SUBDEVICE_ID_IBM_SATURN_SERIAL_ONE_PORT 0x03d4
---
-2.39.5
-
+++ /dev/null
-From 3975b23c37050e63853cd7e5082ceda8ea50d152 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 1 Oct 2024 15:07:27 +0200
-Subject: s390/sclp: Allow user-space to provide PCI reports for optical
- modules
-
-From: Niklas Schnelle <schnelle@linux.ibm.com>
-
-[ Upstream commit e9ab04490667249633fb397be17db46a8fa6d130 ]
-
-The new SCLP action qualifier 3 is used by user-space code to provide
-optical module monitoring data to the platform.
-
-Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
-Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
-Stable-dep-of: aa9f168d55dc ("s390/pci: Support mmap() of PCI resources except for ISM devices")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/s390/char/sclp_pci.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/drivers/s390/char/sclp_pci.c b/drivers/s390/char/sclp_pci.c
-index a3e5a5fb0c1e7..c3466a8c56bb5 100644
---- a/drivers/s390/char/sclp_pci.c
-+++ b/drivers/s390/char/sclp_pci.c
-@@ -27,6 +27,7 @@
- #define SCLP_ERRNOTIFY_AQ_RESET 0
- #define SCLP_ERRNOTIFY_AQ_REPAIR 1
- #define SCLP_ERRNOTIFY_AQ_INFO_LOG 2
-+#define SCLP_ERRNOTIFY_AQ_OPTICS_DATA 3
-
- static DEFINE_MUTEX(sclp_pci_mutex);
- static struct sclp_register sclp_pci_event = {
-@@ -116,6 +117,7 @@ static int sclp_pci_check_report(struct zpci_report_error_header *report)
- case SCLP_ERRNOTIFY_AQ_RESET:
- case SCLP_ERRNOTIFY_AQ_REPAIR:
- case SCLP_ERRNOTIFY_AQ_INFO_LOG:
-+ case SCLP_ERRNOTIFY_AQ_OPTICS_DATA:
- break;
- default:
- return -EINVAL;
---
-2.39.5
-
+++ /dev/null
-From 3867566eb8a43354f101dbb141dc38e7f9f8395f Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 2 Apr 2025 22:36:21 +0200
-Subject: s390/virtio_ccw: Don't allocate/assign airqs for non-existing queues
-
-From: David Hildenbrand <david@redhat.com>
-
-[ Upstream commit 2ccd42b959aaf490333dbd3b9b102eaf295c036a ]
-
-If we finds a vq without a name in our input array in
-virtio_ccw_find_vqs(), we treat it as "non-existing" and set the vq pointer
-to NULL; we will not call virtio_ccw_setup_vq() to allocate/setup a vq.
-
-Consequently, we create only a queue if it actually exists (name != NULL)
-and assign an incremental queue index to each such existing queue.
-
-However, in virtio_ccw_register_adapter_ind()->get_airq_indicator() we
-will not ignore these "non-existing queues", but instead assign an airq
-indicator to them.
-
-Besides never releasing them in virtio_ccw_drop_indicators() (because
-there is no virtqueue), the bigger issue seems to be that there will be a
-disagreement between the device and the Linux guest about the airq
-indicator to be used for notifying a queue, because the indicator bit
-for adapter I/O interrupt is derived from the queue index.
-
-The virtio spec states under "Setting Up Two-Stage Queue Indicators":
-
- ... indicator contains the guest address of an area wherein the
- indicators for the devices are contained, starting at bit_nr, one
- bit per virtqueue of the device.
-
-And further in "Notification via Adapter I/O Interrupts":
-
- For notifying the driver of virtqueue buffers, the device sets the
- bit in the guest-provided indicator area at the corresponding
- offset.
-
-For example, QEMU uses in virtio_ccw_notify() the queue index (passed as
-"vector") to select the relevant indicator bit. If a queue does not exist,
-it does not have a corresponding indicator bit assigned, because it
-effectively doesn't have a queue index.
-
-Using a virtio-balloon-ccw device under QEMU with free-page-hinting
-disabled ("free-page-hint=off") but free-page-reporting enabled
-("free-page-reporting=on") will result in free page reporting
-not working as expected: in the virtio_balloon driver, we'll be stuck
-forever in virtballoon_free_page_report()->wait_event(), because the
-waitqueue will not be woken up as the notification from the device is
-lost: it would use the wrong indicator bit.
-
-Free page reporting stops working and we get splats (when configured to
-detect hung wqs) like:
-
- INFO: task kworker/1:3:463 blocked for more than 61 seconds.
- Not tainted 6.14.0 #4
- "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
- task:kworker/1:3 [...]
- Workqueue: events page_reporting_process
- Call Trace:
- [<000002f404e6dfb2>] __schedule+0x402/0x1640
- [<000002f404e6f22e>] schedule+0x3e/0xe0
- [<000002f3846a88fa>] virtballoon_free_page_report+0xaa/0x110 [virtio_balloon]
- [<000002f40435c8a4>] page_reporting_process+0x2e4/0x740
- [<000002f403fd3ee2>] process_one_work+0x1c2/0x400
- [<000002f403fd4b96>] worker_thread+0x296/0x420
- [<000002f403fe10b4>] kthread+0x124/0x290
- [<000002f403f4e0dc>] __ret_from_fork+0x3c/0x60
- [<000002f404e77272>] ret_from_fork+0xa/0x38
-
-There was recently a discussion [1] whether the "holes" should be
-treated differently again, effectively assigning also non-existing
-queues a queue index: that should also fix the issue, but requires other
-workarounds to not break existing setups.
-
-Let's fix it without affecting existing setups for now by properly ignoring
-the non-existing queues, so the indicator bits will match the queue
-indexes.
-
-[1] https://lore.kernel.org/all/cover.1720611677.git.mst@redhat.com/
-
-Fixes: a229989d975e ("virtio: don't allocate vqs when names[i] = NULL")
-Reported-by: Chandra Merla <cmerla@redhat.com>
-Cc: stable@vger.kernel.org
-Signed-off-by: David Hildenbrand <david@redhat.com>
-Tested-by: Thomas Huth <thuth@redhat.com>
-Reviewed-by: Thomas Huth <thuth@redhat.com>
-Reviewed-by: Cornelia Huck <cohuck@redhat.com>
-Acked-by: Michael S. Tsirkin <mst@redhat.com>
-Acked-by: Christian Borntraeger <borntraeger@linux.ibm.com>
-Link: https://lore.kernel.org/r/20250402203621.940090-1-david@redhat.com
-Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/s390/virtio/virtio_ccw.c | 16 ++++++++++++----
- 1 file changed, 12 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
-index ac77951c30c46..75aeb7f8ed099 100644
---- a/drivers/s390/virtio/virtio_ccw.c
-+++ b/drivers/s390/virtio/virtio_ccw.c
-@@ -263,11 +263,17 @@ static struct airq_info *new_airq_info(int index)
- static unsigned long *get_airq_indicator(struct virtqueue *vqs[], int nvqs,
- u64 *first, void **airq_info)
- {
-- int i, j;
-+ int i, j, queue_idx, highest_queue_idx = -1;
- struct airq_info *info;
- unsigned long *indicator_addr = NULL;
- unsigned long bit, flags;
-
-+ /* Array entries without an actual queue pointer must be ignored. */
-+ for (i = 0; i < nvqs; i++) {
-+ if (vqs[i])
-+ highest_queue_idx++;
-+ }
-+
- for (i = 0; i < MAX_AIRQ_AREAS && !indicator_addr; i++) {
- mutex_lock(&airq_areas_lock);
- if (!airq_areas[i])
-@@ -277,7 +283,7 @@ static unsigned long *get_airq_indicator(struct virtqueue *vqs[], int nvqs,
- if (!info)
- return NULL;
- write_lock_irqsave(&info->lock, flags);
-- bit = airq_iv_alloc(info->aiv, nvqs);
-+ bit = airq_iv_alloc(info->aiv, highest_queue_idx + 1);
- if (bit == -1UL) {
- /* Not enough vacancies. */
- write_unlock_irqrestore(&info->lock, flags);
-@@ -286,8 +292,10 @@ static unsigned long *get_airq_indicator(struct virtqueue *vqs[], int nvqs,
- *first = bit;
- *airq_info = info;
- indicator_addr = info->aiv->vector;
-- for (j = 0; j < nvqs; j++) {
-- airq_iv_set_ptr(info->aiv, bit + j,
-+ for (j = 0, queue_idx = 0; j < nvqs; j++) {
-+ if (!vqs[j])
-+ continue;
-+ airq_iv_set_ptr(info->aiv, bit + queue_idx++,
- (unsigned long)vqs[j]);
- }
- write_unlock_irqrestore(&info->lock, flags);
---
-2.39.5
-
+++ /dev/null
-From 060468bc4467e6f881fe984e6dc8054999ede5d7 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 7 Mar 2024 13:28:07 +0100
-Subject: s390/virtio_ccw: fix virtual vs physical address confusion
-
-From: Halil Pasic <pasic@linux.ibm.com>
-
-[ Upstream commit d5cc41686990fa522ce573e5c6c7a619f10c3fd1 ]
-
-Fix virtual vs physical address confusion and use new dma types and helper
-functions to allow for type checking. This does not fix a bug since virtual
-and physical address spaces are currently the same.
-
-Signed-off-by: Halil Pasic <pasic@linux.ibm.com>
-Reviewed-by: Eric Farman <farman@linux.ibm.com>
-Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
-Stable-dep-of: 2ccd42b959aa ("s390/virtio_ccw: Don't allocate/assign airqs for non-existing queues")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/s390/virtio/virtio_ccw.c | 78 ++++++++++++++++----------------
- 1 file changed, 39 insertions(+), 39 deletions(-)
-
-diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
-index ac67576301bf5..ac77951c30c46 100644
---- a/drivers/s390/virtio/virtio_ccw.c
-+++ b/drivers/s390/virtio/virtio_ccw.c
-@@ -85,19 +85,19 @@ static inline unsigned long *indicators2(struct virtio_ccw_device *vcdev)
- }
-
- struct vq_info_block_legacy {
-- __u64 queue;
-+ dma64_t queue;
- __u32 align;
- __u16 index;
- __u16 num;
- } __packed;
-
- struct vq_info_block {
-- __u64 desc;
-+ dma64_t desc;
- __u32 res0;
- __u16 index;
- __u16 num;
-- __u64 avail;
-- __u64 used;
-+ dma64_t avail;
-+ dma64_t used;
- } __packed;
-
- struct virtio_feature_desc {
-@@ -106,8 +106,8 @@ struct virtio_feature_desc {
- } __packed;
-
- struct virtio_thinint_area {
-- unsigned long summary_indicator;
-- unsigned long indicator;
-+ dma64_t summary_indicator;
-+ dma64_t indicator;
- u64 bit_nr;
- u8 isc;
- } __packed;
-@@ -260,12 +260,12 @@ static struct airq_info *new_airq_info(int index)
- return info;
- }
-
--static unsigned long get_airq_indicator(struct virtqueue *vqs[], int nvqs,
-- u64 *first, void **airq_info)
-+static unsigned long *get_airq_indicator(struct virtqueue *vqs[], int nvqs,
-+ u64 *first, void **airq_info)
- {
- int i, j;
- struct airq_info *info;
-- unsigned long indicator_addr = 0;
-+ unsigned long *indicator_addr = NULL;
- unsigned long bit, flags;
-
- for (i = 0; i < MAX_AIRQ_AREAS && !indicator_addr; i++) {
-@@ -275,7 +275,7 @@ static unsigned long get_airq_indicator(struct virtqueue *vqs[], int nvqs,
- info = airq_areas[i];
- mutex_unlock(&airq_areas_lock);
- if (!info)
-- return 0;
-+ return NULL;
- write_lock_irqsave(&info->lock, flags);
- bit = airq_iv_alloc(info->aiv, nvqs);
- if (bit == -1UL) {
-@@ -285,7 +285,7 @@ static unsigned long get_airq_indicator(struct virtqueue *vqs[], int nvqs,
- }
- *first = bit;
- *airq_info = info;
-- indicator_addr = (unsigned long)info->aiv->vector;
-+ indicator_addr = info->aiv->vector;
- for (j = 0; j < nvqs; j++) {
- airq_iv_set_ptr(info->aiv, bit + j,
- (unsigned long)vqs[j]);
-@@ -358,11 +358,11 @@ static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev,
- if (!thinint_area)
- return;
- thinint_area->summary_indicator =
-- (unsigned long) get_summary_indicator(airq_info);
-+ virt_to_dma64(get_summary_indicator(airq_info));
- thinint_area->isc = VIRTIO_AIRQ_ISC;
- ccw->cmd_code = CCW_CMD_SET_IND_ADAPTER;
- ccw->count = sizeof(*thinint_area);
-- ccw->cda = (__u32)virt_to_phys(thinint_area);
-+ ccw->cda = virt_to_dma32(thinint_area);
- } else {
- /* payload is the address of the indicators */
- indicatorp = ccw_device_dma_zalloc(vcdev->cdev,
-@@ -372,7 +372,7 @@ static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev,
- *indicatorp = 0;
- ccw->cmd_code = CCW_CMD_SET_IND;
- ccw->count = sizeof(indicators(vcdev));
-- ccw->cda = (__u32)virt_to_phys(indicatorp);
-+ ccw->cda = virt_to_dma32(indicatorp);
- }
- /* Deregister indicators from host. */
- *indicators(vcdev) = 0;
-@@ -426,7 +426,7 @@ static int virtio_ccw_read_vq_conf(struct virtio_ccw_device *vcdev,
- ccw->cmd_code = CCW_CMD_READ_VQ_CONF;
- ccw->flags = 0;
- ccw->count = sizeof(struct vq_config_block);
-- ccw->cda = (__u32)virt_to_phys(&vcdev->dma_area->config_block);
-+ ccw->cda = virt_to_dma32(&vcdev->dma_area->config_block);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_VQ_CONF);
- if (ret)
- return ret;
-@@ -463,7 +463,7 @@ static void virtio_ccw_del_vq(struct virtqueue *vq, struct ccw1 *ccw)
- }
- ccw->cmd_code = CCW_CMD_SET_VQ;
- ccw->flags = 0;
-- ccw->cda = (__u32)virt_to_phys(info->info_block);
-+ ccw->cda = virt_to_dma32(info->info_block);
- ret = ccw_io_helper(vcdev, ccw,
- VIRTIO_CCW_DOING_SET_VQ | index);
- /*
-@@ -556,22 +556,22 @@ static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev,
- /* Register it with the host. */
- queue = virtqueue_get_desc_addr(vq);
- if (vcdev->revision == 0) {
-- info->info_block->l.queue = queue;
-+ info->info_block->l.queue = u64_to_dma64(queue);
- info->info_block->l.align = KVM_VIRTIO_CCW_RING_ALIGN;
- info->info_block->l.index = i;
- info->info_block->l.num = info->num;
- ccw->count = sizeof(info->info_block->l);
- } else {
-- info->info_block->s.desc = queue;
-+ info->info_block->s.desc = u64_to_dma64(queue);
- info->info_block->s.index = i;
- info->info_block->s.num = info->num;
-- info->info_block->s.avail = (__u64)virtqueue_get_avail_addr(vq);
-- info->info_block->s.used = (__u64)virtqueue_get_used_addr(vq);
-+ info->info_block->s.avail = u64_to_dma64(virtqueue_get_avail_addr(vq));
-+ info->info_block->s.used = u64_to_dma64(virtqueue_get_used_addr(vq));
- ccw->count = sizeof(info->info_block->s);
- }
- ccw->cmd_code = CCW_CMD_SET_VQ;
- ccw->flags = 0;
-- ccw->cda = (__u32)virt_to_phys(info->info_block);
-+ ccw->cda = virt_to_dma32(info->info_block);
- err = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_VQ | i);
- if (err) {
- dev_warn(&vcdev->cdev->dev, "SET_VQ failed\n");
-@@ -605,7 +605,7 @@ static int virtio_ccw_register_adapter_ind(struct virtio_ccw_device *vcdev,
- {
- int ret;
- struct virtio_thinint_area *thinint_area = NULL;
-- unsigned long indicator_addr;
-+ unsigned long *indicator_addr;
- struct airq_info *info;
-
- thinint_area = ccw_device_dma_zalloc(vcdev->cdev,
-@@ -622,15 +622,15 @@ static int virtio_ccw_register_adapter_ind(struct virtio_ccw_device *vcdev,
- ret = -ENOSPC;
- goto out;
- }
-- thinint_area->indicator = virt_to_phys((void *)indicator_addr);
-+ thinint_area->indicator = virt_to_dma64(indicator_addr);
- info = vcdev->airq_info;
- thinint_area->summary_indicator =
-- virt_to_phys(get_summary_indicator(info));
-+ virt_to_dma64(get_summary_indicator(info));
- thinint_area->isc = VIRTIO_AIRQ_ISC;
- ccw->cmd_code = CCW_CMD_SET_IND_ADAPTER;
- ccw->flags = CCW_FLAG_SLI;
- ccw->count = sizeof(*thinint_area);
-- ccw->cda = (__u32)virt_to_phys(thinint_area);
-+ ccw->cda = virt_to_dma32(thinint_area);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_IND_ADAPTER);
- if (ret) {
- if (ret == -EOPNOTSUPP) {
-@@ -658,7 +658,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
- struct irq_affinity *desc)
- {
- struct virtio_ccw_device *vcdev = to_vc_device(vdev);
-- unsigned long *indicatorp = NULL;
-+ dma64_t *indicatorp = NULL;
- int ret, i, queue_idx = 0;
- struct ccw1 *ccw;
-
-@@ -690,7 +690,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
- sizeof(indicators(vcdev)));
- if (!indicatorp)
- goto out;
-- *indicatorp = (unsigned long) indicators(vcdev);
-+ *indicatorp = virt_to_dma64(indicators(vcdev));
- if (vcdev->is_thinint) {
- ret = virtio_ccw_register_adapter_ind(vcdev, vqs, nvqs, ccw);
- if (ret)
-@@ -703,18 +703,18 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
- ccw->cmd_code = CCW_CMD_SET_IND;
- ccw->flags = 0;
- ccw->count = sizeof(indicators(vcdev));
-- ccw->cda = (__u32)virt_to_phys(indicatorp);
-+ ccw->cda = virt_to_dma32(indicatorp);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_IND);
- if (ret)
- goto out;
- }
- /* Register indicators2 with host for config changes */
-- *indicatorp = (unsigned long) indicators2(vcdev);
-+ *indicatorp = virt_to_dma64(indicators2(vcdev));
- *indicators2(vcdev) = 0;
- ccw->cmd_code = CCW_CMD_SET_CONF_IND;
- ccw->flags = 0;
- ccw->count = sizeof(indicators2(vcdev));
-- ccw->cda = (__u32)virt_to_phys(indicatorp);
-+ ccw->cda = virt_to_dma32(indicatorp);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_CONF_IND);
- if (ret)
- goto out;
-@@ -776,7 +776,7 @@ static u64 virtio_ccw_get_features(struct virtio_device *vdev)
- ccw->cmd_code = CCW_CMD_READ_FEAT;
- ccw->flags = 0;
- ccw->count = sizeof(*features);
-- ccw->cda = (__u32)virt_to_phys(features);
-+ ccw->cda = virt_to_dma32(features);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_FEAT);
- if (ret) {
- rc = 0;
-@@ -793,7 +793,7 @@ static u64 virtio_ccw_get_features(struct virtio_device *vdev)
- ccw->cmd_code = CCW_CMD_READ_FEAT;
- ccw->flags = 0;
- ccw->count = sizeof(*features);
-- ccw->cda = (__u32)virt_to_phys(features);
-+ ccw->cda = virt_to_dma32(features);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_FEAT);
- if (ret == 0)
- rc |= (u64)le32_to_cpu(features->features) << 32;
-@@ -846,7 +846,7 @@ static int virtio_ccw_finalize_features(struct virtio_device *vdev)
- ccw->cmd_code = CCW_CMD_WRITE_FEAT;
- ccw->flags = 0;
- ccw->count = sizeof(*features);
-- ccw->cda = (__u32)virt_to_phys(features);
-+ ccw->cda = virt_to_dma32(features);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT);
- if (ret)
- goto out_free;
-@@ -860,7 +860,7 @@ static int virtio_ccw_finalize_features(struct virtio_device *vdev)
- ccw->cmd_code = CCW_CMD_WRITE_FEAT;
- ccw->flags = 0;
- ccw->count = sizeof(*features);
-- ccw->cda = (__u32)virt_to_phys(features);
-+ ccw->cda = virt_to_dma32(features);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT);
-
- out_free:
-@@ -892,7 +892,7 @@ static void virtio_ccw_get_config(struct virtio_device *vdev,
- ccw->cmd_code = CCW_CMD_READ_CONF;
- ccw->flags = 0;
- ccw->count = offset + len;
-- ccw->cda = (__u32)virt_to_phys(config_area);
-+ ccw->cda = virt_to_dma32(config_area);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_CONFIG);
- if (ret)
- goto out_free;
-@@ -939,7 +939,7 @@ static void virtio_ccw_set_config(struct virtio_device *vdev,
- ccw->cmd_code = CCW_CMD_WRITE_CONF;
- ccw->flags = 0;
- ccw->count = offset + len;
-- ccw->cda = (__u32)virt_to_phys(config_area);
-+ ccw->cda = virt_to_dma32(config_area);
- ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_CONFIG);
-
- out_free:
-@@ -963,7 +963,7 @@ static u8 virtio_ccw_get_status(struct virtio_device *vdev)
- ccw->cmd_code = CCW_CMD_READ_STATUS;
- ccw->flags = 0;
- ccw->count = sizeof(vcdev->dma_area->status);
-- ccw->cda = (__u32)virt_to_phys(&vcdev->dma_area->status);
-+ ccw->cda = virt_to_dma32(&vcdev->dma_area->status);
- ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_STATUS);
- /*
- * If the channel program failed (should only happen if the device
-@@ -992,11 +992,11 @@ static void virtio_ccw_set_status(struct virtio_device *vdev, u8 status)
- ccw->cmd_code = CCW_CMD_WRITE_STATUS;
- ccw->flags = 0;
- ccw->count = sizeof(status);
-- ccw->cda = (__u32)virt_to_phys(&vcdev->dma_area->status);
- /* We use ssch for setting the status which is a serializing
- * instruction that guarantees the memory writes have
- * completed before ssch.
- */
-+ ccw->cda = virt_to_dma32(&vcdev->dma_area->status);
- ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_STATUS);
- /* Write failed? We assume status is unchanged. */
- if (ret)
-@@ -1291,7 +1291,7 @@ static int virtio_ccw_set_transport_rev(struct virtio_ccw_device *vcdev)
- ccw->cmd_code = CCW_CMD_SET_VIRTIO_REV;
- ccw->flags = 0;
- ccw->count = sizeof(*rev);
-- ccw->cda = (__u32)virt_to_phys(rev);
-+ ccw->cda = virt_to_dma32(rev);
-
- vcdev->revision = VIRTIO_CCW_REV_MAX;
- do {
---
-2.39.5
-
of-resolver-simplify-of_resolve_phandles-using-__fre.patch
of-resolver-fix-device-node-refcount-leakage-in-of_r.patch
pci-fix-reference-leak-in-pci_register_host_bridge.patch
-s390-virtio_ccw-fix-virtual-vs-physical-address-conf.patch
-s390-virtio_ccw-don-t-allocate-assign-airqs-for-non-.patch
scsi-ufs-qcom-fix-dev-reference-leaked-through-of_qc.patch
-s390-sclp-allow-user-space-to-provide-pci-reports-fo.patch
-s390-pci-report-pci-error-recovery-results-via-sclp.patch
-s390-pci-support-mmap-of-pci-resources-except-for-is.patch
sched-topology-consolidate-and-clean-up-access-to-a-.patch
sched-cpufreq-rework-schedutil-governor-performance-.patch
cpufreq-sched-explicitly-synchronize-limits_changed-.patch