From 43c30e677d9d22fc2b7158f41b002d950e96c489 Mon Sep 17 00:00:00 2001 From: YunYi Yang Date: Fri, 10 Nov 2023 21:18:10 +0800 Subject: [PATCH] Add features and bugfixes of the Hisi SAS driver --- kernel.spec | 259 +- ...-management-code-into-a-new-source-f.patch | 679 ++++ ...pm_add_request-and-blk_pm_put_reques.patch | 126 + ...lock-Schedule-runtime-resume-earlier.patch | 68 + ...eezing-of-a-queue-while-requests-are.patch | 53 + ...et_request-block-for-non-PM-requests.patch | 185 ++ ...support-for-runtime-power-management.patch | 73 + ...-need-to-check-return-value-of-debug.patch | 165 + ...x-type-casting-and-missing-static-qu.patch | 134 + ...x-losing-directly-attached-disk-when.patch | 193 ++ ...e-pci_irq_get_affinity-for-v3-hw-as-.patch | 230 ++ ...0329-scsi-hisi_sas-Some-misc-tidy-up.patch | 315 ++ ...ke-max-IPTT-count-equal-for-all-hw-r.patch | 222 ++ ...x-pointer-usage-error-in-show-debugf.patch | 58 + ...apshot-HW-cache-of-IOST-and-ITCT-at-.patch | 335 ++ ...apshot-AXI-and-RAS-register-at-debug.patch | 345 ++ ...op-kmap_atomic-in-SMP-command-comple.patch | 105 + ..._sas-Drop-SMP-resp-frame-DMA-mapping.patch | 190 ++ ...op-free_irq-when-devm_request_irq-fa.patch | 175 ++ ...dify-return-type-of-debugfs-function.patch | 168 + ...isi_sas-Remove-some-unnecessary-code.patch | 55 + ...move-set-but-not-used-variable-irq_v.patch | 50 + ...e-devm_platform_ioremap_resource-to-.patch | 46 + ...d-debugfs-auto-trigger-for-internal-.patch | 44 + ...sas-Remove-hisi_sas_hw.slot_complete.patch | 84 + ...as-Remove-redundant-work-declaration.patch | 41 + ...emove-some-unused-function-arguments.patch | 153 + ...d-hisi_sas_debugfs_alloc-to-centrali.patch | 257 ++ ...-fix-spelling-mistake-digial-digital.patch | 45 + ...hisi_sas-Make-three-functions-static.patch | 59 + ...n-t-create-debugfs-dump-folder-twice.patch | 55 + ...sas-Add-timestamp-for-a-debugfs-dump.patch | 93 + ...as-Add-debugfs-file-structure-for-CQ.patch | 141 + ...as-Add-debugfs-file-structure-for-DQ.patch | 121 + ...d-debugfs-file-structure-for-registe.patch | 224 ++ ...-Add-debugfs-file-structure-for-port.patch | 126 + ...-Add-debugfs-file-structure-for-IOST.patch | 119 + ...-Add-debugfs-file-structure-for-ITCT.patch | 132 + ...d-debugfs-file-structure-for-IOST-ca.patch | 113 + ...d-debugfs-file-structure-for-ITCT-ca.patch | 112 + ...locate-memory-for-multiple-dumps-of-.patch | 403 +++ ...d-module-parameter-for-debugfs-dump-.patch | 91 + ...d-ability-to-have-multiple-debugfs-d.patch | 283 ++ ...lete-the-debugfs-folder-of-hisi_sas-.patch | 63 + ...Record-the-phy-down-event-in-debugfs.patch | 153 + ...turn-directly-if-init-hardware-faile.patch | 43 + ...s-Stop-converting-a-bool-into-a-bool.patch | 42 + ...place-magic-number-when-handle-chann.patch | 81 + ...dify-the-file-permissions-of-trigger.patch | 45 + ...d-prints-for-v3-hw-interrupt-converg.patch | 56 + ..._sas-Rename-hisi_sas_cq.pci_irq_mask.patch | 74 + ...e-dev_err-in-read_iost_itct_cache_v3.patch | 55 + ...as-Fix-build-error-without-SATA_HOST.patch | 50 + ...-hisi_sas-Display-proc_name-in-sysfs.patch | 78 + ...dify-the-commit-information-for-DSM-.patch | 54 + ...d-SAS_RAS_INTR0-to-debugfs-register-.patch | 44 + ...op-returning-error-code-from-slot_co.patch | 233 ++ ...-not-reset-phy-timer-to-wait-for-str.patch | 54 + ...isi_sas-Remove-one-kerneldoc-comment.patch | 42 + ...HIPRI-and-inherit-it-from-IOCB_HIPRI.patch | 121 + patches/0378-blk-mq-kill-q-mq_map.patch | 129 + ...due-to-change-of-struct-struct-reque.patch | 38 + .../0380-blk-mq-abstract-out-queue-map.patch | 476 +++ ...due-to-change-of-function-blk_mq_map.patch | 258 ++ ...e-dummy-blk_mq_map_queue_type-helper.patch | 58 + ...n-request-bio-flags-to-queue-mapping.patch | 424 +++ ...due-to-change-of-struct-blk_mq_alloc.patch | 43 + ...tware-queue-to-map-to-multiple-hardw.patch | 165 + ...due-to-change-of-struct-blk_mq_hw_ct.patch | 79 + ...attribute-to-the-sysfs-hctx-director.patch | 65 + ...88-blk-mq-support-multiple-hctx-maps.patch | 318 ++ ...due-to-change-of-struct-blk_mq_tag_s.patch | 81 + ...number-of-hardware-queues-from-nr_cp.patch | 111 + ...cache-request-hardware-queue-mapping.patch | 268 ++ ...oken-due-to-change-of-struct-request.patch | 44 + ...q-cleanup-and-improve-list-insertion.patch | 140 + ...394-blk-mq-improve-plug-list-sorting.patch | 75 + ...tial-support-for-multiple-queue-maps.patch | 110 + ...move-queues-types-to-the-block-layer.patch | 174 + ...K_MQ_F_TAG_SHARED-as-BLK_MQ_F_TAG_QU.patch | 187 ++ ...q-Rename-blk_mq_update_tag_set_depth.patch | 68 + ...-tags-in-blk_mq_init_tags-upon-error.patch | 83 + ...-blk-mq-Pass-flags-for-tag-init-free.patch | 267 ++ ...pointers-for-blk_mq_tags-bitmap-tags.patch | 270 ++ ...-due-to-change-of-struct-blk_mq_tags.patch | 53 + ...cilitate-a-shared-sbitmap-per-tagset.patch | 321 ++ ...due-to-change-of-struct-blk_mq_tag_s.patch | 51 + .../0405-blk-mq-Relocate-hctx_may_queue.patch | 133 + ..._active_requests-per-queue-for-when-.patch | 140 + ...due-to-change-of-struct-request_queu.patch | 46 + ...tive_queues_shared_sbitmap-per-tag_s.patch | 165 + ...due-to-change-of-struct-blk_mq_tag_s.patch | 51 + ...t-and-host-template-flag-host_tagset.patch | 100 + ...due-to-change-of-struct-scsi_host_te.patch | 84 + ...scsi-core-Show-nr_hw_queues-in-sysfs.patch | 62 + ...413-scsi-hisi_sas-Switch-v3-hw-to-MQ.patch | 258 ++ ...csi-scsi_debug-Support-hostwide-tags.patch | 241 ++ ...-scsi-scsi_debug-Support-host-tagset.patch | 96 + ...dify-macro-name-for-OOB-phy-linkrate.patch | 74 + ...-not-modify-upper-fields-of-PROG_PHY.patch | 96 + ...ke-phy-index-variable-name-consisten.patch | 162 + ...isi_sas-Add-BIST-support-for-phy-FFE.patch | 250 ++ ...d-BIST-support-for-fixed-code-patter.patch | 181 ++ ...1-scsi-hisi_sas-Add-missing-newlines.patch | 155 + ...422-scsi-hisi_sas-Code-style-cleanup.patch | 85 + ...e-link-state-checks-in-rpm_get-put_s.patch | 98 + ...e-hisi_hba-cq_nvecs-for-calling-call.patch | 81 + ...itch-to-new-framework-to-support-sus.patch | 87 + ...d-controller-runtime-PM-support-for-.patch | 155 + ...-Add-check-for-methods-_PS0-and-_PR0.patch | 69 + ...d-device-link-between-SCSI-devices-a.patch | 86 + ...cover-PHY-state-according-to-the-sta.patch | 55 + ...-Stop-using-queue-0-always-for-v2-hw.patch | 50 + ...runtime-PM-references-to-supplier-on.patch | 121 + ...ntime-Drop-pm_runtime_clean_up_links.patch | 122 + ...e-the-device-earlier-in-__device_rel.patch | 71 + ...lect-a-suitable-queue-for-internal-I.patch | 82 + ...ix-up-probe-error-handling-for-v3-hw.patch | 119 + ...ort-to-skip-power-management-in-devi.patch | 162 + ...-due-to-change-of-struct-dev_pm_info.patch | 37 + ...device-link-support-for-SYNC_STATE_O.patch | 187 ++ ...-Expose-device-link-details-in-sysfs.patch | 552 ++++ ...-due-to-change-of-struct-device_link.patch | 45 + ...sleeping-in-invalid-context-during-d.patch | 144 + ...drivers-base-Fix-device-link-removal.patch | 156 + ...ken-due-to-change-of-struct-dev_link.patch | 41 + ...aid_sas-Rename-scratch_pad-registers.patch | 309 ++ ..._sas-Introduce-new-Aero-adapter-type.patch | 90 + ...s-Load-balance-completions-across-al.patch | 192 ++ ...s-RAID1-PCI-bandwidth-limit-algorith.patch | 118 + ...sas-Add-support-for-High-IOPS-queues.patch | 299 ++ ...s-Enable-coalescing-for-high-IOPS-qu.patch | 64 + ...s-Use-high-IOPS-queues-based-on-IO-w.patch | 125 + ...s-Introduce-various-Aero-performance.patch | 283 ++ ...s-Use-Block-layer-API-to-check-SCSI-.patch | 127 + ...s-Added-support-for-shared-host-tags.patch | 201 ++ ...duce-some-indirection-in-v3-hw-drive.patch | 67 + ...as-Move-debugfs-code-to-v3-hw-driver.patch | 2796 +++++++++++++++++ ...456-scsi-hisi_sas-Remove-preemptible.patch | 72 + ...e-threaded-irq-to-process-CQ-interru.patch | 325 ++ ...e-Introduce-struct-irq_affinity_desc.patch | 457 +++ ...ken-due-to-change-of-struct-msi_desc.patch | 38 + ...60-resource-Add-irqresource_disabled.patch | 54 + ...Add-is_managed-to-struct-irq_affinit.patch | 146 + ...ffinity-Add-irq_update_affinity_desc.patch | 155 + ...form-Add-devm_platform_get_irqs_affi.patch | 208 ++ ...-hisi_sas-Expose-HW-queues-for-v2-hw.patch | 242 ++ ...move-auto_affine_msi_experimental-mo.patch | 52 + ...oduce-a-_gfp-variant-of-event-notifi.patch | 281 ++ ...gfp_t-flags-to-libsas-event-notifier.patch | 174 + ...s-gfp_t-flags-in-isci_port_link_down.patch | 264 ++ ...ass-gfp_t-flags-in-isci_port_link_up.patch | 145 + ...fp_t-flags-in-isci_port_bc_change_re.patch | 213 ++ ...-Pass-gfp_t-flags-to-event-notifiers.patch | 71 + ...-gfp_t-flags-to-libsas-event-notifie.patch | 420 +++ ...s-gfp_t-flags-to-libsas-event-notifi.patch | 155 + ...ss-gfp_t-flags-to-libsas-event-notif.patch | 299 ++ ...gfp_t-flags-parameter-to-event-notif.patch | 288 ++ ...due-to-change-of-struct-sas_ha_struc.patch | 44 + ...itch-back-to-original-libsas-event-n.patch | 133 + ...tch-back-to-original-libsas-event-no.patch | 134 + ...ch-back-to-original-libsas-event-not.patch | 366 +++ ...ch-back-to-original-event-notifiers-.patch | 103 + ...-back-to-original-libsas-event-notif.patch | 79 + ...h-back-to-original-libsas-event-noti.patch | 81 + ...ve-temporarily-added-_gfp-API-varian.patch | 138 + ...move-deferred-probe-check-in-hisi_sa.patch | 60 + ...n-t-check-.nr_hw_queues-in-hisi_sas_.patch | 65 + ...as-Enable-debugfs-support-by-default.patch | 81 + ...i_sas-Add-trace-FIFO-debugfs-support.patch | 385 +++ ...int-SAS-address-for-v3-hw-erroneous-.patch | 57 + ...ll-sas_unregister_ha-to-roll-back-if.patch | 78 + ...rectly-snapshot-registers-when-execu.patch | 175 ++ ...rn-in-v3-hw-channel-interrupt-handle.patch | 66 + ...int-SATA-device-SAS-address-for-soft.patch | 53 + ...as-Put-a-limit-of-link-reset-retries.patch | 90 + ...n-I_T-nexus-resets-in-parallel-for-c.patch | 98 + ...-hisi_sas-Include-HZ-in-timer-macros.patch | 140 + ...set-controller-for-internal-abort-ti.patch | 194 ++ ...eed-up-error-handling-when-internal-.patch | 90 + ...98-scsi-libsas-Export-sas_phy_enable.patch | 73 + ...itialise-devices-in-.slave_alloc-cal.patch | 127 + ...it-for-phyup-in-hisi_sas_control_phy.patch | 265 ++ ...t-always-drain-event-workqueue-for-H.patch | 127 + ...spin_lock-unlock-to-protect-asd_sas_.patch | 56 + ...x-some-issues-related-to-asd_sas_por.patch | 91 + ...pin_lock-unlock-to-protect-asd_sas_p.patch | 65 + ...4xx-hisi_sas-mvsas-pm8001-Use-dev_is.patch | 502 +++ ...rt-PORTE_BROADCAST_RCVD-event-for-re.patch | 84 + ...d-more-logs-for-runtime-suspend-resu.patch | 68 + ...s-Resume-host-while-sending-SMP-I-Os.patch | 71 + ...scsi-libsas-Add-flag-SAS_HA_RESUMING.patch | 66 + ...sas-Refactor-sas_queue_deferred_work.patch | 95 + ...fer-works-of-new-phys-during-suspend.patch | 107 + ...ep-controller-active-between-ISR-of-.patch | 121 + ...-host-active-while-processing-events.patch | 125 + ...e-autosuspend-for-the-host-controlle.patch | 50 + ...mit-users-changing-debugfs-BIST-coun.patch | 109 + ...own-managed-interrupts-with-unsatifi.patch | 76 + ...lation-Isolate-from-handling-managed.patch | 274 ++ ...ys-limit-the-affinity-to-online-CPUs.patch | 104 + ...lways-trust-the-managed-affinity-pro.patch | 48 + ..._mq_tagset_busy_iter-for-shared-tags.patch | 57 + ...me-SAS-host-for-phy-reset-or-enable-.patch | 73 + ...event-parallel-controller-reset-and-.patch | 62 + ...i-hisi_sas-Fix-phyup-timeout-on-FPGA.patch | 114 + ...dify-v3-HW-SSP-underflow-error-proce.patch | 197 ++ ...i-libsas-Refactor-sas_ata_hard_reset.patch | 124 + ...e-sas_ata_wait_after_reset-in-IT-nex.patch | 75 + ...sas-Fix-rescan-after-deleting-a-disk.patch | 154 + ...do-RPM-resume-for-failed-notify-phy-.patch | 59 + ...e-abort-task-set-to-reset-SAS-disks-.patch | 47 + ...te-SATA-dev-FIS-in-sas_ata_task_done.patch | 49 + ...libsas-Add-sas_ata_device_link_abort.patch | 102 + ...-the-ATA-port-lock-in-sas_ata_device.patch | 54 + ...k-phy-for-severe-I_T-nexus-reset-fai.patch | 90 + ..._sas-Disable-SATA-disk-phy-for-sever.patch | 87 + ...-libsas-Add-smp_ata_check_ready_type.patch | 121 + ...x-SATA-devices-missing-issue-during-.patch | 84 + ...-not-export-sas_ata_wait_after_reset.patch | 82 + ...t-a-port-invalid-only-if-there-are-n.patch | 50 + ...it-suspending-state-when-usage-count.patch | 291 ++ ...sure-all-enabled-PHYs-up-during-cont.patch | 113 + ...ze-DIF-DIX-code-to-avoid-calling-rev.patch | 170 + ...IX-config-every-time-sd_revalidate_d.patch | 116 + ...crease-debugfs_dump_index-after-dump.patch | 55 + ...nfigure-the-initialization-registers.patch | 103 + ...dd-slave_destroy-interface-for-v3-hw.patch | 87 + ...ock-requests-before-take-debugfs-sna.patch | 68 + ...rk-around-build-failure-in-suspend-f.patch | 81 + ...eck-usage-count-only-when-the-runtim.patch | 62 + ...-retries-of-START_STOP-when-resuming.patch | 87 + ...v3_hw-Don-t-use-PCI-helper-functions.patch | 91 + ..._hw-Remove-extra-function-calls-for-.patch | 89 + ...si-block-pm-Simplify-resume-handling.patch | 131 + ...ways-set-request-queue-runtime-activ.patch | 134 + ...n-t-lose-track-of-REQ_INTEGRITY-flag.patch | 53 + ...k_mq_-_map_queues-kernel-doc-headers.patch | 81 + ...nr_hw_queues-and-set-map-.nr_queues-.patch | 67 + ...kernel-doc-description-for-a-new-str.patch | 52 + ...dd-decode-for-BLK_MQ_F_TAG_HCTX_SHAR.patch | 50 + ...k-mq-plug-request-for-shared-sbitmap.patch | 60 + ...how-active-requests-per-queue-for-sh.patch | 50 + ...-race-in-the-runtime-power-managemen.patch | 94 + ...s-Enable-msix_load_balance-for-Invad.patch | 46 + ...ace-open-coded-check-with-dev_is_exp.patch | 61 + ...e-warning-on-managed-interrupt-migra.patch | 102 + ...erneldoc-comment-for-struct-irq_affi.patch | 48 + ...-Fix-double-increment-in-alloc_descs.patch | 53 + ...proposed-affinity-at-face-value-if-f.patch | 67 + ...te-device-link-status-correctly-for-.patch | 126 + ...device_pm_lock-locking-for-device-li.patch | 86 + ...form-Add-extra-error-check-in-devm_p.patch | 52 + ...ix-device-link-device-name-collision.patch | 185 ++ ...ent-warning-when-removing-a-device-l.patch | 51 + ...ct-pointless-SYNC_STATE_ONLY-device-.patch | 56 + ...possible-memory-leak-in-device_link_.patch | 76 + series.conf | 256 ++ 258 files changed, 36742 insertions(+), 1 deletion(-) create mode 100644 patches/0319-block-Move-power-management-code-into-a-new-source-f.patch create mode 100644 patches/0320-block-Split-blk_pm_add_request-and-blk_pm_put_reques.patch create mode 100644 patches/0321-block-Schedule-runtime-resume-earlier.patch create mode 100644 patches/0322-block-Allow-unfreezing-of-a-queue-while-requests-are.patch create mode 100644 patches/0323-block-Make-blk_get_request-block-for-non-PM-requests.patch create mode 100644 patches/0324-blk-mq-Enable-support-for-runtime-power-management.patch create mode 100644 patches/0325-scsi-hisi_sas-No-need-to-check-return-value-of-debug.patch create mode 100644 patches/0326-scsi-hisi_sas-Fix-type-casting-and-missing-static-qu.patch create mode 100644 patches/0327-scsi-hisi_sas-Fix-losing-directly-attached-disk-when.patch create mode 100644 patches/0328-scsi-hisi_sas-Use-pci_irq_get_affinity-for-v3-hw-as-.patch create mode 100644 patches/0329-scsi-hisi_sas-Some-misc-tidy-up.patch create mode 100644 patches/0330-scsi-hisi_sas-Make-max-IPTT-count-equal-for-all-hw-r.patch create mode 100644 patches/0331-scsi-hisi_sas-Fix-pointer-usage-error-in-show-debugf.patch create mode 100644 patches/0332-scsi-hisi_sas-Snapshot-HW-cache-of-IOST-and-ITCT-at-.patch create mode 100644 patches/0333-scsi-hisi_sas-Snapshot-AXI-and-RAS-register-at-debug.patch create mode 100644 patches/0334-scsi-hisi_sas-Drop-kmap_atomic-in-SMP-command-comple.patch create mode 100644 patches/0335-scsi-hisi_sas-Drop-SMP-resp-frame-DMA-mapping.patch create mode 100644 patches/0336-scsi-hisi_sas-Drop-free_irq-when-devm_request_irq-fa.patch create mode 100644 patches/0337-scsi-hisi_sas-Modify-return-type-of-debugfs-function.patch create mode 100644 patches/0338-scsi-hisi_sas-Remove-some-unnecessary-code.patch create mode 100644 patches/0339-scsi-hisi_sas-remove-set-but-not-used-variable-irq_v.patch create mode 100644 patches/0340-scsi-hisi_sas-use-devm_platform_ioremap_resource-to-.patch create mode 100644 patches/0341-scsi-hisi_sas-add-debugfs-auto-trigger-for-internal-.patch create mode 100644 patches/0342-scsi-hisi_sas-Remove-hisi_sas_hw.slot_complete.patch create mode 100644 patches/0343-scsi-hisi_sas-Remove-redundant-work-declaration.patch create mode 100644 patches/0344-scsi-hisi_sas-Remove-some-unused-function-arguments.patch create mode 100644 patches/0345-scsi-hisi_sas-Add-hisi_sas_debugfs_alloc-to-centrali.patch create mode 100644 patches/0346-scsi-hisi_sas-fix-spelling-mistake-digial-digital.patch create mode 100644 patches/0347-scsi-hisi_sas-Make-three-functions-static.patch create mode 100644 patches/0348-scsi-hisi_sas-Don-t-create-debugfs-dump-folder-twice.patch create mode 100644 patches/0349-scsi-hisi_sas-Add-timestamp-for-a-debugfs-dump.patch create mode 100644 patches/0350-scsi-hisi_sas-Add-debugfs-file-structure-for-CQ.patch create mode 100644 patches/0351-scsi-hisi_sas-Add-debugfs-file-structure-for-DQ.patch create mode 100644 patches/0352-scsi-hisi_sas-Add-debugfs-file-structure-for-registe.patch create mode 100644 patches/0353-scsi-hisi_sas-Add-debugfs-file-structure-for-port.patch create mode 100644 patches/0354-scsi-hisi_sas-Add-debugfs-file-structure-for-IOST.patch create mode 100644 patches/0355-scsi-hisi_sas-Add-debugfs-file-structure-for-ITCT.patch create mode 100644 patches/0356-scsi-hisi_sas-Add-debugfs-file-structure-for-IOST-ca.patch create mode 100644 patches/0357-scsi-hisi_sas-Add-debugfs-file-structure-for-ITCT-ca.patch create mode 100644 patches/0358-scsi-hisi_sas-Allocate-memory-for-multiple-dumps-of-.patch create mode 100644 patches/0359-scsi-hisi_sas-Add-module-parameter-for-debugfs-dump-.patch create mode 100644 patches/0360-scsi-hisi_sas-Add-ability-to-have-multiple-debugfs-d.patch create mode 100644 patches/0361-scsi-hisi_sas-Delete-the-debugfs-folder-of-hisi_sas-.patch create mode 100644 patches/0362-scsi-hisi_sas-Record-the-phy-down-event-in-debugfs.patch create mode 100644 patches/0363-scsi-hisi_sas-Return-directly-if-init-hardware-faile.patch create mode 100644 patches/0364-scsi-hisi_sas-Stop-converting-a-bool-into-a-bool.patch create mode 100644 patches/0365-scsi-hisi_sas-Replace-magic-number-when-handle-chann.patch create mode 100644 patches/0366-scsi-hisi_sas-Modify-the-file-permissions-of-trigger.patch create mode 100644 patches/0367-scsi-hisi_sas-Add-prints-for-v3-hw-interrupt-converg.patch create mode 100644 patches/0368-scsi-hisi_sas-Rename-hisi_sas_cq.pci_irq_mask.patch create mode 100644 patches/0369-scsi-hisi_sas-Use-dev_err-in-read_iost_itct_cache_v3.patch create mode 100644 patches/0370-scsi-hisi_sas-Fix-build-error-without-SATA_HOST.patch create mode 100644 patches/0371-scsi-hisi_sas-Display-proc_name-in-sysfs.patch create mode 100644 patches/0372-scsi-hisi_sas-Modify-the-commit-information-for-DSM-.patch create mode 100644 patches/0373-scsi-hisi_sas-Add-SAS_RAS_INTR0-to-debugfs-register-.patch create mode 100644 patches/0374-scsi-hisi_sas-Stop-returning-error-code-from-slot_co.patch create mode 100644 patches/0375-scsi-hisi_sas-Do-not-reset-phy-timer-to-wait-for-str.patch create mode 100644 patches/0376-scsi-hisi_sas-Remove-one-kerneldoc-comment.patch create mode 100644 patches/0377-block-add-REQ_HIPRI-and-inherit-it-from-IOCB_HIPRI.patch create mode 100644 patches/0378-blk-mq-kill-q-mq_map.patch create mode 100644 patches/0379-fix-kabi-broken-due-to-change-of-struct-struct-reque.patch create mode 100644 patches/0380-blk-mq-abstract-out-queue-map.patch create mode 100644 patches/0381-fix-kabi-broken-due-to-change-of-function-blk_mq_map.patch create mode 100644 patches/0382-blk-mq-provide-dummy-blk_mq_map_queue_type-helper.patch create mode 100644 patches/0383-blk-mq-pass-in-request-bio-flags-to-queue-mapping.patch create mode 100644 patches/0384-fix-kabi-broken-due-to-change-of-struct-blk_mq_alloc.patch create mode 100644 patches/0385-blk-mq-allow-software-queue-to-map-to-multiple-hardw.patch create mode 100644 patches/0386-fix-kabi-broken-due-to-change-of-struct-blk_mq_hw_ct.patch create mode 100644 patches/0387-blk-mq-add-type-attribute-to-the-sysfs-hctx-director.patch create mode 100644 patches/0388-blk-mq-support-multiple-hctx-maps.patch create mode 100644 patches/0389-fix-kabi-broken-due-to-change-of-struct-blk_mq_tag_s.patch create mode 100644 patches/0390-blk-mq-separate-number-of-hardware-queues-from-nr_cp.patch create mode 100644 patches/0391-blk-mq-cache-request-hardware-queue-mapping.patch create mode 100644 patches/0392-fix-kabi-broken-due-to-change-of-struct-request.patch create mode 100644 patches/0393-blk-mq-cleanup-and-improve-list-insertion.patch create mode 100644 patches/0394-blk-mq-improve-plug-list-sorting.patch create mode 100644 patches/0395-blk-mq-initial-support-for-multiple-queue-maps.patch create mode 100644 patches/0396-block-move-queues-types-to-the-block-layer.patch create mode 100644 patches/0397-blk-mq-Rename-BLK_MQ_F_TAG_SHARED-as-BLK_MQ_F_TAG_QU.patch create mode 100644 patches/0398-blk-mq-Rename-blk_mq_update_tag_set_depth.patch create mode 100644 patches/0399-blk-mq-Free-tags-in-blk_mq_init_tags-upon-error.patch create mode 100644 patches/0400-blk-mq-Pass-flags-for-tag-init-free.patch create mode 100644 patches/0401-blk-mq-Use-pointers-for-blk_mq_tags-bitmap-tags.patch create mode 100644 patches/0402-fix-kabi-broken-due-to-change-of-struct-blk_mq_tags.patch create mode 100644 patches/0403-blk-mq-Facilitate-a-shared-sbitmap-per-tagset.patch create mode 100644 patches/0404-fix-kabi-broken-due-to-change-of-struct-blk_mq_tag_s.patch create mode 100644 patches/0405-blk-mq-Relocate-hctx_may_queue.patch create mode 100644 patches/0406-blk-mq-Record-nr_active_requests-per-queue-for-when-.patch create mode 100644 patches/0407-fix-kabi-broken-due-to-change-of-struct-request_queu.patch create mode 100644 patches/0408-blk-mq-Record-active_queues_shared_sbitmap-per-tag_s.patch create mode 100644 patches/0409-fix-kabi-broken-due-to-change-of-struct-blk_mq_tag_s.patch create mode 100644 patches/0410-scsi-Add-host-and-host-template-flag-host_tagset.patch create mode 100644 patches/0411-fix-kabi-broken-due-to-change-of-struct-scsi_host_te.patch create mode 100644 patches/0412-scsi-core-Show-nr_hw_queues-in-sysfs.patch create mode 100644 patches/0413-scsi-hisi_sas-Switch-v3-hw-to-MQ.patch create mode 100644 patches/0414-scsi-scsi_debug-Support-hostwide-tags.patch create mode 100644 patches/0415-scsi-scsi_debug-Support-host-tagset.patch create mode 100644 patches/0416-scsi-hisi_sas-Modify-macro-name-for-OOB-phy-linkrate.patch create mode 100644 patches/0417-scsi-hisi_sas-Do-not-modify-upper-fields-of-PROG_PHY.patch create mode 100644 patches/0418-scsi-hisi_sas-Make-phy-index-variable-name-consisten.patch create mode 100644 patches/0419-scsi-hisi_sas-Add-BIST-support-for-phy-FFE.patch create mode 100644 patches/0420-scsi-hisi_sas-Add-BIST-support-for-fixed-code-patter.patch create mode 100644 patches/0421-scsi-hisi_sas-Add-missing-newlines.patch create mode 100644 patches/0422-scsi-hisi_sas-Code-style-cleanup.patch create mode 100644 patches/0423-PM-runtime-Remove-link-state-checks-in-rpm_get-put_s.patch create mode 100644 patches/0424-scsi-hisi_sas-Use-hisi_hba-cq_nvecs-for-calling-call.patch create mode 100644 patches/0425-scsi-hisi_sas-Switch-to-new-framework-to-support-sus.patch create mode 100644 patches/0426-scsi-hisi_sas-Add-controller-runtime-PM-support-for-.patch create mode 100644 patches/0427-scsi-hisi_sas-Add-check-for-methods-_PS0-and-_PR0.patch create mode 100644 patches/0428-scsi-hisi_sas-Add-device-link-between-SCSI-devices-a.patch create mode 100644 patches/0429-scsi-hisi_sas-Recover-PHY-state-according-to-the-sta.patch create mode 100644 patches/0430-scsi-hisi_sas-Stop-using-queue-0-always-for-v2-hw.patch create mode 100644 patches/0431-PM-runtime-Drop-runtime-PM-references-to-supplier-on.patch create mode 100644 patches/0432-PM-runtime-Drop-pm_runtime_clean_up_links.patch create mode 100644 patches/0433-PM-runtime-Resume-the-device-earlier-in-__device_rel.patch create mode 100644 patches/0434-scsi-hisi_sas-Select-a-suitable-queue-for-internal-I.patch create mode 100644 patches/0435-scsi-hisi_sas-Fix-up-probe-error-handling-for-v3-hw.patch create mode 100644 patches/0436-PM-core-Add-support-to-skip-power-management-in-devi.patch create mode 100644 patches/0437-fix-kabi-broken-due-to-change-of-struct-dev_pm_info.patch create mode 100644 patches/0438-driver-core-Add-device-link-support-for-SYNC_STATE_O.patch create mode 100644 patches/0439-driver-core-Expose-device-link-details-in-sysfs.patch create mode 100644 patches/0440-fix-kabi-broken-due-to-change-of-struct-device_link.patch create mode 100644 patches/0441-driver-core-Fix-sleeping-in-invalid-context-during-d.patch create mode 100644 patches/0442-drivers-base-Fix-device-link-removal.patch create mode 100644 patches/0443-fix-kabi-broken-due-to-change-of-struct-dev_link.patch create mode 100644 patches/0444-scsi-megaraid_sas-Rename-scratch_pad-registers.patch create mode 100644 patches/0445-scsi-megaraid_sas-Introduce-new-Aero-adapter-type.patch create mode 100644 patches/0446-scsi-megaraid_sas-Load-balance-completions-across-al.patch create mode 100644 patches/0447-scsi-megaraid_sas-RAID1-PCI-bandwidth-limit-algorith.patch create mode 100644 patches/0448-scsi-megaraid_sas-Add-support-for-High-IOPS-queues.patch create mode 100644 patches/0449-scsi-megaraid_sas-Enable-coalescing-for-high-IOPS-qu.patch create mode 100644 patches/0450-scsi-megaraid_sas-Use-high-IOPS-queues-based-on-IO-w.patch create mode 100644 patches/0451-scsi-megaraid_sas-Introduce-various-Aero-performance.patch create mode 100644 patches/0452-scsi-megaraid_sas-Use-Block-layer-API-to-check-SCSI-.patch create mode 100644 patches/0453-scsi-megaraid_sas-Added-support-for-shared-host-tags.patch create mode 100644 patches/0454-scsi-hisi_sas-Reduce-some-indirection-in-v3-hw-drive.patch create mode 100644 patches/0455-scsi-hisi_sas-Move-debugfs-code-to-v3-hw-driver.patch create mode 100644 patches/0456-scsi-hisi_sas-Remove-preemptible.patch create mode 100644 patches/0457-scsi-hisi_sas-use-threaded-irq-to-process-CQ-interru.patch create mode 100644 patches/0458-genirq-core-Introduce-struct-irq_affinity_desc.patch create mode 100644 patches/0459-fix-kabi-broken-due-to-change-of-struct-msi_desc.patch create mode 100644 patches/0460-resource-Add-irqresource_disabled.patch create mode 100644 patches/0461-genirq-affinity-Add-is_managed-to-struct-irq_affinit.patch create mode 100644 patches/0462-genirq-affinity-Add-irq_update_affinity_desc.patch create mode 100644 patches/0463-driver-core-platform-Add-devm_platform_get_irqs_affi.patch create mode 100644 patches/0464-scsi-hisi_sas-Expose-HW-queues-for-v2-hw.patch create mode 100644 patches/0465-scsi-hisi_sas-Remove-auto_affine_msi_experimental-mo.patch create mode 100644 patches/0466-scsi-libsas-Introduce-a-_gfp-variant-of-event-notifi.patch create mode 100644 patches/0467-scsi-mvsas-Pass-gfp_t-flags-to-libsas-event-notifier.patch create mode 100644 patches/0468-scsi-isci-Pass-gfp_t-flags-in-isci_port_link_down.patch create mode 100644 patches/0469-scsi-isci-Pass-gfp_t-flags-in-isci_port_link_up.patch create mode 100644 patches/0470-scsi-isci-Pass-gfp_t-flags-in-isci_port_bc_change_re.patch create mode 100644 patches/0471-scsi-libsas-Pass-gfp_t-flags-to-event-notifiers.patch create mode 100644 patches/0472-scsi-pm80xx-Pass-gfp_t-flags-to-libsas-event-notifie.patch create mode 100644 patches/0473-scsi-aic94xx-Pass-gfp_t-flags-to-libsas-event-notifi.patch create mode 100644 patches/0474-scsi-hisi_sas-Pass-gfp_t-flags-to-libsas-event-notif.patch create mode 100644 patches/0475-scsi-libsas-Add-gfp_t-flags-parameter-to-event-notif.patch create mode 100644 patches/0476-fix-kabi-broken-due-to-change-of-struct-sas_ha_struc.patch create mode 100644 patches/0477-scsi-hisi_sas-Switch-back-to-original-libsas-event-n.patch create mode 100644 patches/0478-scsi-aic94xx-Switch-back-to-original-libsas-event-no.patch create mode 100644 patches/0479-scsi-pm80xx-Switch-back-to-original-libsas-event-not.patch create mode 100644 patches/0480-scsi-libsas-Switch-back-to-original-event-notifiers-.patch create mode 100644 patches/0481-scsi-isci-Switch-back-to-original-libsas-event-notif.patch create mode 100644 patches/0482-scsi-mvsas-Switch-back-to-original-libsas-event-noti.patch create mode 100644 patches/0483-scsi-libsas-Remove-temporarily-added-_gfp-API-varian.patch create mode 100644 patches/0484-scsi-hisi_sas-Remove-deferred-probe-check-in-hisi_sa.patch create mode 100644 patches/0485-scsi-hisi_sas-Don-t-check-.nr_hw_queues-in-hisi_sas_.patch create mode 100644 patches/0486-scsi-hisi_sas-Enable-debugfs-support-by-default.patch create mode 100644 patches/0487-scsi-hisi_sas-Add-trace-FIFO-debugfs-support.patch create mode 100644 patches/0488-scsi-hisi_sas-Print-SAS-address-for-v3-hw-erroneous-.patch create mode 100644 patches/0489-scsi-hisi_sas-Call-sas_unregister_ha-to-roll-back-if.patch create mode 100644 patches/0490-scsi-hisi_sas-Directly-snapshot-registers-when-execu.patch create mode 100644 patches/0491-scsi-hisi_sas-Warn-in-v3-hw-channel-interrupt-handle.patch create mode 100644 patches/0492-scsi-hisi_sas-Print-SATA-device-SAS-address-for-soft.patch create mode 100644 patches/0493-scsi-hisi_sas-Put-a-limit-of-link-reset-retries.patch create mode 100644 patches/0494-scsi-hisi_sas-Run-I_T-nexus-resets-in-parallel-for-c.patch create mode 100644 patches/0495-scsi-hisi_sas-Include-HZ-in-timer-macros.patch create mode 100644 patches/0496-scsi-hisi_sas-Reset-controller-for-internal-abort-ti.patch create mode 100644 patches/0497-scsi-hisi_sas-Speed-up-error-handling-when-internal-.patch create mode 100644 patches/0498-scsi-libsas-Export-sas_phy_enable.patch create mode 100644 patches/0499-scsi-hisi_sas-Initialise-devices-in-.slave_alloc-cal.patch create mode 100644 patches/0500-scsi-hisi_sas-Wait-for-phyup-in-hisi_sas_control_phy.patch create mode 100644 patches/0501-scsi-libsas-Don-t-always-drain-event-workqueue-for-H.patch create mode 100644 patches/0502-scsi-libsas-Add-spin_lock-unlock-to-protect-asd_sas_.patch create mode 100644 patches/0503-scsi-hisi_sas-Fix-some-issues-related-to-asd_sas_por.patch create mode 100644 patches/0504-scsi-mvsas-Add-spin_lock-unlock-to-protect-asd_sas_p.patch create mode 100644 patches/0505-scsi-libsas-aic94xx-hisi_sas-mvsas-pm8001-Use-dev_is.patch create mode 100644 patches/0506-scsi-libsas-Insert-PORTE_BROADCAST_RCVD-event-for-re.patch create mode 100644 patches/0507-scsi-hisi_sas-Add-more-logs-for-runtime-suspend-resu.patch create mode 100644 patches/0508-scsi-libsas-Resume-host-while-sending-SMP-I-Os.patch create mode 100644 patches/0509-scsi-libsas-Add-flag-SAS_HA_RESUMING.patch create mode 100644 patches/0510-scsi-libsas-Refactor-sas_queue_deferred_work.patch create mode 100644 patches/0511-scsi-libsas-Defer-works-of-new-phys-during-suspend.patch create mode 100644 patches/0512-scsi-hisi_sas-Keep-controller-active-between-ISR-of-.patch create mode 100644 patches/0513-scsi-libsas-Keep-host-active-while-processing-events.patch create mode 100644 patches/0514-scsi-hisi_sas-Use-autosuspend-for-the-host-controlle.patch create mode 100644 patches/0515-scsi-hisi_sas-Limit-users-changing-debugfs-BIST-coun.patch create mode 100644 patches/0516-genirq-msi-Shutdown-managed-interrupts-with-unsatifi.patch create mode 100644 patches/0517-genirq-sched-isolation-Isolate-from-handling-managed.patch create mode 100644 patches/0518-genirq-Always-limit-the-affinity-to-online-CPUs.patch create mode 100644 patches/0519-irqchip-gic-v3-Always-trust-the-managed-affinity-pro.patch create mode 100644 patches/0520-blk-mq-Fix-blk_mq_tagset_busy_iter-for-shared-tags.patch create mode 100644 patches/0521-scsi-libsas-Resume-SAS-host-for-phy-reset-or-enable-.patch create mode 100644 patches/0522-scsi-hisi_sas-Prevent-parallel-controller-reset-and-.patch create mode 100644 patches/0523-scsi-hisi_sas-Fix-phyup-timeout-on-FPGA.patch create mode 100644 patches/0524-scsi-hisi_sas-Modify-v3-HW-SSP-underflow-error-proce.patch create mode 100644 patches/0525-scsi-libsas-Refactor-sas_ata_hard_reset.patch create mode 100644 patches/0526-scsi-hisi_sas-Use-sas_ata_wait_after_reset-in-IT-nex.patch create mode 100644 patches/0527-scsi-hisi_sas-Fix-rescan-after-deleting-a-disk.patch create mode 100644 patches/0528-scsi-hisi_sas-Undo-RPM-resume-for-failed-notify-phy-.patch create mode 100644 patches/0529-scsi-hisi_sas-Use-abort-task-set-to-reset-SAS-disks-.patch create mode 100644 patches/0530-scsi-libsas-Update-SATA-dev-FIS-in-sas_ata_task_done.patch create mode 100644 patches/0531-scsi-libsas-Add-sas_ata_device_link_abort.patch create mode 100644 patches/0532-scsi-libsas-Grab-the-ATA-port-lock-in-sas_ata_device.patch create mode 100644 patches/0533-Disable-SATA-disk-phy-for-severe-I_T-nexus-reset-fai.patch create mode 100644 patches/0534-Revert-scsi-hisi_sas-Disable-SATA-disk-phy-for-sever.patch create mode 100644 patches/0535-scsi-libsas-Add-smp_ata_check_ready_type.patch create mode 100644 patches/0536-scsi-hisi_sas-Fix-SATA-devices-missing-issue-during-.patch create mode 100644 patches/0537-scsi-libsas-Do-not-export-sas_ata_wait_after_reset.patch create mode 100644 patches/0538-scsi-hisi_sas-Set-a-port-invalid-only-if-there-are-n.patch create mode 100644 patches/0539-scsi-hisi_sas-Exit-suspending-state-when-usage-count.patch create mode 100644 patches/0540-scsi-hisi_sas-Ensure-all-enabled-PHYs-up-during-cont.patch create mode 100644 patches/0541-scsi-sd-Reorganize-DIF-DIX-code-to-avoid-calling-rev.patch create mode 100644 patches/0542-scsi-sd-Update-DIX-config-every-time-sd_revalidate_d.patch create mode 100644 patches/0543-scsi-hisi_sas-Increase-debugfs_dump_index-after-dump.patch create mode 100644 patches/0544-scsi-hisi_sas-Configure-the-initialization-registers.patch create mode 100644 patches/0545-scsi-hisi_sas-Add-slave_destroy-interface-for-v3-hw.patch create mode 100644 patches/0546-scsi-hisi_sas-Block-requests-before-take-debugfs-sna.patch create mode 100644 patches/0547-scsi-hisi_sas-Work-around-build-failure-in-suspend-f.patch create mode 100644 patches/0548-scsi-hisi_sas-Check-usage-count-only-when-the-runtim.patch create mode 100644 patches/0549-scsi-sd-try-more-retries-of-START_STOP-when-resuming.patch create mode 100644 patches/0550-scsi-hisi_sas_v3_hw-Don-t-use-PCI-helper-functions.patch create mode 100644 patches/0551-scsi-hisi_sas_v3_hw-Remove-extra-function-calls-for-.patch create mode 100644 patches/0552-scsi-block-pm-Simplify-resume-handling.patch create mode 100644 patches/0553-scsi-block-pm-Always-set-request-queue-runtime-activ.patch create mode 100644 patches/0554-block-don-t-lose-track-of-REQ_INTEGRITY-flag.patch create mode 100644 patches/0555-block-Fix-blk_mq_-_map_queues-kernel-doc-headers.patch create mode 100644 patches/0556-blk-mq-Keep-set-nr_hw_queues-and-set-map-.nr_queues-.patch create mode 100644 patches/0557-blk-mq-docs-add-kernel-doc-description-for-a-new-str.patch create mode 100644 patches/0558-blk-mq-debugfs-Add-decode-for-BLK_MQ_F_TAG_HCTX_SHAR.patch create mode 100644 patches/0559-blk-mq-plug-request-for-shared-sbitmap.patch create mode 100644 patches/0560-blk-mq-debugfs-Show-active-requests-per-queue-for-sh.patch create mode 100644 patches/0561-scsi-block-Fix-a-race-in-the-runtime-power-managemen.patch create mode 100644 patches/0562-scsi-megaraid_sas-Enable-msix_load_balance-for-Invad.patch create mode 100644 patches/0563-scsi-pm80xx-Replace-open-coded-check-with-dev_is_exp.patch create mode 100644 patches/0564-x86-vector-Remove-warning-on-managed-interrupt-migra.patch create mode 100644 patches/0565-genirq-Fix-the-kerneldoc-comment-for-struct-irq_affi.patch create mode 100644 patches/0566-genirq-irqdesc-Fix-double-increment-in-alloc_descs.patch create mode 100644 patches/0567-genirq-Take-the-proposed-affinity-at-face-value-if-f.patch create mode 100644 patches/0568-driver-core-Update-device-link-status-correctly-for-.patch create mode 100644 patches/0569-driver-core-Fix-device_pm_lock-locking-for-device-li.patch create mode 100644 patches/0570-driver-core-platform-Add-extra-error-check-in-devm_p.patch create mode 100644 patches/0571-driver-core-Fix-device-link-device-name-collision.patch create mode 100644 patches/0572-driver-core-Prevent-warning-when-removing-a-device-l.patch create mode 100644 patches/0573-driver-core-Reject-pointless-SYNC_STATE_ONLY-device-.patch create mode 100644 patches/0574-driver-core-Fix-possible-memory-leak-in-device_link_.patch diff --git a/kernel.spec b/kernel.spec index 36dd3b72..6dc25b95 100644 --- a/kernel.spec +++ b/kernel.spec @@ -32,7 +32,7 @@ Name: kernel Version: 4.19.90 -Release: %{hulkrelease}.0239 +Release: %{hulkrelease}.0240 Summary: Linux Kernel License: GPLv2 URL: http://www.kernel.org/ @@ -836,6 +836,263 @@ fi %endif %changelog +* Fri Nov 10 2023 YunYi Yang - 4.19.90-2311.1.0.0240 +- driver core: Fix possible memory leak in device_link_add() +- driver core: Reject pointless SYNC_STATE_ONLY device links +- driver core: Prevent warning when removing a device link from unregistered consumer +- driver core: Fix device link device name collision +- driver core: platform: Add extra error check in devm_platform_get_irqs_affinity() +- driver core: Fix device_pm_lock() locking for device links +- driver core: Update device link status correctly for SYNC_STATE_ONLY links +- genirq: Take the proposed affinity at face value if force==true +- genirq/irqdesc: Fix double increment in alloc_descs() +- genirq: Fix the kerneldoc comment for struct irq_affinity_desc +- x86/vector: Remove warning on managed interrupt migration +- scsi: pm80xx: Replace open coded check with dev_is_expander() +- scsi: megaraid_sas: Enable msix_load_balance for Invader and later controllers +- scsi: block: Fix a race in the runtime power management code +- blk-mq-debugfs: Show active requests per queue for shared tags +- blk-mq: plug request for shared sbitmap +- blk-mq-debugfs: Add decode for BLK_MQ_F_TAG_HCTX_SHARED +- blk-mq: docs: add kernel-doc description for a new struct member +- blk-mq: Keep set->nr_hw_queues and set->map[].nr_queues in sync +- block: Fix blk_mq_*_map_queues() kernel-doc headers +- block: don't lose track of REQ_INTEGRITY flag +- scsi: block: pm: Always set request queue runtime active in blk_post_runtime_resume() +- scsi: block: pm: Simplify resume handling +- scsi: hisi_sas_v3_hw: Remove extra function calls for runtime pm +- scsi: hisi_sas_v3_hw: Don't use PCI helper functions +- scsi: sd: try more retries of START_STOP when resuming scsi device +- scsi: hisi_sas: Check usage count only when the runtime PM status is RPM_SUSPENDING +- scsi: hisi_sas: Work around build failure in suspend function +- scsi: hisi_sas: Block requests before take debugfs snapshot +- scsi: hisi_sas: Add slave_destroy interface for v3 hw +- scsi: hisi_sas: Configure the initialization registers according to HBA model +- scsi: hisi_sas: Increase debugfs_dump_index after dump is completed +- scsi: sd: Update DIX config every time sd_revalidate_disk() is called +- scsi: sd: Reorganize DIF/DIX code to avoid calling revalidate twice +- scsi: hisi_sas: Ensure all enabled PHYs up during controller reset +- scsi: hisi_sas: Exit suspending state when usage count is greater than 0 +- scsi: hisi_sas: Set a port invalid only if there are no devices attached when refreshing port id +- scsi: libsas: Do not export sas_ata_wait_after_reset() +- scsi: hisi_sas: Fix SATA devices missing issue during I_T nexus reset +- scsi: libsas: Add smp_ata_check_ready_type() +- Revert "scsi: hisi_sas: Disable SATA disk phy for severe I_T nexus reset failure" +- Disable-SATA-disk-phy-for-severe-I_T-nexus reset failure +- scsi: libsas: Grab the ATA port lock in sas_ata_device_link_abort() +- scsi: libsas: Add sas_ata_device_link_abort() +- scsi: libsas: Update SATA dev FIS in sas_ata_task_done() +- scsi: hisi_sas: Use abort task set to reset SAS disks when discovered +- scsi: hisi_sas: Undo RPM resume for failed notify phy event for v3 HW +- scsi: hisi_sas: Fix rescan after deleting a disk +- scsi: hisi_sas: Use sas_ata_wait_after_reset() in IT nexus reset +- scsi: libsas: Refactor sas_ata_hard_reset() +- scsi: hisi_sas: Modify v3 HW SSP underflow error processing +- scsi: hisi_sas: Fix phyup timeout on FPGA +- scsi: hisi_sas: Prevent parallel controller reset and control phy command +- scsi: libsas: Resume SAS host for phy reset or enable via sysfs +- blk-mq: Fix blk_mq_tagset_busy_iter() for shared tags +- irqchip/gic-v3: Always trust the managed affinity provided by the core code +- genirq: Always limit the affinity to online CPUs +- genirq, sched/isolation: Isolate from handling managed interrupts +- genirq/msi: Shutdown managed interrupts with unsatifiable affinities +- scsi: hisi_sas: Limit users changing debugfs BIST count value +- scsi: hisi_sas: Use autosuspend for the host controller +- scsi: libsas: Keep host active while processing events +- scsi: hisi_sas: Keep controller active between ISR of phyup and the event being processed +- scsi: libsas: Defer works of new phys during suspend +- scsi: libsas: Refactor sas_queue_deferred_work() +- scsi: libsas: Add flag SAS_HA_RESUMING +- scsi: libsas: Resume host while sending SMP I/Os +- scsi: hisi_sas: Add more logs for runtime suspend/resume +- scsi: libsas: Insert PORTE_BROADCAST_RCVD event for resuming host +- scsi: libsas: aic94xx: hisi_sas: mvsas: pm8001: Use dev_is_expander() +- scsi: mvsas: Add spin_lock/unlock() to protect asd_sas_port->phy_list +- scsi: hisi_sas: Fix some issues related to asd_sas_port->phy_list +- scsi: libsas: Add spin_lock/unlock() to protect asd_sas_port->phy_list +- scsi: libsas: Don't always drain event workqueue for HA resume +- scsi: hisi_sas: Wait for phyup in hisi_sas_control_phy() +- scsi: hisi_sas: Initialise devices in .slave_alloc callback +- scsi: libsas: Export sas_phy_enable() +- scsi: hisi_sas: Speed up error handling when internal abort timeout occurs +- scsi: hisi_sas: Reset controller for internal abort timeout +- scsi: hisi_sas: Include HZ in timer macros +- scsi: hisi_sas: Run I_T nexus resets in parallel for clear nexus reset +- scsi: hisi_sas: Put a limit of link reset retries +- scsi: hisi_sas: Print SATA device SAS address for soft reset failure +- scsi: hisi_sas: Warn in v3 hw channel interrupt handler when status reg cleared +- scsi: hisi_sas: Directly snapshot registers when executing a reset +- scsi: hisi_sas: Call sas_unregister_ha() to roll back if .hw_init() fails +- scsi: hisi_sas: Print SAS address for v3 hw erroneous completion print +- scsi: hisi_sas: Add trace FIFO debugfs support +- scsi: hisi_sas: Enable debugfs support by default +- scsi: hisi_sas: Don't check .nr_hw_queues in hisi_sas_task_prep() +- scsi: hisi_sas: Remove deferred probe check in hisi_sas_v2_probe() +- scsi: libsas: Remove temporarily-added _gfp() API variants +- scsi: mvsas: Switch back to original libsas event notifiers +- scsi: isci: Switch back to original libsas event notifiers +- scsi: libsas: Switch back to original event notifiers API +- scsi: pm80xx: Switch back to original libsas event notifiers +- scsi: aic94xx: Switch back to original libsas event notifiers +- scsi: hisi_sas: Switch back to original libsas event notifiers +- fix kabi broken due to change of struct sas_ha_struct +- scsi: libsas: Add gfp_t flags parameter to event notifications +- scsi: hisi_sas: Pass gfp_t flags to libsas event notifiers +- scsi: aic94xx: Pass gfp_t flags to libsas event notifiers +- scsi: pm80xx: Pass gfp_t flags to libsas event notifiers +- scsi: libsas: Pass gfp_t flags to event notifiers +- scsi: isci: Pass gfp_t flags in isci_port_bc_change_received() +- scsi: isci: Pass gfp_t flags in isci_port_link_up() +- scsi: isci: Pass gfp_t flags in isci_port_link_down() +- scsi: mvsas: Pass gfp_t flags to libsas event notifiers +- scsi: libsas: Introduce a _gfp() variant of event notifiers +- scsi: hisi_sas: Remove auto_affine_msi_experimental module_param +- scsi: hisi_sas: Expose HW queues for v2 hw +- driver core: platform: Add devm_platform_get_irqs_affinity() +- genirq/affinity: Add irq_update_affinity_desc() +- genirq/affinity: Add is_managed to struct irq_affinity_desc +- resource: Add irqresource_disabled() +- fix kabi broken due to change of struct msi_desc +- genirq/core: Introduce struct irq_affinity_desc +- scsi: hisi_sas: use threaded irq to process CQ interrupts +- scsi: hisi_sas: Remove preemptible() +- scsi: hisi_sas: Move debugfs code to v3 hw driver +- scsi: hisi_sas: Reduce some indirection in v3 hw driver +- scsi: megaraid_sas: Added support for shared host tagset for cpuhotplug +- scsi: megaraid_sas: Use Block layer API to check SCSI device in-flight IO requests +- scsi: megaraid_sas: Introduce various Aero performance modes +- scsi: megaraid_sas: Use high IOPS queues based on IO workload +- scsi: megaraid_sas: Enable coalescing for high IOPS queues +- scsi: megaraid_sas: Add support for High IOPS queues +- scsi: megaraid_sas: RAID1 PCI bandwidth limit algorithm is applicable for only Ventura +- scsi: megaraid_sas: Load balance completions across all MSI-X +- scsi: megaraid_sas: Introduce new Aero adapter type +- scsi: megaraid_sas: Rename scratch_pad registers +- fix kabi broken due to change of struct dev_link +- drivers: base: Fix device link removal +- driver core: Fix sleeping in invalid context during device link deletion +- fix kabi broken due to change of struct device_link +- driver core: Expose device link details in sysfs +- driver core: Add device link support for SYNC_STATE_ONLY flag +- fix kabi broken due to change of struct dev_pm_info +- PM / core: Add support to skip power management in device/driver model +- scsi: hisi_sas: Fix up probe error handling for v3 hw +- scsi: hisi_sas: Select a suitable queue for internal I/Os +- PM: runtime: Resume the device earlier in __device_release_driver() +- PM: runtime: Drop pm_runtime_clean_up_links() +- PM: runtime: Drop runtime PM references to supplier on link removal +- scsi: hisi_sas: Stop using queue #0 always for v2 hw +- scsi: hisi_sas: Recover PHY state according to the status before reset +- scsi: hisi_sas: Add device link between SCSI devices and hisi_hba +- scsi: hisi_sas: Add check for methods _PS0 and _PR0 +- scsi: hisi_sas: Add controller runtime PM support for v3 hw +- scsi: hisi_sas: Switch to new framework to support suspend and resume +- scsi: hisi_sas: Use hisi_hba->cq_nvecs for calling calling synchronize_irq() +- PM: runtime: Remove link state checks in rpm_get/put_supplier() +- scsi: hisi_sas: Code style cleanup +- scsi: hisi_sas: Add missing newlines +- scsi: hisi_sas: Add BIST support for fixed code pattern +- scsi: hisi_sas: Add BIST support for phy FFE +- scsi: hisi_sas: Make phy index variable name consistent +- scsi: hisi_sas: Do not modify upper fields of PROG_PHY_LINK_RATE reg +- scsi: hisi_sas: Modify macro name for OOB phy linkrate +- scsi: scsi_debug: Support host tagset +- scsi: scsi_debug: Support hostwide tags +- scsi: hisi_sas: Switch v3 hw to MQ +- scsi: core: Show nr_hw_queues in sysfs +- fix kabi broken due to change of struct scsi_host_template and Scsi_Host +- scsi: Add host and host template flag 'host_tagset' +- fix kabi broken due to change of struct blk_mq_tag_set +- blk-mq: Record active_queues_shared_sbitmap per tag_set for when using shared sbitmap +- fix kabi broken due to change of struct request_queue +- blk-mq: Record nr_active_requests per queue for when using shared sbitmap +- blk-mq: Relocate hctx_may_queue() +- fix kabi broken due to change of struct blk_mq_tag_set +- blk-mq: Facilitate a shared sbitmap per tagset +- fix kabi broken due to change of struct blk_mq_tags +- blk-mq: Use pointers for blk_mq_tags bitmap tags +- blk-mq: Pass flags for tag init/free +- blk-mq: Free tags in blk_mq_init_tags() upon error +- blk-mq: Rename blk_mq_update_tag_set_depth() +- blk-mq: Rename BLK_MQ_F_TAG_SHARED as BLK_MQ_F_TAG_QUEUE_SHARED +- block: move queues types to the block layer +- blk-mq: initial support for multiple queue maps +- blk-mq: improve plug list sorting +- blk-mq: cleanup and improve list insertion +- fix kabi broken due to change of struct request +- blk-mq: cache request hardware queue mapping +- blk-mq: separate number of hardware queues from nr_cpu_ids +- fix kabi broken due to change of struct blk_mq_tag_set and blk_mq_ops +- blk-mq: support multiple hctx maps +- blk-mq: add 'type' attribute to the sysfs hctx directory +- fix kabi broken due to change of struct blk_mq_hw_ctx and blk_mq_ctx +- blk-mq: allow software queue to map to multiple hardware queues +- fix kabi broken due to change of struct blk_mq_alloc_data +- blk-mq: pass in request/bio flags to queue mapping +- blk-mq: provide dummy blk_mq_map_queue_type() helper +- fix kabi broken due to change of function blk_mq_map_queues and blk_mq_pci_map_queues +- blk-mq: abstract out queue map +- fix kabi broken due to change of struct struct request_queue +- blk-mq: kill q->mq_map +- block: add REQ_HIPRI and inherit it from IOCB_HIPRI +- scsi: hisi_sas: Remove one kerneldoc comment +- scsi: hisi_sas: Do not reset phy timer to wait for stray phy up +- scsi: hisi_sas: Stop returning error code from slot_complete_vX_hw() +- scsi: hisi_sas: Add SAS_RAS_INTR0 to debugfs register name list +- scsi: hisi_sas: Modify the commit information for DSM method +- scsi: hisi_sas: Display proc_name in sysfs +- scsi: hisi_sas: Fix build error without SATA_HOST +- scsi: hisi_sas: Use dev_err() in read_iost_itct_cache_v3_hw() +- scsi: hisi_sas: Rename hisi_sas_cq.pci_irq_mask +- scsi: hisi_sas: Add prints for v3 hw interrupt converge and automatic affinity +- scsi: hisi_sas: Modify the file permissions of trigger_dump to write only +- scsi: hisi_sas: Replace magic number when handle channel interrupt +- scsi: hisi_sas: Stop converting a bool into a bool +- scsi: hisi_sas: Return directly if init hardware failed +- scsi: hisi_sas: Record the phy down event in debugfs +- scsi: hisi_sas: Delete the debugfs folder of hisi_sas when the probe fails +- scsi: hisi_sas: Add ability to have multiple debugfs dumps +- scsi: hisi_sas: Add module parameter for debugfs dump count +- scsi: hisi_sas: Allocate memory for multiple dumps of debugfs +- scsi: hisi_sas: Add debugfs file structure for ITCT cache +- scsi: hisi_sas: Add debugfs file structure for IOST cache +- scsi: hisi_sas: Add debugfs file structure for ITCT +- scsi: hisi_sas: Add debugfs file structure for IOST +- scsi: hisi_sas: Add debugfs file structure for port +- scsi: hisi_sas: Add debugfs file structure for registers +- scsi: hisi_sas: Add debugfs file structure for DQ +- scsi: hisi_sas: Add debugfs file structure for CQ +- scsi: hisi_sas: Add timestamp for a debugfs dump +- scsi: hisi_sas: Don't create debugfs dump folder twice +- scsi: hisi_sas: Make three functions static +- scsi: hisi_sas: fix spelling mistake "digial" -> "digital" +- scsi: hisi_sas: Add hisi_sas_debugfs_alloc() to centralise allocation +- scsi: hisi_sas: Remove some unused function arguments +- scsi: hisi_sas: Remove redundant work declaration +- scsi: hisi_sas: Remove hisi_sas_hw.slot_complete +- scsi: hisi_sas: add debugfs auto-trigger for internal abort time out +- scsi: hisi_sas: use devm_platform_ioremap_resource() to simplify code +- scsi: hisi_sas: remove set but not used variable 'irq_value' +- scsi: hisi_sas: Remove some unnecessary code +- scsi: hisi_sas: Modify return type of debugfs functions +- scsi: hisi_sas: Drop free_irq() when devm_request_irq() failed +- scsi: hisi_sas: Drop SMP resp frame DMA mapping +- scsi: hisi_sas: Drop kmap_atomic() in SMP command completion +- scsi: hisi_sas: Snapshot AXI and RAS register at debugfs +- scsi: hisi_sas: Snapshot HW cache of IOST and ITCT at debugfs +- scsi: hisi_sas: Fix pointer usage error in show debugfs IOST/ITCT +- scsi: hisi_sas: Make max IPTT count equal for all hw revisions +- scsi: hisi_sas: Some misc tidy-up +- scsi: hisi_sas: Use pci_irq_get_affinity() for v3 hw as experimental +- scsi: hisi_sas: Fix losing directly attached disk when hot-plug +- scsi: hisi_sas: Fix type casting and missing static qualifier in debugfs code +- scsi: hisi_sas: No need to check return value of debugfs_create functions +- blk-mq: Enable support for runtime power management +- block: Make blk_get_request() block for non-PM requests while suspended +- block: Allow unfreezing of a queue while requests are in progress +- block: Schedule runtime resume earlier +- block: Split blk_pm_add_request() and blk_pm_put_request() +- block: Move power management code into a new source file * Fri Nov 10 2023 hongrongxuan - 4.19.90-2311.1.0.0239 - perf metricgroup: Fix find_evsel_group() event selector diff --git a/patches/0319-block-Move-power-management-code-into-a-new-source-f.patch b/patches/0319-block-Move-power-management-code-into-a-new-source-f.patch new file mode 100644 index 00000000..58ecd82e --- /dev/null +++ b/patches/0319-block-Move-power-management-code-into-a-new-source-f.patch @@ -0,0 +1,679 @@ +From b8338713223360db5f3f4adb0046cf27ed3b2636 Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Wed, 26 Sep 2018 14:01:03 -0700 +Subject: [PATCH 001/256] block: Move power management code into a new source + file + +mainline inclusion +from mainline-v4.20-rc1 +commit bca6b067b0b269a7b8ba129e2a918309ca8b4a55 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bca6b067b0b269a7b8ba129e2a918309ca8b4a55 + +---------------------------------------------------------------------- + +Move the code for runtime power management from blk-core.c into the +new source file blk-pm.c. Move the corresponding declarations from + into . For CONFIG_PM=n, leave out +the declarations of the functions that are not used in that mode. +This patch not only reduces the number of #ifdefs in the block layer +core code but also reduces the size of header file +and hence should help to reduce the build time of the Linux kernel +if CONFIG_PM is not defined. + +Signed-off-by: Bart Van Assche +Reviewed-by: Ming Lei +Reviewed-by: Christoph Hellwig +Cc: Jianchao Wang +Cc: Hannes Reinecke +Cc: Johannes Thumshirn +Cc: Alan Stern +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang +--- + block/Kconfig | 3 + + block/Makefile | 1 + + block/blk-core.c | 196 +---------------------------------------- + block/blk-pm.c | 188 +++++++++++++++++++++++++++++++++++++++ + block/blk-pm.h | 43 +++++++++ + block/elevator.c | 22 +---- + drivers/scsi/scsi_pm.c | 1 + + drivers/scsi/sd.c | 1 + + drivers/scsi/sr.c | 1 + + include/linux/blk-pm.h | 24 +++++ + include/linux/blkdev.h | 23 ----- + 11 files changed, 264 insertions(+), 239 deletions(-) + create mode 100644 block/blk-pm.c + create mode 100644 block/blk-pm.h + create mode 100644 include/linux/blk-pm.h + +diff --git a/block/Kconfig b/block/Kconfig +index da71e56f8682..4feed3a3d565 100644 +--- a/block/Kconfig ++++ b/block/Kconfig +@@ -241,4 +241,7 @@ config BLK_MQ_RDMA + depends on BLOCK && INFINIBAND + default y + ++config BLK_PM ++ def_bool BLOCK && PM ++ + source block/Kconfig.iosched +diff --git a/block/Makefile b/block/Makefile +index 572b33f32c07..27eac600474f 100644 +--- a/block/Makefile ++++ b/block/Makefile +@@ -37,3 +37,4 @@ obj-$(CONFIG_BLK_WBT) += blk-wbt.o + obj-$(CONFIG_BLK_DEBUG_FS) += blk-mq-debugfs.o + obj-$(CONFIG_BLK_DEBUG_FS_ZONED)+= blk-mq-debugfs-zoned.o + obj-$(CONFIG_BLK_SED_OPAL) += sed-opal.o ++obj-$(CONFIG_BLK_PM) += blk-pm.o +diff --git a/block/blk-core.c b/block/blk-core.c +index acf5585b0557..466cedc4cad8 100644 +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -42,6 +42,7 @@ + #include "blk.h" + #include "blk-mq.h" + #include "blk-mq-sched.h" ++#include "blk-pm.h" + #include "blk-rq-qos.h" + + #ifdef CONFIG_DEBUG_FS +@@ -2021,16 +2022,6 @@ void part_round_stats(struct request_queue *q, int cpu, struct hd_struct *part) + } + EXPORT_SYMBOL_GPL(part_round_stats); + +-#ifdef CONFIG_PM +-static void blk_pm_put_request(struct request *rq) +-{ +- if (rq->q->dev && !(rq->rq_flags & RQF_PM) && !--rq->q->nr_pending) +- pm_runtime_mark_last_busy(rq->q->dev); +-} +-#else +-static inline void blk_pm_put_request(struct request *rq) {} +-#endif +- + void __blk_put_request(struct request_queue *q, struct request *req) + { + req_flags_t rq_flags = req->rq_flags; +@@ -4072,191 +4063,6 @@ void blk_finish_plug(struct blk_plug *plug) + } + EXPORT_SYMBOL(blk_finish_plug); + +-#ifdef CONFIG_PM +-/** +- * blk_pm_runtime_init - Block layer runtime PM initialization routine +- * @q: the queue of the device +- * @dev: the device the queue belongs to +- * +- * Description: +- * Initialize runtime-PM-related fields for @q and start auto suspend for +- * @dev. Drivers that want to take advantage of request-based runtime PM +- * should call this function after @dev has been initialized, and its +- * request queue @q has been allocated, and runtime PM for it can not happen +- * yet(either due to disabled/forbidden or its usage_count > 0). In most +- * cases, driver should call this function before any I/O has taken place. +- * +- * This function takes care of setting up using auto suspend for the device, +- * the autosuspend delay is set to -1 to make runtime suspend impossible +- * until an updated value is either set by user or by driver. Drivers do +- * not need to touch other autosuspend settings. +- * +- * The block layer runtime PM is request based, so only works for drivers +- * that use request as their IO unit instead of those directly use bio's. +- */ +-void blk_pm_runtime_init(struct request_queue *q, struct device *dev) +-{ +- /* Don't enable runtime PM for blk-mq until it is ready */ +- if (q->mq_ops) { +- pm_runtime_disable(dev); +- return; +- } +- +- q->dev = dev; +- q->rpm_status = RPM_ACTIVE; +- pm_runtime_set_autosuspend_delay(q->dev, -1); +- pm_runtime_use_autosuspend(q->dev); +-} +-EXPORT_SYMBOL(blk_pm_runtime_init); +- +-/** +- * blk_pre_runtime_suspend - Pre runtime suspend check +- * @q: the queue of the device +- * +- * Description: +- * This function will check if runtime suspend is allowed for the device +- * by examining if there are any requests pending in the queue. If there +- * are requests pending, the device can not be runtime suspended; otherwise, +- * the queue's status will be updated to SUSPENDING and the driver can +- * proceed to suspend the device. +- * +- * For the not allowed case, we mark last busy for the device so that +- * runtime PM core will try to autosuspend it some time later. +- * +- * This function should be called near the start of the device's +- * runtime_suspend callback. +- * +- * Return: +- * 0 - OK to runtime suspend the device +- * -EBUSY - Device should not be runtime suspended +- */ +-int blk_pre_runtime_suspend(struct request_queue *q) +-{ +- int ret = 0; +- +- if (!q->dev) +- return ret; +- +- spin_lock_irq(q->queue_lock); +- if (q->nr_pending) { +- ret = -EBUSY; +- pm_runtime_mark_last_busy(q->dev); +- } else { +- q->rpm_status = RPM_SUSPENDING; +- } +- spin_unlock_irq(q->queue_lock); +- return ret; +-} +-EXPORT_SYMBOL(blk_pre_runtime_suspend); +- +-/** +- * blk_post_runtime_suspend - Post runtime suspend processing +- * @q: the queue of the device +- * @err: return value of the device's runtime_suspend function +- * +- * Description: +- * Update the queue's runtime status according to the return value of the +- * device's runtime suspend function and mark last busy for the device so +- * that PM core will try to auto suspend the device at a later time. +- * +- * This function should be called near the end of the device's +- * runtime_suspend callback. +- */ +-void blk_post_runtime_suspend(struct request_queue *q, int err) +-{ +- if (!q->dev) +- return; +- +- spin_lock_irq(q->queue_lock); +- if (!err) { +- q->rpm_status = RPM_SUSPENDED; +- } else { +- q->rpm_status = RPM_ACTIVE; +- pm_runtime_mark_last_busy(q->dev); +- } +- spin_unlock_irq(q->queue_lock); +-} +-EXPORT_SYMBOL(blk_post_runtime_suspend); +- +-/** +- * blk_pre_runtime_resume - Pre runtime resume processing +- * @q: the queue of the device +- * +- * Description: +- * Update the queue's runtime status to RESUMING in preparation for the +- * runtime resume of the device. +- * +- * This function should be called near the start of the device's +- * runtime_resume callback. +- */ +-void blk_pre_runtime_resume(struct request_queue *q) +-{ +- if (!q->dev) +- return; +- +- spin_lock_irq(q->queue_lock); +- q->rpm_status = RPM_RESUMING; +- spin_unlock_irq(q->queue_lock); +-} +-EXPORT_SYMBOL(blk_pre_runtime_resume); +- +-/** +- * blk_post_runtime_resume - Post runtime resume processing +- * @q: the queue of the device +- * @err: return value of the device's runtime_resume function +- * +- * Description: +- * Update the queue's runtime status according to the return value of the +- * device's runtime_resume function. If it is successfully resumed, process +- * the requests that are queued into the device's queue when it is resuming +- * and then mark last busy and initiate autosuspend for it. +- * +- * This function should be called near the end of the device's +- * runtime_resume callback. +- */ +-void blk_post_runtime_resume(struct request_queue *q, int err) +-{ +- if (!q->dev) +- return; +- +- spin_lock_irq(q->queue_lock); +- if (!err) { +- q->rpm_status = RPM_ACTIVE; +- __blk_run_queue(q); +- pm_runtime_mark_last_busy(q->dev); +- pm_request_autosuspend(q->dev); +- } else { +- q->rpm_status = RPM_SUSPENDED; +- } +- spin_unlock_irq(q->queue_lock); +-} +-EXPORT_SYMBOL(blk_post_runtime_resume); +- +-/** +- * blk_set_runtime_active - Force runtime status of the queue to be active +- * @q: the queue of the device +- * +- * If the device is left runtime suspended during system suspend the resume +- * hook typically resumes the device and corrects runtime status +- * accordingly. However, that does not affect the queue runtime PM status +- * which is still "suspended". This prevents processing requests from the +- * queue. +- * +- * This function can be used in driver's resume hook to correct queue +- * runtime PM status and re-enable peeking requests from the queue. It +- * should be called before first request is added to the queue. +- */ +-void blk_set_runtime_active(struct request_queue *q) +-{ +- spin_lock_irq(q->queue_lock); +- q->rpm_status = RPM_ACTIVE; +- pm_runtime_mark_last_busy(q->dev); +- pm_request_autosuspend(q->dev); +- spin_unlock_irq(q->queue_lock); +-} +-EXPORT_SYMBOL(blk_set_runtime_active); +-#endif +- + int __init blk_dev_init(void) + { + BUILD_BUG_ON(REQ_OP_LAST >= (1 << REQ_OP_BITS)); +diff --git a/block/blk-pm.c b/block/blk-pm.c +new file mode 100644 +index 000000000000..9b636960d285 +--- /dev/null ++++ b/block/blk-pm.c +@@ -0,0 +1,188 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++#include ++#include ++ ++/** ++ * blk_pm_runtime_init - Block layer runtime PM initialization routine ++ * @q: the queue of the device ++ * @dev: the device the queue belongs to ++ * ++ * Description: ++ * Initialize runtime-PM-related fields for @q and start auto suspend for ++ * @dev. Drivers that want to take advantage of request-based runtime PM ++ * should call this function after @dev has been initialized, and its ++ * request queue @q has been allocated, and runtime PM for it can not happen ++ * yet(either due to disabled/forbidden or its usage_count > 0). In most ++ * cases, driver should call this function before any I/O has taken place. ++ * ++ * This function takes care of setting up using auto suspend for the device, ++ * the autosuspend delay is set to -1 to make runtime suspend impossible ++ * until an updated value is either set by user or by driver. Drivers do ++ * not need to touch other autosuspend settings. ++ * ++ * The block layer runtime PM is request based, so only works for drivers ++ * that use request as their IO unit instead of those directly use bio's. ++ */ ++void blk_pm_runtime_init(struct request_queue *q, struct device *dev) ++{ ++ /* Don't enable runtime PM for blk-mq until it is ready */ ++ if (q->mq_ops) { ++ pm_runtime_disable(dev); ++ return; ++ } ++ ++ q->dev = dev; ++ q->rpm_status = RPM_ACTIVE; ++ pm_runtime_set_autosuspend_delay(q->dev, -1); ++ pm_runtime_use_autosuspend(q->dev); ++} ++EXPORT_SYMBOL(blk_pm_runtime_init); ++ ++/** ++ * blk_pre_runtime_suspend - Pre runtime suspend check ++ * @q: the queue of the device ++ * ++ * Description: ++ * This function will check if runtime suspend is allowed for the device ++ * by examining if there are any requests pending in the queue. If there ++ * are requests pending, the device can not be runtime suspended; otherwise, ++ * the queue's status will be updated to SUSPENDING and the driver can ++ * proceed to suspend the device. ++ * ++ * For the not allowed case, we mark last busy for the device so that ++ * runtime PM core will try to autosuspend it some time later. ++ * ++ * This function should be called near the start of the device's ++ * runtime_suspend callback. ++ * ++ * Return: ++ * 0 - OK to runtime suspend the device ++ * -EBUSY - Device should not be runtime suspended ++ */ ++int blk_pre_runtime_suspend(struct request_queue *q) ++{ ++ int ret = 0; ++ ++ if (!q->dev) ++ return ret; ++ ++ spin_lock_irq(q->queue_lock); ++ if (q->nr_pending) { ++ ret = -EBUSY; ++ pm_runtime_mark_last_busy(q->dev); ++ } else { ++ q->rpm_status = RPM_SUSPENDING; ++ } ++ spin_unlock_irq(q->queue_lock); ++ return ret; ++} ++EXPORT_SYMBOL(blk_pre_runtime_suspend); ++ ++/** ++ * blk_post_runtime_suspend - Post runtime suspend processing ++ * @q: the queue of the device ++ * @err: return value of the device's runtime_suspend function ++ * ++ * Description: ++ * Update the queue's runtime status according to the return value of the ++ * device's runtime suspend function and mark last busy for the device so ++ * that PM core will try to auto suspend the device at a later time. ++ * ++ * This function should be called near the end of the device's ++ * runtime_suspend callback. ++ */ ++void blk_post_runtime_suspend(struct request_queue *q, int err) ++{ ++ if (!q->dev) ++ return; ++ ++ spin_lock_irq(q->queue_lock); ++ if (!err) { ++ q->rpm_status = RPM_SUSPENDED; ++ } else { ++ q->rpm_status = RPM_ACTIVE; ++ pm_runtime_mark_last_busy(q->dev); ++ } ++ spin_unlock_irq(q->queue_lock); ++} ++EXPORT_SYMBOL(blk_post_runtime_suspend); ++ ++/** ++ * blk_pre_runtime_resume - Pre runtime resume processing ++ * @q: the queue of the device ++ * ++ * Description: ++ * Update the queue's runtime status to RESUMING in preparation for the ++ * runtime resume of the device. ++ * ++ * This function should be called near the start of the device's ++ * runtime_resume callback. ++ */ ++void blk_pre_runtime_resume(struct request_queue *q) ++{ ++ if (!q->dev) ++ return; ++ ++ spin_lock_irq(q->queue_lock); ++ q->rpm_status = RPM_RESUMING; ++ spin_unlock_irq(q->queue_lock); ++} ++EXPORT_SYMBOL(blk_pre_runtime_resume); ++ ++/** ++ * blk_post_runtime_resume - Post runtime resume processing ++ * @q: the queue of the device ++ * @err: return value of the device's runtime_resume function ++ * ++ * Description: ++ * Update the queue's runtime status according to the return value of the ++ * device's runtime_resume function. If it is successfully resumed, process ++ * the requests that are queued into the device's queue when it is resuming ++ * and then mark last busy and initiate autosuspend for it. ++ * ++ * This function should be called near the end of the device's ++ * runtime_resume callback. ++ */ ++void blk_post_runtime_resume(struct request_queue *q, int err) ++{ ++ if (!q->dev) ++ return; ++ ++ spin_lock_irq(q->queue_lock); ++ if (!err) { ++ q->rpm_status = RPM_ACTIVE; ++ __blk_run_queue(q); ++ pm_runtime_mark_last_busy(q->dev); ++ pm_request_autosuspend(q->dev); ++ } else { ++ q->rpm_status = RPM_SUSPENDED; ++ } ++ spin_unlock_irq(q->queue_lock); ++} ++EXPORT_SYMBOL(blk_post_runtime_resume); ++ ++/** ++ * blk_set_runtime_active - Force runtime status of the queue to be active ++ * @q: the queue of the device ++ * ++ * If the device is left runtime suspended during system suspend the resume ++ * hook typically resumes the device and corrects runtime status ++ * accordingly. However, that does not affect the queue runtime PM status ++ * which is still "suspended". This prevents processing requests from the ++ * queue. ++ * ++ * This function can be used in driver's resume hook to correct queue ++ * runtime PM status and re-enable peeking requests from the queue. It ++ * should be called before first request is added to the queue. ++ */ ++void blk_set_runtime_active(struct request_queue *q) ++{ ++ spin_lock_irq(q->queue_lock); ++ q->rpm_status = RPM_ACTIVE; ++ pm_runtime_mark_last_busy(q->dev); ++ pm_request_autosuspend(q->dev); ++ spin_unlock_irq(q->queue_lock); ++} ++EXPORT_SYMBOL(blk_set_runtime_active); +diff --git a/block/blk-pm.h b/block/blk-pm.h +new file mode 100644 +index 000000000000..1ffc8ef203ec +--- /dev/null ++++ b/block/blk-pm.h +@@ -0,0 +1,43 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++ ++#ifndef _BLOCK_BLK_PM_H_ ++#define _BLOCK_BLK_PM_H_ ++ ++#include ++ ++#ifdef CONFIG_PM ++static inline void blk_pm_requeue_request(struct request *rq) ++{ ++ if (rq->q->dev && !(rq->rq_flags & RQF_PM)) ++ rq->q->nr_pending--; ++} ++ ++static inline void blk_pm_add_request(struct request_queue *q, ++ struct request *rq) ++{ ++ if (q->dev && !(rq->rq_flags & RQF_PM) && q->nr_pending++ == 0 && ++ (q->rpm_status == RPM_SUSPENDED || q->rpm_status == RPM_SUSPENDING)) ++ pm_request_resume(q->dev); ++} ++ ++static inline void blk_pm_put_request(struct request *rq) ++{ ++ if (rq->q->dev && !(rq->rq_flags & RQF_PM) && !--rq->q->nr_pending) ++ pm_runtime_mark_last_busy(rq->q->dev); ++} ++#else ++static inline void blk_pm_requeue_request(struct request *rq) ++{ ++} ++ ++static inline void blk_pm_add_request(struct request_queue *q, ++ struct request *rq) ++{ ++} ++ ++static inline void blk_pm_put_request(struct request *rq) ++{ ++} ++#endif ++ ++#endif /* _BLOCK_BLK_PM_H_ */ +diff --git a/block/elevator.c b/block/elevator.c +index 91c8769882d5..93540a12ca44 100644 +--- a/block/elevator.c ++++ b/block/elevator.c +@@ -41,6 +41,7 @@ + + #include "blk.h" + #include "blk-mq-sched.h" ++#include "blk-pm.h" + #include "blk-wbt.h" + + static DEFINE_SPINLOCK(elv_list_lock); +@@ -562,27 +563,6 @@ void elv_bio_merged(struct request_queue *q, struct request *rq, + e->type->ops.sq.elevator_bio_merged_fn(q, rq, bio); + } + +-#ifdef CONFIG_PM +-static void blk_pm_requeue_request(struct request *rq) +-{ +- if (rq->q->dev && !(rq->rq_flags & RQF_PM)) +- rq->q->nr_pending--; +-} +- +-static void blk_pm_add_request(struct request_queue *q, struct request *rq) +-{ +- if (q->dev && !(rq->rq_flags & RQF_PM) && q->nr_pending++ == 0 && +- (q->rpm_status == RPM_SUSPENDED || q->rpm_status == RPM_SUSPENDING)) +- pm_request_resume(q->dev); +-} +-#else +-static inline void blk_pm_requeue_request(struct request *rq) {} +-static inline void blk_pm_add_request(struct request_queue *q, +- struct request *rq) +-{ +-} +-#endif +- + void elv_requeue_request(struct request_queue *q, struct request *rq) + { + /* +diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c +index ebc193f7f7dd..7639df91b110 100644 +--- a/drivers/scsi/scsi_pm.c ++++ b/drivers/scsi/scsi_pm.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + + #include + #include +diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c +index e674565ae488..871f31e5e5d1 100644 +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -45,6 +45,7 @@ + #include + #include + #include ++#include + #include + #include + #include +diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c +index 180087d1c6cd..2c4a17e28e4e 100644 +--- a/drivers/scsi/sr.c ++++ b/drivers/scsi/sr.c +@@ -43,6 +43,7 @@ + #include + #include + #include ++#include + #include + #include + #include +diff --git a/include/linux/blk-pm.h b/include/linux/blk-pm.h +new file mode 100644 +index 000000000000..b80c65aba249 +--- /dev/null ++++ b/include/linux/blk-pm.h +@@ -0,0 +1,24 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++ ++#ifndef _BLK_PM_H_ ++#define _BLK_PM_H_ ++ ++struct device; ++struct request_queue; ++ ++/* ++ * block layer runtime pm functions ++ */ ++#ifdef CONFIG_PM ++extern void blk_pm_runtime_init(struct request_queue *q, struct device *dev); ++extern int blk_pre_runtime_suspend(struct request_queue *q); ++extern void blk_post_runtime_suspend(struct request_queue *q, int err); ++extern void blk_pre_runtime_resume(struct request_queue *q); ++extern void blk_post_runtime_resume(struct request_queue *q, int err); ++extern void blk_set_runtime_active(struct request_queue *q); ++#else ++static inline void blk_pm_runtime_init(struct request_queue *q, ++ struct device *dev) {} ++#endif ++ ++#endif /* _BLK_PM_H_ */ +diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h +index c848f4205729..aac3fa0c4601 100644 +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -1333,29 +1333,6 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id, + extern void blk_put_queue(struct request_queue *); + extern void blk_set_queue_dying(struct request_queue *); + +-/* +- * block layer runtime pm functions +- */ +-#ifdef CONFIG_PM +-extern void blk_pm_runtime_init(struct request_queue *q, struct device *dev); +-extern int blk_pre_runtime_suspend(struct request_queue *q); +-extern void blk_post_runtime_suspend(struct request_queue *q, int err); +-extern void blk_pre_runtime_resume(struct request_queue *q); +-extern void blk_post_runtime_resume(struct request_queue *q, int err); +-extern void blk_set_runtime_active(struct request_queue *q); +-#else +-static inline void blk_pm_runtime_init(struct request_queue *q, +- struct device *dev) {} +-static inline int blk_pre_runtime_suspend(struct request_queue *q) +-{ +- return -ENOSYS; +-} +-static inline void blk_post_runtime_suspend(struct request_queue *q, int err) {} +-static inline void blk_pre_runtime_resume(struct request_queue *q) {} +-static inline void blk_post_runtime_resume(struct request_queue *q, int err) {} +-static inline void blk_set_runtime_active(struct request_queue *q) {} +-#endif +- + /* + * blk_plug permits building a queue of related requests by holding the I/O + * fragments for a short period. This allows merging of sequential requests +-- +2.27.0 + diff --git a/patches/0320-block-Split-blk_pm_add_request-and-blk_pm_put_reques.patch b/patches/0320-block-Split-blk_pm_add_request-and-blk_pm_put_reques.patch new file mode 100644 index 00000000..614b2bd9 --- /dev/null +++ b/patches/0320-block-Split-blk_pm_add_request-and-blk_pm_put_reques.patch @@ -0,0 +1,126 @@ +From 74387c669fe2cf0185713b88b9fa02f64c2c5310 Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Wed, 26 Sep 2018 14:01:05 -0700 +Subject: [PATCH 002/256] block: Split blk_pm_add_request() and + blk_pm_put_request() + +mainline inclusion +from mainline-v4.20-rc1 +commit 154b00d566e221152514ba8259f38b21571081ef +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=154b00d566e221152514ba8259f38b21571081ef + +---------------------------------------------------------------------- + +Move the pm_request_resume() and pm_runtime_mark_last_busy() calls into +two new functions and thereby separate legacy block layer code from code +that works for both the legacy block layer and blk-mq. A later patch will +add calls to the new functions in the blk-mq code. + +Signed-off-by: Bart Van Assche +Reviewed-by: Ming Lei +Reviewed-by: Christoph Hellwig +Cc: Martin K. Petersen +Cc: Jianchao Wang +Cc: Hannes Reinecke +Cc: Johannes Thumshirn +Cc: Alan Stern +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang +--- + block/blk-core.c | 1 + + block/blk-pm.h | 36 +++++++++++++++++++++++++++++++----- + block/elevator.c | 1 + + 3 files changed, 33 insertions(+), 5 deletions(-) + +diff --git a/block/blk-core.c b/block/blk-core.c +index 466cedc4cad8..368d4544d678 100644 +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -2038,6 +2038,7 @@ void __blk_put_request(struct request_queue *q, struct request *req) + + blk_req_zone_write_unlock(req); + blk_pm_put_request(req); ++ blk_pm_mark_last_busy(req); + + elv_completed_request(q, req); + +diff --git a/block/blk-pm.h b/block/blk-pm.h +index 1ffc8ef203ec..a8564ea72a41 100644 +--- a/block/blk-pm.h ++++ b/block/blk-pm.h +@@ -6,8 +6,23 @@ + #include + + #ifdef CONFIG_PM ++static inline void blk_pm_request_resume(struct request_queue *q) ++{ ++ if (q->dev && (q->rpm_status == RPM_SUSPENDED || ++ q->rpm_status == RPM_SUSPENDING)) ++ pm_request_resume(q->dev); ++} ++ ++static inline void blk_pm_mark_last_busy(struct request *rq) ++{ ++ if (rq->q->dev && !(rq->rq_flags & RQF_PM)) ++ pm_runtime_mark_last_busy(rq->q->dev); ++} ++ + static inline void blk_pm_requeue_request(struct request *rq) + { ++ lockdep_assert_held(rq->q->queue_lock); ++ + if (rq->q->dev && !(rq->rq_flags & RQF_PM)) + rq->q->nr_pending--; + } +@@ -15,17 +30,28 @@ static inline void blk_pm_requeue_request(struct request *rq) + static inline void blk_pm_add_request(struct request_queue *q, + struct request *rq) + { +- if (q->dev && !(rq->rq_flags & RQF_PM) && q->nr_pending++ == 0 && +- (q->rpm_status == RPM_SUSPENDED || q->rpm_status == RPM_SUSPENDING)) +- pm_request_resume(q->dev); ++ lockdep_assert_held(q->queue_lock); ++ ++ if (q->dev && !(rq->rq_flags & RQF_PM)) ++ q->nr_pending++; + } + + static inline void blk_pm_put_request(struct request *rq) + { +- if (rq->q->dev && !(rq->rq_flags & RQF_PM) && !--rq->q->nr_pending) +- pm_runtime_mark_last_busy(rq->q->dev); ++ lockdep_assert_held(rq->q->queue_lock); ++ ++ if (rq->q->dev && !(rq->rq_flags & RQF_PM)) ++ --rq->q->nr_pending; + } + #else ++static inline void blk_pm_request_resume(struct request_queue *q) ++{ ++} ++ ++static inline void blk_pm_mark_last_busy(struct request *rq) ++{ ++} ++ + static inline void blk_pm_requeue_request(struct request *rq) + { + } +diff --git a/block/elevator.c b/block/elevator.c +index 93540a12ca44..307214632c91 100644 +--- a/block/elevator.c ++++ b/block/elevator.c +@@ -607,6 +607,7 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where) + trace_block_rq_insert(q, rq); + + blk_pm_add_request(q, rq); ++ blk_pm_request_resume(q); + + rq->q = q; + +-- +2.27.0 + diff --git a/patches/0321-block-Schedule-runtime-resume-earlier.patch b/patches/0321-block-Schedule-runtime-resume-earlier.patch new file mode 100644 index 00000000..e7569804 --- /dev/null +++ b/patches/0321-block-Schedule-runtime-resume-earlier.patch @@ -0,0 +1,68 @@ +From 16e80bbfc1171a7c708e7ebb03b8271f372a0795 Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Wed, 26 Sep 2018 14:01:06 -0700 +Subject: [PATCH 003/256] block: Schedule runtime resume earlier + +mainline inclusion +from mainline-v4.20-rc1 +commit 0d25bd072b494a0290a7855a2e0286c4a0c92041 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0d25bd072b494a0290a7855a2e0286c4a0c92041 + +---------------------------------------------------------------------- + +Instead of scheduling runtime resume of a request queue after a +request has been queued, schedule asynchronous resume during request +allocation. The new pm_request_resume() calls occur after +blk_queue_enter() has increased the q_usage_counter request queue +member. This change is needed for a later patch that will make request +allocation block while the queue status is not RPM_ACTIVE. + +Signed-off-by: Bart Van Assche +Reviewed-by: Ming Lei +Reviewed-by: Christoph Hellwig +Cc: Jianchao Wang +Cc: Hannes Reinecke +Cc: Johannes Thumshirn +Cc: Alan Stern +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang + + Conflicts: + block/blk-core.c +--- + block/blk-core.c | 3 ++- + block/elevator.c | 1 - + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/block/blk-core.c b/block/blk-core.c +index 368d4544d678..20a23cb3c323 100644 +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -1232,7 +1232,8 @@ int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags) + + wait_event(q->mq_freeze_wq, + (!queue_to_wrapper(q)->mq_freeze_depth && +- (pm || !blk_queue_pm_only(q))) || ++ (pm || (blk_pm_request_resume(q), ++ !blk_queue_pm_only(q)))) || + blk_queue_dying(q)); + if (blk_queue_dying(q)) + return -ENODEV; +diff --git a/block/elevator.c b/block/elevator.c +index 307214632c91..93540a12ca44 100644 +--- a/block/elevator.c ++++ b/block/elevator.c +@@ -607,7 +607,6 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where) + trace_block_rq_insert(q, rq); + + blk_pm_add_request(q, rq); +- blk_pm_request_resume(q); + + rq->q = q; + +-- +2.27.0 + diff --git a/patches/0322-block-Allow-unfreezing-of-a-queue-while-requests-are.patch b/patches/0322-block-Allow-unfreezing-of-a-queue-while-requests-are.patch new file mode 100644 index 00000000..f6ac5c30 --- /dev/null +++ b/patches/0322-block-Allow-unfreezing-of-a-queue-while-requests-are.patch @@ -0,0 +1,53 @@ +From 6d037b0ddfd6c3b40636eb6472532521cec4c086 Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Wed, 26 Sep 2018 14:01:08 -0700 +Subject: [PATCH 004/256] block: Allow unfreezing of a queue while requests are + in progress + +mainline inclusion +from mainline-v4.20-rc1 +commit bdd6316094e0370cd183bc979dd7e322b68dc993 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bdd6316094e0370cd183bc979dd7e322b68dc993 + +---------------------------------------------------------------------- + +A later patch will call blk_freeze_queue_start() followed by +blk_mq_unfreeze_queue() without waiting for q_usage_counter to drop +to zero. Make sure that this doesn't cause a kernel warning to appear +by switching from percpu_ref_reinit() to percpu_ref_resurrect(). The +former namely requires that the refcount it operates on is zero. + +Signed-off-by: Bart Van Assche +Reviewed-by: Ming Lei +Reviewed-by: Christoph Hellwig +Cc: Jianchao Wang +Cc: Hannes Reinecke +Cc: Johannes Thumshirn +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang + + Conflicts: + block/blk-mq.c +--- + block/blk-mq.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block/blk-mq.c b/block/blk-mq.c +index 96debbe63ad2..73f0f5ed8ec1 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -203,7 +203,7 @@ void blk_mq_unfreeze_queue(struct request_queue *q) + + WARN_ON_ONCE(q_wrapper->mq_freeze_depth < 0); + if (!q_wrapper->mq_freeze_depth) { +- percpu_ref_reinit(&q->q_usage_counter); ++ percpu_ref_resurrect(&q->q_usage_counter); + wake_up_all(&q->mq_freeze_wq); + } + +-- +2.27.0 + diff --git a/patches/0323-block-Make-blk_get_request-block-for-non-PM-requests.patch b/patches/0323-block-Make-blk_get_request-block-for-non-PM-requests.patch new file mode 100644 index 00000000..838748c5 --- /dev/null +++ b/patches/0323-block-Make-blk_get_request-block-for-non-PM-requests.patch @@ -0,0 +1,185 @@ +From 4796e523839030190bf766ac77d598d1d3680493 Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Wed, 26 Sep 2018 14:01:09 -0700 +Subject: [PATCH 005/256] block: Make blk_get_request() block for non-PM + requests while suspended + +mainline inclusion +from mainline-v4.20-rc1 +commit 7cedffec8e759480f7f7a9be9cd0d7ebf0aafff2 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7cedffec8e759480f7f7a9be9cd0d7ebf0aafff2 + +---------------------------------------------------------------------- + +Instead of allowing requests that are not power management requests +to enter the queue in runtime suspended status (RPM_SUSPENDED), make +the blk_get_request() caller block. This change fixes a starvation +issue: it is now guaranteed that power management requests will be +executed no matter how many blk_get_request() callers are waiting. +For blk-mq, instead of maintaining the q->nr_pending counter, rely +on q->q_usage_counter. Call pm_runtime_mark_last_busy() every time a +request finishes instead of only if the queue depth drops to zero. + +Signed-off-by: Bart Van Assche +Reviewed-by: Ming Lei +Reviewed-by: Christoph Hellwig +Cc: Jianchao Wang +Cc: Hannes Reinecke +Cc: Johannes Thumshirn +Cc: Alan Stern +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang +--- + block/blk-core.c | 37 ++++++++----------------------------- + block/blk-pm.c | 44 +++++++++++++++++++++++++++++++++++++++----- + 2 files changed, 47 insertions(+), 34 deletions(-) + +diff --git a/block/blk-core.c b/block/blk-core.c +index 20a23cb3c323..fe3553382b0e 100644 +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -3069,30 +3069,6 @@ void blk_account_io_done(struct request *req, u64 now) + } + } + +-#ifdef CONFIG_PM +-/* +- * Don't process normal requests when queue is suspended +- * or in the process of suspending/resuming +- */ +-static bool blk_pm_allow_request(struct request *rq) +-{ +- switch (rq->q->rpm_status) { +- case RPM_RESUMING: +- case RPM_SUSPENDING: +- return rq->rq_flags & RQF_PM; +- case RPM_SUSPENDED: +- return false; +- default: +- return true; +- } +-} +-#else +-static bool blk_pm_allow_request(struct request *rq) +-{ +- return true; +-} +-#endif +- + void blk_account_io_start(struct request *rq, bool new_io) + { + struct hd_struct *part; +@@ -3129,11 +3105,14 @@ static struct request *elv_next_request(struct request_queue *q) + + while (1) { + list_for_each_entry(rq, &q->queue_head, queuelist) { +- if (blk_pm_allow_request(rq)) +- return rq; +- +- if (rq->rq_flags & RQF_SOFTBARRIER) +- break; ++#ifdef CONFIG_PM ++ /* ++ * If a request gets queued in state RPM_SUSPENDED ++ * then that's a kernel bug. ++ */ ++ WARN_ON_ONCE(q->rpm_status == RPM_SUSPENDED); ++#endif ++ return rq; + } + + /* +diff --git a/block/blk-pm.c b/block/blk-pm.c +index 9b636960d285..972fbc656846 100644 +--- a/block/blk-pm.c ++++ b/block/blk-pm.c +@@ -1,8 +1,11 @@ + // SPDX-License-Identifier: GPL-2.0 + ++#include + #include + #include + #include ++#include "blk-mq.h" ++#include "blk-mq-tag.h" + + /** + * blk_pm_runtime_init - Block layer runtime PM initialization routine +@@ -68,14 +71,40 @@ int blk_pre_runtime_suspend(struct request_queue *q) + if (!q->dev) + return ret; + ++ WARN_ON_ONCE(q->rpm_status != RPM_ACTIVE); ++ ++ /* ++ * Increase the pm_only counter before checking whether any ++ * non-PM blk_queue_enter() calls are in progress to avoid that any ++ * new non-PM blk_queue_enter() calls succeed before the pm_only ++ * counter is decreased again. ++ */ ++ blk_set_pm_only(q); ++ ret = -EBUSY; ++ /* Switch q_usage_counter from per-cpu to atomic mode. */ ++ blk_freeze_queue_start(q); ++ /* ++ * Wait until atomic mode has been reached. Since that ++ * involves calling call_rcu(), it is guaranteed that later ++ * blk_queue_enter() calls see the pm-only state. See also ++ * http://lwn.net/Articles/573497/. ++ */ ++ percpu_ref_switch_to_atomic_sync(&q->q_usage_counter); ++ if (percpu_ref_is_zero(&q->q_usage_counter)) ++ ret = 0; ++ /* Switch q_usage_counter back to per-cpu mode. */ ++ blk_mq_unfreeze_queue(q); ++ + spin_lock_irq(q->queue_lock); +- if (q->nr_pending) { +- ret = -EBUSY; ++ if (ret < 0) + pm_runtime_mark_last_busy(q->dev); +- } else { ++ else + q->rpm_status = RPM_SUSPENDING; +- } + spin_unlock_irq(q->queue_lock); ++ ++ if (ret) ++ blk_clear_pm_only(q); ++ + return ret; + } + EXPORT_SYMBOL(blk_pre_runtime_suspend); +@@ -106,6 +135,9 @@ void blk_post_runtime_suspend(struct request_queue *q, int err) + pm_runtime_mark_last_busy(q->dev); + } + spin_unlock_irq(q->queue_lock); ++ ++ if (err) ++ blk_clear_pm_only(q); + } + EXPORT_SYMBOL(blk_post_runtime_suspend); + +@@ -153,13 +185,15 @@ void blk_post_runtime_resume(struct request_queue *q, int err) + spin_lock_irq(q->queue_lock); + if (!err) { + q->rpm_status = RPM_ACTIVE; +- __blk_run_queue(q); + pm_runtime_mark_last_busy(q->dev); + pm_request_autosuspend(q->dev); + } else { + q->rpm_status = RPM_SUSPENDED; + } + spin_unlock_irq(q->queue_lock); ++ ++ if (!err) ++ blk_clear_pm_only(q); + } + EXPORT_SYMBOL(blk_post_runtime_resume); + +-- +2.27.0 + diff --git a/patches/0324-blk-mq-Enable-support-for-runtime-power-management.patch b/patches/0324-blk-mq-Enable-support-for-runtime-power-management.patch new file mode 100644 index 00000000..3bd5ca49 --- /dev/null +++ b/patches/0324-blk-mq-Enable-support-for-runtime-power-management.patch @@ -0,0 +1,73 @@ +From a22dc67d198b8a280f08b9c8e837c09895700f3b Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Wed, 26 Sep 2018 14:01:10 -0700 +Subject: [PATCH 006/256] blk-mq: Enable support for runtime power management + +mainline inclusion +from mainline-v4.20-rc1 +commit 986d413b7c156e69198dfc80fb74aa18d0ddef44 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=986d413b7c156e69198dfc80fb74aa18d0ddef44 + +---------------------------------------------------------------------- + +Now that the blk-mq core processes power management requests +(marked with RQF_PREEMPT) in other states than RPM_ACTIVE, enable +runtime power management for blk-mq. + +Signed-off-by: Bart Van Assche +Reviewed-by: Ming Lei +Reviewed-by: Christoph Hellwig +Cc: Jianchao Wang +Cc: Hannes Reinecke +Cc: Johannes Thumshirn +Cc: Alan Stern +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang +--- + block/blk-mq.c | 2 ++ + block/blk-pm.c | 6 ------ + 2 files changed, 2 insertions(+), 6 deletions(-) + +diff --git a/block/blk-mq.c b/block/blk-mq.c +index 73f0f5ed8ec1..d43c0b7723c2 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -33,6 +33,7 @@ + #include "blk-mq.h" + #include "blk-mq-debugfs.h" + #include "blk-mq-tag.h" ++#include "blk-pm.h" + #include "blk-stat.h" + #include "blk-mq-sched.h" + #include "blk-rq-qos.h" +@@ -532,6 +533,7 @@ static void __blk_mq_free_request(struct request *rq) + struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, ctx->cpu); + const int sched_tag = rq->internal_tag; + ++ blk_pm_mark_last_busy(rq); + if (rq->tag != -1) + blk_mq_put_tag(hctx, hctx->tags, ctx, rq->tag); + if (sched_tag != -1) +diff --git a/block/blk-pm.c b/block/blk-pm.c +index 972fbc656846..f8fdae01bea2 100644 +--- a/block/blk-pm.c ++++ b/block/blk-pm.c +@@ -30,12 +30,6 @@ + */ + void blk_pm_runtime_init(struct request_queue *q, struct device *dev) + { +- /* Don't enable runtime PM for blk-mq until it is ready */ +- if (q->mq_ops) { +- pm_runtime_disable(dev); +- return; +- } +- + q->dev = dev; + q->rpm_status = RPM_ACTIVE; + pm_runtime_set_autosuspend_delay(q->dev, -1); +-- +2.27.0 + diff --git a/patches/0325-scsi-hisi_sas-No-need-to-check-return-value-of-debug.patch b/patches/0325-scsi-hisi_sas-No-need-to-check-return-value-of-debug.patch new file mode 100644 index 00000000..f9a109ef --- /dev/null +++ b/patches/0325-scsi-hisi_sas-No-need-to-check-return-value-of-debug.patch @@ -0,0 +1,165 @@ +From 931ad4d4580a677f774272424609ea295784e80c Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Fri, 25 Jan 2019 22:22:27 +0800 +Subject: [PATCH 007/256] scsi: hisi_sas: No need to check return value of + debugfs_create functions + +mainline inclusion +from mainline-v5.1-rc1 +commit c2c7e740577154e755ec373712e32e5864e88315 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c2c7e740577154e755ec373712e32e5864e88315 + +---------------------------------------------------------------------- + +When calling debugfs functions, there is no need to ever check the return +value. The function can work or not, but the code logic should never do +something different based on this. + +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas.h + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 1 + + drivers/scsi/hisi_sas/hisi_sas_main.c | 56 ++++++++++----------------- + 2 files changed, 21 insertions(+), 36 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 2880e4e22a73..d04d784c45b9 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -437,6 +437,7 @@ struct hisi_hba { + unsigned int dq_idx[NR_CPUS]; + int nvecs; + unsigned int dq_num_per_node; ++ bool debugfs_snapshot; + }; + + /* Generic HW DMA host memory structures */ +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 6bccd36556f2..6d8f9e9e0120 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1621,8 +1621,7 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba) + if (test_and_set_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) + return -EPERM; + +- if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct && +- !hisi_hba->debugfs_dump_dentry) ++ if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct) + hisi_hba->hw->debugfs_work_handler(&hisi_hba->debugfs_work); + + dev_info(dev, "controller resetting...\n"); +@@ -3499,67 +3498,51 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + + /* Create dump dir inside device dir */ + dump_dentry = debugfs_create_dir("dump", hisi_hba->debugfs_dir); +- if (!dump_dentry) +- goto fail; + + hisi_hba->debugfs_dump_dentry = dump_dentry; + +- if (!debugfs_create_file("global", 0400, dump_dentry, hisi_hba, +- &hisi_sas_debugfs_global_fops)) +- goto fail; ++ debugfs_create_file("global", 0400, dump_dentry, hisi_hba, ++ &hisi_sas_debugfs_global_fops); + + /* Create port dir and files */ + dentry = debugfs_create_dir("port", dump_dentry); +- if (!dentry) +- goto fail; + + for (p = 0; p < hisi_hba->n_phy; p++) { + snprintf(name, sizeof(name), "%d", p); +- if (!debugfs_create_file(name, 0400, dentry, +- &hisi_hba->phy[p], +- &hisi_sas_debugfs_port_fops)) +- goto fail; ++ debugfs_create_file(name, 0400, dentry, ++ &hisi_hba->phy[p], ++ &hisi_sas_debugfs_port_fops); + } + + /* Create CQ dir and files */ + dentry = debugfs_create_dir("cq", dump_dentry); +- if (!dentry) +- goto fail; + + for (c = 0; c < hisi_hba->queue_count; c++) { + snprintf(name, sizeof(name), "%d", c); + +- if (!debugfs_create_file(name, 0400, dentry, +- &hisi_hba->cq[c], +- &hisi_sas_debugfs_cq_fops)) +- goto fail; ++ debugfs_create_file(name, 0400, dentry, ++ &hisi_hba->cq[c], ++ &hisi_sas_debugfs_cq_fops); + } + + /* Create DQ dir and files */ + dentry = debugfs_create_dir("dq", dump_dentry); +- if (!dentry) +- goto fail; + + for (d = 0; d < hisi_hba->queue_count; d++) { + snprintf(name, sizeof(name), "%d", d); + +- if (!debugfs_create_file(name, 0400, dentry, +- &hisi_hba->dq[d], +- &hisi_sas_debugfs_dq_fops)) +- goto fail; ++ debugfs_create_file(name, 0400, dentry, ++ &hisi_hba->dq[d], ++ &hisi_sas_debugfs_dq_fops); + } + +- if (!debugfs_create_file("iost", 0400, dump_dentry, hisi_hba, +- &hisi_sas_debugfs_iost_fops)) +- goto fail; ++ debugfs_create_file("iost", 0400, dump_dentry, hisi_hba, ++ &hisi_sas_debugfs_iost_fops); + +- if (!debugfs_create_file("itct", 0400, dump_dentry, hisi_hba, +- &hisi_sas_debugfs_itct_fops)) +- goto fail; ++ debugfs_create_file("itct", 0400, dump_dentry, hisi_hba, ++ &hisi_sas_debugfs_itct_fops); + + return; +-fail: +- hisi_sas_debugfs_exit(hisi_hba); + } + + static void hisi_sas_debugfs_snapshot_regs(struct hisi_hba *hisi_hba) +@@ -3620,6 +3603,10 @@ void hisi_sas_debugfs_work_handler(struct work_struct *work) + struct hisi_hba *hisi_hba = + container_of(work, struct hisi_hba, debugfs_work); + ++ if (hisi_hba->debugfs_snapshot) ++ return; ++ hisi_hba->debugfs_snapshot = true; ++ + hisi_sas_debugfs_snapshot_regs(hisi_hba); + } + EXPORT_SYMBOL_GPL(hisi_sas_debugfs_work_handler); +@@ -3634,9 +3621,6 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) + hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev), + hisi_sas_debugfs_dir); + +- if (!hisi_hba->debugfs_dir) +- return; +- + debugfs_create_file("trigger_dump", 0600, + hisi_hba->debugfs_dir, + hisi_hba, +-- +2.27.0 + diff --git a/patches/0326-scsi-hisi_sas-Fix-type-casting-and-missing-static-qu.patch b/patches/0326-scsi-hisi_sas-Fix-type-casting-and-missing-static-qu.patch new file mode 100644 index 00000000..9d4c3dfe --- /dev/null +++ b/patches/0326-scsi-hisi_sas-Fix-type-casting-and-missing-static-qu.patch @@ -0,0 +1,134 @@ +From 98756e9cbfb51aae50bd7ee1b51660669a4fe996 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Fri, 25 Jan 2019 22:22:28 +0800 +Subject: [PATCH 008/256] scsi: hisi_sas: Fix type casting and missing static + qualifier in debugfs code + +mainline inclusion +from mainline-v5.1-rc1 +commit 5b0eeac4bed4b1a261acf3cd893f929e68814a0d +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5b0eeac4bed4b1a261acf3cd893f929e68814a0d + +---------------------------------------------------------------------- + +Sparse can detect some type casting issues in the debugfs code, so fix it +up. + +Also a missing static qualifier is added to hisi_sas_debugfs_to_reg_name(). + +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 4 ++-- + drivers/scsi/hisi_sas/hisi_sas_main.c | 19 ++++++++++--------- + 2 files changed, 12 insertions(+), 11 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index d04d784c45b9..cd64ac88b684 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -422,8 +422,8 @@ struct hisi_hba { + int enable_dix_dif; + + /* debugfs memories */ +- void *debugfs_global_reg; +- void *debugfs_port_reg[HISI_SAS_MAX_PHYS]; ++ u32 *debugfs_global_reg; ++ u32 *debugfs_port_reg[HISI_SAS_MAX_PHYS]; + void *debugfs_complete_hdr[HISI_SAS_MAX_QUEUES]; + struct hisi_sas_cmd_hdr *debugfs_cmd_hdr[HISI_SAS_MAX_QUEUES]; + struct hisi_sas_iost *debugfs_iost; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 6d8f9e9e0120..e7ffc5eaabe6 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -2847,7 +2847,7 @@ static void hisi_sas_debugfs_snapshot_iost_reg(struct hisi_hba *hisi_hba) + } + } + +-const char * ++static const char * + hisi_sas_debugfs_to_reg_name(int off, int base_off, + const struct hisi_sas_debugfs_reg_lu *lu) + { +@@ -2874,10 +2874,10 @@ static void hisi_sas_debugfs_print_reg(u32 *regs_val, const void *ptr, + + if (name) + seq_printf(s, "0x%08x 0x%08x %s\n", off, +- le32_to_cpu(regs_val[i]), name); ++ regs_val[i], name); + else + seq_printf(s, "0x%08x 0x%08x\n", off, +- le32_to_cpu(regs_val[i])); ++ regs_val[i]); + } + } + +@@ -2887,7 +2887,7 @@ static int hisi_sas_debugfs_global_show(struct seq_file *s, void *p) + const struct hisi_sas_hw *hw = hisi_hba->hw; + const struct hisi_sas_debugfs_reg *reg_global = hw->debugfs_reg_global; + +- hisi_sas_debugfs_print_reg((u32 *)hisi_hba->debugfs_global_reg, ++ hisi_sas_debugfs_print_reg(hisi_hba->debugfs_global_reg, + reg_global, s); + + return 0; +@@ -3317,7 +3317,7 @@ static const struct file_operations hisi_sas_debugfs_port_fops = { + }; + + static int hisi_sas_show_row_64(struct seq_file *s, int index, +- int sz, u64 *ptr) ++ int sz, __le64 *ptr) + { + int i; + +@@ -3336,7 +3336,7 @@ static int hisi_sas_show_row_64(struct seq_file *s, int index, + } + + static int hisi_sas_show_row_32(struct seq_file *s, int index, +- int sz, u32 *ptr) ++ int sz, __le32 *ptr) + { + int i; + +@@ -3359,7 +3359,7 @@ static int hisi_sas_cq_show_slot(struct seq_file *s, int slot, void *cq_ptr) + struct hisi_hba *hisi_hba = cq->hisi_hba; + void *complete_queue = hisi_hba->debugfs_complete_hdr[cq->id]; + u64 offset = hisi_hba->hw->complete_hdr_size * slot; +- void *complete_hdr = complete_queue + offset; ++ __le32 *complete_hdr = complete_queue + offset; + + return hisi_sas_show_row_32(s, slot, + hisi_hba->hw->complete_hdr_size, +@@ -3398,7 +3398,7 @@ static int hisi_sas_dq_show_slot(struct seq_file *s, int slot, void *dq_ptr) + struct hisi_hba *hisi_hba = dq->hisi_hba; + void *cmd_queue = hisi_hba->debugfs_cmd_hdr[dq->id]; + u64 offset = sizeof(struct hisi_sas_cmd_hdr) * slot; +- void *cmd_hdr = cmd_queue + offset; ++ __le32 *cmd_hdr = cmd_queue + offset; + + return hisi_sas_show_row_32(s, slot, sizeof(struct hisi_sas_cmd_hdr), + cmd_hdr); +@@ -3434,10 +3434,11 @@ static int hisi_sas_debugfs_iost_show(struct seq_file *s, void *p) + struct hisi_hba *hisi_hba = s->private; + struct hisi_sas_iost *debugfs_iost = hisi_hba->debugfs_iost; + int i, ret, max_command_entries = hisi_hba->hw->max_command_entries; ++ __le64 *iost = &debugfs_iost->qw0; + + for (i = 0; i < max_command_entries; i++, debugfs_iost++) { + ret = hisi_sas_show_row_64(s, i, sizeof(*debugfs_iost), +- (u64 *)debugfs_iost); ++ iost); + if (ret) + return ret; + } +-- +2.27.0 + diff --git a/patches/0327-scsi-hisi_sas-Fix-losing-directly-attached-disk-when.patch b/patches/0327-scsi-hisi_sas-Fix-losing-directly-attached-disk-when.patch new file mode 100644 index 00000000..6567cbde --- /dev/null +++ b/patches/0327-scsi-hisi_sas-Fix-losing-directly-attached-disk-when.patch @@ -0,0 +1,193 @@ +From f644b80b4e1d784042205e7759b124d61204882e Mon Sep 17 00:00:00 2001 +From: Xiaofei Tan +Date: Fri, 25 Jan 2019 22:22:35 +0800 +Subject: [PATCH 009/256] scsi: hisi_sas: Fix losing directly attached disk + when hot-plug + +mainline inclusion +from mainline-v5.1-rc1 +commit b6c9b15e44090aee2a7fba646b06ff166f595b16 +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b6c9b15e44090aee2a7fba646b06ff166f595b16 + +---------------------------------------------------------------------- + +Hot-plugging SAS wire of direct hard disk backplane may cause disk lost. We +have done this test with several types of SATA disk from different venders, +and only two models from Seagate has this problem, ST4000NM0035-1V4107 and +ST3000VM002-1ET166. + +The root cause is that the disk doesn't send D2H frame after OOB finished. +SAS controller will issue phyup interrupt only when D2H frame is received, +otherwise, will be waiting there all the time. + +When this issue happen, we can find the disk again with link reset. To fix +this issue, we setup an timer after OOB finished. If the PHY is not up in +20s, do link reset. Notes: the 20s is an experience value. + +Signed-off-by: Xiaofei Tan +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 1 + + drivers/scsi/hisi_sas/hisi_sas_main.c | 26 ++++++++++++++++++++++- + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 26 +---------------------- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 29 ++------------------------ + 4 files changed, 29 insertions(+), 53 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index cd64ac88b684..daa64e5aff3e 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -608,6 +608,7 @@ extern void hisi_sas_init_mem(struct hisi_hba *hisi_hba); + extern void hisi_sas_rst_work_handler(struct work_struct *work); + extern void hisi_sas_sync_rst_work_handler(struct work_struct *work); + extern void hisi_sas_kill_tasklets(struct hisi_hba *hisi_hba); ++extern void hisi_sas_phy_oob_ready(struct hisi_hba *hisi_hba, int phy_no); + extern bool hisi_sas_notify_phy_event(struct hisi_sas_phy *phy, + enum hisi_sas_phy_event event); + extern void hisi_sas_release_tasks(struct hisi_hba *hisi_hba); +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index e7ffc5eaabe6..852ece4af0f4 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -915,6 +915,30 @@ bool hisi_sas_notify_phy_event(struct hisi_sas_phy *phy, + } + EXPORT_SYMBOL_GPL(hisi_sas_notify_phy_event); + ++static void hisi_sas_wait_phyup_timedout(struct timer_list *t) ++{ ++ struct hisi_sas_phy *phy = from_timer(phy, t, timer); ++ struct hisi_hba *hisi_hba = phy->hisi_hba; ++ struct device *dev = hisi_hba->dev; ++ int phy_no = phy->sas_phy.id; ++ ++ dev_warn(dev, "phy%d wait phyup timeout, issuing link reset\n", phy_no); ++ hisi_sas_notify_phy_event(phy, HISI_PHYE_LINK_RESET); ++} ++ ++void hisi_sas_phy_oob_ready(struct hisi_hba *hisi_hba, int phy_no) ++{ ++ struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; ++ struct device *dev = hisi_hba->dev; ++ ++ if (!timer_pending(&phy->timer)) { ++ dev_dbg(dev, "phy%d OOB ready\n", phy_no); ++ phy->timer.expires = jiffies + HISI_SAS_WAIT_PHYUP_TIMEOUT * HZ; ++ add_timer(&phy->timer); ++ } ++} ++EXPORT_SYMBOL_GPL(hisi_sas_phy_oob_ready); ++ + static void hisi_sas_phy_init(struct hisi_hba *hisi_hba, int phy_no) + { + struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; +@@ -944,7 +968,7 @@ static void hisi_sas_phy_init(struct hisi_hba *hisi_hba, int phy_no) + + spin_lock_init(&phy->lock); + +- timer_setup(&phy->timer, NULL, 0); ++ timer_setup(&phy->timer, hisi_sas_wait_phyup_timedout, 0); + } + + /* Wrapper to ensure we track hisi_sas_phy.enable properly */ +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +index f9867176fa14..1b701ec807e8 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -2889,30 +2889,6 @@ static const struct hisi_sas_hw_error port_ecc_axi_error[] = { + }, + }; + +-static void wait_phyup_timedout_v2_hw(struct timer_list *t) +-{ +- struct hisi_sas_phy *phy = from_timer(phy, t, timer); +- struct hisi_hba *hisi_hba = phy->hisi_hba; +- struct device *dev = hisi_hba->dev; +- int phy_no = phy->sas_phy.id; +- +- dev_warn(dev, "phy%d wait phyup timeout, issuing link reset\n", phy_no); +- hisi_sas_notify_phy_event(phy, HISI_PHYE_LINK_RESET); +-} +- +-static void phy_oob_ready_v2_hw(struct hisi_hba *hisi_hba, int phy_no) +-{ +- struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; +- struct device *dev = hisi_hba->dev; +- +- if (!timer_pending(&phy->timer)) { +- dev_dbg(dev, "phy%d OOB ready\n", phy_no); +- phy->timer.function = wait_phyup_timedout_v2_hw; +- phy->timer.expires = jiffies + HISI_SAS_WAIT_PHYUP_TIMEOUT; +- add_timer(&phy->timer); +- } +-} +- + static irqreturn_t int_chnl_int_v2_hw(int irq_no, void *p) + { + struct hisi_hba *hisi_hba = p; +@@ -2974,7 +2950,7 @@ static irqreturn_t int_chnl_int_v2_hw(int irq_no, void *p) + phy_bcast_v2_hw(phy_no, hisi_hba); + + if (irq_value0 & CHL_INT0_PHY_RDY_MSK) +- phy_oob_ready_v2_hw(hisi_hba, phy_no); ++ hisi_sas_phy_oob_ready(hisi_hba, phy_no); + + hisi_sas_phy_write32(hisi_hba, phy_no, + CHL_INT0, irq_value0 +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 79010d02ad24..cfa9756fb995 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -1916,38 +1916,13 @@ static void handle_chl_int2_v3_hw(struct hisi_hba *hisi_hba, int phy_no) + hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2, irq_value); + } + +-static void wait_phyup_timedout_v3_hw(struct timer_list *t) +-{ +- struct hisi_sas_phy *phy = from_timer(phy, t, timer); +- struct hisi_hba *hisi_hba = phy->hisi_hba; +- struct device *dev = hisi_hba->dev; +- int phy_no = phy->sas_phy.id; +- +- dev_warn(dev, "phy%d wait phyup timeout, issuing link reset\n", phy_no); +- hisi_sas_notify_phy_event(phy, HISI_PHYE_LINK_RESET); +-} +- + static void handle_chl_int0_v3_hw(struct hisi_hba *hisi_hba, int phy_no) + { + u32 irq_value0 = hisi_sas_phy_read32(hisi_hba, phy_no, CHL_INT0); +- struct device *dev = hisi_hba->dev; + +- if (irq_value0 & CHL_INT0_PHY_RDY_MSK) { +- struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; ++ if (irq_value0 & CHL_INT0_PHY_RDY_MSK) ++ hisi_sas_phy_oob_ready(hisi_hba, phy_no); + +- dev_dbg(dev, "phy%d OOB ready\n", phy_no); +- if (phy->phy_attached) +- goto out; +- +- if (!timer_pending(&phy->timer)) { +- phy->timer.function = wait_phyup_timedout_v3_hw; +- phy->timer.expires = jiffies + +- HISI_SAS_WAIT_PHYUP_TIMEOUT; +- add_timer(&phy->timer); +- } +- } +- +-out: + hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, + irq_value0 & (~CHL_INT0_SL_RX_BCST_ACK_MSK) + & (~CHL_INT0_SL_PHY_ENABLE_MSK) +-- +2.27.0 + diff --git a/patches/0328-scsi-hisi_sas-Use-pci_irq_get_affinity-for-v3-hw-as-.patch b/patches/0328-scsi-hisi_sas-Use-pci_irq_get_affinity-for-v3-hw-as-.patch new file mode 100644 index 00000000..21392826 --- /dev/null +++ b/patches/0328-scsi-hisi_sas-Use-pci_irq_get_affinity-for-v3-hw-as-.patch @@ -0,0 +1,230 @@ +From b91fb32b241ad84fb1ff49ace4a97fc76d2cf956 Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Wed, 6 Feb 2019 18:52:55 +0800 +Subject: [PATCH 010/256] scsi: hisi_sas: Use pci_irq_get_affinity() for v3 hw + as experimental + +mainline inclusion +from mainline-v5.1-rc1 +commit 4fefe5bbf599d6c6bee6b2ee376be789b33ca571 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4fefe5bbf599d6c6bee6b2ee376be789b33ca571 + +---------------------------------------------------------------------- + +For auto-control irq affinity mode, choose the dq to deliver IO according +to the current CPU. + +Then it decreases the performance regression that fio and CQ interrupts are +processed on different node. + +For user control irq affinity mode, keep it as before. + +To realize it, also need to distinguish the usage of dq lock and sas_dev +lock. + +We mark as experimental due to ongoing discussion on managed MSI IRQ +during hotplug: +https://marc.info/?l=linux-scsi&m=154876335707751&w=2 + +We're almost at the point where we can expose multiple queues to the upper +layer for SCSI MQ, but we need to sort out the per-HBA tags performance +issue. + +Signed-off-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas.h + drivers/scsi/hisi_sas/hisi_sas_main.c + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 4 +- + drivers/scsi/hisi_sas/hisi_sas_main.c | 20 ++++--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 74 +++++++++++++++++++------- + 3 files changed, 68 insertions(+), 30 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index daa64e5aff3e..06a8bf9f0f73 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -192,6 +192,7 @@ struct hisi_sas_port { + + struct hisi_sas_cq { + struct hisi_hba *hisi_hba; ++ const struct cpumask *pci_irq_mask; + struct tasklet_struct tasklet; + int rd_point; + int id; +@@ -214,8 +215,8 @@ struct hisi_sas_device { + enum sas_device_type dev_type; + unsigned int device_id; + int sata_idx; +- spinlock_t lock; + enum dev_status dev_status; ++ spinlock_t lock; /* For protecting slots */ + }; + + struct hisi_sas_tmf_task { +@@ -420,6 +421,7 @@ struct hisi_hba { + int bist_loopback_enable; + + int enable_dix_dif; ++ unsigned int *reply_map; + + /* debugfs memories */ + u32 *debugfs_global_reg; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 852ece4af0f4..7ccdaaba311c 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -456,9 +456,6 @@ static int hisi_sas_task_prep(struct sas_task *task, + unsigned long flags; + int wr_q_index; + unsigned int curr_node_id = numa_node_id(); +- unsigned int dq_index = +- (hisi_hba->dq_idx[curr_node_id] % hisi_hba->dq_num_per_node) + +- (hisi_hba->dq_num_per_node * curr_node_id); + + if (DEV_IS_GONE(sas_dev)) { + if (sas_dev) +@@ -471,10 +468,14 @@ static int hisi_sas_task_prep(struct sas_task *task, + return -ECOMM; + } + +- if (hisi_hba->user_ctl_irq) +- *dq_pointer = dq = sas_dev->dq; +- else ++ if (hisi_hba->reply_map) { ++ int cpu = raw_smp_processor_id(); ++ unsigned int dq_index = hisi_hba->reply_map[cpu]; ++ + *dq_pointer = dq = &hisi_hba->dq[dq_index]; ++ } else { ++ *dq_pointer = dq = sas_dev->dq; ++ } + + port = to_hisi_sas_port(sas_port); + if (port && !port->port_attached) { +@@ -2207,11 +2208,8 @@ hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, + abort_flag, tag, dq); + case HISI_SAS_INT_ABT_DEV: + for (i = 0; i < hisi_hba->nvecs; i++) { +- const struct cpumask *mask = NULL; +- +- if (hisi_hba->hw->get_managed_irq_aff) +- mask = hisi_hba->hw->get_managed_irq_aff( +- hisi_hba, i); ++ struct hisi_sas_cq *cq = &hisi_hba->cq[i]; ++ const struct cpumask *mask = cq->pci_irq_mask; + /* + * The kernel will not permit unmanaged (MSI are + * managed) IRQ affinity to offline CPUs, so +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index cfa9756fb995..4635c3b161db 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -556,6 +556,11 @@ module_param(user_ctl_irq, bool, 0444); + MODULE_PARM_DESC(user_ctl_irq, "Enable user control irq affinity:\n" + "default is auto-control irq affinity"); + ++static bool auto_affine_msi_experimental; ++module_param(auto_affine_msi_experimental, bool, 0444); ++MODULE_PARM_DESC(auto_affine_msi_experimental, "Enable auto-affinity of MSI IRQs as experimental:\n" ++ "default is off"); ++ + static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off) + { + void __iomem *regs = hisi_hba->regs + off; +@@ -2677,33 +2682,66 @@ static irqreturn_t cq_interrupt_v3_hw(int irq_no, void *p) + return IRQ_HANDLED; + } + ++static void setup_reply_map_v3_hw(struct hisi_hba *hisi_hba, int nvecs) ++{ ++ const struct cpumask *mask; ++ int queue, cpu; ++ ++ for (queue = 0; queue < nvecs; queue++) { ++ struct hisi_sas_cq *cq = &hisi_hba->cq[queue]; ++ ++ mask = pci_irq_get_affinity(hisi_hba->pci_dev, queue + ++ HISI_SAS_CQ_INT_BASE_VECTORS_V3_HW); ++ if (!mask) ++ goto fallback; ++ cq->pci_irq_mask = mask; ++ for_each_cpu(cpu, mask) ++ hisi_hba->reply_map[cpu] = queue; ++ } ++ return; ++ ++fallback: ++ for_each_possible_cpu(cpu) ++ hisi_hba->reply_map[cpu] = cpu % hisi_hba->queue_count; ++ /* Don't clean all CQ masks */ ++} ++ + static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) + { + struct device *dev = hisi_hba->dev; + struct pci_dev *pdev = hisi_hba->pci_dev; + int vectors, rc; + int i, k; +- int max_msi = HISI_SAS_MSI_COUNT_V3_HW; + int max_dq_num, online_numa_num; +- struct irq_affinity desc = { +- .pre_vectors = HISI_SAS_CQ_INT_BASE_VECTORS_V3_HW, +- }; ++ int max_msi = HISI_SAS_MSI_COUNT_V3_HW, min_msi; + +- if (user_ctl_irq) { +- vectors = pci_alloc_irq_vectors(hisi_hba->pci_dev, 1, +- max_msi, PCI_IRQ_MSI); +- } else { +- vectors = pci_alloc_irq_vectors_affinity(hisi_hba->pci_dev, +- HISI_SAS_MIN_VECTORS_V3_HW, +- max_msi, +- PCI_IRQ_MSI | +- PCI_IRQ_AFFINITY, +- &desc); +- } ++ if (auto_affine_msi_experimental) { ++ struct irq_affinity desc = { ++ .pre_vectors = HISI_SAS_CQ_INT_BASE_VECTORS_V3_HW, ++ }; + +- if (vectors < HISI_SAS_MIN_VECTORS_V3_HW) { +- dev_err(dev, "allocate msi (%d) not enough\n", vectors); +- return -ENOENT; ++ min_msi = HISI_SAS_MIN_VECTORS_V3_HW; ++ ++ hisi_hba->reply_map = devm_kcalloc(dev, nr_cpu_ids, ++ sizeof(unsigned int), ++ GFP_KERNEL); ++ if (!hisi_hba->reply_map) ++ return -ENOMEM; ++ vectors = pci_alloc_irq_vectors_affinity(hisi_hba->pci_dev, ++ min_msi, max_msi, ++ PCI_IRQ_MSI | ++ PCI_IRQ_AFFINITY, ++ &desc); ++ if (vectors < 0) ++ return -ENOENT; ++ setup_reply_map_v3_hw(hisi_hba, ++ vectors - HISI_SAS_CQ_INT_BASE_VECTORS_V3_HW); ++ } else { ++ min_msi = max_msi; ++ vectors = pci_alloc_irq_vectors(hisi_hba->pci_dev, min_msi, ++ max_msi, PCI_IRQ_MSI); ++ if (vectors < 0) ++ return vectors; + } + + hisi_hba->nvecs = vectors - HISI_SAS_CQ_INT_BASE_VECTORS_V3_HW; +-- +2.27.0 + diff --git a/patches/0329-scsi-hisi_sas-Some-misc-tidy-up.patch b/patches/0329-scsi-hisi_sas-Some-misc-tidy-up.patch new file mode 100644 index 00000000..ab69eed6 --- /dev/null +++ b/patches/0329-scsi-hisi_sas-Some-misc-tidy-up.patch @@ -0,0 +1,315 @@ +From 9541cd3831fdc35906098420ff727db227b0334d Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Thu, 11 Apr 2019 20:46:44 +0800 +Subject: [PATCH 011/256] scsi: hisi_sas: Some misc tidy-up + +mainline inclusion +from mainline-v5.2-rc1 +commit 01d4e3a2fc07b269eedeefa1f7c5c7090c442900 +category: cleanup +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=01d4e3a2fc07b269eedeefa1f7c5c7090c442900 + +---------------------------------------------------------------------- + +Do some minor tidy-up. + +Signed-off-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 9 ++---- + drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 9 ++---- + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 42 +++++++++++--------------- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 29 ++++++++---------- + 4 files changed, 37 insertions(+), 52 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 7ccdaaba311c..b280cc109efb 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -2600,22 +2600,19 @@ int hisi_sas_get_fw_info(struct hisi_hba *hisi_hba) + + if (device_property_read_u32(dev, "ctrl-reset-reg", + &hisi_hba->ctrl_reset_reg)) { +- dev_err(dev, +- "could not get property ctrl-reset-reg\n"); ++ dev_err(dev, "could not get property ctrl-reset-reg\n"); + return -ENOENT; + } + + if (device_property_read_u32(dev, "ctrl-reset-sts-reg", + &hisi_hba->ctrl_reset_sts_reg)) { +- dev_err(dev, +- "could not get property ctrl-reset-sts-reg\n"); ++ dev_err(dev, "could not get property ctrl-reset-sts-reg\n"); + return -ENOENT; + } + + if (device_property_read_u32(dev, "ctrl-clock-ena-reg", + &hisi_hba->ctrl_clock_ena_reg)) { +- dev_err(dev, +- "could not get property ctrl-clock-ena-reg\n"); ++ dev_err(dev, "could not get property ctrl-clock-ena-reg\n"); + return -ENOENT; + } + } +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +index 6485e2b6456c..1c51cbd94925 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +@@ -1662,8 +1662,7 @@ static int interrupt_init_v1_hw(struct hisi_hba *hisi_hba) + for (j = 0; j < HISI_SAS_PHY_INT_NR; j++, idx++) { + irq = platform_get_irq(pdev, idx); + if (!irq) { +- dev_err(dev, +- "irq init: fail map phy interrupt %d\n", ++ dev_err(dev, "irq init: fail map phy interrupt %d\n", + idx); + return -ENOENT; + } +@@ -1671,8 +1670,7 @@ static int interrupt_init_v1_hw(struct hisi_hba *hisi_hba) + rc = devm_request_irq(dev, irq, phy_interrupts[j], 0, + DRV_NAME " phy", phy); + if (rc) { +- dev_err(dev, "irq init: could not request " +- "phy interrupt %d, rc=%d\n", ++ dev_err(dev, "irq init: could not request phy interrupt %d, rc=%d\n", + irq, rc); + return -ENOENT; + } +@@ -1709,8 +1707,7 @@ static int interrupt_init_v1_hw(struct hisi_hba *hisi_hba) + rc = devm_request_irq(dev, irq, fatal_interrupts[i], 0, + DRV_NAME " fatal", hisi_hba); + if (rc) { +- dev_err(dev, +- "irq init: could not request fatal interrupt %d, rc=%d\n", ++ dev_err(dev, "irq init: could not request fatal interrupt %d, rc=%d\n", + irq, rc); + return -ENOENT; + } +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +index 1b701ec807e8..72fb4fa69668 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -2413,14 +2413,12 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) + slot_err_v2_hw(hisi_hba, task, slot, 2); + + if (ts->stat != SAS_DATA_UNDERRUN) +- dev_info(dev, "erroneous completion iptt=%d task=%pK dev id=%d " +- "CQ hdr: 0x%x 0x%x 0x%x 0x%x " +- "Error info: 0x%x 0x%x 0x%x 0x%x\n", +- slot->idx, task, sas_dev->device_id, +- dw0, complete_hdr->dw1, +- complete_hdr->act, complete_hdr->dw3, +- error_info[0], error_info[1], +- error_info[2], error_info[3]); ++ dev_info(dev, "erroneous completion iptt=%d task=%pK dev id=%d CQ hdr: 0x%x 0x%x 0x%x 0x%x Error info: 0x%x 0x%x 0x%x 0x%x\n", ++ slot->idx, task, sas_dev->device_id, ++ dw0, complete_hdr->dw1, ++ complete_hdr->act, complete_hdr->dw3, ++ error_info[0], error_info[1], ++ error_info[2], error_info[3]); + + if (unlikely(slot->abort)) { + sas_task_abort(task); +@@ -2495,7 +2493,7 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) + spin_lock_irqsave(&device->done_lock, flags); + if (test_bit(SAS_HA_FROZEN, &ha->state)) { + spin_unlock_irqrestore(&device->done_lock, flags); +- dev_info(dev, "slot complete: task(%pK) ignored\n ", ++ dev_info(dev, "slot complete: task(%pK) ignored\n", + task); + return sts; + } +@@ -2936,7 +2934,7 @@ static irqreturn_t int_chnl_int_v2_hw(int irq_no, void *p) + + if (irq_value2 & BIT(CHL_INT2_SL_IDAF_TOUT_CONF_OFF)) { + dev_warn(dev, "phy%d identify timeout\n", +- phy_no); ++ phy_no); + hisi_sas_notify_phy_event(phy, + HISI_PHYE_LINK_RESET); + } +@@ -3039,7 +3037,7 @@ static const struct hisi_sas_hw_error axi_error[] = { + { .msk = BIT(5), .msg = "SATA_AXI_R_ERR" }, + { .msk = BIT(6), .msg = "DQE_AXI_R_ERR" }, + { .msk = BIT(7), .msg = "CQE_AXI_W_ERR" }, +- {}, ++ {} + }; + + static const struct hisi_sas_hw_error fifo_error[] = { +@@ -3048,7 +3046,7 @@ static const struct hisi_sas_hw_error fifo_error[] = { + { .msk = BIT(10), .msg = "GETDQE_FIFO" }, + { .msk = BIT(11), .msg = "CMDP_FIFO" }, + { .msk = BIT(12), .msg = "AWTCTRL_FIFO" }, +- {}, ++ {} + }; + + static const struct hisi_sas_hw_error fatal_axi_errors[] = { +@@ -3112,12 +3110,12 @@ static irqreturn_t fatal_axi_int_v2_hw(int irq_no, void *p) + if (!(err_value & sub->msk)) + continue; + dev_err(dev, "%s (0x%x) found!\n", +- sub->msg, irq_value); ++ sub->msg, irq_value); + queue_work(hisi_hba->wq, &hisi_hba->rst_work); + } + } else { + dev_err(dev, "%s (0x%x) found!\n", +- axi_error->msg, irq_value); ++ axi_error->msg, irq_value); + queue_work(hisi_hba->wq, &hisi_hba->rst_work); + } + } +@@ -3255,7 +3253,7 @@ static irqreturn_t sata_int_v2_hw(int irq_no, void *p) + /* check ERR bit of Status Register */ + if (fis->status & ATA_ERR) { + dev_warn(dev, "sata int: phy%d FIS status: 0x%x\n", phy_no, +- fis->status); ++ fis->status); + hisi_sas_notify_phy_event(phy, HISI_PHYE_LINK_RESET); + res = IRQ_NONE; + goto end; +@@ -3346,8 +3344,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) + rc = devm_request_irq(dev, irq, phy_interrupts[i], 0, + DRV_NAME " phy", hisi_hba); + if (rc) { +- dev_err(dev, "irq init: could not request " +- "phy interrupt %d, rc=%d\n", ++ dev_err(dev, "irq init: could not request phy interrupt %d, rc=%d\n", + irq, rc); + rc = -ENOENT; + goto free_phy_int_irqs; +@@ -3361,8 +3358,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) + rc = devm_request_irq(dev, irq, sata_int_v2_hw, 0, + DRV_NAME " sata", phy); + if (rc) { +- dev_err(dev, "irq init: could not request " +- "sata interrupt %d, rc=%d\n", ++ dev_err(dev, "irq init: could not request sata interrupt %d, rc=%d\n", + irq, rc); + rc = -ENOENT; + goto free_sata_int_irqs; +@@ -3374,8 +3370,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) + rc = devm_request_irq(dev, irq, fatal_interrupts[fatal_no], 0, + DRV_NAME " fatal", hisi_hba); + if (rc) { +- dev_err(dev, +- "irq init: could not request fatal interrupt %d, rc=%d\n", ++ dev_err(dev, "irq init: could not request fatal interrupt %d, rc=%d\n", + irq, rc); + rc = -ENOENT; + goto free_fatal_int_irqs; +@@ -3390,8 +3385,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) + rc = devm_request_irq(dev, irq, cq_interrupt_v2_hw, 0, + DRV_NAME " cq", cq); + if (rc) { +- dev_err(dev, +- "irq init: could not request cq interrupt %d, rc=%d\n", ++ dev_err(dev, "irq init: could not request cq interrupt %d, rc=%d\n", + irq, rc); + rc = -ENOENT; + goto free_cq_int_irqs; +@@ -3543,7 +3537,7 @@ static int write_gpio_v2_hw(struct hisi_hba *hisi_hba, u8 reg_type, + break; + default: + dev_err(dev, "write gpio: unsupported or bad reg type %d\n", +- reg_type); ++ reg_type); + return -EINVAL; + } + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 4635c3b161db..1285d61b29b4 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -2088,7 +2088,7 @@ static const struct hisi_sas_hw_error axi_error[] = { + { .msk = BIT(5), .msg = "SATA_AXI_R_ERR" }, + { .msk = BIT(6), .msg = "DQE_AXI_R_ERR" }, + { .msk = BIT(7), .msg = "CQE_AXI_W_ERR" }, +- {}, ++ {} + }; + + static const struct hisi_sas_hw_error fifo_error[] = { +@@ -2097,7 +2097,7 @@ static const struct hisi_sas_hw_error fifo_error[] = { + { .msk = BIT(10), .msg = "GETDQE_FIFO" }, + { .msk = BIT(11), .msg = "CMDP_FIFO" }, + { .msk = BIT(12), .msg = "AWTCTRL_FIFO" }, +- {}, ++ {} + }; + + static const struct hisi_sas_hw_error fatal_axi_error[] = { +@@ -2453,15 +2453,13 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) + + set_aborted_iptt(hisi_hba, slot); + slot_err_v3_hw(hisi_hba, task, slot); +- dev_info(dev, "erroneous completion iptt=%d task=%pK dev id=%d sas_addr=0x%llx " +- "CQ hdr: 0x%x 0x%x 0x%x 0x%x " +- "Error info: 0x%x 0x%x 0x%x 0x%x\n", +- slot->idx, task, sas_dev->device_id, +- itct->sas_addr, +- dw0, dw1, +- complete_hdr->act, dw3, +- error_info[0], error_info[1], +- error_info[2], error_info[3]); ++ dev_info(dev, "erroneous completion iptt=%d task=%pK dev id=%d sas_addr=0x%llx CQ hdr: 0x%x 0x%x 0x%x 0x%x Error info: 0x%x 0x%x 0x%x 0x%x\n", ++ slot->idx, task, sas_dev->device_id, ++ itct->sas_addr, ++ dw0, dw1, ++ complete_hdr->act, dw3, ++ error_info[0], error_info[1], ++ error_info[2], error_info[3]); + + if ((dw0 & CMPLT_HDR_RSPNS_XFRD_MSK) && + (task->task_proto & SAS_PROTOCOL_SATA || +@@ -2793,8 +2791,7 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) + cq_interrupt_v3_hw, irqflags, + DRV_NAME " cq", cq); + if (rc) { +- dev_err(dev, +- "could not request cq%d interrupt, rc=%d\n", ++ dev_err(dev, "could not request cq%d interrupt, rc=%d\n", + i, rc); + rc = -ENOENT; + goto free_cq_irqs; +@@ -2990,7 +2987,7 @@ static int write_gpio_v3_hw(struct hisi_hba *hisi_hba, u8 reg_type, + break; + default: + dev_err(dev, "write gpio: unsupported or bad reg type %d\n", +- reg_type); ++ reg_type); + return -EINVAL; + } + +@@ -3558,7 +3555,7 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) + + hisi_hba->regs = pcim_iomap(pdev, HISI_SAS_BAR_TO_IOMAP, 0); + if (!hisi_hba->regs) { +- dev_err(dev, "cannot map register.\n"); ++ dev_err(dev, "cannot map register\n"); + rc = -ENOMEM; + goto err_out_ha; + } +@@ -3775,7 +3772,7 @@ static int hisi_sas_v3_resume(struct pci_dev *pdev) + u32 device_state = pdev->current_state; + + dev_warn(dev, "resuming from operating state [D%d]\n", +- device_state); ++ device_state); + pci_set_power_state(pdev, PCI_D0); + pci_enable_wake(pdev, PCI_D0, 0); + pci_restore_state(pdev); +-- +2.27.0 + diff --git a/patches/0330-scsi-hisi_sas-Make-max-IPTT-count-equal-for-all-hw-r.patch b/patches/0330-scsi-hisi_sas-Make-max-IPTT-count-equal-for-all-hw-r.patch new file mode 100644 index 00000000..45e0b3e6 --- /dev/null +++ b/patches/0330-scsi-hisi_sas-Make-max-IPTT-count-equal-for-all-hw-r.patch @@ -0,0 +1,222 @@ +From 4aeca56d2b2bc791a16027a235c6ad81d0f82290 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Mon, 5 Aug 2019 21:47:58 +0800 +Subject: [PATCH 012/256] scsi: hisi_sas: Make max IPTT count equal for all hw + revisions + +mainline inclusion +from mainline-v5.4-rc1 +commit 93352abc81a90314bf032038200ce96989a32c62 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=93352abc81a90314bf032038200ce96989a32c62 + +---------------------------------------------------------------------- + +There is a small optimisation to be had by making the max IPTT the same for +all hw revisions, that being we can drop the check for read and write +pointer being the same in the get free slot function. + +Change v1 hw to have max IPTT of 4096 - same as v2 and v3 hw - and +drop hisi_sas_hw.max_command_entries. + +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas.h + drivers/scsi/hisi_sas/hisi_sas_main.c + drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 6 ++++-- + drivers/scsi/hisi_sas/hisi_sas_main.c | 30 +++++++++++--------------- + drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 3 --- + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 1 - + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 7 ++---- + 5 files changed, 19 insertions(+), 28 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 06a8bf9f0f73..94aeb3bb6329 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -37,7 +37,10 @@ + #define HISI_SAS_MAX_DEVICES HISI_SAS_MAX_ITCT_ENTRIES + #define HISI_SAS_RESET_BIT 0 + #define HISI_SAS_REJECT_CMD_BIT 1 +-#define HISI_SAS_RESERVED_IPTT_CNT 96 ++#define HISI_SAS_MAX_COMMANDS (HISI_SAS_QUEUE_SLOTS) ++#define HISI_SAS_RESERVED_IPTT 96 ++#define HISI_SAS_UNRESERVED_IPTT \ ++ (HISI_SAS_MAX_COMMANDS - HISI_SAS_RESERVED_IPTT) + + #define HISI_SAS_STATUS_BUF_SZ (sizeof(struct hisi_sas_status_buffer)) + #define HISI_SAS_COMMAND_TABLE_SZ (sizeof(union hisi_sas_command_table)) +@@ -337,7 +340,6 @@ struct hisi_sas_hw { + const struct cpumask *(*get_managed_irq_aff)(struct hisi_hba + *hisi_hba, int queue); + void (*debugfs_work_handler)(struct work_struct *work); +- int max_command_entries; + int complete_hdr_size; + struct scsi_host_template *sht; + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index b280cc109efb..7784b6c1b1d8 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -174,8 +174,8 @@ static void hisi_sas_slot_index_free(struct hisi_hba *hisi_hba, int slot_idx) + { + unsigned long flags; + +- if (hisi_hba->hw->slot_index_alloc || (slot_idx >= +- hisi_hba->hw->max_command_entries - HISI_SAS_RESERVED_IPTT_CNT)) { ++ if (hisi_hba->hw->slot_index_alloc || ++ slot_idx >= HISI_SAS_UNRESERVED_IPTT) { + spin_lock_irqsave(&hisi_hba->lock, flags); + hisi_sas_slot_index_clear(hisi_hba, slot_idx); + spin_unlock_irqrestore(&hisi_hba->lock, flags); +@@ -206,8 +206,7 @@ static int hisi_sas_slot_index_alloc(struct hisi_hba *hisi_hba, + if (index >= hisi_hba->slot_index_count) { + index = find_next_zero_bit(bitmap, + hisi_hba->slot_index_count, +- hisi_hba->hw->max_command_entries - +- HISI_SAS_RESERVED_IPTT_CNT); ++ HISI_SAS_UNRESERVED_IPTT); + if (index >= hisi_hba->slot_index_count) { + spin_unlock_irqrestore(&hisi_hba->lock, flags); + return -SAS_QUEUE_FULL; +@@ -2356,7 +2355,7 @@ static struct sas_domain_function_template hisi_sas_transport_ops = { + + void hisi_sas_init_mem(struct hisi_hba *hisi_hba) + { +- int i, s, max_command_entries = hisi_hba->hw->max_command_entries; ++ int i, s, max_command_entries = HISI_SAS_MAX_COMMANDS; + + for (i = 0; i < hisi_hba->queue_count; i++) { + struct hisi_sas_cq *cq = &hisi_hba->cq[i]; +@@ -2388,7 +2387,7 @@ EXPORT_SYMBOL_GPL(hisi_sas_init_mem); + int hisi_sas_alloc(struct hisi_hba *hisi_hba) + { + struct device *dev = hisi_hba->dev; +- int i, j, s, max_command_entries = hisi_hba->hw->max_command_entries; ++ int i, j, s, max_command_entries = HISI_SAS_MAX_COMMANDS; + int max_command_entries_ru, sz_slot_buf_ru; + int blk_cnt, slots_per_blk; + +@@ -2523,8 +2522,7 @@ int hisi_sas_alloc(struct hisi_hba *hisi_hba) + goto err_out; + + hisi_sas_slot_index_init(hisi_hba); +- hisi_hba->last_slot_index = hisi_hba->hw->max_command_entries - +- HISI_SAS_RESERVED_IPTT_CNT; ++ hisi_hba->last_slot_index = HISI_SAS_UNRESERVED_IPTT; + + hisi_hba->wq = create_singlethread_workqueue(dev_name(dev)); + if (!hisi_hba->wq) { +@@ -2738,13 +2736,11 @@ int hisi_sas_probe(struct platform_device *pdev, + /* shost support 16 bytes cmd len base on hw */ + shost->max_cmd_len = 16; + if (hisi_hba->hw->slot_index_alloc) { +- shost->can_queue = hisi_hba->hw->max_command_entries; +- shost->cmd_per_lun = hisi_hba->hw->max_command_entries; ++ shost->can_queue = HISI_SAS_MAX_COMMANDS; ++ shost->cmd_per_lun = HISI_SAS_MAX_COMMANDS; + } else { +- shost->can_queue = hisi_hba->hw->max_command_entries - +- HISI_SAS_RESERVED_IPTT_CNT; +- shost->cmd_per_lun = hisi_hba->hw->max_command_entries - +- HISI_SAS_RESERVED_IPTT_CNT; ++ shost->can_queue = HISI_SAS_UNRESERVED_IPTT; ++ shost->cmd_per_lun = HISI_SAS_UNRESERVED_IPTT; + } + + sha->sas_ha_name = DRV_NAME; +@@ -2853,7 +2849,7 @@ static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba) + + static void hisi_sas_debugfs_snapshot_iost_reg(struct hisi_hba *hisi_hba) + { +- int max_command_entries = hisi_hba->hw->max_command_entries; ++ int max_command_entries = HISI_SAS_MAX_COMMANDS; + void *databuf = hisi_hba->debugfs_iost; + struct hisi_sas_iost *iost; + int i; +@@ -3452,7 +3448,7 @@ static int hisi_sas_debugfs_iost_show(struct seq_file *s, void *p) + { + struct hisi_hba *hisi_hba = s->private; + struct hisi_sas_iost *debugfs_iost = hisi_hba->debugfs_iost; +- int i, ret, max_command_entries = hisi_hba->hw->max_command_entries; ++ int i, ret, max_command_entries = HISI_SAS_MAX_COMMANDS; + __le64 *iost = &debugfs_iost->qw0; + + for (i = 0; i < max_command_entries; i++, debugfs_iost++) { +@@ -3633,7 +3629,7 @@ EXPORT_SYMBOL_GPL(hisi_sas_debugfs_work_handler); + + void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) + { +- int max_command_entries = hisi_hba->hw->max_command_entries; ++ int max_command_entries = HISI_SAS_MAX_COMMANDS; + struct device *dev = hisi_hba->dev; + int p, i, c, d; + size_t sz; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +index 1c51cbd94925..1e03e673ceb5 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +@@ -406,8 +406,6 @@ enum { + TRANS_RX_SMP_RESP_TIMEOUT_ERR, /* 0x31a */ + }; + +-#define HISI_SAS_COMMAND_ENTRIES_V1_HW 4096 +- + #define HISI_SAS_PHY_MAX_INT_NR (HISI_SAS_PHY_INT_NR * HISI_SAS_MAX_PHYS) + #define HISI_SAS_CQ_MAX_INT_NR (HISI_SAS_MAX_QUEUES) + #define HISI_SAS_FATAL_INT_NR (2) +@@ -1806,7 +1804,6 @@ static const struct hisi_sas_hw hisi_sas_v1_hw = { + .phy_set_linkrate = phy_set_linkrate_v1_hw, + .phy_get_max_linkrate = phy_get_max_linkrate_v1_hw, + .get_wideport_bitmap = get_wideport_bitmap_v1_hw, +- .max_command_entries = HISI_SAS_COMMAND_ENTRIES_V1_HW, + .complete_hdr_size = sizeof(struct hisi_sas_complete_v1_hdr), + .sht = &sht_v1_hw, + }; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +index 72fb4fa69668..ff197bc06453 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -3617,7 +3617,6 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = { + .get_events = phy_get_events_v2_hw, + .phy_set_linkrate = phy_set_linkrate_v2_hw, + .phy_get_max_linkrate = phy_get_max_linkrate_v2_hw, +- .max_command_entries = HISI_SAS_COMMAND_ENTRIES_V2_HW, + .complete_hdr_size = sizeof(struct hisi_sas_complete_v2_hdr), + .soft_reset = soft_reset_v2_hw, + .get_phys_state = get_phys_state_v2_hw, +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 1285d61b29b4..12fc3b370265 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -3434,7 +3434,6 @@ static struct scsi_host_template sht_v3_hw = { + static const struct hisi_sas_hw hisi_sas_v3_hw = { + .hw_init = hisi_sas_v3_init, + .setup_itct = setup_itct_v3_hw, +- .max_command_entries = HISI_SAS_COMMAND_ENTRIES_V3_HW, + .get_wideport_bitmap = get_wideport_bitmap_v3_hw, + .complete_hdr_size = sizeof(struct hisi_sas_complete_v3_hdr), + .clear_itct = clear_itct_v3_hw, +@@ -3581,10 +3580,8 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) + shost->max_channel = 1; + /* shost support 16 bytes cmd len base on hw */ + shost->max_cmd_len = 16; +- shost->can_queue = hisi_hba->hw->max_command_entries - +- HISI_SAS_RESERVED_IPTT_CNT; +- shost->cmd_per_lun = hisi_hba->hw->max_command_entries - +- HISI_SAS_RESERVED_IPTT_CNT; ++ shost->can_queue = HISI_SAS_UNRESERVED_IPTT; ++ shost->cmd_per_lun = HISI_SAS_UNRESERVED_IPTT; + + sha->sas_ha_name = DRV_NAME; + sha->dev = dev; +-- +2.27.0 + diff --git a/patches/0331-scsi-hisi_sas-Fix-pointer-usage-error-in-show-debugf.patch b/patches/0331-scsi-hisi_sas-Fix-pointer-usage-error-in-show-debugf.patch new file mode 100644 index 00000000..8002a689 --- /dev/null +++ b/patches/0331-scsi-hisi_sas-Fix-pointer-usage-error-in-show-debugf.patch @@ -0,0 +1,58 @@ +From 68a57e0ec6f82350990e90695f1f2ae8e8b25d87 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Mon, 5 Aug 2019 21:48:00 +0800 +Subject: [PATCH 013/256] scsi: hisi_sas: Fix pointer usage error in show + debugfs IOST/ITCT + +mainline inclusion +from mainline-v5.4-rc1 +commit bee0cf25c030776a8ecfc3c951d3b73259dc6839 +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bee0cf25c030776a8ecfc3c951d3b73259dc6839 + +---------------------------------------------------------------------- + +Fix how the pointer is set in hisi_sas_debugfs_iost_show() and +hisi_sas_debugfs_itct_show(). + +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 7784b6c1b1d8..8733e34b624d 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -3449,9 +3449,10 @@ static int hisi_sas_debugfs_iost_show(struct seq_file *s, void *p) + struct hisi_hba *hisi_hba = s->private; + struct hisi_sas_iost *debugfs_iost = hisi_hba->debugfs_iost; + int i, ret, max_command_entries = HISI_SAS_MAX_COMMANDS; +- __le64 *iost = &debugfs_iost->qw0; + + for (i = 0; i < max_command_entries; i++, debugfs_iost++) { ++ __le64 *iost = &debugfs_iost->qw0; ++ + ret = hisi_sas_show_row_64(s, i, sizeof(*debugfs_iost), + iost); + if (ret) +@@ -3481,8 +3482,10 @@ static int hisi_sas_debugfs_itct_show(struct seq_file *s, void *p) + struct hisi_sas_itct *debugfs_itct = hisi_hba->debugfs_itct; + + for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, debugfs_itct++) { ++ __le64 *itct = &debugfs_itct->qw0; ++ + ret = hisi_sas_show_row_64(s, i, sizeof(*debugfs_itct), +- (u64 *)debugfs_itct); ++ itct); + if (ret) + return ret; + } +-- +2.27.0 + diff --git a/patches/0332-scsi-hisi_sas-Snapshot-HW-cache-of-IOST-and-ITCT-at-.patch b/patches/0332-scsi-hisi_sas-Snapshot-HW-cache-of-IOST-and-ITCT-at-.patch new file mode 100644 index 00000000..e596d51e --- /dev/null +++ b/patches/0332-scsi-hisi_sas-Snapshot-HW-cache-of-IOST-and-ITCT-at-.patch @@ -0,0 +1,335 @@ +From 36522359017fbcf53aeb25727ac69f3f7d5deb00 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Mon, 5 Aug 2019 21:48:01 +0800 +Subject: [PATCH 014/256] scsi: hisi_sas: Snapshot HW cache of IOST and ITCT at + debugfs + +mainline inclusion +from mainline-v5.4-rc1 +commit bbe0a7b348b336625292092c74fc7817aeb8d30b +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F808 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bbe0a7b348b336625292092c74fc7817aeb8d30b + +---------------------------------------------------------------------- + +The value of IOST/ITCT is updated to cache first, and then synchronize to +DDR periodically. So the value in IOST/ITCT cache is the latest data and +it's important for debugging. + +So, the HW cache of IOST and ITCT should be snapshot at debugfs. + +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas.h + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 16 ++++ + drivers/scsi/hisi_sas/hisi_sas_main.c | 114 ++++++++++++++++++++++++- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 32 +++++++ + 3 files changed, 160 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 94aeb3bb6329..bc2b6995dca1 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -42,6 +42,9 @@ + #define HISI_SAS_UNRESERVED_IPTT \ + (HISI_SAS_MAX_COMMANDS - HISI_SAS_RESERVED_IPTT) + ++#define HISI_SAS_IOST_ITCT_CACHE_NUM 64 ++#define HISI_SAS_IOST_ITCT_CACHE_DW_SZ 10 ++ + #define HISI_SAS_STATUS_BUF_SZ (sizeof(struct hisi_sas_status_buffer)) + #define HISI_SAS_COMMAND_TABLE_SZ (sizeof(union hisi_sas_command_table)) + +@@ -293,6 +296,14 @@ enum { + HISI_SAS_BIST_CODE_MODE_FIXED_DATA, + }; + ++struct hisi_sas_iost_itct_cache { ++ u32 data[HISI_SAS_IOST_ITCT_CACHE_DW_SZ]; ++}; ++ ++enum hisi_sas_debugfs_cache_type { ++ HISI_SAS_ITCT_CACHE, ++ HISI_SAS_IOST_CACHE, ++}; + + struct hisi_sas_hw { + int (*hw_init)(struct hisi_hba *hisi_hba); +@@ -340,6 +351,9 @@ struct hisi_sas_hw { + const struct cpumask *(*get_managed_irq_aff)(struct hisi_hba + *hisi_hba, int queue); + void (*debugfs_work_handler)(struct work_struct *work); ++ void (*read_iost_itct_cache)(struct hisi_hba *hisi_hba, ++ enum hisi_sas_debugfs_cache_type type, ++ u32 *cache); + int complete_hdr_size; + struct scsi_host_template *sht; + +@@ -432,6 +446,8 @@ struct hisi_hba { + struct hisi_sas_cmd_hdr *debugfs_cmd_hdr[HISI_SAS_MAX_QUEUES]; + struct hisi_sas_iost *debugfs_iost; + struct hisi_sas_itct *debugfs_itct; ++ u64 *debugfs_iost_cache; ++ u64 *debugfs_itct_cache; + + struct dentry *debugfs_dir; + struct dentry *debugfs_dump_dentry; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 8733e34b624d..2d2373b11b20 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -2835,10 +2835,14 @@ static void hisi_sas_debugfs_snapshot_global_reg(struct hisi_hba *hisi_hba) + + static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba) + { ++ void *cachebuf = hisi_hba->debugfs_itct_cache; + void *databuf = hisi_hba->debugfs_itct; + struct hisi_sas_itct *itct; + int i; + ++ hisi_hba->hw->read_iost_itct_cache(hisi_hba, HISI_SAS_ITCT_CACHE, ++ cachebuf); ++ + itct = hisi_hba->itct; + + for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) { +@@ -2850,10 +2854,14 @@ static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba) + static void hisi_sas_debugfs_snapshot_iost_reg(struct hisi_hba *hisi_hba) + { + int max_command_entries = HISI_SAS_MAX_COMMANDS; ++ void *cachebuf = hisi_hba->debugfs_iost_cache; + void *databuf = hisi_hba->debugfs_iost; + struct hisi_sas_iost *iost; + int i; + ++ hisi_hba->hw->read_iost_itct_cache(hisi_hba, HISI_SAS_IOST_CACHE, ++ cachebuf); ++ + iost = hisi_hba->iost; + + for (i = 0; i < max_command_entries; i++, iost++) { +@@ -3475,6 +3483,46 @@ static const struct file_operations hisi_sas_debugfs_iost_fops = { + .owner = THIS_MODULE, + }; + ++static int hisi_sas_debugfs_iost_cache_show(struct seq_file *s, void *p) ++{ ++ struct hisi_hba *hisi_hba = s->private; ++ struct hisi_sas_iost_itct_cache *iost_cache = ++ (struct hisi_sas_iost_itct_cache *)hisi_hba->debugfs_iost_cache; ++ u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4; ++ int i, tab_idx; ++ __le64 *iost; ++ ++ for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, iost_cache++) { ++ /* ++ * Data struct of IOST cache: ++ * Data[1]: BIT0~15: Table index ++ * Bit16: Valid mask ++ * Data[2]~[9]: IOST table ++ */ ++ tab_idx = (iost_cache->data[1] & 0xffff); ++ iost = (__le64 *)iost_cache; ++ ++ hisi_sas_show_row_64(s, tab_idx, cache_size, iost); ++ } ++ ++ return 0; ++} ++ ++static int hisi_sas_debugfs_iost_cache_open(struct inode *inode, ++ struct file *filp) ++{ ++ return single_open(filp, hisi_sas_debugfs_iost_cache_show, ++ inode->i_private); ++} ++ ++static const struct file_operations hisi_sas_debugfs_iost_cache_fops = { ++ .open = hisi_sas_debugfs_iost_cache_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .owner = THIS_MODULE, ++}; ++ + static int hisi_sas_debugfs_itct_show(struct seq_file *s, void *p) + { + int i, ret; +@@ -3506,6 +3554,46 @@ static const struct file_operations hisi_sas_debugfs_itct_fops = { + .owner = THIS_MODULE, + }; + ++static int hisi_sas_debugfs_itct_cache_show(struct seq_file *s, void *p) ++{ ++ struct hisi_hba *hisi_hba = s->private; ++ struct hisi_sas_iost_itct_cache *itct_cache = ++ (struct hisi_sas_iost_itct_cache *)hisi_hba->debugfs_itct_cache; ++ u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4; ++ int i, tab_idx; ++ __le64 *itct; ++ ++ for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, itct_cache++) { ++ /* ++ * Data struct of ITCT cache: ++ * Data[1]: BIT0~15: Table index ++ * Bit16: Valid mask ++ * Data[2]~[9]: ITCT table ++ */ ++ tab_idx = itct_cache->data[1] & 0xffff; ++ itct = (__le64 *)itct_cache; ++ ++ hisi_sas_show_row_64(s, tab_idx, cache_size, itct); ++ } ++ ++ return 0; ++} ++ ++static int hisi_sas_debugfs_itct_cache_open(struct inode *inode, ++ struct file *filp) ++{ ++ return single_open(filp, hisi_sas_debugfs_itct_cache_show, ++ inode->i_private); ++} ++ ++static const struct file_operations hisi_sas_debugfs_itct_cache_fops = { ++ .open = hisi_sas_debugfs_itct_cache_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .owner = THIS_MODULE, ++}; ++ + static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + { + struct dentry *dump_dentry; +@@ -3558,9 +3646,15 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + debugfs_create_file("iost", 0400, dump_dentry, hisi_hba, + &hisi_sas_debugfs_iost_fops); + ++ debugfs_create_file("iost_cache", 0400, dump_dentry, hisi_hba, ++ &hisi_sas_debugfs_iost_cache_fops); ++ + debugfs_create_file("itct", 0400, dump_dentry, hisi_hba, + &hisi_sas_debugfs_itct_fops); + ++ debugfs_create_file("itct_cache", 0400, dump_dentry, hisi_hba, ++ &hisi_sas_debugfs_itct_cache_fops); ++ + return; + } + +@@ -3715,14 +3809,26 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) + goto fail_iost_dq; + } + +- /* Alloc buffer for iost */ + sz = max_command_entries * sizeof(struct hisi_sas_iost); + + hisi_hba->debugfs_iost = devm_kmalloc(dev, sz, GFP_KERNEL); + if (!hisi_hba->debugfs_iost) + goto fail_iost_dq; + +- /* Alloc buffer for itct */ ++ sz = HISI_SAS_IOST_ITCT_CACHE_NUM * ++ sizeof(struct hisi_sas_iost_itct_cache); ++ ++ hisi_hba->debugfs_iost_cache = devm_kmalloc(dev, sz, GFP_KERNEL); ++ if (!hisi_hba->debugfs_iost_cache) ++ goto fail_iost_cache; ++ ++ sz = HISI_SAS_IOST_ITCT_CACHE_NUM * ++ sizeof(struct hisi_sas_iost_itct_cache); ++ ++ hisi_hba->debugfs_itct_cache = devm_kmalloc(dev, sz, GFP_KERNEL); ++ if (!hisi_hba->debugfs_itct_cache) ++ goto fail_itct_cache; ++ + /* New memory allocation must be locate before itct */ + sz = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct); + +@@ -3732,6 +3838,10 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) + + return; + fail_itct: ++ devm_kfree(dev, hisi_hba->debugfs_iost_cache); ++fail_itct_cache: ++ devm_kfree(dev, hisi_hba->debugfs_iost_cache); ++fail_iost_cache: + devm_kfree(dev, hisi_hba->debugfs_iost); + fail_iost_dq: + for (i = 0; i < d; i++) +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 12fc3b370265..974a72d164c5 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -79,6 +79,7 @@ + #define HGC_DQE_ECC_MB_ADDR_OFF 16 + #define HGC_DQE_ECC_MB_ADDR_MSK (0xfff << HGC_DQE_ECC_MB_ADDR_OFF) + #define CHNL_INT_STATUS 0x148 ++#define TAB_DFX 0x14c + #define HGC_ITCT_ECC_ADDR 0x150 + #define HGC_ITCT_ECC_1B_ADDR_OFF 0 + #define HGC_ITCT_ECC_1B_ADDR_MSK (0x3ff << \ +@@ -91,6 +92,7 @@ + #define AXI_ERR_INFO_MSK (0xff << AXI_ERR_INFO_OFF) + #define FIFO_ERR_INFO_OFF 8 + #define FIFO_ERR_INFO_MSK (0xff << FIFO_ERR_INFO_OFF) ++#define TAB_RD_TYPE 0x15c + #define INT_COAL_EN 0x19c + #define OQ_INT_COAL_TIME 0x1a0 + #define OQ_INT_COAL_CNT 0x1a4 +@@ -3406,6 +3408,35 @@ struct device_attribute *host_attrs_v3_hw[] = { + NULL + }; + ++static void read_iost_itct_cache_v3_hw(struct hisi_hba *hisi_hba, ++ enum hisi_sas_debugfs_cache_type type, ++ u32 *cache) ++{ ++ u32 cache_dw_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * ++ HISI_SAS_IOST_ITCT_CACHE_NUM; ++ u32 *buf = cache; ++ u32 i, val; ++ ++ hisi_sas_write32(hisi_hba, TAB_RD_TYPE, type); ++ ++ for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_DW_SZ; i++) { ++ val = hisi_sas_read32(hisi_hba, TAB_DFX); ++ if (val == 0xffffffff) ++ break; ++ } ++ ++ if (val != 0xffffffff) { ++ pr_err("Issue occur when reading IOST/ITCT cache!\n"); ++ return; ++ } ++ ++ memset(buf, 0, cache_dw_size * 4); ++ buf[0] = val; ++ ++ for (i = 1; i < cache_dw_size; i++) ++ buf[i] = hisi_sas_read32(hisi_hba, TAB_DFX); ++} ++ + static struct scsi_host_template sht_v3_hw = { + .name = DRV_NAME, + .module = THIS_MODULE, +@@ -3463,6 +3494,7 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = { + .set_bist = debugfs_set_bist_v3_hw, + .get_managed_irq_aff = get_managed_irq_aff_v3_hw, + .debugfs_work_handler = hisi_sas_debugfs_work_handler, ++ .read_iost_itct_cache = read_iost_itct_cache_v3_hw, + }; + + static struct Scsi_Host * +-- +2.27.0 + diff --git a/patches/0333-scsi-hisi_sas-Snapshot-AXI-and-RAS-register-at-debug.patch b/patches/0333-scsi-hisi_sas-Snapshot-AXI-and-RAS-register-at-debug.patch new file mode 100644 index 00000000..949b688f --- /dev/null +++ b/patches/0333-scsi-hisi_sas-Snapshot-AXI-and-RAS-register-at-debug.patch @@ -0,0 +1,345 @@ +From fcac5118c386027934eec67877c46e928de4f807 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Mon, 5 Aug 2019 21:48:02 +0800 +Subject: [PATCH 015/256] scsi: hisi_sas: Snapshot AXI and RAS register at + debugfs + +mainline inclusion +from mainline-v5.4-rc1 +commit b0b3e4290e288bb633c4ff6331b2c0b9530aa9b8 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F808 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b0b3e4290e288bb633c4ff6331b2c0b9530aa9b8 + +---------------------------------------------------------------------- + +The AXI and RAS register values should also should be snapshot at debugfs. + +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 12 ++- + drivers/scsi/hisi_sas/hisi_sas_main.c | 132 ++++++++++++++++++++++--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 36 ++++++- + 3 files changed, 162 insertions(+), 18 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index bc2b6995dca1..de5752f07987 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -300,6 +300,13 @@ struct hisi_sas_iost_itct_cache { + u32 data[HISI_SAS_IOST_ITCT_CACHE_DW_SZ]; + }; + ++enum hisi_sas_debugfs_reg_array_member { ++ DEBUGFS_GLOBAL = 0, ++ DEBUGFS_AXI, ++ DEBUGFS_RAS, ++ DEBUGFS_REGS_NUM ++}; ++ + enum hisi_sas_debugfs_cache_type { + HISI_SAS_ITCT_CACHE, + HISI_SAS_IOST_CACHE, +@@ -357,7 +364,7 @@ struct hisi_sas_hw { + int complete_hdr_size; + struct scsi_host_template *sht; + +- const struct hisi_sas_debugfs_reg *debugfs_reg_global; ++ const struct hisi_sas_debugfs_reg *debugfs_reg_array[DEBUGFS_REGS_NUM]; + const struct hisi_sas_debugfs_reg *debugfs_reg_port; + int (*set_bist)(struct hisi_hba *hisi_hba, bool enable); + }; +@@ -440,7 +447,8 @@ struct hisi_hba { + unsigned int *reply_map; + + /* debugfs memories */ +- u32 *debugfs_global_reg; ++ /* Put Global AXI and RAS Register into register array */ ++ u32 *debugfs_regs[DEBUGFS_REGS_NUM]; + u32 *debugfs_port_reg[HISI_SAS_MAX_PHYS]; + void *debugfs_complete_hdr[HISI_SAS_MAX_QUEUES]; + struct hisi_sas_cmd_hdr *debugfs_cmd_hdr[HISI_SAS_MAX_QUEUES]; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 2d2373b11b20..11c27ae7c0a2 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -2824,15 +2824,42 @@ static void hisi_sas_debugfs_snapshot_port_reg(struct hisi_hba *hisi_hba) + + static void hisi_sas_debugfs_snapshot_global_reg(struct hisi_hba *hisi_hba) + { +- u32 *databuf = (u32 *)hisi_hba->debugfs_global_reg; ++ u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_GLOBAL]; ++ const struct hisi_sas_hw *hw = hisi_hba->hw; + const struct hisi_sas_debugfs_reg *global = +- hisi_hba->hw->debugfs_reg_global; ++ hw->debugfs_reg_array[DEBUGFS_GLOBAL]; + int i; + + for (i = 0; i < global->count; i++, databuf++) + *databuf = global->read_global_reg(hisi_hba, 4 * i); + } + ++static void hisi_sas_debugfs_snapshot_axi_reg(struct hisi_hba *hisi_hba) ++{ ++ u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_AXI]; ++ const struct hisi_sas_hw *hw = hisi_hba->hw; ++ const struct hisi_sas_debugfs_reg *axi = ++ hw->debugfs_reg_array[DEBUGFS_AXI]; ++ int i; ++ ++ for (i = 0; i < axi->count; i++, databuf++) ++ *databuf = axi->read_global_reg(hisi_hba, ++ 4 * i + axi->base_off); ++} ++ ++static void hisi_sas_debugfs_snapshot_ras_reg(struct hisi_hba *hisi_hba) ++{ ++ u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_RAS]; ++ const struct hisi_sas_hw *hw = hisi_hba->hw; ++ const struct hisi_sas_debugfs_reg *ras = ++ hw->debugfs_reg_array[DEBUGFS_RAS]; ++ int i; ++ ++ for (i = 0; i < ras->count; i++, databuf++) ++ *databuf = ras->read_global_reg(hisi_hba, ++ 4 * i + ras->base_off); ++} ++ + static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba) + { + void *cachebuf = hisi_hba->debugfs_itct_cache; +@@ -2908,9 +2935,9 @@ static int hisi_sas_debugfs_global_show(struct seq_file *s, void *p) + { + struct hisi_hba *hisi_hba = s->private; + const struct hisi_sas_hw *hw = hisi_hba->hw; +- const struct hisi_sas_debugfs_reg *reg_global = hw->debugfs_reg_global; ++ const void *reg_global = hw->debugfs_reg_array[DEBUGFS_GLOBAL]; + +- hisi_sas_debugfs_print_reg(hisi_hba->debugfs_global_reg, ++ hisi_sas_debugfs_print_reg(hisi_hba->debugfs_regs[DEBUGFS_GLOBAL], + reg_global, s); + + return 0; +@@ -3312,6 +3339,58 @@ static const struct file_operations hisi_sas_debugfs_bist_enable_ops = { + .owner = THIS_MODULE, + }; + ++static int hisi_sas_debugfs_axi_show(struct seq_file *s, void *p) ++{ ++ struct hisi_hba *hisi_hba = s->private; ++ const struct hisi_sas_hw *hw = hisi_hba->hw; ++ const void *reg_axi = hw->debugfs_reg_array[DEBUGFS_AXI]; ++ ++ hisi_sas_debugfs_print_reg(hisi_hba->debugfs_regs[DEBUGFS_AXI], ++ reg_axi, s); ++ ++ return 0; ++} ++ ++static int hisi_sas_debugfs_axi_open(struct inode *inode, struct file *filp) ++{ ++ return single_open(filp, hisi_sas_debugfs_axi_show, ++ inode->i_private); ++} ++ ++static const struct file_operations hisi_sas_debugfs_axi_fops = { ++ .open = hisi_sas_debugfs_axi_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .owner = THIS_MODULE, ++}; ++ ++static int hisi_sas_debugfs_ras_show(struct seq_file *s, void *p) ++{ ++ struct hisi_hba *hisi_hba = s->private; ++ const struct hisi_sas_hw *hw = hisi_hba->hw; ++ const void *reg_ras = hw->debugfs_reg_array[DEBUGFS_RAS]; ++ ++ hisi_sas_debugfs_print_reg(hisi_hba->debugfs_regs[DEBUGFS_RAS], ++ reg_ras, s); ++ ++ return 0; ++} ++ ++static int hisi_sas_debugfs_ras_open(struct inode *inode, struct file *filp) ++{ ++ return single_open(filp, hisi_sas_debugfs_ras_show, ++ inode->i_private); ++} ++ ++static const struct file_operations hisi_sas_debugfs_ras_fops = { ++ .open = hisi_sas_debugfs_ras_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .owner = THIS_MODULE, ++}; ++ + + static int hisi_sas_debugfs_port_show(struct seq_file *s, void *p) + { +@@ -3655,6 +3734,12 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + debugfs_create_file("itct_cache", 0400, dump_dentry, hisi_hba, + &hisi_sas_debugfs_itct_cache_fops); + ++ debugfs_create_file("axi", 0400, dump_dentry, hisi_hba, ++ &hisi_sas_debugfs_axi_fops); ++ ++ debugfs_create_file("ras", 0400, dump_dentry, hisi_hba, ++ &hisi_sas_debugfs_ras_fops); ++ + return; + } + +@@ -3664,6 +3749,8 @@ static void hisi_sas_debugfs_snapshot_regs(struct hisi_hba *hisi_hba) + + hisi_sas_debugfs_snapshot_global_reg(hisi_hba); + hisi_sas_debugfs_snapshot_port_reg(hisi_hba); ++ hisi_sas_debugfs_snapshot_axi_reg(hisi_hba); ++ hisi_sas_debugfs_snapshot_ras_reg(hisi_hba); + hisi_sas_debugfs_snapshot_cq_reg(hisi_hba); + hisi_sas_debugfs_snapshot_dq_reg(hisi_hba); + hisi_sas_debugfs_snapshot_itct_reg(hisi_hba); +@@ -3727,6 +3814,7 @@ EXPORT_SYMBOL_GPL(hisi_sas_debugfs_work_handler); + void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) + { + int max_command_entries = HISI_SAS_MAX_COMMANDS; ++ const struct hisi_sas_hw *hw = hisi_hba->hw; + struct device *dev = hisi_hba->dev; + int p, i, c, d; + size_t sz; +@@ -3771,16 +3859,14 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) + hisi_hba, &hisi_sas_debugfs_bist_enable_ops)) + goto fail_global; + +- /* Alloc buffer for global */ +- sz = hisi_hba->hw->debugfs_reg_global->count * 4; +- hisi_hba->debugfs_global_reg = +- devm_kmalloc(dev, sz, GFP_KERNEL); ++ sz = hw->debugfs_reg_array[DEBUGFS_GLOBAL]->count * 4; ++ hisi_hba->debugfs_regs[DEBUGFS_GLOBAL] = ++ devm_kmalloc(dev, sz, GFP_KERNEL); + +- if (!hisi_hba->debugfs_global_reg) ++ if (!hisi_hba->debugfs_regs[DEBUGFS_GLOBAL]) + goto fail_global; + +- /* Alloc buffer for port */ +- sz = hisi_hba->hw->debugfs_reg_port->count * 4; ++ sz = hw->debugfs_reg_port->count * 4; + for (p = 0; p < hisi_hba->n_phy; p++) { + hisi_hba->debugfs_port_reg[p] = + devm_kmalloc(dev, sz, GFP_KERNEL); +@@ -3789,8 +3875,21 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) + goto fail_port; + } + +- /* Alloc buffer for cq */ +- sz = hisi_hba->hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS; ++ sz = hw->debugfs_reg_array[DEBUGFS_AXI]->count * 4; ++ hisi_hba->debugfs_regs[DEBUGFS_AXI] = ++ devm_kmalloc(dev, sz, GFP_KERNEL); ++ ++ if (!hisi_hba->debugfs_regs[DEBUGFS_AXI]) ++ goto fail_axi; ++ ++ sz = hw->debugfs_reg_array[DEBUGFS_RAS]->count * 4; ++ hisi_hba->debugfs_regs[DEBUGFS_RAS] = ++ devm_kmalloc(dev, sz, GFP_KERNEL); ++ ++ if (!hisi_hba->debugfs_regs[DEBUGFS_RAS]) ++ goto fail_ras; ++ ++ sz = hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS; + for (c = 0; c < hisi_hba->queue_count; c++) { + hisi_hba->debugfs_complete_hdr[c] = + devm_kmalloc(dev, sz, GFP_KERNEL); +@@ -3799,7 +3898,6 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) + goto fail_cq; + } + +- /* Alloc buffer for dq */ + sz = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS; + for (d = 0; d < hisi_hba->queue_count; d++) { + hisi_hba->debugfs_cmd_hdr[d] = +@@ -3849,10 +3947,14 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) + fail_cq: + for (i = 0; i < c; i++) + devm_kfree(dev, hisi_hba->debugfs_complete_hdr[i]); ++ devm_kfree(dev, hisi_hba->debugfs_regs[DEBUGFS_RAS]); ++fail_ras: ++ devm_kfree(dev, hisi_hba->debugfs_regs[DEBUGFS_AXI]); ++fail_axi: + fail_port: + for (i = 0; i < p; i++) + devm_kfree(dev, hisi_hba->debugfs_port_reg[i]); +- devm_kfree(dev, hisi_hba->debugfs_global_reg); ++ devm_kfree(dev, hisi_hba->debugfs_regs[DEBUGFS_GLOBAL]); + fail_global: + hisi_sas_debugfs_exit(hisi_hba); + dev_info(dev, "failed to init debugfs!\n"); +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 974a72d164c5..9500a02ae9c2 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -3264,6 +3264,38 @@ static const struct hisi_sas_debugfs_reg debugfs_global_reg = { + .read_global_reg = hisi_sas_read32, + }; + ++static const struct hisi_sas_debugfs_reg_lu debugfs_axi_reg_lu[] = { ++ HISI_SAS_DEBUGFS_REG(AM_CFG_MAX_TRANS), ++ HISI_SAS_DEBUGFS_REG(AM_CFG_SINGLE_PORT_MAX_TRANS), ++ HISI_SAS_DEBUGFS_REG(AXI_CFG), ++ HISI_SAS_DEBUGFS_REG(AM_ROB_ECC_ERR_ADDR), ++ {} ++}; ++ ++static const struct hisi_sas_debugfs_reg debugfs_axi_reg = { ++ .lu = debugfs_axi_reg_lu, ++ .count = 0x61, ++ .base_off = AXI_MASTER_CFG_BASE, ++ .read_global_reg = hisi_sas_read32, ++}; ++ ++static const struct hisi_sas_debugfs_reg_lu debugfs_ras_reg_lu[] = { ++ HISI_SAS_DEBUGFS_REG(SAS_RAS_INTR1), ++ HISI_SAS_DEBUGFS_REG(SAS_RAS_INTR0_MASK), ++ HISI_SAS_DEBUGFS_REG(SAS_RAS_INTR1_MASK), ++ HISI_SAS_DEBUGFS_REG(CFG_SAS_RAS_INTR_MASK), ++ HISI_SAS_DEBUGFS_REG(SAS_RAS_INTR2), ++ HISI_SAS_DEBUGFS_REG(SAS_RAS_INTR2_MASK), ++ {} ++}; ++ ++static const struct hisi_sas_debugfs_reg debugfs_ras_reg = { ++ .lu = debugfs_ras_reg_lu, ++ .count = 0x10, ++ .base_off = RAS_BASE, ++ .read_global_reg = hisi_sas_read32, ++}; ++ + static void debugfs_snapshot_prepare_v3_hw(struct hisi_hba *hisi_hba) + { + struct device *dev = hisi_hba->dev; +@@ -3487,7 +3519,9 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = { + .get_events = phy_get_events_v3_hw, + .write_gpio = write_gpio_v3_hw, + .wait_cmds_complete_timeout = wait_cmds_complete_timeout_v3_hw, +- .debugfs_reg_global = &debugfs_global_reg, ++ .debugfs_reg_array[DEBUGFS_GLOBAL] = &debugfs_global_reg, ++ .debugfs_reg_array[DEBUGFS_AXI] = &debugfs_axi_reg, ++ .debugfs_reg_array[DEBUGFS_RAS] = &debugfs_ras_reg, + .debugfs_reg_port = &debugfs_port_reg, + .snapshot_prepare = debugfs_snapshot_prepare_v3_hw, + .snapshot_restore = debugfs_snapshot_restore_v3_hw, +-- +2.27.0 + diff --git a/patches/0334-scsi-hisi_sas-Drop-kmap_atomic-in-SMP-command-comple.patch b/patches/0334-scsi-hisi_sas-Drop-kmap_atomic-in-SMP-command-comple.patch new file mode 100644 index 00000000..44587955 --- /dev/null +++ b/patches/0334-scsi-hisi_sas-Drop-kmap_atomic-in-SMP-command-comple.patch @@ -0,0 +1,105 @@ +From 9a166aaf81f6d23144d06dad41a81294e0e6bd6b Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Mon, 5 Aug 2019 21:48:06 +0800 +Subject: [PATCH 016/256] scsi: hisi_sas: Drop kmap_atomic() in SMP command + completion + +mainline inclusion +from mainline-v5.4-rc1 +commit 1c003146c64bb3ae86f1a08d73a7e4551d7cd04a +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1c003146c64bb3ae86f1a08d73a7e4551d7cd04a + +---------------------------------------------------------------------- + +The call to kmap_atomic() in the SMP command completion code is +unnecessary, since kmap() is only really concerned with highmem, which is +not relevant on arm64. The controller only finds itself in arm64 systems. + +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 4 +--- + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 4 +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 4 +--- + 3 files changed, 3 insertions(+), 9 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +index 1e03e673ceb5..eebc774ba443 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +@@ -1283,11 +1283,10 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba, + } + case SAS_PROTOCOL_SMP: + { +- void *to; + struct scatterlist *sg_resp = &task->smp_task.smp_resp; ++ void *to = page_address(sg_page(sg_resp)); + + ts->stat = SAM_STAT_GOOD; +- to = kmap_atomic(sg_page(sg_resp)); + + dma_unmap_sg(dev, &task->smp_task.smp_resp, 1, + DMA_FROM_DEVICE); +@@ -1297,7 +1296,6 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba, + hisi_sas_status_buf_addr_mem(slot) + + sizeof(struct hisi_sas_err_record), + sg_dma_len(sg_resp)); +- kunmap_atomic(to); + break; + } + case SAS_PROTOCOL_SATA: +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +index ff197bc06453..a2689ca8421a 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -2441,10 +2441,9 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) + case SAS_PROTOCOL_SMP: + { + struct scatterlist *sg_resp = &task->smp_task.smp_resp; +- void *to; ++ void *to = page_address(sg_page(sg_resp)); + + ts->stat = SAM_STAT_GOOD; +- to = kmap_atomic(sg_page(sg_resp)); + + dma_unmap_sg(dev, &task->smp_task.smp_resp, 1, + DMA_FROM_DEVICE); +@@ -2454,7 +2453,6 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) + hisi_sas_status_buf_addr_mem(slot) + + sizeof(struct hisi_sas_err_record), + sg_dma_len(sg_resp)); +- kunmap_atomic(to); + break; + } + case SAS_PROTOCOL_SATA: +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 9500a02ae9c2..c3b8432c5c34 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -2533,10 +2533,9 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) + } + case SAS_PROTOCOL_SMP: { + struct scatterlist *sg_resp = &task->smp_task.smp_resp; +- void *to; ++ void *to = page_address(sg_page(sg_resp)); + + ts->stat = SAM_STAT_GOOD; +- to = kmap_atomic(sg_page(sg_resp)); + + dma_unmap_sg(dev, &task->smp_task.smp_resp, 1, + DMA_FROM_DEVICE); +@@ -2546,7 +2545,6 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) + hisi_sas_status_buf_addr_mem(slot) + + sizeof(struct hisi_sas_err_record), + sg_dma_len(sg_resp)); +- kunmap_atomic(to); + break; + } + case SAS_PROTOCOL_SATA: +-- +2.27.0 + diff --git a/patches/0335-scsi-hisi_sas-Drop-SMP-resp-frame-DMA-mapping.patch b/patches/0335-scsi-hisi_sas-Drop-SMP-resp-frame-DMA-mapping.patch new file mode 100644 index 00000000..d0c96049 --- /dev/null +++ b/patches/0335-scsi-hisi_sas-Drop-SMP-resp-frame-DMA-mapping.patch @@ -0,0 +1,190 @@ +From bdd4a0cfc443fb35d16930f3287c5f58bbf44486 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Mon, 5 Aug 2019 21:48:07 +0800 +Subject: [PATCH 017/256] scsi: hisi_sas: Drop SMP resp frame DMA mapping + +mainline inclusion +from mainline-v5.4-rc1 +commit 5f6c32d7ce576e9275ab2e9b21192f5cd5f24273 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5f6c32d7ce576e9275ab2e9b21192f5cd5f24273 + +---------------------------------------------------------------------- + +The SMP frame response is written to the command table and not the SMP +response pointer from libsas, so don't bother DMA mapping (and unmapping) +the SMP response from libsas. + +Suggested-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 30 +++++++------------------- + drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 4 +--- + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 4 +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 4 +--- + 4 files changed, 11 insertions(+), 31 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 11c27ae7c0a2..f57b8689fc3d 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -300,8 +300,8 @@ static void hisi_sas_task_prep_abort(struct hisi_hba *hisi_hba, + } + + static void hisi_sas_dma_unmap(struct hisi_hba *hisi_hba, +- struct sas_task *task, int n_elem, +- int n_elem_req, int n_elem_resp) ++ struct sas_task *task, int n_elem, ++ int n_elem_req) + { + struct device *dev = hisi_hba->dev; + +@@ -315,22 +315,19 @@ static void hisi_sas_dma_unmap(struct hisi_hba *hisi_hba, + if (n_elem_req) + dma_unmap_sg(dev, &task->smp_task.smp_req, + 1, DMA_TO_DEVICE); +- if (n_elem_resp) +- dma_unmap_sg(dev, &task->smp_task.smp_resp, +- 1, DMA_FROM_DEVICE); + } + } + } + + static int hisi_sas_dma_map(struct hisi_hba *hisi_hba, + struct sas_task *task, int *n_elem, +- int *n_elem_req, int *n_elem_resp) ++ int *n_elem_req) + { + struct device *dev = hisi_hba->dev; + int rc; + + if (!sas_protocol_ata(task->task_proto)) { +- unsigned int req_len, resp_len; ++ unsigned int req_len; + + if (task->num_scatter) { + *n_elem = dma_map_sg(dev, task->scatter, +@@ -351,17 +348,6 @@ static int hisi_sas_dma_map(struct hisi_hba *hisi_hba, + rc = -EINVAL; + goto err_out_dma_unmap; + } +- *n_elem_resp = dma_map_sg(dev, &task->smp_task.smp_resp, +- 1, DMA_FROM_DEVICE); +- if (!*n_elem_resp) { +- rc = -ENOMEM; +- goto err_out_dma_unmap; +- } +- resp_len = sg_dma_len(&task->smp_task.smp_resp); +- if (resp_len & 0x3) { +- rc = -EINVAL; +- goto err_out_dma_unmap; +- } + } + } else + *n_elem = task->num_scatter; +@@ -376,7 +362,7 @@ static int hisi_sas_dma_map(struct hisi_hba *hisi_hba, + + err_out_dma_unmap: + hisi_sas_dma_unmap(hisi_hba, task, *n_elem, +- *n_elem_req, *n_elem_resp); ++ *n_elem_req); + prep_out: + return rc; + } +@@ -450,7 +436,7 @@ static int hisi_sas_task_prep(struct sas_task *task, + struct asd_sas_port *sas_port = device->port; + struct device *dev = hisi_hba->dev; + int dlvry_queue_slot, dlvry_queue, rc, slot_idx; +- int n_elem = 0, n_elem_dif = 0, n_elem_req = 0, n_elem_resp = 0; ++ int n_elem = 0, n_elem_dif = 0, n_elem_req = 0; + struct hisi_sas_dq *dq; + unsigned long flags; + int wr_q_index; +@@ -487,7 +473,7 @@ static int hisi_sas_task_prep(struct sas_task *task, + } + + rc = hisi_sas_dma_map(hisi_hba, task, &n_elem, +- &n_elem_req, &n_elem_resp); ++ &n_elem_req); + if (rc < 0) + goto prep_out; + +@@ -580,7 +566,7 @@ static int hisi_sas_task_prep(struct sas_task *task, + hisi_sas_dif_dma_unmap(hisi_hba, task, n_elem_dif); + err_out_dma_unmap: + hisi_sas_dma_unmap(hisi_hba, task, n_elem, +- n_elem_req, n_elem_resp); ++ n_elem_req); + prep_out: + dev_err(dev, "task prep: failed[%d]!\n", rc); + return rc; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +index eebc774ba443..fb64684384c6 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +@@ -1288,14 +1288,12 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba, + + ts->stat = SAM_STAT_GOOD; + +- dma_unmap_sg(dev, &task->smp_task.smp_resp, 1, +- DMA_FROM_DEVICE); + dma_unmap_sg(dev, &task->smp_task.smp_req, 1, + DMA_TO_DEVICE); + memcpy(to + sg_resp->offset, + hisi_sas_status_buf_addr_mem(slot) + + sizeof(struct hisi_sas_err_record), +- sg_dma_len(sg_resp)); ++ sg_resp->length); + break; + } + case SAS_PROTOCOL_SATA: +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +index a2689ca8421a..d1453a6c6dda 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -2445,14 +2445,12 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) + + ts->stat = SAM_STAT_GOOD; + +- dma_unmap_sg(dev, &task->smp_task.smp_resp, 1, +- DMA_FROM_DEVICE); + dma_unmap_sg(dev, &task->smp_task.smp_req, 1, + DMA_TO_DEVICE); + memcpy(to + sg_resp->offset, + hisi_sas_status_buf_addr_mem(slot) + + sizeof(struct hisi_sas_err_record), +- sg_dma_len(sg_resp)); ++ sg_resp->length); + break; + } + case SAS_PROTOCOL_SATA: +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index c3b8432c5c34..19be76c54b4c 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -2537,14 +2537,12 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) + + ts->stat = SAM_STAT_GOOD; + +- dma_unmap_sg(dev, &task->smp_task.smp_resp, 1, +- DMA_FROM_DEVICE); + dma_unmap_sg(dev, &task->smp_task.smp_req, 1, + DMA_TO_DEVICE); + memcpy(to + sg_resp->offset, + hisi_sas_status_buf_addr_mem(slot) + + sizeof(struct hisi_sas_err_record), +- sg_dma_len(sg_resp)); ++ sg_resp->length); + break; + } + case SAS_PROTOCOL_SATA: +-- +2.27.0 + diff --git a/patches/0336-scsi-hisi_sas-Drop-free_irq-when-devm_request_irq-fa.patch b/patches/0336-scsi-hisi_sas-Drop-free_irq-when-devm_request_irq-fa.patch new file mode 100644 index 00000000..b7b360d6 --- /dev/null +++ b/patches/0336-scsi-hisi_sas-Drop-free_irq-when-devm_request_irq-fa.patch @@ -0,0 +1,175 @@ +From e1fb6703de353883b5a1cf2ffef6a99548b24095 Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Mon, 5 Aug 2019 21:48:08 +0800 +Subject: [PATCH 018/256] scsi: hisi_sas: Drop free_irq() when + devm_request_irq() failed + +mainline inclusion +from mainline-v5.4-rc1 +commit e16963f378faf82d307cad2796953f198497c614 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e16963f378faf82d307cad2796953f198497c614 + +---------------------------------------------------------------------- + +It will free irq automatically if devm_request_irq() failed, so drop +free_irq() if devm_request_irq() failed. + +Signed-off-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 33 ++++++-------------------- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 22 ++++------------- + 2 files changed, 11 insertions(+), 44 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +index d1453a6c6dda..bb1efab2b682 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -3329,8 +3329,8 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) + { + struct platform_device *pdev = hisi_hba->platform_dev; + struct device *dev = &pdev->dev; +- int irq, rc, irq_map[128]; +- int i, phy_no, fatal_no, queue_no, k; ++ int irq, rc = 0, irq_map[128]; ++ int i, phy_no, fatal_no, queue_no; + + for (i = 0; i < 128; i++) + irq_map[i] = platform_get_irq(pdev, i); +@@ -3343,7 +3343,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) + dev_err(dev, "irq init: could not request phy interrupt %d, rc=%d\n", + irq, rc); + rc = -ENOENT; +- goto free_phy_int_irqs; ++ goto err_out; + } + } + +@@ -3357,7 +3357,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) + dev_err(dev, "irq init: could not request sata interrupt %d, rc=%d\n", + irq, rc); + rc = -ENOENT; +- goto free_sata_int_irqs; ++ goto err_out; + } + } + +@@ -3369,7 +3369,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) + dev_err(dev, "irq init: could not request fatal interrupt %d, rc=%d\n", + irq, rc); + rc = -ENOENT; +- goto free_fatal_int_irqs; ++ goto err_out; + } + } + +@@ -3384,34 +3384,15 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) + dev_err(dev, "irq init: could not request cq interrupt %d, rc=%d\n", + irq, rc); + rc = -ENOENT; +- goto free_cq_int_irqs; ++ goto err_out; + } + tasklet_init(t, cq_tasklet_v2_hw, (unsigned long)cq); + } + + hisi_hba->nvecs = hisi_hba->queue_count; + hisi_hba->dq_num_per_node = hisi_hba->queue_count / num_online_nodes(); +- return 0; +- +-free_cq_int_irqs: +- for (k = 0; k < queue_no; k++) { +- struct hisi_sas_cq *cq = &hisi_hba->cq[k]; + +- free_irq(irq_map[k + 96], cq); +- tasklet_kill(&cq->tasklet); +- } +-free_fatal_int_irqs: +- for (k = 0; k < fatal_no; k++) +- free_irq(irq_map[k + 81], hisi_hba); +-free_sata_int_irqs: +- for (k = 0; k < phy_no; k++) { +- struct hisi_sas_phy *phy = &hisi_hba->phy[k]; +- +- free_irq(irq_map[k + 72], phy); +- } +-free_phy_int_irqs: +- for (k = 0; k < i; k++) +- free_irq(irq_map[k + 1], hisi_hba); ++err_out: + return rc; + } + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 19be76c54b4c..75161290bcc7 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -2706,8 +2706,7 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) + { + struct device *dev = hisi_hba->dev; + struct pci_dev *pdev = hisi_hba->pci_dev; +- int vectors, rc; +- int i, k; ++ int vectors, rc, i; + int max_dq_num, online_numa_num; + int max_msi = HISI_SAS_MSI_COUNT_V3_HW, min_msi; + +@@ -2765,7 +2764,7 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) + if (rc) { + dev_err(dev, "could not request chnl interrupt, rc=%d\n", rc); + rc = -ENOENT; +- goto free_phy_irq; ++ goto free_irq_vectors; + } + + rc = devm_request_irq(dev, pci_irq_vector(pdev, PCI_IRQ_AXI_FATAL), +@@ -2774,7 +2773,7 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) + if (rc) { + dev_err(dev, "could not request fatal interrupt, rc=%d\n", rc); + rc = -ENOENT; +- goto free_chnl_interrupt; ++ goto free_irq_vectors; + } + + /* Init tasklets for cq only */ +@@ -2792,7 +2791,7 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) + dev_err(dev, "could not request cq%d interrupt, rc=%d\n", + i, rc); + rc = -ENOENT; +- goto free_cq_irqs; ++ goto free_irq_vectors; + } + + tasklet_init(t, cq_tasklet_v3_hw, (uintptr_t)cq); +@@ -2800,19 +2799,6 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) + + return 0; + +-free_cq_irqs: +- for (k = 0; k < i; k++) { +- struct hisi_sas_cq *cq = &hisi_hba->cq[k]; +- int nr = hisi_sas_intr_conv ? PCI_IRQ_CQ_BASE : +- PCI_IRQ_CQ_BASE + k; +- +- free_irq(pci_irq_vector(pdev, nr), cq); +- } +- free_irq(pci_irq_vector(pdev, PCI_IRQ_AXI_FATAL), hisi_hba); +-free_chnl_interrupt: +- free_irq(pci_irq_vector(pdev, PCI_IRQ_CHANNEL), hisi_hba); +-free_phy_irq: +- free_irq(pci_irq_vector(pdev, PCI_IRQ_PHY), hisi_hba); + free_irq_vectors: + pci_free_irq_vectors(pdev); + return rc; +-- +2.27.0 + diff --git a/patches/0337-scsi-hisi_sas-Modify-return-type-of-debugfs-function.patch b/patches/0337-scsi-hisi_sas-Modify-return-type-of-debugfs-function.patch new file mode 100644 index 00000000..5f483110 --- /dev/null +++ b/patches/0337-scsi-hisi_sas-Modify-return-type-of-debugfs-function.patch @@ -0,0 +1,168 @@ +From 1949f735e8b04a558c9af20291737d84fc6c650c Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Mon, 5 Aug 2019 21:48:09 +0800 +Subject: [PATCH 019/256] scsi: hisi_sas: Modify return type of debugfs + functions + +mainline inclusion +from mainline-v5.4-rc1 +commit 7bf18e849d80e1beb118fd6d3bd5ccfcb1267d09 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7bf18e849d80e1beb118fd6d3bd5ccfcb1267d09 + +---------------------------------------------------------------------- + +For functions which always return 0, which is never checked, make to return +void. + +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 51 ++++++++++----------------- + 1 file changed, 18 insertions(+), 33 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index f57b8689fc3d..525f6ba94459 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -3404,8 +3404,8 @@ static const struct file_operations hisi_sas_debugfs_port_fops = { + .owner = THIS_MODULE, + }; + +-static int hisi_sas_show_row_64(struct seq_file *s, int index, +- int sz, __le64 *ptr) ++static void hisi_sas_show_row_64(struct seq_file *s, int index, ++ int sz, __le64 *ptr) + { + int i; + +@@ -3419,12 +3419,10 @@ static int hisi_sas_show_row_64(struct seq_file *s, int index, + } + + seq_puts(s, "\n"); +- +- return 0; + } + +-static int hisi_sas_show_row_32(struct seq_file *s, int index, +- int sz, __le32 *ptr) ++static void hisi_sas_show_row_32(struct seq_file *s, int index, ++ int sz, __le32 *ptr) + { + int i; + +@@ -3437,11 +3435,9 @@ static int hisi_sas_show_row_32(struct seq_file *s, int index, + seq_puts(s, "\n\t"); + } + seq_puts(s, "\n"); +- +- return 0; + } + +-static int hisi_sas_cq_show_slot(struct seq_file *s, int slot, void *cq_ptr) ++static void hisi_sas_cq_show_slot(struct seq_file *s, int slot, void *cq_ptr) + { + struct hisi_sas_cq *cq = cq_ptr; + struct hisi_hba *hisi_hba = cq->hisi_hba; +@@ -3449,20 +3445,18 @@ static int hisi_sas_cq_show_slot(struct seq_file *s, int slot, void *cq_ptr) + u64 offset = hisi_hba->hw->complete_hdr_size * slot; + __le32 *complete_hdr = complete_queue + offset; + +- return hisi_sas_show_row_32(s, slot, +- hisi_hba->hw->complete_hdr_size, +- complete_hdr); ++ hisi_sas_show_row_32(s, slot, ++ hisi_hba->hw->complete_hdr_size, ++ complete_hdr); + } + + static int hisi_sas_debugfs_cq_show(struct seq_file *s, void *p) + { + struct hisi_sas_cq *cq = s->private; +- int slot, ret; ++ int slot; + + for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) { +- ret = hisi_sas_cq_show_slot(s, slot, cq); +- if (ret) +- return ret; ++ hisi_sas_cq_show_slot(s, slot, cq); + } + return 0; + } +@@ -3480,7 +3474,7 @@ static const struct file_operations hisi_sas_debugfs_cq_fops = { + .owner = THIS_MODULE, + }; + +-static int hisi_sas_dq_show_slot(struct seq_file *s, int slot, void *dq_ptr) ++static void hisi_sas_dq_show_slot(struct seq_file *s, int slot, void *dq_ptr) + { + struct hisi_sas_dq *dq = dq_ptr; + struct hisi_hba *hisi_hba = dq->hisi_hba; +@@ -3488,18 +3482,15 @@ static int hisi_sas_dq_show_slot(struct seq_file *s, int slot, void *dq_ptr) + u64 offset = sizeof(struct hisi_sas_cmd_hdr) * slot; + __le32 *cmd_hdr = cmd_queue + offset; + +- return hisi_sas_show_row_32(s, slot, sizeof(struct hisi_sas_cmd_hdr), +- cmd_hdr); ++ hisi_sas_show_row_32(s, slot, sizeof(struct hisi_sas_cmd_hdr), cmd_hdr); + } + + static int hisi_sas_debugfs_dq_show(struct seq_file *s, void *p) + { +- int slot, ret; ++ int slot; + + for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) { +- ret = hisi_sas_dq_show_slot(s, slot, s->private); +- if (ret) +- return ret; ++ hisi_sas_dq_show_slot(s, slot, s->private); + } + return 0; + } +@@ -3521,15 +3512,12 @@ static int hisi_sas_debugfs_iost_show(struct seq_file *s, void *p) + { + struct hisi_hba *hisi_hba = s->private; + struct hisi_sas_iost *debugfs_iost = hisi_hba->debugfs_iost; +- int i, ret, max_command_entries = HISI_SAS_MAX_COMMANDS; ++ int i, max_command_entries = HISI_SAS_MAX_COMMANDS; + + for (i = 0; i < max_command_entries; i++, debugfs_iost++) { + __le64 *iost = &debugfs_iost->qw0; + +- ret = hisi_sas_show_row_64(s, i, sizeof(*debugfs_iost), +- iost); +- if (ret) +- return ret; ++ hisi_sas_show_row_64(s, i, sizeof(*debugfs_iost), iost); + } + + return 0; +@@ -3590,17 +3578,14 @@ static const struct file_operations hisi_sas_debugfs_iost_cache_fops = { + + static int hisi_sas_debugfs_itct_show(struct seq_file *s, void *p) + { +- int i, ret; ++ int i; + struct hisi_hba *hisi_hba = s->private; + struct hisi_sas_itct *debugfs_itct = hisi_hba->debugfs_itct; + + for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, debugfs_itct++) { + __le64 *itct = &debugfs_itct->qw0; + +- ret = hisi_sas_show_row_64(s, i, sizeof(*debugfs_itct), +- itct); +- if (ret) +- return ret; ++ hisi_sas_show_row_64(s, i, sizeof(*debugfs_itct), itct); + } + + return 0; +-- +2.27.0 + diff --git a/patches/0338-scsi-hisi_sas-Remove-some-unnecessary-code.patch b/patches/0338-scsi-hisi_sas-Remove-some-unnecessary-code.patch new file mode 100644 index 00000000..844dc8e7 --- /dev/null +++ b/patches/0338-scsi-hisi_sas-Remove-some-unnecessary-code.patch @@ -0,0 +1,55 @@ +From 828bbc54c60ef9e6a9a42b6e946dcdb03df491a4 Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Mon, 5 Aug 2019 21:48:10 +0800 +Subject: [PATCH 020/256] scsi: hisi_sas: Remove some unnecessary code + +mainline inclusion +from mainline-v5.4-rc1 +commit a07b48766c5232b98154f68010512a9269f2841e +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a07b48766c5232b98154f68010512a9269f2841e + +---------------------------------------------------------------------- + +Remove some unnecessary code, including: + + - Explicit zeroing of memory allocated for dmam_alloc_coherent() + + - Some duplicated code + + - Some redundant masking + +Signed-off-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 75161290bcc7..722ef2be390a 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -3543,8 +3543,6 @@ hisi_sas_shost_alloc_pci(struct pci_dev *pdev) + else + hisi_hba->enable_dix_dif = enable_dix_dif; + +- timer_setup(&hisi_hba->timer, NULL, 0); +- + if (hisi_sas_get_fw_info(hisi_hba) < 0) + goto err_out; + +@@ -3636,7 +3634,6 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) + sha->lldd_module = THIS_MODULE; + sha->sas_addr = &hisi_hba->sas_addr[0]; + sha->num_phys = hisi_hba->n_phy; +- sha->core.shost = hisi_hba->shost; + + for (i = 0; i < hisi_hba->n_phy; i++) { + sha->sas_phy[i] = &hisi_hba->phy[i].sas_phy; +-- +2.27.0 + diff --git a/patches/0339-scsi-hisi_sas-remove-set-but-not-used-variable-irq_v.patch b/patches/0339-scsi-hisi_sas-remove-set-but-not-used-variable-irq_v.patch new file mode 100644 index 00000000..b1ed8272 --- /dev/null +++ b/patches/0339-scsi-hisi_sas-remove-set-but-not-used-variable-irq_v.patch @@ -0,0 +1,50 @@ +From fa233debff70e9c2a7fb6157041cf9989f54a449 Mon Sep 17 00:00:00 2001 +From: zhengbin +Date: Thu, 22 Aug 2019 22:20:47 +0800 +Subject: [PATCH 021/256] scsi: hisi_sas: remove set but not used variable + 'irq_value' + +mainline inclusion +from mainline-v5.4-rc1 +commit 328bc6debf3dcaf8859dd1323882e8e24ec6e3f8 +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=328bc6debf3dcaf8859dd1323882e8e24ec6e3f8 + +---------------------------------------------------------------------- + +Fixes gcc '-Wunused-but-set-variable' warning: + +drivers/scsi/hisi_sas/hisi_sas_v1_hw.c: In function cq_interrupt_v1_hw: +drivers/scsi/hisi_sas/hisi_sas_v1_hw.c:1542:6: warning: variable irq_value set but not used [-Wunused-but-set-variable] + +Reported-by: Hulk Robot +Signed-off-by: zhengbin +Acked-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +index fb64684384c6..7ec286b11973 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +@@ -1505,11 +1505,9 @@ static irqreturn_t cq_interrupt_v1_hw(int irq, void *p) + struct hisi_sas_complete_v1_hdr *complete_queue = + (struct hisi_sas_complete_v1_hdr *) + hisi_hba->complete_hdr[queue]; +- u32 irq_value, rd_point = cq->rd_point, wr_point; ++ u32 rd_point = cq->rd_point, wr_point; + + spin_lock(&hisi_hba->lock); +- irq_value = hisi_sas_read32(hisi_hba, OQ_INT_SRC); +- + hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue); + wr_point = hisi_sas_read32(hisi_hba, + COMPL_Q_0_WR_PTR + (0x14 * queue)); +-- +2.27.0 + diff --git a/patches/0340-scsi-hisi_sas-use-devm_platform_ioremap_resource-to-.patch b/patches/0340-scsi-hisi_sas-use-devm_platform_ioremap_resource-to-.patch new file mode 100644 index 00000000..63cabd1e --- /dev/null +++ b/patches/0340-scsi-hisi_sas-use-devm_platform_ioremap_resource-to-.patch @@ -0,0 +1,46 @@ +From 75124c02f44abe105de74198c93fae75ccfa6465 Mon Sep 17 00:00:00 2001 +From: YueHaibing +Date: Wed, 4 Sep 2019 21:02:56 +0800 +Subject: [PATCH 022/256] scsi: hisi_sas: use devm_platform_ioremap_resource() + to simplify code + +mainline inclusion +from mainline-v5.4-rc1 +commit c0c1a71e9542e6b0b58642332eb86fd32c9b2ed8 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c0c1a71e9542e6b0b58642332eb86fd32c9b2ed8 + +---------------------------------------------------------------------- + +Use devm_platform_ioremap_resource() to simplify the code a bit. +This is detected by coccinelle. + +Link: https://lore.kernel.org/r/20190904130256.24704-1-yuehaibing@huawei.com +Reported-by: Hulk Robot +Signed-off-by: YueHaibing +Acked-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 525f6ba94459..ce6fe08cf18b 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -2659,8 +2659,7 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev, + goto err_out; + } + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- hisi_hba->regs = devm_ioremap_resource(dev, res); ++ hisi_hba->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(hisi_hba->regs)) + goto err_out; + +-- +2.27.0 + diff --git a/patches/0341-scsi-hisi_sas-add-debugfs-auto-trigger-for-internal-.patch b/patches/0341-scsi-hisi_sas-add-debugfs-auto-trigger-for-internal-.patch new file mode 100644 index 00000000..ed442f15 --- /dev/null +++ b/patches/0341-scsi-hisi_sas-add-debugfs-auto-trigger-for-internal-.patch @@ -0,0 +1,44 @@ +From 964fbaacc84bc16a624a8d40204975ef14c01372 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Fri, 6 Sep 2019 20:55:25 +0800 +Subject: [PATCH 023/256] scsi: hisi_sas: add debugfs auto-trigger for internal + abort time out + +mainline inclusion +from mainline-v5.4-rc1 +commit 7105e68afaec062c0329910a491e57c9f3a82bef +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F808 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7105e68afaec062c0329910a491e57c9f3a82bef + +---------------------------------------------------------------------- + +This trigger is add at _hisi_sas_internal_task_abort() + +Link: https://lore.kernel.org/r/1567774537-20003-2-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index ce6fe08cf18b..bb8d872958c1 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -2132,6 +2132,9 @@ _hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, + + /* Internal abort timed out */ + if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { ++ if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct) ++ queue_work(hisi_hba->wq, &hisi_hba->debugfs_work); ++ + if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { + struct hisi_sas_slot *slot = task->lldd_task; + +-- +2.27.0 + diff --git a/patches/0342-scsi-hisi_sas-Remove-hisi_sas_hw.slot_complete.patch b/patches/0342-scsi-hisi_sas-Remove-hisi_sas_hw.slot_complete.patch new file mode 100644 index 00000000..2ca74a8d --- /dev/null +++ b/patches/0342-scsi-hisi_sas-Remove-hisi_sas_hw.slot_complete.patch @@ -0,0 +1,84 @@ +From a78f22345f24aa09d1e53ed898f0683af04045b5 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Fri, 6 Sep 2019 20:55:32 +0800 +Subject: [PATCH 024/256] scsi: hisi_sas: Remove hisi_sas_hw.slot_complete + +mainline inclusion +from mainline-v5.4-rc1 +commit 971b59443f213d8085d122fae65aa96087b269bc +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=971b59443f213d8085d122fae65aa96087b269bc + +---------------------------------------------------------------------- + +We never call hisi_sas_hw.slot_complete, so remove it. + +Link: https://lore.kernel.org/r/1567774537-20003-9-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas.h +--- + drivers/scsi/hisi_sas/hisi_sas.h | 2 -- + drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 1 - + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 1 - + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 1 - + 4 files changed, 5 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index de5752f07987..3fc67664c22a 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -331,8 +331,6 @@ struct hisi_sas_hw { + struct hisi_sas_slot *slot, + unsigned int device_id, + int abort_flag, int tag_to_abort); +- int (*slot_complete)(struct hisi_hba *hisi_hba, +- struct hisi_sas_slot *slot); + void (*phys_init)(struct hisi_hba *hisi_hba); + void (*phy_start)(struct hisi_hba *hisi_hba, int phy_no); + void (*phy_disable)(struct hisi_hba *hisi_hba, int phy_no); +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +index 7ec286b11973..1228f282d443 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +@@ -1790,7 +1790,6 @@ static const struct hisi_sas_hw hisi_sas_v1_hw = { + .prep_smp = prep_smp_v1_hw, + .prep_ssp = prep_ssp_v1_hw, + .start_delivery = start_delivery_v1_hw, +- .slot_complete = slot_complete_v1_hw, + .phys_init = phys_init_v1_hw, + .phy_start = start_phy_v1_hw, + .phy_disable = disable_phy_v1_hw, +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +index bb1efab2b682..a835487fd406 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -3586,7 +3586,6 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = { + .prep_stp = prep_ata_v2_hw, + .prep_abort = prep_abort_v2_hw, + .start_delivery = start_delivery_v2_hw, +- .slot_complete = slot_complete_v2_hw, + .phys_init = phys_init_v2_hw, + .phy_start = start_phy_v2_hw, + .phy_disable = disable_phy_v2_hw, +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 722ef2be390a..eee696afb28d 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -3488,7 +3488,6 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = { + .prep_stp = prep_ata_v3_hw, + .prep_abort = prep_abort_v3_hw, + .start_delivery = start_delivery_v3_hw, +- .slot_complete = slot_complete_v3_hw, + .phys_init = phys_init_v3_hw, + .phy_start = start_phy_v3_hw, + .phy_disable = disable_phy_v3_hw, +-- +2.27.0 + diff --git a/patches/0343-scsi-hisi_sas-Remove-redundant-work-declaration.patch b/patches/0343-scsi-hisi_sas-Remove-redundant-work-declaration.patch new file mode 100644 index 00000000..bf2c321f --- /dev/null +++ b/patches/0343-scsi-hisi_sas-Remove-redundant-work-declaration.patch @@ -0,0 +1,41 @@ +From 550219eca40a5ec48fea8356e364671249118752 Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Fri, 6 Sep 2019 20:55:33 +0800 +Subject: [PATCH 025/256] scsi: hisi_sas: Remove redundant work declaration + +mainline inclusion +from mainline-v5.4-rc1 +commit 27f22723c3f4a1a3e66642b3da7a3d16ee602972 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=27f22723c3f4a1a3e66642b3da7a3d16ee602972 + +---------------------------------------------------------------------- + +Remove redundant work declaration in HISI_SAS_DECLARE_RST_WORK_ON_STACK + +Link: https://lore.kernel.org/r/1567774537-20003-10-git-send-email-john.garry@huawei.com +Signed-off-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas.h | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 3fc67664c22a..ba4470bf99da 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -153,7 +153,6 @@ struct hisi_sas_rst { + + #define HISI_SAS_DECLARE_RST_WORK_ON_STACK(r) \ + DECLARE_COMPLETION_ONSTACK(c); \ +- DECLARE_WORK(w, hisi_sas_sync_rst_work_handler); \ + struct hisi_sas_rst r = HISI_SAS_RST_WORK_INIT(r, c) + + enum hisi_sas_bit_err_type { +-- +2.27.0 + diff --git a/patches/0344-scsi-hisi_sas-Remove-some-unused-function-arguments.patch b/patches/0344-scsi-hisi_sas-Remove-some-unused-function-arguments.patch new file mode 100644 index 00000000..254b67c0 --- /dev/null +++ b/patches/0344-scsi-hisi_sas-Remove-some-unused-function-arguments.patch @@ -0,0 +1,153 @@ +From 028074c6fbdc8343b75c8dea156a0323fccaae95 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Fri, 6 Sep 2019 20:55:34 +0800 +Subject: [PATCH 026/256] scsi: hisi_sas: Remove some unused function arguments + +mainline inclusion +from mainline-v5.4-rc1 +commit 4bc058097aa8b1af046fa000fbc6bf5408ace9bf +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4bc058097aa8b1af046fa000fbc6bf5408ace9bf + +---------------------------------------------------------------------- + +Some function arguments are unused, so remove them. + +Also move the timeout print in for wait_cmds_complete_timeout_vX_hw() +callsites into that same function. + +Link: https://lore.kernel.org/r/1567774537-20003-11-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas.h + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 2 +- + drivers/scsi/hisi_sas/hisi_sas_main.c | 5 ++--- + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 9 +++++---- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 15 ++++++--------- + 4 files changed, 14 insertions(+), 17 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index ba4470bf99da..4b974461cb41 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -348,7 +348,7 @@ struct hisi_sas_hw { + u32 (*get_phys_state)(struct hisi_hba *hisi_hba); + int (*write_gpio)(struct hisi_hba *hisi_hba, u8 reg_type, + u8 reg_index, u8 reg_count, u8 *write_data); +- int (*wait_cmds_complete_timeout)(struct hisi_hba *hisi_hba, ++ void (*wait_cmds_complete_timeout)(struct hisi_hba *hisi_hba, + int delay_ms, int timeout_ms); + void (*snapshot_prepare)(struct hisi_hba *hisi_hba); + void (*snapshot_restore)(struct hisi_hba *hisi_hba); +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index bb8d872958c1..7df98ca85e86 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1438,8 +1438,7 @@ static void hisi_sas_refresh_port_id(struct hisi_hba *hisi_hba) + } + } + +-static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 old_state, +- u32 state) ++static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state) + { + struct sas_ha_struct *sas_ha = &hisi_hba->sha; + struct asd_sas_port *_sas_port = NULL; +@@ -1615,7 +1614,7 @@ void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba) + clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags); + + state = hisi_hba->hw->get_phys_state(hisi_hba); +- hisi_sas_rescan_topology(hisi_hba, hisi_hba->phy_state, state); ++ hisi_sas_rescan_topology(hisi_hba, state); + } + EXPORT_SYMBOL_GPL(hisi_sas_controller_reset_done); + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +index a835487fd406..55faa3ec72f9 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -3521,7 +3521,7 @@ static int write_gpio_v2_hw(struct hisi_hba *hisi_hba, u8 reg_type, + return 0; + } + +-static int wait_cmds_complete_timeout_v2_hw(struct hisi_hba *hisi_hba, ++static void wait_cmds_complete_timeout_v2_hw(struct hisi_hba *hisi_hba, + int delay_ms, int timeout_ms) + { + struct device *dev = hisi_hba->dev; +@@ -3536,12 +3536,13 @@ static int wait_cmds_complete_timeout_v2_hw(struct hisi_hba *hisi_hba, + msleep(delay_ms); + } + +- if (time >= timeout_ms) +- return -ETIMEDOUT; ++ if (time >= timeout_ms) { ++ dev_dbg(dev, "Wait commands complete timeout!\n"); ++ return; ++ } + + dev_dbg(dev, "wait commands complete %dms\n", time); + +- return 0; + } + + struct device_attribute *host_attrs_v2_hw[] = { +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index eee696afb28d..e55442525ae6 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -2978,7 +2978,7 @@ static int write_gpio_v3_hw(struct hisi_hba *hisi_hba, u8 reg_type, + return 0; + } + +-static int wait_cmds_complete_timeout_v3_hw(struct hisi_hba *hisi_hba, ++static void wait_cmds_complete_timeout_v3_hw(struct hisi_hba *hisi_hba, + int delay_ms, int timeout_ms) + { + struct device *dev = hisi_hba->dev; +@@ -2993,12 +2993,12 @@ static int wait_cmds_complete_timeout_v3_hw(struct hisi_hba *hisi_hba, + msleep(delay_ms); + } + +- if (time >= timeout_ms) +- return -ETIMEDOUT; ++ if (time >= timeout_ms) { ++ dev_dbg(dev, "Wait commands complete timeout!\n"); ++ return; ++ } + + dev_dbg(dev, "wait commands complete %dms\n", time); +- +- return 0; + } + + static ssize_t intr_conv_show(struct device *dev, +@@ -3280,15 +3280,12 @@ static const struct hisi_sas_debugfs_reg debugfs_ras_reg = { + + static void debugfs_snapshot_prepare_v3_hw(struct hisi_hba *hisi_hba) + { +- struct device *dev = hisi_hba->dev; +- + set_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); + + hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0); + + /* delay:100ms, timeout:5s */ +- if (wait_cmds_complete_timeout_v3_hw(hisi_hba, 100, 5000) == -ETIMEDOUT) +- dev_dbg(dev, "Wait commands complete timeout!\n"); ++ wait_cmds_complete_timeout_v3_hw(hisi_hba, 100, 5000); + + hisi_sas_kill_tasklets(hisi_hba); + } +-- +2.27.0 + diff --git a/patches/0345-scsi-hisi_sas-Add-hisi_sas_debugfs_alloc-to-centrali.patch b/patches/0345-scsi-hisi_sas-Add-hisi_sas_debugfs_alloc-to-centrali.patch new file mode 100644 index 00000000..e6770df3 --- /dev/null +++ b/patches/0345-scsi-hisi_sas-Add-hisi_sas_debugfs_alloc-to-centrali.patch @@ -0,0 +1,257 @@ +From 358e2dd648ece28f89d203414df561d0c634745a Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Fri, 6 Sep 2019 20:55:35 +0800 +Subject: [PATCH 027/256] scsi: hisi_sas: Add hisi_sas_debugfs_alloc() to + centralise allocation + +mainline inclusion +from mainline-v5.4-rc1 +commit 7ec7082c57ecdd8d37040d31203951f7e2e8e218 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F808 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7ec7082c57ecdd8d37040d31203951f7e2e8e218 + +---------------------------------------------------------------------- + +We extract the code of memory allocate and construct an new function for +it. We think it's convenient for subsequent optimization. + +Link: https://lore.kernel.org/r/1567774537-20003-12-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 117 +++++++++++++++----------- + 1 file changed, 66 insertions(+), 51 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 7df98ca85e86..6e49a91aa492 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -3783,60 +3783,77 @@ void hisi_sas_debugfs_work_handler(struct work_struct *work) + } + EXPORT_SYMBOL_GPL(hisi_sas_debugfs_work_handler); + +-void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) ++void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba) ++{ ++ struct device *dev = hisi_hba->dev; ++ int i; ++ ++ devm_kfree(dev, hisi_hba->debugfs_iost_cache); ++ devm_kfree(dev, hisi_hba->debugfs_itct_cache); ++ devm_kfree(dev, hisi_hba->debugfs_iost); ++ ++ for (i = 0; i < hisi_hba->queue_count; i++) ++ devm_kfree(dev, hisi_hba->debugfs_cmd_hdr[i]); ++ ++ for (i = 0; i < hisi_hba->queue_count; i++) ++ devm_kfree(dev, hisi_hba->debugfs_complete_hdr[i]); ++ ++ for (i = 0; i < DEBUGFS_REGS_NUM; i++) ++ devm_kfree(dev, hisi_hba->debugfs_regs[i]); ++ ++ for (i = 0; i < hisi_hba->n_phy; i++) ++ devm_kfree(dev, hisi_hba->debugfs_port_reg[i]); ++} ++ ++int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba) + { +- int max_command_entries = HISI_SAS_MAX_COMMANDS; + const struct hisi_sas_hw *hw = hisi_hba->hw; + struct device *dev = hisi_hba->dev; +- int p, i, c, d; ++ int p, c, d; + size_t sz; + +- hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev), +- hisi_sas_debugfs_dir); ++ hisi_hba->debugfs_dump_dentry = ++ debugfs_create_dir("dump", hisi_hba->debugfs_dir); + +- debugfs_create_file("trigger_dump", 0600, +- hisi_hba->debugfs_dir, +- hisi_hba, +- &hisi_sas_debugfs_trigger_dump_fops); + /* create bist structures */ + hisi_hba->debugfs_bist_dentry = debugfs_create_dir("bist", + hisi_hba->debugfs_dir); + if (!hisi_hba->debugfs_bist_dentry) +- goto fail_global; ++ goto fail; + + if (!debugfs_create_file("link_rate", 0644, + hisi_hba->debugfs_bist_dentry, hisi_hba, + &hisi_sas_debugfs_bist_linkrate_ops)) +- goto fail_global; ++ goto fail; + + if (!debugfs_create_file("code_mode", 0644, + hisi_hba->debugfs_bist_dentry, hisi_hba, + &hisi_sas_debugfs_bist_code_mode_ops)) +- goto fail_global; ++ goto fail; + + if (!debugfs_create_file("phy_id", 0644, hisi_hba->debugfs_bist_dentry, + hisi_hba, &hisi_sas_debugfs_bist_phy_ops)) +- goto fail_global; ++ goto fail; + + if (!debugfs_create_u32("cnt", 0644, hisi_hba->debugfs_bist_dentry, + &hisi_hba->bist_loopback_cnt)) +- goto fail_global; ++ goto fail; + + if (!debugfs_create_file("loopback_mode", 0400, + hisi_hba->debugfs_bist_dentry, + hisi_hba, &hisi_sas_debugfs_bist_mode_ops)) +- goto fail_global; ++ goto fail; + + if (!debugfs_create_file("enable", 0644, hisi_hba->debugfs_bist_dentry, + hisi_hba, &hisi_sas_debugfs_bist_enable_ops)) +- goto fail_global; ++ goto fail; + + sz = hw->debugfs_reg_array[DEBUGFS_GLOBAL]->count * 4; + hisi_hba->debugfs_regs[DEBUGFS_GLOBAL] = + devm_kmalloc(dev, sz, GFP_KERNEL); + + if (!hisi_hba->debugfs_regs[DEBUGFS_GLOBAL]) +- goto fail_global; ++ goto fail; + + sz = hw->debugfs_reg_port->count * 4; + for (p = 0; p < hisi_hba->n_phy; p++) { +@@ -3844,7 +3861,7 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) + devm_kmalloc(dev, sz, GFP_KERNEL); + + if (!hisi_hba->debugfs_port_reg[p]) +- goto fail_port; ++ goto fail; + } + + sz = hw->debugfs_reg_array[DEBUGFS_AXI]->count * 4; +@@ -3852,14 +3869,14 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) + devm_kmalloc(dev, sz, GFP_KERNEL); + + if (!hisi_hba->debugfs_regs[DEBUGFS_AXI]) +- goto fail_axi; ++ goto fail; + + sz = hw->debugfs_reg_array[DEBUGFS_RAS]->count * 4; + hisi_hba->debugfs_regs[DEBUGFS_RAS] = + devm_kmalloc(dev, sz, GFP_KERNEL); + + if (!hisi_hba->debugfs_regs[DEBUGFS_RAS]) +- goto fail_ras; ++ goto fail; + + sz = hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS; + for (c = 0; c < hisi_hba->queue_count; c++) { +@@ -3867,7 +3884,7 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) + devm_kmalloc(dev, sz, GFP_KERNEL); + + if (!hisi_hba->debugfs_complete_hdr[c]) +- goto fail_cq; ++ goto fail; + } + + sz = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS; +@@ -3876,60 +3893,58 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) + devm_kmalloc(dev, sz, GFP_KERNEL); + + if (!hisi_hba->debugfs_cmd_hdr[d]) +- goto fail_iost_dq; ++ goto fail; + } + +- sz = max_command_entries * sizeof(struct hisi_sas_iost); ++ sz = HISI_SAS_MAX_COMMANDS * sizeof(struct hisi_sas_iost); + + hisi_hba->debugfs_iost = devm_kmalloc(dev, sz, GFP_KERNEL); + if (!hisi_hba->debugfs_iost) +- goto fail_iost_dq; ++ goto fail; + + sz = HISI_SAS_IOST_ITCT_CACHE_NUM * + sizeof(struct hisi_sas_iost_itct_cache); + + hisi_hba->debugfs_iost_cache = devm_kmalloc(dev, sz, GFP_KERNEL); + if (!hisi_hba->debugfs_iost_cache) +- goto fail_iost_cache; ++ goto fail; + + sz = HISI_SAS_IOST_ITCT_CACHE_NUM * + sizeof(struct hisi_sas_iost_itct_cache); + + hisi_hba->debugfs_itct_cache = devm_kmalloc(dev, sz, GFP_KERNEL); + if (!hisi_hba->debugfs_itct_cache) +- goto fail_itct_cache; ++ goto fail; + + /* New memory allocation must be locate before itct */ + sz = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct); + + hisi_hba->debugfs_itct = devm_kmalloc(dev, sz, GFP_KERNEL); + if (!hisi_hba->debugfs_itct) +- goto fail_itct; ++ goto fail; ++ ++ return 0; ++fail: ++ hisi_sas_debugfs_release(hisi_hba); ++ return -ENOMEM; ++} ++ ++void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) ++{ ++ struct device *dev = hisi_hba->dev; ++ ++ hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev), ++ hisi_sas_debugfs_dir); ++ debugfs_create_file("trigger_dump", 0600, ++ hisi_hba->debugfs_dir, ++ hisi_hba, ++ &hisi_sas_debugfs_trigger_dump_fops); ++ ++ if (hisi_sas_debugfs_alloc(hisi_hba)) { ++ debugfs_remove_recursive(hisi_hba->debugfs_dir); ++ dev_dbg(dev, "failed to init debugfs!\n"); ++ } + +- return; +-fail_itct: +- devm_kfree(dev, hisi_hba->debugfs_iost_cache); +-fail_itct_cache: +- devm_kfree(dev, hisi_hba->debugfs_iost_cache); +-fail_iost_cache: +- devm_kfree(dev, hisi_hba->debugfs_iost); +-fail_iost_dq: +- for (i = 0; i < d; i++) +- devm_kfree(dev, hisi_hba->debugfs_cmd_hdr[i]); +-fail_cq: +- for (i = 0; i < c; i++) +- devm_kfree(dev, hisi_hba->debugfs_complete_hdr[i]); +- devm_kfree(dev, hisi_hba->debugfs_regs[DEBUGFS_RAS]); +-fail_ras: +- devm_kfree(dev, hisi_hba->debugfs_regs[DEBUGFS_AXI]); +-fail_axi: +-fail_port: +- for (i = 0; i < p; i++) +- devm_kfree(dev, hisi_hba->debugfs_port_reg[i]); +- devm_kfree(dev, hisi_hba->debugfs_regs[DEBUGFS_GLOBAL]); +-fail_global: +- hisi_sas_debugfs_exit(hisi_hba); +- dev_info(dev, "failed to init debugfs!\n"); + } + EXPORT_SYMBOL_GPL(hisi_sas_debugfs_init); + +-- +2.27.0 + diff --git a/patches/0346-scsi-hisi_sas-fix-spelling-mistake-digial-digital.patch b/patches/0346-scsi-hisi_sas-fix-spelling-mistake-digial-digital.patch new file mode 100644 index 00000000..aebc7510 --- /dev/null +++ b/patches/0346-scsi-hisi_sas-fix-spelling-mistake-digial-digital.patch @@ -0,0 +1,45 @@ +From f532b6321c64f9d52a6f6dc9e24badff7b359388 Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Mon, 16 Sep 2019 10:17:06 +0100 +Subject: [PATCH 028/256] scsi: hisi_sas: fix spelling mistake "digial" -> + "digital" + +mainline inclusion +from mainline-v5.5-rc1 +commit b1000fcca1760d3e81f0943f0ca8b9be3ed3b999 +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b1000fcca1760d3e81f0943f0ca8b9be3ed3b999 + +---------------------------------------------------------------------- + +There is a spelling mistake in literal string. Fix it. + +Link: https://lore.kernel.org/r/20190916091706.32268-1-colin.king@canonical.com +Signed-off-by: Colin Ian King +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 6e49a91aa492..4e1bdfa370d9 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -3182,7 +3182,7 @@ static struct { + int value; + char *name; + } hisi_sas_debugfs_loop_modes[] = { +- { HISI_SAS_BIST_LOOPBACK_MODE_DIGITAL, "digial" }, ++ { HISI_SAS_BIST_LOOPBACK_MODE_DIGITAL, "digital" }, + { HISI_SAS_BIST_LOOPBACK_MODE_SERDES, "serdes" }, + { HISI_SAS_BIST_LOOPBACK_MODE_REMOTE, "remote" }, + }; +-- +2.27.0 + diff --git a/patches/0347-scsi-hisi_sas-Make-three-functions-static.patch b/patches/0347-scsi-hisi_sas-Make-three-functions-static.patch new file mode 100644 index 00000000..83197073 --- /dev/null +++ b/patches/0347-scsi-hisi_sas-Make-three-functions-static.patch @@ -0,0 +1,59 @@ +From dd20d91b68bc381cf952cc87de63122aaa7997f7 Mon Sep 17 00:00:00 2001 +From: YueHaibing +Date: Mon, 23 Sep 2019 13:40:35 +0800 +Subject: [PATCH 029/256] scsi: hisi_sas: Make three functions static + +mainline inclusion +from mainline-v5.4-rc2 +commit 4b6b1bb68628ec49e4cbfabd8ac17a169f079cd8 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4b6b1bb68628ec49e4cbfabd8ac17a169f079cd8 + +---------------------------------------------------------------------- + +Fix sparse warnings: + +drivers/scsi/hisi_sas/hisi_sas_main.c:3686:6: + warning: symbol 'hisi_sas_debugfs_release' was not declared. Should it be static? +drivers/scsi/hisi_sas/hisi_sas_main.c:3708:5: + warning: symbol 'hisi_sas_debugfs_alloc' was not declared. Should it be static? +drivers/scsi/hisi_sas/hisi_sas_main.c:3799:6: + warning: symbol 'hisi_sas_debugfs_bist_init' was not declared. Should it be static? + +Link: https://lore.kernel.org/r/20190923054035.19036-1-yuehaibing@huawei.com +Reported-by: Hulk Robot +Signed-off-by: YueHaibing +Acked-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 4e1bdfa370d9..31820f024340 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -3783,7 +3783,7 @@ void hisi_sas_debugfs_work_handler(struct work_struct *work) + } + EXPORT_SYMBOL_GPL(hisi_sas_debugfs_work_handler); + +-void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba) ++static void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba) + { + struct device *dev = hisi_hba->dev; + int i; +@@ -3805,7 +3805,7 @@ void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba) + devm_kfree(dev, hisi_hba->debugfs_port_reg[i]); + } + +-int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba) ++static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba) + { + const struct hisi_sas_hw *hw = hisi_hba->hw; + struct device *dev = hisi_hba->dev; +-- +2.27.0 + diff --git a/patches/0348-scsi-hisi_sas-Don-t-create-debugfs-dump-folder-twice.patch b/patches/0348-scsi-hisi_sas-Don-t-create-debugfs-dump-folder-twice.patch new file mode 100644 index 00000000..3a52c4dd --- /dev/null +++ b/patches/0348-scsi-hisi_sas-Don-t-create-debugfs-dump-folder-twice.patch @@ -0,0 +1,55 @@ +From 692f1e7568e1ec959c180b694d14585e5ea0262a Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Thu, 24 Oct 2019 22:08:08 +0800 +Subject: [PATCH 030/256] scsi: hisi_sas: Don't create debugfs dump folder + twice + +mainline inclusion +from mainline-v5.5-rc1 +commit 35160421b63d4753a72e9f72ebcdd9d6f88f84b9 +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=35160421b63d4753a72e9f72ebcdd9d6f88f84b9 + +---------------------------------------------------------------------- + +Due to a merge error, we attempt to create 2x debugfs dump folders, which +fails: +[ 861.101914] debugfs: Directory 'dump' with parent '0000:74:02.0' +already present! + +This breaks the dump function. + +To fix, remove the superfluous attempt to create the folder. + +Fixes: 7ec7082c57ec ("scsi: hisi_sas: Add hisi_sas_debugfs_alloc() to centralise allocation") +Link: https://lore.kernel.org/r/1571926105-74636-2-git-send-email-john.garry@huawei.com +Signed-off-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 31820f024340..bb0287eed0dc 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -3812,9 +3812,6 @@ static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba) + int p, c, d; + size_t sz; + +- hisi_hba->debugfs_dump_dentry = +- debugfs_create_dir("dump", hisi_hba->debugfs_dir); +- + /* create bist structures */ + hisi_hba->debugfs_bist_dentry = debugfs_create_dir("bist", + hisi_hba->debugfs_dir); +-- +2.27.0 + diff --git a/patches/0349-scsi-hisi_sas-Add-timestamp-for-a-debugfs-dump.patch b/patches/0349-scsi-hisi_sas-Add-timestamp-for-a-debugfs-dump.patch new file mode 100644 index 00000000..2ef87dfc --- /dev/null +++ b/patches/0349-scsi-hisi_sas-Add-timestamp-for-a-debugfs-dump.patch @@ -0,0 +1,93 @@ +From 9b82db5e3825250cfde2ef9e2903c4d16001415b Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Thu, 24 Oct 2019 22:08:12 +0800 +Subject: [PATCH 031/256] scsi: hisi_sas: Add timestamp for a debugfs dump + +mainline inclusion +from mainline-v5.5-rc1 +commit d28ed83b769378deefa82456f962e14a4b0afadf +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d28ed83b769378deefa82456f962e14a4b0afadf + +---------------------------------------------------------------------- + +It's useful to know when the dump occurred, so add a timestamp file for +this. + +Link: https://lore.kernel.org/r/1571926105-74636-6-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas.h +--- + drivers/scsi/hisi_sas/hisi_sas.h | 2 ++ + drivers/scsi/hisi_sas/hisi_sas_main.c | 8 ++++++++ + 2 files changed, 10 insertions(+) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 4b974461cb41..70af2568877d 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -452,6 +453,7 @@ struct hisi_hba { + struct hisi_sas_iost *debugfs_iost; + struct hisi_sas_itct *debugfs_itct; + u64 *debugfs_iost_cache; ++ u64 debugfs_timestamp; + u64 *debugfs_itct_cache; + + struct dentry *debugfs_dir; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index bb0287eed0dc..5c761b49d0de 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -3647,6 +3647,7 @@ static const struct file_operations hisi_sas_debugfs_itct_cache_fops = { + + static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + { ++ u64 *debugfs_timestamp; + struct dentry *dump_dentry; + struct dentry *dentry; + char name[256]; +@@ -3654,11 +3655,15 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + int c; + int d; + ++ debugfs_timestamp = &hisi_hba->debugfs_timestamp; + /* Create dump dir inside device dir */ + dump_dentry = debugfs_create_dir("dump", hisi_hba->debugfs_dir); + + hisi_hba->debugfs_dump_dentry = dump_dentry; + ++ debugfs_create_u64("timestamp", 0400, dump_dentry, ++ debugfs_timestamp); ++ + debugfs_create_file("global", 0400, dump_dentry, hisi_hba, + &hisi_sas_debugfs_global_fops); + +@@ -3774,7 +3779,10 @@ void hisi_sas_debugfs_work_handler(struct work_struct *work) + { + struct hisi_hba *hisi_hba = + container_of(work, struct hisi_hba, debugfs_work); ++ u64 timestamp = local_clock(); + ++ do_div(timestamp, NSEC_PER_MSEC); ++ hisi_hba->debugfs_timestamp = timestamp; + if (hisi_hba->debugfs_snapshot) + return; + hisi_hba->debugfs_snapshot = true; +-- +2.27.0 + diff --git a/patches/0350-scsi-hisi_sas-Add-debugfs-file-structure-for-CQ.patch b/patches/0350-scsi-hisi_sas-Add-debugfs-file-structure-for-CQ.patch new file mode 100644 index 00000000..fdecbf73 --- /dev/null +++ b/patches/0350-scsi-hisi_sas-Add-debugfs-file-structure-for-CQ.patch @@ -0,0 +1,141 @@ +From 824e648fc92f4498915263d534b448da71e1ac9e Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Thu, 24 Oct 2019 22:08:13 +0800 +Subject: [PATCH 032/256] scsi: hisi_sas: Add debugfs file structure for CQ + +mainline inclusion +from mainline-v5.5-rc1 +commit 35ea630b2bad4fe9f7db34624eaab3663bb2cb42 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=35ea630b2bad4fe9f7db34624eaab3663bb2cb42 + +---------------------------------------------------------------------- + +Create a file structure which was used to save the memory address and CQ +pointer for CQ at debugfs. This structure is bound to the corresponding +debugfs file, it can help callback function of debugfs file to get what it +need. + +Link: https://lore.kernel.org/r/1571926105-74636-7-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 7 ++++++- + drivers/scsi/hisi_sas/hisi_sas_main.c | 26 ++++++++++++++------------ + 2 files changed, 20 insertions(+), 13 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 70af2568877d..8692c01c8dc3 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -367,6 +367,11 @@ struct hisi_sas_hw { + int (*set_bist)(struct hisi_hba *hisi_hba, bool enable); + }; + ++struct hisi_sas_debugfs_cq { ++ struct hisi_sas_cq *cq; ++ void *complete_hdr; ++}; ++ + struct hisi_hba { + /* This must be the first element, used by SHOST_TO_SAS_HA */ + struct sas_ha_struct *p; +@@ -448,7 +453,7 @@ struct hisi_hba { + /* Put Global AXI and RAS Register into register array */ + u32 *debugfs_regs[DEBUGFS_REGS_NUM]; + u32 *debugfs_port_reg[HISI_SAS_MAX_PHYS]; +- void *debugfs_complete_hdr[HISI_SAS_MAX_QUEUES]; ++ struct hisi_sas_debugfs_cq debugfs_cq[HISI_SAS_MAX_QUEUES]; + struct hisi_sas_cmd_hdr *debugfs_cmd_hdr[HISI_SAS_MAX_QUEUES]; + struct hisi_sas_iost *debugfs_iost; + struct hisi_sas_itct *debugfs_itct; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 5c761b49d0de..f3fddd1ab961 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -2775,7 +2775,7 @@ static void hisi_sas_debugfs_snapshot_cq_reg(struct hisi_hba *hisi_hba) + int i; + + for (i = 0; i < hisi_hba->queue_count; i++) +- memcpy(hisi_hba->debugfs_complete_hdr[i], ++ memcpy(hisi_hba->debugfs_cq[i].complete_hdr, + hisi_hba->complete_hdr[i], + HISI_SAS_QUEUE_SLOTS * queue_entry_size); + } +@@ -3438,13 +3438,13 @@ static void hisi_sas_show_row_32(struct seq_file *s, int index, + seq_puts(s, "\n"); + } + +-static void hisi_sas_cq_show_slot(struct seq_file *s, int slot, void *cq_ptr) ++static void hisi_sas_cq_show_slot(struct seq_file *s, int slot, ++ struct hisi_sas_debugfs_cq *debugfs_cq) + { +- struct hisi_sas_cq *cq = cq_ptr; ++ struct hisi_sas_cq *cq = debugfs_cq->cq; + struct hisi_hba *hisi_hba = cq->hisi_hba; +- void *complete_queue = hisi_hba->debugfs_complete_hdr[cq->id]; + u64 offset = hisi_hba->hw->complete_hdr_size * slot; +- __le32 *complete_hdr = complete_queue + offset; ++ __le32 *complete_hdr = debugfs_cq->complete_hdr + offset; + + hisi_sas_show_row_32(s, slot, + hisi_hba->hw->complete_hdr_size, +@@ -3453,11 +3453,11 @@ static void hisi_sas_cq_show_slot(struct seq_file *s, int slot, void *cq_ptr) + + static int hisi_sas_debugfs_cq_show(struct seq_file *s, void *p) + { +- struct hisi_sas_cq *cq = s->private; ++ struct hisi_sas_debugfs_cq *debugfs_cq = s->private; + int slot; + + for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) { +- hisi_sas_cq_show_slot(s, slot, cq); ++ hisi_sas_cq_show_slot(s, slot, debugfs_cq); + } + return 0; + } +@@ -3684,7 +3684,7 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + snprintf(name, sizeof(name), "%d", c); + + debugfs_create_file(name, 0400, dentry, +- &hisi_hba->cq[c], ++ &hisi_hba->debugfs_cq[c], + &hisi_sas_debugfs_cq_fops); + } + +@@ -3804,7 +3804,7 @@ static void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba) + devm_kfree(dev, hisi_hba->debugfs_cmd_hdr[i]); + + for (i = 0; i < hisi_hba->queue_count; i++) +- devm_kfree(dev, hisi_hba->debugfs_complete_hdr[i]); ++ devm_kfree(dev, hisi_hba->debugfs_cq[i].complete_hdr); + + for (i = 0; i < DEBUGFS_REGS_NUM; i++) + devm_kfree(dev, hisi_hba->debugfs_regs[i]); +@@ -3885,11 +3885,13 @@ static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba) + + sz = hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS; + for (c = 0; c < hisi_hba->queue_count; c++) { +- hisi_hba->debugfs_complete_hdr[c] = +- devm_kmalloc(dev, sz, GFP_KERNEL); ++ struct hisi_sas_debugfs_cq *cq = ++ &hisi_hba->debugfs_cq[c]; + +- if (!hisi_hba->debugfs_complete_hdr[c]) ++ cq->complete_hdr = devm_kmalloc(dev, sz, GFP_KERNEL); ++ if (!cq->complete_hdr) + goto fail; ++ cq->cq = &hisi_hba->cq[c]; + } + + sz = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS; +-- +2.27.0 + diff --git a/patches/0351-scsi-hisi_sas-Add-debugfs-file-structure-for-DQ.patch b/patches/0351-scsi-hisi_sas-Add-debugfs-file-structure-for-DQ.patch new file mode 100644 index 00000000..3f5a735e --- /dev/null +++ b/patches/0351-scsi-hisi_sas-Add-debugfs-file-structure-for-DQ.patch @@ -0,0 +1,121 @@ +From 0ed108e584e31c81d328314586eb9bce51767516 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Thu, 24 Oct 2019 22:08:14 +0800 +Subject: [PATCH 033/256] scsi: hisi_sas: Add debugfs file structure for DQ + +mainline inclusion +from mainline-v5.5-rc1 +commit 1b54c4db725d875dcae645a3da74625b9e4b3bdf +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1b54c4db725d875dcae645a3da74625b9e4b3bdf + +---------------------------------------------------------------------- + +Create a file structure which was used to save the memory address and DQ +pointer for DQ at debugfs. This structure is bound to the corresponding +debugfs file, it can help callback function of debugfs file to get what it +need. + +Link: https://lore.kernel.org/r/1571926105-74636-8-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 7 ++++++- + drivers/scsi/hisi_sas/hisi_sas_main.c | 19 ++++++++++--------- + 2 files changed, 16 insertions(+), 10 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 8692c01c8dc3..95a29c345c30 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -372,6 +372,11 @@ struct hisi_sas_debugfs_cq { + void *complete_hdr; + }; + ++struct hisi_sas_debugfs_dq { ++ struct hisi_sas_dq *dq; ++ struct hisi_sas_cmd_hdr *hdr; ++}; ++ + struct hisi_hba { + /* This must be the first element, used by SHOST_TO_SAS_HA */ + struct sas_ha_struct *p; +@@ -454,7 +459,7 @@ struct hisi_hba { + u32 *debugfs_regs[DEBUGFS_REGS_NUM]; + u32 *debugfs_port_reg[HISI_SAS_MAX_PHYS]; + struct hisi_sas_debugfs_cq debugfs_cq[HISI_SAS_MAX_QUEUES]; +- struct hisi_sas_cmd_hdr *debugfs_cmd_hdr[HISI_SAS_MAX_QUEUES]; ++ struct hisi_sas_debugfs_dq debugfs_dq[HISI_SAS_MAX_QUEUES]; + struct hisi_sas_iost *debugfs_iost; + struct hisi_sas_itct *debugfs_itct; + u64 *debugfs_iost_cache; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index f3fddd1ab961..fe8c998e3e9f 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -2786,7 +2786,7 @@ static void hisi_sas_debugfs_snapshot_dq_reg(struct hisi_hba *hisi_hba) + int i; + + for (i = 0; i < hisi_hba->queue_count; i++) +- memcpy(hisi_hba->debugfs_cmd_hdr[i], ++ memcpy(hisi_hba->debugfs_dq[i].hdr, + hisi_hba->cmd_hdr[i], + HISI_SAS_QUEUE_SLOTS * queue_entry_size); + } +@@ -3477,9 +3477,8 @@ static const struct file_operations hisi_sas_debugfs_cq_fops = { + + static void hisi_sas_dq_show_slot(struct seq_file *s, int slot, void *dq_ptr) + { +- struct hisi_sas_dq *dq = dq_ptr; +- struct hisi_hba *hisi_hba = dq->hisi_hba; +- void *cmd_queue = hisi_hba->debugfs_cmd_hdr[dq->id]; ++ struct hisi_sas_debugfs_dq *debugfs_dq = dq_ptr; ++ void *cmd_queue = debugfs_dq->hdr; + u64 offset = sizeof(struct hisi_sas_cmd_hdr) * slot; + __le32 *cmd_hdr = cmd_queue + offset; + +@@ -3695,7 +3694,7 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + snprintf(name, sizeof(name), "%d", d); + + debugfs_create_file(name, 0400, dentry, +- &hisi_hba->dq[d], ++ &hisi_hba->debugfs_dq[d], + &hisi_sas_debugfs_dq_fops); + } + +@@ -3801,7 +3800,7 @@ static void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba) + devm_kfree(dev, hisi_hba->debugfs_iost); + + for (i = 0; i < hisi_hba->queue_count; i++) +- devm_kfree(dev, hisi_hba->debugfs_cmd_hdr[i]); ++ devm_kfree(dev, hisi_hba->debugfs_dq[i].hdr); + + for (i = 0; i < hisi_hba->queue_count; i++) + devm_kfree(dev, hisi_hba->debugfs_cq[i].complete_hdr); +@@ -3896,11 +3895,13 @@ static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba) + + sz = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS; + for (d = 0; d < hisi_hba->queue_count; d++) { +- hisi_hba->debugfs_cmd_hdr[d] = +- devm_kmalloc(dev, sz, GFP_KERNEL); ++ struct hisi_sas_debugfs_dq *dq = ++ &hisi_hba->debugfs_dq[d]; + +- if (!hisi_hba->debugfs_cmd_hdr[d]) ++ dq->hdr = devm_kmalloc(dev, sz, GFP_KERNEL); ++ if (!dq->hdr) + goto fail; ++ dq->dq = &hisi_hba->dq[d]; + } + + sz = HISI_SAS_MAX_COMMANDS * sizeof(struct hisi_sas_iost); +-- +2.27.0 + diff --git a/patches/0352-scsi-hisi_sas-Add-debugfs-file-structure-for-registe.patch b/patches/0352-scsi-hisi_sas-Add-debugfs-file-structure-for-registe.patch new file mode 100644 index 00000000..5926621d --- /dev/null +++ b/patches/0352-scsi-hisi_sas-Add-debugfs-file-structure-for-registe.patch @@ -0,0 +1,224 @@ +From 83bde9fb72007472e0838dd10576d0849cafdaa6 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Thu, 24 Oct 2019 22:08:15 +0800 +Subject: [PATCH 034/256] scsi: hisi_sas: Add debugfs file structure for + registers + +mainline inclusion +from mainline-v5.5-rc1 +commit c61163981076476e0bcf2d453dcddf8db605f115 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c61163981076476e0bcf2d453dcddf8db605f115 + +---------------------------------------------------------------------- + +Create a file structure which was used to save the memory address and +hisi_hba pointer for REGS at debugfs. This structure is bound to the +corresponding debugfs file, it can help callback function of debugfs file +to get what it need. + +Link: https://lore.kernel.org/r/1571926105-74636-9-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 7 ++- + drivers/scsi/hisi_sas/hisi_sas_main.c | 62 +++++++++++++-------------- + 2 files changed, 35 insertions(+), 34 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 95a29c345c30..fd8a128cf4d3 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -377,6 +377,11 @@ struct hisi_sas_debugfs_dq { + struct hisi_sas_cmd_hdr *hdr; + }; + ++struct hisi_sas_debugfs_regs { ++ struct hisi_hba *hisi_hba; ++ u32 *data; ++}; ++ + struct hisi_hba { + /* This must be the first element, used by SHOST_TO_SAS_HA */ + struct sas_ha_struct *p; +@@ -456,7 +461,7 @@ struct hisi_hba { + + /* debugfs memories */ + /* Put Global AXI and RAS Register into register array */ +- u32 *debugfs_regs[DEBUGFS_REGS_NUM]; ++ struct hisi_sas_debugfs_regs debugfs_regs[DEBUGFS_REGS_NUM]; + u32 *debugfs_port_reg[HISI_SAS_MAX_PHYS]; + struct hisi_sas_debugfs_cq debugfs_cq[HISI_SAS_MAX_QUEUES]; + struct hisi_sas_debugfs_dq debugfs_dq[HISI_SAS_MAX_QUEUES]; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index fe8c998e3e9f..504c83e4f620 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -2811,7 +2811,7 @@ static void hisi_sas_debugfs_snapshot_port_reg(struct hisi_hba *hisi_hba) + + static void hisi_sas_debugfs_snapshot_global_reg(struct hisi_hba *hisi_hba) + { +- u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_GLOBAL]; ++ u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_GLOBAL].data; + const struct hisi_sas_hw *hw = hisi_hba->hw; + const struct hisi_sas_debugfs_reg *global = + hw->debugfs_reg_array[DEBUGFS_GLOBAL]; +@@ -2823,7 +2823,7 @@ static void hisi_sas_debugfs_snapshot_global_reg(struct hisi_hba *hisi_hba) + + static void hisi_sas_debugfs_snapshot_axi_reg(struct hisi_hba *hisi_hba) + { +- u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_AXI]; ++ u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_AXI].data; + const struct hisi_sas_hw *hw = hisi_hba->hw; + const struct hisi_sas_debugfs_reg *axi = + hw->debugfs_reg_array[DEBUGFS_AXI]; +@@ -2836,7 +2836,7 @@ static void hisi_sas_debugfs_snapshot_axi_reg(struct hisi_hba *hisi_hba) + + static void hisi_sas_debugfs_snapshot_ras_reg(struct hisi_hba *hisi_hba) + { +- u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_RAS]; ++ u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_RAS].data; + const struct hisi_sas_hw *hw = hisi_hba->hw; + const struct hisi_sas_debugfs_reg *ras = + hw->debugfs_reg_array[DEBUGFS_RAS]; +@@ -2920,11 +2920,12 @@ static void hisi_sas_debugfs_print_reg(u32 *regs_val, const void *ptr, + + static int hisi_sas_debugfs_global_show(struct seq_file *s, void *p) + { +- struct hisi_hba *hisi_hba = s->private; ++ struct hisi_sas_debugfs_regs *global = s->private; ++ struct hisi_hba *hisi_hba = global->hisi_hba; + const struct hisi_sas_hw *hw = hisi_hba->hw; + const void *reg_global = hw->debugfs_reg_array[DEBUGFS_GLOBAL]; + +- hisi_sas_debugfs_print_reg(hisi_hba->debugfs_regs[DEBUGFS_GLOBAL], ++ hisi_sas_debugfs_print_reg(global->data, + reg_global, s); + + return 0; +@@ -3328,11 +3329,12 @@ static const struct file_operations hisi_sas_debugfs_bist_enable_ops = { + + static int hisi_sas_debugfs_axi_show(struct seq_file *s, void *p) + { +- struct hisi_hba *hisi_hba = s->private; ++ struct hisi_sas_debugfs_regs *ras = s->private; ++ struct hisi_hba *hisi_hba = ras->hisi_hba; + const struct hisi_sas_hw *hw = hisi_hba->hw; + const void *reg_axi = hw->debugfs_reg_array[DEBUGFS_AXI]; + +- hisi_sas_debugfs_print_reg(hisi_hba->debugfs_regs[DEBUGFS_AXI], ++ hisi_sas_debugfs_print_reg(ras->data, + reg_axi, s); + + return 0; +@@ -3354,11 +3356,12 @@ static const struct file_operations hisi_sas_debugfs_axi_fops = { + + static int hisi_sas_debugfs_ras_show(struct seq_file *s, void *p) + { +- struct hisi_hba *hisi_hba = s->private; ++ struct hisi_sas_debugfs_regs *ras = s->private; ++ struct hisi_hba *hisi_hba = ras->hisi_hba; + const struct hisi_sas_hw *hw = hisi_hba->hw; + const void *reg_ras = hw->debugfs_reg_array[DEBUGFS_RAS]; + +- hisi_sas_debugfs_print_reg(hisi_hba->debugfs_regs[DEBUGFS_RAS], ++ hisi_sas_debugfs_print_reg(ras->data, + reg_ras, s); + + return 0; +@@ -3663,7 +3666,8 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + debugfs_create_u64("timestamp", 0400, dump_dentry, + debugfs_timestamp); + +- debugfs_create_file("global", 0400, dump_dentry, hisi_hba, ++ debugfs_create_file("global", 0400, dump_dentry, ++ &hisi_hba->debugfs_regs[DEBUGFS_GLOBAL], + &hisi_sas_debugfs_global_fops); + + /* Create port dir and files */ +@@ -3710,10 +3714,12 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + debugfs_create_file("itct_cache", 0400, dump_dentry, hisi_hba, + &hisi_sas_debugfs_itct_cache_fops); + +- debugfs_create_file("axi", 0400, dump_dentry, hisi_hba, ++ debugfs_create_file("axi", 0400, dump_dentry, ++ &hisi_hba->debugfs_regs[DEBUGFS_AXI], + &hisi_sas_debugfs_axi_fops); + +- debugfs_create_file("ras", 0400, dump_dentry, hisi_hba, ++ debugfs_create_file("ras", 0400, dump_dentry, ++ &hisi_hba->debugfs_regs[DEBUGFS_RAS], + &hisi_sas_debugfs_ras_fops); + + return; +@@ -3806,7 +3812,7 @@ static void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba) + devm_kfree(dev, hisi_hba->debugfs_cq[i].complete_hdr); + + for (i = 0; i < DEBUGFS_REGS_NUM; i++) +- devm_kfree(dev, hisi_hba->debugfs_regs[i]); ++ devm_kfree(dev, hisi_hba->debugfs_regs[i].data); + + for (i = 0; i < hisi_hba->n_phy; i++) + devm_kfree(dev, hisi_hba->debugfs_port_reg[i]); +@@ -3816,7 +3822,7 @@ static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba) + { + const struct hisi_sas_hw *hw = hisi_hba->hw; + struct device *dev = hisi_hba->dev; +- int p, c, d; ++ int p, c, d, r; + size_t sz; + + /* create bist structures */ +@@ -3852,12 +3858,16 @@ static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba) + hisi_hba, &hisi_sas_debugfs_bist_enable_ops)) + goto fail; + +- sz = hw->debugfs_reg_array[DEBUGFS_GLOBAL]->count * 4; +- hisi_hba->debugfs_regs[DEBUGFS_GLOBAL] = +- devm_kmalloc(dev, sz, GFP_KERNEL); ++ for (r = 0; r < DEBUGFS_REGS_NUM; r++) { ++ struct hisi_sas_debugfs_regs *regs = ++ &hisi_hba->debugfs_regs[r]; + +- if (!hisi_hba->debugfs_regs[DEBUGFS_GLOBAL]) +- goto fail; ++ sz = hw->debugfs_reg_array[r]->count * 4; ++ regs->data = devm_kmalloc(dev, sz, GFP_KERNEL); ++ if (!regs->data) ++ goto fail; ++ regs->hisi_hba = hisi_hba; ++ } + + sz = hw->debugfs_reg_port->count * 4; + for (p = 0; p < hisi_hba->n_phy; p++) { +@@ -3868,20 +3878,6 @@ static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba) + goto fail; + } + +- sz = hw->debugfs_reg_array[DEBUGFS_AXI]->count * 4; +- hisi_hba->debugfs_regs[DEBUGFS_AXI] = +- devm_kmalloc(dev, sz, GFP_KERNEL); +- +- if (!hisi_hba->debugfs_regs[DEBUGFS_AXI]) +- goto fail; +- +- sz = hw->debugfs_reg_array[DEBUGFS_RAS]->count * 4; +- hisi_hba->debugfs_regs[DEBUGFS_RAS] = +- devm_kmalloc(dev, sz, GFP_KERNEL); +- +- if (!hisi_hba->debugfs_regs[DEBUGFS_RAS]) +- goto fail; +- + sz = hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS; + for (c = 0; c < hisi_hba->queue_count; c++) { + struct hisi_sas_debugfs_cq *cq = +-- +2.27.0 + diff --git a/patches/0353-scsi-hisi_sas-Add-debugfs-file-structure-for-port.patch b/patches/0353-scsi-hisi_sas-Add-debugfs-file-structure-for-port.patch new file mode 100644 index 00000000..f57b3147 --- /dev/null +++ b/patches/0353-scsi-hisi_sas-Add-debugfs-file-structure-for-port.patch @@ -0,0 +1,126 @@ +From 4b0c14a897505a38214d3a5bda2b9ce2629e0e82 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Thu, 24 Oct 2019 22:08:16 +0800 +Subject: [PATCH 035/256] scsi: hisi_sas: Add debugfs file structure for port + +mainline inclusion +from mainline-v5.5-rc1 +commit 1f66e1fd26bddb4c9275b61934dbaaf4b0b0bd79 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1f66e1fd26bddb4c9275b61934dbaaf4b0b0bd79 + +---------------------------------------------------------------------- + +Create a file structure which was used to save the memory address and phy +pointer for port at debugfs. This structure is bound to the corresponding +debugfs file, it can help callback function of debugfs file to get what it +need. + +Link: https://lore.kernel.org/r/1571926105-74636-10-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 7 ++++++- + drivers/scsi/hisi_sas/hisi_sas_main.c | 20 +++++++++++--------- + 2 files changed, 17 insertions(+), 10 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index fd8a128cf4d3..646ab7d6ad05 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -382,6 +382,11 @@ struct hisi_sas_debugfs_regs { + u32 *data; + }; + ++struct hisi_sas_debugfs_port { ++ struct hisi_sas_phy *phy; ++ u32 *data; ++}; ++ + struct hisi_hba { + /* This must be the first element, used by SHOST_TO_SAS_HA */ + struct sas_ha_struct *p; +@@ -462,7 +467,7 @@ struct hisi_hba { + /* debugfs memories */ + /* Put Global AXI and RAS Register into register array */ + struct hisi_sas_debugfs_regs debugfs_regs[DEBUGFS_REGS_NUM]; +- u32 *debugfs_port_reg[HISI_SAS_MAX_PHYS]; ++ struct hisi_sas_debugfs_port debugfs_port_reg[HISI_SAS_MAX_PHYS]; + struct hisi_sas_debugfs_cq debugfs_cq[HISI_SAS_MAX_QUEUES]; + struct hisi_sas_debugfs_dq debugfs_dq[HISI_SAS_MAX_QUEUES]; + struct hisi_sas_iost *debugfs_iost; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 504c83e4f620..637308372ec3 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -2800,7 +2800,7 @@ static void hisi_sas_debugfs_snapshot_port_reg(struct hisi_hba *hisi_hba) + u32 *databuf; + + for (phy_cnt = 0; phy_cnt < hisi_hba->n_phy; phy_cnt++) { +- databuf = (u32 *)hisi_hba->debugfs_port_reg[phy_cnt]; ++ databuf = hisi_hba->debugfs_port_reg[phy_cnt].data; + for (i = 0; i < port->count; i++, databuf++) { + offset = port->base_off + 4 * i; + *databuf = port->read_port_reg(hisi_hba, phy_cnt, +@@ -3384,13 +3384,13 @@ static const struct file_operations hisi_sas_debugfs_ras_fops = { + + static int hisi_sas_debugfs_port_show(struct seq_file *s, void *p) + { +- struct hisi_sas_phy *phy = s->private; ++ struct hisi_sas_debugfs_port *port = s->private; ++ struct hisi_sas_phy *phy = port->phy; + struct hisi_hba *hisi_hba = phy->hisi_hba; + const struct hisi_sas_hw *hw = hisi_hba->hw; + const struct hisi_sas_debugfs_reg *reg_port = hw->debugfs_reg_port; +- u32 *databuf = hisi_hba->debugfs_port_reg[phy->sas_phy.id]; + +- hisi_sas_debugfs_print_reg(databuf, reg_port, s); ++ hisi_sas_debugfs_print_reg(port->data, reg_port, s); + + return 0; + } +@@ -3676,7 +3676,7 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + for (p = 0; p < hisi_hba->n_phy; p++) { + snprintf(name, sizeof(name), "%d", p); + debugfs_create_file(name, 0400, dentry, +- &hisi_hba->phy[p], ++ &hisi_hba->debugfs_port_reg[p], + &hisi_sas_debugfs_port_fops); + } + +@@ -3815,7 +3815,7 @@ static void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba) + devm_kfree(dev, hisi_hba->debugfs_regs[i].data); + + for (i = 0; i < hisi_hba->n_phy; i++) +- devm_kfree(dev, hisi_hba->debugfs_port_reg[i]); ++ devm_kfree(dev, hisi_hba->debugfs_port_reg[i].data); + } + + static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba) +@@ -3871,11 +3871,13 @@ static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba) + + sz = hw->debugfs_reg_port->count * 4; + for (p = 0; p < hisi_hba->n_phy; p++) { +- hisi_hba->debugfs_port_reg[p] = +- devm_kmalloc(dev, sz, GFP_KERNEL); ++ struct hisi_sas_debugfs_port *port = ++ &hisi_hba->debugfs_port_reg[p]; + +- if (!hisi_hba->debugfs_port_reg[p]) ++ port->data = devm_kmalloc(dev, sz, GFP_KERNEL); ++ if (!port->data) + goto fail; ++ port->phy = &hisi_hba->phy[p]; + } + + sz = hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS; +-- +2.27.0 + diff --git a/patches/0354-scsi-hisi_sas-Add-debugfs-file-structure-for-IOST.patch b/patches/0354-scsi-hisi_sas-Add-debugfs-file-structure-for-IOST.patch new file mode 100644 index 00000000..fd396502 --- /dev/null +++ b/patches/0354-scsi-hisi_sas-Add-debugfs-file-structure-for-IOST.patch @@ -0,0 +1,119 @@ +From e00c5ac44e259d43bb4cd815b95985e9966d66df Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Thu, 24 Oct 2019 22:08:17 +0800 +Subject: [PATCH 036/256] scsi: hisi_sas: Add debugfs file structure for IOST + +mainline inclusion +from mainline-v5.5-rc1 +commit e15f2e2dff5b809dce923839f21362d6b0d06b1e +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e15f2e2dff5b809dce923839f21362d6b0d06b1e + +---------------------------------------------------------------------- + +Create a file structure which was used to save the memory address for IOST +at debugfs. This structure is bound to the corresponding debugfs file, it +can help callback function of debugfs file to get what it needs. + +Link: https://lore.kernel.org/r/1571926105-74636-11-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas.h | 6 +++++- + drivers/scsi/hisi_sas/hisi_sas_main.c | 21 +++++++++++---------- + 2 files changed, 16 insertions(+), 11 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 646ab7d6ad05..efedf889b91c 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -387,6 +387,10 @@ struct hisi_sas_debugfs_port { + u32 *data; + }; + ++struct hisi_sas_debugfs_iost { ++ struct hisi_sas_iost *iost; ++}; ++ + struct hisi_hba { + /* This must be the first element, used by SHOST_TO_SAS_HA */ + struct sas_ha_struct *p; +@@ -470,7 +474,7 @@ struct hisi_hba { + struct hisi_sas_debugfs_port debugfs_port_reg[HISI_SAS_MAX_PHYS]; + struct hisi_sas_debugfs_cq debugfs_cq[HISI_SAS_MAX_QUEUES]; + struct hisi_sas_debugfs_dq debugfs_dq[HISI_SAS_MAX_QUEUES]; +- struct hisi_sas_iost *debugfs_iost; ++ struct hisi_sas_debugfs_iost debugfs_iost; + struct hisi_sas_itct *debugfs_itct; + u64 *debugfs_iost_cache; + u64 debugfs_timestamp; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 637308372ec3..4edecfc3e7b7 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -2869,7 +2869,7 @@ static void hisi_sas_debugfs_snapshot_iost_reg(struct hisi_hba *hisi_hba) + { + int max_command_entries = HISI_SAS_MAX_COMMANDS; + void *cachebuf = hisi_hba->debugfs_iost_cache; +- void *databuf = hisi_hba->debugfs_iost; ++ void *databuf = hisi_hba->debugfs_iost.iost; + struct hisi_sas_iost *iost; + int i; + +@@ -3513,14 +3513,14 @@ static const struct file_operations hisi_sas_debugfs_dq_fops = { + + static int hisi_sas_debugfs_iost_show(struct seq_file *s, void *p) + { +- struct hisi_hba *hisi_hba = s->private; +- struct hisi_sas_iost *debugfs_iost = hisi_hba->debugfs_iost; ++ struct hisi_sas_debugfs_iost *debugfs_iost = s->private; ++ struct hisi_sas_iost *iost = debugfs_iost->iost; + int i, max_command_entries = HISI_SAS_MAX_COMMANDS; + +- for (i = 0; i < max_command_entries; i++, debugfs_iost++) { +- __le64 *iost = &debugfs_iost->qw0; ++ for (i = 0; i < max_command_entries; i++, iost++) { ++ __le64 *data = &iost->qw0; + +- hisi_sas_show_row_64(s, i, sizeof(*debugfs_iost), iost); ++ hisi_sas_show_row_64(s, i, sizeof(*iost), data); + } + + return 0; +@@ -3702,7 +3702,8 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + &hisi_sas_debugfs_dq_fops); + } + +- debugfs_create_file("iost", 0400, dump_dentry, hisi_hba, ++ debugfs_create_file("iost", 0400, dump_dentry, ++ &hisi_hba->debugfs_iost, + &hisi_sas_debugfs_iost_fops); + + debugfs_create_file("iost_cache", 0400, dump_dentry, hisi_hba, +@@ -3803,7 +3804,7 @@ static void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba) + + devm_kfree(dev, hisi_hba->debugfs_iost_cache); + devm_kfree(dev, hisi_hba->debugfs_itct_cache); +- devm_kfree(dev, hisi_hba->debugfs_iost); ++ devm_kfree(dev, hisi_hba->debugfs_iost.iost); + + for (i = 0; i < hisi_hba->queue_count; i++) + devm_kfree(dev, hisi_hba->debugfs_dq[i].hdr); +@@ -3904,8 +3905,8 @@ static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba) + + sz = HISI_SAS_MAX_COMMANDS * sizeof(struct hisi_sas_iost); + +- hisi_hba->debugfs_iost = devm_kmalloc(dev, sz, GFP_KERNEL); +- if (!hisi_hba->debugfs_iost) ++ hisi_hba->debugfs_iost.iost = devm_kmalloc(dev, sz, GFP_KERNEL); ++ if (!hisi_hba->debugfs_iost.iost) + goto fail; + + sz = HISI_SAS_IOST_ITCT_CACHE_NUM * +-- +2.27.0 + diff --git a/patches/0355-scsi-hisi_sas-Add-debugfs-file-structure-for-ITCT.patch b/patches/0355-scsi-hisi_sas-Add-debugfs-file-structure-for-ITCT.patch new file mode 100644 index 00000000..7b39ec77 --- /dev/null +++ b/patches/0355-scsi-hisi_sas-Add-debugfs-file-structure-for-ITCT.patch @@ -0,0 +1,132 @@ +From ba5cccaa8564d86ff088157755158456395dd6d9 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Thu, 24 Oct 2019 22:08:18 +0800 +Subject: [PATCH 037/256] scsi: hisi_sas: Add debugfs file structure for ITCT + +mainline inclusion +from mainline-v5.5-rc1 +commit 0161d55f23a1e020e5e6892177caf92a61e5c161 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0161d55f23a1e020e5e6892177caf92a61e5c161 + +---------------------------------------------------------------------- + +Create a file structure which was used to save the memory address for ITCT +at debugfs. This structure is bound to the corresponding debugfs file, it +can help callback function of debugfs file to get what it needs. + +Link: https://lore.kernel.org/r/1571926105-74636-12-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 6 +++++- + drivers/scsi/hisi_sas/hisi_sas_main.c | 25 +++++++++++++------------ + 2 files changed, 18 insertions(+), 13 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index efedf889b91c..97ca00c2ece4 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -391,6 +391,10 @@ struct hisi_sas_debugfs_iost { + struct hisi_sas_iost *iost; + }; + ++struct hisi_sas_debugfs_itct { ++ struct hisi_sas_itct *itct; ++}; ++ + struct hisi_hba { + /* This must be the first element, used by SHOST_TO_SAS_HA */ + struct sas_ha_struct *p; +@@ -475,7 +479,7 @@ struct hisi_hba { + struct hisi_sas_debugfs_cq debugfs_cq[HISI_SAS_MAX_QUEUES]; + struct hisi_sas_debugfs_dq debugfs_dq[HISI_SAS_MAX_QUEUES]; + struct hisi_sas_debugfs_iost debugfs_iost; +- struct hisi_sas_itct *debugfs_itct; ++ struct hisi_sas_debugfs_itct debugfs_itct; + u64 *debugfs_iost_cache; + u64 debugfs_timestamp; + u64 *debugfs_itct_cache; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 4edecfc3e7b7..69efd0639964 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1630,7 +1630,7 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba) + if (test_and_set_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) + return -EPERM; + +- if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct) ++ if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct.itct) + hisi_hba->hw->debugfs_work_handler(&hisi_hba->debugfs_work); + + dev_info(dev, "controller resetting...\n"); +@@ -2131,7 +2131,7 @@ _hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, + + /* Internal abort timed out */ + if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { +- if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct) ++ if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct.itct) + queue_work(hisi_hba->wq, &hisi_hba->debugfs_work); + + if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { +@@ -2850,7 +2850,7 @@ static void hisi_sas_debugfs_snapshot_ras_reg(struct hisi_hba *hisi_hba) + static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba) + { + void *cachebuf = hisi_hba->debugfs_itct_cache; +- void *databuf = hisi_hba->debugfs_itct; ++ void *databuf = hisi_hba->debugfs_itct.itct; + struct hisi_sas_itct *itct; + int i; + +@@ -3582,13 +3582,13 @@ static const struct file_operations hisi_sas_debugfs_iost_cache_fops = { + static int hisi_sas_debugfs_itct_show(struct seq_file *s, void *p) + { + int i; +- struct hisi_hba *hisi_hba = s->private; +- struct hisi_sas_itct *debugfs_itct = hisi_hba->debugfs_itct; ++ struct hisi_sas_debugfs_itct *debugfs_itct = s->private; ++ struct hisi_sas_itct *itct = debugfs_itct->itct; + +- for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, debugfs_itct++) { +- __le64 *itct = &debugfs_itct->qw0; ++ for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) { ++ __le64 *data = &itct->qw0; + +- hisi_sas_show_row_64(s, i, sizeof(*debugfs_itct), itct); ++ hisi_sas_show_row_64(s, i, sizeof(*itct), data); + } + + return 0; +@@ -3709,8 +3709,9 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + debugfs_create_file("iost_cache", 0400, dump_dentry, hisi_hba, + &hisi_sas_debugfs_iost_cache_fops); + +- debugfs_create_file("itct", 0400, dump_dentry, hisi_hba, +- &hisi_sas_debugfs_itct_fops); ++ debugfs_create_file("itct", 0400, dump_dentry, ++ &hisi_hba->debugfs_itct, ++ &hisi_sas_debugfs_itct_fops); + + debugfs_create_file("itct_cache", 0400, dump_dentry, hisi_hba, + &hisi_sas_debugfs_itct_cache_fops); +@@ -3926,8 +3927,8 @@ static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba) + /* New memory allocation must be locate before itct */ + sz = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct); + +- hisi_hba->debugfs_itct = devm_kmalloc(dev, sz, GFP_KERNEL); +- if (!hisi_hba->debugfs_itct) ++ hisi_hba->debugfs_itct.itct = devm_kmalloc(dev, sz, GFP_KERNEL); ++ if (!hisi_hba->debugfs_itct.itct) + goto fail; + + return 0; +-- +2.27.0 + diff --git a/patches/0356-scsi-hisi_sas-Add-debugfs-file-structure-for-IOST-ca.patch b/patches/0356-scsi-hisi_sas-Add-debugfs-file-structure-for-IOST-ca.patch new file mode 100644 index 00000000..13668454 --- /dev/null +++ b/patches/0356-scsi-hisi_sas-Add-debugfs-file-structure-for-IOST-ca.patch @@ -0,0 +1,113 @@ +From d320d4bf2adc3fa272fe98290e94ab9931ab5a0f Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Thu, 24 Oct 2019 22:08:19 +0800 +Subject: [PATCH 038/256] scsi: hisi_sas: Add debugfs file structure for IOST + cache + +mainline inclusion +from mainline-v5.5-rc1 +commit b714dd8f36dc609dd4b0078cf5563978134838ed +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b714dd8f36dc609dd4b0078cf5563978134838ed + +---------------------------------------------------------------------- + +Create a file structure which was used to save the memory address for IOST +cache at debugfs. This structure is bound to the corresponding debugfs +file, it can help callback function of debugfs file to get what it needs. + +Link: https://lore.kernel.org/r/1571926105-74636-13-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas.h | 6 +++++- + drivers/scsi/hisi_sas/hisi_sas_main.c | 16 ++++++++-------- + 2 files changed, 13 insertions(+), 9 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 97ca00c2ece4..729eb47f1d5d 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -395,6 +395,10 @@ struct hisi_sas_debugfs_itct { + struct hisi_sas_itct *itct; + }; + ++struct hisi_sas_debugfs_iost_cache { ++ struct hisi_sas_iost_itct_cache *cache; ++}; ++ + struct hisi_hba { + /* This must be the first element, used by SHOST_TO_SAS_HA */ + struct sas_ha_struct *p; +@@ -480,8 +484,8 @@ struct hisi_hba { + struct hisi_sas_debugfs_dq debugfs_dq[HISI_SAS_MAX_QUEUES]; + struct hisi_sas_debugfs_iost debugfs_iost; + struct hisi_sas_debugfs_itct debugfs_itct; +- u64 *debugfs_iost_cache; + u64 debugfs_timestamp; ++ struct hisi_sas_debugfs_iost_cache debugfs_iost_cache; + u64 *debugfs_itct_cache; + + struct dentry *debugfs_dir; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 69efd0639964..30f6cd0fc190 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -2868,7 +2868,7 @@ static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba) + static void hisi_sas_debugfs_snapshot_iost_reg(struct hisi_hba *hisi_hba) + { + int max_command_entries = HISI_SAS_MAX_COMMANDS; +- void *cachebuf = hisi_hba->debugfs_iost_cache; ++ void *cachebuf = hisi_hba->debugfs_iost_cache.cache; + void *databuf = hisi_hba->debugfs_iost.iost; + struct hisi_sas_iost *iost; + int i; +@@ -3541,9 +3541,8 @@ static const struct file_operations hisi_sas_debugfs_iost_fops = { + + static int hisi_sas_debugfs_iost_cache_show(struct seq_file *s, void *p) + { +- struct hisi_hba *hisi_hba = s->private; +- struct hisi_sas_iost_itct_cache *iost_cache = +- (struct hisi_sas_iost_itct_cache *)hisi_hba->debugfs_iost_cache; ++ struct hisi_sas_debugfs_iost_cache *debugfs_iost_cache = s->private; ++ struct hisi_sas_iost_itct_cache *iost_cache = debugfs_iost_cache->cache; + u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4; + int i, tab_idx; + __le64 *iost; +@@ -3706,7 +3705,8 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + &hisi_hba->debugfs_iost, + &hisi_sas_debugfs_iost_fops); + +- debugfs_create_file("iost_cache", 0400, dump_dentry, hisi_hba, ++ debugfs_create_file("iost_cache", 0400, dump_dentry, ++ &hisi_hba->debugfs_iost_cache, + &hisi_sas_debugfs_iost_cache_fops); + + debugfs_create_file("itct", 0400, dump_dentry, +@@ -3803,7 +3803,7 @@ static void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba) + struct device *dev = hisi_hba->dev; + int i; + +- devm_kfree(dev, hisi_hba->debugfs_iost_cache); ++ devm_kfree(dev, hisi_hba->debugfs_iost_cache.cache); + devm_kfree(dev, hisi_hba->debugfs_itct_cache); + devm_kfree(dev, hisi_hba->debugfs_iost.iost); + +@@ -3913,8 +3913,8 @@ static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba) + sz = HISI_SAS_IOST_ITCT_CACHE_NUM * + sizeof(struct hisi_sas_iost_itct_cache); + +- hisi_hba->debugfs_iost_cache = devm_kmalloc(dev, sz, GFP_KERNEL); +- if (!hisi_hba->debugfs_iost_cache) ++ hisi_hba->debugfs_iost_cache.cache = devm_kmalloc(dev, sz, GFP_KERNEL); ++ if (!hisi_hba->debugfs_iost_cache.cache) + goto fail; + + sz = HISI_SAS_IOST_ITCT_CACHE_NUM * +-- +2.27.0 + diff --git a/patches/0357-scsi-hisi_sas-Add-debugfs-file-structure-for-ITCT-ca.patch b/patches/0357-scsi-hisi_sas-Add-debugfs-file-structure-for-ITCT-ca.patch new file mode 100644 index 00000000..122b6057 --- /dev/null +++ b/patches/0357-scsi-hisi_sas-Add-debugfs-file-structure-for-ITCT-ca.patch @@ -0,0 +1,112 @@ +From a6081d5c6051b13538647a658f0bba41b9c692c7 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Thu, 24 Oct 2019 22:08:20 +0800 +Subject: [PATCH 039/256] scsi: hisi_sas: Add debugfs file structure for ITCT + cache + +mainline inclusion +from mainline-v5.5-rc1 +commit 357e4fc7a933ed5bfbf1eb2fad9c198afe6a11e1 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=357e4fc7a933ed5bfbf1eb2fad9c198afe6a11e1 + +---------------------------------------------------------------------- + +Create a file structure which was used to save the memory address for +ITCT cache at debugfs. This structure is bound to the corresponding debugfs +file, it can help callback function of debugfs file to get what it needs. + +Link: https://lore.kernel.org/r/1571926105-74636-14-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas.h | 6 +++++- + drivers/scsi/hisi_sas/hisi_sas_main.c | 16 ++++++++-------- + 2 files changed, 13 insertions(+), 9 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 729eb47f1d5d..505d74780eab 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -399,6 +399,10 @@ struct hisi_sas_debugfs_iost_cache { + struct hisi_sas_iost_itct_cache *cache; + }; + ++struct hisi_sas_debugfs_itct_cache { ++ struct hisi_sas_iost_itct_cache *cache; ++}; ++ + struct hisi_hba { + /* This must be the first element, used by SHOST_TO_SAS_HA */ + struct sas_ha_struct *p; +@@ -486,7 +490,7 @@ struct hisi_hba { + struct hisi_sas_debugfs_itct debugfs_itct; + u64 debugfs_timestamp; + struct hisi_sas_debugfs_iost_cache debugfs_iost_cache; +- u64 *debugfs_itct_cache; ++ struct hisi_sas_debugfs_itct_cache debugfs_itct_cache; + + struct dentry *debugfs_dir; + struct dentry *debugfs_dump_dentry; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 30f6cd0fc190..e218a95cfd38 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -2849,7 +2849,7 @@ static void hisi_sas_debugfs_snapshot_ras_reg(struct hisi_hba *hisi_hba) + + static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba) + { +- void *cachebuf = hisi_hba->debugfs_itct_cache; ++ void *cachebuf = hisi_hba->debugfs_itct_cache.cache; + void *databuf = hisi_hba->debugfs_itct.itct; + struct hisi_sas_itct *itct; + int i; +@@ -3608,9 +3608,8 @@ static const struct file_operations hisi_sas_debugfs_itct_fops = { + + static int hisi_sas_debugfs_itct_cache_show(struct seq_file *s, void *p) + { +- struct hisi_hba *hisi_hba = s->private; +- struct hisi_sas_iost_itct_cache *itct_cache = +- (struct hisi_sas_iost_itct_cache *)hisi_hba->debugfs_itct_cache; ++ struct hisi_sas_debugfs_itct_cache *debugfs_itct_cache = s->private; ++ struct hisi_sas_iost_itct_cache *itct_cache = debugfs_itct_cache->cache; + u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4; + int i, tab_idx; + __le64 *itct; +@@ -3713,7 +3712,8 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + &hisi_hba->debugfs_itct, + &hisi_sas_debugfs_itct_fops); + +- debugfs_create_file("itct_cache", 0400, dump_dentry, hisi_hba, ++ debugfs_create_file("itct_cache", 0400, dump_dentry, ++ &hisi_hba->debugfs_itct_cache, + &hisi_sas_debugfs_itct_cache_fops); + + debugfs_create_file("axi", 0400, dump_dentry, +@@ -3804,7 +3804,7 @@ static void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba) + int i; + + devm_kfree(dev, hisi_hba->debugfs_iost_cache.cache); +- devm_kfree(dev, hisi_hba->debugfs_itct_cache); ++ devm_kfree(dev, hisi_hba->debugfs_itct_cache.cache); + devm_kfree(dev, hisi_hba->debugfs_iost.iost); + + for (i = 0; i < hisi_hba->queue_count; i++) +@@ -3920,8 +3920,8 @@ static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba) + sz = HISI_SAS_IOST_ITCT_CACHE_NUM * + sizeof(struct hisi_sas_iost_itct_cache); + +- hisi_hba->debugfs_itct_cache = devm_kmalloc(dev, sz, GFP_KERNEL); +- if (!hisi_hba->debugfs_itct_cache) ++ hisi_hba->debugfs_itct_cache.cache = devm_kmalloc(dev, sz, GFP_KERNEL); ++ if (!hisi_hba->debugfs_itct_cache.cache) + goto fail; + + /* New memory allocation must be locate before itct */ +-- +2.27.0 + diff --git a/patches/0358-scsi-hisi_sas-Allocate-memory-for-multiple-dumps-of-.patch b/patches/0358-scsi-hisi_sas-Allocate-memory-for-multiple-dumps-of-.patch new file mode 100644 index 00000000..f5f4ab86 --- /dev/null +++ b/patches/0358-scsi-hisi_sas-Allocate-memory-for-multiple-dumps-of-.patch @@ -0,0 +1,403 @@ +From ee919d66c52843676e7c4e09879de08614957b2a Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Thu, 24 Oct 2019 22:08:21 +0800 +Subject: [PATCH 040/256] scsi: hisi_sas: Allocate memory for multiple dumps of + debugfs + +mainline inclusion +from mainline-v5.5-rc1 +commit a70e33eae363e6f3e2ad9498daaccd231790f7f5 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a70e33eae363e6f3e2ad9498daaccd231790f7f5 + +---------------------------------------------------------------------- + +We add multiple dumps for debugfs, but only allocate memory this time and +only dump #0. + +Link: https://lore.kernel.org/r/1571926105-74636-15-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 25 ++++-- + drivers/scsi/hisi_sas/hisi_sas_main.c | 111 ++++++++++++++------------ + 2 files changed, 79 insertions(+), 57 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 505d74780eab..785f0c3f7cb9 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -367,6 +367,8 @@ struct hisi_sas_hw { + int (*set_bist)(struct hisi_hba *hisi_hba, bool enable); + }; + ++#define HISI_SAS_MAX_DEBUGFS_DUMP (50) ++ + struct hisi_sas_debugfs_cq { + struct hisi_sas_cq *cq; + void *complete_hdr; +@@ -482,15 +484,22 @@ struct hisi_hba { + + /* debugfs memories */ + /* Put Global AXI and RAS Register into register array */ +- struct hisi_sas_debugfs_regs debugfs_regs[DEBUGFS_REGS_NUM]; +- struct hisi_sas_debugfs_port debugfs_port_reg[HISI_SAS_MAX_PHYS]; +- struct hisi_sas_debugfs_cq debugfs_cq[HISI_SAS_MAX_QUEUES]; +- struct hisi_sas_debugfs_dq debugfs_dq[HISI_SAS_MAX_QUEUES]; +- struct hisi_sas_debugfs_iost debugfs_iost; +- struct hisi_sas_debugfs_itct debugfs_itct; ++ struct hisi_sas_debugfs_regs ++ debugfs_regs[HISI_SAS_MAX_DEBUGFS_DUMP][DEBUGFS_REGS_NUM]; ++ struct hisi_sas_debugfs_port ++ debugfs_port_reg[HISI_SAS_MAX_DEBUGFS_DUMP][HISI_SAS_MAX_PHYS]; ++ struct hisi_sas_debugfs_cq ++ debugfs_cq[HISI_SAS_MAX_DEBUGFS_DUMP][HISI_SAS_MAX_QUEUES]; ++ struct hisi_sas_debugfs_dq ++ debugfs_dq[HISI_SAS_MAX_DEBUGFS_DUMP][HISI_SAS_MAX_QUEUES]; ++ struct hisi_sas_debugfs_iost debugfs_iost[HISI_SAS_MAX_DEBUGFS_DUMP]; ++ struct hisi_sas_debugfs_itct debugfs_itct[HISI_SAS_MAX_DEBUGFS_DUMP]; ++ struct hisi_sas_debugfs_iost_cache ++ debugfs_iost_cache[HISI_SAS_MAX_DEBUGFS_DUMP]; ++ struct hisi_sas_debugfs_itct_cache ++ debugfs_itct_cache[HISI_SAS_MAX_DEBUGFS_DUMP]; ++ + u64 debugfs_timestamp; +- struct hisi_sas_debugfs_iost_cache debugfs_iost_cache; +- struct hisi_sas_debugfs_itct_cache debugfs_itct_cache; + + struct dentry *debugfs_dir; + struct dentry *debugfs_dump_dentry; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index e218a95cfd38..4f9fd39991fc 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1630,7 +1630,7 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba) + if (test_and_set_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) + return -EPERM; + +- if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct.itct) ++ if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct) + hisi_hba->hw->debugfs_work_handler(&hisi_hba->debugfs_work); + + dev_info(dev, "controller resetting...\n"); +@@ -2131,7 +2131,7 @@ _hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, + + /* Internal abort timed out */ + if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { +- if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct.itct) ++ if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct) + queue_work(hisi_hba->wq, &hisi_hba->debugfs_work); + + if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { +@@ -2775,7 +2775,7 @@ static void hisi_sas_debugfs_snapshot_cq_reg(struct hisi_hba *hisi_hba) + int i; + + for (i = 0; i < hisi_hba->queue_count; i++) +- memcpy(hisi_hba->debugfs_cq[i].complete_hdr, ++ memcpy(hisi_hba->debugfs_cq[0][i].complete_hdr, + hisi_hba->complete_hdr[i], + HISI_SAS_QUEUE_SLOTS * queue_entry_size); + } +@@ -2786,7 +2786,7 @@ static void hisi_sas_debugfs_snapshot_dq_reg(struct hisi_hba *hisi_hba) + int i; + + for (i = 0; i < hisi_hba->queue_count; i++) +- memcpy(hisi_hba->debugfs_dq[i].hdr, ++ memcpy(hisi_hba->debugfs_dq[0][i].hdr, + hisi_hba->cmd_hdr[i], + HISI_SAS_QUEUE_SLOTS * queue_entry_size); + } +@@ -2800,7 +2800,7 @@ static void hisi_sas_debugfs_snapshot_port_reg(struct hisi_hba *hisi_hba) + u32 *databuf; + + for (phy_cnt = 0; phy_cnt < hisi_hba->n_phy; phy_cnt++) { +- databuf = hisi_hba->debugfs_port_reg[phy_cnt].data; ++ databuf = hisi_hba->debugfs_port_reg[0][phy_cnt].data; + for (i = 0; i < port->count; i++, databuf++) { + offset = port->base_off + 4 * i; + *databuf = port->read_port_reg(hisi_hba, phy_cnt, +@@ -2811,7 +2811,7 @@ static void hisi_sas_debugfs_snapshot_port_reg(struct hisi_hba *hisi_hba) + + static void hisi_sas_debugfs_snapshot_global_reg(struct hisi_hba *hisi_hba) + { +- u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_GLOBAL].data; ++ u32 *databuf = hisi_hba->debugfs_regs[0][DEBUGFS_GLOBAL].data; + const struct hisi_sas_hw *hw = hisi_hba->hw; + const struct hisi_sas_debugfs_reg *global = + hw->debugfs_reg_array[DEBUGFS_GLOBAL]; +@@ -2823,7 +2823,7 @@ static void hisi_sas_debugfs_snapshot_global_reg(struct hisi_hba *hisi_hba) + + static void hisi_sas_debugfs_snapshot_axi_reg(struct hisi_hba *hisi_hba) + { +- u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_AXI].data; ++ u32 *databuf = hisi_hba->debugfs_regs[0][DEBUGFS_AXI].data; + const struct hisi_sas_hw *hw = hisi_hba->hw; + const struct hisi_sas_debugfs_reg *axi = + hw->debugfs_reg_array[DEBUGFS_AXI]; +@@ -2836,7 +2836,7 @@ static void hisi_sas_debugfs_snapshot_axi_reg(struct hisi_hba *hisi_hba) + + static void hisi_sas_debugfs_snapshot_ras_reg(struct hisi_hba *hisi_hba) + { +- u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_RAS].data; ++ u32 *databuf = hisi_hba->debugfs_regs[0][DEBUGFS_RAS].data; + const struct hisi_sas_hw *hw = hisi_hba->hw; + const struct hisi_sas_debugfs_reg *ras = + hw->debugfs_reg_array[DEBUGFS_RAS]; +@@ -2849,8 +2849,8 @@ static void hisi_sas_debugfs_snapshot_ras_reg(struct hisi_hba *hisi_hba) + + static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba) + { +- void *cachebuf = hisi_hba->debugfs_itct_cache.cache; +- void *databuf = hisi_hba->debugfs_itct.itct; ++ void *cachebuf = hisi_hba->debugfs_itct_cache[0].cache; ++ void *databuf = hisi_hba->debugfs_itct[0].itct; + struct hisi_sas_itct *itct; + int i; + +@@ -2868,8 +2868,8 @@ static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba) + static void hisi_sas_debugfs_snapshot_iost_reg(struct hisi_hba *hisi_hba) + { + int max_command_entries = HISI_SAS_MAX_COMMANDS; +- void *cachebuf = hisi_hba->debugfs_iost_cache.cache; +- void *databuf = hisi_hba->debugfs_iost.iost; ++ void *cachebuf = hisi_hba->debugfs_iost_cache[0].cache; ++ void *databuf = hisi_hba->debugfs_iost[0].iost; + struct hisi_sas_iost *iost; + int i; + +@@ -3665,7 +3665,7 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + debugfs_timestamp); + + debugfs_create_file("global", 0400, dump_dentry, +- &hisi_hba->debugfs_regs[DEBUGFS_GLOBAL], ++ &hisi_hba->debugfs_regs[0][DEBUGFS_GLOBAL], + &hisi_sas_debugfs_global_fops); + + /* Create port dir and files */ +@@ -3674,7 +3674,7 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + for (p = 0; p < hisi_hba->n_phy; p++) { + snprintf(name, sizeof(name), "%d", p); + debugfs_create_file(name, 0400, dentry, +- &hisi_hba->debugfs_port_reg[p], ++ &hisi_hba->debugfs_port_reg[0][p], + &hisi_sas_debugfs_port_fops); + } + +@@ -3685,7 +3685,7 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + snprintf(name, sizeof(name), "%d", c); + + debugfs_create_file(name, 0400, dentry, +- &hisi_hba->debugfs_cq[c], ++ &hisi_hba->debugfs_cq[0][c], + &hisi_sas_debugfs_cq_fops); + } + +@@ -3696,32 +3696,32 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + snprintf(name, sizeof(name), "%d", d); + + debugfs_create_file(name, 0400, dentry, +- &hisi_hba->debugfs_dq[d], ++ &hisi_hba->debugfs_dq[0][d], + &hisi_sas_debugfs_dq_fops); + } + + debugfs_create_file("iost", 0400, dump_dentry, +- &hisi_hba->debugfs_iost, ++ &hisi_hba->debugfs_iost[0], + &hisi_sas_debugfs_iost_fops); + + debugfs_create_file("iost_cache", 0400, dump_dentry, +- &hisi_hba->debugfs_iost_cache, ++ &hisi_hba->debugfs_iost_cache[0], + &hisi_sas_debugfs_iost_cache_fops); + + debugfs_create_file("itct", 0400, dump_dentry, +- &hisi_hba->debugfs_itct, ++ &hisi_hba->debugfs_itct[0], + &hisi_sas_debugfs_itct_fops); + + debugfs_create_file("itct_cache", 0400, dump_dentry, +- &hisi_hba->debugfs_itct_cache, ++ &hisi_hba->debugfs_itct_cache[0], + &hisi_sas_debugfs_itct_cache_fops); + + debugfs_create_file("axi", 0400, dump_dentry, +- &hisi_hba->debugfs_regs[DEBUGFS_AXI], ++ &hisi_hba->debugfs_regs[0][DEBUGFS_AXI], + &hisi_sas_debugfs_axi_fops); + + debugfs_create_file("ras", 0400, dump_dentry, +- &hisi_hba->debugfs_regs[DEBUGFS_RAS], ++ &hisi_hba->debugfs_regs[0][DEBUGFS_RAS], + &hisi_sas_debugfs_ras_fops); + + return; +@@ -3798,33 +3798,35 @@ void hisi_sas_debugfs_work_handler(struct work_struct *work) + } + EXPORT_SYMBOL_GPL(hisi_sas_debugfs_work_handler); + +-static void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba) ++static void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba, int dump_index) + { + struct device *dev = hisi_hba->dev; + int i; + +- devm_kfree(dev, hisi_hba->debugfs_iost_cache.cache); +- devm_kfree(dev, hisi_hba->debugfs_itct_cache.cache); +- devm_kfree(dev, hisi_hba->debugfs_iost.iost); ++ devm_kfree(dev, hisi_hba->debugfs_iost_cache[dump_index].cache); ++ devm_kfree(dev, hisi_hba->debugfs_itct_cache[dump_index].cache); ++ devm_kfree(dev, hisi_hba->debugfs_iost[dump_index].iost); ++ devm_kfree(dev, hisi_hba->debugfs_itct[dump_index].itct); + + for (i = 0; i < hisi_hba->queue_count; i++) +- devm_kfree(dev, hisi_hba->debugfs_dq[i].hdr); ++ devm_kfree(dev, hisi_hba->debugfs_dq[dump_index][i].hdr); + + for (i = 0; i < hisi_hba->queue_count; i++) +- devm_kfree(dev, hisi_hba->debugfs_cq[i].complete_hdr); ++ devm_kfree(dev, ++ hisi_hba->debugfs_cq[dump_index][i].complete_hdr); + + for (i = 0; i < DEBUGFS_REGS_NUM; i++) +- devm_kfree(dev, hisi_hba->debugfs_regs[i].data); ++ devm_kfree(dev, hisi_hba->debugfs_regs[dump_index][i].data); + + for (i = 0; i < hisi_hba->n_phy; i++) +- devm_kfree(dev, hisi_hba->debugfs_port_reg[i].data); ++ devm_kfree(dev, hisi_hba->debugfs_port_reg[dump_index][i].data); + } + +-static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba) ++static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba, int dump_index) + { + const struct hisi_sas_hw *hw = hisi_hba->hw; + struct device *dev = hisi_hba->dev; +- int p, c, d, r; ++ int p, c, d, r, i; + size_t sz; + + /* create bist structures */ +@@ -3862,7 +3864,7 @@ static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba) + + for (r = 0; r < DEBUGFS_REGS_NUM; r++) { + struct hisi_sas_debugfs_regs *regs = +- &hisi_hba->debugfs_regs[r]; ++ &hisi_hba->debugfs_regs[dump_index][r]; + + sz = hw->debugfs_reg_array[r]->count * 4; + regs->data = devm_kmalloc(dev, sz, GFP_KERNEL); +@@ -3874,7 +3876,7 @@ static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba) + sz = hw->debugfs_reg_port->count * 4; + for (p = 0; p < hisi_hba->n_phy; p++) { + struct hisi_sas_debugfs_port *port = +- &hisi_hba->debugfs_port_reg[p]; ++ &hisi_hba->debugfs_port_reg[dump_index][p]; + + port->data = devm_kmalloc(dev, sz, GFP_KERNEL); + if (!port->data) +@@ -3885,7 +3887,7 @@ static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba) + sz = hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS; + for (c = 0; c < hisi_hba->queue_count; c++) { + struct hisi_sas_debugfs_cq *cq = +- &hisi_hba->debugfs_cq[c]; ++ &hisi_hba->debugfs_cq[dump_index][c]; + + cq->complete_hdr = devm_kmalloc(dev, sz, GFP_KERNEL); + if (!cq->complete_hdr) +@@ -3896,7 +3898,7 @@ static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba) + sz = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS; + for (d = 0; d < hisi_hba->queue_count; d++) { + struct hisi_sas_debugfs_dq *dq = +- &hisi_hba->debugfs_dq[d]; ++ &hisi_hba->debugfs_dq[dump_index][d]; + + dq->hdr = devm_kmalloc(dev, sz, GFP_KERNEL); + if (!dq->hdr) +@@ -3906,40 +3908,46 @@ static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba) + + sz = HISI_SAS_MAX_COMMANDS * sizeof(struct hisi_sas_iost); + +- hisi_hba->debugfs_iost.iost = devm_kmalloc(dev, sz, GFP_KERNEL); +- if (!hisi_hba->debugfs_iost.iost) ++ hisi_hba->debugfs_iost[dump_index].iost = ++ devm_kmalloc(dev, sz, GFP_KERNEL); ++ if (!hisi_hba->debugfs_iost[dump_index].iost) + goto fail; + + sz = HISI_SAS_IOST_ITCT_CACHE_NUM * + sizeof(struct hisi_sas_iost_itct_cache); + +- hisi_hba->debugfs_iost_cache.cache = devm_kmalloc(dev, sz, GFP_KERNEL); +- if (!hisi_hba->debugfs_iost_cache.cache) ++ hisi_hba->debugfs_iost_cache[dump_index].cache = ++ devm_kmalloc(dev, sz, GFP_KERNEL); ++ if (!hisi_hba->debugfs_iost_cache[dump_index].cache) + goto fail; + + sz = HISI_SAS_IOST_ITCT_CACHE_NUM * + sizeof(struct hisi_sas_iost_itct_cache); + +- hisi_hba->debugfs_itct_cache.cache = devm_kmalloc(dev, sz, GFP_KERNEL); +- if (!hisi_hba->debugfs_itct_cache.cache) ++ hisi_hba->debugfs_itct_cache[dump_index].cache = ++ devm_kmalloc(dev, sz, GFP_KERNEL); ++ if (!hisi_hba->debugfs_itct_cache[dump_index].cache) + goto fail; + + /* New memory allocation must be locate before itct */ + sz = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct); + +- hisi_hba->debugfs_itct.itct = devm_kmalloc(dev, sz, GFP_KERNEL); +- if (!hisi_hba->debugfs_itct.itct) ++ hisi_hba->debugfs_itct[dump_index].itct = ++ devm_kmalloc(dev, sz, GFP_KERNEL); ++ if (!hisi_hba->debugfs_itct[dump_index].itct) + goto fail; + + return 0; + fail: +- hisi_sas_debugfs_release(hisi_hba); ++ for (i = 0; i < HISI_SAS_MAX_DEBUGFS_DUMP; i++) ++ hisi_sas_debugfs_release(hisi_hba, i); + return -ENOMEM; + } + + void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) + { + struct device *dev = hisi_hba->dev; ++ int i; + + hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev), + hisi_sas_debugfs_dir); +@@ -3948,11 +3956,16 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) + hisi_hba, + &hisi_sas_debugfs_trigger_dump_fops); + +- if (hisi_sas_debugfs_alloc(hisi_hba)) { +- debugfs_remove_recursive(hisi_hba->debugfs_dir); +- dev_dbg(dev, "failed to init debugfs!\n"); +- } ++ hisi_hba->debugfs_dump_dentry = ++ debugfs_create_dir("dump", hisi_hba->debugfs_dir); + ++ for (i = 0; i < HISI_SAS_MAX_DEBUGFS_DUMP; i++) { ++ if (hisi_sas_debugfs_alloc(hisi_hba, i)) { ++ debugfs_remove_recursive(hisi_hba->debugfs_dir); ++ dev_dbg(dev, "failed to init debugfs!\n"); ++ break; ++ } ++ } + } + EXPORT_SYMBOL_GPL(hisi_sas_debugfs_init); + +-- +2.27.0 + diff --git a/patches/0359-scsi-hisi_sas-Add-module-parameter-for-debugfs-dump-.patch b/patches/0359-scsi-hisi_sas-Add-module-parameter-for-debugfs-dump-.patch new file mode 100644 index 00000000..782f18e6 --- /dev/null +++ b/patches/0359-scsi-hisi_sas-Add-module-parameter-for-debugfs-dump-.patch @@ -0,0 +1,91 @@ +From 5ff6e72a58288a7d02553953b0fd8258c8c6baa8 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Thu, 24 Oct 2019 22:08:22 +0800 +Subject: [PATCH 041/256] scsi: hisi_sas: Add module parameter for debugfs dump + count + +mainline inclusion +from mainline-v5.5-rc1 +commit 905ab01faf5fc81ba2fc46dddcd21ad5a2dd137b +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=905ab01faf5fc81ba2fc46dddcd21ad5a2dd137b + +---------------------------------------------------------------------- + +We still only use dump index #0 however. + +Link: https://lore.kernel.org/r/1571926105-74636-16-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas.h | 1 + + drivers/scsi/hisi_sas/hisi_sas_main.c | 16 +++++++++++++--- + 2 files changed, 14 insertions(+), 3 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 785f0c3f7cb9..5604e6d7bc25 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -649,6 +649,7 @@ struct hisi_sas_slot_dif_buf_table { + }; + + extern bool hisi_sas_debugfs_enable; ++extern u32 hisi_sas_debugfs_dump_count; + extern struct dentry *hisi_sas_debugfs_dir; + extern int skip_bus_flag; + extern struct scsi_transport_template *hisi_sas_stt; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 4f9fd39991fc..ab7e07f1ed51 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -3939,7 +3939,7 @@ static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba, int dump_index) + + return 0; + fail: +- for (i = 0; i < HISI_SAS_MAX_DEBUGFS_DUMP; i++) ++ for (i = 0; i < hisi_sas_debugfs_dump_count; i++) + hisi_sas_debugfs_release(hisi_hba, i); + return -ENOMEM; + } +@@ -3959,7 +3959,7 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) + hisi_hba->debugfs_dump_dentry = + debugfs_create_dir("dump", hisi_hba->debugfs_dir); + +- for (i = 0; i < HISI_SAS_MAX_DEBUGFS_DUMP; i++) { ++ for (i = 0; i < hisi_sas_debugfs_dump_count; i++) { + if (hisi_sas_debugfs_alloc(hisi_hba, i)) { + debugfs_remove_recursive(hisi_hba->debugfs_dir); + dev_dbg(dev, "failed to init debugfs!\n"); +@@ -3999,14 +3999,24 @@ EXPORT_SYMBOL_GPL(hisi_sas_debugfs_enable); + module_param_named(debugfs_enable, hisi_sas_debugfs_enable, bool, 0444); + MODULE_PARM_DESC(hisi_sas_debugfs_enable, "Enable driver debugfs (default disabled)"); + ++u32 hisi_sas_debugfs_dump_count = 1; ++EXPORT_SYMBOL_GPL(hisi_sas_debugfs_dump_count); ++module_param_named(debugfs_dump_count, hisi_sas_debugfs_dump_count, uint, 0444); ++MODULE_PARM_DESC(hisi_sas_debugfs_dump_count, "Number of debugfs dumps to allow"); ++ + static __init int hisi_sas_init(void) + { + hisi_sas_stt = sas_domain_attach_transport(&hisi_sas_transport_ops); + if (!hisi_sas_stt) + return -ENOMEM; + +- if (hisi_sas_debugfs_enable) ++ if (hisi_sas_debugfs_enable) { + hisi_sas_debugfs_dir = debugfs_create_dir("hisi_sas", NULL); ++ if (hisi_sas_debugfs_dump_count > HISI_SAS_MAX_DEBUGFS_DUMP) { ++ pr_info("hisi_sas: Limiting debugfs dump count\n"); ++ hisi_sas_debugfs_dump_count = HISI_SAS_MAX_DEBUGFS_DUMP; ++ } ++ } + + return 0; + } +-- +2.27.0 + diff --git a/patches/0360-scsi-hisi_sas-Add-ability-to-have-multiple-debugfs-d.patch b/patches/0360-scsi-hisi_sas-Add-ability-to-have-multiple-debugfs-d.patch new file mode 100644 index 00000000..d499fb40 --- /dev/null +++ b/patches/0360-scsi-hisi_sas-Add-ability-to-have-multiple-debugfs-d.patch @@ -0,0 +1,283 @@ +From 934427661fda0fdcab4fbaad5e298f9517345f73 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Thu, 24 Oct 2019 22:08:23 +0800 +Subject: [PATCH 042/256] scsi: hisi_sas: Add ability to have multiple debugfs + dumps + +mainline inclusion +from mainline-v5.5-rc1 +commit 8f6432986e610612688dc77c2683657d7289546f +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8f6432986e610612688dc77c2683657d7289546f + +---------------------------------------------------------------------- + +We use the module parameter debugfs_dump_count to manage the upper limit of +the memory block for multiple dumps. + +Link: https://lore.kernel.org/r/1571926105-74636-17-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas.h + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 5 +- + drivers/scsi/hisi_sas/hisi_sas_main.c | 72 ++++++++++++++++----------- + 2 files changed, 46 insertions(+), 31 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 5604e6d7bc25..9eba71ad47fd 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -499,8 +499,8 @@ struct hisi_hba { + struct hisi_sas_debugfs_itct_cache + debugfs_itct_cache[HISI_SAS_MAX_DEBUGFS_DUMP]; + +- u64 debugfs_timestamp; +- ++ u64 debugfs_timestamp[HISI_SAS_MAX_DEBUGFS_DUMP]; ++ int debugfs_dump_index; + struct dentry *debugfs_dir; + struct dentry *debugfs_dump_dentry; + struct dentry *debugfs_bist_dentry; +@@ -509,7 +509,6 @@ struct hisi_hba { + unsigned int dq_idx[NR_CPUS]; + int nvecs; + unsigned int dq_num_per_node; +- bool debugfs_snapshot; + }; + + /* Generic HW DMA host memory structures */ +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index ab7e07f1ed51..5d890758059b 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -2772,10 +2772,11 @@ struct dentry *hisi_sas_debugfs_dir; + static void hisi_sas_debugfs_snapshot_cq_reg(struct hisi_hba *hisi_hba) + { + int queue_entry_size = hisi_hba->hw->complete_hdr_size; ++ int dump_index = hisi_hba->debugfs_dump_index; + int i; + + for (i = 0; i < hisi_hba->queue_count; i++) +- memcpy(hisi_hba->debugfs_cq[0][i].complete_hdr, ++ memcpy(hisi_hba->debugfs_cq[dump_index][i].complete_hdr, + hisi_hba->complete_hdr[i], + HISI_SAS_QUEUE_SLOTS * queue_entry_size); + } +@@ -2783,16 +2784,18 @@ static void hisi_sas_debugfs_snapshot_cq_reg(struct hisi_hba *hisi_hba) + static void hisi_sas_debugfs_snapshot_dq_reg(struct hisi_hba *hisi_hba) + { + int queue_entry_size = sizeof(struct hisi_sas_cmd_hdr); ++ int dump_index = hisi_hba->debugfs_dump_index; + int i; + + for (i = 0; i < hisi_hba->queue_count; i++) +- memcpy(hisi_hba->debugfs_dq[0][i].hdr, ++ memcpy(hisi_hba->debugfs_dq[dump_index][i].hdr, + hisi_hba->cmd_hdr[i], + HISI_SAS_QUEUE_SLOTS * queue_entry_size); + } + + static void hisi_sas_debugfs_snapshot_port_reg(struct hisi_hba *hisi_hba) + { ++ int dump_index = hisi_hba->debugfs_dump_index; + const struct hisi_sas_debugfs_reg *port = + hisi_hba->hw->debugfs_reg_port; + int i, phy_cnt; +@@ -2800,7 +2803,7 @@ static void hisi_sas_debugfs_snapshot_port_reg(struct hisi_hba *hisi_hba) + u32 *databuf; + + for (phy_cnt = 0; phy_cnt < hisi_hba->n_phy; phy_cnt++) { +- databuf = hisi_hba->debugfs_port_reg[0][phy_cnt].data; ++ databuf = hisi_hba->debugfs_port_reg[dump_index][phy_cnt].data; + for (i = 0; i < port->count; i++, databuf++) { + offset = port->base_off + 4 * i; + *databuf = port->read_port_reg(hisi_hba, phy_cnt, +@@ -2811,7 +2814,8 @@ static void hisi_sas_debugfs_snapshot_port_reg(struct hisi_hba *hisi_hba) + + static void hisi_sas_debugfs_snapshot_global_reg(struct hisi_hba *hisi_hba) + { +- u32 *databuf = hisi_hba->debugfs_regs[0][DEBUGFS_GLOBAL].data; ++ int dump_index = hisi_hba->debugfs_dump_index; ++ u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL].data; + const struct hisi_sas_hw *hw = hisi_hba->hw; + const struct hisi_sas_debugfs_reg *global = + hw->debugfs_reg_array[DEBUGFS_GLOBAL]; +@@ -2823,7 +2827,8 @@ static void hisi_sas_debugfs_snapshot_global_reg(struct hisi_hba *hisi_hba) + + static void hisi_sas_debugfs_snapshot_axi_reg(struct hisi_hba *hisi_hba) + { +- u32 *databuf = hisi_hba->debugfs_regs[0][DEBUGFS_AXI].data; ++ int dump_index = hisi_hba->debugfs_dump_index; ++ u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI].data; + const struct hisi_sas_hw *hw = hisi_hba->hw; + const struct hisi_sas_debugfs_reg *axi = + hw->debugfs_reg_array[DEBUGFS_AXI]; +@@ -2836,7 +2841,8 @@ static void hisi_sas_debugfs_snapshot_axi_reg(struct hisi_hba *hisi_hba) + + static void hisi_sas_debugfs_snapshot_ras_reg(struct hisi_hba *hisi_hba) + { +- u32 *databuf = hisi_hba->debugfs_regs[0][DEBUGFS_RAS].data; ++ int dump_index = hisi_hba->debugfs_dump_index; ++ u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS].data; + const struct hisi_sas_hw *hw = hisi_hba->hw; + const struct hisi_sas_debugfs_reg *ras = + hw->debugfs_reg_array[DEBUGFS_RAS]; +@@ -2849,8 +2855,9 @@ static void hisi_sas_debugfs_snapshot_ras_reg(struct hisi_hba *hisi_hba) + + static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba) + { +- void *cachebuf = hisi_hba->debugfs_itct_cache[0].cache; +- void *databuf = hisi_hba->debugfs_itct[0].itct; ++ int dump_index = hisi_hba->debugfs_dump_index; ++ void *cachebuf = hisi_hba->debugfs_itct_cache[dump_index].cache; ++ void *databuf = hisi_hba->debugfs_itct[dump_index].itct; + struct hisi_sas_itct *itct; + int i; + +@@ -2867,9 +2874,10 @@ static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba) + + static void hisi_sas_debugfs_snapshot_iost_reg(struct hisi_hba *hisi_hba) + { ++ int dump_index = hisi_hba->debugfs_dump_index; + int max_command_entries = HISI_SAS_MAX_COMMANDS; +- void *cachebuf = hisi_hba->debugfs_iost_cache[0].cache; +- void *databuf = hisi_hba->debugfs_iost[0].iost; ++ void *cachebuf = hisi_hba->debugfs_iost_cache[dump_index].cache; ++ void *databuf = hisi_hba->debugfs_iost[dump_index].iost; + struct hisi_sas_iost *iost; + int i; + +@@ -3648,6 +3656,7 @@ static const struct file_operations hisi_sas_debugfs_itct_cache_fops = { + static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + { + u64 *debugfs_timestamp; ++ int dump_index = hisi_hba->debugfs_dump_index; + struct dentry *dump_dentry; + struct dentry *dentry; + char name[256]; +@@ -3655,17 +3664,17 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + int c; + int d; + +- debugfs_timestamp = &hisi_hba->debugfs_timestamp; +- /* Create dump dir inside device dir */ +- dump_dentry = debugfs_create_dir("dump", hisi_hba->debugfs_dir); ++ snprintf(name, 256, "%d", dump_index); + +- hisi_hba->debugfs_dump_dentry = dump_dentry; ++ dump_dentry = debugfs_create_dir(name, hisi_hba->debugfs_dump_dentry); ++ ++ debugfs_timestamp = &hisi_hba->debugfs_timestamp[dump_index]; + + debugfs_create_u64("timestamp", 0400, dump_dentry, + debugfs_timestamp); + + debugfs_create_file("global", 0400, dump_dentry, +- &hisi_hba->debugfs_regs[0][DEBUGFS_GLOBAL], ++ &hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL], + &hisi_sas_debugfs_global_fops); + + /* Create port dir and files */ +@@ -3674,7 +3683,7 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + for (p = 0; p < hisi_hba->n_phy; p++) { + snprintf(name, sizeof(name), "%d", p); + debugfs_create_file(name, 0400, dentry, +- &hisi_hba->debugfs_port_reg[0][p], ++ &hisi_hba->debugfs_port_reg[dump_index][p], + &hisi_sas_debugfs_port_fops); + } + +@@ -3685,7 +3694,7 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + snprintf(name, sizeof(name), "%d", c); + + debugfs_create_file(name, 0400, dentry, +- &hisi_hba->debugfs_cq[0][c], ++ &hisi_hba->debugfs_cq[dump_index][c], + &hisi_sas_debugfs_cq_fops); + } + +@@ -3696,32 +3705,32 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) + snprintf(name, sizeof(name), "%d", d); + + debugfs_create_file(name, 0400, dentry, +- &hisi_hba->debugfs_dq[0][d], ++ &hisi_hba->debugfs_dq[dump_index][d], + &hisi_sas_debugfs_dq_fops); + } + + debugfs_create_file("iost", 0400, dump_dentry, +- &hisi_hba->debugfs_iost[0], ++ &hisi_hba->debugfs_iost[dump_index], + &hisi_sas_debugfs_iost_fops); + + debugfs_create_file("iost_cache", 0400, dump_dentry, +- &hisi_hba->debugfs_iost_cache[0], ++ &hisi_hba->debugfs_iost_cache[dump_index], + &hisi_sas_debugfs_iost_cache_fops); + + debugfs_create_file("itct", 0400, dump_dentry, +- &hisi_hba->debugfs_itct[0], ++ &hisi_hba->debugfs_itct[dump_index], + &hisi_sas_debugfs_itct_fops); + + debugfs_create_file("itct_cache", 0400, dump_dentry, +- &hisi_hba->debugfs_itct_cache[0], ++ &hisi_hba->debugfs_itct_cache[dump_index], + &hisi_sas_debugfs_itct_cache_fops); + + debugfs_create_file("axi", 0400, dump_dentry, +- &hisi_hba->debugfs_regs[0][DEBUGFS_AXI], ++ &hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI], + &hisi_sas_debugfs_axi_fops); + + debugfs_create_file("ras", 0400, dump_dentry, +- &hisi_hba->debugfs_regs[0][DEBUGFS_RAS], ++ &hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS], + &hisi_sas_debugfs_ras_fops); + + return; +@@ -3761,6 +3770,8 @@ static ssize_t hisi_sas_debugfs_trigger_dump_write(struct file *file, + * If not 0, will return -EFAULT. + * Keep manual dump as one time only + */ ++ if (hisi_hba->debugfs_dump_index >= hisi_sas_debugfs_dump_count) ++ return -EFAULT; + + /* Not allow to input more than 8 char */ + if (count > sizeof(buf)) +@@ -3786,15 +3797,20 @@ void hisi_sas_debugfs_work_handler(struct work_struct *work) + { + struct hisi_hba *hisi_hba = + container_of(work, struct hisi_hba, debugfs_work); ++ int debugfs_dump_index = hisi_hba->debugfs_dump_index; ++ struct device *dev = hisi_hba->dev; + u64 timestamp = local_clock(); + +- do_div(timestamp, NSEC_PER_MSEC); +- hisi_hba->debugfs_timestamp = timestamp; +- if (hisi_hba->debugfs_snapshot) ++ if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) { ++ dev_warn(dev, "dump count exceeded!\n"); + return; +- hisi_hba->debugfs_snapshot = true; ++ } ++ ++ do_div(timestamp, NSEC_PER_MSEC); ++ hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp; + + hisi_sas_debugfs_snapshot_regs(hisi_hba); ++ hisi_hba->debugfs_dump_index++; + } + EXPORT_SYMBOL_GPL(hisi_sas_debugfs_work_handler); + +-- +2.27.0 + diff --git a/patches/0361-scsi-hisi_sas-Delete-the-debugfs-folder-of-hisi_sas-.patch b/patches/0361-scsi-hisi_sas-Delete-the-debugfs-folder-of-hisi_sas-.patch new file mode 100644 index 00000000..47d84e44 --- /dev/null +++ b/patches/0361-scsi-hisi_sas-Delete-the-debugfs-folder-of-hisi_sas-.patch @@ -0,0 +1,63 @@ +From 5a590140fd53edea3b7e17435eb3a8a55cda25be Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Thu, 24 Oct 2019 22:08:24 +0800 +Subject: [PATCH 043/256] scsi: hisi_sas: Delete the debugfs folder of hisi_sas + when the probe fails + +mainline inclusion +from mainline-v5.5-rc1 +commit cabe7c10c97a0857a9fb14b6c772ab784947995d +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cabe7c10c97a0857a9fb14b6c772ab784947995d + +---------------------------------------------------------------------- + +Although if the debugfs initialization fails, we will delete the debugfs +folder of hisi_sas, but we did not consider the scenario where debugfs was +successfully initialized, but the probe failed for other reasons. We found +out that hisi_sas folder is still remain after the probe failed. + +When probe fail, we should delete debugfs folder to avoid the above issue. + +Link: https://lore.kernel.org/r/1571926105-74636-18-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 1 + + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 5d890758059b..d25fbb051bd3 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -2761,6 +2761,7 @@ int hisi_sas_probe(struct platform_device *pdev, + err_out_register_ha: + scsi_remove_host(shost); + err_out: ++ hisi_sas_debugfs_exit(hisi_hba); + hisi_sas_free(hisi_hba); + scsi_host_put(shost); + return rc; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index e55442525ae6..e83a5ad2a491 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -3665,6 +3665,7 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) + err_out_register_ha: + scsi_remove_host(shost); + err_out_ha: ++ hisi_sas_debugfs_exit(hisi_hba); + scsi_host_put(shost); + err_out_regions: + pci_release_regions(pdev); +-- +2.27.0 + diff --git a/patches/0362-scsi-hisi_sas-Record-the-phy-down-event-in-debugfs.patch b/patches/0362-scsi-hisi_sas-Record-the-phy-down-event-in-debugfs.patch new file mode 100644 index 00000000..1a6e06cf --- /dev/null +++ b/patches/0362-scsi-hisi_sas-Record-the-phy-down-event-in-debugfs.patch @@ -0,0 +1,153 @@ +From f08c96997e8c6734d1f375f661b02971462a1a07 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Thu, 24 Oct 2019 22:08:25 +0800 +Subject: [PATCH 044/256] scsi: hisi_sas: Record the phy down event in debugfs + +mainline inclusion +from mainline-v5.5-rc1 +commit f873b66119f2d6fc7b932a68df8d77a26357bab6 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f873b66119f2d6fc7b932a68df8d77a26357bab6 + +---------------------------------------------------------------------- + +The number of phy down reflects the quality of the link between SAS +controller and disk. In order to allow the user to confirm the link quality +of the system, we record the number of phy down for each phy. + +The user can check the current phy down count by reading the debugfs file +corresponding to the specific phy, or clear the phy down count by writing 0 +to the debugfs file. + +Link: https://lore.kernel.org/r/1571926105-74636-19-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 1 + + drivers/scsi/hisi_sas/hisi_sas_main.c | 63 ++++++++++++++++++++++++++ + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 2 + + 3 files changed, 66 insertions(+) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 9eba71ad47fd..6b66c056ecc8 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -188,6 +188,7 @@ struct hisi_sas_phy { + enum sas_linkrate maximum_linkrate; + u32 code_error_count; + int enable; ++ atomic_t down_cnt; + }; + + struct hisi_sas_port { +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index d25fbb051bd3..356ebe30b5c0 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -3794,6 +3794,52 @@ static const struct file_operations hisi_sas_debugfs_trigger_dump_fops = { + .owner = THIS_MODULE, + }; + ++static ssize_t hisi_sas_debugfs_phy_down_cnt_write(struct file *filp, ++ const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct seq_file *s = filp->private_data; ++ struct hisi_sas_phy *phy = s->private; ++ unsigned int set_val; ++ int res; ++ ++ res = kstrtouint_from_user(buf, count, 0, &set_val); ++ if (res) ++ return res; ++ ++ if (set_val > 0) ++ return -EINVAL; ++ ++ atomic_set(&phy->down_cnt, 0); ++ ++ return count; ++} ++ ++static int hisi_sas_debugfs_phy_down_cnt_show(struct seq_file *s, void *p) ++{ ++ struct hisi_sas_phy *phy = s->private; ++ ++ seq_printf(s, "%d\n", atomic_read(&phy->down_cnt)); ++ ++ return 0; ++} ++ ++static int hisi_sas_debugfs_phy_down_cnt_open(struct inode *inode, ++ struct file *filp) ++{ ++ return single_open(filp, hisi_sas_debugfs_phy_down_cnt_show, ++ inode->i_private); ++} ++ ++static const struct file_operations hisi_sas_debugfs_phy_down_cnt_ops = { ++ .open = hisi_sas_debugfs_phy_down_cnt_open, ++ .read = seq_read, ++ .write = hisi_sas_debugfs_phy_down_cnt_write, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .owner = THIS_MODULE, ++}; ++ + void hisi_sas_debugfs_work_handler(struct work_struct *work) + { + struct hisi_hba *hisi_hba = +@@ -3961,6 +4007,21 @@ static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba, int dump_index) + return -ENOMEM; + } + ++static void hisi_sas_debugfs_phy_down_cnt_init(struct hisi_hba *hisi_hba) ++{ ++ struct dentry *dir = debugfs_create_dir("phy_down_cnt", ++ hisi_hba->debugfs_dir); ++ char name[16]; ++ int phy_no; ++ ++ for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) { ++ snprintf(name, 16, "%d", phy_no); ++ debugfs_create_file(name, 0600, dir, ++ &hisi_hba->phy[phy_no], ++ &hisi_sas_debugfs_phy_down_cnt_ops); ++ } ++} ++ + void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) + { + struct device *dev = hisi_hba->dev; +@@ -3976,6 +4037,8 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) + hisi_hba->debugfs_dump_dentry = + debugfs_create_dir("dump", hisi_hba->debugfs_dir); + ++ hisi_sas_debugfs_phy_down_cnt_init(hisi_hba); ++ + for (i = 0; i < hisi_sas_debugfs_dump_count; i++) { + if (hisi_sas_debugfs_alloc(hisi_hba, i)) { + debugfs_remove_recursive(hisi_hba->debugfs_dir); +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index e83a5ad2a491..35fee5d5d141 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -1704,6 +1704,8 @@ static irqreturn_t phy_down_v3_hw(int phy_no, struct hisi_hba *hisi_hba) + u32 phy_state, sl_ctrl, txid_auto; + struct device *dev = hisi_hba->dev; + ++ atomic_inc(&phy->down_cnt); ++ + del_timer(&phy->timer); + hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 1); + +-- +2.27.0 + diff --git a/patches/0363-scsi-hisi_sas-Return-directly-if-init-hardware-faile.patch b/patches/0363-scsi-hisi_sas-Return-directly-if-init-hardware-faile.patch new file mode 100644 index 00000000..f858594b --- /dev/null +++ b/patches/0363-scsi-hisi_sas-Return-directly-if-init-hardware-faile.patch @@ -0,0 +1,43 @@ +From 471030107b6e0558e7f48b56bab032764bcf23db Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Tue, 12 Nov 2019 17:30:57 +0800 +Subject: [PATCH 045/256] scsi: hisi_sas: Return directly if init hardware + failed + +mainline inclusion +from mainline-v5.5-rc1 +commit 547fde8b5a1923050f388caae4f76613b5a620e0 +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=547fde8b5a1923050f388caae4f76613b5a620e0 + +---------------------------------------------------------------------- + +Need to return directly if init hardware failed. + +Fixes: 73a4925d154c ("scsi: hisi_sas: Update all the registers after suspend and resume") +Link: https://lore.kernel.org/r/1573551059-107873-3-git-send-email-john.garry@huawei.com +Signed-off-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 35fee5d5d141..500fd6e54f38 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -3832,6 +3832,7 @@ static int hisi_sas_v3_resume(struct pci_dev *pdev) + if (rc) { + scsi_remove_host(shost); + pci_disable_device(pdev); ++ return rc; + } + hisi_hba->hw->phys_init(hisi_hba); + sas_resume_ha(sha); +-- +2.27.0 + diff --git a/patches/0364-scsi-hisi_sas-Stop-converting-a-bool-into-a-bool.patch b/patches/0364-scsi-hisi_sas-Stop-converting-a-bool-into-a-bool.patch new file mode 100644 index 00000000..0b0cd8d9 --- /dev/null +++ b/patches/0364-scsi-hisi_sas-Stop-converting-a-bool-into-a-bool.patch @@ -0,0 +1,42 @@ +From c43a766e667773e9ea9080be6369ec747095f2af Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Tue, 12 Nov 2019 17:30:59 +0800 +Subject: [PATCH 046/256] scsi: hisi_sas: Stop converting a bool into a bool + +mainline inclusion +from mainline-v5.5-rc1 +commit 964231aa0c7ef53ebc9c2a6889bbc50d8a3f2220 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=964231aa0c7ef53ebc9c2a6889bbc50d8a3f2220 + +---------------------------------------------------------------------- + +The !! operator on a bool is pointless, so remove an example in +hisi_sas_rescan_topology(). + +Link: https://lore.kernel.org/r/1573551059-107873-5-git-send-email-john.garry@huawei.com +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 356ebe30b5c0..ee2b22ba37f9 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1448,7 +1448,7 @@ static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state) + struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; + struct asd_sas_phy *sas_phy = &phy->sas_phy; + struct asd_sas_port *sas_port = sas_phy->port; +- bool do_port_check = !!(_sas_port != sas_port); ++ bool do_port_check = _sas_port != sas_port; + + if (!sas_phy->phy->enabled) + continue; +-- +2.27.0 + diff --git a/patches/0365-scsi-hisi_sas-Replace-magic-number-when-handle-chann.patch b/patches/0365-scsi-hisi_sas-Replace-magic-number-when-handle-chann.patch new file mode 100644 index 00000000..ff7241f5 --- /dev/null +++ b/patches/0365-scsi-hisi_sas-Replace-magic-number-when-handle-chann.patch @@ -0,0 +1,81 @@ +From 4547d00f3a5893db5ca63008fcfc47b94aad169e Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Mon, 20 Jan 2020 20:22:33 +0800 +Subject: [PATCH 047/256] scsi: hisi_sas: Replace magic number when handle + channel interrupt + +mainline inclusion +from mainline-v5.6-rc1 +commit d2815fdf9a0e6c629d062f9a7e24cb7cdbef3dee +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d2815fdf9a0e6c629d062f9a7e24cb7cdbef3dee + +---------------------------------------------------------------------- + +We use magic number as offset and mask when handle channel interrupt, so +use macro to replace it. + +Link: https://lore.kernel.org/r/1579522957-4393-4-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 500fd6e54f38..c8328e1ef166 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -540,6 +540,13 @@ struct hisi_sas_err_record_v3 { + (op == READ_16) || (op == WRITE_16) || \ + (op == READ_32) || (op == WRITE_32)) + ++#define CHNL_INT_STS_MSK 0xeeeeeeee ++#define CHNL_INT_STS_PHY_MSK 0xe ++#define CHNL_INT_STS_INT0_MSK BIT(1) ++#define CHNL_INT_STS_INT1_MSK BIT(2) ++#define CHNL_INT_STS_INT2_MSK BIT(3) ++#define CHNL_WIDTH 4 ++ + enum { + DSM_FUNC_ERR_HANDLE_MSI = 0, + }; +@@ -1945,22 +1952,23 @@ static irqreturn_t int_chnl_int_v3_hw(int irq_no, void *p) + int phy_no = 0; + + irq_msk = hisi_sas_read32(hisi_hba, CHNL_INT_STATUS) +- & 0xeeeeeeee; ++ & CHNL_INT_STS_MSK; ++ + /* + * These three irqs mask save at high 3 bit, the last bit + * is reserved. So we use 0xe to clear those after handle. + */ + while (irq_msk) { +- if (irq_msk & (2 << (phy_no * 4))) ++ if (irq_msk & (CHNL_INT_STS_INT0_MSK << (phy_no * CHNL_WIDTH))) + handle_chl_int0_v3_hw(hisi_hba, phy_no); + +- if (irq_msk & (4 << (phy_no * 4))) ++ if (irq_msk & (CHNL_INT_STS_INT1_MSK << (phy_no * CHNL_WIDTH))) + handle_chl_int1_v3_hw(hisi_hba, phy_no); + +- if (irq_msk & (8 << (phy_no * 4))) ++ if (irq_msk & (CHNL_INT_STS_INT2_MSK << (phy_no * CHNL_WIDTH))) + handle_chl_int2_v3_hw(hisi_hba, phy_no); + +- irq_msk &= ~(0xe << (phy_no * 4)); ++ irq_msk &= ~(CHNL_INT_STS_PHY_MSK << (phy_no * CHNL_WIDTH)); + phy_no++; + } + +-- +2.27.0 + diff --git a/patches/0366-scsi-hisi_sas-Modify-the-file-permissions-of-trigger.patch b/patches/0366-scsi-hisi_sas-Modify-the-file-permissions-of-trigger.patch new file mode 100644 index 00000000..7a521c77 --- /dev/null +++ b/patches/0366-scsi-hisi_sas-Modify-the-file-permissions-of-trigger.patch @@ -0,0 +1,45 @@ +From 9eafe4e70aead818a870aa28d6e691c01a956ebf Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Mon, 20 Jan 2020 20:22:34 +0800 +Subject: [PATCH 048/256] scsi: hisi_sas: Modify the file permissions of + trigger_dump to write only + +mainline inclusion +from mainline-v5.6-rc1 +commit 3cd2f3c35d29a50947a975feffdcbe2d6a2418c0 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3cd2f3c35d29a50947a975feffdcbe2d6a2418c0 + +---------------------------------------------------------------------- + +The trigger_dump file is only used to manually trigger the dump, and did +not provide a read callback function for it, so its file permission +setting to 600 is wrong,and should be changed to 200. + +Link: https://lore.kernel.org/r/1579522957-4393-5-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index ee2b22ba37f9..7185cc263597 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -4029,7 +4029,7 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) + + hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev), + hisi_sas_debugfs_dir); +- debugfs_create_file("trigger_dump", 0600, ++ debugfs_create_file("trigger_dump", 0200, + hisi_hba->debugfs_dir, + hisi_hba, + &hisi_sas_debugfs_trigger_dump_fops); +-- +2.27.0 + diff --git a/patches/0367-scsi-hisi_sas-Add-prints-for-v3-hw-interrupt-converg.patch b/patches/0367-scsi-hisi_sas-Add-prints-for-v3-hw-interrupt-converg.patch new file mode 100644 index 00000000..f3a8795e --- /dev/null +++ b/patches/0367-scsi-hisi_sas-Add-prints-for-v3-hw-interrupt-converg.patch @@ -0,0 +1,56 @@ +From d1560f7c868b359aebea3353693dbc32e8b40966 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Mon, 20 Jan 2020 20:22:35 +0800 +Subject: [PATCH 049/256] scsi: hisi_sas: Add prints for v3 hw interrupt + converge and automatic affinity + +mainline inclusion +from mainline-v5.6-rc1 +commit 33c77c31b752c561dd4b3c25661f949014c31370 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=33c77c31b752c561dd4b3c25661f949014c31370 + +---------------------------------------------------------------------- + +Add prints to inform the user of enabled features. + +Link: https://lore.kernel.org/r/1579522957-4393-6-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index c8328e1ef166..6a64653a68b9 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -2725,6 +2725,8 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) + .pre_vectors = HISI_SAS_CQ_INT_BASE_VECTORS_V3_HW, + }; + ++ dev_info(dev, "Enable MSI auto-affinity\n"); ++ + min_msi = HISI_SAS_MIN_VECTORS_V3_HW; + + hisi_hba->reply_map = devm_kcalloc(dev, nr_cpu_ids, +@@ -2786,6 +2788,9 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) + goto free_irq_vectors; + } + ++ if (hisi_sas_intr_conv) ++ dev_info(dev, "Enable interrupt converge\n"); ++ + /* Init tasklets for cq only */ + for (i = 0; i < hisi_hba->nvecs; i++) { + struct hisi_sas_cq *cq = &hisi_hba->cq[i]; +-- +2.27.0 + diff --git a/patches/0368-scsi-hisi_sas-Rename-hisi_sas_cq.pci_irq_mask.patch b/patches/0368-scsi-hisi_sas-Rename-hisi_sas_cq.pci_irq_mask.patch new file mode 100644 index 00000000..cfa2cf64 --- /dev/null +++ b/patches/0368-scsi-hisi_sas-Rename-hisi_sas_cq.pci_irq_mask.patch @@ -0,0 +1,74 @@ +From b21f1564636dafdb69f78c1c53dc6aa72af12c16 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Mon, 20 Jan 2020 20:22:36 +0800 +Subject: [PATCH 050/256] scsi: hisi_sas: Rename hisi_sas_cq.pci_irq_mask + +mainline inclusion +from mainline-v5.6-rc1 +commit 11e673206f217ce6604b7b0269e3cfc65171c380 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=11e673206f217ce6604b7b0269e3cfc65171c380 + +---------------------------------------------------------------------- + +In future we will want to use hisi_sas_cq.pci_irq_mask for non-pci +interrupt masks, so rename to be more general. + +Link: https://lore.kernel.org/r/1579522957-4393-7-git-send-email-john.garry@huawei.com +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas.h + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 2 +- + drivers/scsi/hisi_sas/hisi_sas_main.c | 2 +- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 6b66c056ecc8..f6dbb9dd3ea3 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -199,7 +199,7 @@ struct hisi_sas_port { + + struct hisi_sas_cq { + struct hisi_hba *hisi_hba; +- const struct cpumask *pci_irq_mask; ++ const struct cpumask *irq_mask; + struct tasklet_struct tasklet; + int rd_point; + int id; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 7185cc263597..87d5c745ad0f 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -2196,7 +2196,7 @@ hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, + case HISI_SAS_INT_ABT_DEV: + for (i = 0; i < hisi_hba->nvecs; i++) { + struct hisi_sas_cq *cq = &hisi_hba->cq[i]; +- const struct cpumask *mask = cq->pci_irq_mask; ++ const struct cpumask *mask = cq->irq_mask; + /* + * The kernel will not permit unmanaged (MSI are + * managed) IRQ affinity to offline CPUs, so +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 6a64653a68b9..11196e52b8df 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -2700,7 +2700,7 @@ static void setup_reply_map_v3_hw(struct hisi_hba *hisi_hba, int nvecs) + HISI_SAS_CQ_INT_BASE_VECTORS_V3_HW); + if (!mask) + goto fallback; +- cq->pci_irq_mask = mask; ++ cq->irq_mask = mask; + for_each_cpu(cpu, mask) + hisi_hba->reply_map[cpu] = queue; + } +-- +2.27.0 + diff --git a/patches/0369-scsi-hisi_sas-Use-dev_err-in-read_iost_itct_cache_v3.patch b/patches/0369-scsi-hisi_sas-Use-dev_err-in-read_iost_itct_cache_v3.patch new file mode 100644 index 00000000..ac0070e1 --- /dev/null +++ b/patches/0369-scsi-hisi_sas-Use-dev_err-in-read_iost_itct_cache_v3.patch @@ -0,0 +1,55 @@ +From f5d34efb7e7b9d8b8b748c913b5dae1de4d0fc47 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Wed, 11 Mar 2020 23:22:24 +0800 +Subject: [PATCH 051/256] scsi: hisi_sas: Use dev_err() in + read_iost_itct_cache_v3_hw() + +mainline inclusion +from mainline-v5.7-rc1 +commit 1e067dd8a3681310a36302640dc33c4f3fb0c190 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1e067dd8a3681310a36302640dc33c4f3fb0c190 + +---------------------------------------------------------------------- + +The print of pr_err() does not come with device information, so replace it +with dev_err(). Also improve the grammar in the message. + +Link: https://lore.kernel.org/r/1583940144-230800-1-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 11196e52b8df..1d12269c69cf 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -3440,6 +3440,7 @@ static void read_iost_itct_cache_v3_hw(struct hisi_hba *hisi_hba, + { + u32 cache_dw_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * + HISI_SAS_IOST_ITCT_CACHE_NUM; ++ struct device *dev = hisi_hba->dev; + u32 *buf = cache; + u32 i, val; + +@@ -3452,7 +3453,7 @@ static void read_iost_itct_cache_v3_hw(struct hisi_hba *hisi_hba, + } + + if (val != 0xffffffff) { +- pr_err("Issue occur when reading IOST/ITCT cache!\n"); ++ dev_err(dev, "Issue occurred in reading IOST/ITCT cache!\n"); + return; + } + +-- +2.27.0 + diff --git a/patches/0370-scsi-hisi_sas-Fix-build-error-without-SATA_HOST.patch b/patches/0370-scsi-hisi_sas-Fix-build-error-without-SATA_HOST.patch new file mode 100644 index 00000000..b47c2320 --- /dev/null +++ b/patches/0370-scsi-hisi_sas-Fix-build-error-without-SATA_HOST.patch @@ -0,0 +1,50 @@ +From 12e50f4d307d9f916618ecc15ae6ab8fd309c2c8 Mon Sep 17 00:00:00 2001 +From: YueHaibing +Date: Thu, 2 Apr 2020 16:58:12 +0800 +Subject: [PATCH 052/256] scsi: hisi_sas: Fix build error without SATA_HOST + +mainline inclusion +from mainline-v5.7-rc2 +commit 1d95b8a2d41f0cfbf3cefb5d986941bde2e1378f +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1d95b8a2d41f0cfbf3cefb5d986941bde2e1378f + +---------------------------------------------------------------------- + +If SATA_HOST is n, build fails: + +drivers/scsi/hisi_sas/hisi_sas_main.o: In function +`hisi_sas_fill_ata_reset_cmd': hisi_sas_main.c:(.text+0x2500): undefined +reference to `ata_tf_to_fis' + +Select SATA_HOST to fix this. + +Link: https://lore.kernel.org/r/20200402085812.32948-1-yuehaibing@huawei.com +Fixes: bd322af15ce9 ("ata: make SATA_PMP option selectable only if any SATA host driver is enabled") +Reported-by: Hulk Robot +Reviewed-by: Bartlomiej Zolnierkiewicz +Acked-by: John Garry +Signed-off-by: YueHaibing +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/scsi/hisi_sas/Kconfig b/drivers/scsi/hisi_sas/Kconfig +index 57183fce70fb..79ad42352825 100644 +--- a/drivers/scsi/hisi_sas/Kconfig ++++ b/drivers/scsi/hisi_sas/Kconfig +@@ -5,6 +5,7 @@ config SCSI_HISI_SAS + select SCSI_SAS_LIBSAS + select BLK_DEV_INTEGRITY + depends on ATA ++ select SATA_HOST + help + This driver supports HiSilicon's SAS HBA, including support based + on platform device +-- +2.27.0 + diff --git a/patches/0371-scsi-hisi_sas-Display-proc_name-in-sysfs.patch b/patches/0371-scsi-hisi_sas-Display-proc_name-in-sysfs.patch new file mode 100644 index 00000000..73215448 --- /dev/null +++ b/patches/0371-scsi-hisi_sas-Display-proc_name-in-sysfs.patch @@ -0,0 +1,78 @@ +From e0aa959a007e601c086a59ade4fb862e5b3d945c Mon Sep 17 00:00:00 2001 +From: Jason Yan +Date: Tue, 12 May 2020 19:32:58 +0800 +Subject: [PATCH 053/256] scsi: hisi_sas: Display proc_name in sysfs + +mainline inclusion +from mainline-v5.8-rc1 +commit 55ce24b3bfd75f76696a00f2666caaf806eebea2 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=55ce24b3bfd75f76696a00f2666caaf806eebea2 + +---------------------------------------------------------------------- + +The 'proc_name' entry in sysfs for hisi_sas is 'null' now because it is not +initialized in scsi_host_template. It looks like: + +[root@localhost ~]# cat /sys/class/scsi_host/host2/proc_name +(null) + +While the other driver's entry looks like: + +linux-vnMQMU:~ # cat /sys/class/scsi_host/host0/proc_name +megaraid_sas + +Link: https://lore.kernel.org/r/20200512113258.30781-1-yanaijie@huawei.com +Cc: John Garry +Cc: Xiang Chen +Acked-by: John Garry +Signed-off-by: Jason Yan +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 1 + + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 1 + + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 1 + + 3 files changed, 3 insertions(+) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +index 1228f282d443..c21a18703cab 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +@@ -1761,6 +1761,7 @@ static struct device_attribute *host_attrs_v1_hw[] = { + + static struct scsi_host_template sht_v1_hw = { + .name = DRV_NAME, ++ .proc_name = DRV_NAME, + .module = THIS_MODULE, + .queuecommand = sas_queuecommand, + .target_alloc = sas_target_alloc, +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +index 55faa3ec72f9..c044ce0a0f18 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -3552,6 +3552,7 @@ struct device_attribute *host_attrs_v2_hw[] = { + + static struct scsi_host_template sht_v2_hw = { + .name = DRV_NAME, ++ .proc_name = DRV_NAME, + .module = THIS_MODULE, + .queuecommand = sas_queuecommand, + .target_alloc = sas_target_alloc, +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 1d12269c69cf..beddbe30f46a 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -3466,6 +3466,7 @@ static void read_iost_itct_cache_v3_hw(struct hisi_hba *hisi_hba, + + static struct scsi_host_template sht_v3_hw = { + .name = DRV_NAME, ++ .proc_name = DRV_NAME, + .module = THIS_MODULE, + .queuecommand = sas_queuecommand, + .target_alloc = sas_target_alloc, +-- +2.27.0 + diff --git a/patches/0372-scsi-hisi_sas-Modify-the-commit-information-for-DSM-.patch b/patches/0372-scsi-hisi_sas-Modify-the-commit-information-for-DSM-.patch new file mode 100644 index 00000000..dc01ea15 --- /dev/null +++ b/patches/0372-scsi-hisi_sas-Modify-the-commit-information-for-DSM-.patch @@ -0,0 +1,54 @@ +From bc9f33c274fd9ccc3d0657060246cf13c4159130 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Fri, 15 May 2020 22:13:43 +0800 +Subject: [PATCH 054/256] scsi: hisi_sas: Modify the commit information for DSM + method + +mainline inclusion +from mainline-v5.8-rc1 +commit 1e954d1f002db802937deb87a868c3f62fe1badf +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1e954d1f002db802937deb87a868c3f62fe1badf + +---------------------------------------------------------------------- + +Make it clear that BIOS may modify some register settings. + +Link: https://lore.kernel.org/r/1589552025-165012-3-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index beddbe30f46a..64dd08b35710 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -1010,12 +1010,14 @@ static int hw_init_v3_hw(struct hisi_hba *hisi_hba) + } + + /* +- * Switch over to MSI handling due to non-standard PCI implementation. ++ * This DSM handles some hardware-related configurations: ++ * 1. Switch over to MSI error handling in kernel ++ * 2. BIOS *may* reset some register values through this method + */ + obj = acpi_evaluate_dsm(ACPI_HANDLE(dev), &guid, 0, + DSM_FUNC_ERR_HANDLE_MSI, NULL); + if (!obj) +- dev_warn(dev, "Switch over to MSI handling failed\n"); ++ dev_warn(dev, "can not find DSM method, ignore\n"); + else + ACPI_FREE(obj); + +-- +2.27.0 + diff --git a/patches/0373-scsi-hisi_sas-Add-SAS_RAS_INTR0-to-debugfs-register-.patch b/patches/0373-scsi-hisi_sas-Add-SAS_RAS_INTR0-to-debugfs-register-.patch new file mode 100644 index 00000000..a5a82660 --- /dev/null +++ b/patches/0373-scsi-hisi_sas-Add-SAS_RAS_INTR0-to-debugfs-register-.patch @@ -0,0 +1,44 @@ +From 93cff3ac69959b31914c09f017af32d5e82e6dd8 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Fri, 15 May 2020 22:13:44 +0800 +Subject: [PATCH 055/256] scsi: hisi_sas: Add SAS_RAS_INTR0 to debugfs register + name list + +mainline inclusion +from mainline-v5.8-rc1 +commit 1a0efb55b2bb9e970b8842030ce65d645ddba90c +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1a0efb55b2bb9e970b8842030ce65d645ddba90c + +---------------------------------------------------------------------- + +Register SAS_RAS_INTR0 can help us to figure out which ECC error has +occurred. This register is helpful to identify RAS issue, so we add it to +the list of debugfs register name list for easier retrieval. + +Link: https://lore.kernel.org/r/1589552025-165012-4-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 64dd08b35710..bdc47cf8d9e0 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -3279,6 +3279,7 @@ static const struct hisi_sas_debugfs_reg debugfs_axi_reg = { + }; + + static const struct hisi_sas_debugfs_reg_lu debugfs_ras_reg_lu[] = { ++ HISI_SAS_DEBUGFS_REG(SAS_RAS_INTR0), + HISI_SAS_DEBUGFS_REG(SAS_RAS_INTR1), + HISI_SAS_DEBUGFS_REG(SAS_RAS_INTR0_MASK), + HISI_SAS_DEBUGFS_REG(SAS_RAS_INTR1_MASK), +-- +2.27.0 + diff --git a/patches/0374-scsi-hisi_sas-Stop-returning-error-code-from-slot_co.patch b/patches/0374-scsi-hisi_sas-Stop-returning-error-code-from-slot_co.patch new file mode 100644 index 00000000..3c3e2d06 --- /dev/null +++ b/patches/0374-scsi-hisi_sas-Stop-returning-error-code-from-slot_co.patch @@ -0,0 +1,233 @@ +From eea66f4e6856e729db5fdbccdb29d7c55e49fbdc Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Fri, 15 May 2020 22:13:45 +0800 +Subject: [PATCH 056/256] scsi: hisi_sas: Stop returning error code from + slot_complete_vX_hw() + +mainline inclusion +from mainline-v5.8-rc1 +commit 1cdee004426164d1b00b66d3f6e7308c3714def6 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1cdee004426164d1b00b66d3f6e7308c3714def6 + +---------------------------------------------------------------------- + +The error codes are never checked, stop returning them. + +Link: https://lore.kernel.org/r/1589552025-165012-5-git-send-email-john.garry@huawei.com +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v1_hw.c + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 12 ++++-------- + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 16 ++++++---------- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 16 ++++++---------- + 3 files changed, 16 insertions(+), 28 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +index c21a18703cab..09cc42e66dd5 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +@@ -1179,15 +1179,14 @@ static void slot_err_v1_hw(struct hisi_hba *hisi_hba, + + } + +-static int slot_complete_v1_hw(struct hisi_hba *hisi_hba, +- struct hisi_sas_slot *slot) ++static void slot_complete_v1_hw(struct hisi_hba *hisi_hba, ++ struct hisi_sas_slot *slot) + { + struct sas_task *task = slot->task; + struct hisi_sas_device *sas_dev; + struct device *dev = hisi_hba->dev; + struct task_status_struct *ts; + struct domain_device *device; +- enum exec_status sts; + struct hisi_sas_complete_v1_hdr *complete_queue = + hisi_hba->complete_hdr[slot->cmplt_queue]; + struct hisi_sas_complete_v1_hdr *complete_hdr; +@@ -1198,7 +1197,7 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba, + cmplt_hdr_data = le32_to_cpu(complete_hdr->data); + + if (unlikely(!task || !task->lldd_task || !task->dev)) +- return -EINVAL; ++ return; + + ts = &task->task_status; + device = task->dev; +@@ -1265,7 +1264,7 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba, + slot_err_v1_hw(hisi_hba, task, slot); + if (unlikely(slot->abort)) { + sas_task_abort(task); +- return ts->stat; ++ return; + } + goto out; + } +@@ -1315,12 +1314,9 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba, + + out: + hisi_sas_slot_task_free(hisi_hba, task, slot, true); +- sts = ts->stat; + + if (task->task_done) + task->task_done(task); +- +- return sts; + } + + /* Interrupts */ +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +index c044ce0a0f18..6de3fe10c5be 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -2332,8 +2332,8 @@ static void slot_err_v2_hw(struct hisi_hba *hisi_hba, + } + } + +-static int +-slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) ++static void slot_complete_v2_hw(struct hisi_hba *hisi_hba, ++ struct hisi_sas_slot *slot) + { + struct sas_task *task = slot->task; + struct hisi_sas_device *sas_dev; +@@ -2341,7 +2341,6 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) + struct task_status_struct *ts; + struct domain_device *device; + struct sas_ha_struct *ha; +- enum exec_status sts; + struct hisi_sas_complete_v2_hdr *complete_queue = + hisi_hba->complete_hdr[slot->cmplt_queue]; + struct hisi_sas_complete_v2_hdr *complete_hdr = +@@ -2351,7 +2350,7 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) + u32 dw0; + + if (unlikely(!task || !task->lldd_task || !task->dev)) +- return -EINVAL; ++ return; + + ts = &task->task_status; + device = task->dev; +@@ -2422,7 +2421,7 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) + + if (unlikely(slot->abort)) { + sas_task_abort(task); +- return ts->stat; ++ return; + } + goto out; + } +@@ -2474,12 +2473,11 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) + } + + out: +- sts = ts->stat; + spin_lock_irqsave(&task->task_state_lock, flags); + if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { + spin_unlock_irqrestore(&task->task_state_lock, flags); + dev_info(dev, "slot complete: task(%pK) aborted\n", task); +- return SAS_ABORTED_TASK; ++ return; + } + task->task_state_flags |= SAS_TASK_STATE_DONE; + spin_unlock_irqrestore(&task->task_state_lock, flags); +@@ -2491,15 +2489,13 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) + spin_unlock_irqrestore(&device->done_lock, flags); + dev_info(dev, "slot complete: task(%pK) ignored\n", + task); +- return sts; ++ return; + } + spin_unlock_irqrestore(&device->done_lock, flags); + } + + if (task->task_done) + task->task_done(task); +- +- return sts; + } + + static void prep_ata_v2_hw(struct hisi_hba *hisi_hba, +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index bdc47cf8d9e0..7719c13df112 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -2389,8 +2389,8 @@ static int ssp_need_spin_up(struct hisi_sas_slot *slot) + return 0; + } + +-static int +-slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) ++static void slot_complete_v3_hw(struct hisi_hba *hisi_hba, ++ struct hisi_sas_slot *slot) + { + struct sas_task *task = slot->task; + struct hisi_sas_device *sas_dev; +@@ -2398,7 +2398,6 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) + struct task_status_struct *ts; + struct domain_device *device; + struct sas_ha_struct *ha; +- enum exec_status sts; + struct hisi_sas_complete_v3_hdr *complete_queue = + hisi_hba->complete_hdr[slot->cmplt_queue]; + struct hisi_sas_complete_v3_hdr *complete_hdr = +@@ -2408,7 +2407,7 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) + u32 dw0, dw1, dw3; + + if (unlikely(!task || !task->lldd_task || !task->dev)) +- return -EINVAL; ++ return; + + ts = &task->task_status; + device = task->dev; +@@ -2518,7 +2517,7 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) + else + sas_task_abort(task); + +- return ts->stat; ++ return; + } + goto out; + } +@@ -2576,12 +2575,11 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) + } + + out: +- sts = ts->stat; + spin_lock_irqsave(&task->task_state_lock, flags); + if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { + spin_unlock_irqrestore(&task->task_state_lock, flags); + dev_info(dev, "slot complete: task(%pK) aborted\n", task); +- return SAS_ABORTED_TASK; ++ return; + } + task->task_state_flags |= SAS_TASK_STATE_DONE; + spin_unlock_irqrestore(&task->task_state_lock, flags); +@@ -2593,15 +2591,13 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) + spin_unlock_irqrestore(&device->done_lock, flags); + dev_info(dev, "slot complete: task(%pK) ignored\n ", + task); +- return sts; ++ return; + } + spin_unlock_irqrestore(&device->done_lock, flags); + } + + if (task->task_done) + task->task_done(task); +- +- return sts; + } + + static void hisi_sas_disk_err_handler(struct hisi_hba *hisi_hba, +-- +2.27.0 + diff --git a/patches/0375-scsi-hisi_sas-Do-not-reset-phy-timer-to-wait-for-str.patch b/patches/0375-scsi-hisi_sas-Do-not-reset-phy-timer-to-wait-for-str.patch new file mode 100644 index 00000000..72195ac1 --- /dev/null +++ b/patches/0375-scsi-hisi_sas-Do-not-reset-phy-timer-to-wait-for-str.patch @@ -0,0 +1,54 @@ +From 670c3284c21c895ea549ad00a5a82552ae476514 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Fri, 15 May 2020 22:13:42 +0800 +Subject: [PATCH 057/256] scsi: hisi_sas: Do not reset phy timer to wait for + stray phy up + +mainline inclusion +from mainline-v5.8-rc1 +commit e16b9ed61e078d836a0f24a82080cf29d7539c7e +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e16b9ed61e078d836a0f24a82080cf29d7539c7e + +---------------------------------------------------------------------- + +We found out that after phy up, the hardware reports another oob interrupt +but did not follow a phy up interrupt: + +oob ready -> phy up -> DEV found -> oob read -> wait phy up -> timeout + +We run link reset when wait phy up timeout, and it send a normal disk into +reset processing. So we made some circumvention action in the code, so that +this abnormal oob interrupt will not start the timer to wait for phy up. + +Link: https://lore.kernel.org/r/1589552025-165012-2-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 87d5c745ad0f..037ab14e40ce 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -917,8 +917,11 @@ void hisi_sas_phy_oob_ready(struct hisi_hba *hisi_hba, int phy_no) + struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; + struct device *dev = hisi_hba->dev; + ++ dev_dbg(dev, "phy%d OOB ready\n", phy_no); ++ if (phy->phy_attached) ++ return; ++ + if (!timer_pending(&phy->timer)) { +- dev_dbg(dev, "phy%d OOB ready\n", phy_no); + phy->timer.expires = jiffies + HISI_SAS_WAIT_PHYUP_TIMEOUT * HZ; + add_timer(&phy->timer); + } +-- +2.27.0 + diff --git a/patches/0376-scsi-hisi_sas-Remove-one-kerneldoc-comment.patch b/patches/0376-scsi-hisi_sas-Remove-one-kerneldoc-comment.patch new file mode 100644 index 00000000..5931d3d1 --- /dev/null +++ b/patches/0376-scsi-hisi_sas-Remove-one-kerneldoc-comment.patch @@ -0,0 +1,42 @@ +From 1c3ce5783a526ceacfdc6da77c5f373eac998009 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Mon, 13 Jul 2020 16:04:31 +0800 +Subject: [PATCH 058/256] scsi: hisi_sas: Remove one kerneldoc comment + +mainline inclusion +from mainline-v5.9-rc1 +commit 3d570a28ee8d7e724fc740019746a6e79c8db06c +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3d570a28ee8d7e724fc740019746a6e79c8db06c + +---------------------------------------------------------------------- + +The comment for interrupt_init_v2_hw() should not be a kerneldoc +comment. Remove it. + +Link: https://lore.kernel.org/r/1594627471-235395-3-git-send-email-john.garry@huawei.com +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +index 6de3fe10c5be..7e0059d3b3ef 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -3317,7 +3317,7 @@ static irq_handler_t fatal_interrupts[HISI_SAS_FATAL_INT_NR] = { + fatal_axi_int_v2_hw + }; + +-/** ++/* + * There is a limitation in the hip06 chipset that we need + * to map in all mbigen interrupts, even if they are not used. + */ +-- +2.27.0 + diff --git a/patches/0377-block-add-REQ_HIPRI-and-inherit-it-from-IOCB_HIPRI.patch b/patches/0377-block-add-REQ_HIPRI-and-inherit-it-from-IOCB_HIPRI.patch new file mode 100644 index 00000000..bcc1fa6b --- /dev/null +++ b/patches/0377-block-add-REQ_HIPRI-and-inherit-it-from-IOCB_HIPRI.patch @@ -0,0 +1,121 @@ +From fb5c594b57a6071005d40bf0ade439c8f8f34a9f Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Wed, 29 Aug 2018 10:36:56 -0600 +Subject: [PATCH 059/256] block: add REQ_HIPRI and inherit it from IOCB_HIPRI + +mainline inclusion +from mainline-v5.0-rc1 +commit d1e36282b0bbd5de6a9c4d5275e94ef3b3438f48 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d1e36282b0bbd5de6a9c4d5275e94ef3b3438f48 + +---------------------------------------------------------------------- + +We use IOCB_HIPRI to poll for IO in the caller instead of scheduling. +This information is not available for (or after) IO submission. The +driver may make different queue choices based on the type of IO, so +make the fact that we will poll for this IO known to the lower layers +as well. + +Reviewed-by: Hannes Reinecke +Reviewed-by: Keith Busch +Reviewed-by: Sagi Grimberg +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang +--- + fs/block_dev.c | 2 ++ + fs/direct-io.c | 2 ++ + fs/iomap.c | 9 ++++++++- + include/linux/blk_types.h | 4 +++- + 4 files changed, 15 insertions(+), 2 deletions(-) + +diff --git a/fs/block_dev.c b/fs/block_dev.c +index e072d1ef16ef..03bfa4b9bff1 100644 +--- a/fs/block_dev.c ++++ b/fs/block_dev.c +@@ -253,6 +253,8 @@ __blkdev_direct_IO_simple(struct kiocb *iocb, struct iov_iter *iter, + bio.bi_opf = dio_bio_write_op(iocb); + task_io_account_write(ret); + } ++ if (iocb->ki_flags & IOCB_HIPRI) ++ bio.bi_opf |= REQ_HIPRI; + + if (iocb->ki_flags & IOCB_NOWAIT) + bio.bi_opf |= REQ_NOWAIT; +diff --git a/fs/direct-io.c b/fs/direct-io.c +index ec7c7d1c0329..29ed7852ac3a 100644 +--- a/fs/direct-io.c ++++ b/fs/direct-io.c +@@ -1267,6 +1267,8 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode, + } else { + dio->op = REQ_OP_READ; + } ++ if (iocb->ki_flags & IOCB_HIPRI) ++ dio->op_flags |= REQ_HIPRI; + + /* + * For AIO O_(D)SYNC writes we need to defer completions to a workqueue +diff --git a/fs/iomap.c b/fs/iomap.c +index 7078add7bbf9..5801deb814cd 100644 +--- a/fs/iomap.c ++++ b/fs/iomap.c +@@ -1599,6 +1599,7 @@ iomap_dio_zero(struct iomap_dio *dio, struct iomap *iomap, loff_t pos, + unsigned len) + { + struct page *page = ZERO_PAGE(0); ++ int flags = REQ_SYNC | REQ_IDLE; + struct bio *bio; + + bio = bio_alloc(GFP_KERNEL, 1); +@@ -1607,9 +1608,12 @@ iomap_dio_zero(struct iomap_dio *dio, struct iomap *iomap, loff_t pos, + bio->bi_private = dio; + bio->bi_end_io = iomap_dio_bio_end_io; + ++ if (dio->iocb->ki_flags & IOCB_HIPRI) ++ flags |= REQ_HIPRI; ++ + get_page(page); + __bio_add_page(bio, page, len, 0); +- bio_set_op_attrs(bio, REQ_OP_WRITE, REQ_SYNC | REQ_IDLE); ++ bio_set_op_attrs(bio, REQ_OP_WRITE, flags); + + atomic_inc(&dio->ref); + return submit_bio(bio); +@@ -1715,6 +1719,9 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length, + bio_set_pages_dirty(bio); + } + ++ if (dio->iocb->ki_flags & IOCB_HIPRI) ++ bio->bi_opf |= REQ_HIPRI; ++ + iov_iter_advance(dio->submit.iter, n); + + dio->size += n; +diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h +index 8075b9955bb3..32c6e0c098d1 100644 +--- a/include/linux/blk_types.h ++++ b/include/linux/blk_types.h +@@ -331,6 +331,8 @@ enum req_flag_bits { + /* command specific flags for REQ_OP_WRITE_ZEROES: */ + __REQ_NOUNMAP, /* do not free blocks when zeroing */ + ++ __REQ_HIPRI, ++ + /* for driver use */ + __REQ_DRV, + __REQ_SWAP, /* swapping request. */ +@@ -351,8 +353,8 @@ enum req_flag_bits { + #define REQ_RAHEAD (1ULL << __REQ_RAHEAD) + #define REQ_BACKGROUND (1ULL << __REQ_BACKGROUND) + #define REQ_NOWAIT (1ULL << __REQ_NOWAIT) +- + #define REQ_NOUNMAP (1ULL << __REQ_NOUNMAP) ++#define REQ_HIPRI (1ULL << __REQ_HIPRI) + + #define REQ_DRV (1ULL << __REQ_DRV) + #define REQ_SWAP (1ULL << __REQ_SWAP) +-- +2.27.0 + diff --git a/patches/0378-blk-mq-kill-q-mq_map.patch b/patches/0378-blk-mq-kill-q-mq_map.patch new file mode 100644 index 00000000..66b4d7dc --- /dev/null +++ b/patches/0378-blk-mq-kill-q-mq_map.patch @@ -0,0 +1,129 @@ +From ccdb0126032e20c3538f382b399681fe7c2aed59 Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Tue, 16 Oct 2018 14:23:06 -0600 +Subject: [PATCH 060/256] blk-mq: kill q->mq_map + +mainline inclusion +from mainline-v5.0-rc1 +commit a8908939af569ce2419f43fd56eeaf003bc3d85d +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a8908939af569ce2419f43fd56eeaf003bc3d85d + +---------------------------------------------------------------------- + +It's just a pointer to set->mq_map, use that instead. Move the +assignment a bit earlier, so we always know it's valid. + +Reviewed-by: Christoph Hellwig +Reviewed-by: Hannes Reinecke +Reviewed-by: Bart Van Assche +Reviewed-by: Keith Busch +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang + + Conflicts: + block/blk-mq.c +--- + block/blk-mq.c | 12 ++++-------- + block/blk-mq.h | 4 +++- + include/linux/blkdev.h | 2 -- + 3 files changed, 7 insertions(+), 11 deletions(-) + +diff --git a/block/blk-mq.c b/block/blk-mq.c +index d43c0b7723c2..226399eca307 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -2577,7 +2577,7 @@ static void blk_mq_map_swqueue(struct request_queue *q) + * If the cpu isn't present, the cpu is mapped to first hctx. + */ + for_each_possible_cpu(i) { +- hctx_idx = q->mq_map[i]; ++ hctx_idx = set->mq_map[i]; + /* unmapped hw queue can be remapped after CPU topo changed */ + if (!set->tags[hctx_idx] && + !__blk_mq_alloc_rq_map(set, hctx_idx)) { +@@ -2587,7 +2587,7 @@ static void blk_mq_map_swqueue(struct request_queue *q) + * case, remap the current ctx to hctx[0] which + * is guaranteed to always have tags allocated + */ +- q->mq_map[i] = 0; ++ set->mq_map[i] = 0; + } + + ctx = per_cpu_ptr(q->queue_ctx, i); +@@ -2685,8 +2685,6 @@ static void blk_mq_del_queue_tag_set(struct request_queue *q) + static void blk_mq_add_queue_tag_set(struct blk_mq_tag_set *set, + struct request_queue *q) + { +- q->tag_set = set; +- + mutex_lock(&set->tag_list_lock); + + /* +@@ -2753,8 +2751,6 @@ void blk_mq_release(struct request_queue *q) + kobject_put(&hctx->kobj); + } + +- q->mq_map = NULL; +- + kfree(q->queue_hw_ctx); + + /* +@@ -2826,7 +2822,7 @@ static void blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set, + int node; + struct blk_mq_hw_ctx *hctx; + +- node = blk_mq_hw_queue_to_node(q->mq_map, i); ++ node = blk_mq_hw_queue_to_node(set->mq_map, i); + /* + * If the hw queue has been mapped to another numa node, + * we need to realloc the hctx. If allocation fails, fallback +@@ -2900,7 +2896,6 @@ struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set, + + INIT_LIST_HEAD(&q->unused_hctx_list); + spin_lock_init(&q->unused_hctx_lock); +- q->mq_map = set->mq_map; + + blk_mq_realloc_hw_ctxs(set, q); + if (!q->nr_hw_queues) +@@ -2910,6 +2905,7 @@ struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set, + blk_queue_rq_timeout(q, set->timeout ? set->timeout : 30 * HZ); + + q->nr_queues = nr_cpu_ids; ++ q->tag_set = set; + + q->queue_flags |= QUEUE_FLAG_MQ_DEFAULT; + +diff --git a/block/blk-mq.h b/block/blk-mq.h +index c6ec9aa12fb2..d224a79cc110 100644 +--- a/block/blk-mq.h ++++ b/block/blk-mq.h +@@ -85,7 +85,9 @@ extern int blk_mq_hw_queue_to_node(unsigned int *map, unsigned int); + static inline struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *q, + int cpu) + { +- return q->queue_hw_ctx[q->mq_map[cpu]]; ++ struct blk_mq_tag_set *set = q->tag_set; ++ ++ return q->queue_hw_ctx[set->mq_map[cpu]]; + } + + /* +diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h +index aac3fa0c4601..36d914d81463 100644 +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -487,8 +487,6 @@ struct request_queue { + + const struct blk_mq_ops *mq_ops; + +- unsigned int *mq_map; +- + /* sw queues */ + struct blk_mq_ctx __percpu *queue_ctx; + unsigned int nr_queues; +-- +2.27.0 + diff --git a/patches/0379-fix-kabi-broken-due-to-change-of-struct-struct-reque.patch b/patches/0379-fix-kabi-broken-due-to-change-of-struct-struct-reque.patch new file mode 100644 index 00000000..79f6e36a --- /dev/null +++ b/patches/0379-fix-kabi-broken-due-to-change-of-struct-struct-reque.patch @@ -0,0 +1,38 @@ +From 5e10cda50f2aa7e22cdc0af41ba16bbfc9c086f4 Mon Sep 17 00:00:00 2001 +From: YunYi Yang +Date: Sat, 16 Sep 2023 22:28:14 +0800 +Subject: [PATCH 061/256] fix kabi broken due to change of struct struct + request_queue + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +---------------------------------------------------------------------------- + +Commit ("blk-mq: kill q->mq_map") changes the +struct request_queue, so we need to fix kabi broken problem. + +Signed-off-by: YunYi Yang +--- + include/linux/blkdev.h | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h +index 36d914d81463..74cb02947a18 100644 +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -487,6 +487,10 @@ struct request_queue { + + const struct blk_mq_ops *mq_ops; + ++#ifdef __GENKSYMS__ ++ unsigned int *mq_map; ++#endif ++ + /* sw queues */ + struct blk_mq_ctx __percpu *queue_ctx; + unsigned int nr_queues; +-- +2.27.0 + diff --git a/patches/0380-blk-mq-abstract-out-queue-map.patch b/patches/0380-blk-mq-abstract-out-queue-map.patch new file mode 100644 index 00000000..2390323b --- /dev/null +++ b/patches/0380-blk-mq-abstract-out-queue-map.patch @@ -0,0 +1,476 @@ +From 178fb53762d32e887de2e80d0010bf36e1153947 Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Mon, 29 Oct 2018 13:06:14 -0600 +Subject: [PATCH 062/256] blk-mq: abstract out queue map + +mainline inclusion +from mainline-v5.0-rc1 +commit ed76e329d74a4b15ac0f5fd3adbd52ec0178a134 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ed76e329d74a4b15ac0f5fd3adbd52ec0178a134 + +---------------------------------------------------------------------- + +This is in preparation for allowing multiple sets of maps per +queue, if so desired. + +Reviewed-by: Hannes Reinecke +Reviewed-by: Bart Van Assche +Reviewed-by: Keith Busch +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang +--- + block/blk-mq-cpumap.c | 10 ++++---- + block/blk-mq-pci.c | 10 ++++---- + block/blk-mq-rdma.c | 4 ++-- + block/blk-mq-virtio.c | 8 +++---- + block/blk-mq.c | 34 ++++++++++++++------------- + block/blk-mq.h | 8 +++---- + drivers/block/virtio_blk.c | 2 +- + drivers/nvme/host/pci.c | 2 +- + drivers/scsi/qla2xxx/qla_os.c | 5 ++-- + drivers/scsi/scsi_lib.c | 2 +- + drivers/scsi/smartpqi/smartpqi_init.c | 3 ++- + drivers/scsi/virtio_scsi.c | 3 ++- + include/linux/blk-mq-pci.h | 4 ++-- + include/linux/blk-mq-virtio.h | 4 ++-- + include/linux/blk-mq.h | 15 +++++++++--- + 15 files changed, 64 insertions(+), 50 deletions(-) + +diff --git a/block/blk-mq-cpumap.c b/block/blk-mq-cpumap.c +index 3eb169f15842..6e6686c55984 100644 +--- a/block/blk-mq-cpumap.c ++++ b/block/blk-mq-cpumap.c +@@ -30,10 +30,10 @@ static int get_first_sibling(unsigned int cpu) + return cpu; + } + +-int blk_mq_map_queues(struct blk_mq_tag_set *set) ++int blk_mq_map_queues(struct blk_mq_queue_map *qmap) + { +- unsigned int *map = set->mq_map; +- unsigned int nr_queues = set->nr_hw_queues; ++ unsigned int *map = qmap->mq_map; ++ unsigned int nr_queues = qmap->nr_queues; + unsigned int cpu, first_sibling; + + for_each_possible_cpu(cpu) { +@@ -62,12 +62,12 @@ EXPORT_SYMBOL_GPL(blk_mq_map_queues); + * We have no quick way of doing reverse lookups. This is only used at + * queue init time, so runtime isn't important. + */ +-int blk_mq_hw_queue_to_node(unsigned int *mq_map, unsigned int index) ++int blk_mq_hw_queue_to_node(struct blk_mq_queue_map *qmap, unsigned int index) + { + int i; + + for_each_possible_cpu(i) { +- if (index == mq_map[i]) ++ if (index == qmap->mq_map[i]) + return local_memory_node(cpu_to_node(i)); + } + +diff --git a/block/blk-mq-pci.c b/block/blk-mq-pci.c +index db644ec624f5..40333d60a850 100644 +--- a/block/blk-mq-pci.c ++++ b/block/blk-mq-pci.c +@@ -31,26 +31,26 @@ + * that maps a queue to the CPUs that have irq affinity for the corresponding + * vector. + */ +-int blk_mq_pci_map_queues(struct blk_mq_tag_set *set, struct pci_dev *pdev, ++int blk_mq_pci_map_queues(struct blk_mq_queue_map *qmap, struct pci_dev *pdev, + int offset) + { + const struct cpumask *mask; + unsigned int queue, cpu; + +- for (queue = 0; queue < set->nr_hw_queues; queue++) { ++ for (queue = 0; queue < qmap->nr_queues; queue++) { + mask = pci_irq_get_affinity(pdev, queue + offset); + if (!mask) + goto fallback; + + for_each_cpu(cpu, mask) +- set->mq_map[cpu] = queue; ++ qmap->mq_map[cpu] = queue; + } + + return 0; + + fallback: +- WARN_ON_ONCE(set->nr_hw_queues > 1); +- blk_mq_clear_mq_map(set); ++ WARN_ON_ONCE(qmap->nr_queues > 1); ++ blk_mq_clear_mq_map(qmap); + return 0; + } + EXPORT_SYMBOL_GPL(blk_mq_pci_map_queues); +diff --git a/block/blk-mq-rdma.c b/block/blk-mq-rdma.c +index 996167f1de18..a71576aff3a5 100644 +--- a/block/blk-mq-rdma.c ++++ b/block/blk-mq-rdma.c +@@ -41,12 +41,12 @@ int blk_mq_rdma_map_queues(struct blk_mq_tag_set *set, + goto fallback; + + for_each_cpu(cpu, mask) +- set->mq_map[cpu] = queue; ++ set->map[0].mq_map[cpu] = queue; + } + + return 0; + + fallback: +- return blk_mq_map_queues(set); ++ return blk_mq_map_queues(&set->map[0]); + } + EXPORT_SYMBOL_GPL(blk_mq_rdma_map_queues); +diff --git a/block/blk-mq-virtio.c b/block/blk-mq-virtio.c +index c3afbca11299..661fbfef480f 100644 +--- a/block/blk-mq-virtio.c ++++ b/block/blk-mq-virtio.c +@@ -29,7 +29,7 @@ + * that maps a queue to the CPUs that have irq affinity for the corresponding + * vector. + */ +-int blk_mq_virtio_map_queues(struct blk_mq_tag_set *set, ++int blk_mq_virtio_map_queues(struct blk_mq_queue_map *qmap, + struct virtio_device *vdev, int first_vec) + { + const struct cpumask *mask; +@@ -38,17 +38,17 @@ int blk_mq_virtio_map_queues(struct blk_mq_tag_set *set, + if (!vdev->config->get_vq_affinity) + goto fallback; + +- for (queue = 0; queue < set->nr_hw_queues; queue++) { ++ for (queue = 0; queue < qmap->nr_queues; queue++) { + mask = vdev->config->get_vq_affinity(vdev, first_vec + queue); + if (!mask) + goto fallback; + + for_each_cpu(cpu, mask) +- set->mq_map[cpu] = queue; ++ qmap->mq_map[cpu] = queue; + } + + return 0; + fallback: +- return blk_mq_map_queues(set); ++ return blk_mq_map_queues(qmap); + } + EXPORT_SYMBOL_GPL(blk_mq_virtio_map_queues); +diff --git a/block/blk-mq.c b/block/blk-mq.c +index 226399eca307..d27de16d158e 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -2165,7 +2165,7 @@ struct blk_mq_tags *blk_mq_alloc_rq_map(struct blk_mq_tag_set *set, + struct blk_mq_tags *tags; + int node; + +- node = blk_mq_hw_queue_to_node(set->mq_map, hctx_idx); ++ node = blk_mq_hw_queue_to_node(&set->map[0], hctx_idx); + if (node == NUMA_NO_NODE) + node = set->numa_node; + +@@ -2216,7 +2216,7 @@ int blk_mq_alloc_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags, + size_t rq_size, left; + int node; + +- node = blk_mq_hw_queue_to_node(set->mq_map, hctx_idx); ++ node = blk_mq_hw_queue_to_node(&set->map[0], hctx_idx); + if (node == NUMA_NO_NODE) + node = set->numa_node; + +@@ -2577,7 +2577,7 @@ static void blk_mq_map_swqueue(struct request_queue *q) + * If the cpu isn't present, the cpu is mapped to first hctx. + */ + for_each_possible_cpu(i) { +- hctx_idx = set->mq_map[i]; ++ hctx_idx = set->map[0].mq_map[i]; + /* unmapped hw queue can be remapped after CPU topo changed */ + if (!set->tags[hctx_idx] && + !__blk_mq_alloc_rq_map(set, hctx_idx)) { +@@ -2587,7 +2587,7 @@ static void blk_mq_map_swqueue(struct request_queue *q) + * case, remap the current ctx to hctx[0] which + * is guaranteed to always have tags allocated + */ +- set->mq_map[i] = 0; ++ set->map[0].mq_map[i] = 0; + } + + ctx = per_cpu_ptr(q->queue_ctx, i); +@@ -2822,7 +2822,7 @@ static void blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set, + int node; + struct blk_mq_hw_ctx *hctx; + +- node = blk_mq_hw_queue_to_node(set->mq_map, i); ++ node = blk_mq_hw_queue_to_node(&set->map[0], i); + /* + * If the hw queue has been mapped to another numa node, + * we need to realloc the hctx. If allocation fails, fallback +@@ -3033,18 +3033,18 @@ static int blk_mq_update_queue_map(struct blk_mq_tag_set *set) + * for (queue = 0; queue < set->nr_hw_queues; queue++) { + * mask = get_cpu_mask(queue) + * for_each_cpu(cpu, mask) +- * set->mq_map[cpu] = queue; ++ * set->map.mq_map[cpu] = queue; + * } + * + * When we need to remap, the table has to be cleared for + * killing stale mapping since one CPU may not be mapped + * to any hw queue. + */ +- blk_mq_clear_mq_map(set); ++ blk_mq_clear_mq_map(&set->map[0]); + + return set->ops->map_queues(set); + } else +- return blk_mq_map_queues(set); ++ return blk_mq_map_queues(&set->map[0]); + } + + /* +@@ -3099,10 +3099,12 @@ int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set) + return -ENOMEM; + + ret = -ENOMEM; +- set->mq_map = kcalloc_node(nr_cpu_ids, sizeof(*set->mq_map), +- GFP_KERNEL, set->numa_node); +- if (!set->mq_map) ++ set->map[0].mq_map = kcalloc_node(nr_cpu_ids, ++ sizeof(*set->map[0].mq_map), ++ GFP_KERNEL, set->numa_node); ++ if (!set->map[0].mq_map) + goto out_free_tags; ++ set->map[0].nr_queues = set->nr_hw_queues; + + ret = blk_mq_update_queue_map(set); + if (ret) +@@ -3118,8 +3120,8 @@ int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set) + return 0; + + out_free_mq_map: +- kfree(set->mq_map); +- set->mq_map = NULL; ++ kfree(set->map[0].mq_map); ++ set->map[0].mq_map = NULL; + out_free_tags: + kfree(set->tags); + set->tags = NULL; +@@ -3134,8 +3136,8 @@ void blk_mq_free_tag_set(struct blk_mq_tag_set *set) + for (i = 0; i < nr_cpu_ids; i++) + blk_mq_free_map_and_requests(set, i); + +- kfree(set->mq_map); +- set->mq_map = NULL; ++ kfree(set->map[0].mq_map); ++ set->map[0].mq_map = NULL; + + kfree(set->tags); + set->tags = NULL; +@@ -3303,7 +3305,7 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, + blk_mq_free_map_and_requests(set, i); + + set->nr_hw_queues = prev_nr_hw_queues; +- blk_mq_map_queues(set); ++ blk_mq_map_queues(&set->map[0]); + goto fallback; + } + blk_mq_map_swqueue(q); +diff --git a/block/blk-mq.h b/block/blk-mq.h +index d224a79cc110..fd61bb3d3eb1 100644 +--- a/block/blk-mq.h ++++ b/block/blk-mq.h +@@ -80,14 +80,14 @@ void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx, + /* + * CPU -> queue mappings + */ +-extern int blk_mq_hw_queue_to_node(unsigned int *map, unsigned int); ++extern int blk_mq_hw_queue_to_node(struct blk_mq_queue_map *qmap, unsigned int); + + static inline struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *q, + int cpu) + { + struct blk_mq_tag_set *set = q->tag_set; + +- return q->queue_hw_ctx[set->mq_map[cpu]]; ++ return q->queue_hw_ctx[set->map[0].mq_map[cpu]]; + } + + /* +@@ -218,12 +218,12 @@ static inline void blk_mq_put_driver_tag(struct request *rq) + __blk_mq_put_driver_tag(hctx, rq); + } + +-static inline void blk_mq_clear_mq_map(struct blk_mq_tag_set *set) ++static inline void blk_mq_clear_mq_map(struct blk_mq_queue_map *qmap) + { + int cpu; + + for_each_possible_cpu(cpu) +- set->mq_map[cpu] = 0; ++ qmap->mq_map[cpu] = 0; + } + + static inline void blk_mq_free_requests(struct list_head *list) +diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c +index 8ec6b0013826..212f81cc0f1d 100644 +--- a/drivers/block/virtio_blk.c ++++ b/drivers/block/virtio_blk.c +@@ -765,7 +765,7 @@ static int virtblk_map_queues(struct blk_mq_tag_set *set) + { + struct virtio_blk *vblk = set->driver_data; + +- return blk_mq_virtio_map_queues(set, vblk->vdev, 0); ++ return blk_mq_virtio_map_queues(&set->map[0], vblk->vdev, 0); + } + + #ifdef CONFIG_VIRTIO_BLK_SCSI +diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c +index f66c0062736e..a409e458d6a4 100644 +--- a/drivers/nvme/host/pci.c ++++ b/drivers/nvme/host/pci.c +@@ -457,7 +457,7 @@ static int nvme_pci_map_queues(struct blk_mq_tag_set *set) + { + struct nvme_dev *dev = set->driver_data; + +- return blk_mq_pci_map_queues(set, to_pci_dev(dev->dev), ++ return blk_mq_pci_map_queues(&set->map[0], to_pci_dev(dev->dev), + dev->num_vecs > 1 ? 1 /* admin queue */ : 0); + } + +diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c +index 8e9d386146ac..31fa7e6c44af 100644 +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -6881,11 +6881,12 @@ static int qla2xxx_map_queues(struct Scsi_Host *shost) + { + int rc; + scsi_qla_host_t *vha = (scsi_qla_host_t *)shost->hostdata; ++ struct blk_mq_queue_map *qmap = &shost->tag_set.map[0]; + + if (USER_CTRL_IRQ(vha->hw)) +- rc = blk_mq_map_queues(&shost->tag_set); ++ rc = blk_mq_map_queues(qmap); + else +- rc = blk_mq_pci_map_queues(&shost->tag_set, vha->hw->pdev, 0); ++ rc = blk_mq_pci_map_queues(qmap, vha->hw->pdev, 0); + return rc; + } + +diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c +index 719cdf5628ec..ed21a6ef6df2 100644 +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -2302,7 +2302,7 @@ static int scsi_map_queues(struct blk_mq_tag_set *set) + + if (shost->hostt->map_queues) + return shost->hostt->map_queues(shost); +- return blk_mq_map_queues(set); ++ return blk_mq_map_queues(&set->map[0]); + } + + void __scsi_init_queue(struct Scsi_Host *shost, struct request_queue *q) +diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c +index d9df5627cfb6..ed72ad0b7c2d 100644 +--- a/drivers/scsi/smartpqi/smartpqi_init.c ++++ b/drivers/scsi/smartpqi/smartpqi_init.c +@@ -5346,7 +5346,8 @@ static int pqi_map_queues(struct Scsi_Host *shost) + { + struct pqi_ctrl_info *ctrl_info = shost_to_hba(shost); + +- return blk_mq_pci_map_queues(&shost->tag_set, ctrl_info->pci_dev, 0); ++ return blk_mq_pci_map_queues(&shost->tag_set.map[0], ++ ctrl_info->pci_dev, 0); + } + + static int pqi_getpciinfo_ioctl(struct pqi_ctrl_info *ctrl_info, +diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c +index ba84514b662a..b69c04087691 100644 +--- a/drivers/scsi/virtio_scsi.c ++++ b/drivers/scsi/virtio_scsi.c +@@ -722,8 +722,9 @@ static void virtscsi_target_destroy(struct scsi_target *starget) + static int virtscsi_map_queues(struct Scsi_Host *shost) + { + struct virtio_scsi *vscsi = shost_priv(shost); ++ struct blk_mq_queue_map *qmap = &shost->tag_set.map[0]; + +- return blk_mq_virtio_map_queues(&shost->tag_set, vscsi->vdev, 2); ++ return blk_mq_virtio_map_queues(qmap, vscsi->vdev, 2); + } + + /* +diff --git a/include/linux/blk-mq-pci.h b/include/linux/blk-mq-pci.h +index 9f4c17f0d2d8..0b1f45c62623 100644 +--- a/include/linux/blk-mq-pci.h ++++ b/include/linux/blk-mq-pci.h +@@ -2,10 +2,10 @@ + #ifndef _LINUX_BLK_MQ_PCI_H + #define _LINUX_BLK_MQ_PCI_H + +-struct blk_mq_tag_set; ++struct blk_mq_queue_map; + struct pci_dev; + +-int blk_mq_pci_map_queues(struct blk_mq_tag_set *set, struct pci_dev *pdev, ++int blk_mq_pci_map_queues(struct blk_mq_queue_map *qmap, struct pci_dev *pdev, + int offset); + + #endif /* _LINUX_BLK_MQ_PCI_H */ +diff --git a/include/linux/blk-mq-virtio.h b/include/linux/blk-mq-virtio.h +index 69b4da262c45..687ae287e1dc 100644 +--- a/include/linux/blk-mq-virtio.h ++++ b/include/linux/blk-mq-virtio.h +@@ -2,10 +2,10 @@ + #ifndef _LINUX_BLK_MQ_VIRTIO_H + #define _LINUX_BLK_MQ_VIRTIO_H + +-struct blk_mq_tag_set; ++struct blk_mq_queue_map; + struct virtio_device; + +-int blk_mq_virtio_map_queues(struct blk_mq_tag_set *set, ++int blk_mq_virtio_map_queues(struct blk_mq_queue_map *qmap, + struct virtio_device *vdev, int first_vec); + + #endif /* _LINUX_BLK_MQ_VIRTIO_H */ +diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h +index 3695a43eb556..8417351f19ea 100644 +--- a/include/linux/blk-mq.h ++++ b/include/linux/blk-mq.h +@@ -84,10 +84,19 @@ struct blk_mq_hw_ctx { + struct srcu_struct srcu[0]; + }; + ++struct blk_mq_queue_map { ++ unsigned int *mq_map; ++ unsigned int nr_queues; ++}; ++ ++enum { ++ HCTX_MAX_TYPES = 1, ++}; ++ + struct blk_mq_tag_set { +- unsigned int *mq_map; ++ struct blk_mq_queue_map map[HCTX_MAX_TYPES]; + const struct blk_mq_ops *ops; +- unsigned int nr_hw_queues; ++ unsigned int nr_hw_queues; /* nr hw queues across maps */ + unsigned int queue_depth; /* max hw supported */ + unsigned int reserved_tags; + unsigned int cmd_size; /* per-request extra data */ +@@ -326,7 +335,7 @@ void blk_mq_freeze_queue_wait(struct request_queue *q); + int blk_mq_freeze_queue_wait_timeout(struct request_queue *q, + unsigned long timeout); + +-int blk_mq_map_queues(struct blk_mq_tag_set *set); ++int blk_mq_map_queues(struct blk_mq_queue_map *qmap); + void blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, int nr_hw_queues); + + void blk_mq_quiesce_queue_nowait(struct request_queue *q); +-- +2.27.0 + diff --git a/patches/0381-fix-kabi-broken-due-to-change-of-function-blk_mq_map.patch b/patches/0381-fix-kabi-broken-due-to-change-of-function-blk_mq_map.patch new file mode 100644 index 00000000..2cde2c93 --- /dev/null +++ b/patches/0381-fix-kabi-broken-due-to-change-of-function-blk_mq_map.patch @@ -0,0 +1,258 @@ +From 719bb7ca29c86dd87566a44e47314527eedee0ef Mon Sep 17 00:00:00 2001 +From: YunYi Yang +Date: Sat, 26 Aug 2023 10:21:12 +0800 +Subject: [PATCH 063/256] fix kabi broken due to change of function + blk_mq_map_queues and blk_mq_pci_map_queues + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +---------------------------------------------------------------------------- + +Commit ("blk-mq: abstract out queue map") +changes function blk_mq_map_queues and blk_mq_pci_map_queues, +so we need to fix kabi broken problem. + +Signed-off-by: YunYi Yang +--- + block/blk-mq-cpumap.c | 10 ++++++-- + block/blk-mq-pci.c | 37 +++++++++++++++++---------- + block/blk-mq-rdma.c | 2 +- + block/blk-mq-virtio.c | 2 +- + block/blk-mq.c | 4 +-- + drivers/nvme/host/pci.c | 2 +- + drivers/scsi/qla2xxx/qla_os.c | 4 +-- + drivers/scsi/scsi_lib.c | 2 +- + drivers/scsi/smartpqi/smartpqi_init.c | 2 +- + include/linux/blk-mq-pci.h | 6 +++-- + include/linux/blk-mq.h | 8 ++++-- + 11 files changed, 50 insertions(+), 29 deletions(-) + +diff --git a/block/blk-mq-cpumap.c b/block/blk-mq-cpumap.c +index 6e6686c55984..cd49d2ba670c 100644 +--- a/block/blk-mq-cpumap.c ++++ b/block/blk-mq-cpumap.c +@@ -30,7 +30,13 @@ static int get_first_sibling(unsigned int cpu) + return cpu; + } + +-int blk_mq_map_queues(struct blk_mq_queue_map *qmap) ++int blk_mq_map_queues(struct blk_mq_tag_set *set) ++{ ++ return blk_mq_map_queues_by_qmap(&set->map[0]); ++} ++EXPORT_SYMBOL_GPL(blk_mq_map_queues); ++ ++int blk_mq_map_queues_by_qmap(struct blk_mq_queue_map *qmap) + { + unsigned int *map = qmap->mq_map; + unsigned int nr_queues = qmap->nr_queues; +@@ -56,7 +62,7 @@ int blk_mq_map_queues(struct blk_mq_queue_map *qmap) + + return 0; + } +-EXPORT_SYMBOL_GPL(blk_mq_map_queues); ++EXPORT_SYMBOL_GPL(blk_mq_map_queues_by_qmap); + + /* + * We have no quick way of doing reverse lookups. This is only used at +diff --git a/block/blk-mq-pci.c b/block/blk-mq-pci.c +index 40333d60a850..6501d9632f59 100644 +--- a/block/blk-mq-pci.c ++++ b/block/blk-mq-pci.c +@@ -19,20 +19,10 @@ + + #include "blk-mq.h" + +-/** +- * blk_mq_pci_map_queues - provide a default queue mapping for PCI device +- * @set: tagset to provide the mapping for +- * @pdev: PCI device associated with @set. +- * @offset: Offset to use for the pci irq vector +- * +- * This function assumes the PCI device @pdev has at least as many available +- * interrupt vectors as @set has queues. It will then query the vector +- * corresponding to each queue for it's affinity mask and built queue mapping +- * that maps a queue to the CPUs that have irq affinity for the corresponding +- * vector. +- */ +-int blk_mq_pci_map_queues(struct blk_mq_queue_map *qmap, struct pci_dev *pdev, +- int offset) ++ ++int blk_mq_pci_map_queues_by_qmap(struct blk_mq_queue_map *qmap, ++ struct pci_dev *pdev, ++ int offset) + { + const struct cpumask *mask; + unsigned int queue, cpu; +@@ -53,4 +43,23 @@ int blk_mq_pci_map_queues(struct blk_mq_queue_map *qmap, struct pci_dev *pdev, + blk_mq_clear_mq_map(qmap); + return 0; + } ++EXPORT_SYMBOL_GPL(blk_mq_pci_map_queues_by_qmap); ++ ++/** ++ * blk_mq_pci_map_queues - provide a default queue mapping for PCI device ++ * @set: tagset to provide the mapping for ++ * @pdev: PCI device associated with @set. ++ * @offset: Offset to use for the pci irq vector ++ * ++ * This function assumes the PCI device @pdev has at least as many available ++ * interrupt vectors as @set has queues. It will then query the vector ++ * corresponding to each queue for it's affinity mask and built queue mapping ++ * that maps a queue to the CPUs that have irq affinity for the corresponding ++ * vector. ++ */ ++int blk_mq_pci_map_queues(struct blk_mq_tag_set *set, struct pci_dev *pdev, ++ int offset) ++{ ++ return blk_mq_pci_map_queues_by_qmap(&set->map[0], pdev, offset); ++} + EXPORT_SYMBOL_GPL(blk_mq_pci_map_queues); +diff --git a/block/blk-mq-rdma.c b/block/blk-mq-rdma.c +index a71576aff3a5..7a7690023484 100644 +--- a/block/blk-mq-rdma.c ++++ b/block/blk-mq-rdma.c +@@ -47,6 +47,6 @@ int blk_mq_rdma_map_queues(struct blk_mq_tag_set *set, + return 0; + + fallback: +- return blk_mq_map_queues(&set->map[0]); ++ return blk_mq_map_queues_by_qmap(&set->map[0]); + } + EXPORT_SYMBOL_GPL(blk_mq_rdma_map_queues); +diff --git a/block/blk-mq-virtio.c b/block/blk-mq-virtio.c +index 661fbfef480f..f5bd128c9b2e 100644 +--- a/block/blk-mq-virtio.c ++++ b/block/blk-mq-virtio.c +@@ -49,6 +49,6 @@ int blk_mq_virtio_map_queues(struct blk_mq_queue_map *qmap, + + return 0; + fallback: +- return blk_mq_map_queues(qmap); ++ return blk_mq_map_queues_by_qmap(qmap); + } + EXPORT_SYMBOL_GPL(blk_mq_virtio_map_queues); +diff --git a/block/blk-mq.c b/block/blk-mq.c +index d27de16d158e..de8892ddd67f 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -3044,7 +3044,7 @@ static int blk_mq_update_queue_map(struct blk_mq_tag_set *set) + + return set->ops->map_queues(set); + } else +- return blk_mq_map_queues(&set->map[0]); ++ return blk_mq_map_queues_by_qmap(&set->map[0]); + } + + /* +@@ -3305,7 +3305,7 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, + blk_mq_free_map_and_requests(set, i); + + set->nr_hw_queues = prev_nr_hw_queues; +- blk_mq_map_queues(&set->map[0]); ++ blk_mq_map_queues_by_qmap(&set->map[0]); + goto fallback; + } + blk_mq_map_swqueue(q); +diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c +index a409e458d6a4..d373a0b7957e 100644 +--- a/drivers/nvme/host/pci.c ++++ b/drivers/nvme/host/pci.c +@@ -457,7 +457,7 @@ static int nvme_pci_map_queues(struct blk_mq_tag_set *set) + { + struct nvme_dev *dev = set->driver_data; + +- return blk_mq_pci_map_queues(&set->map[0], to_pci_dev(dev->dev), ++ return blk_mq_pci_map_queues_by_qmap(&set->map[0], to_pci_dev(dev->dev), + dev->num_vecs > 1 ? 1 /* admin queue */ : 0); + } + +diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c +index 31fa7e6c44af..301d57b828e0 100644 +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -6884,9 +6884,9 @@ static int qla2xxx_map_queues(struct Scsi_Host *shost) + struct blk_mq_queue_map *qmap = &shost->tag_set.map[0]; + + if (USER_CTRL_IRQ(vha->hw)) +- rc = blk_mq_map_queues(qmap); ++ rc = blk_mq_map_queues_by_qmap(qmap); + else +- rc = blk_mq_pci_map_queues(qmap, vha->hw->pdev, 0); ++ rc = blk_mq_pci_map_queues_by_qmap(qmap, vha->hw->pdev, 0); + return rc; + } + +diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c +index ed21a6ef6df2..f3ccf06fb049 100644 +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -2302,7 +2302,7 @@ static int scsi_map_queues(struct blk_mq_tag_set *set) + + if (shost->hostt->map_queues) + return shost->hostt->map_queues(shost); +- return blk_mq_map_queues(&set->map[0]); ++ return blk_mq_map_queues_by_qmap(&set->map[0]); + } + + void __scsi_init_queue(struct Scsi_Host *shost, struct request_queue *q) +diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c +index ed72ad0b7c2d..0718ececb26a 100644 +--- a/drivers/scsi/smartpqi/smartpqi_init.c ++++ b/drivers/scsi/smartpqi/smartpqi_init.c +@@ -5346,7 +5346,7 @@ static int pqi_map_queues(struct Scsi_Host *shost) + { + struct pqi_ctrl_info *ctrl_info = shost_to_hba(shost); + +- return blk_mq_pci_map_queues(&shost->tag_set.map[0], ++ return blk_mq_pci_map_queues_by_qmap(&shost->tag_set.map[0], + ctrl_info->pci_dev, 0); + } + +diff --git a/include/linux/blk-mq-pci.h b/include/linux/blk-mq-pci.h +index 0b1f45c62623..0527c4754246 100644 +--- a/include/linux/blk-mq-pci.h ++++ b/include/linux/blk-mq-pci.h +@@ -5,7 +5,9 @@ + struct blk_mq_queue_map; + struct pci_dev; + +-int blk_mq_pci_map_queues(struct blk_mq_queue_map *qmap, struct pci_dev *pdev, +- int offset); ++int blk_mq_pci_map_queues_by_qmap(struct blk_mq_queue_map *qmap, ++ struct pci_dev *pdev, ++ int offset); ++ + + #endif /* _LINUX_BLK_MQ_PCI_H */ +diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h +index 8417351f19ea..907c8a22ac39 100644 +--- a/include/linux/blk-mq.h ++++ b/include/linux/blk-mq.h +@@ -94,7 +94,11 @@ enum { + }; + + struct blk_mq_tag_set { +- struct blk_mq_queue_map map[HCTX_MAX_TYPES]; ++#ifdef __GENKSYMS__ ++ unsigned int *mq_map; ++#else ++ struct blk_mq_queue_map map[HCTX_MAX_TYPES]; ++#endif + const struct blk_mq_ops *ops; + unsigned int nr_hw_queues; /* nr hw queues across maps */ + unsigned int queue_depth; /* max hw supported */ +@@ -335,7 +339,7 @@ void blk_mq_freeze_queue_wait(struct request_queue *q); + int blk_mq_freeze_queue_wait_timeout(struct request_queue *q, + unsigned long timeout); + +-int blk_mq_map_queues(struct blk_mq_queue_map *qmap); ++int blk_mq_map_queues_by_qmap(struct blk_mq_queue_map *qmap); + void blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, int nr_hw_queues); + + void blk_mq_quiesce_queue_nowait(struct request_queue *q); +-- +2.27.0 + diff --git a/patches/0382-blk-mq-provide-dummy-blk_mq_map_queue_type-helper.patch b/patches/0382-blk-mq-provide-dummy-blk_mq_map_queue_type-helper.patch new file mode 100644 index 00000000..a1db8be8 --- /dev/null +++ b/patches/0382-blk-mq-provide-dummy-blk_mq_map_queue_type-helper.patch @@ -0,0 +1,58 @@ +From 53fecf3e1c2ee3004bacaf40b9858f382200cb59 Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Mon, 29 Oct 2018 13:07:33 -0600 +Subject: [PATCH 064/256] blk-mq: provide dummy blk_mq_map_queue_type() helper + +mainline inclusion +from mainline-v5.0-rc1 +commit ff2c56609d9b1f0739ae3a3bfdb78191d01e4192 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ff2c56609d9b1f0739ae3a3bfdb78191d01e4192 + +---------------------------------------------------------------------- + +Doesn't do anything right now, but it's needed as a prep patch +to get the interfaces right. + +While in there, correct the blk_mq_map_queue() CPU type to an unsigned +int. + +Reviewed-by: Hannes Reinecke +Reviewed-by: Keith Busch +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang +--- + block/blk-mq.h | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/block/blk-mq.h b/block/blk-mq.h +index fd61bb3d3eb1..9a7c4ab52146 100644 +--- a/block/blk-mq.h ++++ b/block/blk-mq.h +@@ -83,13 +83,20 @@ void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx, + extern int blk_mq_hw_queue_to_node(struct blk_mq_queue_map *qmap, unsigned int); + + static inline struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *q, +- int cpu) ++ unsigned int cpu) + { + struct blk_mq_tag_set *set = q->tag_set; + + return q->queue_hw_ctx[set->map[0].mq_map[cpu]]; + } + ++static inline struct blk_mq_hw_ctx *blk_mq_map_queue_type(struct request_queue *q, ++ unsigned int hctx_type, ++ unsigned int cpu) ++{ ++ return blk_mq_map_queue(q, cpu); ++} ++ + /* + * sysfs helpers + */ +-- +2.27.0 + diff --git a/patches/0383-blk-mq-pass-in-request-bio-flags-to-queue-mapping.patch b/patches/0383-blk-mq-pass-in-request-bio-flags-to-queue-mapping.patch new file mode 100644 index 00000000..8dfd297a --- /dev/null +++ b/patches/0383-blk-mq-pass-in-request-bio-flags-to-queue-mapping.patch @@ -0,0 +1,424 @@ +From 782af131ca62ef23a08c96c1a4e8af827e95aa4e Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Mon, 29 Oct 2018 13:11:38 -0600 +Subject: [PATCH 065/256] blk-mq: pass in request/bio flags to queue mapping + +mainline inclusion +from mainline-v5.0-rc1 +commit f9afca4d367b8c915f28d29fcaba7460640403ff +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f9afca4d367b8c915f28d29fcaba7460640403ff + +---------------------------------------------------------------------- + +Prep patch for being able to place request based not just on +CPU location, but also on the type of request. + +Reviewed-by: Hannes Reinecke +Reviewed-by: Keith Busch +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang + + Conflicts: + block/blk-flush.c + block/blk-mq-debugfs.c + block/blk-mq-sched.c + block/blk-mq-tag.c + block/blk-mq.c + block/blk.h +--- + block/blk-flush.c | 7 +++--- + block/blk-mq-debugfs.c | 5 +++-- + block/blk-mq-sched.c | 16 ++++++++++---- + block/blk-mq-tag.c | 5 +++-- + block/blk-mq.c | 50 +++++++++++++++++++++++------------------- + block/blk-mq.h | 6 +++-- + block/blk.h | 6 ++--- + block/mq-deadline.c | 3 ++- + 8 files changed, 59 insertions(+), 39 deletions(-) + +diff --git a/block/blk-flush.c b/block/blk-flush.c +index c1bfcde165af..5fca033cd830 100644 +--- a/block/blk-flush.c ++++ b/block/blk-flush.c +@@ -250,7 +250,7 @@ static void flush_end_io(struct request *flush_rq, blk_status_t error) + fq->rq_status = BLK_STS_OK; + } + +- hctx = blk_mq_map_queue(q, flush_rq->mq_ctx->cpu); ++ hctx = blk_mq_map_queue(q, flush_rq->cmd_flags, flush_rq->mq_ctx->cpu); + if (!q->elevator) { + blk_mq_tag_set_rq(hctx, flush_rq->tag, fq->orig_rq); + flush_rq->tag = -1; +@@ -365,7 +365,8 @@ static bool blk_kick_flush(struct request_queue *q, struct blk_flush_queue *fq, + if (!q->elevator) { + fq->orig_rq = first_rq; + flush_rq->tag = first_rq->tag; +- hctx = blk_mq_map_queue(q, first_rq->mq_ctx->cpu); ++ hctx = blk_mq_map_queue(q, first_rq->cmd_flags, ++ first_rq->mq_ctx->cpu); + blk_mq_tag_set_rq(hctx, first_rq->tag, flush_rq); + } else { + flush_rq->internal_tag = first_rq->internal_tag; +@@ -441,7 +442,7 @@ static void mq_flush_data_end_io(struct request *rq, blk_status_t error) + unsigned long flags; + struct blk_flush_queue *fq = blk_get_flush_queue(q, ctx); + +- hctx = blk_mq_map_queue(q, ctx->cpu); ++ hctx = blk_mq_map_queue(q, rq->cmd_flags, ctx->cpu); + + if (q->elevator) { + WARN_ON(rq->tag < 0); +diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c +index f0865b6ea1e1..2ca8509f887b 100644 +--- a/block/blk-mq-debugfs.c ++++ b/block/blk-mq-debugfs.c +@@ -430,9 +430,10 @@ struct show_busy_params { + static void hctx_show_busy_rq(struct request *rq, void *data, bool reserved) + { + const struct show_busy_params *params = data; ++ struct blk_mq_hw_ctx *hctx; + +- if (blk_mq_map_queue(rq->q, rq->mq_ctx->cpu) == params->hctx && +- blk_mq_rq_state(rq) != MQ_RQ_IDLE) ++ hctx = blk_mq_map_queue(rq->q, rq->cmd_flags, rq->mq_ctx->cpu); ++ if (hctx == params->hctx && blk_mq_rq_state(rq) != MQ_RQ_IDLE) + __blk_mq_debugfs_rq_show(params->m, + list_entry_rq(&rq->queuelist)); + } +diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c +index 0fb33abac3f6..de23433e6e8e 100644 +--- a/block/blk-mq-sched.c ++++ b/block/blk-mq-sched.c +@@ -386,7 +386,7 @@ bool __blk_mq_sched_bio_merge(struct request_queue *q, struct bio *bio) + { + struct elevator_queue *e = q->elevator; + struct blk_mq_ctx *ctx = blk_mq_get_ctx(q); +- struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, ctx->cpu); ++ struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, bio->bi_opf, ctx->cpu); + bool ret = false; + + if (e && e->type->ops.mq.bio_merge) { +@@ -449,7 +449,9 @@ void blk_mq_sched_insert_request(struct request *rq, bool at_head, + struct request_queue *q = rq->q; + struct elevator_queue *e = q->elevator; + struct blk_mq_ctx *ctx = rq->mq_ctx; +- struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, ctx->cpu); ++ struct blk_mq_hw_ctx *hctx; ++ ++ hctx = blk_mq_map_queue(q, rq->cmd_flags, ctx->cpu); + + /* flush rq in flush machinery need to be dispatched directly */ + if (!(rq->rq_flags & RQF_FLUSH_SEQ) && op_is_flush(rq->cmd_flags)) { +@@ -506,8 +508,13 @@ void blk_mq_sched_insert_requests(struct request_queue *q, + struct blk_mq_ctx *ctx, + struct list_head *list, bool run_queue_async) + { +- struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, ctx->cpu); +- struct elevator_queue *e = hctx->queue->elevator; ++ struct blk_mq_hw_ctx *hctx; ++ struct elevator_queue *e; ++ struct request *rq; ++ ++ /* For list inserts, requests better be on the same hw queue */ ++ rq = list_first_entry(list, struct request, queuelist); ++ hctx = blk_mq_map_queue(q, rq->cmd_flags, ctx->cpu); + + /* + * blk_mq_sched_insert_requests() is called from flush plug +@@ -516,6 +523,7 @@ void blk_mq_sched_insert_requests(struct request_queue *q, + */ + percpu_ref_get(&q->q_usage_counter); + ++ e = hctx->queue->elevator; + if (e && e->type->ops.mq.insert_requests) + e->type->ops.mq.insert_requests(hctx, list, false); + else { +diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c +index bee92ab06a5e..fbd61a765088 100644 +--- a/block/blk-mq-tag.c ++++ b/block/blk-mq-tag.c +@@ -169,7 +169,8 @@ unsigned int blk_mq_get_tag(struct blk_mq_alloc_data *data) + io_schedule(); + + data->ctx = blk_mq_get_ctx(data->q); +- data->hctx = blk_mq_map_queue(data->q, data->ctx->cpu); ++ data->hctx = blk_mq_map_queue(data->q, data->cmd_flags, ++ data->ctx->cpu); + tags = blk_mq_tags_from_data(data); + if (data->flags & BLK_MQ_REQ_RESERVED) + bt = &tags->breserved_tags; +@@ -529,7 +530,7 @@ u32 blk_mq_unique_tag(struct request *rq) + int hwq = 0; + + if (q->mq_ops) { +- hctx = blk_mq_map_queue(q, rq->mq_ctx->cpu); ++ hctx = blk_mq_map_queue(q, rq->cmd_flags, rq->mq_ctx->cpu); + hwq = hctx->queue_num; + } + +diff --git a/block/blk-mq.c b/block/blk-mq.c +index de8892ddd67f..f51147cdecb8 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -395,8 +395,8 @@ static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data, + } + + static struct request *blk_mq_get_request(struct request_queue *q, +- struct bio *bio, unsigned int op, +- struct blk_mq_alloc_data *data) ++ struct bio *bio, ++ struct blk_mq_alloc_data *data) + { + struct elevator_queue *e = q->elevator; + struct request *rq; +@@ -410,8 +410,9 @@ static struct request *blk_mq_get_request(struct request_queue *q, + put_ctx_on_error = true; + } + if (likely(!data->hctx)) +- data->hctx = blk_mq_map_queue(q, data->ctx->cpu); +- if (op & REQ_NOWAIT) ++ data->hctx = blk_mq_map_queue(q, data->cmd_flags, ++ data->ctx->cpu); ++ if (data->cmd_flags & REQ_NOWAIT) + data->flags |= BLK_MQ_REQ_NOWAIT; + + if (e) { +@@ -422,9 +423,10 @@ static struct request *blk_mq_get_request(struct request_queue *q, + * dispatch list. Don't include reserved tags in the + * limiting, as it isn't useful. + */ +- if (!op_is_flush(op) && e->type->ops.mq.limit_depth && ++ if (!op_is_flush(data->cmd_flags) && ++ e->type->ops.mq.limit_depth && + !(data->flags & BLK_MQ_REQ_RESERVED)) +- e->type->ops.mq.limit_depth(op, data); ++ e->type->ops.mq.limit_depth(data->cmd_flags, data); + } else { + blk_mq_tag_busy(data->hctx); + } +@@ -439,8 +441,8 @@ static struct request *blk_mq_get_request(struct request_queue *q, + return NULL; + } + +- rq = blk_mq_rq_ctx_init(data, tag, op); +- if (!op_is_flush(op)) { ++ rq = blk_mq_rq_ctx_init(data, tag, data->cmd_flags); ++ if (!op_is_flush(data->cmd_flags)) { + rq->elv.icq = NULL; + if (e && e->type->ops.mq.prepare_request) { + if (e->type->icq_cache && rq_ioc(bio)) +@@ -457,7 +459,7 @@ static struct request *blk_mq_get_request(struct request_queue *q, + struct request *blk_mq_alloc_request(struct request_queue *q, unsigned int op, + blk_mq_req_flags_t flags) + { +- struct blk_mq_alloc_data alloc_data = { .flags = flags }; ++ struct blk_mq_alloc_data alloc_data = { .flags = flags, .cmd_flags = op }; + struct request *rq; + int ret; + +@@ -465,7 +467,7 @@ struct request *blk_mq_alloc_request(struct request_queue *q, unsigned int op, + if (ret) + return ERR_PTR(ret); + +- rq = blk_mq_get_request(q, NULL, op, &alloc_data); ++ rq = blk_mq_get_request(q, NULL, &alloc_data); + blk_queue_exit(q); + + if (!rq) +@@ -483,7 +485,7 @@ EXPORT_SYMBOL(blk_mq_alloc_request); + struct request *blk_mq_alloc_request_hctx(struct request_queue *q, + unsigned int op, blk_mq_req_flags_t flags, unsigned int hctx_idx) + { +- struct blk_mq_alloc_data alloc_data = { .flags = flags }; ++ struct blk_mq_alloc_data alloc_data = { .flags = flags, .cmd_flags = op }; + struct request *rq; + unsigned int cpu; + int ret; +@@ -516,7 +518,7 @@ struct request *blk_mq_alloc_request_hctx(struct request_queue *q, + cpu = cpumask_first_and(alloc_data.hctx->cpumask, cpu_online_mask); + alloc_data.ctx = __blk_mq_get_ctx(q, cpu); + +- rq = blk_mq_get_request(q, NULL, op, &alloc_data); ++ rq = blk_mq_get_request(q, NULL, &alloc_data); + blk_queue_exit(q); + + if (!rq) +@@ -530,7 +532,7 @@ static void __blk_mq_free_request(struct request *rq) + { + struct request_queue *q = rq->q; + struct blk_mq_ctx *ctx = rq->mq_ctx; +- struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, ctx->cpu); ++ struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, rq->cmd_flags, ctx->cpu); + const int sched_tag = rq->internal_tag; + + blk_pm_mark_last_busy(rq); +@@ -547,7 +549,7 @@ void blk_mq_free_request(struct request *rq) + struct request_queue *q = rq->q; + struct elevator_queue *e = q->elevator; + struct blk_mq_ctx *ctx = rq->mq_ctx; +- struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, ctx->cpu); ++ struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, rq->cmd_flags, ctx->cpu); + + if (rq->rq_flags & RQF_ELVPRIV) { + if (e && e->type->ops.mq.finish_request) +@@ -1054,8 +1056,9 @@ bool blk_mq_get_driver_tag(struct request *rq) + { + struct blk_mq_alloc_data data = { + .q = rq->q, +- .hctx = blk_mq_map_queue(rq->q, rq->mq_ctx->cpu), ++ .hctx = blk_mq_map_queue(rq->q, rq->cmd_flags, rq->mq_ctx->cpu), + .flags = BLK_MQ_REQ_NOWAIT, ++ .cmd_flags = rq->cmd_flags, + }; + bool shared; + +@@ -1237,7 +1240,7 @@ bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list, + + rq = list_first_entry(list, struct request, queuelist); + +- hctx = blk_mq_map_queue(rq->q, rq->mq_ctx->cpu); ++ hctx = blk_mq_map_queue(rq->q, rq->cmd_flags, rq->mq_ctx->cpu); + if (!got_budget && !blk_mq_get_dispatch_budget(hctx)) { + blk_mq_put_driver_tag(rq); + no_budget_avail = true; +@@ -1710,7 +1713,8 @@ void blk_mq_request_bypass_insert(struct request *rq, bool at_head, + bool run_queue) + { + struct blk_mq_ctx *ctx = rq->mq_ctx; +- struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(rq->q, ctx->cpu); ++ struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(rq->q, rq->cmd_flags, ++ ctx->cpu); + + spin_lock(&hctx->lock); + if (at_head) +@@ -1926,7 +1930,8 @@ blk_status_t blk_mq_request_issue_directly(struct request *rq) + int srcu_idx; + blk_qc_t unused_cookie; + struct blk_mq_ctx *ctx = rq->mq_ctx; +- struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(rq->q, ctx->cpu); ++ struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(rq->q, rq->cmd_flags, ++ ctx->cpu); + + hctx_lock(hctx, &srcu_idx); + ret = __blk_mq_try_issue_directly(hctx, rq, &unused_cookie, true); +@@ -1961,7 +1966,7 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio) + { + const int is_sync = op_is_sync(bio->bi_opf); + const int is_flush_fua = op_is_flush(bio->bi_opf); +- struct blk_mq_alloc_data data = { .flags = 0 }; ++ struct blk_mq_alloc_data data = { .flags = 0, .cmd_flags = bio->bi_opf }; + struct request *rq; + unsigned int request_count = 0; + struct blk_plug *plug; +@@ -1989,7 +1994,7 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio) + + rq_qos_throttle(q, bio, NULL); + +- rq = blk_mq_get_request(q, bio, bio->bi_opf, &data); ++ rq = blk_mq_get_request(q, bio, &data); + if (unlikely(!rq)) { + rq_qos_cleanup(q, bio); + if (bio->bi_opf & REQ_NOWAIT) +@@ -2058,6 +2063,7 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio) + + if (same_queue_rq) { + data.hctx = blk_mq_map_queue(q, ++ same_queue_rq->cmd_flags, + same_queue_rq->mq_ctx->cpu); + blk_mq_try_issue_directly(data.hctx, same_queue_rq, + &cookie); +@@ -2523,7 +2529,7 @@ static void blk_mq_init_cpu_queues(struct request_queue *q, + * Set local node, IFF we have more than one hw queue. If + * not, we remain on the home node of the device + */ +- hctx = blk_mq_map_queue(q, i); ++ hctx = blk_mq_map_queue_type(q, 0, i); + if (nr_hw_queues > 1 && hctx->numa_node == NUMA_NO_NODE) + hctx->numa_node = local_memory_node(cpu_to_node(i)); + } +@@ -2591,7 +2597,7 @@ static void blk_mq_map_swqueue(struct request_queue *q) + } + + ctx = per_cpu_ptr(q->queue_ctx, i); +- hctx = blk_mq_map_queue(q, i); ++ hctx = blk_mq_map_queue_type(q, 0, i); + + cpumask_set_cpu(i, hctx->cpumask); + ctx->index_hw = hctx->nr_ctx; +diff --git a/block/blk-mq.h b/block/blk-mq.h +index 9a7c4ab52146..29f88f9caa62 100644 +--- a/block/blk-mq.h ++++ b/block/blk-mq.h +@@ -83,6 +83,7 @@ void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx, + extern int blk_mq_hw_queue_to_node(struct blk_mq_queue_map *qmap, unsigned int); + + static inline struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *q, ++ unsigned int flags, + unsigned int cpu) + { + struct blk_mq_tag_set *set = q->tag_set; +@@ -94,7 +95,7 @@ static inline struct blk_mq_hw_ctx *blk_mq_map_queue_type(struct request_queue * + unsigned int hctx_type, + unsigned int cpu) + { +- return blk_mq_map_queue(q, cpu); ++ return blk_mq_map_queue(q, hctx_type, cpu); + } + + /* +@@ -147,6 +148,7 @@ struct blk_mq_alloc_data { + struct request_queue *q; + blk_mq_req_flags_t flags; + unsigned int shallow_depth; ++ unsigned int cmd_flags; + + /* input & output parameter */ + struct blk_mq_ctx *ctx; +@@ -221,7 +223,7 @@ static inline void blk_mq_put_driver_tag(struct request *rq) + if (rq->tag == -1 || rq->internal_tag == -1) + return; + +- hctx = blk_mq_map_queue(rq->q, rq->mq_ctx->cpu); ++ hctx = blk_mq_map_queue(rq->q, rq->cmd_flags, rq->mq_ctx->cpu); + __blk_mq_put_driver_tag(hctx, rq); + } + +diff --git a/block/blk.h b/block/blk.h +index 965e9c507654..6b1ec6e4d782 100644 +--- a/block/blk.h ++++ b/block/blk.h +@@ -134,11 +134,11 @@ static inline void queue_flag_clear(unsigned int flag, struct request_queue *q) + __clear_bit(flag, &q->queue_flags); + } + +-static inline struct blk_flush_queue *blk_get_flush_queue( +- struct request_queue *q, struct blk_mq_ctx *ctx) ++static inline struct blk_flush_queue * ++blk_get_flush_queue(struct request_queue *q, struct blk_mq_ctx *ctx) + { + if (q->mq_ops) +- return blk_mq_map_queue(q, ctx->cpu)->fq; ++ return blk_mq_map_queue(q, REQ_OP_FLUSH, ctx->cpu)->fq; + return q->fq; + } + +diff --git a/block/mq-deadline.c b/block/mq-deadline.c +index 7ad820050675..e79c58aaad2e 100644 +--- a/block/mq-deadline.c ++++ b/block/mq-deadline.c +@@ -573,7 +573,8 @@ static void dd_finish_request(struct request *rq) + if (!list_empty(&dd->fifo_list[WRITE])) { + struct blk_mq_hw_ctx *hctx; + +- hctx = blk_mq_map_queue(q, rq->mq_ctx->cpu); ++ hctx = blk_mq_map_queue(q, rq->cmd_flags, ++ rq->mq_ctx->cpu); + blk_mq_sched_mark_restart_hctx(hctx); + } + spin_unlock_irqrestore(&dd->zone_lock, flags); +-- +2.27.0 + diff --git a/patches/0384-fix-kabi-broken-due-to-change-of-struct-blk_mq_alloc.patch b/patches/0384-fix-kabi-broken-due-to-change-of-struct-blk_mq_alloc.patch new file mode 100644 index 00000000..03a7d3fd --- /dev/null +++ b/patches/0384-fix-kabi-broken-due-to-change-of-struct-blk_mq_alloc.patch @@ -0,0 +1,43 @@ +From 6e5db5e1f0c70bdacffbaf9060305d179a060829 Mon Sep 17 00:00:00 2001 +From: YunYi Yang +Date: Sat, 26 Aug 2023 16:49:36 +0800 +Subject: [PATCH 066/256] fix kabi broken due to change of struct + blk_mq_alloc_data + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +---------------------------------------------------------------------------- + +Commit ("blk-mq: pass in request/bio flags to queue +mapping") changes the struct blk_mq_alloc_data, so we need to +fix kabi broken problem. + +Signed-off-by: YunYi Yang +--- + block/blk-mq.h | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/block/blk-mq.h b/block/blk-mq.h +index 29f88f9caa62..1cbe367d249e 100644 +--- a/block/blk-mq.h ++++ b/block/blk-mq.h +@@ -148,11 +148,13 @@ struct blk_mq_alloc_data { + struct request_queue *q; + blk_mq_req_flags_t flags; + unsigned int shallow_depth; +- unsigned int cmd_flags; + + /* input & output parameter */ + struct blk_mq_ctx *ctx; + struct blk_mq_hw_ctx *hctx; ++#ifndef __GENKSYMS__ ++ unsigned int cmd_flags; ++#endif + }; + + static inline struct blk_mq_tags *blk_mq_tags_from_data(struct blk_mq_alloc_data *data) +-- +2.27.0 + diff --git a/patches/0385-blk-mq-allow-software-queue-to-map-to-multiple-hardw.patch b/patches/0385-blk-mq-allow-software-queue-to-map-to-multiple-hardw.patch new file mode 100644 index 00000000..1f8fa1cb --- /dev/null +++ b/patches/0385-blk-mq-allow-software-queue-to-map-to-multiple-hardw.patch @@ -0,0 +1,165 @@ +From db8838fb0ac40910226e89f8da966f24bd3ccf36 Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Mon, 29 Oct 2018 13:13:29 -0600 +Subject: [PATCH 067/256] blk-mq: allow software queue to map to multiple + hardware queues + +mainline inclusion +from mainline-v5.0-rc1 +commit f31967f0e455d08d3ea1d2f849bf62dafc92dbf4 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f31967f0e455d08d3ea1d2f849bf62dafc92dbf4 + +---------------------------------------------------------------------- + +The mapping used to be dependent on just the CPU location, but +now it's a tuple of (type, cpu) instead. This is a prep patch +for allowing a single software queue to map to multiple hardware +queues. No functional changes in this patch. + +This changes the software queue count to an unsigned short +to save a bit of space. We can still support 64K-1 CPUs, +which should be enough. Add a check to catch a wrap. + +Reviewed-by: Hannes Reinecke +Reviewed-by: Keith Busch +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang +--- + block/blk-mq-sched.c | 2 +- + block/blk-mq.c | 22 ++++++++++++++++------ + block/blk-mq.h | 2 +- + block/kyber-iosched.c | 6 +++--- + include/linux/blk-mq.h | 3 ++- + 5 files changed, 23 insertions(+), 12 deletions(-) + +diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c +index de23433e6e8e..e9f531d5b0f9 100644 +--- a/block/blk-mq-sched.c ++++ b/block/blk-mq-sched.c +@@ -149,7 +149,7 @@ static int blk_mq_do_dispatch_sched(struct blk_mq_hw_ctx *hctx) + static struct blk_mq_ctx *blk_mq_next_ctx(struct blk_mq_hw_ctx *hctx, + struct blk_mq_ctx *ctx) + { +- unsigned idx = ctx->index_hw; ++ unsigned short idx = ctx->index_hw[hctx->type]; + + if (++idx == hctx->nr_ctx) + idx = 0; +diff --git a/block/blk-mq.c b/block/blk-mq.c +index f51147cdecb8..7daa9624b726 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -75,14 +75,18 @@ static bool blk_mq_hctx_has_pending(struct blk_mq_hw_ctx *hctx) + static void blk_mq_hctx_mark_pending(struct blk_mq_hw_ctx *hctx, + struct blk_mq_ctx *ctx) + { +- if (!sbitmap_test_bit(&hctx->ctx_map, ctx->index_hw)) +- sbitmap_set_bit(&hctx->ctx_map, ctx->index_hw); ++ const int bit = ctx->index_hw[hctx->type]; ++ ++ if (!sbitmap_test_bit(&hctx->ctx_map, bit)) ++ sbitmap_set_bit(&hctx->ctx_map, bit); + } + + static void blk_mq_hctx_clear_pending(struct blk_mq_hw_ctx *hctx, + struct blk_mq_ctx *ctx) + { +- sbitmap_clear_bit(&hctx->ctx_map, ctx->index_hw); ++ const int bit = ctx->index_hw[hctx->type]; ++ ++ sbitmap_clear_bit(&hctx->ctx_map, bit); + } + + struct mq_inflight { +@@ -1032,7 +1036,7 @@ static bool dispatch_rq_from_ctx(struct sbitmap *sb, unsigned int bitnr, + struct request *blk_mq_dequeue_from_ctx(struct blk_mq_hw_ctx *hctx, + struct blk_mq_ctx *start) + { +- unsigned off = start ? start->index_hw : 0; ++ unsigned off = start ? start->index_hw[hctx->type] : 0; + struct dispatch_rq_data data = { + .hctx = hctx, + .rq = NULL, +@@ -2598,10 +2602,16 @@ static void blk_mq_map_swqueue(struct request_queue *q) + + ctx = per_cpu_ptr(q->queue_ctx, i); + hctx = blk_mq_map_queue_type(q, 0, i); +- ++ hctx->type = 0; + cpumask_set_cpu(i, hctx->cpumask); +- ctx->index_hw = hctx->nr_ctx; ++ ctx->index_hw[hctx->type] = hctx->nr_ctx; + hctx->ctxs[hctx->nr_ctx++] = ctx; ++ ++ /* ++ * If the nr_ctx type overflows, we have exceeded the ++ * amount of sw queues we can support. ++ */ ++ BUG_ON(!hctx->nr_ctx); + } + + queue_for_each_hw_ctx(q, hctx, i) { +diff --git a/block/blk-mq.h b/block/blk-mq.h +index 1cbe367d249e..beadc82ddb4c 100644 +--- a/block/blk-mq.h ++++ b/block/blk-mq.h +@@ -22,7 +22,7 @@ struct blk_mq_ctx { + } ____cacheline_aligned_in_smp; + + unsigned int cpu; +- unsigned int index_hw; ++ unsigned short index_hw[HCTX_MAX_TYPES]; + + /* incremented at dispatch time */ + unsigned long rq_dispatched[2]; +diff --git a/block/kyber-iosched.c b/block/kyber-iosched.c +index d8f3cb1bffa6..e15ecd335eec 100644 +--- a/block/kyber-iosched.c ++++ b/block/kyber-iosched.c +@@ -507,7 +507,7 @@ static bool kyber_bio_merge(struct blk_mq_hw_ctx *hctx, struct bio *bio) + { + struct kyber_hctx_data *khd = hctx->sched_data; + struct blk_mq_ctx *ctx = blk_mq_get_ctx(hctx->queue); +- struct kyber_ctx_queue *kcq = &khd->kcqs[ctx->index_hw]; ++ struct kyber_ctx_queue *kcq = &khd->kcqs[ctx->index_hw[hctx->type]]; + unsigned int sched_domain = kyber_sched_domain(bio->bi_opf); + struct list_head *rq_list = &kcq->rq_list[sched_domain]; + bool merged; +@@ -533,7 +533,7 @@ static void kyber_insert_requests(struct blk_mq_hw_ctx *hctx, + + list_for_each_entry_safe(rq, next, rq_list, queuelist) { + unsigned int sched_domain = kyber_sched_domain(rq->cmd_flags); +- struct kyber_ctx_queue *kcq = &khd->kcqs[rq->mq_ctx->index_hw]; ++ struct kyber_ctx_queue *kcq = &khd->kcqs[rq->mq_ctx->index_hw[hctx->type]]; + struct list_head *head = &kcq->rq_list[sched_domain]; + + spin_lock(&kcq->lock); +@@ -542,7 +542,7 @@ static void kyber_insert_requests(struct blk_mq_hw_ctx *hctx, + else + list_move_tail(&rq->queuelist, head); + sbitmap_set_bit(&khd->kcq_map[sched_domain], +- rq->mq_ctx->index_hw); ++ rq->mq_ctx->index_hw[hctx->type]); + blk_mq_sched_request_inserted(rq); + spin_unlock(&kcq->lock); + } +diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h +index 907c8a22ac39..c12a56fa867d 100644 +--- a/include/linux/blk-mq.h ++++ b/include/linux/blk-mq.h +@@ -37,7 +37,8 @@ struct blk_mq_hw_ctx { + struct blk_mq_ctx *dispatch_from; + unsigned int dispatch_busy; + +- unsigned int nr_ctx; ++ unsigned short type; ++ unsigned short nr_ctx; + struct blk_mq_ctx **ctxs; + + spinlock_t dispatch_wait_lock; +-- +2.27.0 + diff --git a/patches/0386-fix-kabi-broken-due-to-change-of-struct-blk_mq_hw_ct.patch b/patches/0386-fix-kabi-broken-due-to-change-of-struct-blk_mq_hw_ct.patch new file mode 100644 index 00000000..cff97dc9 --- /dev/null +++ b/patches/0386-fix-kabi-broken-due-to-change-of-struct-blk_mq_hw_ct.patch @@ -0,0 +1,79 @@ +From 91bf4f8c9e030b76b148b9aa4205191a6d633e5b Mon Sep 17 00:00:00 2001 +From: YunYi Yang +Date: Sat, 26 Aug 2023 17:12:16 +0800 +Subject: [PATCH 068/256] fix kabi broken due to change of struct blk_mq_hw_ctx + and blk_mq_ctx + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +---------------------------------------------------------------------------- + +Commit ("blk-mq: allow software queue to map to multiple +hardware queues") changes the struct blk_mq_hw_ctx and blk_mq_ctx, so +we need to fix kabi broken problem. + +Signed-off-by: YunYi Yang +--- + block/blk-mq.h | 7 ++++++- + include/linux/blk-mq.h | 9 ++++++++- + 2 files changed, 14 insertions(+), 2 deletions(-) + +diff --git a/block/blk-mq.h b/block/blk-mq.h +index beadc82ddb4c..f4c3b9702d6f 100644 +--- a/block/blk-mq.h ++++ b/block/blk-mq.h +@@ -22,7 +22,9 @@ struct blk_mq_ctx { + } ____cacheline_aligned_in_smp; + + unsigned int cpu; +- unsigned short index_hw[HCTX_MAX_TYPES]; ++#ifdef __GENKSYMS__ ++ unsigned int index_hw; ++#endif + + /* incremented at dispatch time */ + unsigned long rq_dispatched[2]; +@@ -34,6 +36,9 @@ struct blk_mq_ctx { + struct request_queue *queue; + struct blk_mq_ctxs *ctxs; + struct kobject kobj; ++#ifndef __GENKSYMS__ ++ unsigned short index_hw[HCTX_MAX_TYPES]; ++#endif + } ____cacheline_aligned_in_smp; + + void blk_mq_freeze_queue(struct request_queue *q); +diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h +index c12a56fa867d..2ef1d57d6598 100644 +--- a/include/linux/blk-mq.h ++++ b/include/linux/blk-mq.h +@@ -37,8 +37,11 @@ struct blk_mq_hw_ctx { + struct blk_mq_ctx *dispatch_from; + unsigned int dispatch_busy; + +- unsigned short type; ++#ifndef __GENKSYMS__ + unsigned short nr_ctx; ++#else ++ unsigned int nr_ctx; ++#endif + struct blk_mq_ctx **ctxs; + + spinlock_t dispatch_wait_lock; +@@ -72,7 +75,11 @@ struct blk_mq_hw_ctx { + #endif + + struct list_head hctx_list; ++#ifndef __GENKSYMS__ ++ unsigned short type; ++#else + KABI_RESERVE(1) ++#endif + KABI_RESERVE(2) + KABI_RESERVE(3) + KABI_RESERVE(4) +-- +2.27.0 + diff --git a/patches/0387-blk-mq-add-type-attribute-to-the-sysfs-hctx-director.patch b/patches/0387-blk-mq-add-type-attribute-to-the-sysfs-hctx-director.patch new file mode 100644 index 00000000..e748a4cf --- /dev/null +++ b/patches/0387-blk-mq-add-type-attribute-to-the-sysfs-hctx-director.patch @@ -0,0 +1,65 @@ +From 9be5da85ed217fae66dd2011addd07b0c82d4f8a Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Thu, 25 Oct 2018 08:58:14 -0600 +Subject: [PATCH 069/256] blk-mq: add 'type' attribute to the sysfs hctx + directory + +mainline inclusion +from mainline-v5.0-rc1 +commit a783b81820fe3532809c98371ec904dfdb0ea9e5 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a783b81820fe3532809c98371ec904dfdb0ea9e5 + +---------------------------------------------------------------------- + +It can be useful for a user to verify what type a given hardware +queue is, expose this information in sysfs. + +Reviewed-by: Hannes Reinecke +Reviewed-by: Bart Van Assche +Reviewed-by: Keith Busch +Reviewed-by: Sagi Grimberg +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang +--- + block/blk-mq-sysfs.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/block/blk-mq-sysfs.c b/block/blk-mq-sysfs.c +index cace619d7421..9de1131cb959 100644 +--- a/block/blk-mq-sysfs.c ++++ b/block/blk-mq-sysfs.c +@@ -184,6 +184,11 @@ static ssize_t blk_mq_hw_sysfs_cpus_show(struct blk_mq_hw_ctx *hctx, char *page) + return pos + ret; + } + ++static ssize_t blk_mq_hw_sysfs_type_show(struct blk_mq_hw_ctx *hctx, char *page) ++{ ++ return sprintf(page, "%u\n", hctx->type); ++} ++ + static struct attribute *default_ctx_attrs[] = { + NULL, + }; +@@ -200,11 +205,16 @@ static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_cpus = { + .attr = {.name = "cpu_list", .mode = 0444 }, + .show = blk_mq_hw_sysfs_cpus_show, + }; ++static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_type = { ++ .attr = {.name = "type", .mode = 0444 }, ++ .show = blk_mq_hw_sysfs_type_show, ++}; + + static struct attribute *default_hw_ctx_attrs[] = { + &blk_mq_hw_sysfs_nr_tags.attr, + &blk_mq_hw_sysfs_nr_reserved_tags.attr, + &blk_mq_hw_sysfs_cpus.attr, ++ &blk_mq_hw_sysfs_type.attr, + NULL, + }; + +-- +2.27.0 + diff --git a/patches/0388-blk-mq-support-multiple-hctx-maps.patch b/patches/0388-blk-mq-support-multiple-hctx-maps.patch new file mode 100644 index 00000000..daf565c7 --- /dev/null +++ b/patches/0388-blk-mq-support-multiple-hctx-maps.patch @@ -0,0 +1,318 @@ +From 821e0e8db6f2858ad3318937c6754ce2b16df2bc Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Tue, 30 Oct 2018 10:36:06 -0600 +Subject: [PATCH 070/256] blk-mq: support multiple hctx maps + +mainline inclusion +from mainline-v5.0-rc1 +commit b3c661b15d5ab11d982e58bee23e05c1780528a1 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b3c661b15d5ab11d982e58bee23e05c1780528a1 + +---------------------------------------------------------------------- + +Add support for the tag set carrying multiple queue maps, and +for the driver to inform blk-mq how many it wishes to support +through setting set->nr_maps. + +This adds an mq_ops helper for drivers that support more than 1 +map, mq_ops->rq_flags_to_type(). The function takes request/bio +flags and CPU, and returns a queue map index for that. We then +use the type information in blk_mq_map_queue() to index the map +set. + +Reviewed-by: Hannes Reinecke +Reviewed-by: Keith Busch +Reviewed-by: Sagi Grimberg +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang + + Conflicts: + block/blk-mq.c + include/linux/blk-mq.h +--- + block/blk-mq.c | 91 ++++++++++++++++++++++++++++-------------- + block/blk-mq.h | 33 +++++++++++---- + include/linux/blk-mq.h | 14 +++++++ + 3 files changed, 99 insertions(+), 39 deletions(-) + +diff --git a/block/blk-mq.c b/block/blk-mq.c +index 7daa9624b726..93b875cd6e87 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -2518,7 +2518,8 @@ blk_mq_alloc_hctx(struct request_queue *q, struct blk_mq_tag_set *set, + static void blk_mq_init_cpu_queues(struct request_queue *q, + unsigned int nr_hw_queues) + { +- unsigned int i; ++ struct blk_mq_tag_set *set = q->tag_set; ++ unsigned int i, j; + + for_each_possible_cpu(i) { + struct blk_mq_ctx *__ctx = per_cpu_ptr(q->queue_ctx, i); +@@ -2533,9 +2534,11 @@ static void blk_mq_init_cpu_queues(struct request_queue *q, + * Set local node, IFF we have more than one hw queue. If + * not, we remain on the home node of the device + */ +- hctx = blk_mq_map_queue_type(q, 0, i); +- if (nr_hw_queues > 1 && hctx->numa_node == NUMA_NO_NODE) +- hctx->numa_node = local_memory_node(cpu_to_node(i)); ++ for (j = 0; j < set->nr_maps; j++) { ++ hctx = blk_mq_map_queue_type(q, j, i); ++ if (nr_hw_queues > 1 && hctx->numa_node == NUMA_NO_NODE) ++ hctx->numa_node = local_memory_node(cpu_to_node(i)); ++ } + } + } + +@@ -2570,7 +2573,7 @@ static void blk_mq_free_map_and_requests(struct blk_mq_tag_set *set, + + static void blk_mq_map_swqueue(struct request_queue *q) + { +- unsigned int i, hctx_idx; ++ unsigned int i, j, hctx_idx; + struct blk_mq_hw_ctx *hctx; + struct blk_mq_ctx *ctx; + struct blk_mq_tag_set *set = q->tag_set; +@@ -2601,17 +2604,28 @@ static void blk_mq_map_swqueue(struct request_queue *q) + } + + ctx = per_cpu_ptr(q->queue_ctx, i); +- hctx = blk_mq_map_queue_type(q, 0, i); +- hctx->type = 0; +- cpumask_set_cpu(i, hctx->cpumask); +- ctx->index_hw[hctx->type] = hctx->nr_ctx; +- hctx->ctxs[hctx->nr_ctx++] = ctx; ++ for (j = 0; j < set->nr_maps; j++) { ++ hctx = blk_mq_map_queue_type(q, j, i); + +- /* +- * If the nr_ctx type overflows, we have exceeded the +- * amount of sw queues we can support. +- */ +- BUG_ON(!hctx->nr_ctx); ++ /* ++ * If the CPU is already set in the mask, then we've ++ * mapped this one already. This can happen if ++ * devices share queues across queue maps. ++ */ ++ if (cpumask_test_cpu(i, hctx->cpumask)) ++ continue; ++ ++ cpumask_set_cpu(i, hctx->cpumask); ++ hctx->type = j; ++ ctx->index_hw[hctx->type] = hctx->nr_ctx; ++ hctx->ctxs[hctx->nr_ctx++] = ctx; ++ ++ /* ++ * If the nr_ctx type overflows, we have exceeded the ++ * amount of sw queues we can support. ++ */ ++ BUG_ON(!hctx->nr_ctx); ++ } + } + + queue_for_each_hw_ctx(q, hctx, i) { +@@ -3042,6 +3056,8 @@ static int blk_mq_alloc_rq_maps(struct blk_mq_tag_set *set) + static int blk_mq_update_queue_map(struct blk_mq_tag_set *set) + { + if (set->ops->map_queues && !is_kdump_kernel()) { ++ int i; ++ + /* + * transport .map_queues is usually done in the following + * way: +@@ -3049,18 +3065,21 @@ static int blk_mq_update_queue_map(struct blk_mq_tag_set *set) + * for (queue = 0; queue < set->nr_hw_queues; queue++) { + * mask = get_cpu_mask(queue) + * for_each_cpu(cpu, mask) +- * set->map.mq_map[cpu] = queue; ++ * set->map[x].mq_map[cpu] = queue; + * } + * + * When we need to remap, the table has to be cleared for + * killing stale mapping since one CPU may not be mapped + * to any hw queue. + */ +- blk_mq_clear_mq_map(&set->map[0]); ++ for (i = 0; i < set->nr_maps; i++) ++ blk_mq_clear_mq_map(&set->map[i]); + + return set->ops->map_queues(set); +- } else ++ } else { ++ BUG_ON(set->nr_maps > 1); + return blk_mq_map_queues_by_qmap(&set->map[0]); ++ } + } + + /* +@@ -3071,7 +3090,7 @@ static int blk_mq_update_queue_map(struct blk_mq_tag_set *set) + */ + int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set) + { +- int ret; ++ int i, ret; + + BUILD_BUG_ON(BLK_MQ_MAX_DEPTH > 1 << BLK_MQ_UNIQUE_TAG_BITS); + +@@ -3094,6 +3113,11 @@ int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set) + set->queue_depth = BLK_MQ_MAX_DEPTH; + } + ++ if (!set->nr_maps) ++ set->nr_maps = 1; ++ else if (set->nr_maps > HCTX_MAX_TYPES) ++ return -EINVAL; ++ + /* + * If a crashdump is active, then we are potentially in a very + * memory constrained environment. Limit us to 1 queue and +@@ -3115,12 +3139,14 @@ int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set) + return -ENOMEM; + + ret = -ENOMEM; +- set->map[0].mq_map = kcalloc_node(nr_cpu_ids, +- sizeof(*set->map[0].mq_map), +- GFP_KERNEL, set->numa_node); +- if (!set->map[0].mq_map) +- goto out_free_tags; +- set->map[0].nr_queues = set->nr_hw_queues; ++ for (i = 0; i < set->nr_maps; i++) { ++ set->map[i].mq_map = kcalloc_node(nr_cpu_ids, ++ sizeof(struct blk_mq_queue_map), ++ GFP_KERNEL, set->numa_node); ++ if (!set->map[i].mq_map) ++ goto out_free_mq_map; ++ set->map[i].nr_queues = set->nr_hw_queues; ++ } + + ret = blk_mq_update_queue_map(set); + if (ret) +@@ -3136,9 +3162,10 @@ int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set) + return 0; + + out_free_mq_map: +- kfree(set->map[0].mq_map); +- set->map[0].mq_map = NULL; +-out_free_tags: ++ for (i = 0; i < set->nr_maps; i++) { ++ kfree(set->map[i].mq_map); ++ set->map[i].mq_map = NULL; ++ } + kfree(set->tags); + set->tags = NULL; + return ret; +@@ -3147,13 +3174,15 @@ EXPORT_SYMBOL(blk_mq_alloc_tag_set); + + void blk_mq_free_tag_set(struct blk_mq_tag_set *set) + { +- int i; ++ int i, j; + + for (i = 0; i < nr_cpu_ids; i++) + blk_mq_free_map_and_requests(set, i); + +- kfree(set->map[0].mq_map); +- set->map[0].mq_map = NULL; ++ for (j = 0; j < set->nr_maps; j++) { ++ kfree(set->map[j].mq_map); ++ set->map[j].mq_map = NULL; ++ } + + kfree(set->tags); + set->tags = NULL; +diff --git a/block/blk-mq.h b/block/blk-mq.h +index f4c3b9702d6f..85ef48e858db 100644 +--- a/block/blk-mq.h ++++ b/block/blk-mq.h +@@ -87,20 +87,37 @@ void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx, + */ + extern int blk_mq_hw_queue_to_node(struct blk_mq_queue_map *qmap, unsigned int); + +-static inline struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *q, +- unsigned int flags, +- unsigned int cpu) ++/* ++ * blk_mq_map_queue_type() - map (hctx_type,cpu) to hardware queue ++ * @q: request queue ++ * @hctx_type: the hctx type index ++ * @cpu: CPU ++ */ ++static inline struct blk_mq_hw_ctx *blk_mq_map_queue_type(struct request_queue *q, ++ unsigned int hctx_type, ++ unsigned int cpu) + { + struct blk_mq_tag_set *set = q->tag_set; + +- return q->queue_hw_ctx[set->map[0].mq_map[cpu]]; ++ return q->queue_hw_ctx[set->map[hctx_type].mq_map[cpu]]; + } + +-static inline struct blk_mq_hw_ctx *blk_mq_map_queue_type(struct request_queue *q, +- unsigned int hctx_type, +- unsigned int cpu) ++/* ++ * blk_mq_map_queue() - map (cmd_flags,type) to hardware queue ++ * @q: request queue ++ * @flags: request command flags ++ * @cpu: CPU ++ */ ++static inline struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *q, ++ unsigned int flags, ++ unsigned int cpu) + { +- return blk_mq_map_queue(q, hctx_type, cpu); ++ int hctx_type = 0; ++ ++ if (q->mq_ops->rq_flags_to_type) ++ hctx_type = q->mq_ops->rq_flags_to_type(q, flags); ++ ++ return blk_mq_map_queue_type(q, hctx_type, cpu); + } + + /* +diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h +index 2ef1d57d6598..9ae7e7449c89 100644 +--- a/include/linux/blk-mq.h ++++ b/include/linux/blk-mq.h +@@ -107,6 +107,13 @@ struct blk_mq_tag_set { + #else + struct blk_mq_queue_map map[HCTX_MAX_TYPES]; + #endif ++ /* ++ * map[] holds ctx -> hctx mappings, one map exists for each type ++ * that the driver wishes to support. There are no restrictions ++ * on maps being of the same size, and it's perfectly legal to ++ * share maps between types. ++ */ ++ unsigned int nr_maps; /* nr entries in map[] */ + const struct blk_mq_ops *ops; + unsigned int nr_hw_queues; /* nr hw queues across maps */ + unsigned int queue_depth; /* max hw supported */ +@@ -141,6 +148,8 @@ struct blk_mq_queue_data { + + typedef blk_status_t (queue_rq_fn)(struct blk_mq_hw_ctx *, + const struct blk_mq_queue_data *); ++/* takes rq->cmd_flags as input, returns a hardware type index */ ++typedef int (rq_flags_to_type_fn)(struct request_queue *, unsigned int); + typedef bool (get_budget_fn)(struct blk_mq_hw_ctx *); + typedef void (put_budget_fn)(struct blk_mq_hw_ctx *); + typedef enum blk_eh_timer_return (timeout_fn)(struct request *, bool); +@@ -165,6 +174,11 @@ struct blk_mq_ops { + */ + queue_rq_fn *queue_rq; + ++ /* ++ * Return a queue map type for the given request/bio flags ++ */ ++ rq_flags_to_type_fn *rq_flags_to_type; ++ + /* + * Reserve budget before queue request, once .queue_rq is + * run, it is driver's responsibility to release the +-- +2.27.0 + diff --git a/patches/0389-fix-kabi-broken-due-to-change-of-struct-blk_mq_tag_s.patch b/patches/0389-fix-kabi-broken-due-to-change-of-struct-blk_mq_tag_s.patch new file mode 100644 index 00000000..875ac299 --- /dev/null +++ b/patches/0389-fix-kabi-broken-due-to-change-of-struct-blk_mq_tag_s.patch @@ -0,0 +1,81 @@ +From 0590ef08027c9f36d5a3ae5653913494289adb21 Mon Sep 17 00:00:00 2001 +From: YunYi Yang +Date: Sat, 26 Aug 2023 17:21:54 +0800 +Subject: [PATCH 071/256] fix kabi broken due to change of struct + blk_mq_tag_set and blk_mq_ops + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +---------------------------------------------------------------------------- + +Commit 9867bd2cd8dc ("blk-mq: support multiple hctx maps") +changes the struct blk_mq_tag_set and blk_mq_ops, so we need +to fix kabi broken problem. + +Signed-off-by: YunYi Yang +--- + include/linux/blk-mq.h | 23 +++++++++++------------ + 1 file changed, 11 insertions(+), 12 deletions(-) + +diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h +index 9ae7e7449c89..6a7d5b28b620 100644 +--- a/include/linux/blk-mq.h ++++ b/include/linux/blk-mq.h +@@ -107,13 +107,6 @@ struct blk_mq_tag_set { + #else + struct blk_mq_queue_map map[HCTX_MAX_TYPES]; + #endif +- /* +- * map[] holds ctx -> hctx mappings, one map exists for each type +- * that the driver wishes to support. There are no restrictions +- * on maps being of the same size, and it's perfectly legal to +- * share maps between types. +- */ +- unsigned int nr_maps; /* nr entries in map[] */ + const struct blk_mq_ops *ops; + unsigned int nr_hw_queues; /* nr hw queues across maps */ + unsigned int queue_depth; /* max hw supported */ +@@ -129,7 +122,11 @@ struct blk_mq_tag_set { + struct mutex tag_list_lock; + struct list_head tag_list; + ++#ifndef __GENKSYMS__ ++ unsigned int nr_maps; /* nr entries in map[] */ ++#else + KABI_RESERVE(1) ++#endif + KABI_RESERVE(2) + KABI_RESERVE(3) + KABI_RESERVE(4) +@@ -174,11 +171,6 @@ struct blk_mq_ops { + */ + queue_rq_fn *queue_rq; + +- /* +- * Return a queue map type for the given request/bio flags +- */ +- rq_flags_to_type_fn *rq_flags_to_type; +- + /* + * Reserve budget before queue request, once .queue_rq is + * run, it is driver's responsibility to release the +@@ -238,7 +230,14 @@ struct blk_mq_ops { + void (*show_rq)(struct seq_file *m, struct request *rq); + #endif + ++#ifndef __GENKSYMS__ ++ /* ++ * Return a queue map type for the given request/bio flags ++ */ ++ rq_flags_to_type_fn * rq_flags_to_type; ++#else + KABI_RESERVE(1) ++#endif + KABI_RESERVE(2) + KABI_RESERVE(3) + KABI_RESERVE(4) +-- +2.27.0 + diff --git a/patches/0390-blk-mq-separate-number-of-hardware-queues-from-nr_cp.patch b/patches/0390-blk-mq-separate-number-of-hardware-queues-from-nr_cp.patch new file mode 100644 index 00000000..457e73eb --- /dev/null +++ b/patches/0390-blk-mq-separate-number-of-hardware-queues-from-nr_cp.patch @@ -0,0 +1,111 @@ +From 27945ba1f630b775743aa40fb49b881eb7b486f7 Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Mon, 29 Oct 2018 13:25:27 -0600 +Subject: [PATCH 072/256] blk-mq: separate number of hardware queues from + nr_cpu_ids + +mainline inclusion +from mainline-v5.0-rc1 +commit 392546aed22009060911f76b6ea24520e2f8b50f +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=392546aed22009060911f76b6ea24520e2f8b50f + +---------------------------------------------------------------------- + +With multiple maps, nr_cpu_ids is no longer the maximum number of +hardware queues we support on a given devices. The initializer of +the tag_set can have set ->nr_hw_queues larger than the available +number of CPUs, since we can exceed that with multiple queue maps. + +Reviewed-by: Hannes Reinecke +Reviewed-by: Bart Van Assche +Reviewed-by: Keith Busch +Reviewed-by: Sagi Grimberg +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang +--- + block/blk-mq.c | 28 +++++++++++++++++++++------- + 1 file changed, 21 insertions(+), 7 deletions(-) + +diff --git a/block/blk-mq.c b/block/blk-mq.c +index 93b875cd6e87..ef03b048d607 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -2899,6 +2899,19 @@ static void blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set, + mutex_unlock(&q->sysfs_lock); + } + ++/* ++ * Maximum number of hardware queues we support. For single sets, we'll never ++ * have more than the CPUs (software queues). For multiple sets, the tag_set ++ * user may have set ->nr_hw_queues larger. ++ */ ++static unsigned int nr_hw_queues(struct blk_mq_tag_set *set) ++{ ++ if (set->nr_maps == 1) ++ return nr_cpu_ids; ++ ++ return max(set->nr_hw_queues, nr_cpu_ids); ++} ++ + struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set, + struct request_queue *q) + { +@@ -2919,7 +2932,8 @@ struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set, + /* init q->mq_kobj and sw queues' kobjects */ + blk_mq_sysfs_init(q); + +- q->queue_hw_ctx = kcalloc_node(nr_cpu_ids, sizeof(*(q->queue_hw_ctx)), ++ q->nr_queues = nr_hw_queues(set); ++ q->queue_hw_ctx = kcalloc_node(q->nr_queues, sizeof(*(q->queue_hw_ctx)), + GFP_KERNEL, set->numa_node); + if (!q->queue_hw_ctx) + goto err_sys_init; +@@ -2934,7 +2948,6 @@ struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set, + INIT_WORK(&q->timeout_work, blk_mq_timeout_work); + blk_queue_rq_timeout(q, set->timeout ? set->timeout : 30 * HZ); + +- q->nr_queues = nr_cpu_ids; + q->tag_set = set; + + q->queue_flags |= QUEUE_FLAG_MQ_DEFAULT; +@@ -3128,12 +3141,13 @@ int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set) + set->queue_depth = min(64U, set->queue_depth); + } + /* +- * There is no use for more h/w queues than cpus. ++ * There is no use for more h/w queues than cpus if we just have ++ * a single map + */ +- if (set->nr_hw_queues > nr_cpu_ids) ++ if (set->nr_maps == 1 && set->nr_hw_queues > nr_cpu_ids) + set->nr_hw_queues = nr_cpu_ids; + +- set->tags = kcalloc_node(nr_cpu_ids, sizeof(struct blk_mq_tags *), ++ set->tags = kcalloc_node(nr_hw_queues(set), sizeof(struct blk_mq_tags *), + GFP_KERNEL, set->numa_node); + if (!set->tags) + return -ENOMEM; +@@ -3176,7 +3190,7 @@ void blk_mq_free_tag_set(struct blk_mq_tag_set *set) + { + int i, j; + +- for (i = 0; i < nr_cpu_ids; i++) ++ for (i = 0; i < nr_hw_queues(set); i++) + blk_mq_free_map_and_requests(set, i); + + for (j = 0; j < set->nr_maps; j++) { +@@ -3310,7 +3324,7 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, + + lockdep_assert_held(&set->tag_list_lock); + +- if (nr_hw_queues > nr_cpu_ids) ++ if (set->nr_maps == 1 && nr_hw_queues > nr_cpu_ids) + nr_hw_queues = nr_cpu_ids; + if (nr_hw_queues < 1 || nr_hw_queues == set->nr_hw_queues) + return; +-- +2.27.0 + diff --git a/patches/0391-blk-mq-cache-request-hardware-queue-mapping.patch b/patches/0391-blk-mq-cache-request-hardware-queue-mapping.patch new file mode 100644 index 00000000..9c8adec7 --- /dev/null +++ b/patches/0391-blk-mq-cache-request-hardware-queue-mapping.patch @@ -0,0 +1,268 @@ +From 93c5378d9b730a6f1449bbaccd37aa6bd28a96e4 Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Mon, 29 Oct 2018 15:06:13 -0600 +Subject: [PATCH 073/256] blk-mq: cache request hardware queue mapping + +mainline inclusion +from mainline-v5.0-rc1 +commit ea4f995ee8b8f0578b3319949f2edd5d812fdb0a +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ea4f995ee8b8f0578b3319949f2edd5d812fdb0a + +---------------------------------------------------------------------- + +We call blk_mq_map_queue() a lot, at least two times for each +request per IO, sometimes more. Since we now have an indirect +call as well in that function. cache the mapping so we don't +have to re-call blk_mq_map_queue() for the same request +multiple times. + +Reviewed-by: Keith Busch +Reviewed-by: Sagi Grimberg +Reviewed-by: Hannes Reinecke +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang + + Conflicts: + block/blk-flush.c + block/blk-mq-debugfs.c + block/blk-mq-tag.c + block/blk-mq.c +--- + block/blk-flush.c | 14 +++++--------- + block/blk-mq-debugfs.c | 5 ++--- + block/blk-mq-sched.c | 6 ++---- + block/blk-mq-tag.c | 4 +--- + block/blk-mq.c | 22 +++++++++------------- + block/blk-mq.h | 5 +---- + include/linux/blkdev.h | 1 + + 7 files changed, 21 insertions(+), 36 deletions(-) + +diff --git a/block/blk-flush.c b/block/blk-flush.c +index 5fca033cd830..4676e3812f30 100644 +--- a/block/blk-flush.c ++++ b/block/blk-flush.c +@@ -250,7 +250,7 @@ static void flush_end_io(struct request *flush_rq, blk_status_t error) + fq->rq_status = BLK_STS_OK; + } + +- hctx = blk_mq_map_queue(q, flush_rq->cmd_flags, flush_rq->mq_ctx->cpu); ++ hctx = flush_rq->mq_hctx; + if (!q->elevator) { + blk_mq_tag_set_rq(hctx, flush_rq->tag, fq->orig_rq); + flush_rq->tag = -1; +@@ -358,16 +358,14 @@ static bool blk_kick_flush(struct request_queue *q, struct blk_flush_queue *fq, + * just for cheating put/get driver tag. + */ + if (q->mq_ops) { +- struct blk_mq_hw_ctx *hctx; +- + flush_rq->mq_ctx = first_rq->mq_ctx; ++ flush_rq->mq_hctx = first_rq->mq_hctx; + + if (!q->elevator) { + fq->orig_rq = first_rq; + flush_rq->tag = first_rq->tag; +- hctx = blk_mq_map_queue(q, first_rq->cmd_flags, +- first_rq->mq_ctx->cpu); +- blk_mq_tag_set_rq(hctx, first_rq->tag, flush_rq); ++ blk_mq_tag_set_rq(flush_rq->mq_hctx, ++ first_rq->tag, flush_rq); + } else { + flush_rq->internal_tag = first_rq->internal_tag; + } +@@ -437,13 +435,11 @@ static void flush_data_end_io(struct request *rq, blk_status_t error) + static void mq_flush_data_end_io(struct request *rq, blk_status_t error) + { + struct request_queue *q = rq->q; +- struct blk_mq_hw_ctx *hctx; ++ struct blk_mq_hw_ctx *hctx = rq->mq_hctx; + struct blk_mq_ctx *ctx = rq->mq_ctx; + unsigned long flags; + struct blk_flush_queue *fq = blk_get_flush_queue(q, ctx); + +- hctx = blk_mq_map_queue(q, rq->cmd_flags, ctx->cpu); +- + if (q->elevator) { + WARN_ON(rq->tag < 0); + blk_mq_put_driver_tag_hctx(hctx, rq); +diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c +index 2ca8509f887b..ff2328464826 100644 +--- a/block/blk-mq-debugfs.c ++++ b/block/blk-mq-debugfs.c +@@ -430,10 +430,9 @@ struct show_busy_params { + static void hctx_show_busy_rq(struct request *rq, void *data, bool reserved) + { + const struct show_busy_params *params = data; +- struct blk_mq_hw_ctx *hctx; + +- hctx = blk_mq_map_queue(rq->q, rq->cmd_flags, rq->mq_ctx->cpu); +- if (hctx == params->hctx && blk_mq_rq_state(rq) != MQ_RQ_IDLE) ++ if (rq->mq_hctx == params->hctx && ++ blk_mq_rq_state(rq) != MQ_RQ_IDLE) + __blk_mq_debugfs_rq_show(params->m, + list_entry_rq(&rq->queuelist)); + } +diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c +index e9f531d5b0f9..436163e863d8 100644 +--- a/block/blk-mq-sched.c ++++ b/block/blk-mq-sched.c +@@ -449,9 +449,7 @@ void blk_mq_sched_insert_request(struct request *rq, bool at_head, + struct request_queue *q = rq->q; + struct elevator_queue *e = q->elevator; + struct blk_mq_ctx *ctx = rq->mq_ctx; +- struct blk_mq_hw_ctx *hctx; +- +- hctx = blk_mq_map_queue(q, rq->cmd_flags, ctx->cpu); ++ struct blk_mq_hw_ctx *hctx = rq->mq_hctx; + + /* flush rq in flush machinery need to be dispatched directly */ + if (!(rq->rq_flags & RQF_FLUSH_SEQ) && op_is_flush(rq->cmd_flags)) { +@@ -514,7 +512,7 @@ void blk_mq_sched_insert_requests(struct request_queue *q, + + /* For list inserts, requests better be on the same hw queue */ + rq = list_first_entry(list, struct request, queuelist); +- hctx = blk_mq_map_queue(q, rq->cmd_flags, ctx->cpu); ++ hctx = rq->mq_hctx; + + /* + * blk_mq_sched_insert_requests() is called from flush plug +diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c +index fbd61a765088..fa713873bbb0 100644 +--- a/block/blk-mq-tag.c ++++ b/block/blk-mq-tag.c +@@ -526,12 +526,10 @@ int blk_mq_tag_update_depth(struct blk_mq_hw_ctx *hctx, + u32 blk_mq_unique_tag(struct request *rq) + { + struct request_queue *q = rq->q; +- struct blk_mq_hw_ctx *hctx; + int hwq = 0; + + if (q->mq_ops) { +- hctx = blk_mq_map_queue(q, rq->cmd_flags, rq->mq_ctx->cpu); +- hwq = hctx->queue_num; ++ hwq = rq->mq_hctx->queue_num; + } + + return (hwq << BLK_MQ_UNIQUE_TAG_BITS) | +diff --git a/block/blk-mq.c b/block/blk-mq.c +index ef03b048d607..4eff753282dc 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -359,6 +359,7 @@ static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data, + /* csd/requeue_work/fifo_time is initialized before use */ + rq->q = data->q; + rq->mq_ctx = data->ctx; ++ rq->mq_hctx = data->hctx; + rq->rq_flags = rq_flags; + rq->cpu = -1; + rq->cmd_flags = op; +@@ -536,10 +537,11 @@ static void __blk_mq_free_request(struct request *rq) + { + struct request_queue *q = rq->q; + struct blk_mq_ctx *ctx = rq->mq_ctx; +- struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, rq->cmd_flags, ctx->cpu); ++ struct blk_mq_hw_ctx *hctx = rq->mq_hctx; + const int sched_tag = rq->internal_tag; + + blk_pm_mark_last_busy(rq); ++ rq->mq_hctx = NULL; + if (rq->tag != -1) + blk_mq_put_tag(hctx, hctx->tags, ctx, rq->tag); + if (sched_tag != -1) +@@ -553,7 +555,7 @@ void blk_mq_free_request(struct request *rq) + struct request_queue *q = rq->q; + struct elevator_queue *e = q->elevator; + struct blk_mq_ctx *ctx = rq->mq_ctx; +- struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, rq->cmd_flags, ctx->cpu); ++ struct blk_mq_hw_ctx *hctx = rq->mq_hctx; + + if (rq->rq_flags & RQF_ELVPRIV) { + if (e && e->type->ops.mq.finish_request) +@@ -1060,7 +1062,7 @@ bool blk_mq_get_driver_tag(struct request *rq) + { + struct blk_mq_alloc_data data = { + .q = rq->q, +- .hctx = blk_mq_map_queue(rq->q, rq->cmd_flags, rq->mq_ctx->cpu), ++ .hctx = rq->mq_hctx, + .flags = BLK_MQ_REQ_NOWAIT, + .cmd_flags = rq->cmd_flags, + }; +@@ -1244,7 +1246,7 @@ bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list, + + rq = list_first_entry(list, struct request, queuelist); + +- hctx = blk_mq_map_queue(rq->q, rq->cmd_flags, rq->mq_ctx->cpu); ++ hctx = rq->mq_hctx; + if (!got_budget && !blk_mq_get_dispatch_budget(hctx)) { + blk_mq_put_driver_tag(rq); + no_budget_avail = true; +@@ -1716,9 +1718,7 @@ void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq, + void blk_mq_request_bypass_insert(struct request *rq, bool at_head, + bool run_queue) + { +- struct blk_mq_ctx *ctx = rq->mq_ctx; +- struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(rq->q, rq->cmd_flags, +- ctx->cpu); ++ struct blk_mq_hw_ctx *hctx = rq->mq_hctx; + + spin_lock(&hctx->lock); + if (at_head) +@@ -1933,9 +1933,7 @@ blk_status_t blk_mq_request_issue_directly(struct request *rq) + blk_status_t ret; + int srcu_idx; + blk_qc_t unused_cookie; +- struct blk_mq_ctx *ctx = rq->mq_ctx; +- struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(rq->q, rq->cmd_flags, +- ctx->cpu); ++ struct blk_mq_hw_ctx *hctx = rq->mq_hctx; + + hctx_lock(hctx, &srcu_idx); + ret = __blk_mq_try_issue_directly(hctx, rq, &unused_cookie, true); +@@ -2066,9 +2064,7 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio) + blk_mq_put_ctx(data.ctx); + + if (same_queue_rq) { +- data.hctx = blk_mq_map_queue(q, +- same_queue_rq->cmd_flags, +- same_queue_rq->mq_ctx->cpu); ++ data.hctx = same_queue_rq->mq_hctx; + blk_mq_try_issue_directly(data.hctx, same_queue_rq, + &cookie); + } +diff --git a/block/blk-mq.h b/block/blk-mq.h +index 85ef48e858db..a7bfffcbd301 100644 +--- a/block/blk-mq.h ++++ b/block/blk-mq.h +@@ -242,13 +242,10 @@ static inline void blk_mq_put_driver_tag_hctx(struct blk_mq_hw_ctx *hctx, + + static inline void blk_mq_put_driver_tag(struct request *rq) + { +- struct blk_mq_hw_ctx *hctx; +- + if (rq->tag == -1 || rq->internal_tag == -1) + return; + +- hctx = blk_mq_map_queue(rq->q, rq->cmd_flags, rq->mq_ctx->cpu); +- __blk_mq_put_driver_tag(hctx, rq); ++ __blk_mq_put_driver_tag(rq->mq_hctx, rq); + } + + static inline void blk_mq_clear_mq_map(struct blk_mq_queue_map *qmap) +diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h +index 74cb02947a18..ff73fbc87b32 100644 +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -159,6 +159,7 @@ enum mq_rq_state { + struct request { + struct request_queue *q; + struct blk_mq_ctx *mq_ctx; ++ struct blk_mq_hw_ctx *mq_hctx; + + int cpu; + unsigned int cmd_flags; /* op and common flags */ +-- +2.27.0 + diff --git a/patches/0392-fix-kabi-broken-due-to-change-of-struct-request.patch b/patches/0392-fix-kabi-broken-due-to-change-of-struct-request.patch new file mode 100644 index 00000000..c47a90ff --- /dev/null +++ b/patches/0392-fix-kabi-broken-due-to-change-of-struct-request.patch @@ -0,0 +1,44 @@ +From db4e4e7cf5333822e1c25eec5b825df6c56dc8f6 Mon Sep 17 00:00:00 2001 +From: YunYi Yang +Date: Fri, 25 Aug 2023 15:13:45 +0800 +Subject: [PATCH 074/256] fix kabi broken due to change of struct request + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +---------------------------------------------------------------------------- + +Commit 6a137b2f297a ("blk-mq: cache request hardware queue mapping") +changes the struct request, so we need to fix kabi broken problem. + +Signed-off-by: YunYi Yang +--- + include/linux/blkdev.h | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h +index ff73fbc87b32..7d76f401e1a9 100644 +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -159,7 +159,6 @@ enum mq_rq_state { + struct request { + struct request_queue *q; + struct blk_mq_ctx *mq_ctx; +- struct blk_mq_hw_ctx *mq_hctx; + + int cpu; + unsigned int cmd_flags; /* op and common flags */ +@@ -278,6 +277,9 @@ struct request { + #ifdef CONFIG_BLK_CGROUP + struct request_list *rl; /* rl this rq is alloced from */ + #endif ++#ifndef __GENKSYMS__ ++ struct blk_mq_hw_ctx *mq_hctx; ++#endif + }; + + static inline bool blk_op_is_scsi(unsigned int op) +-- +2.27.0 + diff --git a/patches/0393-blk-mq-cleanup-and-improve-list-insertion.patch b/patches/0393-blk-mq-cleanup-and-improve-list-insertion.patch new file mode 100644 index 00000000..0736c860 --- /dev/null +++ b/patches/0393-blk-mq-cleanup-and-improve-list-insertion.patch @@ -0,0 +1,140 @@ +From 81a15060ddbf690026648c51d33c1930c5c68358 Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Tue, 30 Oct 2018 11:31:51 -0600 +Subject: [PATCH 075/256] blk-mq: cleanup and improve list insertion + +mainline inclusion +from mainline-v5.0-rc1 +commit 67cae4c948a5311121905a2a8740c50daf7f6478 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=67cae4c948a5311121905a2a8740c50daf7f6478 + +---------------------------------------------------------------------- + +It's somewhat strange to have a list insertion function that +relies on the fact that the caller has mapped things correctly. +Pass in the hardware queue directly for insertion, which makes +for a much cleaner interface and implementation. + +Reviewed-by: Keith Busch +Reviewed-by: Sagi Grimberg +Reviewed-by: Hannes Reinecke +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang +--- + block/blk-mq-sched.c | 10 ++-------- + block/blk-mq-sched.h | 2 +- + block/blk-mq.c | 25 ++++++++++++++----------- + 3 files changed, 17 insertions(+), 20 deletions(-) + +diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c +index 436163e863d8..9bf39bb94935 100644 +--- a/block/blk-mq-sched.c ++++ b/block/blk-mq-sched.c +@@ -502,18 +502,12 @@ void blk_mq_sched_insert_request(struct request *rq, bool at_head, + blk_mq_run_hw_queue(hctx, async); + } + +-void blk_mq_sched_insert_requests(struct request_queue *q, ++void blk_mq_sched_insert_requests(struct blk_mq_hw_ctx *hctx, + struct blk_mq_ctx *ctx, + struct list_head *list, bool run_queue_async) + { +- struct blk_mq_hw_ctx *hctx; + struct elevator_queue *e; +- struct request *rq; +- +- /* For list inserts, requests better be on the same hw queue */ +- rq = list_first_entry(list, struct request, queuelist); +- hctx = rq->mq_hctx; +- ++ struct request_queue *q = hctx->queue; + /* + * blk_mq_sched_insert_requests() is called from flush plug + * context only, and hold one usage counter to prevent queue +diff --git a/block/blk-mq-sched.h b/block/blk-mq-sched.h +index c81a26e7b620..69bfdf7c09f7 100644 +--- a/block/blk-mq-sched.h ++++ b/block/blk-mq-sched.h +@@ -21,7 +21,7 @@ void blk_mq_sched_restart(struct blk_mq_hw_ctx *hctx); + + void blk_mq_sched_insert_request(struct request *rq, bool at_head, + bool run_queue, bool async); +-void blk_mq_sched_insert_requests(struct request_queue *q, ++void blk_mq_sched_insert_requests(struct blk_mq_hw_ctx *hctx, + struct blk_mq_ctx *ctx, + struct list_head *list, bool run_queue_async); + +diff --git a/block/blk-mq.c b/block/blk-mq.c +index 4eff753282dc..e684adf7abdd 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -1764,11 +1764,12 @@ static int plug_ctx_cmp(void *priv, struct list_head *a, struct list_head *b) + + void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule) + { ++ struct blk_mq_hw_ctx *this_hctx; + struct blk_mq_ctx *this_ctx; + struct request_queue *this_q; + struct request *rq; + LIST_HEAD(list); +- LIST_HEAD(ctx_list); ++ LIST_HEAD(rq_list); + unsigned int depth; + + list_splice_init(&plug->mq_list, &list); +@@ -1776,6 +1777,7 @@ void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule) + list_sort(NULL, &list, plug_ctx_cmp); + + this_q = NULL; ++ this_hctx = NULL; + this_ctx = NULL; + depth = 0; + +@@ -1783,30 +1785,31 @@ void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule) + rq = list_entry_rq(list.next); + list_del_init(&rq->queuelist); + BUG_ON(!rq->q); +- if (rq->mq_ctx != this_ctx) { +- if (this_ctx) { ++ if (rq->mq_hctx != this_hctx || rq->mq_ctx != this_ctx) { ++ if (this_hctx) { + trace_block_unplug(this_q, depth, !from_schedule); +- blk_mq_sched_insert_requests(this_q, this_ctx, +- &ctx_list, ++ blk_mq_sched_insert_requests(this_hctx, this_ctx, ++ &rq_list, + from_schedule); + } + +- this_ctx = rq->mq_ctx; + this_q = rq->q; ++ this_ctx = rq->mq_ctx; ++ this_hctx = rq->mq_hctx; + depth = 0; + } + + depth++; +- list_add_tail(&rq->queuelist, &ctx_list); ++ list_add_tail(&rq->queuelist, &rq_list); + } + + /* +- * If 'this_ctx' is set, we know we have entries to complete +- * on 'ctx_list'. Do those. ++ * If 'this_hctx' is set, we know we have entries to complete ++ * on 'rq_list'. Do those. + */ +- if (this_ctx) { ++ if (this_hctx) { + trace_block_unplug(this_q, depth, !from_schedule); +- blk_mq_sched_insert_requests(this_q, this_ctx, &ctx_list, ++ blk_mq_sched_insert_requests(this_hctx, this_ctx, &rq_list, + from_schedule); + } + } +-- +2.27.0 + diff --git a/patches/0394-blk-mq-improve-plug-list-sorting.patch b/patches/0394-blk-mq-improve-plug-list-sorting.patch new file mode 100644 index 00000000..0264bcbc --- /dev/null +++ b/patches/0394-blk-mq-improve-plug-list-sorting.patch @@ -0,0 +1,75 @@ +From 1cc66c1d3220f9adf279badff2504fb8223aae06 Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Tue, 30 Oct 2018 12:24:04 -0600 +Subject: [PATCH 076/256] blk-mq: improve plug list sorting + +mainline inclusion +from mainline-v5.0-rc1 +commit 3110fc79606fb6003949246c6fb325dd43445273 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3110fc79606fb6003949246c6fb325dd43445273 + +---------------------------------------------------------------------- + +Currently we only look at the software queue, but with support +for multiple maps, we should also look at the hardware queue. +This is important since we'll flush out the request list if +either the software queue or hardware queue don't match. + +This sorts by software queue first, then hardware queue if +that differs. Finally we sort by request location like before. +This minimizes the flush points per plug list. + +Reviewed-by: Keith Busch +Reviewed-by: Sagi Grimberg +Reviewed-by: Hannes Reinecke +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang +--- + block/blk-mq.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/block/blk-mq.c b/block/blk-mq.c +index e684adf7abdd..0cfb9449984d 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -1752,14 +1752,21 @@ void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx, + spin_unlock(&ctx->lock); + } + +-static int plug_ctx_cmp(void *priv, struct list_head *a, struct list_head *b) ++static int plug_rq_cmp(void *priv, struct list_head *a, struct list_head *b) + { + struct request *rqa = container_of(a, struct request, queuelist); + struct request *rqb = container_of(b, struct request, queuelist); + +- return !(rqa->mq_ctx < rqb->mq_ctx || +- (rqa->mq_ctx == rqb->mq_ctx && +- blk_rq_pos(rqa) < blk_rq_pos(rqb))); ++ if (rqa->mq_ctx < rqb->mq_ctx) ++ return -1; ++ else if (rqa->mq_ctx > rqb->mq_ctx) ++ return 1; ++ else if (rqa->mq_hctx < rqb->mq_hctx) ++ return -1; ++ else if (rqa->mq_hctx > rqb->mq_hctx) ++ return 1; ++ ++ return blk_rq_pos(rqa) > blk_rq_pos(rqb); + } + + void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule) +@@ -1774,7 +1781,7 @@ void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule) + + list_splice_init(&plug->mq_list, &list); + +- list_sort(NULL, &list, plug_ctx_cmp); ++ list_sort(NULL, &list, plug_rq_cmp); + + this_q = NULL; + this_hctx = NULL; +-- +2.27.0 + diff --git a/patches/0395-blk-mq-initial-support-for-multiple-queue-maps.patch b/patches/0395-blk-mq-initial-support-for-multiple-queue-maps.patch new file mode 100644 index 00000000..f56092b9 --- /dev/null +++ b/patches/0395-blk-mq-initial-support-for-multiple-queue-maps.patch @@ -0,0 +1,110 @@ +From fe988836e8c12967b1ad7f4d2e8282f5eee59e0e Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Wed, 24 Oct 2018 13:16:11 -0600 +Subject: [PATCH 077/256] blk-mq: initial support for multiple queue maps + +mainline inclusion +from mainline-v5.0-rc1 +commit 843477d4cc5c4bb4e346c561ecd3b9d0bd67e8c8 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=843477d4cc5c4bb4e346c561ecd3b9d0bd67e8c8 + +---------------------------------------------------------------------- + +Add a queue offset to the tag map. This enables users to map +iteratively, for each queue map type they support. + +Bump maximum number of supported maps to 2, we're now fully +able to support more than 1 map. + +Reviewed-by: Hannes Reinecke +Reviewed-by: Keith Busch +Reviewed-by: Sagi Grimberg +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang +--- + block/blk-mq-cpumap.c | 9 +++++---- + block/blk-mq-pci.c | 2 +- + block/blk-mq-virtio.c | 2 +- + include/linux/blk-mq.h | 3 ++- + 4 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/block/blk-mq-cpumap.c b/block/blk-mq-cpumap.c +index cd49d2ba670c..6d4345abb7ce 100644 +--- a/block/blk-mq-cpumap.c ++++ b/block/blk-mq-cpumap.c +@@ -14,9 +14,10 @@ + #include "blk.h" + #include "blk-mq.h" + +-static int cpu_to_queue_index(unsigned int nr_queues, const int cpu) ++static int cpu_to_queue_index(struct blk_mq_queue_map *qmap, ++ unsigned int nr_queues, const int cpu) + { +- return cpu % nr_queues; ++ return qmap->queue_offset + (cpu % nr_queues); + } + + static int get_first_sibling(unsigned int cpu) +@@ -50,11 +51,11 @@ int blk_mq_map_queues_by_qmap(struct blk_mq_queue_map *qmap) + * performace optimizations. + */ + if (cpu < nr_queues) { +- map[cpu] = cpu_to_queue_index(nr_queues, cpu); ++ map[cpu] = cpu_to_queue_index(qmap, nr_queues, cpu); + } else { + first_sibling = get_first_sibling(cpu); + if (first_sibling == cpu) +- map[cpu] = cpu_to_queue_index(nr_queues, cpu); ++ map[cpu] = cpu_to_queue_index(qmap, nr_queues, cpu); + else + map[cpu] = map[first_sibling]; + } +diff --git a/block/blk-mq-pci.c b/block/blk-mq-pci.c +index 6501d9632f59..04b5f6a1fa20 100644 +--- a/block/blk-mq-pci.c ++++ b/block/blk-mq-pci.c +@@ -33,7 +33,7 @@ int blk_mq_pci_map_queues_by_qmap(struct blk_mq_queue_map *qmap, + goto fallback; + + for_each_cpu(cpu, mask) +- qmap->mq_map[cpu] = queue; ++ qmap->mq_map[cpu] = qmap->queue_offset + queue; + } + + return 0; +diff --git a/block/blk-mq-virtio.c b/block/blk-mq-virtio.c +index f5bd128c9b2e..b67d52e4cddf 100644 +--- a/block/blk-mq-virtio.c ++++ b/block/blk-mq-virtio.c +@@ -44,7 +44,7 @@ int blk_mq_virtio_map_queues(struct blk_mq_queue_map *qmap, + goto fallback; + + for_each_cpu(cpu, mask) +- qmap->mq_map[cpu] = queue; ++ qmap->mq_map[cpu] = qmap->queue_offset + queue; + } + + return 0; +diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h +index 6a7d5b28b620..61f1391eade6 100644 +--- a/include/linux/blk-mq.h ++++ b/include/linux/blk-mq.h +@@ -95,10 +95,11 @@ struct blk_mq_hw_ctx { + struct blk_mq_queue_map { + unsigned int *mq_map; + unsigned int nr_queues; ++ unsigned int queue_offset; + }; + + enum { +- HCTX_MAX_TYPES = 1, ++ HCTX_MAX_TYPES = 2, + }; + + struct blk_mq_tag_set { +-- +2.27.0 + diff --git a/patches/0396-block-move-queues-types-to-the-block-layer.patch b/patches/0396-block-move-queues-types-to-the-block-layer.patch new file mode 100644 index 00000000..48bf2889 --- /dev/null +++ b/patches/0396-block-move-queues-types-to-the-block-layer.patch @@ -0,0 +1,174 @@ +From 5b706e22e480b90de0ec298c4080499823788e5a Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig +Date: Sun, 2 Dec 2018 17:46:16 +0100 +Subject: [PATCH 078/256] block: move queues types to the block layer + +mainline inclusion +from mainline-v5.0-rc1 +commit e20ba6e1da029136ded295f33076483d65ddf50a +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e20ba6e1da029136ded295f33076483d65ddf50a + +---------------------------------------------------------------------- + +Having another indirect all in the fast path doesn't really help +in our post-spectre world. Also having too many queue type is just +going to create confusion, so I'd rather manage them centrally. + +Note that the queue type naming and ordering changes a bit - the +first index now is the default queue for everything not explicitly +marked, the optional ones are read and poll queues. + +Reviewed-by: Sagi Grimberg +Signed-off-by: Christoph Hellwig +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang + + Conflicts: + drivers/nvme/host/pci.c + include/linux/blk-mq.h +--- + block/blk-mq-sysfs.c | 9 ++++++++- + block/blk-mq.h | 21 ++++++++++++--------- + drivers/nvme/host/pci.c | 4 +++- + include/linux/blk-mq.h | 17 ++++++----------- + 4 files changed, 29 insertions(+), 22 deletions(-) + +diff --git a/block/blk-mq-sysfs.c b/block/blk-mq-sysfs.c +index 9de1131cb959..ed5488565676 100644 +--- a/block/blk-mq-sysfs.c ++++ b/block/blk-mq-sysfs.c +@@ -184,9 +184,16 @@ static ssize_t blk_mq_hw_sysfs_cpus_show(struct blk_mq_hw_ctx *hctx, char *page) + return pos + ret; + } + ++static const char *const hctx_types[] = { ++ [HCTX_TYPE_DEFAULT] = "default", ++ [HCTX_TYPE_READ] = "read", ++ [HCTX_TYPE_POLL] = "poll", ++}; ++ + static ssize_t blk_mq_hw_sysfs_type_show(struct blk_mq_hw_ctx *hctx, char *page) + { +- return sprintf(page, "%u\n", hctx->type); ++ BUILD_BUG_ON(ARRAY_SIZE(hctx_types) != HCTX_MAX_TYPES); ++ return sprintf(page, "%s\n", hctx_types[hctx->type]); + } + + static struct attribute *default_ctx_attrs[] = { +diff --git a/block/blk-mq.h b/block/blk-mq.h +index a7bfffcbd301..53db914ad7fd 100644 +--- a/block/blk-mq.h ++++ b/block/blk-mq.h +@@ -90,16 +90,14 @@ extern int blk_mq_hw_queue_to_node(struct blk_mq_queue_map *qmap, unsigned int); + /* + * blk_mq_map_queue_type() - map (hctx_type,cpu) to hardware queue + * @q: request queue +- * @hctx_type: the hctx type index ++ * @type: the hctx type index + * @cpu: CPU + */ + static inline struct blk_mq_hw_ctx *blk_mq_map_queue_type(struct request_queue *q, +- unsigned int hctx_type, ++ enum hctx_type type, + unsigned int cpu) + { +- struct blk_mq_tag_set *set = q->tag_set; +- +- return q->queue_hw_ctx[set->map[hctx_type].mq_map[cpu]]; ++ return q->queue_hw_ctx[q->tag_set->map[type].mq_map[cpu]]; + } + + /* +@@ -112,12 +110,17 @@ static inline struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *q, + unsigned int flags, + unsigned int cpu) + { +- int hctx_type = 0; ++ enum hctx_type type = HCTX_TYPE_DEFAULT; ++ ++ if (q->tag_set->nr_maps > HCTX_TYPE_POLL && ++ ((flags & REQ_HIPRI) && test_bit(QUEUE_FLAG_POLL, &q->queue_flags))) ++ type = HCTX_TYPE_POLL; + +- if (q->mq_ops->rq_flags_to_type) +- hctx_type = q->mq_ops->rq_flags_to_type(q, flags); ++ else if (q->tag_set->nr_maps > HCTX_TYPE_READ && ++ ((flags & REQ_OP_MASK) == REQ_OP_READ)) ++ type = HCTX_TYPE_READ; + +- return blk_mq_map_queue_type(q, hctx_type, cpu); ++ return blk_mq_map_queue_type(q, type, cpu); + } + + /* +diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c +index d373a0b7957e..20582873a605 100644 +--- a/drivers/nvme/host/pci.c ++++ b/drivers/nvme/host/pci.c +@@ -457,7 +457,8 @@ static int nvme_pci_map_queues(struct blk_mq_tag_set *set) + { + struct nvme_dev *dev = set->driver_data; + +- return blk_mq_pci_map_queues_by_qmap(&set->map[0], to_pci_dev(dev->dev), ++ return blk_mq_pci_map_queues_by_qmap(&set->map[HCTX_TYPE_DEFAULT], ++ to_pci_dev(dev->dev), + dev->num_vecs > 1 ? 1 /* admin queue */ : 0); + } + +@@ -2065,6 +2066,7 @@ static int nvme_dev_add(struct nvme_dev *dev) + if (!dev->ctrl.tagset) { + dev->tagset.ops = &nvme_mq_ops; + dev->tagset.nr_hw_queues = dev->online_queues - 1; ++ dev->tagset.nr_maps = HCTX_MAX_TYPES; + dev->tagset.timeout = NVME_IO_TIMEOUT; + dev->tagset.numa_node = dev_to_node(dev->dev); + dev->tagset.queue_depth = min_t(unsigned int, dev->q_depth, +diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h +index 61f1391eade6..b0200a1e1f84 100644 +--- a/include/linux/blk-mq.h ++++ b/include/linux/blk-mq.h +@@ -98,8 +98,12 @@ struct blk_mq_queue_map { + unsigned int queue_offset; + }; + +-enum { +- HCTX_MAX_TYPES = 2, ++enum hctx_type { ++ HCTX_TYPE_DEFAULT, /* all I/O not otherwise accounted for */ ++ HCTX_TYPE_READ, /* just for READ I/O */ ++ HCTX_TYPE_POLL, /* polled I/O of any kind */ ++ ++ HCTX_MAX_TYPES, + }; + + struct blk_mq_tag_set { +@@ -146,8 +150,6 @@ struct blk_mq_queue_data { + + typedef blk_status_t (queue_rq_fn)(struct blk_mq_hw_ctx *, + const struct blk_mq_queue_data *); +-/* takes rq->cmd_flags as input, returns a hardware type index */ +-typedef int (rq_flags_to_type_fn)(struct request_queue *, unsigned int); + typedef bool (get_budget_fn)(struct blk_mq_hw_ctx *); + typedef void (put_budget_fn)(struct blk_mq_hw_ctx *); + typedef enum blk_eh_timer_return (timeout_fn)(struct request *, bool); +@@ -231,14 +233,7 @@ struct blk_mq_ops { + void (*show_rq)(struct seq_file *m, struct request *rq); + #endif + +-#ifndef __GENKSYMS__ +- /* +- * Return a queue map type for the given request/bio flags +- */ +- rq_flags_to_type_fn * rq_flags_to_type; +-#else + KABI_RESERVE(1) +-#endif + KABI_RESERVE(2) + KABI_RESERVE(3) + KABI_RESERVE(4) +-- +2.27.0 + diff --git a/patches/0397-blk-mq-Rename-BLK_MQ_F_TAG_SHARED-as-BLK_MQ_F_TAG_QU.patch b/patches/0397-blk-mq-Rename-BLK_MQ_F_TAG_SHARED-as-BLK_MQ_F_TAG_QU.patch new file mode 100644 index 00000000..3ce951c4 --- /dev/null +++ b/patches/0397-blk-mq-Rename-BLK_MQ_F_TAG_SHARED-as-BLK_MQ_F_TAG_QU.patch @@ -0,0 +1,187 @@ +From 84b58e24990a4197e670959877ca1480765d5f16 Mon Sep 17 00:00:00 2001 +From: Ming Lei +Date: Wed, 19 Aug 2020 23:20:19 +0800 +Subject: [PATCH 079/256] blk-mq: Rename BLK_MQ_F_TAG_SHARED as + BLK_MQ_F_TAG_QUEUE_SHARED + +mainline inclusion +from mainline-v5.10-rc1 +commit 51db1c37ee166159c5753ce8d64d6bacf113e0f0 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=51db1c37ee166159c5753ce8d64d6bacf113e0f0 + +---------------------------------------------------------------------- + +BLK_MQ_F_TAG_SHARED actually means that tags is shared among request +queues, all of which should belong to LUNs attached to same HBA. + +So rename it to make the point explicitly. + +[jpg: rebase a few times, add rnbd-clt.c change] + +Suggested-by: Bart Van Assche +Signed-off-by: Ming Lei +Signed-off-by: John Garry +Tested-by: Douglas Gilbert +Reviewed-by: Hannes Reinecke +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang + + Conflicts: + block/blk-mq-debugfs.c + block/blk-mq-tag.h + block/blk-mq.c + drivers/block/rnbd/rnbd-clt.c + include/linux/blk-mq.h +--- + block/blk-mq-debugfs.c | 2 +- + block/blk-mq-tag.c | 2 +- + block/blk-mq-tag.h | 4 ++-- + block/blk-mq.c | 20 ++++++++++---------- + include/linux/blk-mq.h | 2 +- + 5 files changed, 15 insertions(+), 15 deletions(-) + +diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c +index ff2328464826..1735b07a6b5e 100644 +--- a/block/blk-mq-debugfs.c ++++ b/block/blk-mq-debugfs.c +@@ -251,7 +251,7 @@ static const char *const alloc_policy_name[] = { + #define HCTX_FLAG_NAME(name) [ilog2(BLK_MQ_F_##name)] = #name + static const char *const hctx_flag_name[] = { + HCTX_FLAG_NAME(SHOULD_MERGE), +- HCTX_FLAG_NAME(TAG_SHARED), ++ HCTX_FLAG_NAME(TAG_QUEUE_SHARED), + HCTX_FLAG_NAME(SG_MERGE), + HCTX_FLAG_NAME(BLOCKING), + HCTX_FLAG_NAME(NO_SCHED), +diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c +index fa713873bbb0..2d5e769d1e57 100644 +--- a/block/blk-mq-tag.c ++++ b/block/blk-mq-tag.c +@@ -72,7 +72,7 @@ static inline bool hctx_may_queue(struct blk_mq_hw_ctx *hctx, + { + unsigned int depth, users; + +- if (!hctx || !(hctx->flags & BLK_MQ_F_TAG_SHARED)) ++ if (!hctx || !(hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED)) + return true; + if (!test_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state)) + return true; +diff --git a/block/blk-mq-tag.h b/block/blk-mq-tag.h +index bc7a4c58c76f..8e9a2e3ae842 100644 +--- a/block/blk-mq-tag.h ++++ b/block/blk-mq-tag.h +@@ -71,7 +71,7 @@ extern void __blk_mq_tag_idle(struct blk_mq_hw_ctx *); + + static inline bool blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx) + { +- if (!(hctx->flags & BLK_MQ_F_TAG_SHARED)) ++ if (!(hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED)) + return false; + + return __blk_mq_tag_busy(hctx); +@@ -79,7 +79,7 @@ static inline bool blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx) + + static inline void blk_mq_tag_idle(struct blk_mq_hw_ctx *hctx) + { +- if (!(hctx->flags & BLK_MQ_F_TAG_SHARED)) ++ if (!(hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED)) + return; + + __blk_mq_tag_idle(hctx); +diff --git a/block/blk-mq.c b/block/blk-mq.c +index 0cfb9449984d..376136165299 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -347,7 +347,7 @@ static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data, + rq->tag = -1; + rq->internal_tag = tag; + } else { +- if (data->hctx->flags & BLK_MQ_F_TAG_SHARED) { ++ if (data->hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED) { + rq_flags = RQF_MQ_INFLIGHT; + atomic_inc(&data->hctx->nr_active); + } +@@ -1116,7 +1116,7 @@ static bool blk_mq_mark_tag_wait(struct blk_mq_hw_ctx *hctx, + wait_queue_entry_t *wait; + bool ret; + +- if (!(hctx->flags & BLK_MQ_F_TAG_SHARED)) { ++ if (!(hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED)) { + if (!test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state)) + set_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state); + +@@ -1267,7 +1267,7 @@ bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list, + * For non-shared tags, the RESTART check + * will suffice. + */ +- if (hctx->flags & BLK_MQ_F_TAG_SHARED) ++ if (hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED) + no_tag = true; + break; + } +@@ -2472,7 +2472,7 @@ blk_mq_alloc_hctx(struct request_queue *q, struct blk_mq_tag_set *set, + spin_lock_init(&hctx->lock); + INIT_LIST_HEAD(&hctx->dispatch); + hctx->queue = q; +- hctx->flags = set->flags & ~BLK_MQ_F_TAG_SHARED; ++ hctx->flags = set->flags & ~BLK_MQ_F_TAG_QUEUE_SHARED; + + INIT_LIST_HEAD(&hctx->hctx_list); + +@@ -2680,10 +2680,10 @@ static void queue_set_hctx_shared(struct request_queue *q, bool shared) + + queue_for_each_hw_ctx(q, hctx, i) { + if (shared) { +- hctx->flags |= BLK_MQ_F_TAG_SHARED; ++ hctx->flags |= BLK_MQ_F_TAG_QUEUE_SHARED; + } else { + blk_mq_tag_idle(hctx); +- hctx->flags &= ~BLK_MQ_F_TAG_SHARED; ++ hctx->flags &= ~BLK_MQ_F_TAG_QUEUE_SHARED; + } + } + } +@@ -2710,7 +2710,7 @@ static void blk_mq_del_queue_tag_set(struct request_queue *q) + list_del(&q->tag_set_list); + if (list_is_singular(&set->tag_list)) { + /* just transitioned to unshared */ +- set->flags &= ~BLK_MQ_F_TAG_SHARED; ++ set->flags &= ~BLK_MQ_F_TAG_QUEUE_SHARED; + /* update existing queue */ + blk_mq_update_tag_set_depth(set, false); + } +@@ -2727,12 +2727,12 @@ static void blk_mq_add_queue_tag_set(struct blk_mq_tag_set *set, + * Check to see if we're transitioning to shared (from 1 to 2 queues). + */ + if (!list_empty(&set->tag_list) && +- !(set->flags & BLK_MQ_F_TAG_SHARED)) { +- set->flags |= BLK_MQ_F_TAG_SHARED; ++ !(set->flags & BLK_MQ_F_TAG_QUEUE_SHARED)) { ++ set->flags |= BLK_MQ_F_TAG_QUEUE_SHARED; + /* update existing queue */ + blk_mq_update_tag_set_depth(set, true); + } +- if (set->flags & BLK_MQ_F_TAG_SHARED) ++ if (set->flags & BLK_MQ_F_TAG_QUEUE_SHARED) + queue_set_hctx_shared(q, true); + list_add_tail(&q->tag_set_list, &set->tag_list); + +diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h +index b0200a1e1f84..9eb44330d4b3 100644 +--- a/include/linux/blk-mq.h ++++ b/include/linux/blk-mq.h +@@ -245,7 +245,7 @@ struct blk_mq_ops { + + enum { + BLK_MQ_F_SHOULD_MERGE = 1 << 0, +- BLK_MQ_F_TAG_SHARED = 1 << 1, ++ BLK_MQ_F_TAG_QUEUE_SHARED = 1 << 1, + BLK_MQ_F_SG_MERGE = 1 << 2, + BLK_MQ_F_BLOCKING = 1 << 5, + BLK_MQ_F_NO_SCHED = 1 << 6, +-- +2.27.0 + diff --git a/patches/0398-blk-mq-Rename-blk_mq_update_tag_set_depth.patch b/patches/0398-blk-mq-Rename-blk_mq_update_tag_set_depth.patch new file mode 100644 index 00000000..3b2b79bc --- /dev/null +++ b/patches/0398-blk-mq-Rename-blk_mq_update_tag_set_depth.patch @@ -0,0 +1,68 @@ +From 7f010bd7a129e583ace6e23fc79a96becb4bb115 Mon Sep 17 00:00:00 2001 +From: Hannes Reinecke +Date: Wed, 19 Aug 2020 23:20:20 +0800 +Subject: [PATCH 080/256] blk-mq: Rename blk_mq_update_tag_set_depth() + +mainline inclusion +from mainline-v5.10-rc1 +commit 655ac30094da0d724ce66161f15675d30da89cd8 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=655ac30094da0d724ce66161f15675d30da89cd8 + +---------------------------------------------------------------------- + +The function does not set the depth, but rather transitions from +shared to non-shared queues and vice versa. + +So rename it to blk_mq_update_tag_set_shared() to better reflect +its purpose. + +[jpg: take out some unrelated changes in blk_mq_init_bitmap_tags()] + +Signed-off-by: Hannes Reinecke +Signed-off-by: John Garry +Tested-by: Douglas Gilbert +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang +--- + block/blk-mq.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/block/blk-mq.c b/block/blk-mq.c +index 376136165299..feb7cfc52c1c 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -2688,8 +2688,8 @@ static void queue_set_hctx_shared(struct request_queue *q, bool shared) + } + } + +-static void blk_mq_update_tag_set_depth(struct blk_mq_tag_set *set, +- bool shared) ++static void blk_mq_update_tag_set_shared(struct blk_mq_tag_set *set, ++ bool shared) + { + struct request_queue *q; + +@@ -2712,7 +2712,7 @@ static void blk_mq_del_queue_tag_set(struct request_queue *q) + /* just transitioned to unshared */ + set->flags &= ~BLK_MQ_F_TAG_QUEUE_SHARED; + /* update existing queue */ +- blk_mq_update_tag_set_depth(set, false); ++ blk_mq_update_tag_set_shared(set, false); + } + mutex_unlock(&set->tag_list_lock); + INIT_LIST_HEAD(&q->tag_set_list); +@@ -2730,7 +2730,7 @@ static void blk_mq_add_queue_tag_set(struct blk_mq_tag_set *set, + !(set->flags & BLK_MQ_F_TAG_QUEUE_SHARED)) { + set->flags |= BLK_MQ_F_TAG_QUEUE_SHARED; + /* update existing queue */ +- blk_mq_update_tag_set_depth(set, true); ++ blk_mq_update_tag_set_shared(set, true); + } + if (set->flags & BLK_MQ_F_TAG_QUEUE_SHARED) + queue_set_hctx_shared(q, true); +-- +2.27.0 + diff --git a/patches/0399-blk-mq-Free-tags-in-blk_mq_init_tags-upon-error.patch b/patches/0399-blk-mq-Free-tags-in-blk_mq_init_tags-upon-error.patch new file mode 100644 index 00000000..c1100312 --- /dev/null +++ b/patches/0399-blk-mq-Free-tags-in-blk_mq_init_tags-upon-error.patch @@ -0,0 +1,83 @@ +From 6c13a5eb75ce1bbf70ed0c7d9c8e7b4fe6e745bb Mon Sep 17 00:00:00 2001 +From: Hannes Reinecke +Date: Wed, 19 Aug 2020 23:20:21 +0800 +Subject: [PATCH 081/256] blk-mq: Free tags in blk_mq_init_tags() upon error + +mainline inclusion +from mainline-v5.10-rc1 +commit 4d063237b92a4e8d99350ad05492a45009a3c78c +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4d063237b92a4e8d99350ad05492a45009a3c78c + +---------------------------------------------------------------------- + +Since the tags are allocated in blk_mq_init_tags(), it's better practice +to free in that same function upon error, rather than a callee which is to +init the bitmap tags (blk_mq_init_tags()). + +[jpg: Split from an earlier patch with a new commit message] + +Signed-off-by: Hannes Reinecke +Signed-off-by: John Garry +Tested-by: Douglas Gilbert +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang + + Conflicts: + block/blk-mq-tag.c +--- + block/blk-mq-tag.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c +index 2d5e769d1e57..92094ae471b2 100644 +--- a/block/blk-mq-tag.c ++++ b/block/blk-mq-tag.c +@@ -407,24 +407,22 @@ static int bt_alloc(struct sbitmap_queue *bt, unsigned int depth, + node); + } + +-static struct blk_mq_tags *blk_mq_init_bitmap_tags(struct blk_mq_tags *tags, +- int node, int alloc_policy) ++static int blk_mq_init_bitmap_tags(struct blk_mq_tags *tags, ++ int node, int alloc_policy) + { + unsigned int depth = tags->nr_tags - tags->nr_reserved_tags; + bool round_robin = alloc_policy == BLK_TAG_ALLOC_RR; + + if (bt_alloc(&tags->bitmap_tags, depth, round_robin, node)) +- goto free_tags; ++ return -ENOMEM; + if (bt_alloc(&tags->breserved_tags, tags->nr_reserved_tags, round_robin, + node)) + goto free_bitmap_tags; + +- return tags; ++ return 0; + free_bitmap_tags: + sbitmap_queue_free(&tags->bitmap_tags); +-free_tags: +- kfree(blk_mq_tags_to_wrapper(tags)); +- return NULL; ++ return -ENOMEM; + } + + struct blk_mq_tags *blk_mq_init_tags(unsigned int total_tags, +@@ -448,7 +446,11 @@ struct blk_mq_tags *blk_mq_init_tags(unsigned int total_tags, + tags->nr_reserved_tags = reserved_tags; + spin_lock_init(&tags_wrapper->lock); + +- return blk_mq_init_bitmap_tags(tags, node, alloc_policy); ++ if (blk_mq_init_bitmap_tags(tags, node, alloc_policy) < 0) { ++ kfree(tags); ++ return NULL; ++ } ++ return tags; + } + + void blk_mq_free_tags(struct blk_mq_tags *tags) +-- +2.27.0 + diff --git a/patches/0400-blk-mq-Pass-flags-for-tag-init-free.patch b/patches/0400-blk-mq-Pass-flags-for-tag-init-free.patch new file mode 100644 index 00000000..8b36572e --- /dev/null +++ b/patches/0400-blk-mq-Pass-flags-for-tag-init-free.patch @@ -0,0 +1,267 @@ +From 77dcb35e7695d33a709e13b3bca0f53f2bfb19e5 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Wed, 19 Aug 2020 23:20:22 +0800 +Subject: [PATCH 082/256] blk-mq: Pass flags for tag init/free + +mainline inclusion +from mainline-v5.10-rc1 +commit 1c0706a70a64eda48477caa880657e07f5196512 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1c0706a70a64eda48477caa880657e07f5196512 + +---------------------------------------------------------------------- + +Pass hctx/tagset flags argument down to blk_mq_init_tags() and +blk_mq_free_tags() for selective init/free. + +For now, make it include the alloc policy flag, which can be evaluated +when needed (in blk_mq_init_tags()). + +Signed-off-by: John Garry +Tested-by: Douglas Gilbert +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang + + Conflicts: + block/blk-mq-sched.c + block/blk-mq-tag.h +--- + block/blk-mq-sched.c | 9 ++++++--- + block/blk-mq-tag.c | 12 +++++++----- + block/blk-mq-tag.h | 6 ++++-- + block/blk-mq.c | 25 ++++++++++++++----------- + block/blk-mq.h | 5 +++-- + 5 files changed, 34 insertions(+), 23 deletions(-) + +diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c +index 9bf39bb94935..e45c54e7f8d1 100644 +--- a/block/blk-mq-sched.c ++++ b/block/blk-mq-sched.c +@@ -541,9 +541,11 @@ static void blk_mq_sched_free_tags(struct blk_mq_tag_set *set, + struct blk_mq_hw_ctx *hctx, + unsigned int hctx_idx) + { ++ unsigned int flags = set->flags; ++ + if (hctx->sched_tags) { + blk_mq_free_rqs(set, hctx->sched_tags, hctx_idx); +- blk_mq_free_rq_map(hctx->sched_tags); ++ blk_mq_free_rq_map(hctx->sched_tags, flags); + hctx->sched_tags = NULL; + } + } +@@ -553,16 +555,17 @@ static int blk_mq_sched_alloc_tags(struct request_queue *q, + unsigned int hctx_idx) + { + struct blk_mq_tag_set *set = q->tag_set; ++ unsigned int flags = set->flags; + int ret; + + hctx->sched_tags = blk_mq_alloc_rq_map(set, hctx_idx, q->nr_requests, +- set->reserved_tags); ++ set->reserved_tags, flags); + if (!hctx->sched_tags) + return -ENOMEM; + + ret = blk_mq_alloc_rqs(set, hctx->sched_tags, hctx_idx, q->nr_requests); + if (ret) { +- blk_mq_free_rq_map(hctx->sched_tags); ++ blk_mq_free_rq_map(hctx->sched_tags, flags); + hctx->sched_tags = NULL; + } + +diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c +index 92094ae471b2..27e336a89f78 100644 +--- a/block/blk-mq-tag.c ++++ b/block/blk-mq-tag.c +@@ -427,8 +427,9 @@ static int blk_mq_init_bitmap_tags(struct blk_mq_tags *tags, + + struct blk_mq_tags *blk_mq_init_tags(unsigned int total_tags, + unsigned int reserved_tags, +- int node, int alloc_policy) ++ int node, unsigned int flags) + { ++ int alloc_policy = BLK_MQ_FLAG_TO_ALLOC_POLICY(flags); + struct blk_mq_tags *tags; + struct blk_mq_tags_wrapper *tags_wrapper; + +@@ -453,7 +454,7 @@ struct blk_mq_tags *blk_mq_init_tags(unsigned int total_tags, + return tags; + } + +-void blk_mq_free_tags(struct blk_mq_tags *tags) ++void blk_mq_free_tags(struct blk_mq_tags *tags, unsigned int flags) + { + sbitmap_queue_free(&tags->bitmap_tags); + sbitmap_queue_free(&tags->breserved_tags); +@@ -475,6 +476,7 @@ int blk_mq_tag_update_depth(struct blk_mq_hw_ctx *hctx, + */ + if (tdepth > tags->nr_tags) { + struct blk_mq_tag_set *set = hctx->queue->tag_set; ++ unsigned int flags = set->flags; + struct blk_mq_tags *new; + bool ret; + +@@ -489,17 +491,17 @@ int blk_mq_tag_update_depth(struct blk_mq_hw_ctx *hctx, + return -EINVAL; + + new = blk_mq_alloc_rq_map(set, hctx->queue_num, tdepth, +- tags->nr_reserved_tags); ++ tags->nr_reserved_tags, flags); + if (!new) + return -ENOMEM; + ret = blk_mq_alloc_rqs(set, new, hctx->queue_num, tdepth); + if (ret) { +- blk_mq_free_rq_map(new); ++ blk_mq_free_rq_map(new, flags); + return -ENOMEM; + } + + blk_mq_free_rqs(set, *tagsptr, hctx->queue_num); +- blk_mq_free_rq_map(*tagsptr); ++ blk_mq_free_rq_map(*tagsptr, flags); + *tagsptr = new; + } else { + /* +diff --git a/block/blk-mq-tag.h b/block/blk-mq-tag.h +index 8e9a2e3ae842..ad7948b59156 100644 +--- a/block/blk-mq-tag.h ++++ b/block/blk-mq-tag.h +@@ -38,8 +38,10 @@ struct blk_mq_tags_wrapper { + #define blk_mq_tags_unlock_irqrestore(tags, flags) \ + spin_unlock_irqrestore(&blk_mq_tags_to_wrapper(tags)->lock, flags) + +-extern struct blk_mq_tags *blk_mq_init_tags(unsigned int nr_tags, unsigned int reserved_tags, int node, int alloc_policy); +-extern void blk_mq_free_tags(struct blk_mq_tags *tags); ++extern struct blk_mq_tags *blk_mq_init_tags(unsigned int nr_tags, ++ unsigned int reserved_tags, ++ int node, unsigned int flags); ++extern void blk_mq_free_tags(struct blk_mq_tags *tags, unsigned int flags); + + extern unsigned int blk_mq_get_tag(struct blk_mq_alloc_data *data); + extern void blk_mq_put_tag(struct blk_mq_hw_ctx *hctx, struct blk_mq_tags *tags, +diff --git a/block/blk-mq.c b/block/blk-mq.c +index feb7cfc52c1c..ecedc471fee8 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -2163,20 +2163,21 @@ void blk_mq_free_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags, + } + } + +-void blk_mq_free_rq_map(struct blk_mq_tags *tags) ++void blk_mq_free_rq_map(struct blk_mq_tags *tags, unsigned int flags) + { + kfree(tags->rqs); + tags->rqs = NULL; + kfree(tags->static_rqs); + tags->static_rqs = NULL; + +- blk_mq_free_tags(tags); ++ blk_mq_free_tags(tags, flags); + } + + struct blk_mq_tags *blk_mq_alloc_rq_map(struct blk_mq_tag_set *set, + unsigned int hctx_idx, + unsigned int nr_tags, +- unsigned int reserved_tags) ++ unsigned int reserved_tags, ++ unsigned int flags) + { + struct blk_mq_tags *tags; + int node; +@@ -2185,8 +2186,7 @@ struct blk_mq_tags *blk_mq_alloc_rq_map(struct blk_mq_tag_set *set, + if (node == NUMA_NO_NODE) + node = set->numa_node; + +- tags = blk_mq_init_tags(nr_tags, reserved_tags, node, +- BLK_MQ_FLAG_TO_ALLOC_POLICY(set->flags)); ++ tags = blk_mq_init_tags(nr_tags, reserved_tags, node, flags); + if (!tags) + return NULL; + +@@ -2194,7 +2194,7 @@ struct blk_mq_tags *blk_mq_alloc_rq_map(struct blk_mq_tag_set *set, + GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY, + node); + if (!tags->rqs) { +- blk_mq_free_tags(tags); ++ blk_mq_free_tags(tags, flags); + return NULL; + } + +@@ -2203,7 +2203,7 @@ struct blk_mq_tags *blk_mq_alloc_rq_map(struct blk_mq_tag_set *set, + node); + if (!tags->static_rqs) { + kfree(tags->rqs); +- blk_mq_free_tags(tags); ++ blk_mq_free_tags(tags, flags); + return NULL; + } + +@@ -2550,10 +2550,11 @@ static void blk_mq_init_cpu_queues(struct request_queue *q, + + static bool __blk_mq_alloc_rq_map(struct blk_mq_tag_set *set, int hctx_idx) + { ++ unsigned int flags = set->flags; + int ret = 0; + + set->tags[hctx_idx] = blk_mq_alloc_rq_map(set, hctx_idx, +- set->queue_depth, set->reserved_tags); ++ set->queue_depth, set->reserved_tags, flags); + if (!set->tags[hctx_idx]) + return false; + +@@ -2562,7 +2563,7 @@ static bool __blk_mq_alloc_rq_map(struct blk_mq_tag_set *set, int hctx_idx) + if (!ret) + return true; + +- blk_mq_free_rq_map(set->tags[hctx_idx]); ++ blk_mq_free_rq_map(set->tags[hctx_idx], flags); + set->tags[hctx_idx] = NULL; + return false; + } +@@ -2570,9 +2571,11 @@ static bool __blk_mq_alloc_rq_map(struct blk_mq_tag_set *set, int hctx_idx) + static void blk_mq_free_map_and_requests(struct blk_mq_tag_set *set, + unsigned int hctx_idx) + { ++ unsigned int flags = set->flags; ++ + if (set->tags && set->tags[hctx_idx]) { + blk_mq_free_rqs(set, set->tags[hctx_idx], hctx_idx); +- blk_mq_free_rq_map(set->tags[hctx_idx]); ++ blk_mq_free_rq_map(set->tags[hctx_idx], flags); + set->tags[hctx_idx] = NULL; + } + } +@@ -3032,7 +3035,7 @@ static int __blk_mq_alloc_rq_maps(struct blk_mq_tag_set *set) + + out_unwind: + while (--i >= 0) +- blk_mq_free_rq_map(set->tags[i]); ++ blk_mq_free_rq_map(set->tags[i], set->flags); + + return -ENOMEM; + } +diff --git a/block/blk-mq.h b/block/blk-mq.h +index 53db914ad7fd..9f26211c3060 100644 +--- a/block/blk-mq.h ++++ b/block/blk-mq.h +@@ -59,11 +59,12 @@ void blk_mq_unquiesce_queue_internal(struct request_queue *q); + */ + void blk_mq_free_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags, + unsigned int hctx_idx); +-void blk_mq_free_rq_map(struct blk_mq_tags *tags); ++void blk_mq_free_rq_map(struct blk_mq_tags *tags, unsigned int flags); + struct blk_mq_tags *blk_mq_alloc_rq_map(struct blk_mq_tag_set *set, + unsigned int hctx_idx, + unsigned int nr_tags, +- unsigned int reserved_tags); ++ unsigned int reserved_tags, ++ unsigned int flags); + int blk_mq_alloc_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags, + unsigned int hctx_idx, unsigned int depth); + +-- +2.27.0 + diff --git a/patches/0401-blk-mq-Use-pointers-for-blk_mq_tags-bitmap-tags.patch b/patches/0401-blk-mq-Use-pointers-for-blk_mq_tags-bitmap-tags.patch new file mode 100644 index 00000000..9b702b8a --- /dev/null +++ b/patches/0401-blk-mq-Use-pointers-for-blk_mq_tags-bitmap-tags.patch @@ -0,0 +1,270 @@ +From e4e4a28d09e1e43f7cbdf11251f3a762f9534ce8 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Wed, 19 Aug 2020 23:20:23 +0800 +Subject: [PATCH 083/256] blk-mq: Use pointers for blk_mq_tags bitmap tags + +mainline inclusion +from mainline-v5.10-rc1 +commit 222a5ae03cdd12e7643f2f64689a39ed547650cb +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=222a5ae03cdd12e7643f2f64689a39ed547650cb + +---------------------------------------------------------------------- + +Introduce pointers for the blk_mq_tags regular and reserved bitmap tags, +with the goal of later being able to use a common shared tag bitmap across +all HW contexts in a set. + +Signed-off-by: John Garry +Tested-by: Don Brace #SCSI resv cmds patches used +Tested-by: Douglas Gilbert +Reviewed-by: Hannes Reinecke +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang + + Conflicts: + block/blk-mq-tag.c + block/blk-mq.c + block/kyber-iosched.c +--- + block/bfq-iosched.c | 4 ++-- + block/blk-mq-debugfs.c | 8 ++++---- + block/blk-mq-tag.c | 43 ++++++++++++++++++++++-------------------- + block/blk-mq-tag.h | 7 +++++-- + block/blk-mq.c | 2 +- + block/kyber-iosched.c | 4 ++-- + 6 files changed, 37 insertions(+), 31 deletions(-) + +diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c +index 473d9e31ff87..2213cb0345b3 100644 +--- a/block/bfq-iosched.c ++++ b/block/bfq-iosched.c +@@ -5378,8 +5378,8 @@ static void bfq_depth_updated(struct blk_mq_hw_ctx *hctx) + struct blk_mq_tags *tags = hctx->sched_tags; + unsigned int min_shallow; + +- min_shallow = bfq_update_depths(bfqd, &tags->bitmap_tags); +- sbitmap_queue_min_shallow_depth(&tags->bitmap_tags, min_shallow); ++ min_shallow = bfq_update_depths(bfqd, tags->bitmap_tags); ++ sbitmap_queue_min_shallow_depth(tags->bitmap_tags, min_shallow); + } + + static int bfq_init_hctx(struct blk_mq_hw_ctx *hctx, unsigned int index) +diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c +index 1735b07a6b5e..8fb54b625e41 100644 +--- a/block/blk-mq-debugfs.c ++++ b/block/blk-mq-debugfs.c +@@ -465,11 +465,11 @@ static void blk_mq_debugfs_tags_show(struct seq_file *m, + atomic_read(&tags->active_queues)); + + seq_puts(m, "\nbitmap_tags:\n"); +- sbitmap_queue_show(&tags->bitmap_tags, m); ++ sbitmap_queue_show(tags->bitmap_tags, m); + + if (tags->nr_reserved_tags) { + seq_puts(m, "\nbreserved_tags:\n"); +- sbitmap_queue_show(&tags->breserved_tags, m); ++ sbitmap_queue_show(tags->breserved_tags, m); + } + } + +@@ -500,7 +500,7 @@ static int hctx_tags_bitmap_show(void *data, struct seq_file *m) + if (res) + goto out; + if (hctx->tags) +- sbitmap_bitmap_show(&hctx->tags->bitmap_tags.sb, m); ++ sbitmap_bitmap_show(&hctx->tags->bitmap_tags->sb, m); + mutex_unlock(&q->sysfs_lock); + + out: +@@ -534,7 +534,7 @@ static int hctx_sched_tags_bitmap_show(void *data, struct seq_file *m) + if (res) + goto out; + if (hctx->sched_tags) +- sbitmap_bitmap_show(&hctx->sched_tags->bitmap_tags.sb, m); ++ sbitmap_bitmap_show(&hctx->sched_tags->bitmap_tags->sb, m); + mutex_unlock(&q->sysfs_lock); + + out: +diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c +index 27e336a89f78..8e7d1ddd924a 100644 +--- a/block/blk-mq-tag.c ++++ b/block/blk-mq-tag.c +@@ -19,7 +19,7 @@ bool blk_mq_has_free_tags(struct blk_mq_tags *tags) + if (!tags) + return true; + +- return sbitmap_any_bit_clear(&tags->bitmap_tags.sb); ++ return sbitmap_any_bit_clear(&tags->bitmap_tags->sb); + } + + /* +@@ -42,9 +42,9 @@ bool __blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx) + */ + void blk_mq_tag_wakeup_all(struct blk_mq_tags *tags, bool include_reserve) + { +- sbitmap_queue_wake_all(&tags->bitmap_tags); ++ sbitmap_queue_wake_all(tags->bitmap_tags); + if (include_reserve) +- sbitmap_queue_wake_all(&tags->breserved_tags); ++ sbitmap_queue_wake_all(tags->breserved_tags); + } + + /* +@@ -121,10 +121,10 @@ unsigned int blk_mq_get_tag(struct blk_mq_alloc_data *data) + WARN_ON_ONCE(1); + return BLK_MQ_TAG_FAIL; + } +- bt = &tags->breserved_tags; ++ bt = tags->breserved_tags; + tag_offset = 0; + } else { +- bt = &tags->bitmap_tags; ++ bt = tags->bitmap_tags; + tag_offset = tags->nr_reserved_tags; + } + +@@ -173,9 +173,9 @@ unsigned int blk_mq_get_tag(struct blk_mq_alloc_data *data) + data->ctx->cpu); + tags = blk_mq_tags_from_data(data); + if (data->flags & BLK_MQ_REQ_RESERVED) +- bt = &tags->breserved_tags; ++ bt = tags->breserved_tags; + else +- bt = &tags->bitmap_tags; ++ bt = tags->bitmap_tags; + + finish_wait(&ws->wait, &wait); + +@@ -206,10 +206,10 @@ void blk_mq_put_tag(struct blk_mq_hw_ctx *hctx, struct blk_mq_tags *tags, + const int real_tag = tag - tags->nr_reserved_tags; + + BUG_ON(real_tag >= tags->nr_tags); +- sbitmap_queue_clear(&tags->bitmap_tags, real_tag, ctx->cpu); ++ sbitmap_queue_clear(tags->bitmap_tags, real_tag, ctx->cpu); + } else { + BUG_ON(tag >= tags->nr_reserved_tags); +- sbitmap_queue_clear(&tags->breserved_tags, tag, ctx->cpu); ++ sbitmap_queue_clear(tags->breserved_tags, tag, ctx->cpu); + } + } + +@@ -323,8 +323,8 @@ static void blk_mq_all_tag_busy_iter(struct blk_mq_tags *tags, + busy_tag_iter_fn *fn, void *priv) + { + if (tags->nr_reserved_tags) +- bt_tags_for_each(tags, &tags->breserved_tags, fn, priv, true); +- bt_tags_for_each(tags, &tags->bitmap_tags, fn, priv, false); ++ bt_tags_for_each(tags, tags->breserved_tags, fn, priv, true); ++ bt_tags_for_each(tags, tags->bitmap_tags, fn, priv, false); + } + + void blk_mq_tagset_busy_iter(struct blk_mq_tag_set *tagset, +@@ -394,8 +394,8 @@ void blk_mq_queue_tag_busy_iter(struct request_queue *q, busy_iter_fn *fn, + continue; + + if (tags->nr_reserved_tags) +- bt_for_each(hctx, &tags->breserved_tags, fn, priv, true); +- bt_for_each(hctx, &tags->bitmap_tags, fn, priv, false); ++ bt_for_each(hctx, tags->breserved_tags, fn, priv, true); ++ bt_for_each(hctx, tags->bitmap_tags, fn, priv, false); + } + blk_queue_exit(q); + } +@@ -413,15 +413,18 @@ static int blk_mq_init_bitmap_tags(struct blk_mq_tags *tags, + unsigned int depth = tags->nr_tags - tags->nr_reserved_tags; + bool round_robin = alloc_policy == BLK_TAG_ALLOC_RR; + +- if (bt_alloc(&tags->bitmap_tags, depth, round_robin, node)) ++ if (bt_alloc(&tags->__bitmap_tags, depth, round_robin, node)) + return -ENOMEM; +- if (bt_alloc(&tags->breserved_tags, tags->nr_reserved_tags, round_robin, +- node)) ++ if (bt_alloc(&tags->__breserved_tags, tags->nr_reserved_tags, ++ round_robin, node)) + goto free_bitmap_tags; + ++ tags->bitmap_tags = &tags->__bitmap_tags; ++ tags->breserved_tags = &tags->__breserved_tags; ++ + return 0; + free_bitmap_tags: +- sbitmap_queue_free(&tags->bitmap_tags); ++ sbitmap_queue_free(&tags->__bitmap_tags); + return -ENOMEM; + } + +@@ -456,8 +459,8 @@ struct blk_mq_tags *blk_mq_init_tags(unsigned int total_tags, + + void blk_mq_free_tags(struct blk_mq_tags *tags, unsigned int flags) + { +- sbitmap_queue_free(&tags->bitmap_tags); +- sbitmap_queue_free(&tags->breserved_tags); ++ sbitmap_queue_free(&tags->__bitmap_tags); ++ sbitmap_queue_free(&tags->__breserved_tags); + kfree(blk_mq_tags_to_wrapper(tags)); + } + +@@ -508,7 +511,7 @@ int blk_mq_tag_update_depth(struct blk_mq_hw_ctx *hctx, + * Don't need (or can't) update reserved tags here, they + * remain static and should never need resizing. + */ +- sbitmap_queue_resize(&tags->bitmap_tags, ++ sbitmap_queue_resize(tags->bitmap_tags, + tdepth - tags->nr_reserved_tags); + } + +diff --git a/block/blk-mq-tag.h b/block/blk-mq-tag.h +index ad7948b59156..d932f9416d93 100644 +--- a/block/blk-mq-tag.h ++++ b/block/blk-mq-tag.h +@@ -13,8 +13,11 @@ struct blk_mq_tags { + + atomic_t active_queues; + +- struct sbitmap_queue bitmap_tags; +- struct sbitmap_queue breserved_tags; ++ struct sbitmap_queue *bitmap_tags; ++ struct sbitmap_queue *breserved_tags; ++ ++ struct sbitmap_queue __bitmap_tags; ++ struct sbitmap_queue __breserved_tags; + + struct request **rqs; + struct request **static_rqs; +diff --git a/block/blk-mq.c b/block/blk-mq.c +index ecedc471fee8..7e17a06f4c9e 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -1135,7 +1135,7 @@ static bool blk_mq_mark_tag_wait(struct blk_mq_hw_ctx *hctx, + if (!list_empty_careful(&wait->entry)) + return false; + +- wq = &bt_wait_ptr(&hctx->tags->bitmap_tags, hctx)->wait; ++ wq = &bt_wait_ptr(hctx->tags->bitmap_tags, hctx)->wait; + + spin_lock_irq(&wq->lock); + spin_lock(&hctx->dispatch_wait_lock); +diff --git a/block/kyber-iosched.c b/block/kyber-iosched.c +index e15ecd335eec..b67359461d49 100644 +--- a/block/kyber-iosched.c ++++ b/block/kyber-iosched.c +@@ -395,11 +395,11 @@ static void kyber_depth_updated(struct blk_mq_hw_ctx *hctx) + { + struct kyber_queue_data *kqd = hctx->queue->elevator->elevator_data; + struct blk_mq_tags *tags = hctx->sched_tags; +- unsigned int shift = tags->bitmap_tags.sb.shift; ++ unsigned int shift = tags->bitmap_tags->sb.shift; + + kqd->async_depth = (1U << shift) * KYBER_ASYNC_PERCENT / 100U; + +- sbitmap_queue_min_shallow_depth(&tags->bitmap_tags, kqd->async_depth); ++ sbitmap_queue_min_shallow_depth(tags->bitmap_tags, kqd->async_depth); + } + + static int kyber_init_hctx(struct blk_mq_hw_ctx *hctx, unsigned int hctx_idx) +-- +2.27.0 + diff --git a/patches/0402-fix-kabi-broken-due-to-change-of-struct-blk_mq_tags.patch b/patches/0402-fix-kabi-broken-due-to-change-of-struct-blk_mq_tags.patch new file mode 100644 index 00000000..ee367e63 --- /dev/null +++ b/patches/0402-fix-kabi-broken-due-to-change-of-struct-blk_mq_tags.patch @@ -0,0 +1,53 @@ +From dd3ba3d596c2b84e2741a6ea7920a444c54c94d3 Mon Sep 17 00:00:00 2001 +From: YunYi Yang +Date: Thu, 24 Aug 2023 17:29:53 +0800 +Subject: [PATCH 084/256] fix kabi broken due to change of struct blk_mq_tags + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +---------------------------------------------------------------------- + +Commit ("blk-mq: Use pointers for blk_mq_tags +bitmap tags") changes the struct blk_mq_tags, so we need +to fix kabi broken problem. + +Signed-off-by: YunYi Yang +--- + block/blk-mq-tag.h | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/block/blk-mq-tag.h b/block/blk-mq-tag.h +index d932f9416d93..ce57fd05a4c2 100644 +--- a/block/blk-mq-tag.h ++++ b/block/blk-mq-tag.h +@@ -13,15 +13,21 @@ struct blk_mq_tags { + + atomic_t active_queues; + +- struct sbitmap_queue *bitmap_tags; +- struct sbitmap_queue *breserved_tags; +- ++#ifdef __GENKSYMS__ ++ struct sbitmap_queue bitmap_tags; ++ struct sbitmap_queue breserved_tags; ++#else + struct sbitmap_queue __bitmap_tags; + struct sbitmap_queue __breserved_tags; +- ++#endif + struct request **rqs; + struct request **static_rqs; + struct list_head page_list; ++ ++#ifndef __GENKSYMS__ ++ struct sbitmap_queue *bitmap_tags; ++ struct sbitmap_queue *breserved_tags; ++#endif + }; + + struct blk_mq_tags_wrapper { +-- +2.27.0 + diff --git a/patches/0403-blk-mq-Facilitate-a-shared-sbitmap-per-tagset.patch b/patches/0403-blk-mq-Facilitate-a-shared-sbitmap-per-tagset.patch new file mode 100644 index 00000000..e33cd7ef --- /dev/null +++ b/patches/0403-blk-mq-Facilitate-a-shared-sbitmap-per-tagset.patch @@ -0,0 +1,321 @@ +From 19361218c43d57d91214969c710daee5ca0ab6be Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Wed, 19 Aug 2020 23:20:24 +0800 +Subject: [PATCH 085/256] blk-mq: Facilitate a shared sbitmap per tagset + +mainline inclusion +from mainline-v5.10-rc1 +commit 32bc15afed04bd73e29d713d8db47818d6aa89af +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=32bc15afed04bd73e29d713d8db47818d6aa89af + +---------------------------------------------------------------------- + +Some SCSI HBAs (such as HPSA, megaraid, mpt3sas, hisi_sas_v3 ..) support +multiple reply queues with single hostwide tags. + +In addition, these drivers want to use interrupt assignment in +pci_alloc_irq_vectors(PCI_IRQ_AFFINITY). However, as discussed in [0], +CPU hotplug may cause in-flight IO completion to not be serviced when an +interrupt is shutdown. That problem is solved in commit bf0beec0607d +("blk-mq: drain I/O when all CPUs in a hctx are offline"). + +However, to take advantage of that blk-mq feature, the HBA HW queuess are +required to be mapped to that of the blk-mq hctx's; to do that, the HBA HW +queues need to be exposed to the upper layer. + +In making that transition, the per-SCSI command request tags are no +longer unique per Scsi host - they are just unique per hctx. As such, the +HBA LLDD would have to generate this tag internally, which has a certain +performance overhead. + +However another problem is that blk-mq assumes the host may accept +(Scsi_host.can_queue * #hw queue) commands. In commit 6eb045e092ef ("scsi: + core: avoid host-wide host_busy counter for scsi_mq"), the Scsi host busy +counter was removed, which would stop the LLDD being sent more than +.can_queue commands; however, it should still be ensured that the block +layer does not issue more than .can_queue commands to the Scsi host. + +To solve this problem, introduce a shared sbitmap per blk_mq_tag_set, +which may be requested at init time. + +New flag BLK_MQ_F_TAG_HCTX_SHARED should be set when requesting the +tagset to indicate whether the shared sbitmap should be used. + +Even when BLK_MQ_F_TAG_HCTX_SHARED is set, a full set of tags and requests +are still allocated per hctx; the reason for this is that if tags and +requests were only allocated for a single hctx - like hctx0 - it may break +block drivers which expect a request be associated with a specific hctx, +i.e. not always hctx0. This will introduce extra memory usage. + +This change is based on work originally from Ming Lei in [1] and from +Bart's suggestion in [2]. + +[0] https://lore.kernel.org/linux-block/alpine.DEB.2.21.1904051331270.1802@nanos.tec.linutronix.de/ +[1] https://lore.kernel.org/linux-block/20190531022801.10003-1-ming.lei@redhat.com/ +[2] https://lore.kernel.org/linux-block/ff77beff-5fd9-9f05-12b6-826922bace1f@huawei.com/T/#m3db0a602f095cbcbff27e9c884d6b4ae826144be + +Signed-off-by: John Garry +Tested-by: Don Brace #SCSI resv cmds patches used +Tested-by: Douglas Gilbert +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang + + Conflicts: + block/blk-mq-sched.c + block/blk-mq-tag.c + include/linux/blk-mq.h +--- + block/blk-mq-sched.c | 5 +++-- + block/blk-mq-tag.c | 51 ++++++++++++++++++++++++++++++++++++++---- + block/blk-mq-tag.h | 7 ++++++ + block/blk-mq.c | 15 +++++++++++++ + block/blk-mq.h | 5 +++++ + include/linux/blk-mq.h | 9 ++++++++ + 6 files changed, 86 insertions(+), 6 deletions(-) + +diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c +index e45c54e7f8d1..17a32a815cb3 100644 +--- a/block/blk-mq-sched.c ++++ b/block/blk-mq-sched.c +@@ -541,7 +541,7 @@ static void blk_mq_sched_free_tags(struct blk_mq_tag_set *set, + struct blk_mq_hw_ctx *hctx, + unsigned int hctx_idx) + { +- unsigned int flags = set->flags; ++ unsigned int flags = set->flags & ~BLK_MQ_F_TAG_HCTX_SHARED; + + if (hctx->sched_tags) { + blk_mq_free_rqs(set, hctx->sched_tags, hctx_idx); +@@ -555,7 +555,8 @@ static int blk_mq_sched_alloc_tags(struct request_queue *q, + unsigned int hctx_idx) + { + struct blk_mq_tag_set *set = q->tag_set; +- unsigned int flags = set->flags; ++ /* Clear HCTX_SHARED so tags are init'ed */ ++ unsigned int flags = set->flags & ~BLK_MQ_F_TAG_HCTX_SHARED; + int ret; + + hctx->sched_tags = blk_mq_alloc_rq_map(set, hctx_idx, q->nr_requests, +diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c +index 8e7d1ddd924a..e8bd8e8ccab4 100644 +--- a/block/blk-mq-tag.c ++++ b/block/blk-mq-tag.c +@@ -254,7 +254,7 @@ static bool bt_iter(struct sbitmap *bitmap, unsigned int bitnr, void *data) + if (!rq) + return true; + +- if (rq->q == hctx->queue) ++ if (rq->q == hctx->queue && rq->mq_hctx == hctx) + iter_data->fn(hctx, rq, iter_data->data, reserved); + blk_mq_put_rq_ref(rq); + return true; +@@ -428,6 +428,38 @@ static int blk_mq_init_bitmap_tags(struct blk_mq_tags *tags, + return -ENOMEM; + } + ++int blk_mq_init_shared_sbitmap(struct blk_mq_tag_set *set, unsigned int flags) ++{ ++ unsigned int depth = set->queue_depth - set->reserved_tags; ++ int alloc_policy = BLK_MQ_FLAG_TO_ALLOC_POLICY(set->flags); ++ bool round_robin = alloc_policy == BLK_TAG_ALLOC_RR; ++ int i, node = set->numa_node; ++ ++ if (bt_alloc(&set->__bitmap_tags, depth, round_robin, node)) ++ return -ENOMEM; ++ if (bt_alloc(&set->__breserved_tags, set->reserved_tags, ++ round_robin, node)) ++ goto free_bitmap_tags; ++ ++ for (i = 0; i < set->nr_hw_queues; i++) { ++ struct blk_mq_tags *tags = set->tags[i]; ++ ++ tags->bitmap_tags = &set->__bitmap_tags; ++ tags->breserved_tags = &set->__breserved_tags; ++ } ++ ++ return 0; ++free_bitmap_tags: ++ sbitmap_queue_free(&set->__bitmap_tags); ++ return -ENOMEM; ++} ++ ++void blk_mq_exit_shared_sbitmap(struct blk_mq_tag_set *set) ++{ ++ sbitmap_queue_free(&set->__bitmap_tags); ++ sbitmap_queue_free(&set->__breserved_tags); ++} ++ + struct blk_mq_tags *blk_mq_init_tags(unsigned int total_tags, + unsigned int reserved_tags, + int node, unsigned int flags) +@@ -450,6 +482,9 @@ struct blk_mq_tags *blk_mq_init_tags(unsigned int total_tags, + tags->nr_reserved_tags = reserved_tags; + spin_lock_init(&tags_wrapper->lock); + ++ if (flags & BLK_MQ_F_TAG_HCTX_SHARED) ++ return tags; ++ + if (blk_mq_init_bitmap_tags(tags, node, alloc_policy) < 0) { + kfree(tags); + return NULL; +@@ -459,8 +494,10 @@ struct blk_mq_tags *blk_mq_init_tags(unsigned int total_tags, + + void blk_mq_free_tags(struct blk_mq_tags *tags, unsigned int flags) + { +- sbitmap_queue_free(&tags->__bitmap_tags); +- sbitmap_queue_free(&tags->__breserved_tags); ++ if (!(flags & BLK_MQ_F_TAG_HCTX_SHARED)) { ++ sbitmap_queue_free(tags->bitmap_tags); ++ sbitmap_queue_free(tags->breserved_tags); ++ } + kfree(blk_mq_tags_to_wrapper(tags)); + } + +@@ -479,7 +516,8 @@ int blk_mq_tag_update_depth(struct blk_mq_hw_ctx *hctx, + */ + if (tdepth > tags->nr_tags) { + struct blk_mq_tag_set *set = hctx->queue->tag_set; +- unsigned int flags = set->flags; ++ /* Only sched tags can grow, so clear HCTX_SHARED flag */ ++ unsigned int flags = set->flags & ~BLK_MQ_F_TAG_HCTX_SHARED; + struct blk_mq_tags *new; + bool ret; + +@@ -518,6 +556,11 @@ int blk_mq_tag_update_depth(struct blk_mq_hw_ctx *hctx, + return 0; + } + ++void blk_mq_tag_resize_shared_sbitmap(struct blk_mq_tag_set *set, unsigned int size) ++{ ++ sbitmap_queue_resize(&set->__bitmap_tags, size - set->reserved_tags); ++} ++ + /** + * blk_mq_unique_tag() - return a tag that is unique queue-wide + * @rq: request for which to compute a unique tag +diff --git a/block/blk-mq-tag.h b/block/blk-mq-tag.h +index ce57fd05a4c2..b2851213e859 100644 +--- a/block/blk-mq-tag.h ++++ b/block/blk-mq-tag.h +@@ -52,6 +52,10 @@ extern struct blk_mq_tags *blk_mq_init_tags(unsigned int nr_tags, + int node, unsigned int flags); + extern void blk_mq_free_tags(struct blk_mq_tags *tags, unsigned int flags); + ++extern int blk_mq_init_shared_sbitmap(struct blk_mq_tag_set *set, ++ unsigned int flags); ++extern void blk_mq_exit_shared_sbitmap(struct blk_mq_tag_set *set); ++ + extern unsigned int blk_mq_get_tag(struct blk_mq_alloc_data *data); + extern void blk_mq_put_tag(struct blk_mq_hw_ctx *hctx, struct blk_mq_tags *tags, + struct blk_mq_ctx *ctx, unsigned int tag); +@@ -59,6 +63,9 @@ extern bool blk_mq_has_free_tags(struct blk_mq_tags *tags); + extern int blk_mq_tag_update_depth(struct blk_mq_hw_ctx *hctx, + struct blk_mq_tags **tags, + unsigned int depth, bool can_grow); ++extern void blk_mq_tag_resize_shared_sbitmap(struct blk_mq_tag_set *set, ++ unsigned int size); ++ + extern void blk_mq_tag_wakeup_all(struct blk_mq_tags *tags, bool); + void blk_mq_queue_tag_busy_iter(struct request_queue *q, busy_iter_fn *fn, + void *priv); +diff --git a/block/blk-mq.c b/block/blk-mq.c +index 7e17a06f4c9e..38503e19ae84 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -3179,11 +3179,21 @@ int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set) + if (ret) + goto out_free_mq_map; + ++ if (blk_mq_is_sbitmap_shared(set->flags)) { ++ if (blk_mq_init_shared_sbitmap(set, set->flags)) { ++ ret = -ENOMEM; ++ goto out_free_mq_rq_maps; ++ } ++ } ++ + mutex_init(&set->tag_list_lock); + INIT_LIST_HEAD(&set->tag_list); + + return 0; + ++out_free_mq_rq_maps: ++ for (i = 0; i < set->nr_hw_queues; i++) ++ blk_mq_free_map_and_requests(set, i); + out_free_mq_map: + for (i = 0; i < set->nr_maps; i++) { + kfree(set->map[i].mq_map); +@@ -3202,6 +3212,9 @@ void blk_mq_free_tag_set(struct blk_mq_tag_set *set) + for (i = 0; i < nr_hw_queues(set); i++) + blk_mq_free_map_and_requests(set, i); + ++ if (blk_mq_is_sbitmap_shared(set->flags)) ++ blk_mq_exit_shared_sbitmap(set); ++ + for (j = 0; j < set->nr_maps; j++) { + kfree(set->map[j].mq_map); + set->map[j].mq_map = NULL; +@@ -3235,6 +3248,8 @@ int blk_mq_update_nr_requests(struct request_queue *q, unsigned int nr) + if (!hctx->sched_tags) { + ret = blk_mq_tag_update_depth(hctx, &hctx->tags, nr, + false); ++ if (!ret && blk_mq_is_sbitmap_shared(set->flags)) ++ blk_mq_tag_resize_shared_sbitmap(set, nr); + } else { + ret = blk_mq_tag_update_depth(hctx, &hctx->sched_tags, + nr, true); +diff --git a/block/blk-mq.h b/block/blk-mq.h +index 9f26211c3060..1196eb42f27c 100644 +--- a/block/blk-mq.h ++++ b/block/blk-mq.h +@@ -183,6 +183,11 @@ struct blk_mq_alloc_data { + #endif + }; + ++static inline bool blk_mq_is_sbitmap_shared(unsigned int flags) ++{ ++ return flags & BLK_MQ_F_TAG_HCTX_SHARED; ++} ++ + static inline struct blk_mq_tags *blk_mq_tags_from_data(struct blk_mq_alloc_data *data) + { + if (data->flags & BLK_MQ_REQ_INTERNAL) +diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h +index 9eb44330d4b3..e1daabd15659 100644 +--- a/include/linux/blk-mq.h ++++ b/include/linux/blk-mq.h +@@ -106,6 +106,12 @@ enum hctx_type { + HCTX_MAX_TYPES, + }; + ++/** ++ * struct blk_mq_tag_set - tag set that can be shared between request queues ++ * @__bitmap_tags: A shared tags sbitmap, used over all hctx's ++ * @__breserved_tags: ++ * A shared reserved tags sbitmap, used over all hctx's ++ */ + struct blk_mq_tag_set { + #ifdef __GENKSYMS__ + unsigned int *mq_map; +@@ -122,6 +128,8 @@ struct blk_mq_tag_set { + unsigned int flags; /* BLK_MQ_F_* */ + void *driver_data; + ++ struct sbitmap_queue __bitmap_tags; ++ struct sbitmap_queue __breserved_tags; + struct blk_mq_tags **tags; + + struct mutex tag_list_lock; +@@ -247,6 +255,7 @@ enum { + BLK_MQ_F_SHOULD_MERGE = 1 << 0, + BLK_MQ_F_TAG_QUEUE_SHARED = 1 << 1, + BLK_MQ_F_SG_MERGE = 1 << 2, ++ BLK_MQ_F_TAG_HCTX_SHARED = 1 << 3, + BLK_MQ_F_BLOCKING = 1 << 5, + BLK_MQ_F_NO_SCHED = 1 << 6, + BLK_MQ_F_ALLOC_POLICY_START_BIT = 8, +-- +2.27.0 + diff --git a/patches/0404-fix-kabi-broken-due-to-change-of-struct-blk_mq_tag_s.patch b/patches/0404-fix-kabi-broken-due-to-change-of-struct-blk_mq_tag_s.patch new file mode 100644 index 00000000..5a204e7d --- /dev/null +++ b/patches/0404-fix-kabi-broken-due-to-change-of-struct-blk_mq_tag_s.patch @@ -0,0 +1,51 @@ +From aab5346ed031f55b56350fd854a5e6f71c1dac3c Mon Sep 17 00:00:00 2001 +From: YunYi Yang +Date: Fri, 25 Aug 2023 15:48:05 +0800 +Subject: [PATCH 086/256] fix kabi broken due to change of struct + blk_mq_tag_set + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +---------------------------------------------------------------------------- + +Commit ("blk-mq: Facilitate a shared sbitmap per tagset") +changes the struct blk_mq_tag_set, so we need to fix kabi broken problem. + +Signed-off-by: YunYi Yang +--- + include/linux/blk-mq.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h +index e1daabd15659..847d2c725348 100644 +--- a/include/linux/blk-mq.h ++++ b/include/linux/blk-mq.h +@@ -128,8 +128,6 @@ struct blk_mq_tag_set { + unsigned int flags; /* BLK_MQ_F_* */ + void *driver_data; + +- struct sbitmap_queue __bitmap_tags; +- struct sbitmap_queue __breserved_tags; + struct blk_mq_tags **tags; + + struct mutex tag_list_lock; +@@ -137,11 +135,13 @@ struct blk_mq_tag_set { + + #ifndef __GENKSYMS__ + unsigned int nr_maps; /* nr entries in map[] */ ++ struct sbitmap_queue __bitmap_tags; ++ struct sbitmap_queue __breserved_tags; + #else + KABI_RESERVE(1) +-#endif + KABI_RESERVE(2) + KABI_RESERVE(3) ++#endif + KABI_RESERVE(4) + KABI_RESERVE(5) + KABI_RESERVE(6) +-- +2.27.0 + diff --git a/patches/0405-blk-mq-Relocate-hctx_may_queue.patch b/patches/0405-blk-mq-Relocate-hctx_may_queue.patch new file mode 100644 index 00000000..10eab6b4 --- /dev/null +++ b/patches/0405-blk-mq-Relocate-hctx_may_queue.patch @@ -0,0 +1,133 @@ +From 796836afb278436ff6efe4e3906b27b7b24b0b4f Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Wed, 19 Aug 2020 23:20:25 +0800 +Subject: [PATCH 087/256] blk-mq: Relocate hctx_may_queue() + +mainline inclusion +from mainline-v5.10-rc1 +commit a0235d230f3245aa4bd70b514d5effb24be61acd +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a0235d230f3245aa4bd70b514d5effb24be61acd + +---------------------------------------------------------------------- + +blk-mq.h and blk-mq-tag.h include on each other, which is less than ideal. + +Locate hctx_may_queue() to blk-mq.h, as it is not really tag specific code. + +In this way, we can drop the blk-mq-tag.h include of blk-mq.h + +Signed-off-by: John Garry +Tested-by: Douglas Gilbert +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang + + Conflicts: + block/blk-mq-tag.h +--- + block/blk-mq-tag.c | 31 ------------------------------- + block/blk-mq-tag.h | 2 -- + block/blk-mq.h | 32 ++++++++++++++++++++++++++++++++ + 3 files changed, 32 insertions(+), 33 deletions(-) + +diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c +index e8bd8e8ccab4..09dceca5142d 100644 +--- a/block/blk-mq-tag.c ++++ b/block/blk-mq-tag.c +@@ -63,37 +63,6 @@ void __blk_mq_tag_idle(struct blk_mq_hw_ctx *hctx) + blk_mq_tag_wakeup_all(tags, false); + } + +-/* +- * For shared tag users, we track the number of currently active users +- * and attempt to provide a fair share of the tag depth for each of them. +- */ +-static inline bool hctx_may_queue(struct blk_mq_hw_ctx *hctx, +- struct sbitmap_queue *bt) +-{ +- unsigned int depth, users; +- +- if (!hctx || !(hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED)) +- return true; +- if (!test_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state)) +- return true; +- +- /* +- * Don't try dividing an ant +- */ +- if (bt->sb.depth == 1) +- return true; +- +- users = atomic_read(&hctx->tags->active_queues); +- if (!users) +- return true; +- +- /* +- * Allow at least some tags +- */ +- depth = max((bt->sb.depth + users - 1) / users, 4U); +- return atomic_read(&hctx->nr_active) < depth; +-} +- + static int __blk_mq_get_tag(struct blk_mq_alloc_data *data, + struct sbitmap_queue *bt) + { +diff --git a/block/blk-mq-tag.h b/block/blk-mq-tag.h +index b2851213e859..f19fb28fd2bc 100644 +--- a/block/blk-mq-tag.h ++++ b/block/blk-mq-tag.h +@@ -2,8 +2,6 @@ + #ifndef INT_BLK_MQ_TAG_H + #define INT_BLK_MQ_TAG_H + +-#include "blk-mq.h" +- + /* + * Tag address space map. + */ +diff --git a/block/blk-mq.h b/block/blk-mq.h +index 1196eb42f27c..734af4425954 100644 +--- a/block/blk-mq.h ++++ b/block/blk-mq.h +@@ -275,4 +275,36 @@ static inline void blk_mq_free_requests(struct list_head *list) + } + } + ++/* ++ * For shared tag users, we track the number of currently active users ++ * and attempt to provide a fair share of the tag depth for each of them. ++ */ ++static inline bool hctx_may_queue(struct blk_mq_hw_ctx *hctx, ++ struct sbitmap_queue *bt) ++{ ++ unsigned int depth, users; ++ ++ if (!hctx || !(hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED)) ++ return true; ++ if (!test_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state)) ++ return true; ++ ++ /* ++ * Don't try dividing an ant ++ */ ++ if (bt->sb.depth == 1) ++ return true; ++ ++ users = atomic_read(&hctx->tags->active_queues); ++ if (!users) ++ return true; ++ ++ /* ++ * Allow at least some tags ++ */ ++ depth = max((bt->sb.depth + users - 1) / users, 4U); ++ return atomic_read(&hctx->nr_active) < depth; ++} ++ ++ + #endif +-- +2.27.0 + diff --git a/patches/0406-blk-mq-Record-nr_active_requests-per-queue-for-when-.patch b/patches/0406-blk-mq-Record-nr_active_requests-per-queue-for-when-.patch new file mode 100644 index 00000000..7eb9bf3d --- /dev/null +++ b/patches/0406-blk-mq-Record-nr_active_requests-per-queue-for-when-.patch @@ -0,0 +1,140 @@ +From 6cdad8a6dcf3e6b03ce0090da5a30089ba39ff2a Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Wed, 19 Aug 2020 23:20:26 +0800 +Subject: [PATCH 088/256] blk-mq: Record nr_active_requests per queue for when + using shared sbitmap + +mainline inclusion +from mainline-v5.10-rc1 +commit bccf5e26d99c28980bd6ced474422a1b18402263 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bccf5e26d99c28980bd6ced474422a1b18402263 + +---------------------------------------------------------------------- + +The per-hctx nr_active value can no longer be used to fairly assign a share +of tag depth per request queue for when using a shared sbitmap, as it does +not consider that the tags are shared tags over all hctx's. + +For this case, record the nr_active_requests per request_queue, and make +the judgement based on that value. + +Co-developed-with: Kashyap Desai +Signed-off-by: John Garry +Tested-by: Don Brace #SCSI resv cmds patches used +Tested-by: Douglas Gilbert +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang + + Conflicts: + block/blk-mq.c +--- + block/blk-core.c | 2 ++ + block/blk-mq.c | 3 ++- + block/blk-mq.h | 26 ++++++++++++++++++++++++-- + include/linux/blkdev.h | 2 ++ + 4 files changed, 30 insertions(+), 3 deletions(-) + +diff --git a/block/blk-core.c b/block/blk-core.c +index fe3553382b0e..4192bcf5b0f3 100644 +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -1322,6 +1322,8 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id, + q->backing_dev_info->name = "block"; + q->node = node_id; + ++ atomic_set(&q->nr_active_requests_shared_sbitmap, 0); ++ + timer_setup(&q->backing_dev_info->laptop_mode_wb_timer, + laptop_mode_timer_fn, 0); + timer_setup(&q->timeout, blk_rq_timed_out_timer, 0); +diff --git a/block/blk-mq.c b/block/blk-mq.c +index 38503e19ae84..a61ff58b108a 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -568,7 +568,7 @@ void blk_mq_free_request(struct request *rq) + + ctx->rq_completed[rq_is_sync(rq)]++; + if (rq->rq_flags & RQF_MQ_INFLIGHT) +- atomic_dec(&hctx->nr_active); ++ __blk_mq_dec_active_requests(hctx); + + if (unlikely(laptop_mode && !blk_rq_is_passthrough(rq))) + laptop_io_completion(q->backing_dev_info); +@@ -1080,6 +1080,7 @@ bool blk_mq_get_driver_tag(struct request *rq) + if (shared) { + rq->rq_flags |= RQF_MQ_INFLIGHT; + atomic_inc(&data.hctx->nr_active); ++ __blk_mq_inc_active_requests(data.hctx); + } + data.hctx->tags->rqs[rq->tag] = rq; + } +diff --git a/block/blk-mq.h b/block/blk-mq.h +index 734af4425954..1bd704349865 100644 +--- a/block/blk-mq.h ++++ b/block/blk-mq.h +@@ -228,6 +228,28 @@ static inline bool blk_mq_get_dispatch_budget(struct blk_mq_hw_ctx *hctx) + return true; + } + ++static inline void __blk_mq_inc_active_requests(struct blk_mq_hw_ctx *hctx) ++{ ++ if (blk_mq_is_sbitmap_shared(hctx->flags)) ++ atomic_inc(&hctx->queue->nr_active_requests_shared_sbitmap); ++ else ++ atomic_inc(&hctx->nr_active); ++} ++ ++static inline void __blk_mq_dec_active_requests(struct blk_mq_hw_ctx *hctx) ++{ ++ if (blk_mq_is_sbitmap_shared(hctx->flags)) ++ atomic_dec(&hctx->queue->nr_active_requests_shared_sbitmap); ++ else ++ atomic_dec(&hctx->nr_active); ++} ++ ++static inline int __blk_mq_active_requests(struct blk_mq_hw_ctx *hctx) ++{ ++ if (blk_mq_is_sbitmap_shared(hctx->flags)) ++ return atomic_read(&hctx->queue->nr_active_requests_shared_sbitmap); ++ return atomic_read(&hctx->nr_active); ++} + static inline void __blk_mq_put_driver_tag(struct blk_mq_hw_ctx *hctx, + struct request *rq) + { +@@ -236,7 +258,7 @@ static inline void __blk_mq_put_driver_tag(struct blk_mq_hw_ctx *hctx, + + if (rq->rq_flags & RQF_MQ_INFLIGHT) { + rq->rq_flags &= ~RQF_MQ_INFLIGHT; +- atomic_dec(&hctx->nr_active); ++ __blk_mq_dec_active_requests(hctx); + } + } + +@@ -303,7 +325,7 @@ static inline bool hctx_may_queue(struct blk_mq_hw_ctx *hctx, + * Allow at least some tags + */ + depth = max((bt->sb.depth + users - 1) / users, 4U); +- return atomic_read(&hctx->nr_active) < depth; ++ return __blk_mq_active_requests(hctx) < depth; + } + + +diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h +index 7d76f401e1a9..af2e2d49d00c 100644 +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -608,6 +608,8 @@ struct request_queue { + struct work_struct timeout_work; + struct list_head timeout_list; + ++ atomic_t nr_active_requests_shared_sbitmap; ++ + struct list_head icq_list; + #ifdef CONFIG_BLK_CGROUP + DECLARE_BITMAP (blkcg_pols, BLKCG_MAX_POLS); +-- +2.27.0 + diff --git a/patches/0407-fix-kabi-broken-due-to-change-of-struct-request_queu.patch b/patches/0407-fix-kabi-broken-due-to-change-of-struct-request_queu.patch new file mode 100644 index 00000000..0fe5a453 --- /dev/null +++ b/patches/0407-fix-kabi-broken-due-to-change-of-struct-request_queu.patch @@ -0,0 +1,46 @@ +From ad6a39e691a7eed85d38acc33053cb184b5efca3 Mon Sep 17 00:00:00 2001 +From: YunYi Yang +Date: Fri, 25 Aug 2023 16:54:27 +0800 +Subject: [PATCH 089/256] fix kabi broken due to change of struct request_queue + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +---------------------------------------------------------------------------- + +Commit ("blk-mq: Record nr_active_requests per queue +for when using shared sbitmap") changes the struct request_queue, +so we need to fix kabi broken problem. + +Signed-off-by: YunYi Yang +--- + include/linux/blkdev.h | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h +index af2e2d49d00c..b4216c70193d 100644 +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -608,8 +608,6 @@ struct request_queue { + struct work_struct timeout_work; + struct list_head timeout_list; + +- atomic_t nr_active_requests_shared_sbitmap; +- + struct list_head icq_list; + #ifdef CONFIG_BLK_CGROUP + DECLARE_BITMAP (blkcg_pols, BLKCG_MAX_POLS); +@@ -710,6 +708,9 @@ struct request_queue { + + #define BLK_MAX_WRITE_HINTS 5 + u64 write_hints[BLK_MAX_WRITE_HINTS]; ++#ifndef __GENKSYMS__ ++ atomic_t nr_active_requests_shared_sbitmap; ++#endif + }; + + #define QUEUE_FLAG_QUEUED 0 /* uses generic tag queueing */ +-- +2.27.0 + diff --git a/patches/0408-blk-mq-Record-active_queues_shared_sbitmap-per-tag_s.patch b/patches/0408-blk-mq-Record-active_queues_shared_sbitmap-per-tag_s.patch new file mode 100644 index 00000000..cd05d197 --- /dev/null +++ b/patches/0408-blk-mq-Record-active_queues_shared_sbitmap-per-tag_s.patch @@ -0,0 +1,165 @@ +From 372770b627778576f8a3b5d390f01af21d3e9177 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Wed, 19 Aug 2020 23:20:27 +0800 +Subject: [PATCH 090/256] blk-mq: Record active_queues_shared_sbitmap per + tag_set for when using shared sbitmap + +mainline inclusion +from mainline-v5.10-rc1 +commit f1b49fdc1c64db110aa1315831e5fe0f8599fa56 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f1b49fdc1c64db110aa1315831e5fe0f8599fa56 + +---------------------------------------------------------------------- + +For when using a shared sbitmap, no longer should the number of active +request queues per hctx be relied on for when judging how to share the tag +bitmap. + +Instead maintain the number of active request queues per tag_set, and make +the judgement based on that. + +Originally-from: Kashyap Desai +Signed-off-by: John Garry +Tested-by: Don Brace #SCSI resv cmds patches used +Tested-by: Douglas Gilbert +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang + + Conflicts: + include/linux/blkdev.h +--- + block/blk-mq-tag.c | 33 +++++++++++++++++++++++++-------- + block/blk-mq.c | 2 ++ + block/blk-mq.h | 16 +++++++++++++--- + include/linux/blk-mq.h | 1 + + include/linux/blkdev.h | 1 + + 5 files changed, 42 insertions(+), 11 deletions(-) + +diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c +index 09dceca5142d..3a714775b588 100644 +--- a/block/blk-mq-tag.c ++++ b/block/blk-mq-tag.c +@@ -30,9 +30,18 @@ bool blk_mq_has_free_tags(struct blk_mq_tags *tags) + */ + bool __blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx) + { +- if (!test_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state) && +- !test_and_set_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state)) +- atomic_inc(&hctx->tags->active_queues); ++ if (blk_mq_is_sbitmap_shared(hctx->flags)) { ++ struct request_queue *q = hctx->queue; ++ struct blk_mq_tag_set *set = q->tag_set; ++ ++ if (!test_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags) && ++ !test_and_set_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags)) ++ atomic_inc(&set->active_queues_shared_sbitmap); ++ } else { ++ if (!test_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state) && ++ !test_and_set_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state)) ++ atomic_inc(&hctx->tags->active_queues); ++ } + + return true; + } +@@ -54,11 +63,19 @@ void blk_mq_tag_wakeup_all(struct blk_mq_tags *tags, bool include_reserve) + void __blk_mq_tag_idle(struct blk_mq_hw_ctx *hctx) + { + struct blk_mq_tags *tags = hctx->tags; +- +- if (!test_and_clear_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state)) +- return; +- +- atomic_dec(&tags->active_queues); ++ struct request_queue *q = hctx->queue; ++ struct blk_mq_tag_set *set = q->tag_set; ++ ++ if (blk_mq_is_sbitmap_shared(hctx->flags)) { ++ if (!test_and_clear_bit(QUEUE_FLAG_HCTX_ACTIVE, ++ &q->queue_flags)) ++ return; ++ atomic_dec(&set->active_queues_shared_sbitmap); ++ } else { ++ if (!test_and_clear_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state)) ++ return; ++ atomic_dec(&tags->active_queues); ++ } + + blk_mq_tag_wakeup_all(tags, false); + } +diff --git a/block/blk-mq.c b/block/blk-mq.c +index a61ff58b108a..bec2190a64dd 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -3181,6 +3181,8 @@ int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set) + goto out_free_mq_map; + + if (blk_mq_is_sbitmap_shared(set->flags)) { ++ atomic_set(&set->active_queues_shared_sbitmap, 0); ++ + if (blk_mq_init_shared_sbitmap(set, set->flags)) { + ret = -ENOMEM; + goto out_free_mq_rq_maps; +diff --git a/block/blk-mq.h b/block/blk-mq.h +index 1bd704349865..7d21b7ecf178 100644 +--- a/block/blk-mq.h ++++ b/block/blk-mq.h +@@ -308,8 +308,6 @@ static inline bool hctx_may_queue(struct blk_mq_hw_ctx *hctx, + + if (!hctx || !(hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED)) + return true; +- if (!test_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state)) +- return true; + + /* + * Don't try dividing an ant +@@ -317,7 +315,19 @@ static inline bool hctx_may_queue(struct blk_mq_hw_ctx *hctx, + if (bt->sb.depth == 1) + return true; + +- users = atomic_read(&hctx->tags->active_queues); ++ if (blk_mq_is_sbitmap_shared(hctx->flags)) { ++ struct request_queue *q = hctx->queue; ++ struct blk_mq_tag_set *set = q->tag_set; ++ ++ if (!test_bit(BLK_MQ_S_TAG_ACTIVE, &q->queue_flags)) ++ return true; ++ users = atomic_read(&set->active_queues_shared_sbitmap); ++ } else { ++ if (!test_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state)) ++ return true; ++ users = atomic_read(&hctx->tags->active_queues); ++ } ++ + if (!users) + return true; + +diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h +index 847d2c725348..4033a1c7795e 100644 +--- a/include/linux/blk-mq.h ++++ b/include/linux/blk-mq.h +@@ -127,6 +127,7 @@ struct blk_mq_tag_set { + unsigned int timeout; + unsigned int flags; /* BLK_MQ_F_* */ + void *driver_data; ++ atomic_t active_queues_shared_sbitmap; + + struct blk_mq_tags **tags; + +diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h +index b4216c70193d..d0c11bba64ce 100644 +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -749,6 +749,7 @@ struct request_queue { + #define QUEUE_FLAG_QUIESCED_INTERNAL 30 + /* bio will be dispatched asynchronous */ + #define QUEUE_FLAG_DISPATCH_ASYNC 31 ++#define QUEUE_FLAG_HCTX_ACTIVE 32 /* at least one blk-mq hctx is active */ + + #define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ + (1 << QUEUE_FLAG_SAME_COMP) | \ +-- +2.27.0 + diff --git a/patches/0409-fix-kabi-broken-due-to-change-of-struct-blk_mq_tag_s.patch b/patches/0409-fix-kabi-broken-due-to-change-of-struct-blk_mq_tag_s.patch new file mode 100644 index 00000000..1a8621ff --- /dev/null +++ b/patches/0409-fix-kabi-broken-due-to-change-of-struct-blk_mq_tag_s.patch @@ -0,0 +1,51 @@ +From a985ec0957e87bc142cc32395abbbf905cae8b11 Mon Sep 17 00:00:00 2001 +From: YunYi Yang +Date: Fri, 25 Aug 2023 17:04:26 +0800 +Subject: [PATCH 091/256] fix kabi broken due to change of struct + blk_mq_tag_set + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +---------------------------------------------------------------------------- + +Commit ("blk-mq: Record active_queues_shared_sbitmap +per tag_set for when using shared sbitmap") changes the struct +blk_mq_tag_set, so we need to fix kabi broken problem. + +Signed-off-by: YunYi Yang +--- + include/linux/blk-mq.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h +index 4033a1c7795e..e5b1debe272b 100644 +--- a/include/linux/blk-mq.h ++++ b/include/linux/blk-mq.h +@@ -127,7 +127,6 @@ struct blk_mq_tag_set { + unsigned int timeout; + unsigned int flags; /* BLK_MQ_F_* */ + void *driver_data; +- atomic_t active_queues_shared_sbitmap; + + struct blk_mq_tags **tags; + +@@ -138,12 +137,13 @@ struct blk_mq_tag_set { + unsigned int nr_maps; /* nr entries in map[] */ + struct sbitmap_queue __bitmap_tags; + struct sbitmap_queue __breserved_tags; ++ atomic_t active_queues_shared_sbitmap; + #else + KABI_RESERVE(1) + KABI_RESERVE(2) + KABI_RESERVE(3) +-#endif + KABI_RESERVE(4) ++#endif + KABI_RESERVE(5) + KABI_RESERVE(6) + KABI_RESERVE(7) +-- +2.27.0 + diff --git a/patches/0410-scsi-Add-host-and-host-template-flag-host_tagset.patch b/patches/0410-scsi-Add-host-and-host-template-flag-host_tagset.patch new file mode 100644 index 00000000..db881d18 --- /dev/null +++ b/patches/0410-scsi-Add-host-and-host-template-flag-host_tagset.patch @@ -0,0 +1,100 @@ +From 301ee7c61f265f3a23028f3bb086d9646499ead9 Mon Sep 17 00:00:00 2001 +From: Hannes Reinecke +Date: Wed, 19 Aug 2020 23:20:30 +0800 +Subject: [PATCH 092/256] scsi: Add host and host template flag 'host_tagset' + +mainline inclusion +from mainline-v5.10-rc1 +commit bdb01301f3ea51a59eff252b06643fc1fe843e57 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bdb01301f3ea51a59eff252b06643fc1fe843e57 + +---------------------------------------------------------------------- + +Add Host and host template flag 'host_tagset' so hostwide tagset can be +shared on multiple reply queues after the SCSI device's reply queue is +converted to blk-mq hw queue. + +[jpg: Update comment on .can_queue and add Scsi_Host.host_tagset] + +Signed-off-by: Hannes Reinecke +Signed-off-by: John Garry +Tested-by: Don Brace #SCSI resv cmds patches used +Tested-by: Douglas Gilbert +Acked-by: Martin K. Petersen +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/scsi_lib.c + include/scsi/scsi_host.h +--- + drivers/scsi/hosts.c | 1 + + drivers/scsi/scsi_lib.c | 2 ++ + include/scsi/scsi_host.h | 9 ++++++++- + 3 files changed, 11 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c +index 5299fa75215a..54eeaed92b60 100644 +--- a/drivers/scsi/hosts.c ++++ b/drivers/scsi/hosts.c +@@ -436,6 +436,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) + shost->unchecked_isa_dma = sht->unchecked_isa_dma; + shost->use_clustering = sht->use_clustering; + shost->no_write_same = sht->no_write_same; ++ shost->host_tagset = sht->host_tagset; + + if (shost_eh_deadline == -1 || !sht->eh_host_reset_handler) + shost->eh_deadline = -1; +diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c +index f3ccf06fb049..4575ce343dbb 100644 +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -2464,6 +2464,8 @@ int scsi_mq_setup_tags(struct Scsi_Host *shost) + shost->tag_set.flags |= + BLK_ALLOC_POLICY_TO_MQ_FLAG(shost->hostt->tag_alloc_policy); + shost->tag_set.driver_data = shost; ++ if (shost->host_tagset) ++ shost->tag_set.flags |= BLK_MQ_F_TAG_HCTX_SHARED; + + return blk_mq_alloc_tag_set(&shost->tag_set); + } +diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h +index 6382e92d1e27..c9efb9729f6f 100644 +--- a/include/scsi/scsi_host.h ++++ b/include/scsi/scsi_host.h +@@ -443,6 +443,9 @@ struct scsi_host_template { + /* True if the low-level driver supports blk-mq only */ + unsigned force_blk_mq:1; + ++ /* True if the host uses host-wide tagspace */ ++ unsigned host_tagset:1; ++ + /* + * Countdown for host blocking with no commands outstanding. + */ +@@ -618,7 +621,8 @@ struct Scsi_Host { + * + * Note: it is assumed that each hardware queue has a queue depth of + * can_queue. In other words, the total queue depth per host +- * is nr_hw_queues * can_queue. ++ * is nr_hw_queues * can_queue. However, for when host_tagset is set, ++ * the total queue depth is can_queue. + */ + unsigned nr_hw_queues; + /* +@@ -659,6 +663,9 @@ struct Scsi_Host { + unsigned use_blk_mq:1; + unsigned use_cmd_list:1; + ++ /* True if the host uses host-wide tagspace */ ++ unsigned host_tagset:1; ++ + /* Host responded with short (<36 bytes) INQUIRY result */ + unsigned short_inquiry:1; + +-- +2.27.0 + diff --git a/patches/0411-fix-kabi-broken-due-to-change-of-struct-scsi_host_te.patch b/patches/0411-fix-kabi-broken-due-to-change-of-struct-scsi_host_te.patch new file mode 100644 index 00000000..1167c284 --- /dev/null +++ b/patches/0411-fix-kabi-broken-due-to-change-of-struct-scsi_host_te.patch @@ -0,0 +1,84 @@ +From d389bbd1c92f5dd316ec0847c7f914b12ece0d0e Mon Sep 17 00:00:00 2001 +From: YunYi Yang +Date: Fri, 25 Aug 2023 17:22:22 +0800 +Subject: [PATCH 093/256] fix kabi broken due to change of struct + scsi_host_template and Scsi_Host + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +---------------------------------------------------------------------------- + +Commit ("scsi: Add host and host template flag 'host_tagset'") +changes the struct struct scsi_host_template and Scsi_Host, so we need to +fix kabi broken problem. + +Signed-off-by: YunYi Yang + + Conflicts: + include/scsi/scsi_host.h +--- + include/scsi/scsi_host.h | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h +index c9efb9729f6f..845619f71448 100644 +--- a/include/scsi/scsi_host.h ++++ b/include/scsi/scsi_host.h +@@ -443,9 +443,6 @@ struct scsi_host_template { + /* True if the low-level driver supports blk-mq only */ + unsigned force_blk_mq:1; + +- /* True if the host uses host-wide tagspace */ +- unsigned host_tagset:1; +- + /* + * Countdown for host blocking with no commands outstanding. + */ +@@ -491,7 +488,12 @@ struct scsi_host_template { + unsigned int cmd_size; + struct scsi_host_cmd_pool *cmd_pool; + ++#ifndef __GENKSYMS__ ++ /* True if the host uses host-wide tagspace */ ++ unsigned host_tagset:1; ++#else + KABI_RESERVE(1) ++#endif + KABI_RESERVE(2) + KABI_RESERVE(3) + KABI_RESERVE(4) +@@ -663,9 +665,6 @@ struct Scsi_Host { + unsigned use_blk_mq:1; + unsigned use_cmd_list:1; + +- /* True if the host uses host-wide tagspace */ +- unsigned host_tagset:1; +- + /* Host responded with short (<36 bytes) INQUIRY result */ + unsigned short_inquiry:1; + +@@ -717,16 +716,17 @@ struct Scsi_Host { + */ + struct device *dma_dev; + +- + #ifndef __GENKSYMS__ + union { + bool is_builtin; + KABI_RESERVE(1) + }; ++ /* True if the host uses host-wide tagspace */ ++ unsigned host_tagset:1; + #else + KABI_RESERVE(1) +-#endif + KABI_RESERVE(2) ++#endif + KABI_RESERVE(3) + KABI_RESERVE(4) + KABI_RESERVE(5) +-- +2.27.0 + diff --git a/patches/0412-scsi-core-Show-nr_hw_queues-in-sysfs.patch b/patches/0412-scsi-core-Show-nr_hw_queues-in-sysfs.patch new file mode 100644 index 00000000..cb9358dd --- /dev/null +++ b/patches/0412-scsi-core-Show-nr_hw_queues-in-sysfs.patch @@ -0,0 +1,62 @@ +From 3f3c4a2d57f32678b57467937ee0d6270961e95f Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Wed, 19 Aug 2020 23:20:31 +0800 +Subject: [PATCH 094/256] scsi: core: Show nr_hw_queues in sysfs + +mainline inclusion +from mainline-v5.10-rc1 +commit 64f1501bd2a9c8ab1df548e1ed224552f9c7ac71 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=64f1501bd2a9c8ab1df548e1ed224552f9c7ac71 + +---------------------------------------------------------------------- + +So that we don't use a value of 0 for when Scsi_Host.nr_hw_queues is unset, +use the tag_set->nr_hw_queues (which holds 1 for this case). + +Signed-off-by: John Garry +Tested-by: Douglas Gilbert +Acked-by: Martin K. Petersen +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/scsi_sysfs.c +--- + drivers/scsi/scsi_sysfs.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c +index 18299693e4ff..6118db6a7c1d 100644 +--- a/drivers/scsi/scsi_sysfs.c ++++ b/drivers/scsi/scsi_sysfs.c +@@ -386,6 +386,16 @@ show_host_busy(struct device *dev, struct device_attribute *attr, char *buf) + } + static DEVICE_ATTR(host_busy, S_IRUGO, show_host_busy, NULL); + ++static ssize_t ++nr_hw_queues_show(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct Scsi_Host *shost = class_to_shost(dev); ++ struct blk_mq_tag_set *tag_set = &shost->tag_set; ++ ++ return snprintf(buf, 20, "%d\n", tag_set->nr_hw_queues); ++} ++static DEVICE_ATTR(nr_hw_queues, 0444, nr_hw_queues_show, NULL); ++ + static struct attribute *scsi_sysfs_shost_attrs[] = { + &dev_attr_use_blk_mq.attr, + &dev_attr_unique_id.attr, +@@ -404,6 +414,7 @@ static struct attribute *scsi_sysfs_shost_attrs[] = { + &dev_attr_prot_guard_type.attr, + &dev_attr_host_reset.attr, + &dev_attr_eh_deadline.attr, ++ &dev_attr_nr_hw_queues.attr, + NULL + }; + +-- +2.27.0 + diff --git a/patches/0413-scsi-hisi_sas-Switch-v3-hw-to-MQ.patch b/patches/0413-scsi-hisi_sas-Switch-v3-hw-to-MQ.patch new file mode 100644 index 00000000..f042ac65 --- /dev/null +++ b/patches/0413-scsi-hisi_sas-Switch-v3-hw-to-MQ.patch @@ -0,0 +1,258 @@ +From 2657c5842c0b0de1e7ea09934d997cbf797119c6 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Wed, 19 Aug 2020 23:20:32 +0800 +Subject: [PATCH 095/256] scsi: hisi_sas: Switch v3 hw to MQ + +mainline inclusion +from mainline-v5.10-rc1 +commit 8d98416a55ebfecbe57fd26981decf6fcdf37b11 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8d98416a55ebfecbe57fd26981decf6fcdf37b11 + +---------------------------------------------------------------------- + +Now that the block layer provides a shared tag, we can switch the driver +to expose all HW queues. + +Signed-off-by: John Garry +Tested-by: Douglas Gilbert +Acked-by: Martin K. Petersen +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas.h + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 3 +- + drivers/scsi/hisi_sas/hisi_sas_main.c | 36 ++++++----- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 88 ++++++++++---------------- + 3 files changed, 56 insertions(+), 71 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index f6dbb9dd3ea3..35c1247caa15 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -13,6 +13,8 @@ + #define _HISI_SAS_H_ + + #include ++#include ++#include + #include + #include + #include +@@ -481,7 +483,6 @@ struct hisi_hba { + int bist_loopback_enable; + + int enable_dix_dif; +- unsigned int *reply_map; + + /* debugfs memories */ + /* Put Global AXI and RAS Register into register array */ +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 037ab14e40ce..3f49d60d01f3 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -437,6 +437,7 @@ static int hisi_sas_task_prep(struct sas_task *task, + struct device *dev = hisi_hba->dev; + int dlvry_queue_slot, dlvry_queue, rc, slot_idx; + int n_elem = 0, n_elem_dif = 0, n_elem_req = 0; ++ struct scsi_cmnd *scmd = NULL; + struct hisi_sas_dq *dq; + unsigned long flags; + int wr_q_index; +@@ -453,10 +454,23 @@ static int hisi_sas_task_prep(struct sas_task *task, + return -ECOMM; + } + +- if (hisi_hba->reply_map) { +- int cpu = raw_smp_processor_id(); +- unsigned int dq_index = hisi_hba->reply_map[cpu]; ++ if (task->uldd_task) { ++ struct ata_queued_cmd *qc; + ++ if (dev_is_sata(device)) { ++ qc = task->uldd_task; ++ scmd = qc->scsicmd; ++ } else { ++ scmd = task->uldd_task; ++ } ++ } ++ ++ if (scmd) { ++ unsigned int dq_index; ++ u32 blk_tag; ++ ++ blk_tag = blk_mq_unique_tag(scmd->request); ++ dq_index = blk_mq_unique_tag_to_hwq(blk_tag); + *dq_pointer = dq = &hisi_hba->dq[dq_index]; + } else { + *dq_pointer = dq = sas_dev->dq; +@@ -483,21 +497,9 @@ static int hisi_sas_task_prep(struct sas_task *task, + + if (hisi_hba->hw->slot_index_alloc) + rc = hisi_hba->hw->slot_index_alloc(hisi_hba, device); +- else { +- struct scsi_cmnd *scsi_cmnd = NULL; +- +- if (task->uldd_task) { +- struct ata_queued_cmd *qc; ++ else ++ rc = hisi_sas_slot_index_alloc(hisi_hba, scmd); + +- if (dev_is_sata(device)) { +- qc = task->uldd_task; +- scsi_cmnd = qc->scsicmd; +- } else { +- scsi_cmnd = task->uldd_task; +- } +- } +- rc = hisi_sas_slot_index_alloc(hisi_hba, scsi_cmnd); +- } + if (rc < 0) + goto err_out_dif_dma_unmap; + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 7719c13df112..1f5bd0b98d28 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -2686,70 +2686,37 @@ static irqreturn_t cq_interrupt_v3_hw(int irq_no, void *p) + return IRQ_HANDLED; + } + +-static void setup_reply_map_v3_hw(struct hisi_hba *hisi_hba, int nvecs) ++static int interrupt_preinit_v3_hw(struct hisi_hba *hisi_hba) + { +- const struct cpumask *mask; +- int queue, cpu; +- +- for (queue = 0; queue < nvecs; queue++) { +- struct hisi_sas_cq *cq = &hisi_hba->cq[queue]; ++ int vectors; ++ int max_msi = HISI_SAS_MSI_COUNT_V3_HW, min_msi; ++ struct Scsi_Host *shost = hisi_hba->shost; ++ struct irq_affinity desc = { ++ .pre_vectors = HISI_SAS_CQ_INT_BASE_VECTORS_V3_HW, ++ }; ++ ++ min_msi = HISI_SAS_MIN_VECTORS_V3_HW; ++ vectors = pci_alloc_irq_vectors_affinity(hisi_hba->pci_dev, ++ min_msi, max_msi, ++ PCI_IRQ_MSI | ++ PCI_IRQ_AFFINITY, ++ &desc); ++ if (vectors < 0) ++ return -ENOENT; + +- mask = pci_irq_get_affinity(hisi_hba->pci_dev, queue + +- HISI_SAS_CQ_INT_BASE_VECTORS_V3_HW); +- if (!mask) +- goto fallback; +- cq->irq_mask = mask; +- for_each_cpu(cpu, mask) +- hisi_hba->reply_map[cpu] = queue; +- } +- return; ++ hisi_hba->nvecs = vectors - HISI_SAS_CQ_INT_BASE_VECTORS_V3_HW; ++ shost->nr_hw_queues = hisi_hba->nvecs; + +-fallback: +- for_each_possible_cpu(cpu) +- hisi_hba->reply_map[cpu] = cpu % hisi_hba->queue_count; +- /* Don't clean all CQ masks */ ++ return 0; + } + + static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) + { + struct device *dev = hisi_hba->dev; + struct pci_dev *pdev = hisi_hba->pci_dev; +- int vectors, rc, i; ++ int rc, i; + int max_dq_num, online_numa_num; +- int max_msi = HISI_SAS_MSI_COUNT_V3_HW, min_msi; +- +- if (auto_affine_msi_experimental) { +- struct irq_affinity desc = { +- .pre_vectors = HISI_SAS_CQ_INT_BASE_VECTORS_V3_HW, +- }; +- +- dev_info(dev, "Enable MSI auto-affinity\n"); +- +- min_msi = HISI_SAS_MIN_VECTORS_V3_HW; +- +- hisi_hba->reply_map = devm_kcalloc(dev, nr_cpu_ids, +- sizeof(unsigned int), +- GFP_KERNEL); +- if (!hisi_hba->reply_map) +- return -ENOMEM; +- vectors = pci_alloc_irq_vectors_affinity(hisi_hba->pci_dev, +- min_msi, max_msi, +- PCI_IRQ_MSI | +- PCI_IRQ_AFFINITY, +- &desc); +- if (vectors < 0) +- return -ENOENT; +- setup_reply_map_v3_hw(hisi_hba, +- vectors - HISI_SAS_CQ_INT_BASE_VECTORS_V3_HW); +- } else { +- min_msi = max_msi; +- vectors = pci_alloc_irq_vectors(hisi_hba->pci_dev, min_msi, +- max_msi, PCI_IRQ_MSI); +- if (vectors < 0) +- return vectors; +- } + +- hisi_hba->nvecs = vectors - HISI_SAS_CQ_INT_BASE_VECTORS_V3_HW; + max_dq_num = (hisi_hba->nvecs < hisi_hba->queue_count) ? + hisi_hba->nvecs : hisi_hba->queue_count; + online_numa_num = num_online_nodes(); +@@ -3463,6 +3430,15 @@ static void read_iost_itct_cache_v3_hw(struct hisi_hba *hisi_hba, + buf[i] = hisi_sas_read32(hisi_hba, TAB_DFX); + } + ++static int hisi_sas_map_queues(struct Scsi_Host *shost) ++{ ++ struct hisi_hba *hisi_hba = shost_priv(shost); ++ struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT]; ++ ++ return blk_mq_pci_map_queues_by_qmap(qmap, hisi_hba->pci_dev, ++ HISI_SAS_CQ_INT_BASE_VECTORS_V3_HW); ++} ++ + static struct scsi_host_template sht_v3_hw = { + .name = DRV_NAME, + .proc_name = DRV_NAME, +@@ -3472,6 +3448,7 @@ static struct scsi_host_template sht_v3_hw = { + .slave_configure = hisi_sas_slave_configure, + .scan_finished = hisi_sas_scan_finished, + .scan_start = hisi_sas_scan_start, ++ .map_queues = hisi_sas_map_queues, + .change_queue_depth = sas_change_queue_depth, + .bios_param = sas_bios_param, + .this_id = -1, +@@ -3487,6 +3464,7 @@ static struct scsi_host_template sht_v3_hw = { + .shost_attrs = host_attrs_v3_hw, + .host_reset = hisi_sas_host_reset, + .tag_alloc_policy = BLK_TAG_ALLOC_RR, ++ .host_tagset = 1, + }; + + static const struct hisi_sas_hw hisi_sas_v3_hw = { +@@ -3662,6 +3640,10 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) + SHOST_DIX_GUARD_CRC); + } + ++ rc = interrupt_preinit_v3_hw(hisi_hba); ++ if (rc) ++ goto err_out_ha; ++ dev_err(dev, "%d hw queues\n", shost->nr_hw_queues); + rc = scsi_add_host(shost, dev); + if (rc) + goto err_out_ha; +-- +2.27.0 + diff --git a/patches/0414-scsi-scsi_debug-Support-hostwide-tags.patch b/patches/0414-scsi-scsi_debug-Support-hostwide-tags.patch new file mode 100644 index 00000000..aefd0112 --- /dev/null +++ b/patches/0414-scsi-scsi_debug-Support-hostwide-tags.patch @@ -0,0 +1,241 @@ +From 3ac862dd393682c2de8d3fa3b539a2a6f47d84cb Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 9 Jul 2020 20:23:20 +0800 +Subject: [PATCH 096/256] scsi: scsi_debug: Support hostwide tags + +mainline inclusion +from mainline-v5.9-rc1 +commit c10fa55f5e7ad3638237dd66fcb28a7225acdff8 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c10fa55f5e7ad3638237dd66fcb28a7225acdff8 + +---------------------------------------------------------------------- + +Many SCSI HBAs support a hostwide tagset, whereby each command submitted to +the HW from all submission queues must have a unique tag identifier. + +Normally this unique tag will be in the range [0, max queue], where "max +queue" is the depth of each of the submission queues. + +Add support for this hostwide tag feature, via module parameter +"host_max_queue". A non-zero value means that the feature is enabled. In +this case, the submission queues are not exposed to upper layer, i.e. from +blk-mq prespective, the device has a single hw queue. There are 2 reasons +for this: + + a. It is assumed that the host can support nr_hw_queues * can_queue + commands, but this is not true for hostwide tags + + b. For nr_hw_queues != 0, the request tag is not unique over all HW + queues, and some HBA drivers want to use this tag for the hostwide tag + +However, like many SCSI HBA drivers today - megaraid sas being an example - +the full set of HW submission queues are still used in the LLDD driver. So +instead of using a complicated "reply_map" to create a per-CPU submission +queue mapping like megaraid_sas (as it depends on a PCI device + MSIs) - +use a simple algorithm: + + hwq = cpu % queue count + +If the host_max_queue param is set non-zero, then the max queue depth is +fixed at this value also. + +If and when hostwide shared tags are supported in blk-mq/scsi mid-layer, +then the policy to set nr_hw_queues = 0 for hostwide tags can be revised. + +Link: https://lore.kernel.org/r/1594297400-24756-3-git-send-email-john.garry@huawei.com +Acked-by: Douglas Gilbert +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/scsi_debug.c +--- + drivers/scsi/scsi_debug.c | 80 +++++++++++++++++++++++++++++++++------ + 1 file changed, 68 insertions(+), 12 deletions(-) + +diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c +index e0279b0b5ec8..8abf0dac6d44 100644 +--- a/drivers/scsi/scsi_debug.c ++++ b/drivers/scsi/scsi_debug.c +@@ -278,6 +278,7 @@ struct sdebug_defer { + struct execute_work ew; + int sqa_idx; /* index of sdebug_queue array */ + int qc_idx; /* index of sdebug_queued_cmd array within sqa_idx */ ++ int hc_idx; /* hostwide tag index */ + int issuing_cpu; + bool init_hrt; + bool init_wq; +@@ -634,6 +635,7 @@ static int sdebug_dsense = DEF_D_SENSE; + static int sdebug_every_nth = DEF_EVERY_NTH; + static int sdebug_fake_rw = DEF_FAKE_RW; + static unsigned int sdebug_guard = DEF_GUARD; ++static int sdebug_host_max_queue; /* per host */ + static int sdebug_lowest_aligned = DEF_LOWEST_ALIGNED; + static int sdebug_max_luns = DEF_MAX_LUNS; + static int sdebug_max_queue = SDEBUG_CANQUEUE; /* per submit queue */ +@@ -3785,15 +3787,28 @@ static int resp_xdwriteread_10(struct scsi_cmnd *scp, + + static struct sdebug_queue *get_queue(struct scsi_cmnd *cmnd) + { +- u32 tag = blk_mq_unique_tag(cmnd->request); +- u16 hwq = blk_mq_unique_tag_to_hwq(tag); ++ u16 hwq; + +- pr_debug("tag=%#x, hwq=%d\n", tag, hwq); +- if (WARN_ON_ONCE(hwq >= submit_queues)) +- hwq = 0; ++ if (sdebug_host_max_queue) { ++ /* Provide a simple method to choose the hwq */ ++ hwq = smp_processor_id() % submit_queues; ++ } else { ++ u32 tag = blk_mq_unique_tag(cmnd->request); ++ ++ hwq = blk_mq_unique_tag_to_hwq(tag); ++ ++ pr_debug("tag=%#x, hwq=%d\n", tag, hwq); ++ if (WARN_ON_ONCE(hwq >= submit_queues)) ++ hwq = 0; ++ } + return sdebug_q_arr + hwq; + } + ++static u32 get_tag(struct scsi_cmnd *cmnd) ++{ ++ return blk_mq_unique_tag(cmnd->request); ++} ++ + /* Queued (deferred) command completions converge here. */ + static void sdebug_q_cmd_complete(struct sdebug_defer *sd_dp) + { +@@ -3825,8 +3840,8 @@ static void sdebug_q_cmd_complete(struct sdebug_defer *sd_dp) + scp = sqcp->a_cmnd; + if (unlikely(scp == NULL)) { + spin_unlock_irqrestore(&sqp->qc_lock, iflags); +- pr_err("scp is NULL, sqa_idx=%d, qc_idx=%d\n", +- sd_dp->sqa_idx, qc_idx); ++ pr_err("scp is NULL, sqa_idx=%d, qc_idx=%d, hc_idx=%d\n", ++ sd_dp->sqa_idx, qc_idx, sd_dp->hc_idx); + return; + } + devip = (struct sdebug_dev_info *)scp->device->hostdata; +@@ -4427,6 +4442,10 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, + return SCSI_MLQUEUE_HOST_BUSY; + } + ++ /* Set the hostwide tag */ ++ if (sdebug_host_max_queue) ++ sd_dp->hc_idx = get_tag(cmnd); ++ + cmnd->result = pfp != NULL ? pfp(cmnd, devip) : 0; + if (cmnd->result & SDEG_RES_IMMED_MASK) { + /* +@@ -4520,6 +4539,7 @@ module_param_named(guard, sdebug_guard, uint, S_IRUGO); + module_param_named(host_lock, sdebug_host_lock, bool, S_IRUGO | S_IWUSR); + module_param_string(inq_vendor, sdebug_inq_vendor_id, + sizeof(sdebug_inq_vendor_id), S_IRUGO|S_IWUSR); ++module_param_named(host_max_queue, sdebug_host_max_queue, int, S_IRUGO); + module_param_string(inq_product, sdebug_inq_product_id, + sizeof(sdebug_inq_product_id), S_IRUGO|S_IWUSR); + module_param_string(inq_rev, sdebug_inq_product_rev, +@@ -4579,6 +4599,8 @@ MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)"); + MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)"); + MODULE_PARM_DESC(host_lock, "host_lock is ignored (def=0)"); + MODULE_PARM_DESC(inq_vendor, "SCSI INQUIRY vendor string (def=\"Linux\")"); ++MODULE_PARM_DESC(host_max_queue, ++ "host max # of queued cmds (0 to max(def) [max_queue fixed equal for !0])"); + MODULE_PARM_DESC(inq_product, "SCSI INQUIRY product string (def=\"scsi_debug\")"); + MODULE_PARM_DESC(inq_rev, "SCSI INQUIRY revision string (def=\"" + SDEBUG_VERSION "\")"); +@@ -5001,7 +5023,8 @@ static ssize_t max_queue_store(struct device_driver *ddp, const char *buf, + struct sdebug_queue *sqp; + + if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n > 0) && +- (n <= SDEBUG_CANQUEUE)) { ++ (n <= SDEBUG_CANQUEUE) && ++ (sdebug_host_max_queue == 0)) { + block_unblock_all_queues(true); + k = 0; + for (j = 0, sqp = sdebug_q_arr; j < submit_queues; +@@ -5024,6 +5047,17 @@ static ssize_t max_queue_store(struct device_driver *ddp, const char *buf, + } + static DRIVER_ATTR_RW(max_queue); + ++static ssize_t host_max_queue_show(struct device_driver *ddp, char *buf) ++{ ++ return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_host_max_queue); ++} ++ ++/* ++ * Since this is used for .can_queue, and we get the hc_idx tag from the bitmap ++ * in range [0, sdebug_host_max_queue), we can't change it. ++ */ ++static DRIVER_ATTR_RO(host_max_queue); ++ + static ssize_t no_uld_show(struct device_driver *ddp, char *buf) + { + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_no_uld); +@@ -5281,6 +5315,7 @@ static struct attribute *sdebug_drv_attrs[] = { + &driver_attr_ptype.attr, + &driver_attr_dsense.attr, + &driver_attr_fake_rw.attr, ++ &driver_attr_host_max_queue.attr, + &driver_attr_no_lun_0.attr, + &driver_attr_num_tgts.attr, + &driver_attr_dev_size_mb.attr, +@@ -5386,6 +5421,21 @@ static int __init scsi_debug_init(void) + pr_err("submit_queues must be 1 or more\n"); + return -EINVAL; + } ++ ++ if ((sdebug_host_max_queue > SDEBUG_CANQUEUE) || ++ (sdebug_host_max_queue < 0)) { ++ pr_err("host_max_queue must be in range [0 %d]\n", ++ SDEBUG_CANQUEUE); ++ return -EINVAL; ++ } ++ ++ if (sdebug_host_max_queue && ++ (sdebug_max_queue != sdebug_host_max_queue)) { ++ sdebug_max_queue = sdebug_host_max_queue; ++ pr_warn("fixing max submit queue depth to host max queue depth, %d\n", ++ sdebug_max_queue); ++ } ++ + sdebug_q_arr = kcalloc(submit_queues, sizeof(struct sdebug_queue), + GFP_KERNEL); + if (sdebug_q_arr == NULL) +@@ -5873,7 +5923,10 @@ static int sdebug_driver_probe(struct device *dev) + + sdbg_host = to_sdebug_host(dev); + +- sdebug_driver_template.can_queue = sdebug_max_queue; ++ if (sdebug_host_max_queue) ++ sdebug_driver_template.can_queue = sdebug_host_max_queue; ++ else ++ sdebug_driver_template.can_queue = sdebug_max_queue; + if (sdebug_clustering) + sdebug_driver_template.use_clustering = ENABLE_CLUSTERING; + hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(sdbg_host)); +@@ -5887,9 +5940,12 @@ static int sdebug_driver_probe(struct device *dev) + my_name, submit_queues, nr_cpu_ids); + submit_queues = nr_cpu_ids; + } +- /* Decide whether to tell scsi subsystem that we want mq */ +- /* Following should give the same answer for each host */ +- if (shost_use_blk_mq(hpnt)) ++ /* ++ * Decide whether to tell scsi subsystem that we want mq. The ++ * following should give the same answer for each host. If the host ++ * has a limit of hostwide max commands, then do not set. ++ */ ++ if (!sdebug_host_max_queue) + hpnt->nr_hw_queues = submit_queues; + + sdbg_host->shost = hpnt; +-- +2.27.0 + diff --git a/patches/0415-scsi-scsi_debug-Support-host-tagset.patch b/patches/0415-scsi-scsi_debug-Support-host-tagset.patch new file mode 100644 index 00000000..39786485 --- /dev/null +++ b/patches/0415-scsi-scsi_debug-Support-host-tagset.patch @@ -0,0 +1,96 @@ +From 290aea3fbccc81e1a7bc96e66d2a44bcc2736b13 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Wed, 19 Aug 2020 23:20:33 +0800 +Subject: [PATCH 097/256] scsi: scsi_debug: Support host tagset + +mainline inclusion +from mainline-v5.10-rc1 +commit f7c4cdc712ab803f7cdd3d47025081831f457ecc +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f7c4cdc712ab803f7cdd3d47025081831f457ecc + +---------------------------------------------------------------------- + +When host_max_queue is set (> 0), set the Scsi_Host.host_tagset such that +blk-mq will use a hostwide tagset over all SCSI host submission queues. + +This means that we may expose all submission queues and always use the hwq +chosen by blk-mq. + +And since if sdebug_host_max_queue is set, sdebug_max_queue is fixed to the +same value, we can simplify how sdebug_driver_template.can_queue is set. + +Signed-off-by: John Garry +Tested-by: Douglas Gilbert +Acked-by: Martin K. Petersen +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/scsi_debug.c +--- + drivers/scsi/scsi_debug.c | 28 ++++++++++------------------ + 1 file changed, 10 insertions(+), 18 deletions(-) + +diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c +index 8abf0dac6d44..cc5d720916f2 100644 +--- a/drivers/scsi/scsi_debug.c ++++ b/drivers/scsi/scsi_debug.c +@@ -3788,19 +3788,14 @@ static int resp_xdwriteread_10(struct scsi_cmnd *scp, + static struct sdebug_queue *get_queue(struct scsi_cmnd *cmnd) + { + u16 hwq; ++ u32 tag = blk_mq_unique_tag(cmnd->request); + +- if (sdebug_host_max_queue) { +- /* Provide a simple method to choose the hwq */ +- hwq = smp_processor_id() % submit_queues; +- } else { +- u32 tag = blk_mq_unique_tag(cmnd->request); ++ hwq = blk_mq_unique_tag_to_hwq(tag); + +- hwq = blk_mq_unique_tag_to_hwq(tag); ++ pr_debug("tag=%#x, hwq=%d\n", tag, hwq); ++ if (WARN_ON_ONCE(hwq >= submit_queues)) ++ hwq = 0; + +- pr_debug("tag=%#x, hwq=%d\n", tag, hwq); +- if (WARN_ON_ONCE(hwq >= submit_queues)) +- hwq = 0; +- } + return sdebug_q_arr + hwq; + } + +@@ -5923,10 +5918,7 @@ static int sdebug_driver_probe(struct device *dev) + + sdbg_host = to_sdebug_host(dev); + +- if (sdebug_host_max_queue) +- sdebug_driver_template.can_queue = sdebug_host_max_queue; +- else +- sdebug_driver_template.can_queue = sdebug_max_queue; ++ sdebug_driver_template.can_queue = sdebug_max_queue; + if (sdebug_clustering) + sdebug_driver_template.use_clustering = ENABLE_CLUSTERING; + hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(sdbg_host)); +@@ -5942,11 +5934,11 @@ static int sdebug_driver_probe(struct device *dev) + } + /* + * Decide whether to tell scsi subsystem that we want mq. The +- * following should give the same answer for each host. If the host +- * has a limit of hostwide max commands, then do not set. ++ * following should give the same answer for each host. + */ +- if (!sdebug_host_max_queue) +- hpnt->nr_hw_queues = submit_queues; ++ hpnt->nr_hw_queues = submit_queues; ++ if (sdebug_host_max_queue) ++ hpnt->host_tagset = 1; + + sdbg_host->shost = hpnt; + *((struct sdebug_host_info **)hpnt->hostdata) = sdbg_host; +-- +2.27.0 + diff --git a/patches/0416-scsi-hisi_sas-Modify-macro-name-for-OOB-phy-linkrate.patch b/patches/0416-scsi-hisi_sas-Modify-macro-name-for-OOB-phy-linkrate.patch new file mode 100644 index 00000000..ad3d1e74 --- /dev/null +++ b/patches/0416-scsi-hisi_sas-Modify-macro-name-for-OOB-phy-linkrate.patch @@ -0,0 +1,74 @@ +From bdc1bf67479d6ed91ea0ca455226b3bb7b7ed193 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Tue, 1 Sep 2020 19:13:04 +0800 +Subject: [PATCH 098/256] scsi: hisi_sas: Modify macro name for OOB phy + linkrate + +mainline inclusion +from mainline-v5.10-rc1 +commit 4b3a1f1feda62b0b15536548b6d31ca549de2e3a +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4b3a1f1feda62b0b15536548b6d31ca549de2e3a + +---------------------------------------------------------------------- + +The macro for OOB phy linkrate is named CFG_PROG_PHY_LINK_RATE_* but that +is inaccurate. For clarification, include OOB in macro name. + +Link: https://lore.kernel.org/r/1598958790-232272-3-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 15 +++++++-------- + 1 file changed, 7 insertions(+), 8 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 1f5bd0b98d28..2ab1584d762d 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -199,8 +199,8 @@ + #define PHY_CFG_PHY_RST_OFF 3 + #define PHY_CFG_PHY_RST_MSK (0x1 << PHY_CFG_PHY_RST_OFF) + #define PROG_PHY_LINK_RATE (PORT_BASE + 0x8) +-#define CFG_PROG_PHY_LINK_RATE_OFF 8 +-#define CFG_PROG_PHY_LINK_RATE_MSK (0xf << CFG_PROG_PHY_LINK_RATE_OFF) ++#define CFG_PROG_OOB_PHY_LINK_RATE_OFF 8 ++#define CFG_PROG_OOB_PHY_LINK_RATE_MSK (0xf << CFG_PROG_OOB_PHY_LINK_RATE_OFF) + #define PHY_CTRL (PORT_BASE + 0x14) + #define PHY_CTRL_RESET_OFF 0 + #define PHY_CTRL_RESET_MSK (0x1 << PHY_CTRL_RESET_OFF) +@@ -3312,10 +3312,9 @@ static void hisi_sas_bist_test_restore_v3_hw(struct hisi_hba *hisi_hba) + /*restore the linkrate*/ + reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, PROG_PHY_LINK_RATE); + /* init OOB link rate as 1.5 Gbits */ +- reg_val &= ~CFG_PROG_PHY_LINK_RATE_MSK; +- reg_val |= (0x800 << CFG_PROG_PHY_LINK_RATE_OFF); +- hisi_sas_phy_write32(hisi_hba, phy_id, +- PROG_PHY_LINK_RATE, reg_val); ++ reg_val &= ~CFG_PROG_OOB_PHY_LINK_RATE_MSK; ++ reg_val |= (0x8 << CFG_PROG_OOB_PHY_LINK_RATE_OFF); ++ hisi_sas_phy_write32(hisi_hba, phy_id, PROG_PHY_LINK_RATE, reg_val); + + /* enable PHY */ + hisi_sas_phy_enable(hisi_hba, phy_id, 1); +@@ -3339,8 +3338,8 @@ static int debugfs_set_bist_v3_hw(struct hisi_hba *hisi_hba, bool enable) + /* set linkrate of bit test*/ + reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, + PROG_PHY_LINK_RATE); +- reg_val &= ~CFG_PROG_PHY_LINK_RATE_MSK; +- reg_val |= (linkrate << CFG_PROG_PHY_LINK_RATE_OFF); ++ reg_val &= ~CFG_PROG_OOB_PHY_LINK_RATE_MSK; ++ reg_val |= (linkrate << CFG_PROG_OOB_PHY_LINK_RATE_OFF); + hisi_sas_phy_write32(hisi_hba, phy_id, + PROG_PHY_LINK_RATE, reg_val); + +-- +2.27.0 + diff --git a/patches/0417-scsi-hisi_sas-Do-not-modify-upper-fields-of-PROG_PHY.patch b/patches/0417-scsi-hisi_sas-Do-not-modify-upper-fields-of-PROG_PHY.patch new file mode 100644 index 00000000..5d157250 --- /dev/null +++ b/patches/0417-scsi-hisi_sas-Do-not-modify-upper-fields-of-PROG_PHY.patch @@ -0,0 +1,96 @@ +From e7082e66646bef944308703ccf316ddb5df0018b Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Tue, 1 Sep 2020 19:13:05 +0800 +Subject: [PATCH 099/256] scsi: hisi_sas: Do not modify upper fields of + PROG_PHY_LINK_RATE reg + +mainline inclusion +from mainline-v5.10-rc1 +commit caeddc0453b9215669a39ea335f1af1f3f91cc99 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=caeddc0453b9215669a39ea335f1af1f3f91cc99 + +---------------------------------------------------------------------- + +When updating PROG_PHY_LINK_RATE to set linkrate for a phy we used a +hard-coded initial value instead of getting the current value from the +register. The assumption was that this register would not be modified, but +in fact it was partially modified in a new version of hardware. The +hard-coded value we used changed the default value of the register to a an +incorrect setting and as a result the SAS controller could not change +linkrate for the phy. + +Delete hard-coded value and always read the latest value of register before +updating it. + +Link: https://lore.kernel.org/r/1598958790-232272-4-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 21 ++++++++++++--------- + 1 file changed, 12 insertions(+), 9 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 2ab1584d762d..39ff01eb193b 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -199,6 +199,8 @@ + #define PHY_CFG_PHY_RST_OFF 3 + #define PHY_CFG_PHY_RST_MSK (0x1 << PHY_CFG_PHY_RST_OFF) + #define PROG_PHY_LINK_RATE (PORT_BASE + 0x8) ++#define CFG_PROG_PHY_LINK_RATE_OFF 0 ++#define CFG_PROG_PHY_LINK_RATE_MSK (0xff << CFG_PROG_PHY_LINK_RATE_OFF) + #define CFG_PROG_OOB_PHY_LINK_RATE_OFF 8 + #define CFG_PROG_OOB_PHY_LINK_RATE_MSK (0xf << CFG_PROG_OOB_PHY_LINK_RATE_OFF) + #define PHY_CTRL (PORT_BASE + 0x14) +@@ -659,20 +661,20 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) + } + + for (i = 0; i < hisi_hba->n_phy; i++) { ++ enum sas_linkrate max; + struct hisi_sas_phy *phy = &hisi_hba->phy[i]; + struct asd_sas_phy *sas_phy = &phy->sas_phy; +- u32 prog_phy_link_rate = 0x800; ++ u32 prog_phy_link_rate = hisi_sas_phy_read32(hisi_hba, i, ++ PROG_PHY_LINK_RATE); + ++ prog_phy_link_rate &= ~CFG_PROG_PHY_LINK_RATE_MSK; + if (!sas_phy->phy || (sas_phy->phy->maximum_linkrate < + SAS_LINK_RATE_1_5_GBPS)) { +- prog_phy_link_rate = 0x855; ++ max = SAS_LINK_RATE_12_0_GBPS; + } else { +- enum sas_linkrate max = sas_phy->phy->maximum_linkrate; +- +- prog_phy_link_rate = +- hisi_sas_get_prog_phy_linkrate_mask(max) | +- 0x800; ++ max = sas_phy->phy->maximum_linkrate; + } ++ prog_phy_link_rate |= hisi_sas_get_prog_phy_linkrate_mask(max); + + if (skip_bus_flag) { + hisi_sas_phy_write32(hisi_hba, i, +@@ -2803,9 +2805,10 @@ static void phy_set_linkrate_v3_hw(struct hisi_hba *hisi_hba, int phy_no, + struct sas_phy_linkrates *r) + { + enum sas_linkrate max = r->maximum_linkrate; +- /* init OOB link rate as 1.5 Gbits */ +- u32 prog_phy_link_rate = 0x800; ++ u32 prog_phy_link_rate = hisi_sas_phy_read32(hisi_hba, phy_no, ++ PROG_PHY_LINK_RATE); + ++ prog_phy_link_rate &= ~CFG_PROG_PHY_LINK_RATE_MSK; + prog_phy_link_rate |= hisi_sas_get_prog_phy_linkrate_mask(max); + hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE, + prog_phy_link_rate); +-- +2.27.0 + diff --git a/patches/0418-scsi-hisi_sas-Make-phy-index-variable-name-consisten.patch b/patches/0418-scsi-hisi_sas-Make-phy-index-variable-name-consisten.patch new file mode 100644 index 00000000..a8818eb1 --- /dev/null +++ b/patches/0418-scsi-hisi_sas-Make-phy-index-variable-name-consisten.patch @@ -0,0 +1,162 @@ +From a0b88b53cb88abdcb2feef26ffbd8ce589e2e091 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Tue, 1 Sep 2020 19:13:06 +0800 +Subject: [PATCH 100/256] scsi: hisi_sas: Make phy index variable name + consistent + +mainline inclusion +from mainline-v5.10-rc1 +commit ca06f2cd01d08fe01b155ee774a2c6518b03b275 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ca06f2cd01d08fe01b155ee774a2c6518b03b275 + +---------------------------------------------------------------------- + +We use "phy_id" to identify phy in the BIST code but the rest of code +always uses "phy_no". Change it for consistency. + +Link: https://lore.kernel.org/r/1598958790-232272-5-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 52 +++++++++++++------------- + 1 file changed, 26 insertions(+), 26 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 39ff01eb193b..949925ac576b 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -3285,69 +3285,69 @@ static void debugfs_snapshot_restore_v3_hw(struct hisi_hba *hisi_hba) + static void hisi_sas_bist_test_prep_v3_hw(struct hisi_hba *hisi_hba) + { + u32 reg_val; +- int phy_id = hisi_hba->bist_loopback_phy_id; ++ int phy_no = hisi_hba->bist_loopback_phy_id; + + /* disable PHY */ +- hisi_sas_phy_enable(hisi_hba, phy_id, 0); ++ hisi_sas_phy_enable(hisi_hba, phy_no, 0); + + /* disable ALOS */ +- reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, SERDES_CFG); ++ reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, SERDES_CFG); + reg_val |= CFG_ALOS_CHK_DISABLE_MSK; +- hisi_sas_phy_write32(hisi_hba, phy_id, SERDES_CFG, reg_val); ++ hisi_sas_phy_write32(hisi_hba, phy_no, SERDES_CFG, reg_val); + } + + static void hisi_sas_bist_test_restore_v3_hw(struct hisi_hba *hisi_hba) + { + u32 reg_val; +- int phy_id = hisi_hba->bist_loopback_phy_id; ++ int phy_no = hisi_hba->bist_loopback_phy_id; + + /* disable loopback */ +- reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, SAS_PHY_BIST_CTRL); ++ reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, SAS_PHY_BIST_CTRL); + reg_val &= ~(CFG_RX_BIST_EN_MSK | CFG_TX_BIST_EN_MSK | + CFG_BIST_TEST_MSK); +- hisi_sas_phy_write32(hisi_hba, phy_id, SAS_PHY_BIST_CTRL, reg_val); ++ hisi_sas_phy_write32(hisi_hba, phy_no, SAS_PHY_BIST_CTRL, reg_val); + +- /* enable ALOS*/ +- reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, SERDES_CFG); ++ /* enable ALOS */ ++ reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, SERDES_CFG); + reg_val &= ~CFG_ALOS_CHK_DISABLE_MSK; +- hisi_sas_phy_write32(hisi_hba, phy_id, SERDES_CFG, reg_val); ++ hisi_sas_phy_write32(hisi_hba, phy_no, SERDES_CFG, reg_val); + +- /*restore the linkrate*/ +- reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, PROG_PHY_LINK_RATE); ++ /* restore the linkrate */ ++ reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, PROG_PHY_LINK_RATE); + /* init OOB link rate as 1.5 Gbits */ + reg_val &= ~CFG_PROG_OOB_PHY_LINK_RATE_MSK; + reg_val |= (0x8 << CFG_PROG_OOB_PHY_LINK_RATE_OFF); +- hisi_sas_phy_write32(hisi_hba, phy_id, PROG_PHY_LINK_RATE, reg_val); ++ hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE, reg_val); + + /* enable PHY */ +- hisi_sas_phy_enable(hisi_hba, phy_id, 1); ++ hisi_sas_phy_enable(hisi_hba, phy_no, 1); + } + + static int debugfs_set_bist_v3_hw(struct hisi_hba *hisi_hba, bool enable) + { + u32 reg_val, mode_tmp; + u32 linkrate = hisi_hba->bist_loopback_linkrate; +- u32 phy_id = hisi_hba->bist_loopback_phy_id; ++ u32 phy_no = hisi_hba->bist_loopback_phy_id; + u32 code_mode = hisi_hba->bist_loopback_code_mode; + u32 path_mode = hisi_hba->bist_loopback_mode; + +- pr_err("linkrate=%d phy_id=%d code_mode=%d path_mode=%d\n", linkrate, +- phy_id, code_mode, path_mode); ++ pr_err("linkrate=%d phy_no=%d code_mode=%d path_mode=%d\n", linkrate, ++ phy_no, code_mode, path_mode); + mode_tmp = path_mode ? 2 : 1; + if (enable) { + /* some preparations before bist test */ + hisi_sas_bist_test_prep_v3_hw(hisi_hba); + + /* set linkrate of bit test*/ +- reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, ++ reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, + PROG_PHY_LINK_RATE); + reg_val &= ~CFG_PROG_OOB_PHY_LINK_RATE_MSK; + reg_val |= (linkrate << CFG_PROG_OOB_PHY_LINK_RATE_OFF); +- hisi_sas_phy_write32(hisi_hba, phy_id, ++ hisi_sas_phy_write32(hisi_hba, phy_no, + PROG_PHY_LINK_RATE, reg_val); + + /* set code mode of bit test */ +- reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, ++ reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, + SAS_PHY_BIST_CTRL); + reg_val &= ~(CFG_BIST_MODE_SEL_MSK | + CFG_LOOP_TEST_MODE_MSK | +@@ -3357,27 +3357,27 @@ static int debugfs_set_bist_v3_hw(struct hisi_hba *hisi_hba, bool enable) + reg_val |= ((code_mode << CFG_BIST_MODE_SEL_OFF) | + (mode_tmp << CFG_LOOP_TEST_MODE_OFF) | + CFG_BIST_TEST_MSK); +- hisi_sas_phy_write32(hisi_hba, phy_id, ++ hisi_sas_phy_write32(hisi_hba, phy_no, + SAS_PHY_BIST_CTRL, reg_val); + + /*set the bist init data*/ +- hisi_sas_phy_write32(hisi_hba, phy_id, ++ hisi_sas_phy_write32(hisi_hba, phy_no, + SAS_PHY_BIST_CODE, 0x1); +- hisi_sas_phy_write32(hisi_hba, phy_id, ++ hisi_sas_phy_write32(hisi_hba, phy_no, + SAS_PHY_BIST_CODE1, 0x80); + + mdelay(100); + reg_val |= (CFG_RX_BIST_EN_MSK | CFG_TX_BIST_EN_MSK); +- hisi_sas_phy_write32(hisi_hba, phy_id, ++ hisi_sas_phy_write32(hisi_hba, phy_no, + SAS_PHY_BIST_CTRL, reg_val); + + /* clear error bit */ + mdelay(100); +- hisi_sas_phy_read32(hisi_hba, phy_id, SAS_BIST_ERR_CNT); ++ hisi_sas_phy_read32(hisi_hba, phy_no, SAS_BIST_ERR_CNT); + } else { + /* disable bist test and recover it */ + hisi_hba->bist_loopback_cnt += hisi_sas_phy_read32(hisi_hba, +- phy_id, SAS_BIST_ERR_CNT); ++ phy_no, SAS_BIST_ERR_CNT); + hisi_sas_bist_test_restore_v3_hw(hisi_hba); + } + +-- +2.27.0 + diff --git a/patches/0419-scsi-hisi_sas-Add-BIST-support-for-phy-FFE.patch b/patches/0419-scsi-hisi_sas-Add-BIST-support-for-phy-FFE.patch new file mode 100644 index 00000000..03d8fc31 --- /dev/null +++ b/patches/0419-scsi-hisi_sas-Add-BIST-support-for-phy-FFE.patch @@ -0,0 +1,250 @@ +From 2d518965ca61621c4d8eca330d65e73c0119f946 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Tue, 1 Sep 2020 19:13:07 +0800 +Subject: [PATCH 101/256] scsi: hisi_sas: Add BIST support for phy FFE + +mainline inclusion +from mainline-v5.10-rc1 +commit 2c4d582322ff412f83f5c538e33c9440a30db73d +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2c4d582322ff412f83f5c538e33c9440a30db73d + +---------------------------------------------------------------------- + +Add BIST support for phy FFE (Feed forward equalizer) setting. The user can +configure FFE through the new debugfs interface. + +FFE is a parameter used for link layer control. It will affect the link +quality between the SAS controller and the backplane. In the BIST test, the +FFE interface is provided to assist board testers in optimizing link +parameters. + +The modification of the FFE parameter will affect the test after BIST or +the normal running of the board. The user should save the initial FFE +values and restore them after BIST test is complete. + +Link: https://lore.kernel.org/r/1598958790-232272-6-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas.h + drivers/scsi/hisi_sas/hisi_sas_main.c + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 13 +++++ + drivers/scsi/hisi_sas/hisi_sas_main.c | 75 ++++++++++++++++++++++++++ + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 27 ++++++++-- + 3 files changed, 112 insertions(+), 3 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 35c1247caa15..9d255a7cee73 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -315,6 +315,18 @@ enum hisi_sas_debugfs_cache_type { + HISI_SAS_IOST_CACHE, + }; + ++enum hisi_sas_debugfs_bist_ffe_cfg { ++ FFE_SAS_1_5_GBPS, ++ FFE_SAS_3_0_GBPS, ++ FFE_SAS_6_0_GBPS, ++ FFE_SAS_12_0_GBPS, ++ FFE_RESV, ++ FFE_SATA_1_5_GBPS, ++ FFE_SATA_3_0_GBPS, ++ FFE_SATA_6_0_GBPS, ++ FFE_CFG_MAX ++}; ++ + struct hisi_sas_hw { + int (*hw_init)(struct hisi_hba *hisi_hba); + void (*setup_itct)(struct hisi_hba *hisi_hba, +@@ -481,6 +493,7 @@ struct hisi_hba { + int bist_loopback_mode; + u32 bist_loopback_cnt; + int bist_loopback_enable; ++ u32 debugfs_bist_ffe[HISI_SAS_MAX_PHYS][FFE_CFG_MAX]; + + int enable_dix_dif; + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 3f49d60d01f3..efb958a36757 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -3799,6 +3799,58 @@ static const struct file_operations hisi_sas_debugfs_trigger_dump_fops = { + .owner = THIS_MODULE, + }; + ++static const struct { ++ char *name; ++} hisi_sas_debugfs_ffe_name[FFE_CFG_MAX] = { ++ { "SAS_1_5_GBPS" }, ++ { "SAS_3_0_GBPS" }, ++ { "SAS_6_0_GBPS" }, ++ { "SAS_12_0_GBPS" }, ++ { "FFE_RESV" }, ++ { "SATA_1_5_GBPS" }, ++ { "SATA_3_0_GBPS" }, ++ { "SATA_6_0_GBPS" }, ++}; ++ ++static ssize_t hisi_sas_debugfs_write(struct file *filp, ++ const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct seq_file *m = filp->private_data; ++ u32 *val = m->private; ++ int res; ++ ++ res = kstrtouint_from_user(buf, count, 0, val); ++ if (res) ++ return res; ++ ++ return count; ++} ++ ++static int hisi_sas_debugfs_show(struct seq_file *s, void *p) ++{ ++ u32 *val = s->private; ++ ++ seq_printf(s, "0x%x\n", *val); ++ ++ return 0; ++} ++ ++static int hisi_sas_debugfs_open(struct inode *inode, struct file *filp) ++{ ++ return single_open(filp, hisi_sas_debugfs_show, ++ inode->i_private); ++} ++ ++static const struct file_operations hisi_sas_debugfs_ops = { ++ .open = hisi_sas_debugfs_open, ++ .read = seq_read, ++ .write = hisi_sas_debugfs_write, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .owner = THIS_MODULE, ++}; ++ + static ssize_t hisi_sas_debugfs_phy_down_cnt_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) +@@ -3896,6 +3948,8 @@ static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba, int dump_index) + struct device *dev = hisi_hba->dev; + int p, c, d, r, i; + size_t sz; ++ struct dentry *ports_dentry; ++ int phy_no; + + /* create bist structures */ + hisi_hba->debugfs_bist_dentry = debugfs_create_dir("bist", +@@ -3930,6 +3984,27 @@ static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba, int dump_index) + hisi_hba, &hisi_sas_debugfs_bist_enable_ops)) + goto fail; + ++ ports_dentry = debugfs_create_dir("port", ++ hisi_hba->debugfs_bist_dentry); ++ ++ for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) { ++ struct dentry *port_dentry; ++ struct dentry *ffe_dentry; ++ char name[256]; ++ ++ snprintf(name, 256, "%d", phy_no); ++ port_dentry = debugfs_create_dir(name, ports_dentry); ++ ffe_dentry = debugfs_create_dir("ffe", port_dentry); ++ for (i = 0; i < FFE_CFG_MAX; i++) { ++ if (i == FFE_RESV) ++ continue; ++ debugfs_create_file(hisi_sas_debugfs_ffe_name[i].name, ++ 0600, ffe_dentry, ++ &hisi_hba->debugfs_bist_ffe[phy_no][i], ++ &hisi_sas_debugfs_ops); ++ } ++ } ++ + for (r = 0; r < DEBUGFS_REGS_NUM; r++) { + struct hisi_sas_debugfs_regs *regs = + &hisi_hba->debugfs_regs[dump_index][r]; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 949925ac576b..5c57800e54be 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -306,6 +306,7 @@ + #define DMA_RX_STATUS_BUSY_MSK (0x1 << DMA_RX_STATUS_BUSY_OFF) + + #define COARSETUNE_TIME (PORT_BASE + 0x304) ++#define TXDEEMPH_G1 (PORT_BASE + 0x350) + #define ERR_CNT_DWS_LOST (PORT_BASE + 0x380) + #define ERR_CNT_RESET_PROB (PORT_BASE + 0x384) + #define ERR_CNT_INVLD_DW (PORT_BASE + 0x390) +@@ -620,7 +621,7 @@ static u32 hisi_sas_phy_read32(struct hisi_hba *hisi_hba, + + static void init_reg_v3_hw(struct hisi_hba *hisi_hba) + { +- int i; ++ int i, j; + + /* Global registers init */ + hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, +@@ -723,6 +724,13 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) + /* used for 12G negotiate */ + hisi_sas_phy_write32(hisi_hba, i, COARSETUNE_TIME, 0x1e); + hisi_sas_phy_write32(hisi_hba, i, AIP_LIMIT, 0x2ffff); ++ ++ /* get default FFE configuration for BIST */ ++ for (j = 0; j < FFE_CFG_MAX; j++) { ++ u32 val = hisi_sas_phy_read32(hisi_hba, i, ++ TXDEEMPH_G1 + (j * 0x4)); ++ hisi_hba->debugfs_bist_ffe[i][j] = val; ++ } + } + + for (i = 0; i < hisi_hba->queue_count; i++) { +@@ -3286,10 +3294,16 @@ static void hisi_sas_bist_test_prep_v3_hw(struct hisi_hba *hisi_hba) + { + u32 reg_val; + int phy_no = hisi_hba->bist_loopback_phy_id; ++ int i; + + /* disable PHY */ + hisi_sas_phy_enable(hisi_hba, phy_no, 0); + ++ /* update FFE */ ++ for (i = 0; i < FFE_CFG_MAX; i++) ++ hisi_sas_phy_write32(hisi_hba, phy_no, TXDEEMPH_G1 + (i * 0x4), ++ hisi_hba->debugfs_bist_ffe[phy_no][i]); ++ + /* disable ALOS */ + reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, SERDES_CFG); + reg_val |= CFG_ALOS_CHK_DISABLE_MSK; +@@ -3328,11 +3342,18 @@ static int debugfs_set_bist_v3_hw(struct hisi_hba *hisi_hba, bool enable) + u32 reg_val, mode_tmp; + u32 linkrate = hisi_hba->bist_loopback_linkrate; + u32 phy_no = hisi_hba->bist_loopback_phy_id; ++ u32 *ffe = hisi_hba->debugfs_bist_ffe[phy_no]; + u32 code_mode = hisi_hba->bist_loopback_code_mode; + u32 path_mode = hisi_hba->bist_loopback_mode; ++ struct device *dev = hisi_hba->dev; ++ ++ dev_info(dev, "BIST info:phy%d link_rate=%d code_mode=%d path_mode=%d ffe={0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x}\n", ++ phy_no, linkrate, code_mode, path_mode, ++ ffe[FFE_SAS_1_5_GBPS], ffe[FFE_SAS_3_0_GBPS], ++ ffe[FFE_SAS_6_0_GBPS], ffe[FFE_SAS_12_0_GBPS], ++ ffe[FFE_SATA_1_5_GBPS], ffe[FFE_SATA_3_0_GBPS], ++ ffe[FFE_SATA_6_0_GBPS]); + +- pr_err("linkrate=%d phy_no=%d code_mode=%d path_mode=%d\n", linkrate, +- phy_no, code_mode, path_mode); + mode_tmp = path_mode ? 2 : 1; + if (enable) { + /* some preparations before bist test */ +-- +2.27.0 + diff --git a/patches/0420-scsi-hisi_sas-Add-BIST-support-for-fixed-code-patter.patch b/patches/0420-scsi-hisi_sas-Add-BIST-support-for-fixed-code-patter.patch new file mode 100644 index 00000000..3760188e --- /dev/null +++ b/patches/0420-scsi-hisi_sas-Add-BIST-support-for-fixed-code-patter.patch @@ -0,0 +1,181 @@ +From 1f78f6ba39db53690450472eb328f3502faf6e34 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Tue, 1 Sep 2020 19:13:08 +0800 +Subject: [PATCH 102/256] scsi: hisi_sas: Add BIST support for fixed code + pattern + +mainline inclusion +from mainline-v5.10-rc1 +commit 981cc23e741a641ca92c37c7a3df180ced702118 +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=981cc23e741a641ca92c37c7a3df180ced702118 + +---------------------------------------------------------------------- + +Through the new debugfs interface the user can select fixed code +patterns. Add two new interfaces fixed_code and fixed_code1. + +Link: https://lore.kernel.org/r/1598958790-232272-7-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 37 ++++++++++++--------- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 45 +++++++++++++++++--------- + 2 files changed, 52 insertions(+), 30 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 9d255a7cee73..c6b1ba0e8797 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -284,21 +284,6 @@ enum { + HISI_SAS_BIST_LOOPBACK_MODE_REMOTE, + }; + +-enum { +- HISI_SAS_BIST_CODE_MODE_PRBS7 = 0, +- HISI_SAS_BIST_CODE_MODE_PRBS23, +- HISI_SAS_BIST_CODE_MODE_PRBS31, +- HISI_SAS_BIST_CODE_MODE_JTPAT, +- HISI_SAS_BIST_CODE_MODE_CJTPAT, +- HISI_SAS_BIST_CODE_MODE_SCRAMBED_0, +- HISI_SAS_BIST_CODE_MODE_TRAIN, +- HISI_SAS_BIST_CODE_MODE_TRAIN_DONE, +- HISI_SAS_BIST_CODE_MODE_HFTP, +- HISI_SAS_BIST_CODE_MODE_MFTP, +- HISI_SAS_BIST_CODE_MODE_LFTP, +- HISI_SAS_BIST_CODE_MODE_FIXED_DATA, +-}; +- + struct hisi_sas_iost_itct_cache { + u32 data[HISI_SAS_IOST_ITCT_CACHE_DW_SZ]; + }; +@@ -327,6 +312,27 @@ enum hisi_sas_debugfs_bist_ffe_cfg { + FFE_CFG_MAX + }; + ++enum hisi_sas_debugfs_bist_fixed_code { ++ FIXED_CODE, ++ FIXED_CODE_1, ++ FIXED_CODE_MAX ++}; ++ ++enum { ++ HISI_SAS_BIST_CODE_MODE_PRBS7, ++ HISI_SAS_BIST_CODE_MODE_PRBS23, ++ HISI_SAS_BIST_CODE_MODE_PRBS31, ++ HISI_SAS_BIST_CODE_MODE_JTPAT, ++ HISI_SAS_BIST_CODE_MODE_CJTPAT, ++ HISI_SAS_BIST_CODE_MODE_SCRAMBED_0, ++ HISI_SAS_BIST_CODE_MODE_TRAIN, ++ HISI_SAS_BIST_CODE_MODE_TRAIN_DONE, ++ HISI_SAS_BIST_CODE_MODE_HFTP, ++ HISI_SAS_BIST_CODE_MODE_MFTP, ++ HISI_SAS_BIST_CODE_MODE_LFTP, ++ HISI_SAS_BIST_CODE_MODE_FIXED_DATA, ++}; ++ + struct hisi_sas_hw { + int (*hw_init)(struct hisi_hba *hisi_hba); + void (*setup_itct)(struct hisi_hba *hisi_hba, +@@ -494,6 +500,7 @@ struct hisi_hba { + u32 bist_loopback_cnt; + int bist_loopback_enable; + u32 debugfs_bist_ffe[HISI_SAS_MAX_PHYS][FFE_CFG_MAX]; ++ u32 debugfs_bist_fixed_code[FIXED_CODE_MAX]; + + int enable_dix_dif; + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 5c57800e54be..a32b02d3f81e 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -3337,6 +3337,8 @@ static void hisi_sas_bist_test_restore_v3_hw(struct hisi_hba *hisi_hba) + hisi_sas_phy_enable(hisi_hba, phy_no, 1); + } + ++#define SAS_PHY_BIST_CODE_INIT 0x1 ++#define SAS_PHY_BIST_CODE1_INIT 0x80 + static int debugfs_set_bist_v3_hw(struct hisi_hba *hisi_hba, bool enable) + { + u32 reg_val, mode_tmp; +@@ -3345,14 +3347,17 @@ static int debugfs_set_bist_v3_hw(struct hisi_hba *hisi_hba, bool enable) + u32 *ffe = hisi_hba->debugfs_bist_ffe[phy_no]; + u32 code_mode = hisi_hba->bist_loopback_code_mode; + u32 path_mode = hisi_hba->bist_loopback_mode; ++ u32 *fix_code = &hisi_hba->debugfs_bist_fixed_code[0]; + struct device *dev = hisi_hba->dev; + +- dev_info(dev, "BIST info:phy%d link_rate=%d code_mode=%d path_mode=%d ffe={0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x}\n", ++ ++ dev_info(dev, "BIST info:phy%d link_rate=%d code_mode=%d path_mode=%d ffe={0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x} fixed_code={0x%x, 0x%x}\n", + phy_no, linkrate, code_mode, path_mode, + ffe[FFE_SAS_1_5_GBPS], ffe[FFE_SAS_3_0_GBPS], + ffe[FFE_SAS_6_0_GBPS], ffe[FFE_SAS_12_0_GBPS], + ffe[FFE_SATA_1_5_GBPS], ffe[FFE_SATA_3_0_GBPS], +- ffe[FFE_SATA_6_0_GBPS]); ++ ffe[FFE_SATA_6_0_GBPS], fix_code[FIXED_CODE], ++ fix_code[FIXED_CODE_1]); + + mode_tmp = path_mode ? 2 : 1; + if (enable) { +@@ -3370,27 +3375,37 @@ static int debugfs_set_bist_v3_hw(struct hisi_hba *hisi_hba, bool enable) + /* set code mode of bit test */ + reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, + SAS_PHY_BIST_CTRL); +- reg_val &= ~(CFG_BIST_MODE_SEL_MSK | +- CFG_LOOP_TEST_MODE_MSK | +- CFG_RX_BIST_EN_MSK | +- CFG_TX_BIST_EN_MSK | +- CFG_BIST_TEST_MSK); ++ reg_val &= ~(CFG_BIST_MODE_SEL_MSK | CFG_LOOP_TEST_MODE_MSK | ++ CFG_RX_BIST_EN_MSK | CFG_TX_BIST_EN_MSK | ++ CFG_BIST_TEST_MSK); + reg_val |= ((code_mode << CFG_BIST_MODE_SEL_OFF) | + (mode_tmp << CFG_LOOP_TEST_MODE_OFF) | + CFG_BIST_TEST_MSK); +- hisi_sas_phy_write32(hisi_hba, phy_no, +- SAS_PHY_BIST_CTRL, reg_val); ++ hisi_sas_phy_write32(hisi_hba, phy_no, SAS_PHY_BIST_CTRL, ++ reg_val); + + /*set the bist init data*/ +- hisi_sas_phy_write32(hisi_hba, phy_no, +- SAS_PHY_BIST_CODE, 0x1); +- hisi_sas_phy_write32(hisi_hba, phy_no, +- SAS_PHY_BIST_CODE1, 0x80); ++ if (code_mode == HISI_SAS_BIST_CODE_MODE_FIXED_DATA) { ++ reg_val = hisi_hba->debugfs_bist_fixed_code[0]; ++ hisi_sas_phy_write32(hisi_hba, phy_no, ++ SAS_PHY_BIST_CODE, reg_val); ++ ++ reg_val = hisi_hba->debugfs_bist_fixed_code[1]; ++ hisi_sas_phy_write32(hisi_hba, phy_no, ++ SAS_PHY_BIST_CODE1, reg_val); ++ } else { ++ hisi_sas_phy_write32(hisi_hba, phy_no, ++ SAS_PHY_BIST_CODE, ++ SAS_PHY_BIST_CODE_INIT); ++ hisi_sas_phy_write32(hisi_hba, phy_no, ++ SAS_PHY_BIST_CODE1, ++ SAS_PHY_BIST_CODE1_INIT); ++ } + + mdelay(100); + reg_val |= (CFG_RX_BIST_EN_MSK | CFG_TX_BIST_EN_MSK); +- hisi_sas_phy_write32(hisi_hba, phy_no, +- SAS_PHY_BIST_CTRL, reg_val); ++ hisi_sas_phy_write32(hisi_hba, phy_no, SAS_PHY_BIST_CTRL, ++ reg_val); + + /* clear error bit */ + mdelay(100); +-- +2.27.0 + diff --git a/patches/0421-scsi-hisi_sas-Add-missing-newlines.patch b/patches/0421-scsi-hisi_sas-Add-missing-newlines.patch new file mode 100644 index 00000000..611e5ba2 --- /dev/null +++ b/patches/0421-scsi-hisi_sas-Add-missing-newlines.patch @@ -0,0 +1,155 @@ +From 767946b7c4103789e1277bb66742e72923744a56 Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Tue, 1 Sep 2020 19:13:09 +0800 +Subject: [PATCH 103/256] scsi: hisi_sas: Add missing newlines + +mainline inclusion +from mainline-v5.10-rc1 +commit b601577df68af896e563ca62ca07d8681912eabc +category: cleanup +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b601577df68af896e563ca62ca07d8681912eabc + +---------------------------------------------------------------------- + +Newline is missing from some printk() statements. Add them. + +Link: https://lore.kernel.org/r/1598958790-232272-8-git-send-email-john.garry@huawei.com +Signed-off-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 2 +- + drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 24 ++++++++++++------------ + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2 +- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 2 +- + 4 files changed, 15 insertions(+), 15 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index efb958a36757..618f93ae6b56 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -353,7 +353,7 @@ static int hisi_sas_dma_map(struct hisi_hba *hisi_hba, + *n_elem = task->num_scatter; + + if (*n_elem > HISI_SAS_SGE_PAGE_CNT) { +- dev_err(dev, "task prep: n_elem(%d) > HISI_SAS_SGE_PAGE_CNT", ++ dev_err(dev, "task prep: n_elem(%d) > HISI_SAS_SGE_PAGE_CNT\n", + *n_elem); + rc = -EINVAL; + goto err_out_dma_unmap; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +index 09cc42e66dd5..c82abcf2567c 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +@@ -756,7 +756,7 @@ static int hw_init_v1_hw(struct hisi_hba *hisi_hba) + + rc = reset_hw_v1_hw(hisi_hba); + if (rc) { +- dev_err(dev, "hisi_sas_reset_hw failed, rc=%d", rc); ++ dev_err(dev, "hisi_sas_reset_hw failed, rc=%d\n", rc); + return rc; + } + +@@ -1170,7 +1170,7 @@ static void slot_err_v1_hw(struct hisi_hba *hisi_hba, + case SAS_PROTOCOL_STP: + case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: + { +- dev_err(dev, "slot err: SATA/STP not supported"); ++ dev_err(dev, "slot err: SATA/STP not supported\n"); + } + break; + default: +@@ -1222,35 +1222,35 @@ static void slot_complete_v1_hw(struct hisi_hba *hisi_hba, + u32 info_reg = hisi_sas_read32(hisi_hba, HGC_INVLD_DQE_INFO); + + if (info_reg & HGC_INVLD_DQE_INFO_DQ_MSK) +- dev_err(dev, "slot complete: [%d:%d] has dq IPTT err", ++ dev_err(dev, "slot complete: [%d:%d] has dq IPTT err\n", + slot->cmplt_queue, slot->cmplt_queue_slot); + + if (info_reg & HGC_INVLD_DQE_INFO_TYPE_MSK) +- dev_err(dev, "slot complete: [%d:%d] has dq type err", ++ dev_err(dev, "slot complete: [%d:%d] has dq type err\n", + slot->cmplt_queue, slot->cmplt_queue_slot); + + if (info_reg & HGC_INVLD_DQE_INFO_FORCE_MSK) +- dev_err(dev, "slot complete: [%d:%d] has dq force phy err", ++ dev_err(dev, "slot complete: [%d:%d] has dq force phy err\n", + slot->cmplt_queue, slot->cmplt_queue_slot); + + if (info_reg & HGC_INVLD_DQE_INFO_PHY_MSK) +- dev_err(dev, "slot complete: [%d:%d] has dq phy id err", ++ dev_err(dev, "slot complete: [%d:%d] has dq phy id err\n", + slot->cmplt_queue, slot->cmplt_queue_slot); + + if (info_reg & HGC_INVLD_DQE_INFO_ABORT_MSK) +- dev_err(dev, "slot complete: [%d:%d] has dq abort flag err", ++ dev_err(dev, "slot complete: [%d:%d] has dq abort flag err\n", + slot->cmplt_queue, slot->cmplt_queue_slot); + + if (info_reg & HGC_INVLD_DQE_INFO_IPTT_OF_MSK) +- dev_err(dev, "slot complete: [%d:%d] has dq IPTT or ICT err", ++ dev_err(dev, "slot complete: [%d:%d] has dq IPTT or ICT err\n", + slot->cmplt_queue, slot->cmplt_queue_slot); + + if (info_reg & HGC_INVLD_DQE_INFO_SSP_ERR_MSK) +- dev_err(dev, "slot complete: [%d:%d] has dq SSP frame type err", ++ dev_err(dev, "slot complete: [%d:%d] has dq SSP frame type err\n", + slot->cmplt_queue, slot->cmplt_queue_slot); + + if (info_reg & HGC_INVLD_DQE_INFO_OFL_MSK) +- dev_err(dev, "slot complete: [%d:%d] has dq order frame len err", ++ dev_err(dev, "slot complete: [%d:%d] has dq order frame len err\n", + slot->cmplt_queue, slot->cmplt_queue_slot); + + ts->stat = SAS_OPEN_REJECT; +@@ -1298,7 +1298,7 @@ static void slot_complete_v1_hw(struct hisi_hba *hisi_hba, + case SAS_PROTOCOL_SATA: + case SAS_PROTOCOL_STP: + case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: +- dev_err(dev, "slot complete: SATA/STP not supported"); ++ dev_err(dev, "slot complete: SATA/STP not supported\n"); + break; + + default: +@@ -1421,7 +1421,7 @@ static irqreturn_t int_bcast_v1_hw(int irq, void *p) + irq_value = hisi_sas_phy_read32(hisi_hba, phy_no, CHL_INT2); + + if (!(irq_value & CHL_INT2_SL_RX_BC_ACK_MSK)) { +- dev_err(dev, "bcast: irq_value = %x not set enable bit", ++ dev_err(dev, "bcast: irq_value = %x not set enable bit\n", + irq_value); + res = IRQ_NONE; + goto end; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +index 7e0059d3b3ef..404bbf228b78 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -1389,7 +1389,7 @@ static int hw_init_v2_hw(struct hisi_hba *hisi_hba) + + rc = reset_hw_v2_hw(hisi_hba); + if (rc) { +- dev_err(dev, "hisi_sas_reset_hw failed, rc=%d", rc); ++ dev_err(dev, "hisi_sas_reset_hw failed, rc=%d\n", rc); + return rc; + } + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index a32b02d3f81e..838d8ebd01a3 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -1006,7 +1006,7 @@ static int hw_init_v3_hw(struct hisi_hba *hisi_hba) + + rc = reset_hw_v3_hw(hisi_hba); + if (rc) { +- dev_err(dev, "hisi_sas_reset_hw failed, rc=%d", rc); ++ dev_err(dev, "hisi_sas_reset_hw failed, rc=%d\n", rc); + return rc; + } + +-- +2.27.0 + diff --git a/patches/0422-scsi-hisi_sas-Code-style-cleanup.patch b/patches/0422-scsi-hisi_sas-Code-style-cleanup.patch new file mode 100644 index 00000000..0875461c --- /dev/null +++ b/patches/0422-scsi-hisi_sas-Code-style-cleanup.patch @@ -0,0 +1,85 @@ +From 3a4353d0a0d5219732510fb29a6cfb997a4880ab Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Tue, 1 Sep 2020 19:13:10 +0800 +Subject: [PATCH 104/256] scsi: hisi_sas: Code style cleanup + +mainline inclusion +from mainline-v5.10-rc1 +commit 26f84f9bc3ba04dd415a93e4ca16eda896cf94ea +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=26f84f9bc3ba04dd415a93e4ca16eda896cf94ea + +---------------------------------------------------------------------- + +Remove extra blank lines and add spaces around operators. + +Link: https://lore.kernel.org/r/1598958790-232272-9-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 1 - + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2 +- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 4 +--- + 3 files changed, 2 insertions(+), 5 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 618f93ae6b56..fda58be3c08f 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1472,7 +1472,6 @@ static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state) + } else { + hisi_sas_phy_down(hisi_hba, phy_no, 0); + } +- + } + } + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +index 404bbf228b78..1d1ee655c9fb 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -1209,7 +1209,7 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba) + hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0x7ffe20fe); + hisi_sas_write32(hisi_hba, SAS_ECC_INTR_MSK, 0xfff00c30); + for (i = 0; i < hisi_hba->queue_count; i++) +- hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK+0x4*i, 0); ++ hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK + 0x4 * i, 0); + + hisi_sas_write32(hisi_hba, AXI_AHB_CLK_CFG, 1); + hisi_sas_write32(hisi_hba, HYPER_STREAM_ID_EN_CFG, 1); +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 838d8ebd01a3..f66c6599ec44 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -651,7 +651,7 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) + hisi_sas_write32(hisi_hba, AWQOS_AWCACHE_CFG, 0xf0f0); + hisi_sas_write32(hisi_hba, ARQOS_ARCACHE_CFG, 0xf0f0); + for (i = 0; i < hisi_hba->queue_count; i++) +- hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK+0x4*i, 0); ++ hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK + 0x4 * i, 0); + + hisi_sas_write32(hisi_hba, HYPER_STREAM_ID_EN_CFG, 1); + +@@ -1495,7 +1495,6 @@ static void prep_smp_v3_hw(struct hisi_hba *hisi_hba, + + hdr->cmd_table_addr = cpu_to_le64(req_dma_addr); + hdr->sts_buffer_addr = cpu_to_le64(hisi_sas_status_buf_addr_dma(slot)); +- + } + + static void prep_ata_v3_hw(struct hisi_hba *hisi_hba, +@@ -1607,7 +1606,6 @@ static void prep_abort_v3_hw(struct hisi_hba *hisi_hba, + /* dw7 */ + hdr->dw7 = cpu_to_le32(tag_to_abort << CMD_HDR_ABORT_IPTT_OFF); + hdr->transfer_tags = cpu_to_le32(slot->idx); +- + } + + static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba) +-- +2.27.0 + diff --git a/patches/0423-PM-runtime-Remove-link-state-checks-in-rpm_get-put_s.patch b/patches/0423-PM-runtime-Remove-link-state-checks-in-rpm_get-put_s.patch new file mode 100644 index 00000000..23393696 --- /dev/null +++ b/patches/0423-PM-runtime-Remove-link-state-checks-in-rpm_get-put_s.patch @@ -0,0 +1,98 @@ +From b439491aa05b0301a6c08084525b4b1c7cbb8b2a Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Tue, 22 Sep 2020 21:11:06 +0800 +Subject: [PATCH 105/256] PM: runtime: Remove link state checks in + rpm_get/put_supplier() + +mainline inclusion +from mainline-v5.10-rc1 +commit d12544fb2aa9944b180c35914031a8384ab082c1 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d12544fb2aa9944b180c35914031a8384ab082c1 + +---------------------------------------------------------------------- + +To support runtime PM for hisi SAS driver (the driver is in directory +drivers/scsi/hisi_sas), we add device link between scsi_device->sdev_gendev +(consumer device) and hisi_hba->dev(supplier device) with flags +DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE. + +After runtime suspended consumers and supplier, unload the dirver which +causes a hung. + +We found that it called function device_release_driver_internal() to +release the supplier device (hisi_hba->dev), as the device link was +busy, it set the device link state to DL_STATE_SUPPLIER_UNBIND, and +then it called device_release_driver_internal() to release the consumer +device (scsi_device->sdev_gendev). + +Then it would try to call pm_runtime_get_sync() to resume the consumer +device, but because consumer-supplier relation existed, it would try +to resume the supplier first, but as the link state was already +DL_STATE_SUPPLIER_UNBIND, so it skipped resuming the supplier and only +resumed the consumer which hanged (it sends IOs to resume scsi_device +while the SAS controller is suspended). + +Simple flow is as follows: + +device_release_driver_internal -> (supplier device) + if device_links_busy -> + device_links_unbind_consumers -> + ... + WRITE_ONCE(link->status, DL_STATE_SUPPLIER_UNBIND) + device_release_driver_internal (consumer device) + pm_runtime_get_sync -> (consumer device) + ... + __rpm_callback -> + rpm_get_suppliers -> + if link->state == DL_STATE_SUPPLIER_UNBIND -> skip the action of resuming the supplier + ... + pm_runtime_clean_up_links + ... + +Correct suspend/resume ordering between a supplier device and its consumer +devices (resume the supplier device before resuming consumer devices, and +suspend consumer devices before suspending the supplier device) should be +guaranteed by runtime PM, but the state checks in rpm_get_supplier() and +rpm_put_supplier() break this rule, so remove them. + +Signed-off-by: Xiang Chen +[ rjw: Subject and changelog edits ] +Cc: All applicable +Signed-off-by: Rafael J. Wysocki +Signed-off-by: YunYi Yang + + Conflicts: + drivers/base/power/runtime.c +--- + drivers/base/power/runtime.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c +index eaae4adf9ce4..9b4f0e095a33 100644 +--- a/drivers/base/power/runtime.c ++++ b/drivers/base/power/runtime.c +@@ -268,8 +268,7 @@ static int rpm_get_suppliers(struct device *dev) + list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) { + int retval; + +- if (!(link->flags & DL_FLAG_PM_RUNTIME) || +- READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND) ++ if (!(link->flags & DL_FLAG_PM_RUNTIME)) + continue; + + retval = pm_runtime_get_sync(link->supplier); +@@ -288,8 +287,6 @@ static void rpm_put_suppliers(struct device *dev) + struct device_link *link; + + list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) { +- if (READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND) +- continue; + + while (refcount_dec_not_one(&link->rpm_active)) + pm_runtime_put(link->supplier); +-- +2.27.0 + diff --git a/patches/0424-scsi-hisi_sas-Use-hisi_hba-cq_nvecs-for-calling-call.patch b/patches/0424-scsi-hisi_sas-Use-hisi_hba-cq_nvecs-for-calling-call.patch new file mode 100644 index 00000000..56b89d8d --- /dev/null +++ b/patches/0424-scsi-hisi_sas-Use-hisi_hba-cq_nvecs-for-calling-call.patch @@ -0,0 +1,81 @@ +From 118af04e6a6bd559b4a82f842070cdcff7e8f3f8 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Fri, 2 Oct 2020 22:30:32 +0800 +Subject: [PATCH 106/256] scsi: hisi_sas: Use hisi_hba->cq_nvecs for calling + calling synchronize_irq() + +mainline inclusion +from mainline-v5.10-rc1 +commit 7f054da7738a66fc70239ee899e74d899bad3834 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7f054da7738a66fc70239ee899e74d899bad3834 + +---------------------------------------------------------------------- + +A call trace is observed when running function level reset with online CPUs +less than 16 and MSI auto-affinity enabled. + +[16538.348038] Call trace: +[16538.348422] pci_irq_vector+0x98/0xc0 +[16538.348947] disable_host_v3_hw+0x8c/0x288 [hisi_sas_v3_hw] +[16538.349706] hisi_sas_reset_prepare_v3_hw+0x60/0x88 [hisi_sas_v3_hw] +[16538.350631] pci_dev_save_and_disable+0x38/0x68 +[16538.351290] pci_reset_function+0x44/0x88 +[16538.351846] reset_store+0x6c/0xb8 +[16538.352429] dev_attr_store+0x44/0x60 +[16538.353035] sysfs_kf_write+0x58/0x80 +[16538.353558] kernfs_fop_write+0x140/0x230 +[16538.354175] __vfs_write+0x48/0x80 +[16538.354675] vfs_write+0xb8/0x1d8 +[16538.355145] ksys_write+0x74/0xf8 +[16538.355615] __arm64_sys_write+0x24/0x30 +[16538.356240] el0_svc_common.constprop.4+0x80/0x1f0 +[16538.356905] do_el0_svc+0x2c/0x38 +[16538.357408] el0_svc+0x14/0x40 +[16538.357848] el0_sync_handler+0xbc/0x2ec +[16538.358388] el0_sync+0x140/0x180 + +The reason is that if we use pci_alloc_irq_vectors_affinity() to allocate +IRQs, the number of CQ IRQs can only be less than or equal to the number of +online CPUs, but we use hisi_hba->queue_count (always 16) to iterate during +interrupt_disable_v3_hw(). + +Use hisi_hba->cq_nvecs to replace hisi_hba->queue_count to avoid +synchronize IRQ on a CPU which does not exist. + +Link: https://lore.kernel.org/r/1601649038-25534-2-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index f66c6599ec44..6b64fd9baa76 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -2828,10 +2828,11 @@ static void interrupt_disable_v3_hw(struct hisi_hba *hisi_hba) + synchronize_irq(pci_irq_vector(pdev, PCI_IRQ_PHY)); + synchronize_irq(pci_irq_vector(pdev, PCI_IRQ_CHANNEL)); + synchronize_irq(pci_irq_vector(pdev, PCI_IRQ_AXI_FATAL)); +- for (i = 0; i < hisi_hba->nvecs; i++) { ++ for (i = 0; i < hisi_hba->queue_count; i++) + hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK + 0x4 * i, 0x1); +- synchronize_irq(pci_irq_vector(pdev, i + PCI_IRQ_CQ_BASE)); +- } ++ ++ for (i = 0; i < hisi_hba->nvecs; i++) ++ synchronize_irq(pci_irq_vector(pdev, i + 16)); + + hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, 0xffffffff); + hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK2, 0xffffffff); +-- +2.27.0 + diff --git a/patches/0425-scsi-hisi_sas-Switch-to-new-framework-to-support-sus.patch b/patches/0425-scsi-hisi_sas-Switch-to-new-framework-to-support-sus.patch new file mode 100644 index 00000000..ee2ce255 --- /dev/null +++ b/patches/0425-scsi-hisi_sas-Switch-to-new-framework-to-support-sus.patch @@ -0,0 +1,87 @@ +From ce50dac7d351cfa6d04645851a489ab3ae3f8ea4 Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Fri, 2 Oct 2020 22:30:33 +0800 +Subject: [PATCH 107/256] scsi: hisi_sas: Switch to new framework to support + suspend and resume + +mainline inclusion +from mainline-v5.10-rc1 +commit 6c459ea1542b8937779cbeefb2b1cc77a554c29c +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81U + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6c459ea1542b8937779cbeefb2b1cc77a554c29c + +---------------------------------------------------------------------- + +For v3 hw we will add support for runtime PM which is only supported in new +framework. Legacy PM support and new framework are not allowed to be used +together. Switch to new framework to support suspend and resume. + +Link: https://lore.kernel.org/r/1601649038-25534-3-git-send-email-john.garry@huawei.com +Signed-off-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 6b64fd9baa76..4bfeb925499e 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -3791,8 +3791,9 @@ enum { + hip08, + }; + +-static int hisi_sas_v3_suspend(struct pci_dev *pdev, pm_message_t state) ++static int suspend_v3_hw(struct device *device) + { ++ struct pci_dev *pdev = to_pci_dev(device); + struct sas_ha_struct *sha = pci_get_drvdata(pdev); + struct hisi_hba *hisi_hba = sha->lldd_ha; + struct device *dev = hisi_hba->dev; +@@ -3823,7 +3824,7 @@ static int hisi_sas_v3_suspend(struct pci_dev *pdev, pm_message_t state) + + hisi_sas_init_mem(hisi_hba); + +- device_state = pci_choose_state(pdev, state); ++ device_state = pci_choose_state(pdev, PMSG_SUSPEND); + dev_warn(dev, "entering operating state [D%d]\n", + device_state); + pci_save_state(pdev); +@@ -3836,8 +3837,9 @@ static int hisi_sas_v3_suspend(struct pci_dev *pdev, pm_message_t state) + return 0; + } + +-static int hisi_sas_v3_resume(struct pci_dev *pdev) ++static int resume_v3_hw(struct device *device) + { ++ struct pci_dev *pdev = to_pci_dev(device); + struct sas_ha_struct *sha = pci_get_drvdata(pdev); + struct hisi_hba *hisi_hba = sha->lldd_ha; + struct Scsi_Host *shost = hisi_hba->shost; +@@ -3885,14 +3887,17 @@ static const struct pci_error_handlers hisi_sas_err_handler = { + .reset_done = hisi_sas_reset_done_v3_hw, + }; + ++static const struct dev_pm_ops hisi_sas_v3_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(suspend_v3_hw, resume_v3_hw) ++}; ++ + static struct pci_driver sas_v3_pci_driver = { + .name = DRV_NAME, + .id_table = sas_v3_pci_table, + .probe = hisi_sas_v3_probe, + .remove = hisi_sas_v3_remove, +- .suspend = hisi_sas_v3_suspend, +- .resume = hisi_sas_v3_resume, + .err_handler = &hisi_sas_err_handler, ++ .driver.pm = &hisi_sas_v3_pm_ops, + }; + + module_pci_driver(sas_v3_pci_driver); +-- +2.27.0 + diff --git a/patches/0426-scsi-hisi_sas-Add-controller-runtime-PM-support-for-.patch b/patches/0426-scsi-hisi_sas-Add-controller-runtime-PM-support-for-.patch new file mode 100644 index 00000000..e2401d1c --- /dev/null +++ b/patches/0426-scsi-hisi_sas-Add-controller-runtime-PM-support-for-.patch @@ -0,0 +1,155 @@ +From 83d0f626c9259c45a0a88bada62e1967f3fcd8ca Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Fri, 2 Oct 2020 22:30:34 +0800 +Subject: [PATCH 108/256] scsi: hisi_sas: Add controller runtime PM support for + v3 hw + +mainline inclusion +from mainline-v5.10-rc1 +commit 65ff4aef7e9bde00871875c5fbc9c6b79df6f5ba +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81U + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=65ff4aef7e9bde00871875c5fbc9c6b79df6f5ba + +---------------------------------------------------------------------- + +Add controller runtime PM support for v3 hw. + +Link: https://lore.kernel.org/r/1601649038-25534-4-git-send-email-john.garry@huawei.com +Signed-off-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas.h | 2 + + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 56 +++++++++++++++++++++++++- + 2 files changed, 56 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index c6b1ba0e8797..fdf9207f2efe 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -40,6 +41,7 @@ + #define HISI_SAS_MAX_DEVICES HISI_SAS_MAX_ITCT_ENTRIES + #define HISI_SAS_RESET_BIT 0 + #define HISI_SAS_REJECT_CMD_BIT 1 ++#define HISI_SAS_PM_BIT 2 + #define HISI_SAS_MAX_COMMANDS (HISI_SAS_QUEUE_SLOTS) + #define HISI_SAS_RESERVED_IPTT 96 + #define HISI_SAS_UNRESERVED_IPTT \ +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 4bfeb925499e..d2ae66b8a828 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -3695,6 +3695,17 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) + + scsi_scan_host(shost); + ++ /* ++ * For the situation that there are ATA disks connected with SAS ++ * controller, it additionally creates ata_port which will affect the ++ * child_count of hisi_hba->dev. Even if suspended all the disks, ++ * ata_port is still and the child_count of hisi_hba->dev is not 0. ++ * So use pm_suspend_ignore_children() to ignore the effect to ++ * hisi_hba->dev. ++ */ ++ pm_suspend_ignore_children(dev, true); ++ pm_runtime_put_noidle(&pdev->dev); ++ + return 0; + + err_out_register_ha: +@@ -3735,6 +3746,7 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev) + struct hisi_hba *hisi_hba = sha->lldd_ha; + struct Scsi_Host *shost = sha->core.shost; + ++ pm_runtime_get_noresume(dev); + if (timer_pending(&hisi_hba->timer)) + del_timer(&hisi_hba->timer); + +@@ -3791,7 +3803,7 @@ enum { + hip08, + }; + +-static int suspend_v3_hw(struct device *device) ++static int _suspend_v3_hw(struct device *device) + { + struct pci_dev *pdev = to_pci_dev(device); + struct sas_ha_struct *sha = pci_get_drvdata(pdev); +@@ -3837,7 +3849,7 @@ static int suspend_v3_hw(struct device *device) + return 0; + } + +-static int resume_v3_hw(struct device *device) ++static int _resume_v3_hw(struct device *device) + { + struct pci_dev *pdev = to_pci_dev(device); + struct sas_ha_struct *sha = pci_get_drvdata(pdev); +@@ -3876,6 +3888,34 @@ static int resume_v3_hw(struct device *device) + return 0; + } + ++static int suspend_v3_hw(struct device *device) ++{ ++ struct pci_dev *pdev = to_pci_dev(device); ++ struct sas_ha_struct *sha = pci_get_drvdata(pdev); ++ struct hisi_hba *hisi_hba = sha->lldd_ha; ++ int rc; ++ ++ set_bit(HISI_SAS_PM_BIT, &hisi_hba->flags); ++ ++ rc = _suspend_v3_hw(device); ++ if (rc) ++ clear_bit(HISI_SAS_PM_BIT, &hisi_hba->flags); ++ ++ return rc; ++} ++ ++static int resume_v3_hw(struct device *device) ++{ ++ struct pci_dev *pdev = to_pci_dev(device); ++ struct sas_ha_struct *sha = pci_get_drvdata(pdev); ++ struct hisi_hba *hisi_hba = sha->lldd_ha; ++ int rc = _resume_v3_hw(device); ++ ++ clear_bit(HISI_SAS_PM_BIT, &hisi_hba->flags); ++ ++ return rc; ++} ++ + static const struct pci_device_id sas_v3_pci_table[] = { + { PCI_VDEVICE(HUAWEI, 0xa230), hip08 }, + {} +@@ -3887,8 +3927,20 @@ static const struct pci_error_handlers hisi_sas_err_handler = { + .reset_done = hisi_sas_reset_done_v3_hw, + }; + ++static int runtime_suspend_v3_hw(struct device *dev) ++{ ++ return suspend_v3_hw(dev); ++} ++ ++static int runtime_resume_v3_hw(struct device *dev) ++{ ++ return resume_v3_hw(dev); ++} ++ + static const struct dev_pm_ops hisi_sas_v3_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(suspend_v3_hw, resume_v3_hw) ++ SET_RUNTIME_PM_OPS(runtime_suspend_v3_hw, ++ runtime_resume_v3_hw, NULL) + }; + + static struct pci_driver sas_v3_pci_driver = { +-- +2.27.0 + diff --git a/patches/0427-scsi-hisi_sas-Add-check-for-methods-_PS0-and-_PR0.patch b/patches/0427-scsi-hisi_sas-Add-check-for-methods-_PS0-and-_PR0.patch new file mode 100644 index 00000000..f308f46f --- /dev/null +++ b/patches/0427-scsi-hisi_sas-Add-check-for-methods-_PS0-and-_PR0.patch @@ -0,0 +1,69 @@ +From 3486af537ecd5299314cc588054515d632c20f48 Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Fri, 2 Oct 2020 22:30:35 +0800 +Subject: [PATCH 109/256] scsi: hisi_sas: Add check for methods _PS0 and _PR0 + +mainline inclusion +from mainline-v5.10-rc1 +commit e06596d5000c58f35721f334fe2eee28e3b01a77 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81U + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e06596d5000c58f35721f334fe2eee28e3b01a77 + +---------------------------------------------------------------------- + +To support system suspend/resume or runtime suspend/resume, need to use the +function pci_set_power_state() to change the power state which requires at +least method _PS0 or _PR0 be filled by platform for v3 hw. So check whether +the method is supported, if not, print a warning. + +A Kconfig dependency is added as there is no stub for +acpi_device_power_manageable(). + +Link: https://lore.kernel.org/r/1601649038-25534-5-git-send-email-john.garry@huawei.com +Signed-off-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/Kconfig | 1 + + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 4 ++++ + 2 files changed, 5 insertions(+) + +diff --git a/drivers/scsi/hisi_sas/Kconfig b/drivers/scsi/hisi_sas/Kconfig +index 79ad42352825..11c46b217caa 100644 +--- a/drivers/scsi/hisi_sas/Kconfig ++++ b/drivers/scsi/hisi_sas/Kconfig +@@ -14,5 +14,6 @@ config SCSI_HISI_SAS_PCI + tristate "HiSilicon SAS on PCI bus" + depends on SCSI_HISI_SAS + depends on PCI ++ depends on ACPI + help + This driver supports HiSilicon's SAS HBA based on PCI device +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index d2ae66b8a828..8e3f25d6a669 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -1000,6 +1000,7 @@ static int reset_hw_v3_hw(struct hisi_hba *hisi_hba) + static int hw_init_v3_hw(struct hisi_hba *hisi_hba) + { + struct device *dev = hisi_hba->dev; ++ struct acpi_device *acpi_dev; + union acpi_object *obj; + guid_t guid; + int rc; +@@ -1031,6 +1032,9 @@ static int hw_init_v3_hw(struct hisi_hba *hisi_hba) + else + ACPI_FREE(obj); + ++ acpi_dev = ACPI_COMPANION(dev); ++ if (!acpi_device_power_manageable(acpi_dev)) ++ dev_notice(dev, "neither _PS0 nor _PR0 is defined\n"); + return 0; + } + +-- +2.27.0 + diff --git a/patches/0428-scsi-hisi_sas-Add-device-link-between-SCSI-devices-a.patch b/patches/0428-scsi-hisi_sas-Add-device-link-between-SCSI-devices-a.patch new file mode 100644 index 00000000..f1048423 --- /dev/null +++ b/patches/0428-scsi-hisi_sas-Add-device-link-between-SCSI-devices-a.patch @@ -0,0 +1,86 @@ +From 289d9d2a64eeea383aed68c81a3a7aaa16a2d0fe Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Fri, 2 Oct 2020 22:30:36 +0800 +Subject: [PATCH 110/256] scsi: hisi_sas: Add device link between SCSI devices + and hisi_hba + +mainline inclusion +from mainline-v5.10-rc1 +commit 16fd4a7c5917097e9a3da03b39a92381eee40724 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F81U + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=16fd4a7c5917097e9a3da03b39a92381eee40724 + +---------------------------------------------------------------------- + +Runtime PM of SCSI devices is already supported in SCSI layer, we can +suspend/resume every SCSI device separately. But if there is no link +between hisi_hba and SCSI devices or SCSI targets it will cause issues if +the controller is suspended while SCSI devices are still resuming. Only +when all the SCSI devices under the controller are suspended, the +controller can be suspended. Add the device link between SCSI devices +and the controller. + +Link: https://lore.kernel.org/r/1601649038-25534-6-git-send-email-john.garry@huawei.com +Signed-off-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 29 +++++++++++++++++++++++++- + 1 file changed, 28 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 8e3f25d6a669..71e3a77c8725 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -3098,6 +3098,33 @@ static ssize_t intr_coal_count_store(struct device *dev, + } + static DEVICE_ATTR_RW(intr_coal_count); + ++static int slave_configure_v3_hw(struct scsi_device *sdev) ++{ ++ struct Scsi_Host *shost = dev_to_shost(&sdev->sdev_gendev); ++ struct domain_device *ddev = sdev_to_domain_dev(sdev); ++ struct hisi_hba *hisi_hba = shost_priv(shost); ++ struct device *dev = hisi_hba->dev; ++ int ret = sas_slave_configure(sdev); ++ ++ if (ret) ++ return ret; ++ if (!dev_is_sata(ddev)) ++ sas_change_queue_depth(sdev, 64); ++ ++ if (sdev->type == TYPE_ENCLOSURE) ++ return 0; ++ ++ if (!device_link_add(&sdev->sdev_gendev, dev, ++ DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE)) { ++ if (pm_runtime_enabled(dev)) { ++ dev_info(dev, "add device link failed, disable runtime PM for the host\n"); ++ pm_runtime_disable(dev); ++ } ++ } ++ ++ return 0; ++} ++ + static const struct hisi_sas_debugfs_reg_lu debugfs_port_reg_lu[] = { + HISI_SAS_DEBUGFS_REG(PHY_CFG), + HISI_SAS_DEBUGFS_REG(HARD_PHY_LINKRATE), +@@ -3486,7 +3513,7 @@ static struct scsi_host_template sht_v3_hw = { + .module = THIS_MODULE, + .queuecommand = sas_queuecommand, + .target_alloc = sas_target_alloc, +- .slave_configure = hisi_sas_slave_configure, ++ .slave_configure = slave_configure_v3_hw, + .scan_finished = hisi_sas_scan_finished, + .scan_start = hisi_sas_scan_start, + .map_queues = hisi_sas_map_queues, +-- +2.27.0 + diff --git a/patches/0429-scsi-hisi_sas-Recover-PHY-state-according-to-the-sta.patch b/patches/0429-scsi-hisi_sas-Recover-PHY-state-according-to-the-sta.patch new file mode 100644 index 00000000..c3d16245 --- /dev/null +++ b/patches/0429-scsi-hisi_sas-Recover-PHY-state-according-to-the-sta.patch @@ -0,0 +1,55 @@ +From d3472a9e338e29304bc85e4b54c9b8677fbd3894 Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Fri, 2 Oct 2020 22:30:38 +0800 +Subject: [PATCH 111/256] scsi: hisi_sas: Recover PHY state according to the + status before reset + +mainline inclusion +from mainline-v5.10-rc1 +commit 69f4ec1edb136d2d2511d1ef96f94ef0aeecefdf +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81U + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=69f4ec1edb136d2d2511d1ef96f94ef0aeecefdf + +---------------------------------------------------------------------- + +Currently the PHY state is set according to the state of the PHYs after +reset. This is invalid as the PHYs are already re-initialized. + +Set PHY state according to the state before the reset instead of after. + +Link: https://lore.kernel.org/r/1601649038-25534-8-git-send-email-john.garry@huawei.com +Signed-off-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index fda58be3c08f..06d5964bae35 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1601,7 +1601,6 @@ EXPORT_SYMBOL_GPL(hisi_sas_controller_reset_prepare); + void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba) + { + struct Scsi_Host *shost = hisi_hba->shost; +- u32 state; + + /* Init and wait for PHYs to come up and all libsas event finished. */ + hisi_hba->hw->phys_init(hisi_hba); +@@ -1617,8 +1616,7 @@ void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba) + scsi_unblock_requests(shost); + clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags); + +- state = hisi_hba->hw->get_phys_state(hisi_hba); +- hisi_sas_rescan_topology(hisi_hba, state); ++ hisi_sas_rescan_topology(hisi_hba, hisi_hba->phy_state); + } + EXPORT_SYMBOL_GPL(hisi_sas_controller_reset_done); + +-- +2.27.0 + diff --git a/patches/0430-scsi-hisi_sas-Stop-using-queue-0-always-for-v2-hw.patch b/patches/0430-scsi-hisi_sas-Stop-using-queue-0-always-for-v2-hw.patch new file mode 100644 index 00000000..75991f20 --- /dev/null +++ b/patches/0430-scsi-hisi_sas-Stop-using-queue-0-always-for-v2-hw.patch @@ -0,0 +1,50 @@ +From e3047cf5f635651ba59ca62a46b900be21f81206 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 15 Oct 2020 16:27:05 +0800 +Subject: [PATCH 112/256] scsi: hisi_sas: Stop using queue #0 always for v2 hw + +mainline inclusion +from mainline-v5.10-rc2 +commit fab09aaee80389a37d8ab49396afbb77fa86583a +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fab09aaee80389a37d8ab49396afbb77fa86583a + +---------------------------------------------------------------------- + +In commit 8d98416a55eb ("scsi: hisi_sas: Switch v3 hw to MQ"), the dispatch +function was changed to choose the delivery queue based on the request tag +HW queue index. + +This heavily degrades performance for v2 hw, since the HW queues are not +exposed there, and, as such, HW queue #0 is used for every command. + +Revert to previous behaviour for when nr_hw_queues is not set, that being +to choose the HW queue based on target device index. + +Link: https://lore.kernel.org/r/1602750425-240341-1-git-send-email-john.garry@huawei.com +Fixes: 8d98416a55eb ("scsi: hisi_sas: Switch v3 hw to MQ") +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 06d5964bae35..b78fe6102ba4 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -465,7 +465,7 @@ static int hisi_sas_task_prep(struct sas_task *task, + } + } + +- if (scmd) { ++ if (scmd && hisi_hba->shost->nr_hw_queues) { + unsigned int dq_index; + u32 blk_tag; + +-- +2.27.0 + diff --git a/patches/0431-PM-runtime-Drop-runtime-PM-references-to-supplier-on.patch b/patches/0431-PM-runtime-Drop-runtime-PM-references-to-supplier-on.patch new file mode 100644 index 00000000..0918734e --- /dev/null +++ b/patches/0431-PM-runtime-Drop-runtime-PM-references-to-supplier-on.patch @@ -0,0 +1,121 @@ +From c81fe8475e4acd0ec7e1991d972c10bd71d5d5a4 Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +Date: Wed, 21 Oct 2020 21:12:15 +0200 +Subject: [PATCH 113/256] PM: runtime: Drop runtime PM references to supplier + on link removal + +mainline inclusion +from mainline-v5.10-rc3 +commit e0e398e204634db8fb71bd89cf2f6e3e5bd09b51 +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e0e398e204634db8fb71bd89cf2f6e3e5bd09b51 + +---------------------------------------------------------------------- + +While removing a device link, drop the supplier device's runtime PM +usage counter as many times as needed to drop all of the runtime PM +references to it from the consumer in addition to dropping the +consumer's link count. + +Fixes: baa8809f6097 ("PM / runtime: Optimize the use of device links") +Signed-off-by: Rafael J. Wysocki +Cc: 5.1+ # 5.1+ +Tested-by: Xiang Chen +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: YunYi Yang +--- + drivers/base/core.c | 6 ++---- + drivers/base/power/runtime.c | 21 ++++++++++++++++++++- + include/linux/pm_runtime.h | 4 ++-- + 3 files changed, 24 insertions(+), 7 deletions(-) + +diff --git a/drivers/base/core.c b/drivers/base/core.c +index 7f27b007b040..18b95535d9eb 100644 +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -456,8 +456,7 @@ static void __device_link_del(struct kref *kref) + dev_info(link->consumer, "Dropping the link to %s\n", + dev_name(link->supplier)); + +- if (link->flags & DL_FLAG_PM_RUNTIME) +- pm_runtime_drop_link(link->consumer); ++ pm_runtime_drop_link(link); + + list_del_rcu(&link->s_node); + list_del_rcu(&link->c_node); +@@ -471,8 +470,7 @@ static void __device_link_del(struct kref *kref) + dev_info(link->consumer, "Dropping the link to %s\n", + dev_name(link->supplier)); + +- if (link->flags & DL_FLAG_PM_RUNTIME) +- pm_runtime_drop_link(link->consumer); ++ pm_runtime_drop_link(link); + + list_del(&link->s_node); + list_del(&link->c_node); +diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c +index 9b4f0e095a33..6c290af79a31 100644 +--- a/drivers/base/power/runtime.c ++++ b/drivers/base/power/runtime.c +@@ -1610,7 +1610,7 @@ void pm_runtime_new_link(struct device *dev) + spin_unlock_irq(&dev->power.lock); + } + +-void pm_runtime_drop_link(struct device *dev) ++static void pm_runtime_drop_link_count(struct device *dev) + { + spin_lock_irq(&dev->power.lock); + WARN_ON(dev->power.links_count == 0); +@@ -1618,6 +1618,25 @@ void pm_runtime_drop_link(struct device *dev) + spin_unlock_irq(&dev->power.lock); + } + ++/** ++ * pm_runtime_drop_link - Prepare for device link removal. ++ * @link: Device link going away. ++ * ++ * Drop the link count of the consumer end of @link and decrement the supplier ++ * device's runtime PM usage counter as many times as needed to drop all of the ++ * PM runtime reference to it from the consumer. ++ */ ++void pm_runtime_drop_link(struct device_link *link) ++{ ++ if (!(link->flags & DL_FLAG_PM_RUNTIME)) ++ return; ++ ++ pm_runtime_drop_link_count(link->consumer); ++ ++ while (refcount_dec_not_one(&link->rpm_active)) ++ pm_runtime_put(link->supplier); ++} ++ + static bool pm_runtime_need_not_resume(struct device *dev) + { + return atomic_read(&dev->power.usage_count) <= 1 && +diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h +index f0fc4700b6ff..c66130c88f66 100644 +--- a/include/linux/pm_runtime.h ++++ b/include/linux/pm_runtime.h +@@ -59,7 +59,7 @@ extern void pm_runtime_clean_up_links(struct device *dev); + extern void pm_runtime_get_suppliers(struct device *dev); + extern void pm_runtime_put_suppliers(struct device *dev); + extern void pm_runtime_new_link(struct device *dev); +-extern void pm_runtime_drop_link(struct device *dev); ++extern void pm_runtime_drop_link(struct device_link *link); + + static inline void pm_suspend_ignore_children(struct device *dev, bool enable) + { +@@ -176,7 +176,7 @@ static inline void pm_runtime_clean_up_links(struct device *dev) {} + static inline void pm_runtime_get_suppliers(struct device *dev) {} + static inline void pm_runtime_put_suppliers(struct device *dev) {} + static inline void pm_runtime_new_link(struct device *dev) {} +-static inline void pm_runtime_drop_link(struct device *dev) {} ++static inline void pm_runtime_drop_link(struct device_link *link) {} + + #endif /* !CONFIG_PM */ + +-- +2.27.0 + diff --git a/patches/0432-PM-runtime-Drop-pm_runtime_clean_up_links.patch b/patches/0432-PM-runtime-Drop-pm_runtime_clean_up_links.patch new file mode 100644 index 00000000..e7302a47 --- /dev/null +++ b/patches/0432-PM-runtime-Drop-pm_runtime_clean_up_links.patch @@ -0,0 +1,122 @@ +From fdc89781c5e67a8541d6527285fc9237c1cee65a Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +Date: Wed, 21 Oct 2020 21:13:10 +0200 +Subject: [PATCH 114/256] PM: runtime: Drop pm_runtime_clean_up_links() + +mainline inclusion +from mainline-v5.10-rc3 +commit d6e36668598154820177bfd78c1621d8e6c580a2 +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d6e36668598154820177bfd78c1621d8e6c580a2 + +---------------------------------------------------------------------- + +After commit d12544fb2aa9 ("PM: runtime: Remove link state checks in +rpm_get/put_supplier()") nothing prevents the consumer device's +runtime PM from acquiring additional references to the supplier +device after pm_runtime_clean_up_links() has run (or even while it +is running), so calling this function from __device_release_driver() +may be pointless (or even harmful). + +Moreover, it ignores stateless device links, so the runtime PM +handling of managed and stateless device links is inconsistent +because of it, so better get rid of it entirely. + +Fixes: d12544fb2aa9 ("PM: runtime: Remove link state checks in rpm_get/put_supplier()") +Signed-off-by: Rafael J. Wysocki +Cc: 5.1+ # 5.1+ +Tested-by: Xiang Chen +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: YunYi Yang + + Conflicts: + drivers/base/power/runtime.c +--- + drivers/base/dd.c | 1 - + drivers/base/power/runtime.c | 35 ----------------------------------- + include/linux/pm_runtime.h | 2 -- + 3 files changed, 38 deletions(-) + +diff --git a/drivers/base/dd.c b/drivers/base/dd.c +index 0377c3c0f2d4..48f67a119ed6 100644 +--- a/drivers/base/dd.c ++++ b/drivers/base/dd.c +@@ -1010,7 +1010,6 @@ static void __device_release_driver(struct device *dev, struct device *parent) + } + + pm_runtime_get_sync(dev); +- pm_runtime_clean_up_links(dev); + + driver_sysfs_remove(dev); + +diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c +index 6c290af79a31..d5fdd321f0c8 100644 +--- a/drivers/base/power/runtime.c ++++ b/drivers/base/power/runtime.c +@@ -1520,41 +1520,6 @@ void pm_runtime_remove(struct device *dev) + pm_runtime_reinit(dev); + } + +-/** +- * pm_runtime_clean_up_links - Prepare links to consumers for driver removal. +- * @dev: Device whose driver is going to be removed. +- * +- * Check links from this device to any consumers and if any of them have active +- * runtime PM references to the device, drop the usage counter of the device +- * (as many times as needed). +- * +- * Links with the DL_FLAG_MANAGED flag unset are ignored. +- * +- * Since the device is guaranteed to be runtime-active at the point this is +- * called, nothing else needs to be done here. +- * +- * Moreover, this is called after device_links_busy() has returned 'false', so +- * the status of each link is guaranteed to be DL_STATE_SUPPLIER_UNBIND and +- * therefore rpm_active can't be manipulated concurrently. +- */ +-void pm_runtime_clean_up_links(struct device *dev) +-{ +- struct device_link *link; +- int idx; +- +- idx = device_links_read_lock(); +- +- list_for_each_entry_rcu(link, &dev->links.consumers, s_node) { +- if (!(link->flags & DL_FLAG_MANAGED)) +- continue; +- +- while (refcount_dec_not_one(&link->rpm_active)) +- pm_runtime_put_noidle(dev); +- } +- +- device_links_read_unlock(idx); +-} +- + /** + * pm_runtime_get_suppliers - Resume and reference-count supplier devices. + * @dev: Consumer device. +diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h +index c66130c88f66..8c2f9ce2a579 100644 +--- a/include/linux/pm_runtime.h ++++ b/include/linux/pm_runtime.h +@@ -55,7 +55,6 @@ extern unsigned long pm_runtime_autosuspend_expiration(struct device *dev); + extern void pm_runtime_update_max_time_suspended(struct device *dev, + s64 delta_ns); + extern void pm_runtime_set_memalloc_noio(struct device *dev, bool enable); +-extern void pm_runtime_clean_up_links(struct device *dev); + extern void pm_runtime_get_suppliers(struct device *dev); + extern void pm_runtime_put_suppliers(struct device *dev); + extern void pm_runtime_new_link(struct device *dev); +@@ -172,7 +171,6 @@ static inline unsigned long pm_runtime_autosuspend_expiration( + struct device *dev) { return 0; } + static inline void pm_runtime_set_memalloc_noio(struct device *dev, + bool enable){} +-static inline void pm_runtime_clean_up_links(struct device *dev) {} + static inline void pm_runtime_get_suppliers(struct device *dev) {} + static inline void pm_runtime_put_suppliers(struct device *dev) {} + static inline void pm_runtime_new_link(struct device *dev) {} +-- +2.27.0 + diff --git a/patches/0433-PM-runtime-Resume-the-device-earlier-in-__device_rel.patch b/patches/0433-PM-runtime-Resume-the-device-earlier-in-__device_rel.patch new file mode 100644 index 00000000..d8480899 --- /dev/null +++ b/patches/0433-PM-runtime-Resume-the-device-earlier-in-__device_rel.patch @@ -0,0 +1,71 @@ +From 9bedfe4131440692bac36fbef365e277e4ecf687 Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +Date: Thu, 22 Oct 2020 17:38:22 +0200 +Subject: [PATCH 115/256] PM: runtime: Resume the device earlier in + __device_release_driver() + +mainline inclusion +from mainline-v5.10-rc3 +commit 9226c504e364158a17a68ff1fe9d67d266922f50 +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9226c504e364158a17a68ff1fe9d67d266922f50 + +---------------------------------------------------------------------- + +Since the device is resumed from runtime-suspend in +__device_release_driver() anyway, it is better to do that before +looking for busy managed device links from it to consumers, because +if there are any, device_links_unbind_consumers() will be called +and it will cause the consumer devices' drivers to unbind, so the +consumer devices will be runtime-resumed. In turn, resuming each +consumer device will cause the supplier to be resumed and when the +runtime PM references from the given consumer to it are dropped, it +may be suspended. Then, the runtime-resume of the next consumer +will cause the supplier to resume again and so on. + +Update the code accordingly. + +Signed-off-by: Rafael J. Wysocki +Fixes: 9ed9895370ae ("driver core: Functional dependencies tracking support") +Cc: All applicable # All applicable +Tested-by: Xiang Chen +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: YunYi Yang +--- + drivers/base/dd.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/base/dd.c b/drivers/base/dd.c +index 48f67a119ed6..f7050854aee2 100644 +--- a/drivers/base/dd.c ++++ b/drivers/base/dd.c +@@ -994,6 +994,8 @@ static void __device_release_driver(struct device *dev, struct device *parent) + + drv = dev->driver; + if (drv) { ++ pm_runtime_get_sync(dev); ++ + while (device_links_busy(dev)) { + __device_driver_unlock(dev, parent); + +@@ -1005,12 +1007,12 @@ static void __device_release_driver(struct device *dev, struct device *parent) + * have released the driver successfully while this one + * was waiting, so check for that. + */ +- if (dev->driver != drv) ++ if (dev->driver != drv) { ++ pm_runtime_put(dev); + return; ++ } + } + +- pm_runtime_get_sync(dev); +- + driver_sysfs_remove(dev); + + if (dev->bus) +-- +2.27.0 + diff --git a/patches/0434-scsi-hisi_sas-Select-a-suitable-queue-for-internal-I.patch b/patches/0434-scsi-hisi_sas-Select-a-suitable-queue-for-internal-I.patch new file mode 100644 index 00000000..653c6bfb --- /dev/null +++ b/patches/0434-scsi-hisi_sas-Select-a-suitable-queue-for-internal-I.patch @@ -0,0 +1,82 @@ +From 7fdc9346b83aa795f83f2d3b27a0e5e44170a870 Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Mon, 7 Dec 2020 21:30:55 +0800 +Subject: [PATCH 116/256] scsi: hisi_sas: Select a suitable queue for internal + I/Os + +mainline inclusion +from mainline-v5.10-rc1 +commit 359db63378eded1ee9c8c9ad72245f9b0158ae95 +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=359db63378eded1ee9c8c9ad72245f9b0158ae95 + +---------------------------------------------------------------------- + +For when managed interrupts are used (and shost->nr_hw_queues is set), a +fixed queue - set per-device - is still used for internal I/Os. + +If all the CPUs mapped to that queue are offlined, then the completions for +that queue are not serviced and any internal I/Os will time out. + +Fix by selecting a queue for internal I/Os from the queue mapped from the +current CPU in this scenario. + +This is still not ideal as it does not deal with CPU hotplug for inflight +internal I/Os, and needs proper support from [0]. + +[0] https://lore.kernel.org/linux-scsi/20200703130122.111448-1-hare@suse.de/T/#m7d77d049b18f33a24ef206af69ebb66d07440556 + +Link: https://lore.kernel.org/r/1607347855-59091-1-git-send-email-john.garry@huawei.com +Fixes: 8d98416a55eb ("scsi: hisi_sas: Switch v3 hw to MQ") +Signed-off-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 6 ++++++ + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 7 +++++++ + 2 files changed, 13 insertions(+) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index b78fe6102ba4..4946a9879ed8 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -472,6 +472,12 @@ static int hisi_sas_task_prep(struct sas_task *task, + blk_tag = blk_mq_unique_tag(scmd->request); + dq_index = blk_mq_unique_tag_to_hwq(blk_tag); + *dq_pointer = dq = &hisi_hba->dq[dq_index]; ++ } else if (hisi_hba->shost->nr_hw_queues) { ++ struct Scsi_Host *shost = hisi_hba->shost; ++ struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT]; ++ int queue = qmap->mq_map[raw_smp_processor_id()]; ++ ++ *dq_pointer = dq = &hisi_hba->dq[queue]; + } else { + *dq_pointer = dq = sas_dev->dq; + } +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 71e3a77c8725..74ac8bc54f44 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -2787,6 +2787,13 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) + } + + tasklet_init(t, cq_tasklet_v3_hw, (uintptr_t)cq); ++ ++ cq->irq_mask = pci_irq_get_affinity(pdev, ++ i + HISI_SAS_CQ_INT_BASE_VECTORS_V3_HW); ++ if (!cq->irq_mask) { ++ dev_err(dev, "could not get cq%d irq affinity!\n", i); ++ return -ENOENT; ++ } + } + + return 0; +-- +2.27.0 + diff --git a/patches/0435-scsi-hisi_sas-Fix-up-probe-error-handling-for-v3-hw.patch b/patches/0435-scsi-hisi_sas-Fix-up-probe-error-handling-for-v3-hw.patch new file mode 100644 index 00000000..0160ec00 --- /dev/null +++ b/patches/0435-scsi-hisi_sas-Fix-up-probe-error-handling-for-v3-hw.patch @@ -0,0 +1,119 @@ +From a603e98da8305078799d3ecf534e7f27d1ba57f0 Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Thu, 7 Jan 2021 07:40:36 +0000 +Subject: [PATCH 117/256] scsi: hisi_sas: Fix up probe error handling for v3 hw + +mainline inclusion +from mainline-v5.11-rc1 +commit 2ebde94f2ea4cffd812ece2f318c2f4922239b1d +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2ebde94f2ea4cffd812ece2f318c2f4922239b1d + +---------------------------------------------------------------------- + +[ Upstream commit 2ebde94f2ea4cffd812ece2f318c2f4922239b1d ] + +Fix some rollbacks in function hisi_sas_v3_probe() and +interrupt_init_v3_hw(). + +Link: https://lore.kernel.org/r/1606207594-196362-3-git-send-email-john.garry@huawei.com +Fixes: 8d98416a55eb ("scsi: hisi_sas: Switch v3 hw to MQ") +Signed-off-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +Signed-off-by: Chen Jun +Acked-by: Xie XiuQi +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 26 +++++++++++--------------- + 1 file changed, 11 insertions(+), 15 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 74ac8bc54f44..b03fe2b680f8 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -2743,8 +2743,7 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) + DRV_NAME " phy", hisi_hba); + if (rc) { + dev_err(dev, "could not request phy interrupt, rc=%d\n", rc); +- rc = -ENOENT; +- goto free_irq_vectors; ++ return -ENOENT; + } + + rc = devm_request_irq(dev, pci_irq_vector(pdev, PCI_IRQ_CHANNEL), +@@ -2752,8 +2751,7 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) + DRV_NAME " channel", hisi_hba); + if (rc) { + dev_err(dev, "could not request chnl interrupt, rc=%d\n", rc); +- rc = -ENOENT; +- goto free_irq_vectors; ++ return -ENOENT; + } + + rc = devm_request_irq(dev, pci_irq_vector(pdev, PCI_IRQ_AXI_FATAL), +@@ -2761,8 +2759,7 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) + DRV_NAME " fatal", hisi_hba); + if (rc) { + dev_err(dev, "could not request fatal interrupt, rc=%d\n", rc); +- rc = -ENOENT; +- goto free_irq_vectors; ++ return -ENOENT; + } + + if (hisi_sas_intr_conv) +@@ -2782,8 +2779,7 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) + if (rc) { + dev_err(dev, "could not request cq%d interrupt, rc=%d\n", + i, rc); +- rc = -ENOENT; +- goto free_irq_vectors; ++ return -ENOENT; + } + + tasklet_init(t, cq_tasklet_v3_hw, (uintptr_t)cq); +@@ -2797,10 +2793,6 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) + } + + return 0; +- +-free_irq_vectors: +- pci_free_irq_vectors(pdev); +- return rc; + } + + static int hisi_sas_v3_init(struct hisi_hba *hisi_hba) +@@ -3717,11 +3709,11 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) + + rc = interrupt_preinit_v3_hw(hisi_hba); + if (rc) +- goto err_out_ha; ++ goto err_out_debugfs; + dev_err(dev, "%d hw queues\n", shost->nr_hw_queues); + rc = scsi_add_host(shost, dev); + if (rc) +- goto err_out_ha; ++ goto err_out_free_irq_vectors; + + rc = sas_register_ha(sha); + if (rc) +@@ -3748,8 +3740,12 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) + + err_out_register_ha: + scsi_remove_host(shost); +-err_out_ha: ++err_out_free_irq_vectors: ++ pci_free_irq_vectors(pdev); ++err_out_debugfs: + hisi_sas_debugfs_exit(hisi_hba); ++err_out_ha: ++ hisi_sas_free(hisi_hba); + scsi_host_put(shost); + err_out_regions: + pci_release_regions(pdev); +-- +2.27.0 + diff --git a/patches/0436-PM-core-Add-support-to-skip-power-management-in-devi.patch b/patches/0436-PM-core-Add-support-to-skip-power-management-in-devi.patch new file mode 100644 index 00000000..f84ecf10 --- /dev/null +++ b/patches/0436-PM-core-Add-support-to-skip-power-management-in-devi.patch @@ -0,0 +1,162 @@ +From c929316a2aa2c05a57c8e63e75564d19e278fb8a Mon Sep 17 00:00:00 2001 +From: Sudeep Holla +Date: Thu, 14 Feb 2019 18:29:10 +0000 +Subject: [PATCH 118/256] PM / core: Add support to skip power management in + device/driver model + +mainline inclusion +from mainline-v5.1-rc1 +commit 85945c28b5a888043cb2b54f880d80d8915f21f5 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=85945c28b5a888043cb2b54f880d80d8915f21f5 + +---------------------------------------------------------------------- + +All device objects in the driver model contain fields that control the +handling of various power management activities. However, it's not +always useful. There are few instances where pseudo devices are added +to the model just to take advantage of many other features like +kobjects, udev events, and so on. One such example is cpu devices and +their caches. + +The sysfs for the cpu caches are managed by adding devices with cpu +as the parent in cpu_device_create() when secondary cpu is brought +online. Generally when the secondary CPUs are hotplugged back in as part +of resume from suspend-to-ram, we call cpu_device_create() from the cpu +hotplug state machine while the cpu device associated with that CPU is +not yet ready to be resumed as the device_resume() call happens bit +later. It's not really needed to set the flag is_prepared for cpu +devices as they are mostly pseudo device and hotplug framework deals +with state machine and not managed through the cpu device. + +This often results in annoying warning when resuming: +Enabling non-boot CPUs ... +CPU1: Booted secondary processor + cache: parent cpu1 should not be sleeping +CPU1 is up +CPU2: Booted secondary processor + cache: parent cpu2 should not be sleeping +CPU2 is up +.... and so on. + +So in order to fix these kind of errors, we could just completely avoid +doing any power management related initialisations and operations if +they are not used by these devices. + +Add no_pm flags to indicate that the device doesn't require any sort of +PM activities and all of them can be completely skipped. We can use the +same flag to also avoid adding not used *power* sysfs entries for these +devices. For now, lets use this for cpu cache devices. + +Reviewed-by: Ulf Hansson +Signed-off-by: Sudeep Holla +Tested-by: Eugeniu Rosca +Signed-off-by: Rafael J. Wysocki +Signed-off-by: YunYi Yang +--- + drivers/base/cpu.c | 1 + + drivers/base/power/main.c | 7 +++++++ + drivers/base/power/sysfs.c | 6 ++++++ + include/linux/device.h | 10 ++++++++++ + include/linux/pm.h | 1 + + 5 files changed, 25 insertions(+) + +diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c +index c16b58adbdfe..68d45e2e2cd4 100644 +--- a/drivers/base/cpu.c ++++ b/drivers/base/cpu.c +@@ -420,6 +420,7 @@ __cpu_device_create(struct device *parent, void *drvdata, + dev->parent = parent; + dev->groups = groups; + dev->release = device_create_release; ++ device_set_pm_not_required(dev); + dev_set_drvdata(dev, drvdata); + + retval = kobject_set_name_vargs(&dev->kobj, fmt, args); +diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c +index fe7506aae13c..6dbc19de3ac6 100644 +--- a/drivers/base/power/main.c ++++ b/drivers/base/power/main.c +@@ -123,6 +123,10 @@ void device_pm_unlock(void) + */ + void device_pm_add(struct device *dev) + { ++ /* Skip PM setup/initialization. */ ++ if (device_pm_not_required(dev)) ++ return; ++ + pr_debug("PM: Adding info for %s:%s\n", + dev->bus ? dev->bus->name : "No Bus", dev_name(dev)); + device_pm_check_callbacks(dev); +@@ -141,6 +145,9 @@ void device_pm_add(struct device *dev) + */ + void device_pm_remove(struct device *dev) + { ++ if (device_pm_not_required(dev)) ++ return; ++ + pr_debug("PM: Removing info for %s:%s\n", + dev->bus ? dev->bus->name : "No Bus", dev_name(dev)); + complete_all(&dev->power.completion); +diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c +index 63375f80e241..c3aaa3229998 100644 +--- a/drivers/base/power/sysfs.c ++++ b/drivers/base/power/sysfs.c +@@ -681,6 +681,10 @@ int dpm_sysfs_add(struct device *dev) + { + int rc; + ++ /* No need to create PM sysfs if explicitly disabled. */ ++ if (device_pm_not_required(dev)) ++ return 0; ++ + rc = sysfs_create_group(&dev->kobj, &pm_attr_group); + if (rc) + return rc; +@@ -760,6 +764,8 @@ void rpm_sysfs_remove(struct device *dev) + + void dpm_sysfs_remove(struct device *dev) + { ++ if (device_pm_not_required(dev)) ++ return; + sysfs_unmerge_group(&dev->kobj, &pm_qos_latency_tolerance_attr_group); + dev_pm_qos_constraints_destroy(dev); + rpm_sysfs_remove(dev); +diff --git a/include/linux/device.h b/include/linux/device.h +index 44a3dd381f55..cd389ed014fa 100644 +--- a/include/linux/device.h ++++ b/include/linux/device.h +@@ -1202,6 +1202,16 @@ static inline bool device_async_suspend_enabled(struct device *dev) + return !!dev->power.async_suspend; + } + ++static inline bool device_pm_not_required(struct device *dev) ++{ ++ return dev->power.no_pm; ++} ++ ++static inline void device_set_pm_not_required(struct device *dev) ++{ ++ dev->power.no_pm = true; ++} ++ + static inline void dev_pm_syscore_device(struct device *dev, bool val) + { + #ifdef CONFIG_PM_SLEEP +diff --git a/include/linux/pm.h b/include/linux/pm.h +index e723b78d8357..e573f956ed8b 100644 +--- a/include/linux/pm.h ++++ b/include/linux/pm.h +@@ -591,6 +591,7 @@ struct dev_pm_info { + bool is_suspended:1; /* Ditto */ + bool is_noirq_suspended:1; + bool is_late_suspended:1; ++ bool no_pm:1; + bool early_init:1; /* Owned by the PM core */ + bool direct_complete:1; /* Owned by the PM core */ + u32 driver_flags; +-- +2.27.0 + diff --git a/patches/0437-fix-kabi-broken-due-to-change-of-struct-dev_pm_info.patch b/patches/0437-fix-kabi-broken-due-to-change-of-struct-dev_pm_info.patch new file mode 100644 index 00000000..29f26176 --- /dev/null +++ b/patches/0437-fix-kabi-broken-due-to-change-of-struct-dev_pm_info.patch @@ -0,0 +1,37 @@ +From 71040333b996884dbf5f6151e37f473311e123ad Mon Sep 17 00:00:00 2001 +From: YunYi Yang +Date: Mon, 28 Aug 2023 15:00:56 +0800 +Subject: [PATCH 119/256] fix kabi broken due to change of struct dev_pm_info + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +---------------------------------------------------------------------------- + +Commit ("PM / core: Add support to skip power +management in device/driver model") changes the struct dev_pm_info, +so we need to fix kabi broken problem. + +Signed-off-by: YunYi Yang +--- + include/linux/pm.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/include/linux/pm.h b/include/linux/pm.h +index e573f956ed8b..9327eb5b32c3 100644 +--- a/include/linux/pm.h ++++ b/include/linux/pm.h +@@ -591,7 +591,9 @@ struct dev_pm_info { + bool is_suspended:1; /* Ditto */ + bool is_noirq_suspended:1; + bool is_late_suspended:1; ++#ifndef __GENKSYMS__ + bool no_pm:1; ++#endif + bool early_init:1; /* Owned by the PM core */ + bool direct_complete:1; /* Owned by the PM core */ + u32 driver_flags; +-- +2.27.0 + diff --git a/patches/0438-driver-core-Add-device-link-support-for-SYNC_STATE_O.patch b/patches/0438-driver-core-Add-device-link-support-for-SYNC_STATE_O.patch new file mode 100644 index 00000000..bd34f4a4 --- /dev/null +++ b/patches/0438-driver-core-Add-device-link-support-for-SYNC_STATE_O.patch @@ -0,0 +1,187 @@ +From a3edbcdaa611a42b359348c17972225d806a0b06 Mon Sep 17 00:00:00 2001 +From: Saravana Kannan +Date: Mon, 28 Oct 2019 15:00:22 -0700 +Subject: [PATCH 120/256] driver core: Add device link support for + SYNC_STATE_ONLY flag + +mainline inclusion +from mainline-v5.5-rc1 +commit 05ef983e0d65a31b370a4e1b93c1efd490ae778f +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=05ef983e0d65a31b370a4e1b93c1efd490ae778f + +---------------------------------------------------------------------- + +Parent devices might need to create "proxy" device links from themselves +to supplier devices to make sure the supplier devices don't get a +sync_state() before the child consumer devices get a chance to add +device links to the supplier devices. + +However, the parent device has no real dependency on the supplier device +and probing, suspend/resume or runtime PM don't need to be affected by +the supplier device. To capture these cases, create a SYNC_STATE_ONLY +device link flag that only affects sync_state() behavior and doesn't +affect probing, suspend/resume or runtime PM. + +Signed-off-by: Saravana Kannan +Link: https://lore.kernel.org/r/20191028220027.251605-2-saravanak@google.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: YunYi Yang +--- + drivers/base/core.c | 50 ++++++++++++++++++++++++++++++++++-------- + include/linux/device.h | 2 ++ + 2 files changed, 43 insertions(+), 9 deletions(-) + +diff --git a/drivers/base/core.c b/drivers/base/core.c +index 18b95535d9eb..1dd3a3c41371 100644 +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -129,6 +129,9 @@ static int device_is_dependent(struct device *dev, void *target) + return ret; + + list_for_each_entry(link, &dev->links.consumers, s_node) { ++ if (link->flags == (DL_FLAG_SYNC_STATE_ONLY | DL_FLAG_MANAGED)) ++ continue; ++ + if (link->consumer == target) + return 1; + +@@ -198,8 +201,11 @@ static int device_reorder_to_tail(struct device *dev, void *not_used) + device_pm_move_last(dev); + + device_for_each_child(dev, NULL, device_reorder_to_tail); +- list_for_each_entry(link, &dev->links.consumers, s_node) ++ list_for_each_entry(link, &dev->links.consumers, s_node) { ++ if (link->flags == (DL_FLAG_SYNC_STATE_ONLY | DL_FLAG_MANAGED)) ++ continue; + device_reorder_to_tail(link->consumer, NULL); ++ } + + return 0; + } +@@ -226,7 +232,8 @@ void device_pm_move_to_tail(struct device *dev) + + #define DL_MANAGED_LINK_FLAGS (DL_FLAG_AUTOREMOVE_CONSUMER | \ + DL_FLAG_AUTOREMOVE_SUPPLIER | \ +- DL_FLAG_AUTOPROBE_CONSUMER) ++ DL_FLAG_AUTOPROBE_CONSUMER | \ ++ DL_FLAG_SYNC_STATE_ONLY) + + #define DL_ADD_VALID_FLAGS (DL_MANAGED_LINK_FLAGS | DL_FLAG_STATELESS | \ + DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE) +@@ -294,6 +301,8 @@ struct device_link *device_link_add(struct device *consumer, + + if (!consumer || !supplier || flags & ~DL_ADD_VALID_FLAGS || + (flags & DL_FLAG_STATELESS && flags & DL_MANAGED_LINK_FLAGS) || ++ (flags & DL_FLAG_SYNC_STATE_ONLY && ++ flags != DL_FLAG_SYNC_STATE_ONLY) || + (flags & DL_FLAG_AUTOPROBE_CONSUMER && + flags & (DL_FLAG_AUTOREMOVE_CONSUMER | + DL_FLAG_AUTOREMOVE_SUPPLIER))) +@@ -314,11 +323,14 @@ struct device_link *device_link_add(struct device *consumer, + + /* + * If the supplier has not been fully registered yet or there is a +- * reverse dependency between the consumer and the supplier already in +- * the graph, return NULL. ++ * reverse (non-SYNC_STATE_ONLY) dependency between the consumer and ++ * the supplier already in the graph, return NULL. If the link is a ++ * SYNC_STATE_ONLY link, we don't check for reverse dependencies ++ * because it only affects sync_state() callbacks. + */ + if (!device_pm_initialized(supplier) +- || device_is_dependent(consumer, supplier)) { ++ || (!(flags & DL_FLAG_SYNC_STATE_ONLY) && ++ device_is_dependent(consumer, supplier))) { + link = NULL; + goto out; + } +@@ -345,9 +357,14 @@ struct device_link *device_link_add(struct device *consumer, + } + + if (flags & DL_FLAG_STATELESS) { +- link->flags |= DL_FLAG_STATELESS; + kref_get(&link->kref); +- goto out; ++ if (link->flags & DL_FLAG_SYNC_STATE_ONLY && ++ !(link->flags & DL_FLAG_STATELESS)) { ++ link->flags |= DL_FLAG_STATELESS; ++ goto reorder; ++ } else { ++ goto out; ++ } + } + + /* +@@ -369,6 +386,12 @@ struct device_link *device_link_add(struct device *consumer, + link->flags |= DL_FLAG_MANAGED; + device_link_init_status(link, consumer, supplier); + } ++ if (link->flags & DL_FLAG_SYNC_STATE_ONLY && ++ !(flags & DL_FLAG_SYNC_STATE_ONLY)) { ++ link->flags &= ~DL_FLAG_SYNC_STATE_ONLY; ++ goto reorder; ++ } ++ + goto out; + } + +@@ -408,6 +431,13 @@ struct device_link *device_link_add(struct device *consumer, + flags & DL_FLAG_PM_RUNTIME) + pm_runtime_resume(supplier); + ++ if (flags & DL_FLAG_SYNC_STATE_ONLY) { ++ dev_dbg(consumer, ++ "Linked as a sync state only consumer to %s\n", ++ dev_name(supplier)); ++ goto out; ++ } ++reorder: + /* + * Move the consumer and all of the devices depending on it to the end + * of dpm_list and the devices_kset list. +@@ -568,7 +598,8 @@ int device_links_check_suppliers(struct device *dev) + device_links_write_lock(); + + list_for_each_entry(link, &dev->links.suppliers, c_node) { +- if (!(link->flags & DL_FLAG_MANAGED)) ++ if (!(link->flags & DL_FLAG_MANAGED) || ++ link->flags & DL_FLAG_SYNC_STATE_ONLY) + continue; + + if (link->status != DL_STATE_AVAILABLE) { +@@ -813,7 +844,8 @@ void device_links_unbind_consumers(struct device *dev) + list_for_each_entry(link, &dev->links.consumers, s_node) { + enum device_link_state status; + +- if (!(link->flags & DL_FLAG_MANAGED)) ++ if (!(link->flags & DL_FLAG_MANAGED) || ++ link->flags & DL_FLAG_SYNC_STATE_ONLY) + continue; + + status = link->status; +diff --git a/include/linux/device.h b/include/linux/device.h +index cd389ed014fa..ac9212a3442b 100644 +--- a/include/linux/device.h ++++ b/include/linux/device.h +@@ -838,6 +838,7 @@ enum device_link_state { + * AUTOREMOVE_SUPPLIER: Remove the link automatically on supplier driver unbind. + * AUTOPROBE_CONSUMER: Probe consumer driver automatically after supplier binds. + * MANAGED: The core tracks presence of supplier/consumer drivers (internal). ++ * SYNC_STATE_ONLY: Link only affects sync_state() behavior. + */ + #define DL_FLAG_STATELESS BIT(0) + #define DL_FLAG_AUTOREMOVE_CONSUMER BIT(1) +@@ -846,6 +847,7 @@ enum device_link_state { + #define DL_FLAG_AUTOREMOVE_SUPPLIER BIT(4) + #define DL_FLAG_AUTOPROBE_CONSUMER BIT(5) + #define DL_FLAG_MANAGED BIT(6) ++#define DL_FLAG_SYNC_STATE_ONLY BIT(7) + + /** + * struct device_link - Device link representation. +-- +2.27.0 + diff --git a/patches/0439-driver-core-Expose-device-link-details-in-sysfs.patch b/patches/0439-driver-core-Expose-device-link-details-in-sysfs.patch new file mode 100644 index 00000000..0ab54de1 --- /dev/null +++ b/patches/0439-driver-core-Expose-device-link-details-in-sysfs.patch @@ -0,0 +1,552 @@ +From 298607549febaf2dbbebc5e25a2027c2b613868a Mon Sep 17 00:00:00 2001 +From: Saravana Kannan +Date: Thu, 21 May 2020 12:17:58 -0700 +Subject: [PATCH 121/256] driver core: Expose device link details in sysfs + +mainline inclusion +from mainline-v5.9-rc1 +commit 287905e68dd29873bcb7986a8290cd1e4cfde600 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=287905e68dd29873bcb7986a8290cd1e4cfde600 + +---------------------------------------------------------------------- + +It's helpful to be able to look at device link details from sysfs. So, +expose it in sysfs. + +Say device-A is supplier of device-B. These are the additional files +this patch would create: + +/sys/class/devlink/device-A:device-B/ + auto_remove_on + consumer/ -> .../device-B/ + runtime_pm + status + supplier/ -> .../device-A/ + sync_state_only + +/sys/devices/.../device-A/ + consumer:device-B/ -> /sys/class/devlink/device-A:device-B/ + +/sys/devices/.../device-B/ + supplier:device-A/ -> /sys/class/devlink/device-A:device-B/ + +That way: +To get a list of all the device link in the system: +ls /sys/class/devlink/ + +To get the consumer names and links of a device: +ls -d /sys/devices/.../device-X/consumer:* + +To get the supplier names and links of a device: +ls -d /sys/devices/.../device-X/supplier:* + +Signed-off-by: Saravana Kannan +Link: https://lore.kernel.org/r/20200521191800.136035-2-saravanak@google.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: YunYi Yang + + Conflicts: + drivers/base/core.c + include/linux/device.h +--- + Documentation/ABI/testing/sysfs-class-devlink | 126 +++++++++++ + .../ABI/testing/sysfs-devices-consumer | 8 + + .../ABI/testing/sysfs-devices-supplier | 8 + + drivers/base/core.c | 211 +++++++++++++++++- + include/linux/device.h | 57 ++--- + 5 files changed, 375 insertions(+), 35 deletions(-) + create mode 100644 Documentation/ABI/testing/sysfs-class-devlink + create mode 100644 Documentation/ABI/testing/sysfs-devices-consumer + create mode 100644 Documentation/ABI/testing/sysfs-devices-supplier + +diff --git a/Documentation/ABI/testing/sysfs-class-devlink b/Documentation/ABI/testing/sysfs-class-devlink +new file mode 100644 +index 000000000000..3a24973abb83 +--- /dev/null ++++ b/Documentation/ABI/testing/sysfs-class-devlink +@@ -0,0 +1,126 @@ ++What: /sys/class/devlink/.../ ++Date: May 2020 ++Contact: Saravana Kannan ++Description: ++ Provide a place in sysfs for the device link objects in the ++ kernel at any given time. The name of a device link directory, ++ denoted as ... above, is of the form : ++ where is the supplier device name and is ++ the consumer device name. ++ ++What: /sys/class/devlink/.../auto_remove_on ++Date: May 2020 ++Contact: Saravana Kannan ++Description: ++ This file indicates if the device link will ever be ++ automatically removed by the driver core when the consumer and ++ supplier devices themselves are still present. ++ ++ This will be one of the following strings: ++ ++ 'consumer unbind' ++ 'supplier unbind' ++ 'never' ++ ++ 'consumer unbind' means the device link will be removed when ++ the consumer's driver is unbound from the consumer device. ++ ++ 'supplier unbind' means the device link will be removed when ++ the supplier's driver is unbound from the supplier device. ++ ++ 'never' means the device link will not be automatically removed ++ when as long as the supplier and consumer devices themselves ++ are still present. ++ ++What: /sys/class/devlink/.../consumer ++Date: May 2020 ++Contact: Saravana Kannan ++Description: ++ This file is a symlink to the consumer device's sysfs directory. ++ ++What: /sys/class/devlink/.../runtime_pm ++Date: May 2020 ++Contact: Saravana Kannan ++Description: ++ This file indicates if the device link has any impact on the ++ runtime power management behavior of the consumer and supplier ++ devices. For example: Making sure the supplier doesn't enter ++ runtime suspend while the consumer is active. ++ ++ This will be one of the following strings: ++ ++ '0' - Does not affect runtime power management ++ '1' - Affects runtime power management ++ ++What: /sys/class/devlink/.../status ++Date: May 2020 ++Contact: Saravana Kannan ++Description: ++ This file indicates the status of the device link. The status ++ of a device link is affected by whether the supplier and ++ consumer devices have been bound to their corresponding ++ drivers. The status of a device link also affects the binding ++ and unbinding of the supplier and consumer devices with their ++ drivers and also affects whether the software state of the ++ supplier device is synced with the hardware state of the ++ supplier device after boot up. ++ See also: sysfs-devices-state_synced. ++ ++ This will be one of the following strings: ++ ++ 'not tracked' ++ 'dormant' ++ 'available' ++ 'consumer probing' ++ 'active' ++ 'supplier unbinding' ++ 'unknown' ++ ++ 'not tracked' means this device link does not track the status ++ and has no impact on the binding, unbinding and syncing the ++ hardware and software device state. ++ ++ 'dormant' means the supplier and the consumer devices have not ++ bound to their driver. ++ ++ 'available' means the supplier has bound to its driver and is ++ available to supply resources to the consumer device. ++ ++ 'consumer probing' means the consumer device is currently ++ trying to bind to its driver. ++ ++ 'active' means the supplier and consumer devices have both ++ bound successfully to their drivers. ++ ++ 'supplier unbinding' means the supplier devices is currently in ++ the process of unbinding from its driver. ++ ++ 'unknown' means the state of the device link is not any of the ++ above. If this is ever the value, there's a bug in the kernel. ++ ++What: /sys/class/devlink/.../supplier ++Date: May 2020 ++Contact: Saravana Kannan ++Description: ++ This file is a symlink to the supplier device's sysfs directory. ++ ++What: /sys/class/devlink/.../sync_state_only ++Date: May 2020 ++Contact: Saravana Kannan ++Description: ++ This file indicates if the device link is limited to only ++ affecting the syncing of the hardware and software state of the ++ supplier device. ++ ++ This will be one of the following strings: ++ ++ '0' ++ '1' - Affects runtime power management ++ ++ '0' means the device link can affect other device behaviors ++ like binding/unbinding, suspend/resume, runtime power ++ management, etc. ++ ++ '1' means the device link will only affect the syncing of ++ hardware and software state of the supplier device after boot ++ up and doesn't not affect other behaviors of the devices. +diff --git a/Documentation/ABI/testing/sysfs-devices-consumer b/Documentation/ABI/testing/sysfs-devices-consumer +new file mode 100644 +index 000000000000..1f06d74d1c3c +--- /dev/null ++++ b/Documentation/ABI/testing/sysfs-devices-consumer +@@ -0,0 +1,8 @@ ++What: /sys/devices/.../consumer: ++Date: May 2020 ++Contact: Saravana Kannan ++Description: ++ The /sys/devices/.../consumer: are symlinks to device ++ links where this device is the supplier. denotes the ++ name of the consumer in that device link. There can be zero or ++ more of these symlinks for a given device. +diff --git a/Documentation/ABI/testing/sysfs-devices-supplier b/Documentation/ABI/testing/sysfs-devices-supplier +new file mode 100644 +index 000000000000..a919e0db5e90 +--- /dev/null ++++ b/Documentation/ABI/testing/sysfs-devices-supplier +@@ -0,0 +1,8 @@ ++What: /sys/devices/.../supplier: ++Date: May 2020 ++Contact: Saravana Kannan ++Description: ++ The /sys/devices/.../supplier: are symlinks to device ++ links where this device is the consumer. denotes the ++ name of the supplier in that device link. There can be zero or ++ more of these symlinks for a given device. +diff --git a/drivers/base/core.c b/drivers/base/core.c +index 1dd3a3c41371..f7c771dec97f 100644 +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -230,6 +230,186 @@ void device_pm_move_to_tail(struct device *dev) + device_links_read_unlock(idx); + } + ++#define to_devlink(dev) container_of((dev), struct device_link, link_dev) ++ ++static ssize_t status_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ char *status; ++ ++ switch (to_devlink(dev)->status) { ++ case DL_STATE_NONE: ++ status = "not tracked"; break; ++ case DL_STATE_DORMANT: ++ status = "dormant"; break; ++ case DL_STATE_AVAILABLE: ++ status = "available"; break; ++ case DL_STATE_CONSUMER_PROBE: ++ status = "consumer probing"; break; ++ case DL_STATE_ACTIVE: ++ status = "active"; break; ++ case DL_STATE_SUPPLIER_UNBIND: ++ status = "supplier unbinding"; break; ++ default: ++ status = "unknown"; break; ++ } ++ return sprintf(buf, "%s\n", status); ++} ++static DEVICE_ATTR_RO(status); ++ ++static ssize_t auto_remove_on_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct device_link *link = to_devlink(dev); ++ char *str; ++ ++ if (link->flags & DL_FLAG_AUTOREMOVE_SUPPLIER) ++ str = "supplier unbind"; ++ else if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) ++ str = "consumer unbind"; ++ else ++ str = "never"; ++ ++ return sprintf(buf, "%s\n", str); ++} ++static DEVICE_ATTR_RO(auto_remove_on); ++ ++static ssize_t runtime_pm_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct device_link *link = to_devlink(dev); ++ ++ return sprintf(buf, "%d\n", !!(link->flags & DL_FLAG_PM_RUNTIME)); ++} ++static DEVICE_ATTR_RO(runtime_pm); ++ ++static ssize_t sync_state_only_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct device_link *link = to_devlink(dev); ++ ++ return sprintf(buf, "%d\n", !!(link->flags & DL_FLAG_SYNC_STATE_ONLY)); ++} ++static DEVICE_ATTR_RO(sync_state_only); ++ ++static struct attribute *devlink_attrs[] = { ++ &dev_attr_status.attr, ++ &dev_attr_auto_remove_on.attr, ++ &dev_attr_runtime_pm.attr, ++ &dev_attr_sync_state_only.attr, ++ NULL, ++}; ++ATTRIBUTE_GROUPS(devlink); ++ ++static void devlink_dev_release(struct device *dev) ++{ ++ kfree(to_devlink(dev)); ++} ++ ++static struct class devlink_class = { ++ .name = "devlink", ++ .owner = THIS_MODULE, ++ .dev_groups = devlink_groups, ++ .dev_release = devlink_dev_release, ++}; ++ ++static int devlink_add_symlinks(struct device *dev, ++ struct class_interface *class_intf) ++{ ++ int ret; ++ size_t len; ++ struct device_link *link = to_devlink(dev); ++ struct device *sup = link->supplier; ++ struct device *con = link->consumer; ++ char *buf; ++ ++ len = max(strlen(dev_name(sup)), strlen(dev_name(con))); ++ len += strlen("supplier:") + 1; ++ buf = kzalloc(len, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ ret = sysfs_create_link(&link->link_dev.kobj, &sup->kobj, "supplier"); ++ if (ret) ++ goto out; ++ ++ ret = sysfs_create_link(&link->link_dev.kobj, &con->kobj, "consumer"); ++ if (ret) ++ goto err_con; ++ ++ snprintf(buf, len, "consumer:%s", dev_name(con)); ++ ret = sysfs_create_link(&sup->kobj, &link->link_dev.kobj, buf); ++ if (ret) ++ goto err_con_dev; ++ ++ snprintf(buf, len, "supplier:%s", dev_name(sup)); ++ ret = sysfs_create_link(&con->kobj, &link->link_dev.kobj, buf); ++ if (ret) ++ goto err_sup_dev; ++ ++ goto out; ++ ++err_sup_dev: ++ snprintf(buf, len, "consumer:%s", dev_name(con)); ++ sysfs_remove_link(&sup->kobj, buf); ++err_con_dev: ++ sysfs_remove_link(&link->link_dev.kobj, "consumer"); ++err_con: ++ sysfs_remove_link(&link->link_dev.kobj, "supplier"); ++out: ++ kfree(buf); ++ return ret; ++} ++ ++static void devlink_remove_symlinks(struct device *dev, ++ struct class_interface *class_intf) ++{ ++ struct device_link *link = to_devlink(dev); ++ size_t len; ++ struct device *sup = link->supplier; ++ struct device *con = link->consumer; ++ char *buf; ++ ++ sysfs_remove_link(&link->link_dev.kobj, "consumer"); ++ sysfs_remove_link(&link->link_dev.kobj, "supplier"); ++ ++ len = max(strlen(dev_name(sup)), strlen(dev_name(con))); ++ len += strlen("supplier:") + 1; ++ buf = kzalloc(len, GFP_KERNEL); ++ if (!buf) { ++ WARN(1, "Unable to properly free device link symlinks!\n"); ++ return; ++ } ++ ++ snprintf(buf, len, "supplier:%s", dev_name(sup)); ++ sysfs_remove_link(&con->kobj, buf); ++ snprintf(buf, len, "consumer:%s", dev_name(con)); ++ sysfs_remove_link(&sup->kobj, buf); ++ kfree(buf); ++} ++ ++static struct class_interface devlink_class_intf = { ++ .class = &devlink_class, ++ .add_dev = devlink_add_symlinks, ++ .remove_dev = devlink_remove_symlinks, ++}; ++ ++static int __init devlink_class_init(void) ++{ ++ int ret; ++ ++ ret = class_register(&devlink_class); ++ if (ret) ++ return ret; ++ ++ ret = class_interface_register(&devlink_class_intf); ++ if (ret) ++ class_unregister(&devlink_class); ++ ++ return ret; ++} ++postcore_initcall(devlink_class_init); ++ + #define DL_MANAGED_LINK_FLAGS (DL_FLAG_AUTOREMOVE_CONSUMER | \ + DL_FLAG_AUTOREMOVE_SUPPLIER | \ + DL_FLAG_AUTOPROBE_CONSUMER | \ +@@ -401,13 +581,6 @@ struct device_link *device_link_add(struct device *consumer, + + refcount_set(&link->rpm_active, 1); + +- if (flags & DL_FLAG_PM_RUNTIME) { +- if (flags & DL_FLAG_RPM_ACTIVE) +- refcount_inc(&link->rpm_active); +- +- pm_runtime_new_link(consumer); +- } +- + get_device(supplier); + link->supplier = supplier; + INIT_LIST_HEAD(&link->s_node); +@@ -417,6 +590,25 @@ struct device_link *device_link_add(struct device *consumer, + link->flags = flags; + kref_init(&link->kref); + ++ link->link_dev.class = &devlink_class; ++ device_set_pm_not_required(&link->link_dev); ++ dev_set_name(&link->link_dev, "%s:%s", ++ dev_name(supplier), dev_name(consumer)); ++ if (device_register(&link->link_dev)) { ++ put_device(consumer); ++ put_device(supplier); ++ kfree(link); ++ link = NULL; ++ goto out; ++ } ++ ++ if (flags & DL_FLAG_PM_RUNTIME) { ++ if (flags & DL_FLAG_RPM_ACTIVE) ++ refcount_inc(&link->rpm_active); ++ ++ pm_runtime_new_link(consumer); ++ } ++ + /* Determine the initial link state. */ + if (flags & DL_FLAG_STATELESS) + link->status = DL_STATE_NONE; +@@ -470,7 +662,7 @@ static void device_link_free(struct device_link *link) + + put_device(link->consumer); + put_device(link->supplier); +- kfree(link); ++ device_unregister(&link->link_dev); + } + + #ifdef CONFIG_SRCU +@@ -881,6 +1073,9 @@ static void device_links_purge(struct device *dev) + { + struct device_link *link, *ln; + ++ if (dev->class == &devlink_class) ++ return; ++ + /* + * Delete all of the remaining links from this device to any other + * devices (either consumers or suppliers). +diff --git a/include/linux/device.h b/include/linux/device.h +index ac9212a3442b..686ff535b75b 100644 +--- a/include/linux/device.h ++++ b/include/linux/device.h +@@ -849,33 +849,6 @@ enum device_link_state { + #define DL_FLAG_MANAGED BIT(6) + #define DL_FLAG_SYNC_STATE_ONLY BIT(7) + +-/** +- * struct device_link - Device link representation. +- * @supplier: The device on the supplier end of the link. +- * @s_node: Hook to the supplier device's list of links to consumers. +- * @consumer: The device on the consumer end of the link. +- * @c_node: Hook to the consumer device's list of links to suppliers. +- * @status: The state of the link (with respect to the presence of drivers). +- * @flags: Link flags. +- * @rpm_active: Whether or not the consumer device is runtime-PM-active. +- * @kref: Count repeated addition of the same link. +- * @rcu_head: An RCU head to use for deferred execution of SRCU callbacks. +- */ +-struct device_link { +- struct device *supplier; +- struct list_head s_node; +- struct device *consumer; +- struct list_head c_node; +- enum device_link_state status; +- u32 flags; +- refcount_t rpm_active; +- struct kref kref; +-#ifdef CONFIG_SRCU +- struct rcu_head rcu_head; +-#endif +- bool supplier_preactivated; /* Owned by consumer probe. */ +-}; +- + /** + * enum dl_dev_state - Device driver presence tracking information. + * @DL_DEV_NO_DRIVER: There is no driver attached to the device. +@@ -1102,6 +1075,36 @@ struct rcu_device { + struct rcu_head rcu_head; + }; + ++/** ++ * struct device_link - Device link representation. ++ * @supplier: The device on the supplier end of the link. ++ * @s_node: Hook to the supplier device's list of links to consumers. ++ * @consumer: The device on the consumer end of the link. ++ * @c_node: Hook to the consumer device's list of links to suppliers. ++ * @link_dev: device used to expose link details in sysfs ++ * @status: The state of the link (with respect to the presence of drivers). ++ * @flags: Link flags. ++ * @rpm_active: Whether or not the consumer device is runtime-PM-active. ++ * @kref: Count repeated addition of the same link. ++ * @rcu_head: An RCU head to use for deferred execution of SRCU callbacks. ++ * @supplier_preactivated: Supplier has been made active before consumer probe. ++ */ ++struct device_link { ++ struct device *supplier; ++ struct list_head s_node; ++ struct device *consumer; ++ struct list_head c_node; ++ struct device link_dev; ++ enum device_link_state status; ++ u32 flags; ++ refcount_t rpm_active; ++ struct kref kref; ++#ifdef CONFIG_SRCU ++ struct rcu_head rcu_head; ++#endif ++ bool supplier_preactivated; /* Owned by consumer probe. */ ++}; ++ + static inline struct device *kobj_to_dev(struct kobject *kobj) + { + return container_of(kobj, struct device, kobj); +-- +2.27.0 + diff --git a/patches/0440-fix-kabi-broken-due-to-change-of-struct-device_link.patch b/patches/0440-fix-kabi-broken-due-to-change-of-struct-device_link.patch new file mode 100644 index 00000000..ba24739f --- /dev/null +++ b/patches/0440-fix-kabi-broken-due-to-change-of-struct-device_link.patch @@ -0,0 +1,45 @@ +From f76bfab8a90882a39a703816d055e626dd753187 Mon Sep 17 00:00:00 2001 +From: YunYi Yang +Date: Mon, 28 Aug 2023 15:44:43 +0800 +Subject: [PATCH 122/256] fix kabi broken due to change of struct device_link + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +---------------------------------------------------------------------------- + +Commit ("driver core: Expose device link details in +sysfs") changes the struct device_link, so we need to fix kabi broken +problem. + +Signed-off-by: YunYi Yang +--- + include/linux/device.h | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/include/linux/device.h b/include/linux/device.h +index 686ff535b75b..18552235be04 100644 +--- a/include/linux/device.h ++++ b/include/linux/device.h +@@ -1094,7 +1094,6 @@ struct device_link { + struct list_head s_node; + struct device *consumer; + struct list_head c_node; +- struct device link_dev; + enum device_link_state status; + u32 flags; + refcount_t rpm_active; +@@ -1103,6 +1102,9 @@ struct device_link { + struct rcu_head rcu_head; + #endif + bool supplier_preactivated; /* Owned by consumer probe. */ ++#ifndef __GENKSYMS__ ++ struct device link_dev; ++#endif + }; + + static inline struct device *kobj_to_dev(struct kobject *kobj) +-- +2.27.0 + diff --git a/patches/0441-driver-core-Fix-sleeping-in-invalid-context-during-d.patch b/patches/0441-driver-core-Fix-sleeping-in-invalid-context-during-d.patch new file mode 100644 index 00000000..159b3b4f --- /dev/null +++ b/patches/0441-driver-core-Fix-sleeping-in-invalid-context-during-d.patch @@ -0,0 +1,144 @@ +From eef1abd685b335e6c7b01e3da46428db3a3b00e2 Mon Sep 17 00:00:00 2001 +From: Saravana Kannan +Date: Thu, 16 Jul 2020 14:45:23 -0700 +Subject: [PATCH 123/256] driver core: Fix sleeping in invalid context during + device link deletion + +mainline inclusion +from mainline-v5.9-rc1 +commit 843e600b8a2b01463c4d873a90b2c2ea8033f1f6 +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=843e600b8a2b01463c4d873a90b2c2ea8033f1f6 + +---------------------------------------------------------------------- + +Marek and Guenter reported that commit 287905e68dd2 ("driver core: +Expose device link details in sysfs") caused sleeping/scheduling while +atomic warnings. + +BUG: sleeping function called from invalid context at kernel/locking/mutex.c:935 +in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 12, name: kworker/0:1 +2 locks held by kworker/0:1/12: + #0: ee8074a8 ((wq_completion)rcu_gp){+.+.}-{0:0}, at: process_one_work+0x174/0x7dc + #1: ee921f20 ((work_completion)(&sdp->work)){+.+.}-{0:0}, at: process_one_work+0x174/0x7dc +Preemption disabled at: +[] srcu_invoke_callbacks+0xc0/0x154 +----- 8< ----- SNIP +[] (device_del) from [] (device_unregister+0x24/0x64) +[] (device_unregister) from [] (srcu_invoke_callbacks+0xcc/0x154) +[] (srcu_invoke_callbacks) from [] (process_one_work+0x234/0x7dc) +[] (process_one_work) from [] (worker_thread+0x44/0x51c) +[] (worker_thread) from [] (kthread+0x158/0x1a0) +[] (kthread) from [] (ret_from_fork+0x14/0x20) +Exception stack(0xee921fb0 to 0xee921ff8) + +This was caused by the device link device being released in the context +of srcu_invoke_callbacks(). There is no need to wait till the RCU +callback to release the device link device. So release the device +earlier and move the call_srcu() into the device release code. That way, +the memory will get freed only after the device is released AND the RCU +callback is called. + +Fixes: 287905e68dd2 ("driver core: Expose device link details in sysfs") +Reported-by: Marek Szyprowski +Reported-by: Guenter Roeck +Reported-by: Naresh Kamboju +Signed-off-by: Saravana Kannan +Tested-by: Marek Szyprowski +Tested-by: Guenter Roeck +Link: https://lore.kernel.org/r/20200716214523.2924704-1-saravanak@google.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: YunYi Yang + + Conflicts: + drivers/base/core.c +--- + drivers/base/core.c | 44 +++++++++++++++++++++++++++----------------- + 1 file changed, 27 insertions(+), 17 deletions(-) + +diff --git a/drivers/base/core.c b/drivers/base/core.c +index f7c771dec97f..7066a9451f77 100644 +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -301,10 +301,34 @@ static struct attribute *devlink_attrs[] = { + }; + ATTRIBUTE_GROUPS(devlink); + ++static void device_link_free(struct device_link *link) ++{ ++ while (refcount_dec_not_one(&link->rpm_active)) ++ pm_runtime_put(link->supplier); ++ ++ put_device(link->consumer); ++ put_device(link->supplier); ++ kfree(link); ++} ++ ++#ifdef CONFIG_SRCU ++static void __device_link_free_srcu(struct rcu_head *rhead) ++{ ++ device_link_free(container_of(rhead, struct device_link, rcu_head)); ++} ++ ++static void devlink_dev_release(struct device *dev) ++{ ++ struct device_link *link = to_devlink(dev); ++ ++ call_srcu(&device_links_srcu, &link->rcu_head, __device_link_free_srcu); ++} ++#else + static void devlink_dev_release(struct device *dev) + { +- kfree(to_devlink(dev)); ++ device_link_free(to_devlink(dev)); + } ++#endif + + static struct class devlink_class = { + .name = "devlink", +@@ -655,22 +679,8 @@ struct device_link *device_link_add(struct device *consumer, + } + EXPORT_SYMBOL_GPL(device_link_add); + +-static void device_link_free(struct device_link *link) +-{ +- while (refcount_dec_not_one(&link->rpm_active)) +- pm_runtime_put(link->supplier); +- +- put_device(link->consumer); +- put_device(link->supplier); +- device_unregister(&link->link_dev); +-} + + #ifdef CONFIG_SRCU +-static void __device_link_free_srcu(struct rcu_head *rhead) +-{ +- device_link_free(container_of(rhead, struct device_link, rcu_head)); +-} +- + static void __device_link_del(struct kref *kref) + { + struct device_link *link = container_of(kref, struct device_link, kref); +@@ -682,7 +692,7 @@ static void __device_link_del(struct kref *kref) + + list_del_rcu(&link->s_node); + list_del_rcu(&link->c_node); +- call_srcu(&device_links_srcu, &link->rcu_head, __device_link_free_srcu); ++ device_unregister(&link->link_dev); + } + #else /* !CONFIG_SRCU */ + static void __device_link_del(struct kref *kref) +@@ -696,7 +706,7 @@ static void __device_link_del(struct kref *kref) + + list_del(&link->s_node); + list_del(&link->c_node); +- device_link_free(link); ++ device_unregister(&link->link_dev); + } + #endif /* !CONFIG_SRCU */ + +-- +2.27.0 + diff --git a/patches/0442-drivers-base-Fix-device-link-removal.patch b/patches/0442-drivers-base-Fix-device-link-removal.patch new file mode 100644 index 00000000..a0ba614d --- /dev/null +++ b/patches/0442-drivers-base-Fix-device-link-removal.patch @@ -0,0 +1,156 @@ +From 992c9f0f8f0c008f7d48e9e5e92fda6ad42c8b43 Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +Date: Mon, 7 Jun 2021 02:01:38 +0000 +Subject: [PATCH 124/256] drivers: base: Fix device link removal + +mainline inclusion +from mainline-v5.13-rc4 +commit 80dd33cf72d1ab4f0af303f1fa242c6d6c8d328f +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=80dd33cf72d1ab4f0af303f1fa242c6d6c8d328f + +---------------------------------------------------------------------- + +When device_link_free() drops references to the supplier and +consumer devices of the device link going away and the reference +being dropped turns out to be the last one for any of those +device objects, its ->release callback will be invoked and it +may sleep which goes against the SRCU callback execution +requirements. + +To address this issue, make the device link removal code carry out +the device_link_free() actions preceded by SRCU synchronization from +a separate work item (the "long" workqueue is used for that, because +it does not matter when the device link memory is released and it may +take time to get to that point) instead of using SRCU callbacks. + +While at it, make the code work analogously when SRCU is not enabled +to reduce the differences between the SRCU and non-SRCU cases. + +Fixes: 843e600b8a2b ("driver core: Fix sleeping in invalid context during device link deletion") +Cc: stable +Reported-by: chenxiang (M) +Tested-by: chenxiang (M) +Reviewed-by: Saravana Kannan +Signed-off-by: Rafael J. Wysocki +Link: https://lore.kernel.org/r/5722787.lOV4Wx5bFT@kreacher +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Chen Jun +Acked-by: Weilong Chen +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/base/core.c +--- + drivers/base/core.c | 40 ++++++++++++++++++++++++++-------------- + include/linux/device.h | 6 ++---- + 2 files changed, 28 insertions(+), 18 deletions(-) + +diff --git a/drivers/base/core.c b/drivers/base/core.c +index 7066a9451f77..4e7c9df73e8e 100644 +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -68,6 +68,12 @@ void device_links_read_unlock(int idx) + { + srcu_read_unlock(&device_links_srcu, idx); + } ++ ++static void device_link_synchronize_removal(void) ++{ ++ synchronize_srcu(&device_links_srcu); ++} ++ + #else /* !CONFIG_SRCU */ + static DECLARE_RWSEM(device_links_lock); + +@@ -91,6 +97,10 @@ void device_links_read_unlock(int not_used) + { + up_read(&device_links_lock); + } ++ ++static inline void device_link_synchronize_removal(void) ++{ ++} + #endif /* !CONFIG_SRCU */ + + static bool device_is_ancestor(struct device *dev, struct device *target) +@@ -301,8 +311,15 @@ static struct attribute *devlink_attrs[] = { + }; + ATTRIBUTE_GROUPS(devlink); + +-static void device_link_free(struct device_link *link) ++static void device_link_release_fn(struct work_struct *work) + { ++ struct device_link *link = container_of(work, ++ struct device_link, ++ rm_work); ++ ++ /* Ensure that all references to the link object have been dropped. */ ++ device_link_synchronize_removal(); ++ + while (refcount_dec_not_one(&link->rpm_active)) + pm_runtime_put(link->supplier); + +@@ -311,24 +328,19 @@ static void device_link_free(struct device_link *link) + kfree(link); + } + +-#ifdef CONFIG_SRCU +-static void __device_link_free_srcu(struct rcu_head *rhead) +-{ +- device_link_free(container_of(rhead, struct device_link, rcu_head)); +-} +- + static void devlink_dev_release(struct device *dev) + { + struct device_link *link = to_devlink(dev); + +- call_srcu(&device_links_srcu, &link->rcu_head, __device_link_free_srcu); +-} +-#else +-static void devlink_dev_release(struct device *dev) +-{ +- device_link_free(to_devlink(dev)); ++ INIT_WORK(&link->rm_work, device_link_release_fn); ++ /* ++ * It may take a while to complete this work because of the SRCU ++ * synchronization in device_link_release_fn() and if the consumer or ++ * supplier devices get deleted when it runs, so put it into the "long" ++ * workqueue. ++ */ ++ queue_work(system_long_wq, &link->rm_work); + } +-#endif + + static struct class devlink_class = { + .name = "devlink", +diff --git a/include/linux/device.h b/include/linux/device.h +index 18552235be04..21c11dad9cee 100644 +--- a/include/linux/device.h ++++ b/include/linux/device.h +@@ -1086,7 +1086,7 @@ struct rcu_device { + * @flags: Link flags. + * @rpm_active: Whether or not the consumer device is runtime-PM-active. + * @kref: Count repeated addition of the same link. +- * @rcu_head: An RCU head to use for deferred execution of SRCU callbacks. ++ * @rm_work: Work structure used for removing the link. + * @supplier_preactivated: Supplier has been made active before consumer probe. + */ + struct device_link { +@@ -1098,9 +1098,7 @@ struct device_link { + u32 flags; + refcount_t rpm_active; + struct kref kref; +-#ifdef CONFIG_SRCU +- struct rcu_head rcu_head; +-#endif ++ struct work_struct rm_work; + bool supplier_preactivated; /* Owned by consumer probe. */ + #ifndef __GENKSYMS__ + struct device link_dev; +-- +2.27.0 + diff --git a/patches/0443-fix-kabi-broken-due-to-change-of-struct-dev_link.patch b/patches/0443-fix-kabi-broken-due-to-change-of-struct-dev_link.patch new file mode 100644 index 00000000..f176698a --- /dev/null +++ b/patches/0443-fix-kabi-broken-due-to-change-of-struct-dev_link.patch @@ -0,0 +1,41 @@ +From ab40614c7ca0aae7fdbb96ceceb2464fafc5e1e4 Mon Sep 17 00:00:00 2001 +From: YunYi Yang +Date: Mon, 28 Aug 2023 16:23:40 +0800 +Subject: [PATCH 125/256] fix kabi broken due to change of struct dev_link + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +---------------------------------------------------------------------------- + +Commit ("drivers: base: Fix device link removal") +changes the struct dev_link, so we need to fix kabi broken problem. + +Signed-off-by: YunYi Yang +--- + include/linux/device.h | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/include/linux/device.h b/include/linux/device.h +index 21c11dad9cee..9c850a68fd2f 100644 +--- a/include/linux/device.h ++++ b/include/linux/device.h +@@ -1098,10 +1098,13 @@ struct device_link { + u32 flags; + refcount_t rpm_active; + struct kref kref; +- struct work_struct rm_work; ++#ifdef CONFIG_SRCU ++ struct rcu_head rcu_head; ++#endif + bool supplier_preactivated; /* Owned by consumer probe. */ + #ifndef __GENKSYMS__ + struct device link_dev; ++ struct work_struct rm_work; + #endif + }; + +-- +2.27.0 + diff --git a/patches/0444-scsi-megaraid_sas-Rename-scratch_pad-registers.patch b/patches/0444-scsi-megaraid_sas-Rename-scratch_pad-registers.patch new file mode 100644 index 00000000..03647c09 --- /dev/null +++ b/patches/0444-scsi-megaraid_sas-Rename-scratch_pad-registers.patch @@ -0,0 +1,309 @@ +From 04241f652280905aa816185a51802c5588d53333 Mon Sep 17 00:00:00 2001 +From: Shivasharan S +Date: Tue, 16 Oct 2018 23:37:51 -0700 +Subject: [PATCH 126/256] scsi: megaraid_sas: Rename scratch_pad registers + +mainline inclusion +from mainline-v5.0-rc1 +commit 81b7645223ea5935161c69fc022a75928a79ccd0 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=81b7645223ea5935161c69fc022a75928a79ccd0 + +---------------------------------------------------------------------- + +Rename the scratch pad registers to match firmware headers. No functional +change. + +Signed-off-by: Sumit Saxena +Signed-off-by: Shivasharan S +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/megaraid/megaraid_sas_fusion.c +--- + drivers/scsi/megaraid/megaraid_sas.h | 9 ++--- + drivers/scsi/megaraid/megaraid_sas_base.c | 43 +++++++++++---------- + drivers/scsi/megaraid/megaraid_sas_fusion.c | 43 +++++++++++---------- + 3 files changed, 48 insertions(+), 47 deletions(-) + +diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h +index 2398e60c4c5f..efede022367f 100644 +--- a/drivers/scsi/megaraid/megaraid_sas.h ++++ b/drivers/scsi/megaraid/megaraid_sas.h +@@ -1592,11 +1592,10 @@ struct megasas_register_set { + + u32 reserved_3[3]; /*00A4h*/ + +- u32 outbound_scratch_pad ; /*00B0h*/ +- u32 outbound_scratch_pad_2; /*00B4h*/ +- u32 outbound_scratch_pad_3; /*00B8h*/ +- u32 outbound_scratch_pad_4; /*00BCh*/ +- ++ u32 outbound_scratch_pad_0; /*00B0h*/ ++ u32 outbound_scratch_pad_1; /*00B4h*/ ++ u32 outbound_scratch_pad_2; /*00B8h*/ ++ u32 outbound_scratch_pad_3; /*00BCh*/ + + u32 inbound_low_queue_port ; /*00C0h*/ + +diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c +index 3f0752dc8ab5..483730abd4da 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_base.c ++++ b/drivers/scsi/megaraid/megaraid_sas_base.c +@@ -602,7 +602,7 @@ megasas_disable_intr_ppc(struct megasas_instance *instance) + static u32 + megasas_read_fw_status_reg_ppc(struct megasas_register_set __iomem * regs) + { +- return readl(&(regs)->outbound_scratch_pad); ++ return readl(&(regs)->outbound_scratch_pad_0); + } + + /** +@@ -727,7 +727,7 @@ megasas_disable_intr_skinny(struct megasas_instance *instance) + static u32 + megasas_read_fw_status_reg_skinny(struct megasas_register_set __iomem *regs) + { +- return readl(&(regs)->outbound_scratch_pad); ++ return readl(&(regs)->outbound_scratch_pad_0); + } + + /** +@@ -872,7 +872,7 @@ megasas_disable_intr_gen2(struct megasas_instance *instance) + static u32 + megasas_read_fw_status_reg_gen2(struct megasas_register_set __iomem *regs) + { +- return readl(&(regs)->outbound_scratch_pad); ++ return readl(&(regs)->outbound_scratch_pad_0); + } + + /** +@@ -5222,7 +5222,7 @@ static int megasas_init_fw(struct megasas_instance *instance) + { + u32 max_sectors_1; + u32 max_sectors_2, tmp_sectors, msix_enable; +- u32 scratch_pad_2, scratch_pad_3, scratch_pad_4, status_reg; ++ u32 scratch_pad_1, scratch_pad_2, scratch_pad_3, status_reg; + resource_size_t base_addr; + struct megasas_register_set __iomem *reg_set; + struct megasas_ctrl_info *ctrl_info = NULL; +@@ -5318,9 +5318,9 @@ static int megasas_init_fw(struct megasas_instance *instance) + fusion = instance->ctrl_context; + + if (instance->adapter_type == VENTURA_SERIES) { +- scratch_pad_3 = +- readl(&instance->reg_set->outbound_scratch_pad_3); +- instance->max_raid_mapsize = ((scratch_pad_3 >> ++ scratch_pad_2 = ++ readl(&instance->reg_set->outbound_scratch_pad_2); ++ instance->max_raid_mapsize = ((scratch_pad_2 >> + MR_MAX_RAID_MAP_SIZE_OFFSET_SHIFT) & + MR_MAX_RAID_MAP_SIZE_MASK); + } +@@ -5331,17 +5331,17 @@ static int megasas_init_fw(struct megasas_instance *instance) + if (msix_enable && !msix_disable) { + int irq_flags = PCI_IRQ_MSIX; + +- scratch_pad_2 = readl +- (&instance->reg_set->outbound_scratch_pad_2); ++ scratch_pad_1 = readl ++ (&instance->reg_set->outbound_scratch_pad_1); + /* Check max MSI-X vectors */ + if (fusion) { + if (instance->adapter_type == THUNDERBOLT_SERIES) { + /* Thunderbolt Series*/ +- instance->msix_vectors = (scratch_pad_2 ++ instance->msix_vectors = (scratch_pad_1 + & MR_MAX_REPLY_QUEUES_OFFSET) + 1; + fw_msix_count = instance->msix_vectors; + } else { +- instance->msix_vectors = ((scratch_pad_2 ++ instance->msix_vectors = ((scratch_pad_1 + & MR_MAX_REPLY_QUEUES_EXT_OFFSET) + >> MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT) + 1; + +@@ -5365,8 +5365,9 @@ static int megasas_init_fw(struct megasas_instance *instance) + } + + if (rdpq_enable) +- instance->is_rdpq = (scratch_pad_2 & MR_RDPQ_MODE_OFFSET) ? +- 1 : 0; ++ instance->is_rdpq = ++ (scratch_pad_1 & MR_RDPQ_MODE_OFFSET) ? ++ 1 : 0; + fw_msix_count = instance->msix_vectors; + /* Save 1-15 reply post index address to local memory + * Index 0 is already saved from reg offset +@@ -5441,12 +5442,12 @@ static int megasas_init_fw(struct megasas_instance *instance) + goto fail_init_adapter; + + if (instance->adapter_type == VENTURA_SERIES) { +- scratch_pad_4 = +- readl(&instance->reg_set->outbound_scratch_pad_4); +- if ((scratch_pad_4 & MR_NVME_PAGE_SIZE_MASK) >= ++ scratch_pad_3 = ++ readl(&instance->reg_set->outbound_scratch_pad_3); ++ if ((scratch_pad_3 & MR_NVME_PAGE_SIZE_MASK) >= + MR_DEFAULT_NVME_PAGE_SHIFT) + instance->nvme_page_size = +- (1 << (scratch_pad_4 & MR_NVME_PAGE_SIZE_MASK)); ++ (1 << (scratch_pad_3 & MR_NVME_PAGE_SIZE_MASK)); + + dev_info(&instance->pdev->dev, + "NVME page size\t: (%d)\n", instance->nvme_page_size); +@@ -6075,7 +6076,7 @@ megasas_set_dma_mask(struct megasas_instance *instance) + { + u64 consistent_mask; + struct pci_dev *pdev; +- u32 scratch_pad_2; ++ u32 scratch_pad_1; + + pdev = instance->pdev; + consistent_mask = (instance->adapter_type == VENTURA_SERIES) ? +@@ -6093,10 +6094,10 @@ megasas_set_dma_mask(struct megasas_instance *instance) + * If 32 bit DMA mask fails, then try for 64 bit mask + * for FW capable of handling 64 bit DMA. + */ +- scratch_pad_2 = readl +- (&instance->reg_set->outbound_scratch_pad_2); ++ scratch_pad_1 = readl ++ (&instance->reg_set->outbound_scratch_pad_1); + +- if (!(scratch_pad_2 & MR_CAN_HANDLE_64_BIT_DMA_OFFSET)) ++ if (!(scratch_pad_1 & MR_CAN_HANDLE_64_BIT_DMA_OFFSET)) + goto fail_set_dma_mask; + else if (dma_set_mask_and_coherent(&pdev->dev, + DMA_BIT_MASK(63))) +diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c +index f45c54f02bfa..299cfb83fb49 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c ++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c +@@ -262,10 +262,10 @@ megasas_fusion_update_can_queue(struct megasas_instance *instance, int fw_boot_c + + reg_set = instance->reg_set; + +- /* ventura FW does not fill outbound_scratch_pad_3 with queue depth */ ++ /* ventura FW does not fill outbound_scratch_pad_2 with queue depth */ + if (instance->adapter_type < VENTURA_SERIES) + cur_max_fw_cmds = +- readl(&instance->reg_set->outbound_scratch_pad_3) & 0x00FFFF; ++ readl(&instance->reg_set->outbound_scratch_pad_2) & 0x00FFFF; + + if (dual_qdepth_disable || !cur_max_fw_cmds) + cur_max_fw_cmds = instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF; +@@ -974,7 +974,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) + struct megasas_header *frame_hdr; + const char *sys_info; + MFI_CAPABILITIES *drv_ops; +- u32 scratch_pad_2; ++ u32 scratch_pad_1; + ktime_t time; + bool cur_fw_64bit_dma_capable; + +@@ -985,14 +985,15 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) + + cmd = fusion->ioc_init_cmd; + +- scratch_pad_2 = readl +- (&instance->reg_set->outbound_scratch_pad_2); ++ scratch_pad_1 = readl ++ (&instance->reg_set->outbound_scratch_pad_1); + +- cur_rdpq_mode = (scratch_pad_2 & MR_RDPQ_MODE_OFFSET) ? 1 : 0; ++ cur_rdpq_mode = (scratch_pad_1 & MR_RDPQ_MODE_OFFSET) ? 1 : 0; + + if (instance->adapter_type == INVADER_SERIES) { + cur_fw_64bit_dma_capable = +- (scratch_pad_2 & MR_CAN_HANDLE_64_BIT_DMA_OFFSET) ? true : false; ++ (scratch_pad_1 & MR_CAN_HANDLE_64_BIT_DMA_OFFSET) ? ++ true : false; + + if (instance->consistent_mask_64bit && !cur_fw_64bit_dma_capable) { + dev_err(&instance->pdev->dev, "Driver was operating on 64bit " +@@ -1010,7 +1011,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) + goto fail_fw_init; + } + +- instance->fw_sync_cache_support = (scratch_pad_2 & ++ instance->fw_sync_cache_support = (scratch_pad_1 & + MR_CAN_HANDLE_SYNC_CACHE_OFFSET) ? 1 : 0; + dev_info(&instance->pdev->dev, "FW supports sync cache\t: %s\n", + instance->fw_sync_cache_support ? "Yes" : "No"); +@@ -1642,7 +1643,7 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) + { + struct megasas_register_set __iomem *reg_set; + struct fusion_context *fusion; +- u32 scratch_pad_2; ++ u32 scratch_pad_1; + int i = 0, count; + + fusion = instance->ctrl_context; +@@ -1659,20 +1660,20 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) + + megasas_configure_queue_sizes(instance); + +- scratch_pad_2 = readl(&instance->reg_set->outbound_scratch_pad_2); +- /* If scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_UNITS_MASK is set, ++ scratch_pad_1 = readl(&instance->reg_set->outbound_scratch_pad_1); ++ /* If scratch_pad_1 & MEGASAS_MAX_CHAIN_SIZE_UNITS_MASK is set, + * Firmware support extended IO chain frame which is 4 times more than + * legacy Firmware. + * Legacy Firmware - Frame size is (8 * 128) = 1K + * 1M IO Firmware - Frame size is (8 * 128 * 4) = 4K + */ +- if (scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_UNITS_MASK) ++ if (scratch_pad_1 & MEGASAS_MAX_CHAIN_SIZE_UNITS_MASK) + instance->max_chain_frame_sz = +- ((scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_MASK) >> ++ ((scratch_pad_1 & MEGASAS_MAX_CHAIN_SIZE_MASK) >> + MEGASAS_MAX_CHAIN_SHIFT) * MEGASAS_1MB_IO; + else + instance->max_chain_frame_sz = +- ((scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_MASK) >> ++ ((scratch_pad_1 & MEGASAS_MAX_CHAIN_SIZE_MASK) >> + MEGASAS_MAX_CHAIN_SHIFT) * MEGASAS_256K_IO; + + if (instance->max_chain_frame_sz < MEGASAS_CHAIN_FRAME_SZ_MIN) { +@@ -3694,7 +3695,7 @@ megasas_release_fusion(struct megasas_instance *instance) + static u32 + megasas_read_fw_status_reg_fusion(struct megasas_register_set __iomem *regs) + { +- return readl(&(regs)->outbound_scratch_pad); ++ return readl(&(regs)->outbound_scratch_pad_0); + } + + /** +@@ -4777,8 +4778,8 @@ void megasas_fusion_crash_dump_wq(struct work_struct *work) + "crash dump and initiating OCR\n"); + status_reg |= MFI_STATE_CRASH_DUMP_DONE; + writel(status_reg, +- &instance->reg_set->outbound_scratch_pad); +- readl(&instance->reg_set->outbound_scratch_pad); ++ &instance->reg_set->outbound_scratch_pad_0); ++ readl(&instance->reg_set->outbound_scratch_pad_0); + return; + } + megasas_alloc_host_crash_buffer(instance); +@@ -4809,13 +4810,13 @@ void megasas_fusion_crash_dump_wq(struct work_struct *work) + instance->fw_crash_buffer_size = instance->drv_buf_index; + instance->fw_crash_state = AVAILABLE; + instance->drv_buf_index = 0; +- writel(status_reg, &instance->reg_set->outbound_scratch_pad); +- readl(&instance->reg_set->outbound_scratch_pad); ++ writel(status_reg, &instance->reg_set->outbound_scratch_pad_0); ++ readl(&instance->reg_set->outbound_scratch_pad_0); + if (!partial_copy) + megasas_reset_fusion(instance->host, 0); + } else { +- writel(status_reg, &instance->reg_set->outbound_scratch_pad); +- readl(&instance->reg_set->outbound_scratch_pad); ++ writel(status_reg, &instance->reg_set->outbound_scratch_pad_0); ++ readl(&instance->reg_set->outbound_scratch_pad_0); + } + } + +-- +2.27.0 + diff --git a/patches/0445-scsi-megaraid_sas-Introduce-new-Aero-adapter-type.patch b/patches/0445-scsi-megaraid_sas-Introduce-new-Aero-adapter-type.patch new file mode 100644 index 00000000..2db1fbd1 --- /dev/null +++ b/patches/0445-scsi-megaraid_sas-Introduce-new-Aero-adapter-type.patch @@ -0,0 +1,90 @@ +From 458fecd942896e988042f1b31a41ccc4b2758bef Mon Sep 17 00:00:00 2001 +From: Shivasharan S +Date: Mon, 17 Dec 2018 00:47:38 -0800 +Subject: [PATCH 127/256] scsi: megaraid_sas: Introduce new Aero adapter type + +mainline inclusion +from mainline-v5.0-rc1 +commit 154a7cde9a895d87ecc9807b34651021d3e6e8a7 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=154a7cde9a895d87ecc9807b34651021d3e6e8a7 + +---------------------------------------------------------------------- + +Identify all Aero controller PCI IDs with new adapter type. + +Signed-off-by: Shivasharan S +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/megaraid/megaraid_sas.h | 1 + + drivers/scsi/megaraid/megaraid_sas_base.c | 18 ++++++++++++------ + 2 files changed, 13 insertions(+), 6 deletions(-) + +diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h +index efede022367f..1ecb2b6cad5e 100644 +--- a/drivers/scsi/megaraid/megaraid_sas.h ++++ b/drivers/scsi/megaraid/megaraid_sas.h +@@ -1553,6 +1553,7 @@ enum MR_ADAPTER_TYPE { + THUNDERBOLT_SERIES = 2, + INVADER_SERIES = 3, + VENTURA_SERIES = 4, ++ AERO_SERIES = 5, + }; + + /* +diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c +index 483730abd4da..355cc094af07 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_base.c ++++ b/drivers/scsi/megaraid/megaraid_sas_base.c +@@ -5358,6 +5358,7 @@ static int megasas_init_fw(struct megasas_instance *instance) + if (instance->msix_vectors > 8) + instance->msix_combined = true; + break; ++ case AERO_SERIES: + case VENTURA_SERIES: + if (instance->msix_vectors > 16) + instance->msix_combined = true; +@@ -6126,12 +6127,14 @@ megasas_set_dma_mask(struct megasas_instance *instance) + /* + * megasas_set_adapter_type - Set adapter type. + * Supported controllers can be divided in +- * 4 categories- enum MR_ADAPTER_TYPE { +- * MFI_SERIES = 1, +- * THUNDERBOLT_SERIES = 2, +- * INVADER_SERIES = 3, +- * VENTURA_SERIES = 4, +- * }; ++ * different categories- ++ * enum MR_ADAPTER_TYPE { ++ * MFI_SERIES = 1, ++ * THUNDERBOLT_SERIES = 2, ++ * INVADER_SERIES = 3, ++ * VENTURA_SERIES = 4, ++ * AERO_SERIES = 5, ++ * }; + * @instance: Adapter soft state + * return: void + */ +@@ -6146,6 +6149,8 @@ static inline void megasas_set_adapter_type(struct megasas_instance *instance) + case PCI_DEVICE_ID_LSI_AERO_10E2: + case PCI_DEVICE_ID_LSI_AERO_10E5: + case PCI_DEVICE_ID_LSI_AERO_10E6: ++ instance->adapter_type = AERO_SERIES; ++ break; + case PCI_DEVICE_ID_LSI_VENTURA: + case PCI_DEVICE_ID_LSI_CRUSADER: + case PCI_DEVICE_ID_LSI_HARPOON: +@@ -6213,6 +6218,7 @@ static int megasas_alloc_ctrl_mem(struct megasas_instance *instance) + if (megasas_alloc_mfi_ctrl_mem(instance)) + goto fail; + break; ++ case AERO_SERIES: + case VENTURA_SERIES: + case THUNDERBOLT_SERIES: + case INVADER_SERIES: +-- +2.27.0 + diff --git a/patches/0446-scsi-megaraid_sas-Load-balance-completions-across-al.patch b/patches/0446-scsi-megaraid_sas-Load-balance-completions-across-al.patch new file mode 100644 index 00000000..8769e1bd --- /dev/null +++ b/patches/0446-scsi-megaraid_sas-Load-balance-completions-across-al.patch @@ -0,0 +1,192 @@ +From ca0bd9913da84d7665466434c78657636d2714c1 Mon Sep 17 00:00:00 2001 +From: Shivasharan S +Date: Tue, 7 May 2019 10:05:36 -0700 +Subject: [PATCH 128/256] scsi: megaraid_sas: Load balance completions across + all MSI-X + +mainline inclusion +from mainline-v5.3-rc1 +commit 1d15d9098ad12b0021ac5a6b851f26d1ab021e5a +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1d15d9098ad12b0021ac5a6b851f26d1ab021e5a + +---------------------------------------------------------------------- + +Driver will use "reply descriptor post queues" in round robin fashion when +the combined MSI-X mode is not enabled. With this IO completions are +distributed and load balanced across all the available reply descriptor +post queues equally. + +This is enabled only if combined MSI-X mode is not enabled in firmware. +This improves performance and also fixes soft lockups. + +When load balancing is enabled, IRQ affinity from driver needs to be +disabled. + +Signed-off-by: Kashyap Desai +Signed-off-by: Shivasharan S +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/megaraid/megaraid_sas_base.c +--- + drivers/scsi/megaraid/megaraid_sas.h | 3 +++ + drivers/scsi/megaraid/megaraid_sas_base.c | 22 +++++++++++++++++---- + drivers/scsi/megaraid/megaraid_sas_fusion.c | 20 +++++++++++++++---- + 3 files changed, 37 insertions(+), 8 deletions(-) + +diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h +index 1ecb2b6cad5e..b57db3fe8447 100644 +--- a/drivers/scsi/megaraid/megaraid_sas.h ++++ b/drivers/scsi/megaraid/megaraid_sas.h +@@ -2197,6 +2197,7 @@ struct megasas_instance { + u32 secure_jbod_support; + u32 support_morethan256jbod; /* FW support for more than 256 PD/JBOD */ + bool use_seqnum_jbod_fp; /* Added for PD sequence */ ++ bool smp_affinity_enable; + spinlock_t crashdump_lock; + + struct megasas_register_set __iomem *reg_set; +@@ -2214,6 +2215,7 @@ struct megasas_instance { + u16 ldio_threshold; + u16 cur_can_queue; + u32 max_sectors_per_req; ++ bool msix_load_balance; + struct megasas_aen_event *ev; + + struct megasas_cmd **cmd_list; +@@ -2250,6 +2252,7 @@ struct megasas_instance { + atomic_t sge_holes_type1; + atomic_t sge_holes_type2; + atomic_t sge_holes_type3; ++ atomic64_t total_io_count; + + struct megasas_instance_template *instancet; + struct tasklet_struct isr_tasklet; +diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c +index 355cc094af07..476e06df9067 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_base.c ++++ b/drivers/scsi/megaraid/megaraid_sas_base.c +@@ -5104,6 +5104,7 @@ megasas_setup_irqs_msix(struct megasas_instance *instance, u8 is_probe) + &instance->irq_context[j]); + /* Retry irq register for IO_APIC*/ + instance->msix_vectors = 0; ++ instance->msix_load_balance = false; + if (is_probe) { + pci_free_irq_vectors(instance->pdev); + return megasas_setup_irqs_ioapic(instance); +@@ -5112,6 +5113,7 @@ megasas_setup_irqs_msix(struct megasas_instance *instance, u8 is_probe) + } + } + } ++ + return 0; + } + +@@ -5369,6 +5371,12 @@ static int megasas_init_fw(struct megasas_instance *instance) + instance->is_rdpq = + (scratch_pad_1 & MR_RDPQ_MODE_OFFSET) ? + 1 : 0; ++ ++ if (!instance->msix_combined) { ++ instance->msix_load_balance = true; ++ instance->smp_affinity_enable = false; ++ } ++ + fw_msix_count = instance->msix_vectors; + /* Save 1-15 reply post index address to local memory + * Index 0 is already saved from reg offset +@@ -5387,17 +5395,20 @@ static int megasas_init_fw(struct megasas_instance *instance) + instance->msix_vectors); + } else /* MFI adapters */ + instance->msix_vectors = 1; ++ + /* Don't bother allocating more MSI-X vectors than cpus */ + instance->msix_vectors = min(instance->msix_vectors, + (unsigned int)num_online_cpus()); +- if (smp_affinity_enable) ++ if (instance->smp_affinity_enable) + irq_flags |= PCI_IRQ_AFFINITY; + i = pci_alloc_irq_vectors(instance->pdev, 1, + instance->msix_vectors, irq_flags); +- if (i > 0) ++ if (i > 0) { + instance->msix_vectors = i; +- else ++ } else { + instance->msix_vectors = 0; ++ instance->msix_load_balance = false; ++ } + } + /* + * MSI-X host index 0 is common for all adapter. +@@ -6461,6 +6472,7 @@ static inline void megasas_init_ctrl_params(struct megasas_instance *instance) + INIT_LIST_HEAD(&instance->internal_reset_pending_q); + + atomic_set(&instance->fw_outstanding, 0); ++ atomic64_set(&instance->total_io_count, 0); + + init_waitqueue_head(&instance->int_cmd_wait_q); + init_waitqueue_head(&instance->abort_cmd_wait_q); +@@ -6483,6 +6495,8 @@ static inline void megasas_init_ctrl_params(struct megasas_instance *instance) + instance->last_time = 0; + instance->disableOnlineCtrlReset = 1; + instance->UnevenSpanSupport = 0; ++ instance->smp_affinity_enable = smp_affinity_enable ? true : false; ++ instance->msix_load_balance = false; + + if (instance->adapter_type != MFI_SERIES) { + INIT_WORK(&instance->work_init, megasas_fusion_ocr_wq); +@@ -6839,7 +6853,7 @@ megasas_resume(struct pci_dev *pdev) + /* Now re-enable MSI-X */ + if (instance->msix_vectors) { + irq_flags = PCI_IRQ_MSIX; +- if (smp_affinity_enable) ++ if (instance->smp_affinity_enable) + irq_flags |= PCI_IRQ_AFFINITY; + } + rval = pci_alloc_irq_vectors(instance->pdev, 1, +diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c +index 299cfb83fb49..17907ce629cf 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c ++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c +@@ -2641,8 +2641,14 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, + fp_possible = (io_info.fpOkForIo > 0) ? true : false; + } + +- cmd->request_desc->SCSIIO.MSIxIndex = +- instance->reply_map[raw_smp_processor_id()]; ++ if (instance->msix_load_balance) ++ cmd->request_desc->SCSIIO.MSIxIndex = ++ (mega_mod64(atomic64_add_return(1, ++ &instance->total_io_count), ++ instance->msix_vectors)); ++ else ++ cmd->request_desc->SCSIIO.MSIxIndex = ++ instance->reply_map[raw_smp_processor_id()]; + + praid_context = &io_request->RaidContext; + +@@ -2969,8 +2975,14 @@ megasas_build_syspd_fusion(struct megasas_instance *instance, + + cmd->request_desc->SCSIIO.DevHandle = io_request->DevHandle; + +- cmd->request_desc->SCSIIO.MSIxIndex = +- instance->reply_map[raw_smp_processor_id()]; ++ if (instance->msix_load_balance) ++ cmd->request_desc->SCSIIO.MSIxIndex = ++ (mega_mod64(atomic64_add_return(1, ++ &instance->total_io_count), ++ instance->msix_vectors)); ++ else ++ cmd->request_desc->SCSIIO.MSIxIndex = ++ instance->reply_map[raw_smp_processor_id()]; + + if (!fp_possible) { + /* system pd firmware path */ +-- +2.27.0 + diff --git a/patches/0447-scsi-megaraid_sas-RAID1-PCI-bandwidth-limit-algorith.patch b/patches/0447-scsi-megaraid_sas-RAID1-PCI-bandwidth-limit-algorith.patch new file mode 100644 index 00000000..068ead35 --- /dev/null +++ b/patches/0447-scsi-megaraid_sas-RAID1-PCI-bandwidth-limit-algorith.patch @@ -0,0 +1,118 @@ +From d34c68a266669b71a439888d5cac9452344a66fc Mon Sep 17 00:00:00 2001 +From: Chandrakanth Patil +Date: Tue, 25 Jun 2019 16:34:28 +0530 +Subject: [PATCH 129/256] scsi: megaraid_sas: RAID1 PCI bandwidth limit + algorithm is applicable for only Ventura + +mainline inclusion +from mainline-v5.3-rc1 +commit 49f2bf1071f06a430920888ff2d1a89395a3b6b5 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=49f2bf1071f06a430920888ff2d1a89395a3b6b5 + +---------------------------------------------------------------------- + +RAID1 PCI bandwidth limit algorithm is not applicable to Aero as it's PCIe +Gen4 adapter. + +Signed-off-by: Sumit Saxena +Signed-off-by: Chandrakanth Patil +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/megaraid/megaraid_sas_fusion.c +--- + drivers/scsi/megaraid/megaraid_sas_base.c | 3 +++ + drivers/scsi/megaraid/megaraid_sas_fusion.c | 24 +++++++++++---------- + drivers/scsi/megaraid/megaraid_sas_fusion.h | 2 +- + 3 files changed, 17 insertions(+), 12 deletions(-) + +diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c +index 476e06df9067..3b9448b486e8 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_base.c ++++ b/drivers/scsi/megaraid/megaraid_sas_base.c +@@ -5327,6 +5327,9 @@ static int megasas_init_fw(struct megasas_instance *instance) + MR_MAX_RAID_MAP_SIZE_MASK); + } + ++ if (instance->adapter_type == VENTURA_SERIES) ++ fusion->pcie_bw_limitation = true; ++ + /* Check if MSI-X is supported while in ready state */ + msix_enable = (instance->instancet->read_fw_status_reg(reg_set) & + 0x4000000) >> 0x1a; +diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c +index 17907ce629cf..e4f644ae06a1 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c ++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c +@@ -2451,9 +2451,10 @@ static void megasas_stream_detect(struct megasas_instance *instance, + * + */ + static void +-megasas_set_raidflag_cpu_affinity(union RAID_CONTEXT_UNION *praid_context, +- struct MR_LD_RAID *raid, bool fp_possible, +- u8 is_read, u32 scsi_buff_len) ++megasas_set_raidflag_cpu_affinity(struct fusion_context *fusion, ++ union RAID_CONTEXT_UNION *praid_context, ++ struct MR_LD_RAID *raid, bool fp_possible, ++ u8 is_read, u32 scsi_buff_len) + { + u8 cpu_sel = MR_RAID_CTX_CPUSEL_0; + struct RAID_CONTEXT_G35 *rctx_g35; +@@ -2511,11 +2512,11 @@ megasas_set_raidflag_cpu_affinity(union RAID_CONTEXT_UNION *praid_context, + * vs MR_RAID_FLAGS_IO_SUB_TYPE_CACHE_BYPASS. + * IO Subtype is not bitmap. + */ +- if ((raid->level == 1) && (!is_read)) { +- if (scsi_buff_len > MR_LARGE_IO_MIN_SIZE) +- praid_context->raid_context_g35.raid_flags = +- (MR_RAID_FLAGS_IO_SUB_TYPE_LDIO_BW_LIMIT +- << MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT); ++ if ((fusion->pcie_bw_limitation) && (raid->level == 1) && (!is_read) && ++ (scsi_buff_len > MR_LARGE_IO_MIN_SIZE)) { ++ praid_context->raid_context_g35.raid_flags = ++ (MR_RAID_FLAGS_IO_SUB_TYPE_LDIO_BW_LIMIT ++ << MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT); + } + } + +@@ -2668,8 +2669,9 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, + (instance->host->can_queue)) { + fp_possible = false; + atomic_dec(&instance->fw_outstanding); +- } else if ((scsi_buff_len > MR_LARGE_IO_MIN_SIZE) || +- (atomic_dec_if_positive(&mrdev_priv->r1_ldio_hint) > 0)) { ++ } else if (fusion->pcie_bw_limitation && ++ ((scsi_buff_len > MR_LARGE_IO_MIN_SIZE) || ++ (atomic_dec_if_positive(&mrdev_priv->r1_ldio_hint) > 0))) { + fp_possible = false; + atomic_dec(&instance->fw_outstanding); + if (scsi_buff_len > MR_LARGE_IO_MIN_SIZE) +@@ -2694,7 +2696,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, + + /* If raid is NULL, set CPU affinity to default CPU0 */ + if (raid) +- megasas_set_raidflag_cpu_affinity(praid_context, ++ megasas_set_raidflag_cpu_affinity(fusion, praid_context, + raid, fp_possible, io_info.isRead, + scsi_buff_len); + else +diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h +index 8e5ebee6517f..68517cb7342b 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_fusion.h ++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h +@@ -1333,7 +1333,7 @@ struct fusion_context { + dma_addr_t ioc_init_request_phys; + struct MPI2_IOC_INIT_REQUEST *ioc_init_request; + struct megasas_cmd *ioc_init_cmd; +- ++ bool pcie_bw_limitation; + }; + + union desc_value { +-- +2.27.0 + diff --git a/patches/0448-scsi-megaraid_sas-Add-support-for-High-IOPS-queues.patch b/patches/0448-scsi-megaraid_sas-Add-support-for-High-IOPS-queues.patch new file mode 100644 index 00000000..1a3bc32e --- /dev/null +++ b/patches/0448-scsi-megaraid_sas-Add-support-for-High-IOPS-queues.patch @@ -0,0 +1,299 @@ +From b77d9a092660443c4023ae782c00f180c19bde3e Mon Sep 17 00:00:00 2001 +From: Chandrakanth Patil +Date: Tue, 25 Jun 2019 16:34:31 +0530 +Subject: [PATCH 130/256] scsi: megaraid_sas: Add support for High IOPS queues + +mainline inclusion +from mainline-v5.3-rc1 +commit 132147d7f620eed4a7bee815eba03561258fc21e +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=132147d7f620eed4a7bee815eba03561258fc21e + +---------------------------------------------------------------------- + +Aero controllers support balanced performance mode through the ability to +configure queues with different properties. + +Reply queues with interrupt coalescing enabled are called "high iops reply +queues" and reply queues with interrupt coalescing disabled are called "low +latency reply queues". + +The driver configures a combination of high iops and low latency reply +queues if: + + - HBA is an AERO controller; + + - MSI-X vectors supported by the HBA is 128; + + - Total CPU count in the system more than high iops queue count; + + - Driver is loaded with default max_msix_vectors module parameter; and + + - System booted in non-kdump mode. + +Signed-off-by: Kashyap Desai +Signed-off-by: Chandrakanth Patil +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/megaraid/megaraid_sas.h + drivers/scsi/megaraid/megaraid_sas_base.c +--- + drivers/scsi/megaraid/megaraid_sas.h | 6 + + drivers/scsi/megaraid/megaraid_sas_base.c | 139 +++++++++++++++++--- + drivers/scsi/megaraid/megaraid_sas_fusion.c | 11 ++ + 3 files changed, 139 insertions(+), 17 deletions(-) + +diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h +index b57db3fe8447..581188ce3042 100644 +--- a/drivers/scsi/megaraid/megaraid_sas.h ++++ b/drivers/scsi/megaraid/megaraid_sas.h +@@ -1547,6 +1547,7 @@ enum FW_BOOT_CONTEXT { + #define MR_CAN_HANDLE_SYNC_CACHE_OFFSET 0X01000000 + + #define MR_CAN_HANDLE_64_BIT_DMA_OFFSET (1 << 25) ++#define MR_INTR_COALESCING_SUPPORT_OFFSET (1 << 26) + + enum MR_ADAPTER_TYPE { + MFI_SERIES = 1, +@@ -2147,6 +2148,9 @@ enum MR_PD_TYPE { + #define MR_DEFAULT_NVME_MDTS_KB 128 + #define MR_NVME_PAGE_SIZE_MASK 0x000000FF + ++/*Aero performance parameters*/ ++#define MR_HIGH_IOPS_QUEUE_COUNT 8 ++ + struct megasas_instance { + + unsigned int *reply_map; +@@ -2317,6 +2321,8 @@ struct megasas_instance { + bool support_nvme_passthru; + u8 task_abort_tmo; + u8 max_reset_tmo; ++ u8 low_latency_index_start; ++ bool balanced_mode; + }; + struct MR_LD_VF_MAP { + u32 size; +diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c +index 3b9448b486e8..35850ba8f071 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_base.c ++++ b/drivers/scsi/megaraid/megaraid_sas_base.c +@@ -5070,6 +5070,8 @@ megasas_setup_irqs_ioapic(struct megasas_instance *instance) + __func__, __LINE__); + return -1; + } ++ instance->balanced_mode = false; ++ instance->low_latency_index_start = 0; + return 0; + } + +@@ -5196,9 +5198,12 @@ megasas_setup_jbod_map(struct megasas_instance *instance) + static void megasas_setup_reply_map(struct megasas_instance *instance) + { + const struct cpumask *mask; +- unsigned int queue, cpu; ++ unsigned int queue, cpu, low_latency_index_start; + +- for (queue = 0; queue < instance->msix_vectors; queue++) { ++ low_latency_index_start = instance->low_latency_index_start; ++ ++ for (queue = low_latency_index_start; ++ queue < instance->msix_vectors; queue++) { + mask = pci_irq_get_affinity(instance->pdev, queue); + if (!mask) + goto fallback; +@@ -5209,8 +5214,75 @@ static void megasas_setup_reply_map(struct megasas_instance *instance) + return; + + fallback: +- for_each_possible_cpu(cpu) +- instance->reply_map[cpu] = cpu % instance->msix_vectors; ++ queue = low_latency_index_start; ++ for_each_possible_cpu(cpu) { ++ instance->reply_map[cpu] = queue; ++ if (queue == (instance->msix_vectors - 1)) ++ queue = low_latency_index_start; ++ else ++ queue++; ++ } ++} ++ ++static int ++__megasas_alloc_irq_vectors(struct megasas_instance *instance) ++{ ++ int i, irq_flags; ++ struct irq_affinity desc = { .pre_vectors = ++ instance->low_latency_index_start }; ++ struct irq_affinity *descp = &desc; ++ ++ irq_flags = PCI_IRQ_MSIX; ++ ++ if (instance->smp_affinity_enable) ++ irq_flags |= PCI_IRQ_AFFINITY; ++ else ++ descp = NULL; ++ ++ i = pci_alloc_irq_vectors_affinity(instance->pdev, ++ instance->low_latency_index_start, ++ instance->msix_vectors, irq_flags, descp); ++ ++ return i; ++} ++ ++/** ++ * megasas_alloc_irq_vectors - Allocate IRQ vectors/enable MSI-x vectors ++ * @instance: Adapter soft state ++ * return: void ++ */ ++static void ++megasas_alloc_irq_vectors(struct megasas_instance *instance) ++{ ++ int i; ++ unsigned int num_msix_req; ++ ++ i = __megasas_alloc_irq_vectors(instance); ++ ++ if (instance->balanced_mode && (i != instance->msix_vectors)) { ++ if (instance->msix_vectors) ++ pci_free_irq_vectors(instance->pdev); ++ /* Disable Balanced IOPS mode and try realloc vectors */ ++ instance->balanced_mode = false; ++ instance->low_latency_index_start = 1; ++ num_msix_req = num_online_cpus() + ++ instance->low_latency_index_start; ++ ++ instance->msix_vectors = min(num_msix_req, ++ instance->msix_vectors); ++ ++ i = __megasas_alloc_irq_vectors(instance); ++ ++ } ++ ++ dev_info(&instance->pdev->dev, ++ "requested/available msix %d/%d\n", instance->msix_vectors, i); ++ ++ if (i > 0) ++ instance->msix_vectors = i; ++ else ++ instance->msix_vectors = 0; ++ + } + + /** +@@ -5233,6 +5305,8 @@ static int megasas_init_fw(struct megasas_instance *instance) + struct IOV_111 *iovPtr; + struct fusion_context *fusion; + bool do_adp_reset = true; ++ bool intr_coalescing; ++ unsigned int num_msix_req; + + fusion = instance->ctrl_context; + +@@ -5334,7 +5408,6 @@ static int megasas_init_fw(struct megasas_instance *instance) + msix_enable = (instance->instancet->read_fw_status_reg(reg_set) & + 0x4000000) >> 0x1a; + if (msix_enable && !msix_disable) { +- int irq_flags = PCI_IRQ_MSIX; + + scratch_pad_1 = readl + (&instance->reg_set->outbound_scratch_pad_1); +@@ -5399,19 +5472,51 @@ static int megasas_init_fw(struct megasas_instance *instance) + } else /* MFI adapters */ + instance->msix_vectors = 1; + +- /* Don't bother allocating more MSI-X vectors than cpus */ +- instance->msix_vectors = min(instance->msix_vectors, +- (unsigned int)num_online_cpus()); +- if (instance->smp_affinity_enable) +- irq_flags |= PCI_IRQ_AFFINITY; +- i = pci_alloc_irq_vectors(instance->pdev, 1, +- instance->msix_vectors, irq_flags); +- if (i > 0) { +- instance->msix_vectors = i; +- } else { +- instance->msix_vectors = 0; ++ ++ /* ++ * For Aero (if some conditions are met), driver will configure ++ * a few additional reply queues with interrupt coalescing ++ * enabled. These queues with interrupt coalescing enabled are ++ * called High IOPS queues and rest of reply queues (based on ++ * number of logical CPUs) are termed as Low latency queues. ++ * ++ * Total Number of reply queues = High IOPS queues ++ * + low latency queues ++ * ++ * For rest of fusion adapters, 1 additional reply queue will be ++ * reserved for management commands, rest of reply queues ++ * (based on number of logical CPUs) will be used for IOs and ++ * referenced as IO queues. ++ * Total Number of reply queues = 1 + IO queues ++ * ++ * MFI adapters supports single MSI-x so single reply queue ++ * will be used for IO and management commands. ++ */ ++ ++ intr_coalescing = (scratch_pad_1 & MR_INTR_COALESCING_SUPPORT_OFFSET) ? ++ true : false; ++ if (intr_coalescing && ++ (num_online_cpus() >= MR_HIGH_IOPS_QUEUE_COUNT) && ++ (instance->msix_vectors == MEGASAS_MAX_MSIX_QUEUES)) ++ instance->balanced_mode = true; ++ else ++ instance->balanced_mode = false; ++ ++ if (instance->balanced_mode) ++ instance->low_latency_index_start = ++ MR_HIGH_IOPS_QUEUE_COUNT; ++ else ++ instance->low_latency_index_start = 1; ++ ++ num_msix_req = num_online_cpus() + ++ instance->low_latency_index_start; ++ ++ instance->msix_vectors = min(num_msix_req, ++ instance->msix_vectors); ++ ++ megasas_alloc_irq_vectors(instance); ++ if (!instance->msix_vectors) + instance->msix_load_balance = false; +- } + } + /* + * MSI-X host index 0 is common for all adapter. +diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c +index e4f644ae06a1..0d54f0cc7bff 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c ++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c +@@ -977,6 +977,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) + u32 scratch_pad_1; + ktime_t time; + bool cur_fw_64bit_dma_capable; ++ bool cur_intr_coalescing; + + fusion = instance->ctrl_context; + +@@ -1011,6 +1012,16 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) + goto fail_fw_init; + } + ++ cur_intr_coalescing = (scratch_pad_1 & MR_INTR_COALESCING_SUPPORT_OFFSET) ? ++ true : false; ++ ++ if ((instance->low_latency_index_start == ++ MR_HIGH_IOPS_QUEUE_COUNT) && cur_intr_coalescing) ++ instance->balanced_mode = true; ++ ++ dev_info(&instance->pdev->dev, "Balanced mode :%s\n", ++ instance->balanced_mode ? "Yes" : "No"); ++ + instance->fw_sync_cache_support = (scratch_pad_1 & + MR_CAN_HANDLE_SYNC_CACHE_OFFSET) ? 1 : 0; + dev_info(&instance->pdev->dev, "FW supports sync cache\t: %s\n", +-- +2.27.0 + diff --git a/patches/0449-scsi-megaraid_sas-Enable-coalescing-for-high-IOPS-qu.patch b/patches/0449-scsi-megaraid_sas-Enable-coalescing-for-high-IOPS-qu.patch new file mode 100644 index 00000000..ff815f31 --- /dev/null +++ b/patches/0449-scsi-megaraid_sas-Enable-coalescing-for-high-IOPS-qu.patch @@ -0,0 +1,64 @@ +From 06a7a54eda74fa0f035a397daa36aa4298ee3be9 Mon Sep 17 00:00:00 2001 +From: Chandrakanth Patil +Date: Tue, 25 Jun 2019 16:34:32 +0530 +Subject: [PATCH 131/256] scsi: megaraid_sas: Enable coalescing for high IOPS + queues + +mainline inclusion +from mainline-v5.3-rc1 +commit ea836f40f8fdb47c7dda2e4aaaa28ae676c3fa41 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ea836f40f8fdb47c7dda2e4aaaa28ae676c3fa41 + +---------------------------------------------------------------------- + +Driver should enable interrupt coalescing (during driver load and after +Controller Reset) for High IOPS queues by masking appropriate bits in IOC +INIT frame. + +Signed-off-by: Kashyap Desai +Signed-off-by: Chandrakanth Patil +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/megaraid/megaraid_sas.h | 2 +- + drivers/scsi/megaraid/megaraid_sas_fusion.c | 8 ++++++++ + 2 files changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h +index 581188ce3042..0fad3b9ec9a3 100644 +--- a/drivers/scsi/megaraid/megaraid_sas.h ++++ b/drivers/scsi/megaraid/megaraid_sas.h +@@ -1720,7 +1720,7 @@ struct megasas_init_frame { + __le32 pad_0; /*0Ch */ + + __le16 flags; /*10h */ +- __le16 reserved_3; /*12h */ ++ __le16 replyqueue_mask; /*12h */ + __le32 data_xfer_len; /*14h */ + + __le32 queue_info_new_phys_addr_lo; /*18h */ +diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c +index 0d54f0cc7bff..9d43af44abd2 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c ++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c +@@ -1107,6 +1107,14 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) + cpu_to_le32(lower_32_bits(ioc_init_handle)); + init_frame->data_xfer_len = cpu_to_le32(sizeof(struct MPI2_IOC_INIT_REQUEST)); + ++ /* ++ * Each bit in replyqueue_mask represents one group of MSI-x vectors ++ * (each group has 8 vectors) ++ */ ++ if (instance->balanced_mode) ++ init_frame->replyqueue_mask = ++ cpu_to_le16(~(~0 << instance->low_latency_index_start / 8)); ++ + req_desc.u.low = cpu_to_le32(lower_32_bits(cmd->frame_phys_addr)); + req_desc.u.high = cpu_to_le32(upper_32_bits(cmd->frame_phys_addr)); + req_desc.MFAIo.RequestFlags = +-- +2.27.0 + diff --git a/patches/0450-scsi-megaraid_sas-Use-high-IOPS-queues-based-on-IO-w.patch b/patches/0450-scsi-megaraid_sas-Use-high-IOPS-queues-based-on-IO-w.patch new file mode 100644 index 00000000..867256ef --- /dev/null +++ b/patches/0450-scsi-megaraid_sas-Use-high-IOPS-queues-based-on-IO-w.patch @@ -0,0 +1,125 @@ +From e00477f935f3153cd027ef985725b12b52250e61 Mon Sep 17 00:00:00 2001 +From: Chandrakanth Patil +Date: Tue, 25 Jun 2019 16:34:34 +0530 +Subject: [PATCH 132/256] scsi: megaraid_sas: Use high IOPS queues based on IO + workload + +mainline inclusion +from mainline-v5.3-rc1 +commit f39e5e52c5b5407173d87b03a6385fbe6ccf1026 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f39e5e52c5b5407173d87b03a6385fbe6ccf1026 + +---------------------------------------------------------------------- + +The driver will use round-robin method for IO submission in batches within +the high IOPS queues when the number of in-flight ios on the target device +is larger than 8. Otherwise the driver will use low latency reply queues. + +Signed-off-by: Kashyap Desai +Signed-off-by: Chandrakanth Patil +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/megaraid/megaraid_sas.h | 3 +++ + drivers/scsi/megaraid/megaraid_sas_fp.c | 1 + + drivers/scsi/megaraid/megaraid_sas_fusion.c | 21 +++++++++++++++++++-- + drivers/scsi/megaraid/megaraid_sas_fusion.h | 1 + + 4 files changed, 24 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h +index 0fad3b9ec9a3..46374bcae3af 100644 +--- a/drivers/scsi/megaraid/megaraid_sas.h ++++ b/drivers/scsi/megaraid/megaraid_sas.h +@@ -2150,6 +2150,8 @@ enum MR_PD_TYPE { + + /*Aero performance parameters*/ + #define MR_HIGH_IOPS_QUEUE_COUNT 8 ++#define MR_DEVICE_HIGH_IOPS_DEPTH 8 ++#define MR_HIGH_IOPS_BATCH_COUNT 16 + + struct megasas_instance { + +@@ -2257,6 +2259,7 @@ struct megasas_instance { + atomic_t sge_holes_type2; + atomic_t sge_holes_type3; + atomic64_t total_io_count; ++ atomic64_t high_iops_outstanding; + + struct megasas_instance_template *instancet; + struct tasklet_struct isr_tasklet; +diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c +index a33628550425..b259ac9473b9 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_fp.c ++++ b/drivers/scsi/megaraid/megaraid_sas_fp.c +@@ -968,6 +968,7 @@ MR_BuildRaidContext(struct megasas_instance *instance, + stripSize = 1 << raid->stripeShift; + stripe_mask = stripSize-1; + ++ io_info->data_arms = raid->rowDataSize; + + /* + * calculate starting row and stripe, and number of strips and rows +diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c +index 9d43af44abd2..67a938d2d451 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c ++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c +@@ -2641,6 +2641,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, + io_info.r1_alt_dev_handle = MR_DEVHANDLE_INVALID; + scsi_buff_len = scsi_bufflen(scp); + io_request->DataLength = cpu_to_le32(scsi_buff_len); ++ io_info.data_arms = 1; + + if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) + io_info.isRead = 1; +@@ -2661,7 +2662,15 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, + fp_possible = (io_info.fpOkForIo > 0) ? true : false; + } + +- if (instance->msix_load_balance) ++ if (instance->balanced_mode && ++ atomic_read(&scp->device->device_busy) > ++ (io_info.data_arms * MR_DEVICE_HIGH_IOPS_DEPTH)) ++ cmd->request_desc->SCSIIO.MSIxIndex = ++ mega_mod64((atomic64_add_return(1, ++ &instance->high_iops_outstanding) / ++ MR_HIGH_IOPS_BATCH_COUNT), ++ instance->low_latency_index_start); ++ else if (instance->msix_load_balance) + cmd->request_desc->SCSIIO.MSIxIndex = + (mega_mod64(atomic64_add_return(1, + &instance->total_io_count), +@@ -2996,7 +3005,15 @@ megasas_build_syspd_fusion(struct megasas_instance *instance, + + cmd->request_desc->SCSIIO.DevHandle = io_request->DevHandle; + +- if (instance->msix_load_balance) ++ if (instance->balanced_mode && ++ atomic_read(&scmd->device->device_busy) > ++ MR_DEVICE_HIGH_IOPS_DEPTH) ++ cmd->request_desc->SCSIIO.MSIxIndex = ++ mega_mod64((atomic64_add_return(1, ++ &instance->high_iops_outstanding) / ++ MR_HIGH_IOPS_BATCH_COUNT), ++ instance->low_latency_index_start); ++ else if (instance->msix_load_balance) + cmd->request_desc->SCSIIO.MSIxIndex = + (mega_mod64(atomic64_add_return(1, + &instance->total_io_count), +diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h +index 68517cb7342b..c734d6139fb5 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_fusion.h ++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h +@@ -952,6 +952,7 @@ struct IO_REQUEST_INFO { + u8 pd_after_lb; + u16 r1_alt_dev_handle; /* raid 1/10 only */ + bool ra_capable; ++ u8 data_arms; + }; + + struct MR_LD_TARGET_SYNC { +-- +2.27.0 + diff --git a/patches/0451-scsi-megaraid_sas-Introduce-various-Aero-performance.patch b/patches/0451-scsi-megaraid_sas-Introduce-various-Aero-performance.patch new file mode 100644 index 00000000..9094a4dd --- /dev/null +++ b/patches/0451-scsi-megaraid_sas-Introduce-various-Aero-performance.patch @@ -0,0 +1,283 @@ +From e8e9a87843ec51b5a8bcc12180361593cd0a9513 Mon Sep 17 00:00:00 2001 +From: Chandrakanth Patil +Date: Tue, 25 Jun 2019 16:34:35 +0530 +Subject: [PATCH 133/256] scsi: megaraid_sas: Introduce various Aero + performance modes + +mainline inclusion +from mainline-v5.3-rc1 +commit 299ee42615e3f5f10dc8604b995368bd05c6a687 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=299ee42615e3f5f10dc8604b995368bd05c6a687 + +---------------------------------------------------------------------- + +For Aero adapters, driver provides three different performance modes +controlled through module parameter named 'perf_mode'. Below are those +performance modes: + + 0: Balanced - Additional high IOPS reply queues will be enabled along with + low latency queues. Interrupt coalescing will be enabled only for these + high IOPS reply queues. + + 1: IOPS - No additional high IOPS queues are enabled. Interrupt coalescing + will be enabled on all reply queues. + + 2: Latency - No additional high IOPS queues are enabled. Interrupt + coalescing will be disabled on all reply queues. This is a legacy + behavior similar to Ventura & Invader Series. + +Default performance mode settings: + + - Performance mode set to 'Balanced', if Aero controller is working in + 16GT/s PCIe speed. + + - Performance mode will be set to 'Latency' mode for all other cases. + +Through module parameter 'perf_mode', user can override default performance +mode to desired one. + +Captured some performance numbers with these performance modes. 4k Random +Read IO performance numbers on 24 SAS SSD drives for above three +performance modes. Performance data is from Intel Skylake and HGST SS300 +(drive model SDLL1DLR400GCCA1). + +IOPS: + ----------------------------------------------------------------------- + |perf_mode | qd = 1 | qd = 64 | note | + |-------------|--------|---------|------------------------------------- + |balanced | 259K | 3061k | Provides max performance numbers | + | | | | both on lower QD workload & | + | | | | also on higher QD workload | + |-------------|--------|---------|------------------------------------- + |iops | 220K | 3100k | Provides max performance numbers | + | | | | only on higher QD workload. | + |-------------|--------|---------|------------------------------------- + |latency | 246k | 2226k | Provides good performance numbers | + | | | | only on lower QD worklaod. | + ----------------------------------------------------------------------- + +Average Latency: + ----------------------------------------------------- + |perf_mode | qd = 1 | qd = 64 | + |-------------|--------------|----------------------| + |balanced | 92.05 usec | 501.12 usec | + |-------------|--------------|----------------------| + |iops | 108.40 usec | 498.10 usec | + |-------------|--------------|----------------------| + |latency | 97.10 usec | 689.26 usec | + ----------------------------------------------------- + +Signed-off-by: Sumit Saxena +Signed-off-by: Chandrakanth Patil +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/megaraid/megaraid_sas_base.c +--- + drivers/scsi/megaraid/megaraid_sas.h | 14 ++++- + drivers/scsi/megaraid/megaraid_sas_base.c | 62 +++++++++++++++++++-- + drivers/scsi/megaraid/megaraid_sas_fusion.c | 23 +++++--- + 3 files changed, 85 insertions(+), 14 deletions(-) + +diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h +index 46374bcae3af..3311d1adca2f 100644 +--- a/drivers/scsi/megaraid/megaraid_sas.h ++++ b/drivers/scsi/megaraid/megaraid_sas.h +@@ -2153,6 +2153,18 @@ enum MR_PD_TYPE { + #define MR_DEVICE_HIGH_IOPS_DEPTH 8 + #define MR_HIGH_IOPS_BATCH_COUNT 16 + ++enum MR_PERF_MODE { ++ MR_BALANCED_PERF_MODE = 0, ++ MR_IOPS_PERF_MODE = 1, ++ MR_LATENCY_PERF_MODE = 2, ++}; ++ ++#define MEGASAS_PERF_MODE_2STR(mode) \ ++ ((mode) == MR_BALANCED_PERF_MODE ? "Balanced" : \ ++ (mode) == MR_IOPS_PERF_MODE ? "IOPS" : \ ++ (mode) == MR_LATENCY_PERF_MODE ? "Latency" : \ ++ "Unknown") ++ + struct megasas_instance { + + unsigned int *reply_map; +@@ -2325,7 +2337,7 @@ struct megasas_instance { + u8 task_abort_tmo; + u8 max_reset_tmo; + u8 low_latency_index_start; +- bool balanced_mode; ++ int perf_mode; + }; + struct MR_LD_VF_MAP { + u32 size; +diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c +index 35850ba8f071..d81e4c1a1f02 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_base.c ++++ b/drivers/scsi/megaraid/megaraid_sas_base.c +@@ -106,6 +106,18 @@ unsigned int scmd_timeout = MEGASAS_DEFAULT_CMD_TIMEOUT; + module_param(scmd_timeout, int, S_IRUGO); + MODULE_PARM_DESC(scmd_timeout, "scsi command timeout (10-90s), default 90s. See megasas_reset_timer."); + ++int perf_mode = -1; ++module_param(perf_mode, int, 0444); ++MODULE_PARM_DESC(perf_mode, "Performance mode (only for Aero adapters), options:\n\t\t" ++ "0 - balanced: High iops and low latency queues are allocated &\n\t\t" ++ "interrupt coalescing is enabled only on high iops queues\n\t\t" ++ "1 - iops: High iops queues are not allocated &\n\t\t" ++ "interrupt coalescing is enabled on all queues\n\t\t" ++ "2 - latency: High iops queues are not allocated &\n\t\t" ++ "interrupt coalescing is disabled on all queues\n\t\t" ++ "default mode is 'balanced'" ++ ); ++ + MODULE_LICENSE("GPL"); + MODULE_VERSION(MEGASAS_VERSION); + MODULE_AUTHOR("megaraidlinux.pdl@avagotech.com"); +@@ -5070,7 +5082,7 @@ megasas_setup_irqs_ioapic(struct megasas_instance *instance) + __func__, __LINE__); + return -1; + } +- instance->balanced_mode = false; ++ instance->perf_mode = MR_LATENCY_PERF_MODE; + instance->low_latency_index_start = 0; + return 0; + } +@@ -5259,11 +5271,12 @@ megasas_alloc_irq_vectors(struct megasas_instance *instance) + + i = __megasas_alloc_irq_vectors(instance); + +- if (instance->balanced_mode && (i != instance->msix_vectors)) { ++ if ((instance->perf_mode == MR_BALANCED_PERF_MODE) & ++ (i != instance->msix_vectors)) { + if (instance->msix_vectors) + pci_free_irq_vectors(instance->pdev); + /* Disable Balanced IOPS mode and try realloc vectors */ +- instance->balanced_mode = false; ++ instance->perf_mode = MR_LATENCY_PERF_MODE; + instance->low_latency_index_start = 1; + num_msix_req = num_online_cpus() + + instance->low_latency_index_start; +@@ -5307,6 +5320,7 @@ static int megasas_init_fw(struct megasas_instance *instance) + bool do_adp_reset = true; + bool intr_coalescing; + unsigned int num_msix_req; ++ u16 lnksta, speed; + + fusion = instance->ctrl_context; + +@@ -5498,11 +5512,47 @@ static int megasas_init_fw(struct megasas_instance *instance) + if (intr_coalescing && + (num_online_cpus() >= MR_HIGH_IOPS_QUEUE_COUNT) && + (instance->msix_vectors == MEGASAS_MAX_MSIX_QUEUES)) +- instance->balanced_mode = true; ++ instance->perf_mode = MR_BALANCED_PERF_MODE; + else +- instance->balanced_mode = false; ++ instance->perf_mode = MR_LATENCY_PERF_MODE; ++ ++ ++ if (instance->adapter_type == AERO_SERIES) { ++ pcie_capability_read_word(instance->pdev, ++ PCI_EXP_LNKSTA, ++ &lnksta); ++ speed = lnksta & PCI_EXP_LNKSTA_CLS; ++ ++ /* ++ * For Aero, if PCIe link speed is <16 GT/s, then driver ++ * should operate in latency perf mode and enable R1 PCI ++ * bandwidth algorithm ++ */ ++ if (speed < 0x4) { ++ instance->perf_mode = MR_LATENCY_PERF_MODE; ++ fusion->pcie_bw_limitation = true; ++ } ++ ++ /* ++ * Performance mode settings provided through module ++ * parameter-perf_mode will take affect only for: ++ * 1. Aero family of adapters. ++ * 2. When user sets module parameter- perf_mode in ++ * range of 0-2. ++ */ ++ if ((perf_mode >= MR_BALANCED_PERF_MODE) && ++ (perf_mode <= MR_LATENCY_PERF_MODE)) ++ instance->perf_mode = perf_mode; ++ /* ++ * If intr coalescing is not supported by controller FW, ++ * then IOPS and Balanced modes are not feasible. ++ */ ++ if (!intr_coalescing) ++ instance->perf_mode = MR_LATENCY_PERF_MODE; ++ ++ } + +- if (instance->balanced_mode) ++ if (instance->perf_mode == MR_BALANCED_PERF_MODE) + instance->low_latency_index_start = + MR_HIGH_IOPS_QUEUE_COUNT; + else +diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c +index 67a938d2d451..145c379e9424 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c ++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c +@@ -1017,10 +1017,10 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) + + if ((instance->low_latency_index_start == + MR_HIGH_IOPS_QUEUE_COUNT) && cur_intr_coalescing) +- instance->balanced_mode = true; ++ instance->perf_mode = MR_BALANCED_PERF_MODE; + +- dev_info(&instance->pdev->dev, "Balanced mode :%s\n", +- instance->balanced_mode ? "Yes" : "No"); ++ dev_info(&instance->pdev->dev, "Performance mode :%s\n", ++ MEGASAS_PERF_MODE_2STR(instance->perf_mode)); + + instance->fw_sync_cache_support = (scratch_pad_1 & + MR_CAN_HANDLE_SYNC_CACHE_OFFSET) ? 1 : 0; +@@ -1111,9 +1111,18 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) + * Each bit in replyqueue_mask represents one group of MSI-x vectors + * (each group has 8 vectors) + */ +- if (instance->balanced_mode) ++ switch (instance->perf_mode) { ++ case MR_BALANCED_PERF_MODE: + init_frame->replyqueue_mask = +- cpu_to_le16(~(~0 << instance->low_latency_index_start / 8)); ++ cpu_to_le16(~(~0 << ++ instance->low_latency_index_start/8)); ++ break; ++ case MR_IOPS_PERF_MODE: ++ init_frame->replyqueue_mask = ++ cpu_to_le16(~(~0 << instance->msix_vectors/8)); ++ break; ++ } ++ + + req_desc.u.low = cpu_to_le32(lower_32_bits(cmd->frame_phys_addr)); + req_desc.u.high = cpu_to_le32(upper_32_bits(cmd->frame_phys_addr)); +@@ -2662,7 +2671,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, + fp_possible = (io_info.fpOkForIo > 0) ? true : false; + } + +- if (instance->balanced_mode && ++ if ((instance->perf_mode == MR_BALANCED_PERF_MODE) && + atomic_read(&scp->device->device_busy) > + (io_info.data_arms * MR_DEVICE_HIGH_IOPS_DEPTH)) + cmd->request_desc->SCSIIO.MSIxIndex = +@@ -3005,7 +3014,7 @@ megasas_build_syspd_fusion(struct megasas_instance *instance, + + cmd->request_desc->SCSIIO.DevHandle = io_request->DevHandle; + +- if (instance->balanced_mode && ++ if ((instance->perf_mode == MR_BALANCED_PERF_MODE) && + atomic_read(&scmd->device->device_busy) > + MR_DEVICE_HIGH_IOPS_DEPTH) + cmd->request_desc->SCSIIO.MSIxIndex = +-- +2.27.0 + diff --git a/patches/0452-scsi-megaraid_sas-Use-Block-layer-API-to-check-SCSI-.patch b/patches/0452-scsi-megaraid_sas-Use-Block-layer-API-to-check-SCSI-.patch new file mode 100644 index 00000000..0f34ca6f --- /dev/null +++ b/patches/0452-scsi-megaraid_sas-Use-Block-layer-API-to-check-SCSI-.patch @@ -0,0 +1,127 @@ +From dcf0e828904fd5fac727dd41394ab84c5694ca71 Mon Sep 17 00:00:00 2001 +From: Anand Lodnoor +Date: Tue, 14 Jan 2020 16:51:21 +0530 +Subject: [PATCH 134/256] scsi: megaraid_sas: Use Block layer API to check SCSI + device in-flight IO requests + +mainline inclusion +from mainline-v5.6-rc1 +commit 4d1634b8d12ecb844f0d1af0b79c703cf9911484 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4d1634b8d12ecb844f0d1af0b79c703cf9911484 + +---------------------------------------------------------------------- + +Remove usage of device_busy counter from driver. Instead of device_busy +counter now driver uses 'nr_active' counter of request_queue to get the +number of inflight request for a LUN. + +Link: https://lore.kernel.org/r/1579000882-20246-11-git-send-email-anand.lodnoor@broadcom.com +Link : https://patchwork.kernel.org/patch/11249297/ +Signed-off-by: Chandrakanth Patil +Signed-off-by: Anand Lodnoor +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/megaraid/megaraid_sas_fusion.c +--- + drivers/scsi/megaraid/megaraid_sas_fusion.c | 66 +++++++++++---------- + 1 file changed, 34 insertions(+), 32 deletions(-) + +diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c +index 145c379e9424..aa06550616a1 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c ++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c +@@ -301,6 +301,38 @@ megasas_fusion_update_can_queue(struct megasas_instance *instance, int fw_boot_c + instance->max_fw_cmds = instance->max_fw_cmds-1; + } + } ++ ++static inline void ++megasas_get_msix_index(struct megasas_instance *instance, ++ struct scsi_cmnd *scmd, ++ struct megasas_cmd_fusion *cmd, ++ u8 data_arms) ++{ ++ int sdev_busy; ++ ++ /* nr_hw_queue = 1 for MegaRAID */ ++ struct blk_mq_hw_ctx *hctx = ++ scmd->device->request_queue->queue_hw_ctx[0]; ++ ++ sdev_busy = atomic_read(&hctx->nr_active); ++ ++ if (instance->perf_mode == MR_BALANCED_PERF_MODE && ++ sdev_busy > (data_arms * MR_DEVICE_HIGH_IOPS_DEPTH)) ++ cmd->request_desc->SCSIIO.MSIxIndex = ++ mega_mod64((atomic64_add_return(1, ++ &instance->high_iops_outstanding) / ++ MR_HIGH_IOPS_BATCH_COUNT), ++ instance->low_latency_index_start); ++ else if (instance->msix_load_balance) ++ cmd->request_desc->SCSIIO.MSIxIndex = ++ (mega_mod64(atomic64_add_return(1, ++ &instance->total_io_count), ++ instance->msix_vectors)); ++ else ++ cmd->request_desc->SCSIIO.MSIxIndex = ++ instance->reply_map[raw_smp_processor_id()]; ++} ++ + /** + * megasas_free_cmds_fusion - Free all the cmds in the free cmd pool + * @instance: Adapter soft state +@@ -2671,22 +2703,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, + fp_possible = (io_info.fpOkForIo > 0) ? true : false; + } + +- if ((instance->perf_mode == MR_BALANCED_PERF_MODE) && +- atomic_read(&scp->device->device_busy) > +- (io_info.data_arms * MR_DEVICE_HIGH_IOPS_DEPTH)) +- cmd->request_desc->SCSIIO.MSIxIndex = +- mega_mod64((atomic64_add_return(1, +- &instance->high_iops_outstanding) / +- MR_HIGH_IOPS_BATCH_COUNT), +- instance->low_latency_index_start); +- else if (instance->msix_load_balance) +- cmd->request_desc->SCSIIO.MSIxIndex = +- (mega_mod64(atomic64_add_return(1, +- &instance->total_io_count), +- instance->msix_vectors)); +- else +- cmd->request_desc->SCSIIO.MSIxIndex = +- instance->reply_map[raw_smp_processor_id()]; ++ megasas_get_msix_index(instance, scp, cmd, io_info.data_arms); + + praid_context = &io_request->RaidContext; + +@@ -3014,22 +3031,7 @@ megasas_build_syspd_fusion(struct megasas_instance *instance, + + cmd->request_desc->SCSIIO.DevHandle = io_request->DevHandle; + +- if ((instance->perf_mode == MR_BALANCED_PERF_MODE) && +- atomic_read(&scmd->device->device_busy) > +- MR_DEVICE_HIGH_IOPS_DEPTH) +- cmd->request_desc->SCSIIO.MSIxIndex = +- mega_mod64((atomic64_add_return(1, +- &instance->high_iops_outstanding) / +- MR_HIGH_IOPS_BATCH_COUNT), +- instance->low_latency_index_start); +- else if (instance->msix_load_balance) +- cmd->request_desc->SCSIIO.MSIxIndex = +- (mega_mod64(atomic64_add_return(1, +- &instance->total_io_count), +- instance->msix_vectors)); +- else +- cmd->request_desc->SCSIIO.MSIxIndex = +- instance->reply_map[raw_smp_processor_id()]; ++ megasas_get_msix_index(instance, scmd, cmd, 1); + + if (!fp_possible) { + /* system pd firmware path */ +-- +2.27.0 + diff --git a/patches/0453-scsi-megaraid_sas-Added-support-for-shared-host-tags.patch b/patches/0453-scsi-megaraid_sas-Added-support-for-shared-host-tags.patch new file mode 100644 index 00000000..3c80a504 --- /dev/null +++ b/patches/0453-scsi-megaraid_sas-Added-support-for-shared-host-tags.patch @@ -0,0 +1,201 @@ +From a9d3bbf5298028487d680e40a627a84ef3e8ed81 Mon Sep 17 00:00:00 2001 +From: Kashyap Desai +Date: Wed, 19 Aug 2020 23:20:35 +0800 +Subject: [PATCH 135/256] scsi: megaraid_sas: Added support for shared host + tagset for cpuhotplug + +mainline inclusion +from mainline-v5.10-rc1 +commit 103fbf8e4020845e4fcf63819288cedb092a3c91 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=103fbf8e4020845e4fcf63819288cedb092a3c91 + +---------------------------------------------------------------------- + +Fusion adapters can steer completions to individual queues, and +we now have support for shared host-wide tags. +So we can enable multiqueue support for fusion adapters. + +Once driver enable shared host-wide tags, cpu hotplug feature is also +supported as it was enabled using below patchsets - +commit bf0beec0607d ("blk-mq: drain I/O when all CPUs in a hctx are +offline") + +Currently driver has provision to disable host-wide tags using +"host_tagset_enable" module parameter. + +Once we do not have any major performance regression using host-wide +tags, we will drop the hand-crafted interrupt affinity settings. + +Performance is also meeting the expecatation - (used both none and +mq-deadline scheduler) +24 Drive SSD on Aero with/without this patch can get 3.1M IOPs +3 VDs consist of 8 SAS SSD on Aero with/without this patch can get 3.1M +IOPs. + +Signed-off-by: Kashyap Desai +Signed-off-by: Hannes Reinecke +Signed-off-by: John Garry +Tested-by: Douglas Gilbert +Acked-by: Martin K. Petersen +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/megaraid/megaraid_sas_base.c +--- + drivers/scsi/megaraid/megaraid_sas_base.c | 39 +++++++++++++++++++++ + drivers/scsi/megaraid/megaraid_sas_fusion.c | 30 +++++++++------- + 2 files changed, 56 insertions(+), 13 deletions(-) + +diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c +index d81e4c1a1f02..daf5b08ab066 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_base.c ++++ b/drivers/scsi/megaraid/megaraid_sas_base.c +@@ -50,6 +50,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -118,6 +119,10 @@ MODULE_PARM_DESC(perf_mode, "Performance mode (only for Aero adapters), options: + "default mode is 'balanced'" + ); + ++int host_tagset_enable = 1; ++module_param(host_tagset_enable, int, 0444); ++MODULE_PARM_DESC(host_tagset_enable, "Shared host tagset enable/disable Default: enable(1)"); ++ + MODULE_LICENSE("GPL"); + MODULE_VERSION(MEGASAS_VERSION); + MODULE_AUTHOR("megaraidlinux.pdl@avagotech.com"); +@@ -2959,6 +2964,19 @@ megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev, + return 0; + } + ++static int megasas_map_queues(struct Scsi_Host *shost) ++{ ++ struct megasas_instance *instance; ++ ++ instance = (struct megasas_instance *)shost->hostdata; ++ ++ if (shost->nr_hw_queues == 1) ++ return 0; ++ ++ return blk_mq_pci_map_queues_by_qmap(&shost->tag_set.map[HCTX_TYPE_DEFAULT], ++ instance->pdev, instance->low_latency_index_start); ++} ++ + static void megasas_aen_polling(struct work_struct *work); + + /** +@@ -3206,6 +3224,7 @@ static struct scsi_host_template megasas_template = { + .shost_attrs = megaraid_host_attrs, + .bios_param = megasas_bios_param, + .use_clustering = ENABLE_CLUSTERING, ++ .map_queues = megasas_map_queues, + .change_queue_depth = scsi_change_queue_depth, + .no_write_same = 1, + }; +@@ -6211,6 +6230,26 @@ static int megasas_io_attach(struct megasas_instance *instance) + host->max_lun = MEGASAS_MAX_LUN; + host->max_cmd_len = 16; + ++ /* Use shared host tagset only for fusion adaptors ++ * if there are managed interrupts (smp affinity enabled case). ++ * Single msix_vectors in kdump, so shared host tag is also disabled. ++ */ ++ ++ host->host_tagset = 0; ++ host->nr_hw_queues = 1; ++ ++ if ((instance->adapter_type != MFI_SERIES) && ++ (instance->msix_vectors > instance->low_latency_index_start) && ++ host_tagset_enable && ++ instance->smp_affinity_enable) { ++ host->host_tagset = 1; ++ host->nr_hw_queues = instance->msix_vectors - ++ instance->low_latency_index_start; ++ } ++ ++ dev_info(&instance->pdev->dev, ++ "Max firmware commands: %d shared with nr_hw_queues = %d\n", ++ instance->max_fw_cmds, host->nr_hw_queues); + /* + * Notify the mid-layer about the new controller + */ +diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c +index aa06550616a1..27878f575670 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c ++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c +@@ -310,27 +310,33 @@ megasas_get_msix_index(struct megasas_instance *instance, + { + int sdev_busy; + +- /* nr_hw_queue = 1 for MegaRAID */ +- struct blk_mq_hw_ctx *hctx = +- scmd->device->request_queue->queue_hw_ctx[0]; +- +- sdev_busy = atomic_read(&hctx->nr_active); ++ /* TBD - if sml remove device_busy in future, driver ++ * should track counter in internal structure. ++ */ ++ sdev_busy = atomic_read(&scmd->device->device_busy); + + if (instance->perf_mode == MR_BALANCED_PERF_MODE && +- sdev_busy > (data_arms * MR_DEVICE_HIGH_IOPS_DEPTH)) ++ sdev_busy > (data_arms * MR_DEVICE_HIGH_IOPS_DEPTH)) { + cmd->request_desc->SCSIIO.MSIxIndex = + mega_mod64((atomic64_add_return(1, + &instance->high_iops_outstanding) / + MR_HIGH_IOPS_BATCH_COUNT), + instance->low_latency_index_start); +- else if (instance->msix_load_balance) ++ } else if (instance->msix_load_balance) { + cmd->request_desc->SCSIIO.MSIxIndex = + (mega_mod64(atomic64_add_return(1, + &instance->total_io_count), + instance->msix_vectors)); +- else ++ } else if (instance->host->nr_hw_queues > 1) { ++ u32 tag = blk_mq_unique_tag(scmd->request); ++ ++ cmd->request_desc->SCSIIO.MSIxIndex = ++ blk_mq_unique_tag_to_hwq(tag) + ++ instance->low_latency_index_start; ++ } else { + cmd->request_desc->SCSIIO.MSIxIndex = + instance->reply_map[raw_smp_processor_id()]; ++ } + } + + /** +@@ -910,9 +916,6 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance) + if (megasas_alloc_cmdlist_fusion(instance)) + goto fail_exit; + +- dev_info(&instance->pdev->dev, "Configured max firmware commands: %d\n", +- instance->max_fw_cmds); +- + /* The first 256 bytes (SMID 0) is not used. Don't add to the cmd list */ + io_req_base = fusion->io_request_frames + MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE; + io_req_base_phys = fusion->io_request_frames_phys + MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE; +@@ -1051,8 +1054,9 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) + MR_HIGH_IOPS_QUEUE_COUNT) && cur_intr_coalescing) + instance->perf_mode = MR_BALANCED_PERF_MODE; + +- dev_info(&instance->pdev->dev, "Performance mode :%s\n", +- MEGASAS_PERF_MODE_2STR(instance->perf_mode)); ++ dev_info(&instance->pdev->dev, "Performance mode :%s (latency index = %d)\n", ++ MEGASAS_PERF_MODE_2STR(instance->perf_mode), ++ instance->low_latency_index_start); + + instance->fw_sync_cache_support = (scratch_pad_1 & + MR_CAN_HANDLE_SYNC_CACHE_OFFSET) ? 1 : 0; +-- +2.27.0 + diff --git a/patches/0454-scsi-hisi_sas-Reduce-some-indirection-in-v3-hw-drive.patch b/patches/0454-scsi-hisi_sas-Reduce-some-indirection-in-v3-hw-drive.patch new file mode 100644 index 00000000..7a33661e --- /dev/null +++ b/patches/0454-scsi-hisi_sas-Reduce-some-indirection-in-v3-hw-drive.patch @@ -0,0 +1,67 @@ +From 3a08bf7e74d5b241decd1857157b20fecdab2590 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Tue, 3 Aug 2021 14:47:26 +0800 +Subject: [PATCH 136/256] scsi: hisi_sas: Reduce some indirection in v3 hw + driver + +mainline inclusion +from mainline-v5.11-rc1 +commit bec99e5250bfe1c575e72a971bc2b2b21cf6c8b4 +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE +CVE: NA + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bec99e5250bfe1c575e72a971bc2b2b21cf6c8b4 + +------------------------------------------------------------------------ + +Sometimes local functions are called indirectly from the hw driver, which +only makes the code harder to follow. Remove these. + +Method .hw_init is only called from platform driver probe, which is not +relevant, so don't set this either. + +Link: https://lore.kernel.org/r/1606207594-196362-2-git-send-email-john.garry@huawei.com +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index b03fe2b680f8..0e5a0ff8365f 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -3535,7 +3535,6 @@ static struct scsi_host_template sht_v3_hw = { + }; + + static const struct hisi_sas_hw hisi_sas_v3_hw = { +- .hw_init = hisi_sas_v3_init, + .setup_itct = setup_itct_v3_hw, + .get_wideport_bitmap = get_wideport_bitmap_v3_hw, + .complete_hdr_size = sizeof(struct hisi_sas_complete_v3_hdr), +@@ -3719,7 +3718,7 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) + if (rc) + goto err_out_register_ha; + +- rc = hisi_hba->hw->hw_init(hisi_hba); ++ rc = hisi_sas_v3_init(hisi_hba); + if (rc) + goto err_out_register_ha; + +@@ -3915,7 +3914,7 @@ static int _resume_v3_hw(struct device *device) + pci_disable_device(pdev); + return rc; + } +- hisi_hba->hw->phys_init(hisi_hba); ++ phys_init_v3_hw(hisi_hba); + sas_resume_ha(sha); + clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags); + +-- +2.27.0 + diff --git a/patches/0455-scsi-hisi_sas-Move-debugfs-code-to-v3-hw-driver.patch b/patches/0455-scsi-hisi_sas-Move-debugfs-code-to-v3-hw-driver.patch new file mode 100644 index 00000000..4f261740 --- /dev/null +++ b/patches/0455-scsi-hisi_sas-Move-debugfs-code-to-v3-hw-driver.patch @@ -0,0 +1,2796 @@ +From 16b71cede31dc8b60362ddc9a443f9b629da5797 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Tue, 3 Aug 2021 14:47:27 +0800 +Subject: [PATCH 137/256] scsi: hisi_sas: Move debugfs code to v3 hw driver + +mainline inclusion +from mainline-v5.11-rc1 +commit 623a4b6d5c2a7595f677fa17348dbca6b461f16a +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=623a4b6d5c2a7595f677fa17348dbca6b461f16a + +---------------------------------------------------------------------- + +Relocate all the debugfs code for DFX to v3 hw since no other versions +support it. + +Link: https://lore.kernel.org/r/1606207594-196362-4-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas.h + drivers/scsi/hisi_sas/hisi_sas_main.c + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 28 - + drivers/scsi/hisi_sas/hisi_sas_main.c | 1367 +----------------------- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 1222 ++++++++++++++++++++- + 3 files changed, 1208 insertions(+), 1409 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index fdf9207f2efe..49aee1c365e2 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -262,24 +262,6 @@ struct hisi_sas_slot { + int idx; + }; + +-#define HISI_SAS_DEBUGFS_REG(x) {#x, x} +- +-struct hisi_sas_debugfs_reg_lu { +- char *name; +- int off; +-}; +- +-struct hisi_sas_debugfs_reg { +- const struct hisi_sas_debugfs_reg_lu *lu; +- int count; +- int base_off; +- union { +- u32 (*read_global_reg)(struct hisi_hba *hisi_hba, u32 off); +- u32 (*read_port_reg)(struct hisi_hba *hisi_hba, int port, +- u32 off); +- }; +-}; +- + enum { + HISI_SAS_BIST_LOOPBACK_MODE_DIGITAL = 0, + HISI_SAS_BIST_LOOPBACK_MODE_SERDES, +@@ -379,15 +361,8 @@ struct hisi_sas_hw { + const struct cpumask *(*get_managed_irq_aff)(struct hisi_hba + *hisi_hba, int queue); + void (*debugfs_work_handler)(struct work_struct *work); +- void (*read_iost_itct_cache)(struct hisi_hba *hisi_hba, +- enum hisi_sas_debugfs_cache_type type, +- u32 *cache); + int complete_hdr_size; + struct scsi_host_template *sht; +- +- const struct hisi_sas_debugfs_reg *debugfs_reg_array[DEBUGFS_REGS_NUM]; +- const struct hisi_sas_debugfs_reg *debugfs_reg_port; +- int (*set_bist)(struct hisi_hba *hisi_hba, bool enable); + }; + + #define HISI_SAS_MAX_DEBUGFS_DUMP (50) +@@ -711,8 +686,5 @@ extern void hisi_sas_release_tasks(struct hisi_hba *hisi_hba); + extern u8 hisi_sas_get_prog_phy_linkrate_mask(enum sas_linkrate max); + extern void hisi_sas_controller_reset_prepare(struct hisi_hba *hisi_hba); + extern void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba); +-extern void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba); +-extern void hisi_sas_debugfs_exit(struct hisi_hba *hisi_hba); + extern void hisi_sas_snapshot_regs(struct hisi_hba *hisi_hba); +-extern void hisi_sas_debugfs_work_handler(struct work_struct *work); + #endif +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 4946a9879ed8..b6bf733e4f0b 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -2769,1376 +2769,12 @@ int hisi_sas_probe(struct platform_device *pdev, + err_out_register_ha: + scsi_remove_host(shost); + err_out: +- hisi_sas_debugfs_exit(hisi_hba); + hisi_sas_free(hisi_hba); + scsi_host_put(shost); + return rc; + } + EXPORT_SYMBOL_GPL(hisi_sas_probe); + +-struct dentry *hisi_sas_debugfs_dir; +- +-static void hisi_sas_debugfs_snapshot_cq_reg(struct hisi_hba *hisi_hba) +-{ +- int queue_entry_size = hisi_hba->hw->complete_hdr_size; +- int dump_index = hisi_hba->debugfs_dump_index; +- int i; +- +- for (i = 0; i < hisi_hba->queue_count; i++) +- memcpy(hisi_hba->debugfs_cq[dump_index][i].complete_hdr, +- hisi_hba->complete_hdr[i], +- HISI_SAS_QUEUE_SLOTS * queue_entry_size); +-} +- +-static void hisi_sas_debugfs_snapshot_dq_reg(struct hisi_hba *hisi_hba) +-{ +- int queue_entry_size = sizeof(struct hisi_sas_cmd_hdr); +- int dump_index = hisi_hba->debugfs_dump_index; +- int i; +- +- for (i = 0; i < hisi_hba->queue_count; i++) +- memcpy(hisi_hba->debugfs_dq[dump_index][i].hdr, +- hisi_hba->cmd_hdr[i], +- HISI_SAS_QUEUE_SLOTS * queue_entry_size); +-} +- +-static void hisi_sas_debugfs_snapshot_port_reg(struct hisi_hba *hisi_hba) +-{ +- int dump_index = hisi_hba->debugfs_dump_index; +- const struct hisi_sas_debugfs_reg *port = +- hisi_hba->hw->debugfs_reg_port; +- int i, phy_cnt; +- u32 offset; +- u32 *databuf; +- +- for (phy_cnt = 0; phy_cnt < hisi_hba->n_phy; phy_cnt++) { +- databuf = hisi_hba->debugfs_port_reg[dump_index][phy_cnt].data; +- for (i = 0; i < port->count; i++, databuf++) { +- offset = port->base_off + 4 * i; +- *databuf = port->read_port_reg(hisi_hba, phy_cnt, +- offset); +- } +- } +-} +- +-static void hisi_sas_debugfs_snapshot_global_reg(struct hisi_hba *hisi_hba) +-{ +- int dump_index = hisi_hba->debugfs_dump_index; +- u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL].data; +- const struct hisi_sas_hw *hw = hisi_hba->hw; +- const struct hisi_sas_debugfs_reg *global = +- hw->debugfs_reg_array[DEBUGFS_GLOBAL]; +- int i; +- +- for (i = 0; i < global->count; i++, databuf++) +- *databuf = global->read_global_reg(hisi_hba, 4 * i); +-} +- +-static void hisi_sas_debugfs_snapshot_axi_reg(struct hisi_hba *hisi_hba) +-{ +- int dump_index = hisi_hba->debugfs_dump_index; +- u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI].data; +- const struct hisi_sas_hw *hw = hisi_hba->hw; +- const struct hisi_sas_debugfs_reg *axi = +- hw->debugfs_reg_array[DEBUGFS_AXI]; +- int i; +- +- for (i = 0; i < axi->count; i++, databuf++) +- *databuf = axi->read_global_reg(hisi_hba, +- 4 * i + axi->base_off); +-} +- +-static void hisi_sas_debugfs_snapshot_ras_reg(struct hisi_hba *hisi_hba) +-{ +- int dump_index = hisi_hba->debugfs_dump_index; +- u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS].data; +- const struct hisi_sas_hw *hw = hisi_hba->hw; +- const struct hisi_sas_debugfs_reg *ras = +- hw->debugfs_reg_array[DEBUGFS_RAS]; +- int i; +- +- for (i = 0; i < ras->count; i++, databuf++) +- *databuf = ras->read_global_reg(hisi_hba, +- 4 * i + ras->base_off); +-} +- +-static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba) +-{ +- int dump_index = hisi_hba->debugfs_dump_index; +- void *cachebuf = hisi_hba->debugfs_itct_cache[dump_index].cache; +- void *databuf = hisi_hba->debugfs_itct[dump_index].itct; +- struct hisi_sas_itct *itct; +- int i; +- +- hisi_hba->hw->read_iost_itct_cache(hisi_hba, HISI_SAS_ITCT_CACHE, +- cachebuf); +- +- itct = hisi_hba->itct; +- +- for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) { +- memcpy(databuf, itct, sizeof(struct hisi_sas_itct)); +- databuf += sizeof(struct hisi_sas_itct); +- } +-} +- +-static void hisi_sas_debugfs_snapshot_iost_reg(struct hisi_hba *hisi_hba) +-{ +- int dump_index = hisi_hba->debugfs_dump_index; +- int max_command_entries = HISI_SAS_MAX_COMMANDS; +- void *cachebuf = hisi_hba->debugfs_iost_cache[dump_index].cache; +- void *databuf = hisi_hba->debugfs_iost[dump_index].iost; +- struct hisi_sas_iost *iost; +- int i; +- +- hisi_hba->hw->read_iost_itct_cache(hisi_hba, HISI_SAS_IOST_CACHE, +- cachebuf); +- +- iost = hisi_hba->iost; +- +- for (i = 0; i < max_command_entries; i++, iost++) { +- memcpy(databuf, iost, sizeof(struct hisi_sas_iost)); +- databuf += sizeof(struct hisi_sas_iost); +- } +-} +- +-static const char * +-hisi_sas_debugfs_to_reg_name(int off, int base_off, +- const struct hisi_sas_debugfs_reg_lu *lu) +-{ +- for (; lu->name; lu++) { +- if (off == lu->off - base_off) +- return lu->name; +- } +- +- return NULL; +-} +- +-static void hisi_sas_debugfs_print_reg(u32 *regs_val, const void *ptr, +- struct seq_file *s) +-{ +- const struct hisi_sas_debugfs_reg *reg = ptr; +- int i; +- +- for (i = 0; i < reg->count; i++) { +- int off = i * 4; +- const char *name; +- +- name = hisi_sas_debugfs_to_reg_name(off, reg->base_off, +- reg->lu); +- +- if (name) +- seq_printf(s, "0x%08x 0x%08x %s\n", off, +- regs_val[i], name); +- else +- seq_printf(s, "0x%08x 0x%08x\n", off, +- regs_val[i]); +- } +-} +- +-static int hisi_sas_debugfs_global_show(struct seq_file *s, void *p) +-{ +- struct hisi_sas_debugfs_regs *global = s->private; +- struct hisi_hba *hisi_hba = global->hisi_hba; +- const struct hisi_sas_hw *hw = hisi_hba->hw; +- const void *reg_global = hw->debugfs_reg_array[DEBUGFS_GLOBAL]; +- +- hisi_sas_debugfs_print_reg(global->data, +- reg_global, s); +- +- return 0; +-} +- +-static int hisi_sas_debugfs_global_open(struct inode *inode, struct file *filp) +-{ +- return single_open(filp, hisi_sas_debugfs_global_show, +- inode->i_private); +-} +- +-static const struct file_operations hisi_sas_debugfs_global_fops = { +- .open = hisi_sas_debugfs_global_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, +- .owner = THIS_MODULE, +-}; +- +-static struct { +- int value; +- char *name; +-} hisi_sas_debugfs_loop_linkrate[] = { +- { SAS_LINK_RATE_1_5_GBPS, "1.5 Gbit" }, +- { SAS_LINK_RATE_3_0_GBPS, "3.0 Gbit" }, +- { SAS_LINK_RATE_6_0_GBPS, "6.0 Gbit" }, +- { SAS_LINK_RATE_12_0_GBPS, "12.0 Gbit"}, +-}; +- +-static int hisi_sas_debugfs_bist_linkrate_show(struct seq_file *s, void *p) +-{ +- struct hisi_hba *hisi_hba = s->private; +- int i; +- +- for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_linkrate); i++) { +- int match = (hisi_hba->bist_loopback_linkrate == +- hisi_sas_debugfs_loop_linkrate[i].value); +- +- seq_printf(s, "%s%s%s ", match ? "[" : "", +- hisi_sas_debugfs_loop_linkrate[i].name, +- match ? "]" : ""); +- } +- seq_puts(s, "\n"); +- +- return 0; +-} +- +-ssize_t hisi_sas_debugfs_bist_linkrate_write(struct file *filp, +- const char __user *buf, +- size_t count, loff_t *ppos) +-{ +- struct seq_file *m = filp->private_data; +- struct hisi_hba *hisi_hba = m->private; +- char kbuf[16] = {}, *pkbuf; +- bool found = false; +- int i; +- +- if (hisi_hba->bist_loopback_enable) +- return -EINVAL; +- +- if (count >= sizeof(kbuf)) +- return -EINVAL; +- +- if (copy_from_user(kbuf, buf, count)) +- return -EINVAL; +- +- pkbuf = strstrip(kbuf); +- +- for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_linkrate); i++) { +- if (!strncmp(hisi_sas_debugfs_loop_linkrate[i].name, +- pkbuf, 16)) { +- hisi_hba->bist_loopback_linkrate = +- hisi_sas_debugfs_loop_linkrate[i].value; +- found = true; +- break; +- } +- } +- +- if (!found) { +- dev_err(hisi_hba->dev, "unknown mode\n"); +- return -EINVAL; +- } +- +- return count; +-} +- +-static int hisi_sas_debugfs_bist_linkrate_open(struct inode *inode, +- struct file *filp) +-{ +- return single_open(filp, hisi_sas_debugfs_bist_linkrate_show, +- inode->i_private); +-} +- +-static const struct file_operations hisi_sas_debugfs_bist_linkrate_ops = { +- .open = hisi_sas_debugfs_bist_linkrate_open, +- .read = seq_read, +- .write = hisi_sas_debugfs_bist_linkrate_write, +- .llseek = seq_lseek, +- .release = single_release, +- .owner = THIS_MODULE, +-}; +- +-static struct { +- int value; +- char *name; +-} hisi_sas_debugfs_loop_code_mode[] = { +- { HISI_SAS_BIST_CODE_MODE_PRBS7, "PRBS7" }, +- { HISI_SAS_BIST_CODE_MODE_PRBS23, "PRBS23" }, +- { HISI_SAS_BIST_CODE_MODE_PRBS31, "PRBS31" }, +- { HISI_SAS_BIST_CODE_MODE_JTPAT, "JTPAT" }, +- { HISI_SAS_BIST_CODE_MODE_CJTPAT, "CJTPAT" }, +- { HISI_SAS_BIST_CODE_MODE_SCRAMBED_0, "SCRAMBED_0" }, +- { HISI_SAS_BIST_CODE_MODE_TRAIN, "TRAIN" }, +- { HISI_SAS_BIST_CODE_MODE_TRAIN_DONE, "TRAIN_DONE" }, +- { HISI_SAS_BIST_CODE_MODE_HFTP, "HFTP" }, +- { HISI_SAS_BIST_CODE_MODE_MFTP, "MFTP" }, +- { HISI_SAS_BIST_CODE_MODE_LFTP, "LFTP" }, +- { HISI_SAS_BIST_CODE_MODE_FIXED_DATA, "FIXED_DATA" }, +-}; +- +-static int hisi_sas_debugfs_bist_code_mode_show(struct seq_file *s, void *p) +-{ +- struct hisi_hba *hisi_hba = s->private; +- int i; +- +- for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_code_mode); i++) { +- int match = (hisi_hba->bist_loopback_code_mode == +- hisi_sas_debugfs_loop_code_mode[i].value); +- +- seq_printf(s, "%s%s%s ", match ? "[" : "", +- hisi_sas_debugfs_loop_code_mode[i].name, +- match ? "]" : ""); +- } +- seq_puts(s, "\n"); +- +- return 0; +-} +- +-ssize_t hisi_sas_debugfs_bist_code_mode_write(struct file *filp, +- const char __user *buf, +- size_t count, loff_t *ppos) +-{ +- struct seq_file *m = filp->private_data; +- struct hisi_hba *hisi_hba = m->private; +- char kbuf[16] = {}, *pkbuf; +- bool found = false; +- int i; +- +- if (hisi_hba->bist_loopback_enable) +- return -EINVAL; +- +- if (count >= sizeof(kbuf)) +- return -EINVAL; +- +- if (copy_from_user(kbuf, buf, count)) +- return -EINVAL; +- +- pkbuf = strstrip(kbuf); +- +- for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_code_mode); i++) { +- if (!strncmp(hisi_sas_debugfs_loop_code_mode[i].name, +- pkbuf, 16)) { +- hisi_hba->bist_loopback_code_mode = +- hisi_sas_debugfs_loop_code_mode[i].value; +- found = true; +- break; +- } +- } +- +- if (!found) { +- dev_err(hisi_hba->dev, "unknown mode\n"); +- return -EINVAL; +- } +- +- return count; +-} +- +-static int hisi_sas_debugfs_bist_code_mode_open(struct inode *inode, +- struct file *filp) +-{ +- return single_open(filp, hisi_sas_debugfs_bist_code_mode_show, +- inode->i_private); +-} +- +-static const struct file_operations hisi_sas_debugfs_bist_code_mode_ops = { +- .open = hisi_sas_debugfs_bist_code_mode_open, +- .read = seq_read, +- .write = hisi_sas_debugfs_bist_code_mode_write, +- .llseek = seq_lseek, +- .release = single_release, +- .owner = THIS_MODULE, +-}; +- +-ssize_t hisi_sas_debugfs_bist_phy_write(struct file *filp, +- const char __user *buf, +- size_t count, loff_t *ppos) +-{ +- struct seq_file *m = filp->private_data; +- struct hisi_hba *hisi_hba = m->private; +- char kbuf[16] = {}, *pkbuf; +- unsigned int phy; +- int val; +- +- if (hisi_hba->bist_loopback_enable) +- return -EINVAL; +- +- if (count >= sizeof(kbuf)) +- return -EINVAL; +- +- if (copy_from_user(kbuf, buf, count)) +- return -EINVAL; +- +- pkbuf = strstrip(kbuf); +- +- val = kstrtouint(pkbuf, 0, &phy); +- if (val < 0) +- return val; +- +- if (phy >= hisi_hba->n_phy) { +- dev_err(hisi_hba->dev, "phy index %d exceeds limit\n", phy); +- return -EINVAL; +- } +- +- hisi_hba->bist_loopback_phy_id = phy; +- +- return count; +-} +- +-static int hisi_sas_debugfs_bist_phy_show(struct seq_file *s, void *p) +-{ +- struct hisi_hba *hisi_hba = s->private; +- +- seq_printf(s, "%d\n", hisi_hba->bist_loopback_phy_id); +- +- return 0; +-} +- +-static int hisi_sas_debugfs_bist_phy_open(struct inode *inode, +- struct file *filp) +-{ +- return single_open(filp, hisi_sas_debugfs_bist_phy_show, +- inode->i_private); +-} +- +-static const struct file_operations hisi_sas_debugfs_bist_phy_ops = { +- .open = hisi_sas_debugfs_bist_phy_open, +- .read = seq_read, +- .write = hisi_sas_debugfs_bist_phy_write, +- .llseek = seq_lseek, +- .release = single_release, +- .owner = THIS_MODULE, +-}; +- +-static struct { +- int value; +- char *name; +-} hisi_sas_debugfs_loop_modes[] = { +- { HISI_SAS_BIST_LOOPBACK_MODE_DIGITAL, "digital" }, +- { HISI_SAS_BIST_LOOPBACK_MODE_SERDES, "serdes" }, +- { HISI_SAS_BIST_LOOPBACK_MODE_REMOTE, "remote" }, +-}; +- +-static int hisi_sas_debugfs_bist_mode_show(struct seq_file *s, void *p) +-{ +- struct hisi_hba *hisi_hba = s->private; +- int i; +- +- for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_modes); i++) { +- int match = (hisi_hba->bist_loopback_mode == +- hisi_sas_debugfs_loop_modes[i].value); +- +- seq_printf(s, "%s%s%s ", match ? "[" : "", +- hisi_sas_debugfs_loop_modes[i].name, +- match ? "]" : ""); +- } +- seq_puts(s, "\n"); +- +- return 0; +-} +- +-ssize_t hisi_sas_debugfs_bist_mode_write(struct file *filp, +- const char __user *buf, +- size_t count, loff_t *ppos) +-{ +- struct seq_file *m = filp->private_data; +- struct hisi_hba *hisi_hba = m->private; +- char kbuf[16] = {}, *pkbuf; +- bool found = false; +- int i; +- +- if (hisi_hba->bist_loopback_enable) +- return -EINVAL; +- +- if (count >= sizeof(kbuf)) +- return -EINVAL; +- +- if (copy_from_user(kbuf, buf, count)) +- return -EINVAL; +- +- pkbuf = strstrip(kbuf); +- +- for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_modes); i++) { +- if (!strncmp(hisi_sas_debugfs_loop_modes[i].name, pkbuf, 16)) { +- hisi_hba->bist_loopback_mode = +- hisi_sas_debugfs_loop_modes[i].value; +- found = true; +- break; +- } +- } +- +- if (!found) { +- dev_err(hisi_hba->dev, "unknown mode\n"); +- return -EINVAL; +- } +- +- return count; +-} +- +-static int hisi_sas_debugfs_bist_mode_open(struct inode *inode, +- struct file *filp) +-{ +- return single_open(filp, hisi_sas_debugfs_bist_mode_show, +- inode->i_private); +-} +- +-static const struct file_operations hisi_sas_debugfs_bist_mode_ops = { +- .open = hisi_sas_debugfs_bist_mode_open, +- .read = seq_read, +- .write = hisi_sas_debugfs_bist_mode_write, +- .llseek = seq_lseek, +- .release = single_release, +- .owner = THIS_MODULE, +-}; +- +-ssize_t hisi_sas_debugfs_bist_enable_write(struct file *filp, +- const char __user *buf, +- size_t count, loff_t *ppos) +-{ +- struct seq_file *m = filp->private_data; +- struct hisi_hba *hisi_hba = m->private; +- char kbuf[16] = {}, *pkbuf; +- int val; +- unsigned int enable; +- +- if (count >= sizeof(kbuf)) +- return -EINVAL; +- +- if (copy_from_user(kbuf, buf, count)) +- return -EINVAL; +- +- pkbuf = strstrip(kbuf); +- +- val = kstrtoint(pkbuf, 0, &enable); +- if (val < 0) +- return val; +- +- if (enable > 1) { +- dev_err(hisi_hba->dev, "must be 0 or 1\n"); +- return -EINVAL; +- } +- +- if (enable == hisi_hba->bist_loopback_enable) +- return count; +- +- if (!hisi_hba->hw->set_bist) +- return -EPERM; +- +- val = hisi_hba->hw->set_bist(hisi_hba, (bool)enable); +- if (val < 0) +- return val; +- +- hisi_hba->bist_loopback_enable = enable; +- +- return count; +-} +- +-static int hisi_sas_debugfs_bist_enable_show(struct seq_file *s, void *p) +-{ +- struct hisi_hba *hisi_hba = s->private; +- +- seq_printf(s, "%d\n", hisi_hba->bist_loopback_enable); +- +- return 0; +-} +- +-static int hisi_sas_debugfs_bist_enable_open(struct inode *inode, +- struct file *filp) +-{ +- return single_open(filp, hisi_sas_debugfs_bist_enable_show, +- inode->i_private); +-} +- +-static const struct file_operations hisi_sas_debugfs_bist_enable_ops = { +- .open = hisi_sas_debugfs_bist_enable_open, +- .read = seq_read, +- .write = hisi_sas_debugfs_bist_enable_write, +- .llseek = seq_lseek, +- .release = single_release, +- .owner = THIS_MODULE, +-}; +- +-static int hisi_sas_debugfs_axi_show(struct seq_file *s, void *p) +-{ +- struct hisi_sas_debugfs_regs *ras = s->private; +- struct hisi_hba *hisi_hba = ras->hisi_hba; +- const struct hisi_sas_hw *hw = hisi_hba->hw; +- const void *reg_axi = hw->debugfs_reg_array[DEBUGFS_AXI]; +- +- hisi_sas_debugfs_print_reg(ras->data, +- reg_axi, s); +- +- return 0; +-} +- +-static int hisi_sas_debugfs_axi_open(struct inode *inode, struct file *filp) +-{ +- return single_open(filp, hisi_sas_debugfs_axi_show, +- inode->i_private); +-} +- +-static const struct file_operations hisi_sas_debugfs_axi_fops = { +- .open = hisi_sas_debugfs_axi_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, +- .owner = THIS_MODULE, +-}; +- +-static int hisi_sas_debugfs_ras_show(struct seq_file *s, void *p) +-{ +- struct hisi_sas_debugfs_regs *ras = s->private; +- struct hisi_hba *hisi_hba = ras->hisi_hba; +- const struct hisi_sas_hw *hw = hisi_hba->hw; +- const void *reg_ras = hw->debugfs_reg_array[DEBUGFS_RAS]; +- +- hisi_sas_debugfs_print_reg(ras->data, +- reg_ras, s); +- +- return 0; +-} +- +-static int hisi_sas_debugfs_ras_open(struct inode *inode, struct file *filp) +-{ +- return single_open(filp, hisi_sas_debugfs_ras_show, +- inode->i_private); +-} +- +-static const struct file_operations hisi_sas_debugfs_ras_fops = { +- .open = hisi_sas_debugfs_ras_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, +- .owner = THIS_MODULE, +-}; +- +- +-static int hisi_sas_debugfs_port_show(struct seq_file *s, void *p) +-{ +- struct hisi_sas_debugfs_port *port = s->private; +- struct hisi_sas_phy *phy = port->phy; +- struct hisi_hba *hisi_hba = phy->hisi_hba; +- const struct hisi_sas_hw *hw = hisi_hba->hw; +- const struct hisi_sas_debugfs_reg *reg_port = hw->debugfs_reg_port; +- +- hisi_sas_debugfs_print_reg(port->data, reg_port, s); +- +- return 0; +-} +- +-static int hisi_sas_debugfs_port_open(struct inode *inode, struct file *filp) +-{ +- return single_open(filp, hisi_sas_debugfs_port_show, inode->i_private); +-} +- +-static const struct file_operations hisi_sas_debugfs_port_fops = { +- .open = hisi_sas_debugfs_port_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, +- .owner = THIS_MODULE, +-}; +- +-static void hisi_sas_show_row_64(struct seq_file *s, int index, +- int sz, __le64 *ptr) +-{ +- int i; +- +- /* completion header size not fixed per HW version */ +- seq_printf(s, "index %04d:\n\t", index); +- /* Convert unit of sz to 8 bytes before compare */ +- for (i = 1; i <= sz / 8; i++, ptr++) { +- seq_printf(s, " 0x%016llx", le64_to_cpu(*ptr)); +- if (!(i % 2)) +- seq_puts(s, "\n\t"); +- } +- +- seq_puts(s, "\n"); +-} +- +-static void hisi_sas_show_row_32(struct seq_file *s, int index, +- int sz, __le32 *ptr) +-{ +- int i; +- +- /* completion header size not fixed per HW version */ +- seq_printf(s, "index %04d:\n\t", index); +- /* Convert unit of sz to 4 bytes before compare */ +- for (i = 1; i <= sz / 4; i++, ptr++) { +- seq_printf(s, " 0x%08x", le32_to_cpu(*ptr)); +- if (!(i % 4)) +- seq_puts(s, "\n\t"); +- } +- seq_puts(s, "\n"); +-} +- +-static void hisi_sas_cq_show_slot(struct seq_file *s, int slot, +- struct hisi_sas_debugfs_cq *debugfs_cq) +-{ +- struct hisi_sas_cq *cq = debugfs_cq->cq; +- struct hisi_hba *hisi_hba = cq->hisi_hba; +- u64 offset = hisi_hba->hw->complete_hdr_size * slot; +- __le32 *complete_hdr = debugfs_cq->complete_hdr + offset; +- +- hisi_sas_show_row_32(s, slot, +- hisi_hba->hw->complete_hdr_size, +- complete_hdr); +-} +- +-static int hisi_sas_debugfs_cq_show(struct seq_file *s, void *p) +-{ +- struct hisi_sas_debugfs_cq *debugfs_cq = s->private; +- int slot; +- +- for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) { +- hisi_sas_cq_show_slot(s, slot, debugfs_cq); +- } +- return 0; +-} +- +-static int hisi_sas_debugfs_cq_open(struct inode *inode, struct file *filp) +-{ +- return single_open(filp, hisi_sas_debugfs_cq_show, inode->i_private); +-} +- +-static const struct file_operations hisi_sas_debugfs_cq_fops = { +- .open = hisi_sas_debugfs_cq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, +- .owner = THIS_MODULE, +-}; +- +-static void hisi_sas_dq_show_slot(struct seq_file *s, int slot, void *dq_ptr) +-{ +- struct hisi_sas_debugfs_dq *debugfs_dq = dq_ptr; +- void *cmd_queue = debugfs_dq->hdr; +- u64 offset = sizeof(struct hisi_sas_cmd_hdr) * slot; +- __le32 *cmd_hdr = cmd_queue + offset; +- +- hisi_sas_show_row_32(s, slot, sizeof(struct hisi_sas_cmd_hdr), cmd_hdr); +-} +- +-static int hisi_sas_debugfs_dq_show(struct seq_file *s, void *p) +-{ +- int slot; +- +- for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) { +- hisi_sas_dq_show_slot(s, slot, s->private); +- } +- return 0; +-} +- +-static int hisi_sas_debugfs_dq_open(struct inode *inode, struct file *filp) +-{ +- return single_open(filp, hisi_sas_debugfs_dq_show, inode->i_private); +-} +- +-static const struct file_operations hisi_sas_debugfs_dq_fops = { +- .open = hisi_sas_debugfs_dq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, +- .owner = THIS_MODULE, +-}; +- +-static int hisi_sas_debugfs_iost_show(struct seq_file *s, void *p) +-{ +- struct hisi_sas_debugfs_iost *debugfs_iost = s->private; +- struct hisi_sas_iost *iost = debugfs_iost->iost; +- int i, max_command_entries = HISI_SAS_MAX_COMMANDS; +- +- for (i = 0; i < max_command_entries; i++, iost++) { +- __le64 *data = &iost->qw0; +- +- hisi_sas_show_row_64(s, i, sizeof(*iost), data); +- } +- +- return 0; +-} +- +-static int hisi_sas_debugfs_iost_open(struct inode *inode, struct file *filp) +-{ +- return single_open(filp, hisi_sas_debugfs_iost_show, inode->i_private); +-} +- +-static const struct file_operations hisi_sas_debugfs_iost_fops = { +- .open = hisi_sas_debugfs_iost_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, +- .owner = THIS_MODULE, +-}; +- +-static int hisi_sas_debugfs_iost_cache_show(struct seq_file *s, void *p) +-{ +- struct hisi_sas_debugfs_iost_cache *debugfs_iost_cache = s->private; +- struct hisi_sas_iost_itct_cache *iost_cache = debugfs_iost_cache->cache; +- u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4; +- int i, tab_idx; +- __le64 *iost; +- +- for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, iost_cache++) { +- /* +- * Data struct of IOST cache: +- * Data[1]: BIT0~15: Table index +- * Bit16: Valid mask +- * Data[2]~[9]: IOST table +- */ +- tab_idx = (iost_cache->data[1] & 0xffff); +- iost = (__le64 *)iost_cache; +- +- hisi_sas_show_row_64(s, tab_idx, cache_size, iost); +- } +- +- return 0; +-} +- +-static int hisi_sas_debugfs_iost_cache_open(struct inode *inode, +- struct file *filp) +-{ +- return single_open(filp, hisi_sas_debugfs_iost_cache_show, +- inode->i_private); +-} +- +-static const struct file_operations hisi_sas_debugfs_iost_cache_fops = { +- .open = hisi_sas_debugfs_iost_cache_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, +- .owner = THIS_MODULE, +-}; +- +-static int hisi_sas_debugfs_itct_show(struct seq_file *s, void *p) +-{ +- int i; +- struct hisi_sas_debugfs_itct *debugfs_itct = s->private; +- struct hisi_sas_itct *itct = debugfs_itct->itct; +- +- for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) { +- __le64 *data = &itct->qw0; +- +- hisi_sas_show_row_64(s, i, sizeof(*itct), data); +- } +- +- return 0; +-} +- +-static int hisi_sas_debugfs_itct_open(struct inode *inode, struct file *filp) +-{ +- return single_open(filp, hisi_sas_debugfs_itct_show, inode->i_private); +-} +- +-static const struct file_operations hisi_sas_debugfs_itct_fops = { +- .open = hisi_sas_debugfs_itct_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, +- .owner = THIS_MODULE, +-}; +- +-static int hisi_sas_debugfs_itct_cache_show(struct seq_file *s, void *p) +-{ +- struct hisi_sas_debugfs_itct_cache *debugfs_itct_cache = s->private; +- struct hisi_sas_iost_itct_cache *itct_cache = debugfs_itct_cache->cache; +- u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4; +- int i, tab_idx; +- __le64 *itct; +- +- for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, itct_cache++) { +- /* +- * Data struct of ITCT cache: +- * Data[1]: BIT0~15: Table index +- * Bit16: Valid mask +- * Data[2]~[9]: ITCT table +- */ +- tab_idx = itct_cache->data[1] & 0xffff; +- itct = (__le64 *)itct_cache; +- +- hisi_sas_show_row_64(s, tab_idx, cache_size, itct); +- } +- +- return 0; +-} +- +-static int hisi_sas_debugfs_itct_cache_open(struct inode *inode, +- struct file *filp) +-{ +- return single_open(filp, hisi_sas_debugfs_itct_cache_show, +- inode->i_private); +-} +- +-static const struct file_operations hisi_sas_debugfs_itct_cache_fops = { +- .open = hisi_sas_debugfs_itct_cache_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, +- .owner = THIS_MODULE, +-}; +- +-static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) +-{ +- u64 *debugfs_timestamp; +- int dump_index = hisi_hba->debugfs_dump_index; +- struct dentry *dump_dentry; +- struct dentry *dentry; +- char name[256]; +- int p; +- int c; +- int d; +- +- snprintf(name, 256, "%d", dump_index); +- +- dump_dentry = debugfs_create_dir(name, hisi_hba->debugfs_dump_dentry); +- +- debugfs_timestamp = &hisi_hba->debugfs_timestamp[dump_index]; +- +- debugfs_create_u64("timestamp", 0400, dump_dentry, +- debugfs_timestamp); +- +- debugfs_create_file("global", 0400, dump_dentry, +- &hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL], +- &hisi_sas_debugfs_global_fops); +- +- /* Create port dir and files */ +- dentry = debugfs_create_dir("port", dump_dentry); +- +- for (p = 0; p < hisi_hba->n_phy; p++) { +- snprintf(name, sizeof(name), "%d", p); +- debugfs_create_file(name, 0400, dentry, +- &hisi_hba->debugfs_port_reg[dump_index][p], +- &hisi_sas_debugfs_port_fops); +- } +- +- /* Create CQ dir and files */ +- dentry = debugfs_create_dir("cq", dump_dentry); +- +- for (c = 0; c < hisi_hba->queue_count; c++) { +- snprintf(name, sizeof(name), "%d", c); +- +- debugfs_create_file(name, 0400, dentry, +- &hisi_hba->debugfs_cq[dump_index][c], +- &hisi_sas_debugfs_cq_fops); +- } +- +- /* Create DQ dir and files */ +- dentry = debugfs_create_dir("dq", dump_dentry); +- +- for (d = 0; d < hisi_hba->queue_count; d++) { +- snprintf(name, sizeof(name), "%d", d); +- +- debugfs_create_file(name, 0400, dentry, +- &hisi_hba->debugfs_dq[dump_index][d], +- &hisi_sas_debugfs_dq_fops); +- } +- +- debugfs_create_file("iost", 0400, dump_dentry, +- &hisi_hba->debugfs_iost[dump_index], +- &hisi_sas_debugfs_iost_fops); +- +- debugfs_create_file("iost_cache", 0400, dump_dentry, +- &hisi_hba->debugfs_iost_cache[dump_index], +- &hisi_sas_debugfs_iost_cache_fops); +- +- debugfs_create_file("itct", 0400, dump_dentry, +- &hisi_hba->debugfs_itct[dump_index], +- &hisi_sas_debugfs_itct_fops); +- +- debugfs_create_file("itct_cache", 0400, dump_dentry, +- &hisi_hba->debugfs_itct_cache[dump_index], +- &hisi_sas_debugfs_itct_cache_fops); +- +- debugfs_create_file("axi", 0400, dump_dentry, +- &hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI], +- &hisi_sas_debugfs_axi_fops); +- +- debugfs_create_file("ras", 0400, dump_dentry, +- &hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS], +- &hisi_sas_debugfs_ras_fops); +- +- return; +-} +- +-static void hisi_sas_debugfs_snapshot_regs(struct hisi_hba *hisi_hba) +-{ +- hisi_hba->hw->snapshot_prepare(hisi_hba); +- +- hisi_sas_debugfs_snapshot_global_reg(hisi_hba); +- hisi_sas_debugfs_snapshot_port_reg(hisi_hba); +- hisi_sas_debugfs_snapshot_axi_reg(hisi_hba); +- hisi_sas_debugfs_snapshot_ras_reg(hisi_hba); +- hisi_sas_debugfs_snapshot_cq_reg(hisi_hba); +- hisi_sas_debugfs_snapshot_dq_reg(hisi_hba); +- hisi_sas_debugfs_snapshot_itct_reg(hisi_hba); +- hisi_sas_debugfs_snapshot_iost_reg(hisi_hba); +- +- /* Avoid re-create files here */ +- if (!hisi_hba->debugfs_dump_dentry) +- hisi_sas_debugfs_create_files(hisi_hba); +- +- hisi_hba->hw->snapshot_restore(hisi_hba); +-} +- +-static ssize_t hisi_sas_debugfs_trigger_dump_write(struct file *file, +- const char __user *user_buf, +- size_t count, +- loff_t *ppos) +-{ +- struct hisi_hba *hisi_hba = file->f_inode->i_private; +- u8 buf[8]; +- +- /* +- * The code, which used for upstream, check +- * the value of debugfs_snapshot here. +- * If not 0, will return -EFAULT. +- * Keep manual dump as one time only +- */ +- if (hisi_hba->debugfs_dump_index >= hisi_sas_debugfs_dump_count) +- return -EFAULT; +- +- /* Not allow to input more than 8 char */ +- if (count > sizeof(buf)) +- return -EFAULT; +- +- if (copy_from_user(buf, user_buf, count)) +- return -EFAULT; +- +- if (buf[0] == '1') +- queue_work(hisi_hba->wq, &hisi_hba->debugfs_work); +- else +- return -EFAULT; +- +- return count; +-} +- +-static const struct file_operations hisi_sas_debugfs_trigger_dump_fops = { +- .write = &hisi_sas_debugfs_trigger_dump_write, +- .owner = THIS_MODULE, +-}; +- +-static const struct { +- char *name; +-} hisi_sas_debugfs_ffe_name[FFE_CFG_MAX] = { +- { "SAS_1_5_GBPS" }, +- { "SAS_3_0_GBPS" }, +- { "SAS_6_0_GBPS" }, +- { "SAS_12_0_GBPS" }, +- { "FFE_RESV" }, +- { "SATA_1_5_GBPS" }, +- { "SATA_3_0_GBPS" }, +- { "SATA_6_0_GBPS" }, +-}; +- +-static ssize_t hisi_sas_debugfs_write(struct file *filp, +- const char __user *buf, +- size_t count, loff_t *ppos) +-{ +- struct seq_file *m = filp->private_data; +- u32 *val = m->private; +- int res; +- +- res = kstrtouint_from_user(buf, count, 0, val); +- if (res) +- return res; +- +- return count; +-} +- +-static int hisi_sas_debugfs_show(struct seq_file *s, void *p) +-{ +- u32 *val = s->private; +- +- seq_printf(s, "0x%x\n", *val); +- +- return 0; +-} +- +-static int hisi_sas_debugfs_open(struct inode *inode, struct file *filp) +-{ +- return single_open(filp, hisi_sas_debugfs_show, +- inode->i_private); +-} +- +-static const struct file_operations hisi_sas_debugfs_ops = { +- .open = hisi_sas_debugfs_open, +- .read = seq_read, +- .write = hisi_sas_debugfs_write, +- .llseek = seq_lseek, +- .release = single_release, +- .owner = THIS_MODULE, +-}; +- +-static ssize_t hisi_sas_debugfs_phy_down_cnt_write(struct file *filp, +- const char __user *buf, +- size_t count, loff_t *ppos) +-{ +- struct seq_file *s = filp->private_data; +- struct hisi_sas_phy *phy = s->private; +- unsigned int set_val; +- int res; +- +- res = kstrtouint_from_user(buf, count, 0, &set_val); +- if (res) +- return res; +- +- if (set_val > 0) +- return -EINVAL; +- +- atomic_set(&phy->down_cnt, 0); +- +- return count; +-} +- +-static int hisi_sas_debugfs_phy_down_cnt_show(struct seq_file *s, void *p) +-{ +- struct hisi_sas_phy *phy = s->private; +- +- seq_printf(s, "%d\n", atomic_read(&phy->down_cnt)); +- +- return 0; +-} +- +-static int hisi_sas_debugfs_phy_down_cnt_open(struct inode *inode, +- struct file *filp) +-{ +- return single_open(filp, hisi_sas_debugfs_phy_down_cnt_show, +- inode->i_private); +-} +- +-static const struct file_operations hisi_sas_debugfs_phy_down_cnt_ops = { +- .open = hisi_sas_debugfs_phy_down_cnt_open, +- .read = seq_read, +- .write = hisi_sas_debugfs_phy_down_cnt_write, +- .llseek = seq_lseek, +- .release = single_release, +- .owner = THIS_MODULE, +-}; +- +-void hisi_sas_debugfs_work_handler(struct work_struct *work) +-{ +- struct hisi_hba *hisi_hba = +- container_of(work, struct hisi_hba, debugfs_work); +- int debugfs_dump_index = hisi_hba->debugfs_dump_index; +- struct device *dev = hisi_hba->dev; +- u64 timestamp = local_clock(); +- +- if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) { +- dev_warn(dev, "dump count exceeded!\n"); +- return; +- } +- +- do_div(timestamp, NSEC_PER_MSEC); +- hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp; +- +- hisi_sas_debugfs_snapshot_regs(hisi_hba); +- hisi_hba->debugfs_dump_index++; +-} +-EXPORT_SYMBOL_GPL(hisi_sas_debugfs_work_handler); +- +-static void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba, int dump_index) +-{ +- struct device *dev = hisi_hba->dev; +- int i; +- +- devm_kfree(dev, hisi_hba->debugfs_iost_cache[dump_index].cache); +- devm_kfree(dev, hisi_hba->debugfs_itct_cache[dump_index].cache); +- devm_kfree(dev, hisi_hba->debugfs_iost[dump_index].iost); +- devm_kfree(dev, hisi_hba->debugfs_itct[dump_index].itct); +- +- for (i = 0; i < hisi_hba->queue_count; i++) +- devm_kfree(dev, hisi_hba->debugfs_dq[dump_index][i].hdr); +- +- for (i = 0; i < hisi_hba->queue_count; i++) +- devm_kfree(dev, +- hisi_hba->debugfs_cq[dump_index][i].complete_hdr); +- +- for (i = 0; i < DEBUGFS_REGS_NUM; i++) +- devm_kfree(dev, hisi_hba->debugfs_regs[dump_index][i].data); +- +- for (i = 0; i < hisi_hba->n_phy; i++) +- devm_kfree(dev, hisi_hba->debugfs_port_reg[dump_index][i].data); +-} +- +-static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba, int dump_index) +-{ +- const struct hisi_sas_hw *hw = hisi_hba->hw; +- struct device *dev = hisi_hba->dev; +- int p, c, d, r, i; +- size_t sz; +- struct dentry *ports_dentry; +- int phy_no; +- +- /* create bist structures */ +- hisi_hba->debugfs_bist_dentry = debugfs_create_dir("bist", +- hisi_hba->debugfs_dir); +- if (!hisi_hba->debugfs_bist_dentry) +- goto fail; +- +- if (!debugfs_create_file("link_rate", 0644, +- hisi_hba->debugfs_bist_dentry, hisi_hba, +- &hisi_sas_debugfs_bist_linkrate_ops)) +- goto fail; +- +- if (!debugfs_create_file("code_mode", 0644, +- hisi_hba->debugfs_bist_dentry, hisi_hba, +- &hisi_sas_debugfs_bist_code_mode_ops)) +- goto fail; +- +- if (!debugfs_create_file("phy_id", 0644, hisi_hba->debugfs_bist_dentry, +- hisi_hba, &hisi_sas_debugfs_bist_phy_ops)) +- goto fail; +- +- if (!debugfs_create_u32("cnt", 0644, hisi_hba->debugfs_bist_dentry, +- &hisi_hba->bist_loopback_cnt)) +- goto fail; +- +- if (!debugfs_create_file("loopback_mode", 0400, +- hisi_hba->debugfs_bist_dentry, +- hisi_hba, &hisi_sas_debugfs_bist_mode_ops)) +- goto fail; +- +- if (!debugfs_create_file("enable", 0644, hisi_hba->debugfs_bist_dentry, +- hisi_hba, &hisi_sas_debugfs_bist_enable_ops)) +- goto fail; +- +- ports_dentry = debugfs_create_dir("port", +- hisi_hba->debugfs_bist_dentry); +- +- for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) { +- struct dentry *port_dentry; +- struct dentry *ffe_dentry; +- char name[256]; +- +- snprintf(name, 256, "%d", phy_no); +- port_dentry = debugfs_create_dir(name, ports_dentry); +- ffe_dentry = debugfs_create_dir("ffe", port_dentry); +- for (i = 0; i < FFE_CFG_MAX; i++) { +- if (i == FFE_RESV) +- continue; +- debugfs_create_file(hisi_sas_debugfs_ffe_name[i].name, +- 0600, ffe_dentry, +- &hisi_hba->debugfs_bist_ffe[phy_no][i], +- &hisi_sas_debugfs_ops); +- } +- } +- +- for (r = 0; r < DEBUGFS_REGS_NUM; r++) { +- struct hisi_sas_debugfs_regs *regs = +- &hisi_hba->debugfs_regs[dump_index][r]; +- +- sz = hw->debugfs_reg_array[r]->count * 4; +- regs->data = devm_kmalloc(dev, sz, GFP_KERNEL); +- if (!regs->data) +- goto fail; +- regs->hisi_hba = hisi_hba; +- } +- +- sz = hw->debugfs_reg_port->count * 4; +- for (p = 0; p < hisi_hba->n_phy; p++) { +- struct hisi_sas_debugfs_port *port = +- &hisi_hba->debugfs_port_reg[dump_index][p]; +- +- port->data = devm_kmalloc(dev, sz, GFP_KERNEL); +- if (!port->data) +- goto fail; +- port->phy = &hisi_hba->phy[p]; +- } +- +- sz = hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS; +- for (c = 0; c < hisi_hba->queue_count; c++) { +- struct hisi_sas_debugfs_cq *cq = +- &hisi_hba->debugfs_cq[dump_index][c]; +- +- cq->complete_hdr = devm_kmalloc(dev, sz, GFP_KERNEL); +- if (!cq->complete_hdr) +- goto fail; +- cq->cq = &hisi_hba->cq[c]; +- } +- +- sz = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS; +- for (d = 0; d < hisi_hba->queue_count; d++) { +- struct hisi_sas_debugfs_dq *dq = +- &hisi_hba->debugfs_dq[dump_index][d]; +- +- dq->hdr = devm_kmalloc(dev, sz, GFP_KERNEL); +- if (!dq->hdr) +- goto fail; +- dq->dq = &hisi_hba->dq[d]; +- } +- +- sz = HISI_SAS_MAX_COMMANDS * sizeof(struct hisi_sas_iost); +- +- hisi_hba->debugfs_iost[dump_index].iost = +- devm_kmalloc(dev, sz, GFP_KERNEL); +- if (!hisi_hba->debugfs_iost[dump_index].iost) +- goto fail; +- +- sz = HISI_SAS_IOST_ITCT_CACHE_NUM * +- sizeof(struct hisi_sas_iost_itct_cache); +- +- hisi_hba->debugfs_iost_cache[dump_index].cache = +- devm_kmalloc(dev, sz, GFP_KERNEL); +- if (!hisi_hba->debugfs_iost_cache[dump_index].cache) +- goto fail; +- +- sz = HISI_SAS_IOST_ITCT_CACHE_NUM * +- sizeof(struct hisi_sas_iost_itct_cache); +- +- hisi_hba->debugfs_itct_cache[dump_index].cache = +- devm_kmalloc(dev, sz, GFP_KERNEL); +- if (!hisi_hba->debugfs_itct_cache[dump_index].cache) +- goto fail; +- +- /* New memory allocation must be locate before itct */ +- sz = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct); +- +- hisi_hba->debugfs_itct[dump_index].itct = +- devm_kmalloc(dev, sz, GFP_KERNEL); +- if (!hisi_hba->debugfs_itct[dump_index].itct) +- goto fail; +- +- return 0; +-fail: +- for (i = 0; i < hisi_sas_debugfs_dump_count; i++) +- hisi_sas_debugfs_release(hisi_hba, i); +- return -ENOMEM; +-} +- +-static void hisi_sas_debugfs_phy_down_cnt_init(struct hisi_hba *hisi_hba) +-{ +- struct dentry *dir = debugfs_create_dir("phy_down_cnt", +- hisi_hba->debugfs_dir); +- char name[16]; +- int phy_no; +- +- for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) { +- snprintf(name, 16, "%d", phy_no); +- debugfs_create_file(name, 0600, dir, +- &hisi_hba->phy[phy_no], +- &hisi_sas_debugfs_phy_down_cnt_ops); +- } +-} +- +-void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) +-{ +- struct device *dev = hisi_hba->dev; +- int i; +- +- hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev), +- hisi_sas_debugfs_dir); +- debugfs_create_file("trigger_dump", 0200, +- hisi_hba->debugfs_dir, +- hisi_hba, +- &hisi_sas_debugfs_trigger_dump_fops); +- +- hisi_hba->debugfs_dump_dentry = +- debugfs_create_dir("dump", hisi_hba->debugfs_dir); +- +- hisi_sas_debugfs_phy_down_cnt_init(hisi_hba); +- +- for (i = 0; i < hisi_sas_debugfs_dump_count; i++) { +- if (hisi_sas_debugfs_alloc(hisi_hba, i)) { +- debugfs_remove_recursive(hisi_hba->debugfs_dir); +- dev_dbg(dev, "failed to init debugfs!\n"); +- break; +- } +- } +-} +-EXPORT_SYMBOL_GPL(hisi_sas_debugfs_init); +- +-void hisi_sas_debugfs_exit(struct hisi_hba *hisi_hba) +-{ +- debugfs_remove_recursive(hisi_hba->debugfs_dir); +- hisi_hba->debugfs_dir = NULL; +-} +-EXPORT_SYMBOL_GPL(hisi_sas_debugfs_exit); +- + int hisi_sas_remove(struct platform_device *pdev) + { + struct sas_ha_struct *sha = platform_get_drvdata(pdev); +@@ -4167,6 +2803,9 @@ EXPORT_SYMBOL_GPL(hisi_sas_debugfs_dump_count); + module_param_named(debugfs_dump_count, hisi_sas_debugfs_dump_count, uint, 0444); + MODULE_PARM_DESC(hisi_sas_debugfs_dump_count, "Number of debugfs dumps to allow"); + ++struct dentry *hisi_sas_debugfs_dir; ++EXPORT_SYMBOL_GPL(hisi_sas_debugfs_dir); ++ + static __init int hisi_sas_init(void) + { + hisi_sas_stt = sas_domain_attach_transport(&hisi_sas_transport_ops); +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 0e5a0ff8365f..f15ca0b8e432 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -573,6 +573,8 @@ module_param(auto_affine_msi_experimental, bool, 0444); + MODULE_PARM_DESC(auto_affine_msi_experimental, "Enable auto-affinity of MSI IRQs as experimental:\n" + "default is off"); + ++static void debugfs_work_handler_v3_hw(struct work_struct *work); ++ + static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off) + { + void __iomem *regs = hisi_hba->regs + off; +@@ -3123,6 +3125,18 @@ static int slave_configure_v3_hw(struct scsi_device *sdev) + + return 0; + } ++#define HISI_SAS_DEBUGFS_REG(x) {#x, x} ++ ++struct hisi_sas_debugfs_reg_lu { ++ char *name; ++ int off; ++}; ++ ++struct hisi_sas_debugfs_reg { ++ const struct hisi_sas_debugfs_reg_lu *lu; ++ int count; ++ int base_off; ++}; + + static const struct hisi_sas_debugfs_reg_lu debugfs_port_reg_lu[] = { + HISI_SAS_DEBUGFS_REG(PHY_CFG), +@@ -3179,7 +3193,6 @@ static const struct hisi_sas_debugfs_reg debugfs_port_reg = { + .lu = debugfs_port_reg_lu, + .count = 0x100, /* number of port regs */ + .base_off = PORT_BASE, +- .read_port_reg = hisi_sas_phy_read32, + }; + + static const struct hisi_sas_debugfs_reg_lu debugfs_global_reg_lu[] = { +@@ -3263,7 +3276,6 @@ static const struct hisi_sas_debugfs_reg_lu debugfs_global_reg_lu[] = { + static const struct hisi_sas_debugfs_reg debugfs_global_reg = { + .lu = debugfs_global_reg_lu, + .count = 0x800, /* number of global regs */ +- .read_global_reg = hisi_sas_read32, + }; + + static const struct hisi_sas_debugfs_reg_lu debugfs_axi_reg_lu[] = { +@@ -3278,7 +3290,6 @@ static const struct hisi_sas_debugfs_reg debugfs_axi_reg = { + .lu = debugfs_axi_reg_lu, + .count = 0x61, + .base_off = AXI_MASTER_CFG_BASE, +- .read_global_reg = hisi_sas_read32, + }; + + static const struct hisi_sas_debugfs_reg_lu debugfs_ras_reg_lu[] = { +@@ -3296,7 +3307,6 @@ static const struct hisi_sas_debugfs_reg debugfs_ras_reg = { + .lu = debugfs_ras_reg_lu, + .count = 0x10, + .base_off = RAS_BASE, +- .read_global_reg = hisi_sas_read32, + }; + + static void debugfs_snapshot_prepare_v3_hw(struct hisi_hba *hisi_hba) +@@ -3557,16 +3567,8 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = { + .get_events = phy_get_events_v3_hw, + .write_gpio = write_gpio_v3_hw, + .wait_cmds_complete_timeout = wait_cmds_complete_timeout_v3_hw, +- .debugfs_reg_array[DEBUGFS_GLOBAL] = &debugfs_global_reg, +- .debugfs_reg_array[DEBUGFS_AXI] = &debugfs_axi_reg, +- .debugfs_reg_array[DEBUGFS_RAS] = &debugfs_ras_reg, +- .debugfs_reg_port = &debugfs_port_reg, +- .snapshot_prepare = debugfs_snapshot_prepare_v3_hw, +- .snapshot_restore = debugfs_snapshot_restore_v3_hw, +- .set_bist = debugfs_set_bist_v3_hw, + .get_managed_irq_aff = get_managed_irq_aff_v3_hw, +- .debugfs_work_handler = hisi_sas_debugfs_work_handler, +- .read_iost_itct_cache = read_iost_itct_cache_v3_hw, ++ .debugfs_work_handler = debugfs_work_handler_v3_hw, + }; + + static struct Scsi_Host * +@@ -3584,7 +3586,7 @@ hisi_sas_shost_alloc_pci(struct pci_dev *pdev) + hisi_hba = shost_priv(shost); + + INIT_WORK(&hisi_hba->rst_work, hisi_sas_rst_work_handler); +- INIT_WORK(&hisi_hba->debugfs_work, hisi_sas_debugfs_work_handler); ++ INIT_WORK(&hisi_hba->debugfs_work, debugfs_work_handler_v3_hw); + INIT_WORK(&hisi_hba->notify_work, ssp_notify_work_handler); + hisi_hba->hw = &hisi_sas_v3_hw; + hisi_hba->pci_dev = pdev; +@@ -3614,6 +3616,1192 @@ hisi_sas_shost_alloc_pci(struct pci_dev *pdev) + return NULL; + } + ++static void debugfs_snapshot_cq_reg_v3_hw(struct hisi_hba *hisi_hba) ++{ ++ int queue_entry_size = hisi_hba->hw->complete_hdr_size; ++ int dump_index = hisi_hba->debugfs_dump_index; ++ int i; ++ ++ for (i = 0; i < hisi_hba->queue_count; i++) ++ memcpy(hisi_hba->debugfs_cq[dump_index][i].complete_hdr, ++ hisi_hba->complete_hdr[i], ++ HISI_SAS_QUEUE_SLOTS * queue_entry_size); ++} ++ ++static void debugfs_snapshot_dq_reg_v3_hw(struct hisi_hba *hisi_hba) ++{ ++ int queue_entry_size = sizeof(struct hisi_sas_cmd_hdr); ++ int dump_index = hisi_hba->debugfs_dump_index; ++ int i; ++ ++ for (i = 0; i < hisi_hba->queue_count; i++) { ++ struct hisi_sas_cmd_hdr *debugfs_cmd_hdr, *cmd_hdr; ++ int j; ++ ++ debugfs_cmd_hdr = hisi_hba->debugfs_dq[dump_index][i].hdr; ++ cmd_hdr = hisi_hba->cmd_hdr[i]; ++ ++ for (j = 0; j < HISI_SAS_QUEUE_SLOTS; j++) ++ memcpy(&debugfs_cmd_hdr[j], &cmd_hdr[j], ++ queue_entry_size); ++ } ++} ++ ++static void debugfs_snapshot_port_reg_v3_hw(struct hisi_hba *hisi_hba) ++{ ++ int dump_index = hisi_hba->debugfs_dump_index; ++ const struct hisi_sas_debugfs_reg *port = &debugfs_port_reg; ++ int i, phy_cnt; ++ u32 offset; ++ u32 *databuf; ++ ++ for (phy_cnt = 0; phy_cnt < hisi_hba->n_phy; phy_cnt++) { ++ databuf = hisi_hba->debugfs_port_reg[dump_index][phy_cnt].data; ++ for (i = 0; i < port->count; i++, databuf++) { ++ offset = port->base_off + 4 * i; ++ *databuf = hisi_sas_phy_read32(hisi_hba, phy_cnt, ++ offset); ++ } ++ } ++} ++ ++static void debugfs_snapshot_global_reg_v3_hw(struct hisi_hba *hisi_hba) ++{ ++ int dump_index = hisi_hba->debugfs_dump_index; ++ u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL].data; ++ int i; ++ ++ for (i = 0; i < debugfs_axi_reg.count; i++, databuf++) ++ *databuf = hisi_sas_read32(hisi_hba, 4 * i); ++} ++ ++static void debugfs_snapshot_axi_reg_v3_hw(struct hisi_hba *hisi_hba) ++{ ++ int dump_index = hisi_hba->debugfs_dump_index; ++ u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI].data; ++ const struct hisi_sas_debugfs_reg *axi = &debugfs_axi_reg; ++ int i; ++ ++ for (i = 0; i < axi->count; i++, databuf++) ++ *databuf = hisi_sas_read32(hisi_hba, 4 * i + axi->base_off); ++} ++ ++static void debugfs_snapshot_ras_reg_v3_hw(struct hisi_hba *hisi_hba) ++{ ++ int dump_index = hisi_hba->debugfs_dump_index; ++ u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS].data; ++ const struct hisi_sas_debugfs_reg *ras = &debugfs_ras_reg; ++ int i; ++ ++ for (i = 0; i < ras->count; i++, databuf++) ++ *databuf = hisi_sas_read32(hisi_hba, 4 * i + ras->base_off); ++} ++ ++static void debugfs_snapshot_itct_reg_v3_hw(struct hisi_hba *hisi_hba) ++{ ++ int dump_index = hisi_hba->debugfs_dump_index; ++ void *cachebuf = hisi_hba->debugfs_itct_cache[dump_index].cache; ++ void *databuf = hisi_hba->debugfs_itct[dump_index].itct; ++ struct hisi_sas_itct *itct; ++ int i; ++ ++ read_iost_itct_cache_v3_hw(hisi_hba, HISI_SAS_ITCT_CACHE, cachebuf); ++ ++ itct = hisi_hba->itct; ++ ++ for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) { ++ memcpy(databuf, itct, sizeof(struct hisi_sas_itct)); ++ databuf += sizeof(struct hisi_sas_itct); ++ } ++} ++ ++static void debugfs_snapshot_iost_reg_v3_hw(struct hisi_hba *hisi_hba) ++{ ++ int dump_index = hisi_hba->debugfs_dump_index; ++ int max_command_entries = HISI_SAS_MAX_COMMANDS; ++ void *cachebuf = hisi_hba->debugfs_iost_cache[dump_index].cache; ++ void *databuf = hisi_hba->debugfs_iost[dump_index].iost; ++ struct hisi_sas_iost *iost; ++ int i; ++ ++ read_iost_itct_cache_v3_hw(hisi_hba, HISI_SAS_IOST_CACHE, cachebuf); ++ ++ iost = hisi_hba->iost; ++ ++ for (i = 0; i < max_command_entries; i++, iost++) { ++ memcpy(databuf, iost, sizeof(struct hisi_sas_iost)); ++ databuf += sizeof(struct hisi_sas_iost); ++ } ++} ++ ++static const char * ++debugfs_to_reg_name_v3_hw(int off, int base_off, ++ const struct hisi_sas_debugfs_reg_lu *lu) ++{ ++ for (; lu->name; lu++) { ++ if (off == lu->off - base_off) ++ return lu->name; ++ } ++ ++ return NULL; ++} ++ ++static void debugfs_print_reg_v3_hw(u32 *regs_val, struct seq_file *s, ++ const struct hisi_sas_debugfs_reg *reg) ++{ ++ int i; ++ ++ for (i = 0; i < reg->count; i++) { ++ int off = i * 4; ++ const char *name; ++ ++ name = debugfs_to_reg_name_v3_hw(off, reg->base_off, ++ reg->lu); ++ ++ if (name) ++ seq_printf(s, "0x%08x 0x%08x %s\n", off, ++ regs_val[i], name); ++ else ++ seq_printf(s, "0x%08x 0x%08x\n", off, ++ regs_val[i]); ++ } ++} ++ ++static int debugfs_global_v3_hw_show(struct seq_file *s, void *p) ++{ ++ struct hisi_sas_debugfs_regs *global = s->private; ++ ++ debugfs_print_reg_v3_hw(global->data, s, ++ &debugfs_global_reg); ++ ++ return 0; ++} ++DEFINE_SHOW_ATTRIBUTE(debugfs_global_v3_hw); ++ ++static int debugfs_axi_v3_hw_show(struct seq_file *s, void *p) ++{ ++ struct hisi_sas_debugfs_regs *axi = s->private; ++ ++ debugfs_print_reg_v3_hw(axi->data, s, ++ &debugfs_axi_reg); ++ ++ return 0; ++} ++DEFINE_SHOW_ATTRIBUTE(debugfs_axi_v3_hw); ++ ++static int debugfs_ras_v3_hw_show(struct seq_file *s, void *p) ++{ ++ struct hisi_sas_debugfs_regs *ras = s->private; ++ ++ debugfs_print_reg_v3_hw(ras->data, s, ++ &debugfs_ras_reg); ++ ++ return 0; ++} ++DEFINE_SHOW_ATTRIBUTE(debugfs_ras_v3_hw); ++ ++static int debugfs_port_v3_hw_show(struct seq_file *s, void *p) ++{ ++ struct hisi_sas_debugfs_port *port = s->private; ++ const struct hisi_sas_debugfs_reg *reg_port = &debugfs_port_reg; ++ ++ debugfs_print_reg_v3_hw(port->data, s, reg_port); ++ ++ return 0; ++} ++DEFINE_SHOW_ATTRIBUTE(debugfs_port_v3_hw); ++ ++static void debugfs_show_row_64_v3_hw(struct seq_file *s, int index, ++ int sz, __le64 *ptr) ++{ ++ int i; ++ ++ /* completion header size not fixed per HW version */ ++ seq_printf(s, "index %04d:\n\t", index); ++ for (i = 1; i <= sz / 8; i++, ptr++) { ++ seq_printf(s, " 0x%016llx", le64_to_cpu(*ptr)); ++ if (!(i % 2)) ++ seq_puts(s, "\n\t"); ++ } ++ ++ seq_puts(s, "\n"); ++} ++ ++static void debugfs_show_row_32_v3_hw(struct seq_file *s, int index, ++ int sz, __le32 *ptr) ++{ ++ int i; ++ ++ /* completion header size not fixed per HW version */ ++ seq_printf(s, "index %04d:\n\t", index); ++ for (i = 1; i <= sz / 4; i++, ptr++) { ++ seq_printf(s, " 0x%08x", le32_to_cpu(*ptr)); ++ if (!(i % 4)) ++ seq_puts(s, "\n\t"); ++ } ++ seq_puts(s, "\n"); ++} ++ ++static void debugfs_cq_show_slot_v3_hw(struct seq_file *s, int slot, ++ struct hisi_sas_debugfs_cq *debugfs_cq) ++{ ++ struct hisi_sas_cq *cq = debugfs_cq->cq; ++ struct hisi_hba *hisi_hba = cq->hisi_hba; ++ __le32 *complete_hdr = debugfs_cq->complete_hdr + ++ (hisi_hba->hw->complete_hdr_size * slot); ++ ++ debugfs_show_row_32_v3_hw(s, slot, ++ hisi_hba->hw->complete_hdr_size, ++ complete_hdr); ++} ++ ++static int debugfs_cq_v3_hw_show(struct seq_file *s, void *p) ++{ ++ struct hisi_sas_debugfs_cq *debugfs_cq = s->private; ++ int slot; ++ ++ for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) ++ debugfs_cq_show_slot_v3_hw(s, slot, debugfs_cq); ++ ++ return 0; ++} ++DEFINE_SHOW_ATTRIBUTE(debugfs_cq_v3_hw); ++ ++static void debugfs_dq_show_slot_v3_hw(struct seq_file *s, int slot, ++ void *dq_ptr) ++{ ++ struct hisi_sas_debugfs_dq *debugfs_dq = dq_ptr; ++ void *cmd_queue = debugfs_dq->hdr; ++ __le32 *cmd_hdr = cmd_queue + ++ sizeof(struct hisi_sas_cmd_hdr) * slot; ++ ++ debugfs_show_row_32_v3_hw(s, slot, sizeof(struct hisi_sas_cmd_hdr), ++ cmd_hdr); ++} ++ ++static int debugfs_dq_v3_hw_show(struct seq_file *s, void *p) ++{ ++ int slot; ++ ++ for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) ++ debugfs_dq_show_slot_v3_hw(s, slot, s->private); ++ ++ return 0; ++} ++DEFINE_SHOW_ATTRIBUTE(debugfs_dq_v3_hw); ++ ++static int debugfs_iost_v3_hw_show(struct seq_file *s, void *p) ++{ ++ struct hisi_sas_debugfs_iost *debugfs_iost = s->private; ++ struct hisi_sas_iost *iost = debugfs_iost->iost; ++ int i, max_command_entries = HISI_SAS_MAX_COMMANDS; ++ ++ for (i = 0; i < max_command_entries; i++, iost++) { ++ __le64 *data = &iost->qw0; ++ ++ debugfs_show_row_64_v3_hw(s, i, sizeof(*iost), data); ++ } ++ ++ return 0; ++} ++DEFINE_SHOW_ATTRIBUTE(debugfs_iost_v3_hw); ++ ++static int debugfs_iost_cache_v3_hw_show(struct seq_file *s, void *p) ++{ ++ struct hisi_sas_debugfs_iost_cache *debugfs_iost_cache = s->private; ++ struct hisi_sas_iost_itct_cache *iost_cache = ++ debugfs_iost_cache->cache; ++ u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4; ++ int i, tab_idx; ++ __le64 *iost; ++ ++ for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, iost_cache++) { ++ /* ++ * Data struct of IOST cache: ++ * Data[1]: BIT0~15: Table index ++ * Bit16: Valid mask ++ * Data[2]~[9]: IOST table ++ */ ++ tab_idx = (iost_cache->data[1] & 0xffff); ++ iost = (__le64 *)iost_cache; ++ ++ debugfs_show_row_64_v3_hw(s, tab_idx, cache_size, iost); ++ } ++ ++ return 0; ++} ++DEFINE_SHOW_ATTRIBUTE(debugfs_iost_cache_v3_hw); ++ ++static int debugfs_itct_v3_hw_show(struct seq_file *s, void *p) ++{ ++ int i; ++ struct hisi_sas_debugfs_itct *debugfs_itct = s->private; ++ struct hisi_sas_itct *itct = debugfs_itct->itct; ++ ++ for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) { ++ __le64 *data = &itct->qw0; ++ ++ debugfs_show_row_64_v3_hw(s, i, sizeof(*itct), data); ++ } ++ ++ return 0; ++} ++DEFINE_SHOW_ATTRIBUTE(debugfs_itct_v3_hw); ++ ++static int debugfs_itct_cache_v3_hw_show(struct seq_file *s, void *p) ++{ ++ struct hisi_sas_debugfs_itct_cache *debugfs_itct_cache = s->private; ++ struct hisi_sas_iost_itct_cache *itct_cache = ++ debugfs_itct_cache->cache; ++ u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4; ++ int i, tab_idx; ++ __le64 *itct; ++ ++ for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, itct_cache++) { ++ /* ++ * Data struct of ITCT cache: ++ * Data[1]: BIT0~15: Table index ++ * Bit16: Valid mask ++ * Data[2]~[9]: ITCT table ++ */ ++ tab_idx = itct_cache->data[1] & 0xffff; ++ itct = (__le64 *)itct_cache; ++ ++ debugfs_show_row_64_v3_hw(s, tab_idx, cache_size, itct); ++ } ++ ++ return 0; ++} ++DEFINE_SHOW_ATTRIBUTE(debugfs_itct_cache_v3_hw); ++ ++static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba) ++{ ++ u64 *debugfs_timestamp; ++ int dump_index = hisi_hba->debugfs_dump_index; ++ struct dentry *dump_dentry; ++ struct dentry *dentry; ++ char name[256]; ++ int p; ++ int c; ++ int d; ++ ++ snprintf(name, 256, "%d", dump_index); ++ ++ dump_dentry = debugfs_create_dir(name, hisi_hba->debugfs_dump_dentry); ++ ++ debugfs_timestamp = &hisi_hba->debugfs_timestamp[dump_index]; ++ ++ debugfs_create_u64("timestamp", 0400, dump_dentry, ++ debugfs_timestamp); ++ ++ debugfs_create_file("global", 0400, dump_dentry, ++ &hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL], ++ &debugfs_global_v3_hw_fops); ++ ++ /* Create port dir and files */ ++ dentry = debugfs_create_dir("port", dump_dentry); ++ for (p = 0; p < hisi_hba->n_phy; p++) { ++ snprintf(name, 256, "%d", p); ++ ++ debugfs_create_file(name, 0400, dentry, ++ &hisi_hba->debugfs_port_reg[dump_index][p], ++ &debugfs_port_v3_hw_fops); ++ } ++ ++ /* Create CQ dir and files */ ++ dentry = debugfs_create_dir("cq", dump_dentry); ++ for (c = 0; c < hisi_hba->queue_count; c++) { ++ snprintf(name, 256, "%d", c); ++ ++ debugfs_create_file(name, 0400, dentry, ++ &hisi_hba->debugfs_cq[dump_index][c], ++ &debugfs_cq_v3_hw_fops); ++ } ++ ++ /* Create DQ dir and files */ ++ dentry = debugfs_create_dir("dq", dump_dentry); ++ for (d = 0; d < hisi_hba->queue_count; d++) { ++ snprintf(name, 256, "%d", d); ++ ++ debugfs_create_file(name, 0400, dentry, ++ &hisi_hba->debugfs_dq[dump_index][d], ++ &debugfs_dq_v3_hw_fops); ++ } ++ ++ debugfs_create_file("iost", 0400, dump_dentry, ++ &hisi_hba->debugfs_iost[dump_index], ++ &debugfs_iost_v3_hw_fops); ++ ++ debugfs_create_file("iost_cache", 0400, dump_dentry, ++ &hisi_hba->debugfs_iost_cache[dump_index], ++ &debugfs_iost_cache_v3_hw_fops); ++ ++ debugfs_create_file("itct", 0400, dump_dentry, ++ &hisi_hba->debugfs_itct[dump_index], ++ &debugfs_itct_v3_hw_fops); ++ ++ debugfs_create_file("itct_cache", 0400, dump_dentry, ++ &hisi_hba->debugfs_itct_cache[dump_index], ++ &debugfs_itct_cache_v3_hw_fops); ++ ++ debugfs_create_file("axi", 0400, dump_dentry, ++ &hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI], ++ &debugfs_axi_v3_hw_fops); ++ ++ debugfs_create_file("ras", 0400, dump_dentry, ++ &hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS], ++ &debugfs_ras_v3_hw_fops); ++} ++ ++static void debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba) ++{ ++ debugfs_snapshot_prepare_v3_hw(hisi_hba); ++ ++ debugfs_snapshot_global_reg_v3_hw(hisi_hba); ++ debugfs_snapshot_port_reg_v3_hw(hisi_hba); ++ debugfs_snapshot_axi_reg_v3_hw(hisi_hba); ++ debugfs_snapshot_ras_reg_v3_hw(hisi_hba); ++ debugfs_snapshot_cq_reg_v3_hw(hisi_hba); ++ debugfs_snapshot_dq_reg_v3_hw(hisi_hba); ++ debugfs_snapshot_itct_reg_v3_hw(hisi_hba); ++ debugfs_snapshot_iost_reg_v3_hw(hisi_hba); ++ ++ debugfs_create_files_v3_hw(hisi_hba); ++ ++ debugfs_snapshot_restore_v3_hw(hisi_hba); ++} ++ ++static ssize_t debugfs_trigger_dump_v3_hw_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct hisi_hba *hisi_hba = file->f_inode->i_private; ++ char buf[8]; ++ ++ if (hisi_hba->debugfs_dump_index >= hisi_sas_debugfs_dump_count) ++ return -EFAULT; ++ ++ if (count > 8) ++ return -EFAULT; ++ ++ if (copy_from_user(buf, user_buf, count)) ++ return -EFAULT; ++ ++ if (buf[0] != '1') ++ return -EFAULT; ++ ++ queue_work(hisi_hba->wq, &hisi_hba->debugfs_work); ++ ++ return count; ++} ++ ++static const struct file_operations debugfs_trigger_dump_v3_hw_fops = { ++ .write = &debugfs_trigger_dump_v3_hw_write, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct { ++ int value; ++ char *name; ++} debugfs_loop_linkrate_v3_hw[] = { ++ { SAS_LINK_RATE_1_5_GBPS, "1.5 Gbit" }, ++ { SAS_LINK_RATE_3_0_GBPS, "3.0 Gbit" }, ++ { SAS_LINK_RATE_6_0_GBPS, "6.0 Gbit" }, ++ { SAS_LINK_RATE_12_0_GBPS, "12.0 Gbit" }, ++}; ++ ++static int debugfs_bist_linkrate_v3_hw_show(struct seq_file *s, void *p) ++{ ++ struct hisi_hba *hisi_hba = s->private; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(debugfs_loop_linkrate_v3_hw); i++) { ++ int match = (hisi_hba->bist_loopback_linkrate == ++ debugfs_loop_linkrate_v3_hw[i].value); ++ ++ seq_printf(s, "%s%s%s ", match ? "[" : "", ++ debugfs_loop_linkrate_v3_hw[i].name, ++ match ? "]" : ""); ++ } ++ seq_puts(s, "\n"); ++ ++ return 0; ++} ++ ++static ssize_t debugfs_bist_linkrate_v3_hw_write(struct file *filp, ++ const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct seq_file *m = filp->private_data; ++ struct hisi_hba *hisi_hba = m->private; ++ char kbuf[16] = {}, *pkbuf; ++ bool found = false; ++ int i; ++ ++ if (hisi_hba->bist_loopback_enable) ++ return -EPERM; ++ ++ if (count >= sizeof(kbuf)) ++ return -EOVERFLOW; ++ ++ if (copy_from_user(kbuf, buf, count)) ++ return -EINVAL; ++ ++ pkbuf = strstrip(kbuf); ++ ++ for (i = 0; i < ARRAY_SIZE(debugfs_loop_linkrate_v3_hw); i++) { ++ if (!strncmp(debugfs_loop_linkrate_v3_hw[i].name, ++ pkbuf, 16)) { ++ hisi_hba->bist_loopback_linkrate = ++ debugfs_loop_linkrate_v3_hw[i].value; ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) ++ return -EINVAL; ++ ++ return count; ++} ++ ++static int debugfs_bist_linkrate_v3_hw_open(struct inode *inode, ++ struct file *filp) ++{ ++ return single_open(filp, debugfs_bist_linkrate_v3_hw_show, ++ inode->i_private); ++} ++ ++static const struct file_operations debugfs_bist_linkrate_v3_hw_fops = { ++ .open = debugfs_bist_linkrate_v3_hw_open, ++ .read = seq_read, ++ .write = debugfs_bist_linkrate_v3_hw_write, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct { ++ int value; ++ char *name; ++} debugfs_loop_code_mode_v3_hw[] = { ++ { HISI_SAS_BIST_CODE_MODE_PRBS7, "PRBS7" }, ++ { HISI_SAS_BIST_CODE_MODE_PRBS23, "PRBS23" }, ++ { HISI_SAS_BIST_CODE_MODE_PRBS31, "PRBS31" }, ++ { HISI_SAS_BIST_CODE_MODE_JTPAT, "JTPAT" }, ++ { HISI_SAS_BIST_CODE_MODE_CJTPAT, "CJTPAT" }, ++ { HISI_SAS_BIST_CODE_MODE_SCRAMBED_0, "SCRAMBED_0" }, ++ { HISI_SAS_BIST_CODE_MODE_TRAIN, "TRAIN" }, ++ { HISI_SAS_BIST_CODE_MODE_TRAIN_DONE, "TRAIN_DONE" }, ++ { HISI_SAS_BIST_CODE_MODE_HFTP, "HFTP" }, ++ { HISI_SAS_BIST_CODE_MODE_MFTP, "MFTP" }, ++ { HISI_SAS_BIST_CODE_MODE_LFTP, "LFTP" }, ++ { HISI_SAS_BIST_CODE_MODE_FIXED_DATA, "FIXED_DATA" }, ++}; ++ ++static int debugfs_bist_code_mode_v3_hw_show(struct seq_file *s, void *p) ++{ ++ struct hisi_hba *hisi_hba = s->private; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(debugfs_loop_code_mode_v3_hw); i++) { ++ int match = (hisi_hba->bist_loopback_code_mode == ++ debugfs_loop_code_mode_v3_hw[i].value); ++ ++ seq_printf(s, "%s%s%s ", match ? "[" : "", ++ debugfs_loop_code_mode_v3_hw[i].name, ++ match ? "]" : ""); ++ } ++ seq_puts(s, "\n"); ++ ++ return 0; ++} ++ ++static ssize_t debugfs_bist_code_mode_v3_hw_write(struct file *filp, ++ const char __user *buf, ++ size_t count, ++ loff_t *ppos) ++{ ++ struct seq_file *m = filp->private_data; ++ struct hisi_hba *hisi_hba = m->private; ++ char kbuf[16] = {}, *pkbuf; ++ bool found = false; ++ int i; ++ ++ if (hisi_hba->bist_loopback_enable) ++ return -EPERM; ++ ++ if (count >= sizeof(kbuf)) ++ return -EINVAL; ++ ++ if (copy_from_user(kbuf, buf, count)) ++ return -EOVERFLOW; ++ ++ pkbuf = strstrip(kbuf); ++ ++ for (i = 0; i < ARRAY_SIZE(debugfs_loop_code_mode_v3_hw); i++) { ++ if (!strncmp(debugfs_loop_code_mode_v3_hw[i].name, ++ pkbuf, 16)) { ++ hisi_hba->bist_loopback_code_mode = ++ debugfs_loop_code_mode_v3_hw[i].value; ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) ++ return -EINVAL; ++ ++ return count; ++} ++ ++static int debugfs_bist_code_mode_v3_hw_open(struct inode *inode, ++ struct file *filp) ++{ ++ return single_open(filp, debugfs_bist_code_mode_v3_hw_show, ++ inode->i_private); ++} ++ ++static const struct file_operations debugfs_bist_code_mode_v3_hw_fops = { ++ .open = debugfs_bist_code_mode_v3_hw_open, ++ .read = seq_read, ++ .write = debugfs_bist_code_mode_v3_hw_write, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .owner = THIS_MODULE, ++}; ++ ++static ssize_t debugfs_bist_phy_v3_hw_write(struct file *filp, ++ const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct seq_file *m = filp->private_data; ++ struct hisi_hba *hisi_hba = m->private; ++ unsigned int phy_no; ++ int val; ++ ++ if (hisi_hba->bist_loopback_enable) ++ return -EPERM; ++ ++ val = kstrtouint_from_user(buf, count, 0, &phy_no); ++ if (val) ++ return val; ++ ++ if (phy_no >= hisi_hba->n_phy) ++ return -EINVAL; ++ ++ hisi_hba->bist_loopback_phy_id = phy_no; ++ ++ return count; ++} ++ ++static int debugfs_bist_phy_v3_hw_show(struct seq_file *s, void *p) ++{ ++ struct hisi_hba *hisi_hba = s->private; ++ ++ seq_printf(s, "%d\n", hisi_hba->bist_loopback_phy_id); ++ ++ return 0; ++} ++ ++static int debugfs_bist_phy_v3_hw_open(struct inode *inode, ++ struct file *filp) ++{ ++ return single_open(filp, debugfs_bist_phy_v3_hw_show, ++ inode->i_private); ++} ++ ++static const struct file_operations debugfs_bist_phy_v3_hw_fops = { ++ .open = debugfs_bist_phy_v3_hw_open, ++ .read = seq_read, ++ .write = debugfs_bist_phy_v3_hw_write, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct { ++ int value; ++ char *name; ++} debugfs_loop_modes_v3_hw[] = { ++ { HISI_SAS_BIST_LOOPBACK_MODE_DIGITAL, "digital" }, ++ { HISI_SAS_BIST_LOOPBACK_MODE_SERDES, "serdes" }, ++ { HISI_SAS_BIST_LOOPBACK_MODE_REMOTE, "remote" }, ++}; ++ ++static int debugfs_bist_mode_v3_hw_show(struct seq_file *s, void *p) ++{ ++ struct hisi_hba *hisi_hba = s->private; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(debugfs_loop_modes_v3_hw); i++) { ++ int match = (hisi_hba->bist_loopback_mode == ++ debugfs_loop_modes_v3_hw[i].value); ++ ++ seq_printf(s, "%s%s%s ", match ? "[" : "", ++ debugfs_loop_modes_v3_hw[i].name, ++ match ? "]" : ""); ++ } ++ seq_puts(s, "\n"); ++ ++ return 0; ++} ++ ++static ssize_t debugfs_bist_mode_v3_hw_write(struct file *filp, ++ const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct seq_file *m = filp->private_data; ++ struct hisi_hba *hisi_hba = m->private; ++ char kbuf[16] = {}, *pkbuf; ++ bool found = false; ++ int i; ++ ++ if (hisi_hba->bist_loopback_enable) ++ return -EPERM; ++ ++ if (count >= sizeof(kbuf)) ++ return -EINVAL; ++ ++ if (copy_from_user(kbuf, buf, count)) ++ return -EOVERFLOW; ++ ++ pkbuf = strstrip(kbuf); ++ ++ for (i = 0; i < ARRAY_SIZE(debugfs_loop_modes_v3_hw); i++) { ++ if (!strncmp(debugfs_loop_modes_v3_hw[i].name, pkbuf, 16)) { ++ hisi_hba->bist_loopback_mode = ++ debugfs_loop_modes_v3_hw[i].value; ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) ++ return -EINVAL; ++ ++ return count; ++} ++ ++static int debugfs_bist_mode_v3_hw_open(struct inode *inode, ++ struct file *filp) ++{ ++ return single_open(filp, debugfs_bist_mode_v3_hw_show, ++ inode->i_private); ++} ++ ++static const struct file_operations debugfs_bist_mode_v3_hw_fops = { ++ .open = debugfs_bist_mode_v3_hw_open, ++ .read = seq_read, ++ .write = debugfs_bist_mode_v3_hw_write, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .owner = THIS_MODULE, ++}; ++ ++static ssize_t debugfs_bist_enable_v3_hw_write(struct file *filp, ++ const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct seq_file *m = filp->private_data; ++ struct hisi_hba *hisi_hba = m->private; ++ unsigned int enable; ++ int val; ++ ++ val = kstrtouint_from_user(buf, count, 0, &enable); ++ if (val) ++ return val; ++ ++ if (enable > 1) ++ return -EINVAL; ++ ++ if (enable == hisi_hba->bist_loopback_enable) ++ return count; ++ ++ val = debugfs_set_bist_v3_hw(hisi_hba, enable); ++ if (val < 0) ++ return val; ++ ++ hisi_hba->bist_loopback_enable = enable; ++ ++ return count; ++} ++ ++static int debugfs_bist_enable_v3_hw_show(struct seq_file *s, void *p) ++{ ++ struct hisi_hba *hisi_hba = s->private; ++ ++ seq_printf(s, "%d\n", hisi_hba->bist_loopback_enable); ++ ++ return 0; ++} ++ ++static int debugfs_bist_enable_v3_hw_open(struct inode *inode, ++ struct file *filp) ++{ ++ return single_open(filp, debugfs_bist_enable_v3_hw_show, ++ inode->i_private); ++} ++ ++static const struct file_operations debugfs_bist_enable_v3_hw_fops = { ++ .open = debugfs_bist_enable_v3_hw_open, ++ .read = seq_read, ++ .write = debugfs_bist_enable_v3_hw_write, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct { ++ char *name; ++} debugfs_ffe_name_v3_hw[FFE_CFG_MAX] = { ++ { "SAS_1_5_GBPS" }, ++ { "SAS_3_0_GBPS" }, ++ { "SAS_6_0_GBPS" }, ++ { "SAS_12_0_GBPS" }, ++ { "FFE_RESV" }, ++ { "SATA_1_5_GBPS" }, ++ { "SATA_3_0_GBPS" }, ++ { "SATA_6_0_GBPS" }, ++}; ++ ++static ssize_t debugfs_v3_hw_write(struct file *filp, ++ const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct seq_file *m = filp->private_data; ++ u32 *val = m->private; ++ int res; ++ ++ res = kstrtouint_from_user(buf, count, 0, val); ++ if (res) ++ return res; ++ ++ return count; ++} ++ ++static int debugfs_v3_hw_show(struct seq_file *s, void *p) ++{ ++ u32 *val = s->private; ++ ++ seq_printf(s, "0x%x\n", *val); ++ ++ return 0; ++} ++ ++static int debugfs_v3_hw_open(struct inode *inode, struct file *filp) ++{ ++ return single_open(filp, debugfs_v3_hw_show, ++ inode->i_private); ++} ++ ++static const struct file_operations debugfs_v3_hw_fops = { ++ .open = debugfs_v3_hw_open, ++ .read = seq_read, ++ .write = debugfs_v3_hw_write, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .owner = THIS_MODULE, ++}; ++ ++static ssize_t debugfs_phy_down_cnt_v3_hw_write(struct file *filp, ++ const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct seq_file *s = filp->private_data; ++ struct hisi_sas_phy *phy = s->private; ++ unsigned int set_val; ++ int res; ++ ++ res = kstrtouint_from_user(buf, count, 0, &set_val); ++ if (res) ++ return res; ++ ++ if (set_val > 0) ++ return -EINVAL; ++ ++ atomic_set(&phy->down_cnt, 0); ++ ++ return count; ++} ++ ++static int debugfs_phy_down_cnt_v3_hw_show(struct seq_file *s, void *p) ++{ ++ struct hisi_sas_phy *phy = s->private; ++ ++ seq_printf(s, "%d\n", atomic_read(&phy->down_cnt)); ++ ++ return 0; ++} ++ ++static int debugfs_phy_down_cnt_v3_hw_open(struct inode *inode, ++ struct file *filp) ++{ ++ return single_open(filp, debugfs_phy_down_cnt_v3_hw_show, ++ inode->i_private); ++} ++ ++static const struct file_operations debugfs_phy_down_cnt_v3_hw_fops = { ++ .open = debugfs_phy_down_cnt_v3_hw_open, ++ .read = seq_read, ++ .write = debugfs_phy_down_cnt_v3_hw_write, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .owner = THIS_MODULE, ++}; ++ ++static void debugfs_work_handler_v3_hw(struct work_struct *work) ++{ ++ struct hisi_hba *hisi_hba = ++ container_of(work, struct hisi_hba, debugfs_work); ++ int debugfs_dump_index = hisi_hba->debugfs_dump_index; ++ struct device *dev = hisi_hba->dev; ++ u64 timestamp = local_clock(); ++ ++ if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) { ++ dev_warn(dev, "dump count exceeded!\n"); ++ return; ++ } ++ ++ do_div(timestamp, NSEC_PER_MSEC); ++ hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp; ++ ++ debugfs_snapshot_regs_v3_hw(hisi_hba); ++ hisi_hba->debugfs_dump_index++; ++} ++ ++static void debugfs_release_v3_hw(struct hisi_hba *hisi_hba, int dump_index) ++{ ++ struct device *dev = hisi_hba->dev; ++ int i; ++ ++ devm_kfree(dev, hisi_hba->debugfs_iost_cache[dump_index].cache); ++ devm_kfree(dev, hisi_hba->debugfs_itct_cache[dump_index].cache); ++ devm_kfree(dev, hisi_hba->debugfs_iost[dump_index].iost); ++ devm_kfree(dev, hisi_hba->debugfs_itct[dump_index].itct); ++ ++ for (i = 0; i < hisi_hba->queue_count; i++) ++ devm_kfree(dev, hisi_hba->debugfs_dq[dump_index][i].hdr); ++ ++ for (i = 0; i < hisi_hba->queue_count; i++) ++ devm_kfree(dev, ++ hisi_hba->debugfs_cq[dump_index][i].complete_hdr); ++ ++ for (i = 0; i < DEBUGFS_REGS_NUM; i++) ++ devm_kfree(dev, hisi_hba->debugfs_regs[dump_index][i].data); ++ ++ for (i = 0; i < hisi_hba->n_phy; i++) ++ devm_kfree(dev, hisi_hba->debugfs_port_reg[dump_index][i].data); ++} ++ ++static const ++struct hisi_sas_debugfs_reg *debugfs_reg_array_v3_hw[DEBUGFS_REGS_NUM] = { ++ [DEBUGFS_GLOBAL] = &debugfs_global_reg, ++ [DEBUGFS_AXI] = &debugfs_axi_reg, ++ [DEBUGFS_RAS] = &debugfs_ras_reg, ++}; ++ ++static int debugfs_alloc_v3_hw(struct hisi_hba *hisi_hba, int dump_index) ++{ ++ const struct hisi_sas_hw *hw = hisi_hba->hw; ++ struct device *dev = hisi_hba->dev; ++ int p, c, d, r, i; ++ size_t sz; ++ ++ for (r = 0; r < DEBUGFS_REGS_NUM; r++) { ++ struct hisi_sas_debugfs_regs *regs = ++ &hisi_hba->debugfs_regs[dump_index][r]; ++ ++ sz = debugfs_reg_array_v3_hw[r]->count * 4; ++ regs->data = devm_kmalloc(dev, sz, GFP_KERNEL); ++ if (!regs->data) ++ goto fail; ++ regs->hisi_hba = hisi_hba; ++ } ++ ++ sz = debugfs_port_reg.count * 4; ++ for (p = 0; p < hisi_hba->n_phy; p++) { ++ struct hisi_sas_debugfs_port *port = ++ &hisi_hba->debugfs_port_reg[dump_index][p]; ++ ++ port->data = devm_kmalloc(dev, sz, GFP_KERNEL); ++ if (!port->data) ++ goto fail; ++ port->phy = &hisi_hba->phy[p]; ++ } ++ ++ sz = hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS; ++ for (c = 0; c < hisi_hba->queue_count; c++) { ++ struct hisi_sas_debugfs_cq *cq = ++ &hisi_hba->debugfs_cq[dump_index][c]; ++ ++ cq->complete_hdr = devm_kmalloc(dev, sz, GFP_KERNEL); ++ if (!cq->complete_hdr) ++ goto fail; ++ cq->cq = &hisi_hba->cq[c]; ++ } ++ ++ sz = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS; ++ for (d = 0; d < hisi_hba->queue_count; d++) { ++ struct hisi_sas_debugfs_dq *dq = ++ &hisi_hba->debugfs_dq[dump_index][d]; ++ ++ dq->hdr = devm_kmalloc(dev, sz, GFP_KERNEL); ++ if (!dq->hdr) ++ goto fail; ++ dq->dq = &hisi_hba->dq[d]; ++ } ++ ++ sz = HISI_SAS_MAX_COMMANDS * sizeof(struct hisi_sas_iost); ++ ++ hisi_hba->debugfs_iost[dump_index].iost = ++ devm_kmalloc(dev, sz, GFP_KERNEL); ++ if (!hisi_hba->debugfs_iost[dump_index].iost) ++ goto fail; ++ ++ sz = HISI_SAS_IOST_ITCT_CACHE_NUM * ++ sizeof(struct hisi_sas_iost_itct_cache); ++ ++ hisi_hba->debugfs_iost_cache[dump_index].cache = ++ devm_kmalloc(dev, sz, GFP_KERNEL); ++ if (!hisi_hba->debugfs_iost_cache[dump_index].cache) ++ goto fail; ++ ++ sz = HISI_SAS_IOST_ITCT_CACHE_NUM * ++ sizeof(struct hisi_sas_iost_itct_cache); ++ ++ hisi_hba->debugfs_itct_cache[dump_index].cache = ++ devm_kmalloc(dev, sz, GFP_KERNEL); ++ if (!hisi_hba->debugfs_itct_cache[dump_index].cache) ++ goto fail; ++ ++ /* New memory allocation must be locate before itct */ ++ sz = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct); ++ ++ hisi_hba->debugfs_itct[dump_index].itct = ++ devm_kmalloc(dev, sz, GFP_KERNEL); ++ if (!hisi_hba->debugfs_itct[dump_index].itct) ++ goto fail; ++ ++ return 0; ++fail: ++ for (i = 0; i < hisi_sas_debugfs_dump_count; i++) ++ debugfs_release_v3_hw(hisi_hba, i); ++ return -ENOMEM; ++} ++ ++static void debugfs_phy_down_cnt_init_v3_hw(struct hisi_hba *hisi_hba) ++{ ++ struct dentry *dir = debugfs_create_dir("phy_down_cnt", ++ hisi_hba->debugfs_dir); ++ char name[16]; ++ int phy_no; ++ ++ for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) { ++ snprintf(name, 16, "%d", phy_no); ++ debugfs_create_file(name, 0600, dir, ++ &hisi_hba->phy[phy_no], ++ &debugfs_phy_down_cnt_v3_hw_fops); ++ } ++} ++ ++static void debugfs_bist_init_v3_hw(struct hisi_hba *hisi_hba) ++{ ++ struct dentry *ports_dentry; ++ int phy_no; ++ ++ hisi_hba->debugfs_bist_dentry = ++ debugfs_create_dir("bist", hisi_hba->debugfs_dir); ++ debugfs_create_file("link_rate", 0600, ++ hisi_hba->debugfs_bist_dentry, hisi_hba, ++ &debugfs_bist_linkrate_v3_hw_fops); ++ ++ debugfs_create_file("code_mode", 0600, ++ hisi_hba->debugfs_bist_dentry, hisi_hba, ++ &debugfs_bist_code_mode_v3_hw_fops); ++ ++ debugfs_create_file("fixed_code", 0600, ++ hisi_hba->debugfs_bist_dentry, ++ &hisi_hba->debugfs_bist_fixed_code[0], ++ &debugfs_v3_hw_fops); ++ ++ debugfs_create_file("fixed_code_1", 0600, ++ hisi_hba->debugfs_bist_dentry, ++ &hisi_hba->debugfs_bist_fixed_code[1], ++ &debugfs_v3_hw_fops); ++ ++ debugfs_create_file("phy_id", 0600, hisi_hba->debugfs_bist_dentry, ++ hisi_hba, &debugfs_bist_phy_v3_hw_fops); ++ ++ debugfs_create_u32("cnt", 0600, hisi_hba->debugfs_bist_dentry, ++ &hisi_hba->bist_loopback_cnt); ++ ++ debugfs_create_file("loopback_mode", 0600, ++ hisi_hba->debugfs_bist_dentry, ++ hisi_hba, &debugfs_bist_mode_v3_hw_fops); ++ ++ debugfs_create_file("enable", 0600, hisi_hba->debugfs_bist_dentry, ++ hisi_hba, &debugfs_bist_enable_v3_hw_fops); ++ ++ ports_dentry = debugfs_create_dir("port", ++ hisi_hba->debugfs_bist_dentry); ++ ++ for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) { ++ struct dentry *port_dentry; ++ struct dentry *ffe_dentry; ++ char name[256]; ++ int i; ++ ++ snprintf(name, 256, "%d", phy_no); ++ port_dentry = debugfs_create_dir(name, ports_dentry); ++ ffe_dentry = debugfs_create_dir("ffe", port_dentry); ++ for (i = 0; i < FFE_CFG_MAX; i++) { ++ if (i == FFE_RESV) ++ continue; ++ debugfs_create_file(debugfs_ffe_name_v3_hw[i].name, ++ 0600, ffe_dentry, ++ &hisi_hba->debugfs_bist_ffe[phy_no][i], ++ &debugfs_v3_hw_fops); ++ } ++ } ++ ++ hisi_hba->bist_loopback_linkrate = SAS_LINK_RATE_1_5_GBPS; ++} ++ ++static void debugfs_init_v3_hw(struct hisi_hba *hisi_hba) ++{ ++ struct device *dev = hisi_hba->dev; ++ int i; ++ ++ hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev), ++ hisi_sas_debugfs_dir); ++ debugfs_create_file("trigger_dump", 0200, ++ hisi_hba->debugfs_dir, ++ hisi_hba, ++ &debugfs_trigger_dump_v3_hw_fops); ++ ++ /* create bist structures */ ++ debugfs_bist_init_v3_hw(hisi_hba); ++ ++ hisi_hba->debugfs_dump_dentry = ++ debugfs_create_dir("dump", hisi_hba->debugfs_dir); ++ ++ debugfs_phy_down_cnt_init_v3_hw(hisi_hba); ++ ++ for (i = 0; i < hisi_sas_debugfs_dump_count; i++) { ++ if (debugfs_alloc_v3_hw(hisi_hba, i)) { ++ debugfs_remove_recursive(hisi_hba->debugfs_dir); ++ dev_dbg(dev, "failed to init debugfs!\n"); ++ break; ++ } ++ } ++} ++ ++static void debugfs_exit_v3_hw(struct hisi_hba *hisi_hba) ++{ ++ debugfs_remove_recursive(hisi_hba->debugfs_dir); ++} ++ + static int + hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) + { +@@ -3697,7 +4885,7 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) + } + + if (hisi_sas_debugfs_enable) +- hisi_sas_debugfs_init(hisi_hba); ++ debugfs_init_v3_hw(hisi_hba); + + if (hisi_hba->enable_dix_dif) { + scsi_host_set_prot(hisi_hba->shost, +@@ -3742,7 +4930,7 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) + err_out_free_irq_vectors: + pci_free_irq_vectors(pdev); + err_out_debugfs: +- hisi_sas_debugfs_exit(hisi_hba); ++ debugfs_exit_v3_hw(hisi_hba); + err_out_ha: + hisi_sas_free(hisi_hba); + scsi_host_put(shost); +@@ -3792,7 +4980,7 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev) + pci_release_regions(pdev); + pci_disable_device(pdev); + hisi_sas_free(hisi_hba); +- hisi_sas_debugfs_exit(hisi_hba); ++ debugfs_exit_v3_hw(hisi_hba); + scsi_host_put(shost); + } + +-- +2.27.0 + diff --git a/patches/0456-scsi-hisi_sas-Remove-preemptible.patch b/patches/0456-scsi-hisi_sas-Remove-preemptible.patch new file mode 100644 index 00000000..c57c173c --- /dev/null +++ b/patches/0456-scsi-hisi_sas-Remove-preemptible.patch @@ -0,0 +1,72 @@ +From ce38a602f708e768b290cc580033eef0b62779e0 Mon Sep 17 00:00:00 2001 +From: "Ahmed S. Darwish" +Date: Tue, 3 Aug 2021 14:47:28 +0800 +Subject: [PATCH 138/256] scsi: hisi_sas: Remove preemptible() + +mainline inclusion +from mainline-v5.11-rc1 +commit 18577cdcaeeb7a1ca5c3adc4d92ed2ba75699625 +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=18577cdcaeeb7a1ca5c3adc4d92ed2ba75699625 + +---------------------------------------------------------------------- + +hisi_sas_task_exec() uses preemptible() to see if it's safe to block. This +does not work for CONFIG_PREEMPT_COUNT=n kernels in which preemptible() +always returns 0. + +The problem is masked when enabling some of the common Kconfig.debug +options (like CONFIG_DEBUG_ATOMIC_SLEEP), as they implicitly enable the +preemption counter. + +In general, driver leaf functions should not make logic decisions based on +the context they're called from. The caller should be the entity +responsible for explicitly indicating context. + +Since hisi_sas_task_exec() already has a gfp_t flags parameter, use it as +the explicit context marker. + +Link: https://lore.kernel.org/r/20201126132952.2287996-3-bigeasy@linutronix.de +Fixes: 214e702d4b70 ("scsi: hisi_sas: Adjust task reject period during host reset") +Fixes: 550c0d89d52d ("scsi: hisi_sas: Replace in_softirq() check in hisi_sas_task_exec()") +Cc: Xiaofei Tan +Cc: Xiang Chen +Cc: John Garry +Acked-by: John Garry +Signed-off-by: Ahmed S. Darwish +Signed-off-by: Sebastian Andrzej Siewior +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index b6bf733e4f0b..31b12a8d1289 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -609,9 +609,10 @@ static int hisi_sas_task_exec(struct sas_task *task, gfp_t gfp_flags, + hisi_hba = dev_to_hisi_hba(device); + dev = hisi_hba->dev; + +- if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags))) +- return -EINVAL; +- ++ if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags))) { ++ if (!gfpflags_allow_blocking(gfp_flags)) ++ return -EINVAL; ++ } + + /* protect task_prep and start_delivery sequence */ + rc = hisi_sas_task_prep(task, is_tmf, tmf, &pass, &dq); +-- +2.27.0 + diff --git a/patches/0457-scsi-hisi_sas-use-threaded-irq-to-process-CQ-interru.patch b/patches/0457-scsi-hisi_sas-use-threaded-irq-to-process-CQ-interru.patch new file mode 100644 index 00000000..59116195 --- /dev/null +++ b/patches/0457-scsi-hisi_sas-use-threaded-irq-to-process-CQ-interru.patch @@ -0,0 +1,325 @@ +From 75f6344f59ff77e44166df6b740b512cc14fb961 Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Mon, 20 Jan 2020 20:22:31 +0800 +Subject: [PATCH 139/256] scsi: hisi_sas: use threaded irq to process CQ + interrupts + +mainline inclusion +from mainline-v5.6-rc1 +commit 81f338e9709db0b67d05bab02809d6a4e6694884 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=81f338e9709db0b67d05bab02809d6a4e6694884 + +---------------------------------------------------------------------- + +Currently IRQ_EFFECTIVE_AFF_MASK is enabled for ARM_GIC and ARM_GIC3, so it +only allows a single target CPU in the affinity mask to process interrupts +and also interrupt thread, and the performance of using threaded irq is +almost the same as tasklet. But if the config is not enabled, the interrupt +thread will be allowed all the CPUs in the affinity mask. At that situation +it improves the performance (about 20%). + +Note: IRQ_EFFECTIVE_AFF_MASK is configured differently for different +architecture chip, and it seems to be better to make it be configured +easily. + +Link: https://lore.kernel.org/r/1579522957-4393-2-git-send-email-john.garry@huawei.com +Signed-off-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas.h + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 4 ++-- + drivers/scsi/hisi_sas/hisi_sas_main.c | 22 +++++++++--------- + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 26 ++++++++------------- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 32 +++++++++++++------------- + 4 files changed, 39 insertions(+), 45 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 49aee1c365e2..b8547e905a80 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -204,9 +204,9 @@ struct hisi_sas_port { + struct hisi_sas_cq { + struct hisi_hba *hisi_hba; + const struct cpumask *irq_mask; +- struct tasklet_struct tasklet; + int rd_point; + int id; ++ int irq_no; + }; + + struct hisi_sas_dq { +@@ -678,7 +678,7 @@ extern void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, + extern void hisi_sas_init_mem(struct hisi_hba *hisi_hba); + extern void hisi_sas_rst_work_handler(struct work_struct *work); + extern void hisi_sas_sync_rst_work_handler(struct work_struct *work); +-extern void hisi_sas_kill_tasklets(struct hisi_hba *hisi_hba); ++extern void hisi_sas_sync_irqs(struct hisi_hba *hisi_hba); + extern void hisi_sas_phy_oob_ready(struct hisi_hba *hisi_hba, int phy_no); + extern bool hisi_sas_notify_phy_event(struct hisi_sas_phy *phy, + enum hisi_sas_phy_event event); +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 31b12a8d1289..23f688bd70e5 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1278,10 +1278,10 @@ static int hisi_sas_exec_internal_tmf_task(struct domain_device *device, + struct hisi_sas_cq *cq = + &hisi_hba->cq[slot->dlvry_queue]; + /* +- * flush tasklet to avoid free'ing task ++ * sync irq to avoid free'ing task + * before using task in IO completion + */ +- tasklet_kill(&cq->tasklet); ++ synchronize_irq(cq->irq_no); + slot->task = NULL; + } + +@@ -1685,11 +1685,11 @@ static int hisi_sas_abort_task(struct sas_task *task) + + if (slot) { + /* +- * flush tasklet to avoid free'ing task ++ * sync irq to avoid free'ing task + * before using task in IO completion + */ + cq = &hisi_hba->cq[slot->dlvry_queue]; +- tasklet_kill(&cq->tasklet); ++ synchronize_irq(cq->irq_no); + } + spin_unlock_irqrestore(&task->task_state_lock, flags); + rc = TMF_RESP_FUNC_COMPLETE; +@@ -1763,10 +1763,10 @@ static int hisi_sas_abort_task(struct sas_task *task) + if (((rc < 0) || (rc == TMF_RESP_FUNC_FAILED)) && + task->lldd_task) { + /* +- * flush tasklet to avoid free'ing task ++ * sync irq to avoid free'ing task + * before using task in IO completion + */ +- tasklet_kill(&cq->tasklet); ++ synchronize_irq(cq->irq_no); + slot->task = NULL; + } + } +@@ -2150,10 +2150,10 @@ _hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, + struct hisi_sas_cq *cq = + &hisi_hba->cq[slot->dlvry_queue]; + /* +- * flush tasklet to avoid free'ing task ++ * sync irq to avoid free'ing task + * before using task in IO completion + */ +- tasklet_kill(&cq->tasklet); ++ synchronize_irq(cq->irq_no); + slot->task = NULL; + } + dev_err(dev, "internal task abort: timeout and not done.\n"); +@@ -2306,17 +2306,17 @@ void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy) + } + EXPORT_SYMBOL_GPL(hisi_sas_phy_down); + +-void hisi_sas_kill_tasklets(struct hisi_hba *hisi_hba) ++void hisi_sas_sync_irqs(struct hisi_hba *hisi_hba) + { + int i; + + for (i = 0; i < hisi_hba->nvecs; i++) { + struct hisi_sas_cq *cq = &hisi_hba->cq[i]; + +- tasklet_kill(&cq->tasklet); ++ synchronize_irq(cq->irq_no); + } + } +-EXPORT_SYMBOL_GPL(hisi_sas_kill_tasklets); ++EXPORT_SYMBOL_GPL(hisi_sas_sync_irqs); + + int hisi_sas_host_reset(struct Scsi_Host *shost, int reset_type) + { +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +index 1d1ee655c9fb..55331ffa3be5 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -3128,9 +3128,9 @@ static irqreturn_t fatal_axi_int_v2_hw(int irq_no, void *p) + return IRQ_HANDLED; + } + +-static void cq_tasklet_v2_hw(unsigned long val) ++static irqreturn_t cq_thread_v2_hw(int irq_no, void *p) + { +- struct hisi_sas_cq *cq = (struct hisi_sas_cq *)val; ++ struct hisi_sas_cq *cq = p; + struct hisi_hba *hisi_hba = cq->hisi_hba; + struct hisi_sas_slot *slot; + struct hisi_sas_itct *itct; +@@ -3192,6 +3192,8 @@ static void cq_tasklet_v2_hw(unsigned long val) + /* update rd_point */ + cq->rd_point = rd_point; + hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point); ++ ++ return IRQ_HANDLED; + } + + static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p) +@@ -3202,9 +3204,7 @@ static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p) + + hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue); + +- tasklet_schedule(&cq->tasklet); +- +- return IRQ_HANDLED; ++ return IRQ_WAKE_THREAD; + } + + static irqreturn_t sata_int_v2_hw(int irq_no, void *p) +@@ -3371,18 +3371,18 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) + + for (queue_no = 0; queue_no < hisi_hba->queue_count; queue_no++) { + struct hisi_sas_cq *cq = &hisi_hba->cq[queue_no]; +- struct tasklet_struct *t = &cq->tasklet; + +- irq = irq_map[queue_no + 96]; +- rc = devm_request_irq(dev, irq, cq_interrupt_v2_hw, 0, +- DRV_NAME " cq", cq); ++ cq->irq_no = irq_map[queue_no + 96]; ++ rc = devm_request_threaded_irq(dev, cq->irq_no, ++ cq_interrupt_v2_hw, ++ cq_thread_v2_hw, IRQF_ONESHOT, ++ DRV_NAME " cq", cq); + if (rc) { + dev_err(dev, "irq init: could not request cq interrupt %d, rc=%d\n", + irq, rc); + rc = -ENOENT; + goto err_out; + } +- tasklet_init(t, cq_tasklet_v2_hw, (unsigned long)cq); + } + + hisi_hba->nvecs = hisi_hba->queue_count; +@@ -3444,7 +3444,6 @@ static int soft_reset_v2_hw(struct hisi_hba *hisi_hba) + + interrupt_disable_v2_hw(hisi_hba); + hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0x0); +- hisi_sas_kill_tasklets(hisi_hba); + + hisi_sas_stop_phys(hisi_hba); + +@@ -3618,11 +3617,6 @@ static int hisi_sas_v2_probe(struct platform_device *pdev) + + static int hisi_sas_v2_remove(struct platform_device *pdev) + { +- struct sas_ha_struct *sha = platform_get_drvdata(pdev); +- struct hisi_hba *hisi_hba = sha->lldd_ha; +- +- hisi_sas_kill_tasklets(hisi_hba); +- + return hisi_sas_remove(pdev); + } + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index f15ca0b8e432..fcb7c704f94c 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -2639,9 +2639,9 @@ static void hisi_sas_disk_err_handler(struct hisi_hba *hisi_hba, + hisi_sas_ata_device_link_abort(device); + } + +-static void cq_tasklet_v3_hw(unsigned long val) ++static irqreturn_t cq_thread_v3_hw(int irq_no, void *p) + { +- struct hisi_sas_cq *cq = (struct hisi_sas_cq *)val; ++ struct hisi_sas_cq *cq = p; + struct hisi_hba *hisi_hba = cq->hisi_hba; + struct hisi_sas_slot *slot; + struct hisi_sas_complete_v3_hdr *complete_queue; +@@ -2685,6 +2685,8 @@ static void cq_tasklet_v3_hw(unsigned long val) + hisi_sas_write32(hisi_hba, + COMPL_Q_0_RD_PTR + (NEXT_DQCQ_REG_OFF * queue), + rd_point); ++ ++ return IRQ_HANDLED; + } + + static irqreturn_t cq_interrupt_v3_hw(int irq_no, void *p) +@@ -2695,9 +2697,7 @@ static irqreturn_t cq_interrupt_v3_hw(int irq_no, void *p) + + hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue); + +- tasklet_schedule(&cq->tasklet); +- +- return IRQ_HANDLED; ++ return IRQ_WAKE_THREAD; + } + + static int interrupt_preinit_v3_hw(struct hisi_hba *hisi_hba) +@@ -2767,25 +2767,27 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) + if (hisi_sas_intr_conv) + dev_info(dev, "Enable interrupt converge\n"); + +- /* Init tasklets for cq only */ + for (i = 0; i < hisi_hba->nvecs; i++) { + struct hisi_sas_cq *cq = &hisi_hba->cq[i]; +- struct tasklet_struct *t = &cq->tasklet; + int nr = hisi_sas_intr_conv ? PCI_IRQ_CQ_BASE : + PCI_IRQ_CQ_BASE + i; +- unsigned long irqflags = hisi_sas_intr_conv ? IRQF_SHARED : 0; + +- rc = devm_request_irq(dev, pci_irq_vector(pdev, nr), +- cq_interrupt_v3_hw, irqflags, +- DRV_NAME " cq", cq); ++ unsigned long irqflags = hisi_sas_intr_conv ? IRQF_SHARED : ++ IRQF_ONESHOT; ++ ++ cq->irq_no = pci_irq_vector(pdev, nr); ++ rc = devm_request_threaded_irq(dev, cq->irq_no, ++ cq_interrupt_v3_hw, ++ cq_thread_v3_hw, ++ irqflags, ++ DRV_NAME " cq", cq); ++ + if (rc) { + dev_err(dev, "could not request cq%d interrupt, rc=%d\n", + i, rc); + return -ENOENT; + } + +- tasklet_init(t, cq_tasklet_v3_hw, (uintptr_t)cq); +- + cq->irq_mask = pci_irq_get_affinity(pdev, + i + HISI_SAS_CQ_INT_BASE_VECTORS_V3_HW); + if (!cq->irq_mask) { +@@ -2899,7 +2901,6 @@ static int disable_host_v3_hw(struct hisi_hba *hisi_hba) + + interrupt_disable_v3_hw(hisi_hba); + hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0x0); +- hisi_sas_kill_tasklets(hisi_hba); + + hisi_sas_stop_phys(hisi_hba); + +@@ -3318,7 +3319,7 @@ static void debugfs_snapshot_prepare_v3_hw(struct hisi_hba *hisi_hba) + /* delay:100ms, timeout:5s */ + wait_cmds_complete_timeout_v3_hw(hisi_hba, 100, 5000); + +- hisi_sas_kill_tasklets(hisi_hba); ++ hisi_sas_sync_irqs(hisi_hba); + } + + static void debugfs_snapshot_restore_v3_hw(struct hisi_hba *hisi_hba) +@@ -4976,7 +4977,6 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev) + sas_remove_host(sha->core.shost); + + hisi_sas_v3_destroy_irqs(pdev, hisi_hba); +- hisi_sas_kill_tasklets(hisi_hba); + pci_release_regions(pdev); + pci_disable_device(pdev); + hisi_sas_free(hisi_hba); +-- +2.27.0 + diff --git a/patches/0458-genirq-core-Introduce-struct-irq_affinity_desc.patch b/patches/0458-genirq-core-Introduce-struct-irq_affinity_desc.patch new file mode 100644 index 00000000..ee66733b --- /dev/null +++ b/patches/0458-genirq-core-Introduce-struct-irq_affinity_desc.patch @@ -0,0 +1,457 @@ +From 21d517137282d919510dc25ae54ab6a8bb4b530e Mon Sep 17 00:00:00 2001 +From: Dou Liyang +Date: Tue, 4 Dec 2018 23:51:20 +0800 +Subject: [PATCH 140/256] genirq/core: Introduce struct irq_affinity_desc + +mainline inclusion +from mainline-v5.0-rc1 +commit bec04037e4e484f41ee4d9409e40616874169d20 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bec04037e4e484f41ee4d9409e40616874169d20 + +---------------------------------------------------------------------- + +The interrupt affinity management uses straight cpumask pointers to convey +the automatically assigned affinity masks for managed interrupts. The core +interrupt descriptor allocation also decides based on the pointer being non +NULL whether an interrupt is managed or not. + +Devices which use managed interrupts usually have two classes of +interrupts: + + - Interrupts for multiple device queues + - Interrupts for general device management + +Currently both classes are treated the same way, i.e. as managed +interrupts. The general interrupts get the default affinity mask assigned +while the device queue interrupts are spread out over the possible CPUs. + +Treating the general interrupts as managed is both a limitation and under +certain circumstances a bug. Assume the following situation: + + default_irq_affinity = 4..7 + +So if CPUs 4-7 are offlined, then the core code will shut down the device +management interrupts because the last CPU in their affinity mask went +offline. + +It's also a limitation because it's desired to allow manual placement of +the general device interrupts for various reasons. If they are marked +managed then the interrupt affinity setting from both user and kernel space +is disabled. + +To remedy that situation it's required to convey more information than the +cpumasks through various interfaces related to interrupt descriptor +allocation. + +Instead of adding yet another argument, create a new data structure +'irq_affinity_desc' which for now just contains the cpumask. This struct +can be expanded to convey auxiliary information in the next step. + +No functional change, just preparatory work. + +[ tglx: Simplified logic and clarified changelog ] + +Suggested-by: Thomas Gleixner +Suggested-by: Bjorn Helgaas +Signed-off-by: Dou Liyang +Signed-off-by: Thomas Gleixner +Cc: linux-pci@vger.kernel.org +Cc: kashyap.desai@broadcom.com +Cc: shivasharan.srikanteshwara@broadcom.com +Cc: sumit.saxena@broadcom.com +Cc: ming.lei@redhat.com +Cc: hch@lst.de +Cc: douliyang1@huawei.com +Link: https://lkml.kernel.org/r/20181204155122.6327-2-douliyangs@gmail.com + +Signed-off-by: YunYi Yang + + Conflicts: + kernel/irq/affinity.c +--- + drivers/pci/msi.c | 9 ++++----- + include/linux/interrupt.h | 14 ++++++++++++-- + include/linux/irq.h | 6 ++++-- + include/linux/irqdomain.h | 6 ++++-- + include/linux/msi.h | 4 ++-- + kernel/irq/affinity.c | 20 ++++++++++++-------- + kernel/irq/devres.c | 4 ++-- + kernel/irq/irqdesc.c | 20 +++++++++++--------- + kernel/irq/irqdomain.c | 5 +++-- + kernel/irq/msi.c | 8 ++++---- + 10 files changed, 58 insertions(+), 38 deletions(-) + +diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c +index 8138f67123a1..b76c9c03e93d 100644 +--- a/drivers/pci/msi.c ++++ b/drivers/pci/msi.c +@@ -555,14 +555,13 @@ static int populate_msi_sysfs(struct pci_dev *pdev) + static struct msi_desc * + msi_setup_entry(struct pci_dev *dev, int nvec, const struct irq_affinity *affd) + { +- struct cpumask *masks = NULL; ++ struct irq_affinity_desc *masks = NULL; + struct msi_desc *entry; + u16 control; + + if (affd) + masks = irq_create_affinity_masks(nvec, affd); + +- + /* MSI Entry Initialization */ + entry = alloc_msi_entry(&dev->dev, nvec, masks); + if (!entry) +@@ -707,7 +706,7 @@ static int msix_setup_entries(struct pci_dev *dev, void __iomem *base, + struct msix_entry *entries, int nvec, + const struct irq_affinity *affd) + { +- struct cpumask *curmsk, *masks = NULL; ++ struct irq_affinity_desc *curmsk, *masks = NULL; + struct msi_desc *entry; + void __iomem *addr; + int ret, i; +@@ -1307,7 +1306,7 @@ const struct cpumask *pci_irq_get_affinity(struct pci_dev *dev, int nr) + + for_each_pci_msi_entry(entry, dev) { + if (i == nr) +- return entry->affinity; ++ return &entry->affinity->mask; + i++; + } + WARN_ON_ONCE(1); +@@ -1319,7 +1318,7 @@ const struct cpumask *pci_irq_get_affinity(struct pci_dev *dev, int nr) + nr >= entry->nvec_used)) + return NULL; + +- return &entry->affinity[nr]; ++ return &entry->affinity[nr].mask; + } else { + return cpu_possible_mask; + } +diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h +index 9c60dc87963a..02d673cc6178 100644 +--- a/include/linux/interrupt.h ++++ b/include/linux/interrupt.h +@@ -273,6 +273,14 @@ struct irq_affinity { + int post_vectors; + }; + ++/** ++ * struct irq_affinity_desc - Interrupt affinity descriptor ++ * @mask: cpumask to hold the affinity assignment ++ */ ++struct irq_affinity_desc { ++ struct cpumask mask; ++}; ++ + #if defined(CONFIG_SMP) + + extern cpumask_var_t irq_default_affinity; +@@ -288,7 +296,9 @@ extern int irq_set_affinity_hint(unsigned int irq, const struct cpumask *m); + extern int + irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify); + +-struct cpumask *irq_create_affinity_masks(int nvec, const struct irq_affinity *affd); ++struct irq_affinity_desc * ++irq_create_affinity_masks(int nvec, const struct irq_affinity *affd); ++ + int irq_calc_affinity_vectors(int minvec, int maxvec, const struct irq_affinity *affd); + + #else /* CONFIG_SMP */ +@@ -322,7 +332,7 @@ irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify) + return 0; + } + +-static inline struct cpumask * ++static inline struct irq_affinity_desc * + irq_create_affinity_masks(int nvec, const struct irq_affinity *affd) + { + return NULL; +diff --git a/include/linux/irq.h b/include/linux/irq.h +index ff291f273200..65ab2d0fa392 100644 +--- a/include/linux/irq.h ++++ b/include/linux/irq.h +@@ -27,6 +27,7 @@ + struct seq_file; + struct module; + struct msi_msg; ++struct irq_affinity_desc; + enum irqchip_irq_state; + + /* +@@ -891,11 +892,12 @@ struct cpumask *irq_data_get_effective_affinity_mask(struct irq_data *d) + unsigned int arch_dynirq_lower_bound(unsigned int from); + + int __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node, +- struct module *owner, const struct cpumask *affinity); ++ struct module *owner, ++ const struct irq_affinity_desc *affinity); + + int __devm_irq_alloc_descs(struct device *dev, int irq, unsigned int from, + unsigned int cnt, int node, struct module *owner, +- const struct cpumask *affinity); ++ const struct irq_affinity_desc *affinity); + + /* use macros to avoid needing export.h for THIS_MODULE */ + #define irq_alloc_descs(irq, from, cnt, node) \ +diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h +index a4796afd6640..4b32a46f7a83 100644 +--- a/include/linux/irqdomain.h ++++ b/include/linux/irqdomain.h +@@ -44,6 +44,7 @@ struct irq_chip; + struct irq_data; + struct cpumask; + struct seq_file; ++struct irq_affinity_desc; + + /* Number of irqs reserved for a legacy isa controller */ + #define NUM_ISA_INTERRUPTS 16 +@@ -278,7 +279,7 @@ extern bool irq_domain_check_msi_remap(void); + extern void irq_set_default_host(struct irq_domain *host); + extern int irq_domain_alloc_descs(int virq, unsigned int nr_irqs, + irq_hw_number_t hwirq, int node, +- const struct cpumask *affinity); ++ const struct irq_affinity_desc *affinity); + + static inline struct fwnode_handle *of_node_to_fwnode(struct device_node *node) + { +@@ -461,7 +462,8 @@ static inline struct irq_domain *irq_domain_add_hierarchy(struct irq_domain *par + + extern int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base, + unsigned int nr_irqs, int node, void *arg, +- bool realloc, const struct cpumask *affinity); ++ bool realloc, ++ const struct irq_affinity_desc *affinity); + extern void irq_domain_free_irqs(unsigned int virq, unsigned int nr_irqs); + extern int irq_domain_activate_irq(struct irq_data *irq_data, bool early); + extern void irq_domain_deactivate_irq(struct irq_data *irq_data); +diff --git a/include/linux/msi.h b/include/linux/msi.h +index 62982e6afddf..c0ad2a47a290 100644 +--- a/include/linux/msi.h ++++ b/include/linux/msi.h +@@ -76,7 +76,7 @@ struct msi_desc { + unsigned int nvec_used; + struct device *dev; + struct msi_msg msg; +- struct cpumask *affinity; ++ struct irq_affinity_desc *affinity; + + union { + /* PCI MSI/X specific data */ +@@ -144,7 +144,7 @@ static inline void pci_write_msi_msg(unsigned int irq, struct msi_msg *msg) + #endif /* CONFIG_PCI_MSI */ + + struct msi_desc *alloc_msi_entry(struct device *dev, int nvec, +- const struct cpumask *affinity); ++ const struct irq_affinity_desc *affinity); + void free_msi_entry(struct msi_desc *entry); + void __pci_read_msi_msg(struct msi_desc *entry, struct msi_msg *msg); + void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg); +diff --git a/kernel/irq/affinity.c b/kernel/irq/affinity.c +index e12cdf637c71..2aa435ceb874 100644 +--- a/kernel/irq/affinity.c ++++ b/kernel/irq/affinity.c +@@ -99,7 +99,7 @@ static int irq_build_affinity_masks(const struct irq_affinity *affd, + cpumask_var_t *node_to_cpumask, + const struct cpumask *cpu_mask, + struct cpumask *nmsk, +- struct cpumask *masks) ++ struct irq_affinity_desc *masks) + { + int n, nodes, cpus_per_vec, extra_vecs, done = 0; + int last_affv = affd->pre_vectors + numvecs; +@@ -117,7 +117,9 @@ static int irq_build_affinity_masks(const struct irq_affinity *affd, + */ + if (numvecs <= nodes) { + for_each_node_mask(n, nodemsk) { +- cpumask_or(masks + curvec, masks + curvec, node_to_cpumask[n]); ++ cpumask_or(&masks[curvec].mask, ++ &masks[curvec].mask, ++ node_to_cpumask[n]); + if (++curvec == last_affv) + curvec = affd->pre_vectors; + } +@@ -150,7 +152,8 @@ static int irq_build_affinity_masks(const struct irq_affinity *affd, + cpus_per_vec++; + --extra_vecs; + } +- irq_spread_init_one(masks + curvec, nmsk, cpus_per_vec); ++ irq_spread_init_one(&masks[curvec].mask, nmsk, ++ cpus_per_vec); + } + + done += v; +@@ -165,20 +168,21 @@ static int irq_build_affinity_masks(const struct irq_affinity *affd, + return done; + } + ++ + /** + * irq_create_affinity_masks - Create affinity masks for multiqueue spreading + * @nvecs: The total number of vectors + * @affd: Description of the affinity requirements + * +- * Returns the masks pointer or NULL if allocation failed. ++ * Returns the irq_affinity_desc pointer or NULL if allocation failed. + */ +-struct cpumask * ++struct irq_affinity_desc * + irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd) + { + int affvecs = nvecs - affd->pre_vectors - affd->post_vectors; + int curvec, usedvecs; + cpumask_var_t nmsk, npresmsk, *node_to_cpumask; +- struct cpumask *masks = NULL; ++ struct irq_affinity_desc *masks = NULL; + + /* + * If there aren't any vectors left after applying the pre/post +@@ -203,7 +207,7 @@ irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd) + + /* Fill out vectors at the beginning that don't need affinity */ + for (curvec = 0; curvec < affd->pre_vectors; curvec++) +- cpumask_copy(masks + curvec, irq_default_affinity); ++ cpumask_copy(&masks[curvec].mask, irq_default_affinity); + + /* Stabilize the cpumasks */ + get_online_cpus(); +@@ -236,7 +240,7 @@ irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd) + else + curvec = affd->pre_vectors + usedvecs; + for (; curvec < nvecs; curvec++) +- cpumask_copy(masks + curvec, irq_default_affinity); ++ cpumask_copy(&masks[curvec].mask, irq_default_affinity); + + outnodemsk: + free_node_to_cpumask(node_to_cpumask); +diff --git a/kernel/irq/devres.c b/kernel/irq/devres.c +index 6a682c229e10..5d5378ea0afe 100644 +--- a/kernel/irq/devres.c ++++ b/kernel/irq/devres.c +@@ -169,7 +169,7 @@ static void devm_irq_desc_release(struct device *dev, void *res) + * @cnt: Number of consecutive irqs to allocate + * @node: Preferred node on which the irq descriptor should be allocated + * @owner: Owning module (can be NULL) +- * @affinity: Optional pointer to an affinity mask array of size @cnt ++ * @affinity: Optional pointer to an irq_affinity_desc array of size @cnt + * which hints where the irq descriptors should be allocated + * and which default affinities to use + * +@@ -179,7 +179,7 @@ static void devm_irq_desc_release(struct device *dev, void *res) + */ + int __devm_irq_alloc_descs(struct device *dev, int irq, unsigned int from, + unsigned int cnt, int node, struct module *owner, +- const struct cpumask *affinity) ++ const struct irq_affinity_desc *affinity) + { + struct irq_desc_devres *dr; + int base; +diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c +index c0248d4dde19..d3ac4c4cd6a3 100644 +--- a/kernel/irq/irqdesc.c ++++ b/kernel/irq/irqdesc.c +@@ -464,28 +464,29 @@ static void free_desc(unsigned int irq) + } + + static int alloc_descs(unsigned int start, unsigned int cnt, int node, +- const struct cpumask *affinity, struct module *owner) ++ const struct irq_affinity_desc *affinity, ++ struct module *owner) + { +- const struct cpumask *mask = NULL; + struct irq_desc *desc; + unsigned int flags; + int i; + + /* Validate affinity mask(s) */ + if (affinity) { +- for (i = 0, mask = affinity; i < cnt; i++, mask++) { +- if (cpumask_empty(mask)) ++ for (i = 0; i < cnt; i++) { ++ if (cpumask_empty(&affinity[i].mask)) + return -EINVAL; + } + } + + flags = affinity ? IRQD_AFFINITY_MANAGED | IRQD_MANAGED_SHUTDOWN : 0; +- mask = NULL; + + for (i = 0; i < cnt; i++) { ++ const struct cpumask *mask = NULL; ++ + if (affinity) { +- node = cpu_to_node(cpumask_first(affinity)); +- mask = affinity; ++ mask = &affinity->mask; ++ node = cpu_to_node(cpumask_first(mask)); + affinity++; + } + desc = alloc_desc(start + i, node, flags, mask, owner); +@@ -592,7 +593,7 @@ static void free_desc(unsigned int irq) + } + + static inline int alloc_descs(unsigned int start, unsigned int cnt, int node, +- const struct cpumask *affinity, ++ const struct irq_affinity_desc *affinity, + struct module *owner) + { + u32 i; +@@ -767,7 +768,8 @@ EXPORT_SYMBOL_GPL(irq_free_descs); + */ + int __ref + __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node, +- struct module *owner, const struct cpumask *affinity) ++ struct module *owner, ++ const struct irq_affinity_desc *affinity) + { + int start, ret; + +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index 89f704ba2e6b..bb388362f396 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -979,7 +979,7 @@ const struct irq_domain_ops irq_domain_simple_ops = { + EXPORT_SYMBOL_GPL(irq_domain_simple_ops); + + int irq_domain_alloc_descs(int virq, unsigned int cnt, irq_hw_number_t hwirq, +- int node, const struct cpumask *affinity) ++ int node, const struct irq_affinity_desc *affinity) + { + unsigned int hint; + +@@ -1303,7 +1303,8 @@ int irq_domain_alloc_irqs_hierarchy(struct irq_domain *domain, + */ + int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base, + unsigned int nr_irqs, int node, void *arg, +- bool realloc, const struct cpumask *affinity) ++ bool realloc, ++ const struct irq_affinity_desc *affinity) + { + int i, ret, virq; + +diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c +index 88269dd5a8ca..b7e4c5999cc8 100644 +--- a/kernel/irq/msi.c ++++ b/kernel/irq/msi.c +@@ -23,11 +23,11 @@ + * @nvec: The number of vectors used in this entry + * @affinity: Optional pointer to an affinity mask array size of @nvec + * +- * If @affinity is not NULL then a an affinity array[@nvec] is allocated +- * and the affinity masks from @affinity are copied. ++ * If @affinity is not NULL then an affinity array[@nvec] is allocated ++ * and the affinity masks and flags from @affinity are copied. + */ +-struct msi_desc * +-alloc_msi_entry(struct device *dev, int nvec, const struct cpumask *affinity) ++struct msi_desc *alloc_msi_entry(struct device *dev, int nvec, ++ const struct irq_affinity_desc *affinity) + { + struct msi_desc *desc; + +-- +2.27.0 + diff --git a/patches/0459-fix-kabi-broken-due-to-change-of-struct-msi_desc.patch b/patches/0459-fix-kabi-broken-due-to-change-of-struct-msi_desc.patch new file mode 100644 index 00000000..747602d5 --- /dev/null +++ b/patches/0459-fix-kabi-broken-due-to-change-of-struct-msi_desc.patch @@ -0,0 +1,38 @@ +From aa4e8efd56b6d14d421dfbe55fe29abe32d7752e Mon Sep 17 00:00:00 2001 +From: YunYi Yang +Date: Mon, 19 Jun 2023 17:25:33 +0800 +Subject: [PATCH 141/256] fix kabi broken due to change of struct msi_desc + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +---------------------------------------------------------------------------- + +Commit ("genirq/core: Introduce struct irq_affinity_desc") +changes struct msi_desc, so we need to fix kabi broken problem. + +Signed-off-by: YunYi Yang +--- + include/linux/msi.h | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/include/linux/msi.h b/include/linux/msi.h +index c0ad2a47a290..75f32a5785dc 100644 +--- a/include/linux/msi.h ++++ b/include/linux/msi.h +@@ -76,7 +76,11 @@ struct msi_desc { + unsigned int nvec_used; + struct device *dev; + struct msi_msg msg; ++#ifndef __GENKSYMS__ + struct irq_affinity_desc *affinity; ++#else ++ struct cpumask *affinity; ++#endif + + union { + /* PCI MSI/X specific data */ +-- +2.27.0 + diff --git a/patches/0460-resource-Add-irqresource_disabled.patch b/patches/0460-resource-Add-irqresource_disabled.patch new file mode 100644 index 00000000..e9d57e93 --- /dev/null +++ b/patches/0460-resource-Add-irqresource_disabled.patch @@ -0,0 +1,54 @@ +From e2918d2df4d13f7cd6e64e465b0ae1f21b7985bf Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Tue, 3 Aug 2021 14:47:31 +0800 +Subject: [PATCH 142/256] resource: Add irqresource_disabled() + +mainline inclusion +from mainline-v5.11-rc1 +commit 9806731db684a475ade1e95d166089b9edbd9da3 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9806731db684a475ade1e95d166089b9edbd9da3 + +---------------------------------------------------------------------- + +Add a common function to set the fields for a irq resource to disabled, +which mimics what is done in acpi_dev_irqresource_disabled(), with a view +to replace that function. + +Signed-off-by: John Garry +Signed-off-by: Marc Zyngier +Reviewed-by: Rafael J. Wysocki +Link: https://lore.kernel.org/r/1606905417-183214-3-git-send-email-john.garry@huawei.com +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + include/linux/ioport.h +--- + include/linux/ioport.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/include/linux/ioport.h b/include/linux/ioport.h +index 1a438ecd15d0..d0dd89b266ca 100644 +--- a/include/linux/ioport.h ++++ b/include/linux/ioport.h +@@ -293,6 +293,12 @@ static inline bool resource_overlaps(struct resource *r1, struct resource *r2) + return (r1->start <= r2->end && r1->end >= r2->start); + } + ++static inline void irqresource_disabled(struct resource *res, u32 irq) ++{ ++ res->start = irq; ++ res->end = irq; ++ res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED | IORESOURCE_UNSET; ++} + + #endif /* __ASSEMBLY__ */ + #endif /* _LINUX_IOPORT_H */ +-- +2.27.0 + diff --git a/patches/0461-genirq-affinity-Add-is_managed-to-struct-irq_affinit.patch b/patches/0461-genirq-affinity-Add-is_managed-to-struct-irq_affinit.patch new file mode 100644 index 00000000..62bd67c8 --- /dev/null +++ b/patches/0461-genirq-affinity-Add-is_managed-to-struct-irq_affinit.patch @@ -0,0 +1,146 @@ +From 6ec3caf5dc2d7983ef6dfa9e810a22f751605d51 Mon Sep 17 00:00:00 2001 +From: Dou Liyang +Date: Tue, 4 Dec 2018 23:51:21 +0800 +Subject: [PATCH 143/256] genirq/affinity: Add is_managed to struct + irq_affinity_desc + +mainline inclusion +from mainline-v5.0-rc1 +commit c410abbbacb9b378365ba17a30df08b4b9eec64f +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c410abbbacb9b378365ba17a30df08b4b9eec64f + +---------------------------------------------------------------------- + +Devices which use managed interrupts usually have two classes of +interrupts: + + - Interrupts for multiple device queues + - Interrupts for general device management + +Currently both classes are treated the same way, i.e. as managed +interrupts. The general interrupts get the default affinity mask assigned +while the device queue interrupts are spread out over the possible CPUs. + +Treating the general interrupts as managed is both a limitation and under +certain circumstances a bug. Assume the following situation: + + default_irq_affinity = 4..7 + +So if CPUs 4-7 are offlined, then the core code will shut down the device +management interrupts because the last CPU in their affinity mask went +offline. + +It's also a limitation because it's desired to allow manual placement of +the general device interrupts for various reasons. If they are marked +managed then the interrupt affinity setting from both user and kernel space +is disabled. That limitation was reported by Kashyap and Sumit. + +Expand struct irq_affinity_desc with a new bit 'is_managed' which is set +for truly managed interrupts (queue interrupts) and cleared for the general +device interrupts. + +[ tglx: Simplify code and massage changelog ] + +Reported-by: Kashyap Desai +Reported-by: Sumit Saxena +Signed-off-by: Dou Liyang +Signed-off-by: Thomas Gleixner +Cc: linux-pci@vger.kernel.org +Cc: shivasharan.srikanteshwara@broadcom.com +Cc: ming.lei@redhat.com +Cc: hch@lst.de +Cc: bhelgaas@google.com +Cc: douliyang1@huawei.com +Link: https://lkml.kernel.org/r/20181204155122.6327-3-douliyangs@gmail.com + +Signed-off-by: YunYi Yang + + Conflicts: + kernel/irq/irqdesc.c +--- + include/linux/interrupt.h | 1 + + kernel/irq/affinity.c | 6 +++++- + kernel/irq/irqdesc.c | 11 +++++++---- + 3 files changed, 13 insertions(+), 5 deletions(-) + +diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h +index 02d673cc6178..2b5d53e0fb00 100644 +--- a/include/linux/interrupt.h ++++ b/include/linux/interrupt.h +@@ -279,6 +279,7 @@ struct irq_affinity { + */ + struct irq_affinity_desc { + struct cpumask mask; ++ unsigned int is_managed : 1; + }; + + #if defined(CONFIG_SMP) +diff --git a/kernel/irq/affinity.c b/kernel/irq/affinity.c +index 2aa435ceb874..87064eba298f 100644 +--- a/kernel/irq/affinity.c ++++ b/kernel/irq/affinity.c +@@ -180,7 +180,7 @@ struct irq_affinity_desc * + irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd) + { + int affvecs = nvecs - affd->pre_vectors - affd->post_vectors; +- int curvec, usedvecs; ++ int curvec, usedvecs, i; + cpumask_var_t nmsk, npresmsk, *node_to_cpumask; + struct irq_affinity_desc *masks = NULL; + +@@ -242,6 +242,10 @@ irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd) + for (; curvec < nvecs; curvec++) + cpumask_copy(&masks[curvec].mask, irq_default_affinity); + ++ /* Mark the managed interrupts */ ++ for (i = affd->pre_vectors; i < nvecs - affd->post_vectors; i++) ++ masks[i].is_managed = 1; ++ + outnodemsk: + free_node_to_cpumask(node_to_cpumask); + outnpresmsk: +diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c +index d3ac4c4cd6a3..1591040b52ea 100644 +--- a/kernel/irq/irqdesc.c ++++ b/kernel/irq/irqdesc.c +@@ -468,27 +468,30 @@ static int alloc_descs(unsigned int start, unsigned int cnt, int node, + struct module *owner) + { + struct irq_desc *desc; +- unsigned int flags; + int i; + + /* Validate affinity mask(s) */ + if (affinity) { +- for (i = 0; i < cnt; i++) { ++ for (i = 0; i < cnt; i++, i++) { + if (cpumask_empty(&affinity[i].mask)) + return -EINVAL; + } + } + +- flags = affinity ? IRQD_AFFINITY_MANAGED | IRQD_MANAGED_SHUTDOWN : 0; +- + for (i = 0; i < cnt; i++) { + const struct cpumask *mask = NULL; ++ unsigned int flags = 0; + + if (affinity) { ++ if (affinity->is_managed) { ++ flags = IRQD_AFFINITY_MANAGED | ++ IRQD_MANAGED_SHUTDOWN; ++ } + mask = &affinity->mask; + node = cpu_to_node(cpumask_first(mask)); + affinity++; + } ++ + desc = alloc_desc(start + i, node, flags, mask, owner); + if (!desc) + goto err; +-- +2.27.0 + diff --git a/patches/0462-genirq-affinity-Add-irq_update_affinity_desc.patch b/patches/0462-genirq-affinity-Add-irq_update_affinity_desc.patch new file mode 100644 index 00000000..4b514a47 --- /dev/null +++ b/patches/0462-genirq-affinity-Add-irq_update_affinity_desc.patch @@ -0,0 +1,155 @@ +From 22f629fd1d0fb1e52279ff70b4ec8e5021c97c43 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Tue, 3 Aug 2021 14:47:30 +0800 +Subject: [PATCH 144/256] genirq/affinity: Add irq_update_affinity_desc() + +mainline inclusion +from mainline-v5.11-rc1 +commit 1d3aec89286254487df7641c30f1b14ad1d127a5 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1d3aec89286254487df7641c30f1b14ad1d127a5 + +---------------------------------------------------------------------- + +Add a function to allow the affinity of an interrupt be switched to +managed, such that interrupts allocated for platform devices may be +managed. + +This new interface has certain limitations, and attempts to use it in the +following circumstances will fail: +- For when the kernel is configured for generic IRQ reservation mode (in + config GENERIC_IRQ_RESERVATION_MODE). The reason being that it could + conflict with managed vs. non-managed interrupt accounting. +- The interrupt is already started, which should not be the case during + init +- The interrupt is already configured as managed, which means double init + +Suggested-by: Thomas Gleixner +Signed-off-by: John Garry +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/1606905417-183214-2-git-send-email-john.garry@huawei.com +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + kernel/irq/manage.c +--- + include/linux/interrupt.h | 9 ++++- + kernel/irq/manage.c | 70 +++++++++++++++++++++++++++++++++++++++ + 2 files changed, 78 insertions(+), 1 deletion(-) + +diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h +index 2b5d53e0fb00..862b5f158d36 100644 +--- a/include/linux/interrupt.h ++++ b/include/linux/interrupt.h +@@ -293,7 +293,8 @@ extern int irq_can_set_affinity(unsigned int irq); + extern int irq_select_affinity(unsigned int irq); + + extern int irq_set_affinity_hint(unsigned int irq, const struct cpumask *m); +- ++extern int irq_update_affinity_desc(unsigned int irq, ++ struct irq_affinity_desc *affinity); + extern int + irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify); + +@@ -327,6 +328,12 @@ static inline int irq_set_affinity_hint(unsigned int irq, + return -EINVAL; + } + ++static inline int irq_update_affinity_desc(unsigned int irq, ++ struct irq_affinity_desc *affinity) ++{ ++ return -EINVAL; ++} ++ + static inline int + irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify) + { +diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c +index f4c0e509d74f..08ba1833c5bd 100644 +--- a/kernel/irq/manage.c ++++ b/kernel/irq/manage.c +@@ -331,6 +331,76 @@ int irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask, + return ret; + } + ++/** ++ * irq_update_affinity_desc - Update affinity management for an interrupt ++ * @irq: The interrupt number to update ++ * @affinity: Pointer to the affinity descriptor ++ * ++ * This interface can be used to configure the affinity management of ++ * interrupts which have been allocated already. ++ * ++ * There are certain limitations on when it may be used - attempts to use it ++ * for when the kernel is configured for generic IRQ reservation mode (in ++ * config GENERIC_IRQ_RESERVATION_MODE) will fail, as it may conflict with ++ * managed/non-managed interrupt accounting. In addition, attempts to use it on ++ * an interrupt which is already started or which has already been configured ++ * as managed will also fail, as these mean invalid init state or double init. ++ */ ++int irq_update_affinity_desc(unsigned int irq, ++ struct irq_affinity_desc *affinity) ++{ ++ struct irq_desc *desc; ++ unsigned long flags; ++ bool activated; ++ int ret = 0; ++ ++ /* ++ * Supporting this with the reservation scheme used by x86 needs ++ * some more thought. Fail it for now. ++ */ ++ if (IS_ENABLED(CONFIG_GENERIC_IRQ_RESERVATION_MODE)) ++ return -EOPNOTSUPP; ++ ++ desc = irq_get_desc_buslock(irq, &flags, 0); ++ if (!desc) ++ return -EINVAL; ++ ++ /* Requires the interrupt to be shut down */ ++ if (irqd_is_started(&desc->irq_data)) { ++ ret = -EBUSY; ++ goto out_unlock; ++ } ++ ++ /* Interrupts which are already managed cannot be modified */ ++ if (irqd_affinity_is_managed(&desc->irq_data)) { ++ ret = -EBUSY; ++ goto out_unlock; ++ } ++ ++ /* ++ * Deactivate the interrupt. That's required to undo ++ * anything an earlier activation has established. ++ */ ++ activated = irqd_is_activated(&desc->irq_data); ++ if (activated) ++ irq_domain_deactivate_irq(&desc->irq_data); ++ ++ if (affinity->is_managed) { ++ irqd_set(&desc->irq_data, IRQD_AFFINITY_MANAGED); ++ irqd_set(&desc->irq_data, IRQD_MANAGED_SHUTDOWN); ++ } ++ ++ cpumask_copy(desc->irq_common_data.affinity, &affinity->mask); ++ ++ /* Restore the activation state */ ++ if (activated) ++ irq_domain_activate_irq(&desc->irq_data, false); ++ ++out_unlock: ++ irq_put_desc_busunlock(desc, flags); ++ return ret; ++} ++ + static int __irq_set_affinity(unsigned int irq, const struct cpumask *mask, + bool force) + { +-- +2.27.0 + diff --git a/patches/0463-driver-core-platform-Add-devm_platform_get_irqs_affi.patch b/patches/0463-driver-core-platform-Add-devm_platform_get_irqs_affi.patch new file mode 100644 index 00000000..4b39a947 --- /dev/null +++ b/patches/0463-driver-core-platform-Add-devm_platform_get_irqs_affi.patch @@ -0,0 +1,208 @@ +From 7a59091a39389b15b17649d76f522021a710887a Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Tue, 3 Aug 2021 14:47:33 +0800 +Subject: [PATCH 145/256] driver core: platform: Add + devm_platform_get_irqs_affinity() + +mainline inclusion +from mainline-v5.11-rc1 +commit e15f2fa959f2cce8a05e8e3a596e75d068cd42c5 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e15f2fa959f2cce8a05e8e3a596e75d068cd42c5 + +---------------------------------------------------------------------- + +Drivers for multi-queue platform devices may also want managed interrupts +for handling HW queue completion interrupts, so add support. + +The function accepts an affinity descriptor pointer, which covers all IRQs +expected for the device. + +The function is devm class as the only current in-tree user will also use +devm method for requesting the interrupts; as such, the function is made +as devm as it can ensure ordering of freeing the irq and disposing of the +mapping. + +Signed-off-by: John Garry +Signed-off-by: Marc Zyngier +Acked-by: Marc Zyngier +Link: https://lore.kernel.org/r/1606905417-183214-5-git-send-email-john.garry@huawei.com +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/base/platform.c | 123 ++++++++++++++++++++++++++++++++ + include/linux/platform_device.h | 6 ++ + 2 files changed, 129 insertions(+) + +diff --git a/drivers/base/platform.c b/drivers/base/platform.c +index 27a291d7917d..2a17ffd89d78 100644 +--- a/drivers/base/platform.c ++++ b/drivers/base/platform.c +@@ -15,6 +15,10 @@ + #include + #include + #include ++#ifndef __GENKSYMS__ ++#include ++#endif ++#include + #include + #include + #include +@@ -189,6 +193,125 @@ int platform_irq_count(struct platform_device *dev) + } + EXPORT_SYMBOL_GPL(platform_irq_count); + ++struct irq_affinity_devres { ++ unsigned int count; ++ unsigned int irq[]; ++}; ++ ++static void platform_disable_acpi_irq(struct platform_device *pdev, int index) ++{ ++ struct resource *r; ++ ++ r = platform_get_resource(pdev, IORESOURCE_IRQ, index); ++ if (r) ++ irqresource_disabled(r, 0); ++} ++ ++static void devm_platform_get_irqs_affinity_release(struct device *dev, ++ void *res) ++{ ++ struct irq_affinity_devres *ptr = res; ++ int i; ++ ++ for (i = 0; i < ptr->count; i++) { ++ irq_dispose_mapping(ptr->irq[i]); ++ ++ if (has_acpi_companion(dev)) ++ platform_disable_acpi_irq(to_platform_device(dev), i); ++ } ++} ++ ++/** ++ * devm_platform_get_irqs_affinity - devm method to get a set of IRQs for a ++ * device using an interrupt affinity descriptor ++ * @dev: platform device pointer ++ * @affd: affinity descriptor ++ * @minvec: minimum count of interrupt vectors ++ * @maxvec: maximum count of interrupt vectors ++ * @irqs: pointer holder for IRQ numbers ++ * ++ * Gets a set of IRQs for a platform device, and updates IRQ afffinty according ++ * to the passed affinity descriptor ++ * ++ * Return: Number of vectors on success, negative error number on failure. ++ */ ++int devm_platform_get_irqs_affinity(struct platform_device *dev, ++ struct irq_affinity *affd, ++ unsigned int minvec, ++ unsigned int maxvec, ++ int **irqs) ++{ ++ struct irq_affinity_devres *ptr; ++ struct irq_affinity_desc *desc; ++ size_t size; ++ int i, ret, nvec; ++ ++ if (!affd) ++ return -EPERM; ++ ++ if (maxvec < minvec) ++ return -ERANGE; ++ ++ nvec = platform_irq_count(dev); ++ ++ if (nvec < minvec) ++ return -ENOSPC; ++ ++ nvec = irq_calc_affinity_vectors(minvec, nvec, affd); ++ if (nvec < minvec) ++ return -ENOSPC; ++ ++ if (nvec > maxvec) ++ nvec = maxvec; ++ ++ size = sizeof(*ptr) + sizeof(unsigned int) * nvec; ++ ptr = devres_alloc(devm_platform_get_irqs_affinity_release, size, ++ GFP_KERNEL); ++ if (!ptr) ++ return -ENOMEM; ++ ++ ptr->count = nvec; ++ ++ for (i = 0; i < nvec; i++) { ++ int irq = platform_get_irq(dev, i); ++ if (irq < 0) { ++ ret = irq; ++ goto err_free_devres; ++ } ++ ptr->irq[i] = irq; ++ } ++ ++ desc = irq_create_affinity_masks(nvec, affd); ++ if (!desc) { ++ ret = -ENOMEM; ++ goto err_free_devres; ++ } ++ ++ for (i = 0; i < nvec; i++) { ++ ret = irq_update_affinity_desc(ptr->irq[i], &desc[i]); ++ if (ret) { ++ dev_err(&dev->dev, "failed to update irq%d affinity descriptor (%d)\n", ++ ptr->irq[i], ret); ++ goto err_free_desc; ++ } ++ } ++ ++ devres_add(&dev->dev, ptr); ++ ++ kfree(desc); ++ ++ *irqs = ptr->irq; ++ ++ return nvec; ++ ++err_free_desc: ++ kfree(desc); ++err_free_devres: ++ devres_free(ptr); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(devm_platform_get_irqs_affinity); ++ + /** + * platform_get_resource_byname - get a resource for a device by name + * @dev: platform device +diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h +index 9e5c98fcea8c..3a181cb1437c 100644 +--- a/include/linux/platform_device.h ++++ b/include/linux/platform_device.h +@@ -16,6 +16,7 @@ + #define PLATFORM_DEVID_NONE (-1) + #define PLATFORM_DEVID_AUTO (-2) + ++struct irq_affinity; + struct mfd_cell; + struct property_entry; + struct platform_device_id; +@@ -56,6 +57,11 @@ devm_platform_ioremap_resource(struct platform_device *pdev, + unsigned int index); + extern int platform_get_irq(struct platform_device *, unsigned int); + extern int platform_irq_count(struct platform_device *); ++extern int devm_platform_get_irqs_affinity(struct platform_device *dev, ++ struct irq_affinity *affd, ++ unsigned int minvec, ++ unsigned int maxvec, ++ int **irqs); + extern struct resource *platform_get_resource_byname(struct platform_device *, + unsigned int, + const char *); +-- +2.27.0 + diff --git a/patches/0464-scsi-hisi_sas-Expose-HW-queues-for-v2-hw.patch b/patches/0464-scsi-hisi_sas-Expose-HW-queues-for-v2-hw.patch new file mode 100644 index 00000000..b729fe8e --- /dev/null +++ b/patches/0464-scsi-hisi_sas-Expose-HW-queues-for-v2-hw.patch @@ -0,0 +1,242 @@ +From 3653ed40d1d60016fc25c60b5e24c8c28e56ff78 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Tue, 3 Aug 2021 14:47:34 +0800 +Subject: [PATCH 146/256] scsi: hisi_sas: Expose HW queues for v2 hw + +mainline inclusion +from mainline-v5.11-rc3 +commit 74a2921948ed8c0e7f079a98442ec3493168cc85 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=74a2921948ed8c0e7f079a98442ec3493168cc85 + +---------------------------------------------------------------------- + +As a performance enhancement, make the completion queue interrupts managed. + +In addition, in commit bf0beec0607d ("blk-mq: drain I/O when all CPUs in a +hctx are offline"), CPU hotplug for MQ devices using managed interrupts is +made safe. So expose HW queues to blk-mq to take advantage of this. + +Flag Scsi_host.host_tagset is also set to ensure that the HBA is not sent +more commands than it can handle. However the driver still does not use +request tag for IPTT as there are many HW bugs means that special rules +apply for IPTT allocation. + +Link: https://lore.kernel.org/r/1606905417-183214-6-git-send-email-john.garry@huawei.com +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 4 ++ + drivers/scsi/hisi_sas/hisi_sas_main.c | 11 +++++ + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 66 +++++++++++++++++++++----- + 3 files changed, 70 insertions(+), 11 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index b8547e905a80..48cde1d897d4 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -319,6 +320,7 @@ enum { + + struct hisi_sas_hw { + int (*hw_init)(struct hisi_hba *hisi_hba); ++ int (*interrupt_preinit)(struct hisi_hba *hisi_hba); + void (*setup_itct)(struct hisi_hba *hisi_hba, + struct hisi_sas_device *device); + int (*slot_index_alloc)(struct hisi_hba *hisi_hba, +@@ -420,6 +422,8 @@ struct hisi_hba { + u32 refclk_frequency_mhz; + u8 sas_addr[SAS_ADDR_SIZE]; + ++ int *irq_map; /* v2 hw */ ++ + int n_phy; + spinlock_t lock; + struct semaphore sem; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 23f688bd70e5..f7bc6d4ddc20 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -2693,6 +2693,13 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev, + return NULL; + } + ++static int hisi_sas_interrupt_preinit(struct hisi_hba *hisi_hba) ++{ ++ if (hisi_hba->hw->interrupt_preinit) ++ return hisi_hba->hw->interrupt_preinit(hisi_hba); ++ return 0; ++} ++ + int hisi_sas_probe(struct platform_device *pdev, + const struct hisi_sas_hw *hw) + { +@@ -2751,6 +2758,10 @@ int hisi_sas_probe(struct platform_device *pdev, + sha->sas_port[i] = &hisi_hba->port[i].sas_port; + } + ++ rc = hisi_sas_interrupt_preinit(hisi_hba); ++ if (rc) ++ goto err_out; ++ + rc = scsi_add_host(shost, &pdev->dev); + if (rc) + goto err_out; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +index 55331ffa3be5..81ff9b76c344 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -3317,6 +3317,30 @@ static irq_handler_t fatal_interrupts[HISI_SAS_FATAL_INT_NR] = { + fatal_axi_int_v2_hw + }; + ++#define CQ0_IRQ_INDEX (96) ++ ++static int hisi_sas_v2_interrupt_preinit(struct hisi_hba *hisi_hba) ++{ ++ struct platform_device *pdev = hisi_hba->platform_dev; ++ struct Scsi_Host *shost = hisi_hba->shost; ++ struct irq_affinity desc = { ++ .pre_vectors = CQ0_IRQ_INDEX, ++ .post_vectors = 16, ++ }; ++ int resv = desc.pre_vectors + desc.post_vectors; ++ int minvec = resv + 1; ++ int nvec; ++ ++ nvec = devm_platform_get_irqs_affinity(pdev, &desc, minvec, 128, ++ &hisi_hba->irq_map); ++ if (nvec < 0) ++ return nvec; ++ ++ shost->nr_hw_queues = hisi_hba->nvecs = nvec - resv; ++ ++ return 0; ++} ++ + /* + * There is a limitation in the hip06 chipset that we need + * to map in all mbigen interrupts, even if they are not used. +@@ -3325,14 +3349,11 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) + { + struct platform_device *pdev = hisi_hba->platform_dev; + struct device *dev = &pdev->dev; +- int irq, rc = 0, irq_map[128]; ++ int irq, rc = 0; + int i, phy_no, fatal_no, queue_no; + +- for (i = 0; i < 128; i++) +- irq_map[i] = platform_get_irq(pdev, i); +- + for (i = 0; i < HISI_SAS_PHY_INT_NR; i++) { +- irq = irq_map[i + 1]; /* Phy up/down is irq1 */ ++ irq = hisi_hba->irq_map[i + 1]; /* Phy up/down is irq1 */ + rc = devm_request_irq(dev, irq, phy_interrupts[i], 0, + DRV_NAME " phy", hisi_hba); + if (rc) { +@@ -3346,7 +3367,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) + for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) { + struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; + +- irq = irq_map[phy_no + 72]; ++ irq = hisi_hba->irq_map[phy_no + 72]; + rc = devm_request_irq(dev, irq, sata_int_v2_hw, 0, + DRV_NAME " sata", phy); + if (rc) { +@@ -3358,7 +3379,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) + } + + for (fatal_no = 0; fatal_no < HISI_SAS_FATAL_INT_NR; fatal_no++) { +- irq = irq_map[fatal_no + 81]; ++ irq = hisi_hba->irq_map[fatal_no + 81]; + rc = devm_request_irq(dev, irq, fatal_interrupts[fatal_no], 0, + DRV_NAME " fatal", hisi_hba); + if (rc) { +@@ -3369,23 +3390,23 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) + } + } + +- for (queue_no = 0; queue_no < hisi_hba->queue_count; queue_no++) { ++ for (queue_no = 0; queue_no < hisi_hba->nvecs; queue_no++) { + struct hisi_sas_cq *cq = &hisi_hba->cq[queue_no]; + +- cq->irq_no = irq_map[queue_no + 96]; ++ cq->irq_no = hisi_hba->irq_map[queue_no + 96]; + rc = devm_request_threaded_irq(dev, cq->irq_no, + cq_interrupt_v2_hw, + cq_thread_v2_hw, IRQF_ONESHOT, + DRV_NAME " cq", cq); + if (rc) { + dev_err(dev, "irq init: could not request cq interrupt %d, rc=%d\n", +- irq, rc); ++ cq->irq_no, rc); + rc = -ENOENT; + goto err_out; + } ++ cq->irq_mask = irq_get_affinity_mask(cq->irq_no); + } + +- hisi_hba->nvecs = hisi_hba->queue_count; + hisi_hba->dq_num_per_node = hisi_hba->queue_count / num_online_nodes(); + + err_out: +@@ -3545,6 +3566,26 @@ struct device_attribute *host_attrs_v2_hw[] = { + NULL + }; + ++static int map_queues_v2_hw(struct Scsi_Host *shost) ++{ ++ struct hisi_hba *hisi_hba = shost_priv(shost); ++ struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT]; ++ const struct cpumask *mask; ++ unsigned int queue, cpu; ++ ++ for (queue = 0; queue < qmap->nr_queues; queue++) { ++ mask = irq_get_affinity_mask(hisi_hba->irq_map[96 + queue]); ++ if (!mask) ++ continue; ++ ++ for_each_cpu(cpu, mask) ++ qmap->mq_map[cpu] = qmap->queue_offset + queue; ++ } ++ ++ return 0; ++ ++} ++ + static struct scsi_host_template sht_v2_hw = { + .name = DRV_NAME, + .proc_name = DRV_NAME, +@@ -3567,10 +3608,13 @@ static struct scsi_host_template sht_v2_hw = { + .ioctl = sas_ioctl, + .shost_attrs = host_attrs_v2_hw, + .host_reset = hisi_sas_host_reset, ++ .map_queues = map_queues_v2_hw, ++ .host_tagset = 1, + }; + + static const struct hisi_sas_hw hisi_sas_v2_hw = { + .hw_init = hisi_sas_v2_init, ++ .interrupt_preinit = hisi_sas_v2_interrupt_preinit, + .setup_itct = setup_itct_v2_hw, + .slot_index_alloc = slot_index_alloc_quirk_v2_hw, + .alloc_dev = alloc_dev_quirk_v2_hw, +-- +2.27.0 + diff --git a/patches/0465-scsi-hisi_sas-Remove-auto_affine_msi_experimental-mo.patch b/patches/0465-scsi-hisi_sas-Remove-auto_affine_msi_experimental-mo.patch new file mode 100644 index 00000000..bd233450 --- /dev/null +++ b/patches/0465-scsi-hisi_sas-Remove-auto_affine_msi_experimental-mo.patch @@ -0,0 +1,52 @@ +From fc4f91ff3dc0a791a932a8f6946596b247c16e4f Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Tue, 3 Aug 2021 14:47:35 +0800 +Subject: [PATCH 147/256] scsi: hisi_sas: Remove auto_affine_msi_experimental + module_param + +mainline inclusion +from mainline-v5.12-rc1 +commit 3997e0fdd5878a7d6224056176800c1db538f468 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3997e0fdd5878a7d6224056176800c1db538f468 + +---------------------------------------------------------------------- + +Now that the driver always uses managed interrupts, delete +auto_affine_msi_experimental module param. + +Link: https://lore.kernel.org/r/1609763622-34119-2-git-send-email-john.garry@huawei.com +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index fcb7c704f94c..bf4fe277289c 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -568,11 +568,6 @@ module_param(user_ctl_irq, bool, 0444); + MODULE_PARM_DESC(user_ctl_irq, "Enable user control irq affinity:\n" + "default is auto-control irq affinity"); + +-static bool auto_affine_msi_experimental; +-module_param(auto_affine_msi_experimental, bool, 0444); +-MODULE_PARM_DESC(auto_affine_msi_experimental, "Enable auto-affinity of MSI IRQs as experimental:\n" +- "default is off"); +- + static void debugfs_work_handler_v3_hw(struct work_struct *work); + + static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off) +-- +2.27.0 + diff --git a/patches/0466-scsi-libsas-Introduce-a-_gfp-variant-of-event-notifi.patch b/patches/0466-scsi-libsas-Introduce-a-_gfp-variant-of-event-notifi.patch new file mode 100644 index 00000000..d5db7f14 --- /dev/null +++ b/patches/0466-scsi-libsas-Introduce-a-_gfp-variant-of-event-notifi.patch @@ -0,0 +1,281 @@ +From d3bb5e8e25dcdb124f24caacd89e598d92437f6d Mon Sep 17 00:00:00 2001 +From: "Ahmed S. Darwish" +Date: Wed, 31 Mar 2021 02:01:08 +0000 +Subject: [PATCH 148/256] scsi: libsas: Introduce a _gfp() variant of event + notifiers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +mainline inclusion +from mainline-v5.12-rc1 +commit c2d0f1a65ab9fbabebb463bf36f50ea8f4633386 +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c2d0f1a65ab9fbabebb463bf36f50ea8f4633386 + +---------------------------------------------------------------------- + +sas_alloc_event() uses in_interrupt() to decide which allocation should be +used. + +The usage of in_interrupt() in drivers is phased out and Linus clearly +requested that code which changes behaviour depending on context should +either be separated or the context be conveyed in an argument passed by the +caller, which usually knows the context. + +The in_interrupt() check is also only partially correct, because it fails +to choose the correct code path when just preemption or interrupts are +disabled. For example, as in the following call chain: + + mvsas/mv_sas.c: mvs_work_queue() [process context] + spin_lock_irqsave(mvs_info::lock, ) + -> libsas/sas_event.c: sas_notify_phy_event() + -> sas_alloc_event() + -> in_interrupt() = false + -> invalid GFP_KERNEL allocation + -> libsas/sas_event.c: sas_notify_port_event() + -> sas_alloc_event() + -> in_interrupt() = false + -> invalid GFP_KERNEL allocation + +Introduce sas_alloc_event_gfp(), sas_notify_port_event_gfp(), and +sas_notify_phy_event_gfp(), which all behave like the non _gfp() variants +but use a caller-passed GFP mask for allocations. + +For bisectability, all callers will be modified first to pass GFP context, +then the non _gfp() libsas API variants will be modified to take a gfp_t by +default. + +Link: https://lore.kernel.org/r/20210118100955.1761652-4-a.darwish@linutronix.de +Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event lost") +Cc: Jason Yan +Reviewed-by: John Garry +Signed-off-by: Ahmed S. Darwish +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +Signed-off-by: Chen Jun +Acked-by:  Weilong Chen +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + Documentation/scsi/libsas.rst + drivers/scsi/libsas/sas_event.c + drivers/scsi/libsas/sas_init.c + include/scsi/libsas.h +--- + Documentation/scsi/libsas.txt | 2 + + drivers/scsi/libsas/sas_event.c | 64 +++++++++++++++++++++++++----- + drivers/scsi/libsas/sas_init.c | 21 +++++++--- + drivers/scsi/libsas/sas_internal.h | 4 ++ + include/scsi/libsas.h | 7 ++++ + 5 files changed, 83 insertions(+), 15 deletions(-) + +diff --git a/Documentation/scsi/libsas.txt b/Documentation/scsi/libsas.txt +index 8cac6492aade..5c28e4727f2c 100644 +--- a/Documentation/scsi/libsas.txt ++++ b/Documentation/scsi/libsas.txt +@@ -156,6 +156,8 @@ The event interface: + void (*notify_ha_event)(struct sas_ha_struct *, enum ha_event); + void (*notify_port_event)(struct sas_phy *, enum port_event); + void (*notify_phy_event)(struct sas_phy *, enum phy_event); ++ void sas_notify_port_event_gfp(struct sas_phy *, enum port_event, gfp_t); ++ void sas_notify_phy_event_gfp(struct sas_phy *, enum phy_event, gfp_t); + + When sas_register_ha() returns, those are set and can be + called by the LLDD to notify the SAS layer of such events +diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c +index ae923eb6de95..21b020f958b8 100644 +--- a/drivers/scsi/libsas/sas_event.c ++++ b/drivers/scsi/libsas/sas_event.c +@@ -148,18 +148,15 @@ static void sas_phy_event_worker(struct work_struct *work) + sas_free_event(ev); + } + +-static int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event) ++static int __sas_notify_port_event(struct asd_sas_phy *phy, ++ enum port_event event, ++ struct asd_sas_event *ev) + { +- struct asd_sas_event *ev; + struct sas_ha_struct *ha = phy->ha; + int ret; + + BUG_ON(event >= PORT_NUM_EVENTS); + +- ev = sas_alloc_event(phy); +- if (!ev) +- return -ENOMEM; +- + INIT_SAS_EVENT(ev, sas_port_event_worker, phy, event); + + ret = sas_queue_event(event, &ev->work, ha); +@@ -169,18 +166,40 @@ static int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event) + return ret; + } + +-int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event) ++int sas_notify_port_event_gfp(struct asd_sas_phy *phy, enum port_event event, ++ gfp_t gfp_flags) + { + struct asd_sas_event *ev; +- struct sas_ha_struct *ha = phy->ha; +- int ret; + +- BUG_ON(event >= PHY_NUM_EVENTS); ++ ev = sas_alloc_event_gfp(phy, gfp_flags); ++ if (!ev) ++ return -ENOMEM; ++ ++ return __sas_notify_port_event(phy, event, ev); ++} ++EXPORT_SYMBOL_GPL(sas_notify_port_event_gfp); ++ ++int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event) ++{ ++ struct asd_sas_event *ev; + + ev = sas_alloc_event(phy); + if (!ev) + return -ENOMEM; + ++ return __sas_notify_port_event(phy, event, ev); ++} ++EXPORT_SYMBOL_GPL(sas_notify_port_event); ++ ++static inline int __sas_notify_phy_event(struct asd_sas_phy *phy, ++ enum phy_event event, ++ struct asd_sas_event *ev) ++{ ++ struct sas_ha_struct *ha = phy->ha; ++ int ret; ++ ++ BUG_ON(event >= PHY_NUM_EVENTS); ++ + INIT_SAS_EVENT(ev, sas_phy_event_worker, phy, event); + + ret = sas_queue_event(event, &ev->work, ha); +@@ -197,3 +216,28 @@ int sas_init_events(struct sas_ha_struct *sas_ha) + + return 0; + } ++ ++int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event, ++ gfp_t gfp_flags) ++{ ++ struct asd_sas_event *ev; ++ ++ ev = sas_alloc_event_gfp(phy, gfp_flags); ++ if (!ev) ++ return -ENOMEM; ++ ++ return __sas_notify_phy_event(phy, event, ev); ++} ++EXPORT_SYMBOL_GPL(sas_notify_phy_event_gfp); ++ ++int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event) ++{ ++ struct asd_sas_event *ev; ++ ++ ev = sas_alloc_event(phy); ++ if (!ev) ++ return -ENOMEM; ++ ++ return __sas_notify_phy_event(phy, event, ev); ++} ++EXPORT_SYMBOL_GPL(sas_notify_phy_event); +diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c +index 89bdd0c1a779..1fcb8347901b 100644 +--- a/drivers/scsi/libsas/sas_init.c ++++ b/drivers/scsi/libsas/sas_init.c +@@ -607,16 +607,15 @@ sas_domain_attach_transport(struct sas_domain_function_template *dft) + } + EXPORT_SYMBOL_GPL(sas_domain_attach_transport); + +- +-struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy) ++static struct asd_sas_event *__sas_alloc_event(struct asd_sas_phy *phy, ++ gfp_t gfp_flags) + { + struct asd_sas_event *event; +- gfp_t flags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL; + struct sas_ha_struct *sas_ha = phy->ha; + struct sas_internal *i = + to_sas_internal(sas_ha->core.shost->transportt); + +- event = kmem_cache_zalloc(sas_event_cache, flags); ++ event = kmem_cache_zalloc(sas_event_cache, gfp_flags); + if (!event) + return NULL; + +@@ -627,7 +626,8 @@ struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy) + if (cmpxchg(&phy->in_shutdown, 0, 1) == 0) { + sas_printk("The phy%02d bursting events, shut it down.\n", + phy->id); +- sas_notify_phy_event(phy, PHYE_SHUTDOWN); ++ sas_notify_phy_event_gfp(phy, PHYE_SHUTDOWN, ++ gfp_flags); + } + } else { + /* Do not support PHY control, stop allocating events */ +@@ -641,6 +641,17 @@ struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy) + return event; + } + ++struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy) ++{ ++ return __sas_alloc_event(phy, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); ++} ++ ++struct asd_sas_event *sas_alloc_event_gfp(struct asd_sas_phy *phy, ++ gfp_t gfp_flags) ++{ ++ return __sas_alloc_event(phy, gfp_flags); ++} ++ + void sas_free_event(struct asd_sas_event *event) + { + struct asd_sas_phy *phy = event->phy; +diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h +index 50e12d662ffe..5ccaab295b09 100644 +--- a/drivers/scsi/libsas/sas_internal.h ++++ b/drivers/scsi/libsas/sas_internal.h +@@ -62,6 +62,8 @@ int sas_register_phys(struct sas_ha_struct *sas_ha); + void sas_unregister_phys(struct sas_ha_struct *sas_ha); + + struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy); ++struct asd_sas_event *sas_alloc_event_gfp(struct asd_sas_phy *phy, ++ gfp_t gfp_flags); + void sas_free_event(struct asd_sas_event *event); + + int sas_register_ports(struct sas_ha_struct *sas_ha); +@@ -91,6 +93,8 @@ int sas_smp_phy_control(struct domain_device *dev, int phy_id, + int sas_smp_get_phy_events(struct sas_phy *phy); + + int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event); ++int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event, ++ gfp_t flags); + void sas_device_set_phy(struct domain_device *dev, struct sas_port *port); + struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy); + struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id); +diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h +index a1a0da5e58e2..5b82e023bc90 100644 +--- a/include/scsi/libsas.h ++++ b/include/scsi/libsas.h +@@ -723,4 +723,11 @@ struct sas_phy *sas_get_local_phy(struct domain_device *dev); + + int sas_request_addr(struct Scsi_Host *shost, u8 *addr); + ++int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event); ++int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event); ++int sas_notify_port_event_gfp(struct asd_sas_phy *phy, enum port_event event, ++ gfp_t gfp_flags); ++int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event, ++ gfp_t gfp_flags); ++ + #endif /* _SASLIB_H_ */ +-- +2.27.0 + diff --git a/patches/0467-scsi-mvsas-Pass-gfp_t-flags-to-libsas-event-notifier.patch b/patches/0467-scsi-mvsas-Pass-gfp_t-flags-to-libsas-event-notifier.patch new file mode 100644 index 00000000..083b11e8 --- /dev/null +++ b/patches/0467-scsi-mvsas-Pass-gfp_t-flags-to-libsas-event-notifier.patch @@ -0,0 +1,174 @@ +From c2f2aee318d4c1462c54fe9f1e38b44b56dfd49e Mon Sep 17 00:00:00 2001 +From: "Ahmed S. Darwish" +Date: Wed, 31 Mar 2021 02:01:09 +0000 +Subject: [PATCH 149/256] scsi: mvsas: Pass gfp_t flags to libsas event + notifiers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +mainline inclusion +from mainline-v5.12-rc1 +commit feb18e900f0048001ff375dca639eaa327ab3c1b +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=feb18e900f0048001ff375dca639eaa327ab3c1b + +---------------------------------------------------------------------- + +mvsas calls the non _gfp version of the libsas event notifiers API, leading +to the buggy call chains below: + + mvsas/mv_sas.c: mvs_work_queue() [process context] + spin_lock_irqsave(mvs_info::lock, ) + -> libsas/sas_event.c: sas_notify_phy_event() + -> sas_alloc_event() + -> in_interrupt() = false + -> invalid GFP_KERNEL allocation + -> libsas/sas_event.c: sas_notify_port_event() + -> sas_alloc_event() + -> in_interrupt() = false + -> invalid GFP_KERNEL allocation + +Use the new event notifiers API instead, which requires callers to +explicitly pass the gfp_t memory allocation flags. + +Below are context analysis for the modified functions: + +=> mvs_bytes_dmaed(): + +Since it is invoked from both process and atomic contexts, let its callers +pass the gfp_t flags. Call chains: + + scsi_scan.c: do_scsi_scan_host() [has msleep()] + -> shost->hostt->scan_start() + -> [mvsas/mv_init.c: Scsi_Host::scsi_host_template .scan_start = mvs_scan_start()] + -> mvsas/mv_sas.c: mvs_scan_start() + -> mvs_bytes_dmaed(..., GFP_KERNEL) + + mvsas/mv_sas.c: mvs_work_queue() + spin_lock_irqsave(mvs_info::lock,) + -> mvs_bytes_dmaed(..., GFP_ATOMIC) + + mvsas/mv_64xx.c: mvs_64xx_isr() || mvsas/mv_94xx.c: mvs_94xx_isr() + -> mvsas/mv_chips.h: mvs_int_full() + -> mvsas/mv_sas.c: mvs_int_port() + -> mvs_bytes_dmaed(..., GFP_ATOMIC); + +=> mvs_work_queue(): + +Invoked from process context, but it calls all the libsas event notifier +APIs under a spin_lock_irqsave(). Pass GFP_ATOMIC. + +Link: https://lore.kernel.org/r/20210118100955.1761652-5-a.darwish@linutronix.de +Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event lost") +Cc: Jason Yan +Reviewed-by: John Garry +Signed-off-by: Ahmed S. Darwish +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +Signed-off-by: Chen Jun +Acked-by:  Weilong Chen +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/mvsas/mv_sas.c +--- + drivers/scsi/mvsas/mv_sas.c | 24 ++++++++++-------------- + 1 file changed, 10 insertions(+), 14 deletions(-) + +diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c +index cff43bd9f675..f97d69ac18a4 100644 +--- a/drivers/scsi/mvsas/mv_sas.c ++++ b/drivers/scsi/mvsas/mv_sas.c +@@ -232,11 +232,10 @@ void mvs_set_sas_addr(struct mvs_info *mvi, int port_id, u32 off_lo, + MVS_CHIP_DISP->write_port_cfg_data(mvi, port_id, hi); + } + +-static void mvs_bytes_dmaed(struct mvs_info *mvi, int i) ++static void mvs_bytes_dmaed(struct mvs_info *mvi, int i, gfp_t gfp_flags) + { + struct mvs_phy *phy = &mvi->phy[i]; + struct asd_sas_phy *sas_phy = &phy->sas_phy; +- struct sas_ha_struct *sas_ha; + if (!phy->phy_attached) + return; + +@@ -245,8 +244,7 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i) + return; + } + +- sas_ha = mvi->sas; +- sas_ha->notify_phy_event(sas_phy, PHYE_OOB_DONE); ++ sas_notify_phy_event_gfp(sas_phy, PHYE_OOB_DONE, gfp_flags); + + if (sas_phy->phy) { + struct sas_phy *sphy = sas_phy->phy; +@@ -278,8 +276,7 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i) + + sas_phy->frame_rcvd_size = phy->frame_rcvd_size; + +- mvi->sas->notify_port_event(sas_phy, +- PORTE_BYTES_DMAED); ++ sas_notify_port_event_gfp(sas_phy, PORTE_BYTES_DMAED, gfp_flags); + } + + void mvs_scan_start(struct Scsi_Host *shost) +@@ -295,7 +292,7 @@ void mvs_scan_start(struct Scsi_Host *shost) + for (j = 0; j < core_nr; j++) { + mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[j]; + for (i = 0; i < mvi->chip->n_phy; ++i) +- mvs_bytes_dmaed(mvi, i); ++ mvs_bytes_dmaed(mvi, i, GFP_KERNEL); + } + mvs_prv->scan_finished = 1; + } +@@ -1897,7 +1894,6 @@ static void mvs_work_queue(struct work_struct *work) + struct mvs_info *mvi = mwq->mvi; + unsigned long flags; + u32 phy_no = (unsigned long) mwq->data; +- struct sas_ha_struct *sas_ha = mvi->sas; + struct mvs_phy *phy = &mvi->phy[phy_no]; + struct asd_sas_phy *sas_phy = &phy->sas_phy; + +@@ -1913,21 +1909,21 @@ static void mvs_work_queue(struct work_struct *work) + if (!(tmp & PHY_READY_MASK)) { + sas_phy_disconnected(sas_phy); + mvs_phy_disconnected(phy); +- sas_ha->notify_phy_event(sas_phy, +- PHYE_LOSS_OF_SIGNAL); ++ sas_notify_phy_event_gfp(sas_phy, ++ PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC); + mv_dprintk("phy%d Removed Device\n", phy_no); + } else { + MVS_CHIP_DISP->detect_porttype(mvi, phy_no); + mvs_update_phyinfo(mvi, phy_no, 1); +- mvs_bytes_dmaed(mvi, phy_no); ++ mvs_bytes_dmaed(mvi, phy_no, GFP_ATOMIC); + mvs_port_notify_formed(sas_phy, 0); + mv_dprintk("phy%d Attached Device\n", phy_no); + } + } + } else if (mwq->handler & EXP_BRCT_CHG) { + phy->phy_event &= ~EXP_BRCT_CHG; +- sas_ha->notify_port_event(sas_phy, +- PORTE_BROADCAST_RCVD); ++ sas_notify_port_event_gfp(sas_phy, ++ PORTE_BROADCAST_RCVD, GFP_ATOMIC); + mv_dprintk("phy%d Got Broadcast Change\n", phy_no); + } + list_del(&mwq->entry); +@@ -2044,7 +2040,7 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events) + mdelay(10); + } + +- mvs_bytes_dmaed(mvi, phy_no); ++ mvs_bytes_dmaed(mvi, phy_no, GFP_ATOMIC); + /* whether driver is going to handle hot plug */ + if (phy->phy_event & PHY_PLUG_OUT) { + mvs_port_notify_formed(&phy->sas_phy, 0); +-- +2.27.0 + diff --git a/patches/0468-scsi-isci-Pass-gfp_t-flags-in-isci_port_link_down.patch b/patches/0468-scsi-isci-Pass-gfp_t-flags-in-isci_port_link_down.patch new file mode 100644 index 00000000..76b6a3d0 --- /dev/null +++ b/patches/0468-scsi-isci-Pass-gfp_t-flags-in-isci_port_link_down.patch @@ -0,0 +1,264 @@ +From 5f2557b303a3c53dd04d1bb0095b291fb002abc2 Mon Sep 17 00:00:00 2001 +From: "Ahmed S. Darwish" +Date: Wed, 31 Mar 2021 02:01:10 +0000 +Subject: [PATCH 150/256] scsi: isci: Pass gfp_t flags in isci_port_link_down() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +mainline inclusion +from mainline-v5.12-rc1 +commit 885ab3b8926fdf9cdd7163dfad99deb9b0662b39 +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=885ab3b8926fdf9cdd7163dfad99deb9b0662b39 + +---------------------------------------------------------------------- + +Use the new libsas event notifiers API, which requires callers to +explicitly pass the gfp_t memory allocation flags. + +sas_notify_phy_event() is exclusively called by isci_port_link_down(). +Below is the context analysis for all of its call chains: + +port.c: port_timeout(), atomic, timer callback (*) +spin_lock_irqsave(isci_host::scic_lock, ) + -> port_state_machine_change(..., SCI_PORT_FAILED) + -> enter SCI port state: *SCI_PORT_FAILED* + -> sci_port_failed_state_enter() + -> isci_port_hard_reset_complete() + -> isci_port_link_down() + +port.c: isci_port_perform_hard_reset() +spin_lock_irqsave(isci_host::scic_lock, ) + -> port.c: sci_port_hard_reset(), atomic (*) + -> phy.c: sci_phy_reset() + -> sci_change_state(SCI_PHY_RESETTING) + -> enter SCI PHY state: *SCI_PHY_RESETTING* + -> sci_phy_resetting_state_enter() + -> port.c: sci_port_deactivate_phy() + -> isci_port_link_down() + +port.c: enter SCI port state: *SCI_PORT_READY* # Cont. from [1] + -> sci_port_ready_state_enter() + -> isci_port_hard_reset_complete() + -> isci_port_link_down() + +phy.c: enter SCI state: *SCI_PHY_STOPPED* # Cont. from [2] + -> sci_phy_stopped_state_enter() + -> host.c: sci_controller_link_down() + -> ->link_down_handler() + == port_config.c: sci_apc_agent_link_down() + -> port.c: sci_port_remove_phy() + -> sci_port_deactivate_phy() + -> isci_port_link_down() + == port_config.c: sci_mpc_agent_link_down() + -> port.c: sci_port_link_down() + -> sci_port_deactivate_phy() + -> isci_port_link_down() + +phy.c: enter SCI state: *SCI_PHY_STARTING* # Cont. from [3] + -> sci_phy_starting_state_enter() + -> host.c: sci_controller_link_down() + -> ->link_down_handler() + == port_config.c: sci_apc_agent_link_down() + -> port.c: sci_port_remove_phy() + -> isci_port_link_down() + == port_config.c: sci_mpc_agent_link_down() + -> port.c: sci_port_link_down() + -> sci_port_deactivate_phy() + -> isci_port_link_down() + +[1] Call chains for 'enter SCI port state: *SCI_PORT_READY*' +------------------------------------------------------------ + +host.c: isci_host_init() (@) +spin_lock_irq(isci_host::scic_lock) + -> sci_controller_initialize(), atomic (*) + -> port_config.c: sci_port_configuration_agent_initialize() + -> sci_mpc_agent_validate_phy_configuration() + -> port.c: sci_port_add_phy() + -> sci_port_general_link_up_handler() + -> port_state_machine_change(, SCI_PORT_READY) + -> enter port state *SCI_PORT_READY* + +host.c: isci_host_start() (@) +spin_lock_irq(isci_host::scic_lock) + -> host.c: sci_controller_start(), atomic (*) + -> host.c: sci_port_start() + -> port.c: port_state_machine_change(, SCI_PORT_READY) + -> enter port state *SCI_PORT_READY* + +port_config.c: apc_agent_timeout(), atomic, timer callback (*) + -> sci_apc_agent_configure_ports() + -> port.c: sci_port_add_phy() + -> sci_port_general_link_up_handler() + -> port_state_machine_change(, SCI_PORT_READY) + -> enter port state *SCI_PORT_READY* + +port_config.c: mpc_agent_timeout(), atomic, timer callback (*) +spin_lock_irqsave(isci_host::scic_lock, ) + -> ->link_up_handler() + == port.c: sci_apc_agent_link_up() + -> sci_port_general_link_up_handler() + -> port_state_machine_change(, SCI_PORT_READY) + -> enter port state *SCI_PORT_READY* + == port.c: sci_mpc_agent_link_up() + -> port.c: sci_port_link_up() + -> sci_port_general_link_up_handler() + -> port_state_machine_change(, SCI_PORT_READY) + -> enter port state *SCI_PORT_READY* + +phy.c: enter SCI state: SCI_PHY_SUB_FINAL # Cont. from [1A] + -> sci_phy_starting_final_substate_enter() + -> sci_change_state(SCI_PHY_READY) + -> enter SCI state: *SCI_PHY_READY* + -> sci_phy_ready_state_enter() + -> host.c: sci_controller_link_up() + -> port_agent.link_up_handler() + == port_config.c: sci_apc_agent_link_up() + -> port.c: sci_port_link_up() + -> sci_port_general_link_up_handler() + -> port_state_machine_change(, SCI_PORT_READY) + -> enter port state *SCI_PORT_READY* + == port_config.c: sci_mpc_agent_link_up() + -> port.c: sci_port_link_up() + -> sci_port_general_link_up_handler() + -> port_state_machine_change(, SCI_PORT_READY) + -> enter port state *SCI_PORT_READY* + +[1A] Call chains for entering SCI state: *SCI_PHY_SUB_FINAL* +------------------------------------------------------------ + +host.c: power_control_timeout(), atomic, timer callback (*) +spin_lock_irqsave(isci_host::scic_lock, ) + -> phy.c: sci_phy_consume_power_handler() + -> phy.c: sci_change_state(SCI_PHY_SUB_FINAL) + +host.c: sci_controller_error_handler(): atomic, irq handler (*) +OR host.c: sci_controller_completion_handler(), atomic, tasklet (*) + -> sci_controller_process_completions() + -> sci_controller_unsolicited_frame() + -> phy.c: sci_phy_frame_handler() + -> sci_change_state(SCI_PHY_SUB_AWAIT_SAS_POWER) + -> sci_phy_starting_await_sas_power_substate_enter() + -> host.c: sci_controller_power_control_queue_insert() + -> phy.c: sci_phy_consume_power_handler() + -> sci_change_state(SCI_PHY_SUB_FINAL) + -> sci_change_state(SCI_PHY_SUB_FINAL) + -> sci_controller_event_completion() + -> phy.c: sci_phy_event_handler() + -> sci_phy_start_sata_link_training() + -> sci_change_state(SCI_PHY_SUB_AWAIT_SATA_POWER) + -> sci_phy_starting_await_sata_power_substate_enter + -> host.c: sci_controller_power_control_queue_insert() + -> phy.c: sci_phy_consume_power_handler() + -> sci_change_state(SCI_PHY_SUB_FINAL) + +[2] Call chains for entering state: *SCI_PHY_STOPPED* +----------------------------------------------------- + +host.c: isci_host_init() (@) +spin_lock_irq(isci_host::scic_lock) + -> sci_controller_initialize(), atomic (*) + -> phy.c: sci_phy_initialize() + -> phy.c: sci_phy_link_layer_initialization() + -> phy.c: sci_change_state(SCI_PHY_STOPPED) + +init.c: PCI ->remove() || PM_OPS ->suspend, process context (+) + -> host.c: isci_host_deinit() + -> sci_controller_stop_phys() + -> phy.c: sci_phy_stop() + -> sci_change_state(SCI_PHY_STOPPED) + +phy.c: isci_phy_control() +spin_lock_irqsave(isci_host::scic_lock, ) + -> sci_phy_stop(), atomic (*) + -> sci_change_state(SCI_PHY_STOPPED) + +[3] Call chains for entering state: *SCI_PHY_STARTING* +------------------------------------------------------ + +phy.c: phy_sata_timeout(), atimer, timer callback (*) +spin_lock_irqsave(isci_host::scic_lock, ) + -> sci_change_state(SCI_PHY_STARTING) + +host.c: phy_startup_timeout(), atomic, timer callback (*) +spin_lock_irqsave(isci_host::scic_lock, ) + -> sci_controller_start_next_phy() + -> sci_phy_start() + -> sci_change_state(SCI_PHY_STARTING) + +host.c: isci_host_start() (@) +spin_lock_irq(isci_host::scic_lock) + -> sci_controller_start(), atomic (*) + -> sci_controller_start_next_phy() + -> sci_phy_start() + -> sci_change_state(SCI_PHY_STARTING) + +phy.c: Enter SCI state *SCI_PHY_SUB_FINAL*, atomic, check above (*) + -> sci_change_state(SCI_PHY_SUB_FINAL) + -> sci_phy_starting_final_substate_enter() + -> sci_change_state(SCI_PHY_READY) + -> Enter SCI state: *SCI_PHY_READY* + -> sci_phy_ready_state_enter() + -> host.c: sci_controller_link_up() + -> sci_controller_start_next_phy() + -> sci_phy_start() + -> sci_change_state(SCI_PHY_STARTING) + +phy.c: sci_phy_event_handler(), atomic, discussed earlier (*) + -> sci_change_state(SCI_PHY_STARTING), 11 instances + +phy.c: enter SCI state: *SCI_PHY_RESETTING*, atomic, discussed (*) + -> sci_phy_resetting_state_enter() + -> sci_change_state(SCI_PHY_STARTING) + +As can be seen from the "(*)" markers above, almost all the call-chains are +atomic. The only exception, marked with "(+)", is a PCI ->remove() and +PM_OPS ->suspend() cold path. Thus, pass GFP_ATOMIC to the libsas phy event +notifier. + +Note, The now-replaced libsas APIs used in_interrupt() to implicitly decide +which memory allocation type to use. This was only partially correct, as +it fails to choose the correct GFP flags when just preemption or interrupts +are disabled. Such buggy code paths are marked with "(@)" in the call +chains above. + +Link: https://lore.kernel.org/r/20210118100955.1761652-6-a.darwish@linutronix.de +Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event lost") +Cc: Artur Paszkiewicz +Reviewed-by: John Garry +Signed-off-by: Ahmed S. Darwish +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +Signed-off-by: Chen Jun +Acked-by:  Weilong Chen +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/isci/port.c +--- + drivers/scsi/isci/port.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c +index 1df45f028ea7..016f62179e65 100644 +--- a/drivers/scsi/isci/port.c ++++ b/drivers/scsi/isci/port.c +@@ -270,8 +270,8 @@ static void isci_port_link_down(struct isci_host *isci_host, + * isci_port_deformed and isci_dev_gone functions. + */ + sas_phy_disconnected(&isci_phy->sas_phy); +- isci_host->sas_ha.notify_phy_event(&isci_phy->sas_phy, +- PHYE_LOSS_OF_SIGNAL); ++ sas_notify_phy_event_gfp(&isci_phy->sas_phy, ++ PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC); + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_port = %p - Done\n", __func__, isci_port); +-- +2.27.0 + diff --git a/patches/0469-scsi-isci-Pass-gfp_t-flags-in-isci_port_link_up.patch b/patches/0469-scsi-isci-Pass-gfp_t-flags-in-isci_port_link_up.patch new file mode 100644 index 00000000..910c12b6 --- /dev/null +++ b/patches/0469-scsi-isci-Pass-gfp_t-flags-in-isci_port_link_up.patch @@ -0,0 +1,145 @@ +From 4132f6c848d392a7f584f36a8193ce2a5552a236 Mon Sep 17 00:00:00 2001 +From: "Ahmed S. Darwish" +Date: Wed, 31 Mar 2021 02:01:11 +0000 +Subject: [PATCH 151/256] scsi: isci: Pass gfp_t flags in isci_port_link_up() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +mainline inclusion +from mainline-v5.12-rc1 +commit 5ce7902902adb8d154d67ba494f06daa29360ef0 +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5ce7902902adb8d154d67ba494f06daa29360ef0 + +---------------------------------------------------------------------- + +Use the new libsas event notifiers API, which requires callers to +explicitly pass the gfp_t memory allocation flags. + +libsas sas_notify_port_event() is called from isci_port_link_up(). Below +is the context analysis for all of its call chains: + +host.c: isci_host_init() (@) +spin_lock_irq(isci_host::scic_lock) + -> sci_controller_initialize(), atomic (*) + -> port_config.c: sci_port_configuration_agent_initialize() + -> sci_mpc_agent_validate_phy_configuration() + -> port.c: sci_port_add_phy() + -> sci_port_general_link_up_handler() + -> sci_port_activate_phy() + -> isci_port_link_up() + +port_config.c: apc_agent_timeout(), atomic, timer callback (*) + -> sci_apc_agent_configure_ports() + -> port.c: sci_port_add_phy() + -> sci_port_general_link_up_handler() + -> sci_port_activate_phy() + -> isci_port_link_up() + +phy.c: enter SCI state: *SCI_PHY_SUB_FINAL* # Cont. from [1] + -> phy.c: sci_phy_starting_final_substate_enter() + -> phy.c: sci_change_state(SCI_PHY_READY) + -> enter SCI state: *SCI_PHY_READY* + -> phy.c: sci_phy_ready_state_enter() + -> host.c: sci_controller_link_up() + -> .link_up_handler() + == port_config.c: sci_apc_agent_link_up() + -> port.c: sci_port_link_up() + -> (continue at [A]) + == port_config.c: sci_mpc_agent_link_up() + -> port.c: sci_port_link_up() + -> (continue at [A]) + +port_config.c: mpc_agent_timeout(), atomic, timer callback (*) +spin_lock_irqsave(isci_host::scic_lock, ) + -> ->link_up_handler() + == port_config.c: sci_apc_agent_link_up() + -> port.c: sci_port_link_up() + -> (continue at [A]) + == port_config.c: sci_mpc_agent_link_up() + -> port.c: sci_port_link_up() + -> (continue at [A]) + +[A] port.c: sci_port_link_up() + -> sci_port_activate_phy() + -> isci_port_link_up() + -> sci_port_general_link_up_handler() + -> sci_port_activate_phy() + -> isci_port_link_up() + +[1] Call chains for entering SCI state: *SCI_PHY_SUB_FINAL* +----------------------------------------------------------- + +host.c: power_control_timeout(), atomic, timer callback (*) +spin_lock_irqsave(isci_host::scic_lock, ) + -> phy.c: sci_phy_consume_power_handler() + -> phy.c: sci_change_state(SCI_PHY_SUB_FINAL) + +host.c: sci_controller_error_handler(): atomic, irq handler (*) +OR host.c: sci_controller_completion_handler(), atomic, tasklet (*) + -> sci_controller_process_completions() + -> sci_controller_unsolicited_frame() + -> phy.c: sci_phy_frame_handler() + -> sci_change_state(SCI_PHY_SUB_AWAIT_SAS_POWER) + -> sci_phy_starting_await_sas_power_substate_enter() + -> host.c: sci_controller_power_control_queue_insert() + -> phy.c: sci_phy_consume_power_handler() + -> sci_change_state(SCI_PHY_SUB_FINAL) + -> sci_change_state(SCI_PHY_SUB_FINAL) + -> sci_controller_event_completion() + -> phy.c: sci_phy_event_handler() + -> sci_phy_start_sata_link_training() + -> sci_change_state(SCI_PHY_SUB_AWAIT_SATA_POWER) + -> sci_phy_starting_await_sata_power_substate_enter + -> host.c: sci_controller_power_control_queue_insert() + -> phy.c: sci_phy_consume_power_handler() + -> sci_change_state(SCI_PHY_SUB_FINAL) + +As can be seen from the "(*)" markers above, all the call-chains are +atomic. Pass GFP_ATOMIC to libsas port event notifier. + +Note, the now-replaced libsas APIs used in_interrupt() to implicitly decide +which memory allocation type to use. This was only partially correct, as +it fails to choose the correct GFP flags when just preemption or interrupts +are disabled. Such buggy code paths are marked with "(@)" in the call +chains above. + +Link: https://lore.kernel.org/r/20210118100955.1761652-7-a.darwish@linutronix.de +Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event lost") +Cc: Artur Paszkiewicz +Reviewed-by: John Garry +Signed-off-by: Ahmed S. Darwish +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +Signed-off-by: Chen Jun +Acked-by:  Weilong Chen +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/isci/port.c +--- + drivers/scsi/isci/port.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c +index 016f62179e65..520200c06bf7 100644 +--- a/drivers/scsi/isci/port.c ++++ b/drivers/scsi/isci/port.c +@@ -223,8 +223,8 @@ static void isci_port_link_up(struct isci_host *isci_host, + /* Notify libsas that we have an address frame, if indeed + * we've found an SSP, SMP, or STP target */ + if (success) +- isci_host->sas_ha.notify_port_event(&iphy->sas_phy, +- PORTE_BYTES_DMAED); ++ sas_notify_port_event_gfp(&iphy->sas_phy, ++ PORTE_BYTES_DMAED, GFP_ATOMIC); + } + + +-- +2.27.0 + diff --git a/patches/0470-scsi-isci-Pass-gfp_t-flags-in-isci_port_bc_change_re.patch b/patches/0470-scsi-isci-Pass-gfp_t-flags-in-isci_port_bc_change_re.patch new file mode 100644 index 00000000..9c27836b --- /dev/null +++ b/patches/0470-scsi-isci-Pass-gfp_t-flags-in-isci_port_bc_change_re.patch @@ -0,0 +1,213 @@ +From 18495f3fcdd060e5e59c8ea8aee7c5bd71500763 Mon Sep 17 00:00:00 2001 +From: "Ahmed S. Darwish" +Date: Wed, 31 Mar 2021 02:01:12 +0000 +Subject: [PATCH 152/256] scsi: isci: Pass gfp_t flags in + isci_port_bc_change_received() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +mainline inclusion +from mainline-v5.12-rc1 +commit 71dca5539fcf977aead0c9ea1962e70e78484b8e +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=71dca5539fcf977aead0c9ea1962e70e78484b8e + +---------------------------------------------------------------------- + +Use the new libsas event notifiers API, which requires callers to +explicitly pass the gfp_t memory allocation flags. + +libsas sas_notify_port_event() is called from +isci_port_bc_change_received(). Below is the context analysis for all of +its call chains: + +host.c: sci_controller_error_handler(): atomic, irq handler (*) +OR host.c: sci_controller_completion_handler(), atomic, tasklet (*) + -> sci_controller_process_completions() + -> sci_controller_event_completion() + -> phy.c: sci_phy_event_handler() + -> port.c: sci_port_broadcast_change_received() + -> isci_port_bc_change_received() + +host.c: isci_host_init() (@) +spin_lock_irq(isci_host::scic_lock) + -> sci_controller_initialize(), atomic (*) + -> port_config.c: sci_port_configuration_agent_initialize() + -> sci_mpc_agent_validate_phy_configuration() + -> port.c: sci_port_add_phy() + -> sci_port_set_phy() + -> phy.c: sci_phy_set_port() + -> port.c: sci_port_broadcast_change_received() + -> isci_port_bc_change_received() + +port_config.c: apc_agent_timeout(), atomic, timer callback (*) + -> sci_apc_agent_configure_ports() + -> port.c: sci_port_add_phy() + -> sci_port_set_phy() + -> phy.c: sci_phy_set_port() + -> port.c: sci_port_broadcast_change_received() + -> isci_port_bc_change_received() + +phy.c: enter SCI state: *SCI_PHY_STOPPED* # Cont. from [1] + -> sci_phy_stopped_state_enter() + -> host.c: sci_controller_link_down() + -> ->link_down_handler() + == port_config.c: sci_apc_agent_link_down() + -> port.c: sci_port_remove_phy() + -> sci_port_clear_phy() + -> phy.c: sci_phy_set_port() + -> port.c: sci_port_broadcast_change_received() + -> isci_port_bc_change_received() + +phy.c: enter SCI state: *SCI_PHY_STARTING* # Cont. from [2] + -> sci_phy_starting_state_enter() + -> host.c: sci_controller_link_down() + -> ->link_down_handler() + == port_config.c: sci_apc_agent_link_down() + -> port.c: sci_port_remove_phy() + -> sci_port_clear_phy() + -> phy.c: sci_phy_set_port() + -> port.c: sci_port_broadcast_change_received() + -> isci_port_bc_change_received() + +[1] Call chains for entering state: *SCI_PHY_STOPPED* +----------------------------------------------------- + +host.c: isci_host_init() (@) +spin_lock_irq(isci_host::scic_lock) + -> sci_controller_initialize(), atomic (*) + -> phy.c: sci_phy_initialize() + -> phy.c: sci_phy_link_layer_initialization() + -> phy.c: sci_change_state(SCI_PHY_STOPPED) + +init.c: PCI ->remove() || PM_OPS ->suspend, process context (+) + -> host.c: isci_host_deinit() + -> sci_controller_stop_phys() + -> phy.c: sci_phy_stop() + -> sci_change_state(SCI_PHY_STOPPED) + +phy.c: isci_phy_control() +spin_lock_irqsave(isci_host::scic_lock, ) + -> sci_phy_stop(), atomic (*) + -> sci_change_state(SCI_PHY_STOPPED) + +[2] Call chains for entering state: *SCI_PHY_STARTING* +------------------------------------------------------ + +phy.c: phy_sata_timeout(), atimer, timer callback (*) +spin_lock_irqsave(isci_host::scic_lock, ) + -> sci_change_state(SCI_PHY_STARTING) + +host.c: phy_startup_timeout(), atomic, timer callback (*) +spin_lock_irqsave(isci_host::scic_lock, ) + -> sci_controller_start_next_phy() + -> sci_phy_start() + -> sci_change_state(SCI_PHY_STARTING) + +host.c: isci_host_start() (@) +spin_lock_irq(isci_host::scic_lock) + -> sci_controller_start(), atomic (*) + -> sci_controller_start_next_phy() + -> sci_phy_start() + -> sci_change_state(SCI_PHY_STARTING) + +phy.c: Enter SCI state *SCI_PHY_SUB_FINAL* # Cont. from [2A] + -> sci_change_state(SCI_PHY_SUB_FINAL) + -> sci_phy_starting_final_substate_enter() + -> sci_change_state(SCI_PHY_READY) + -> Enter SCI state: *SCI_PHY_READY* + -> sci_phy_ready_state_enter() + -> host.c: sci_controller_link_up() + -> sci_controller_start_next_phy() + -> sci_phy_start() + -> sci_change_state(SCI_PHY_STARTING) + +phy.c: sci_phy_event_handler(), atomic, discussed earlier (*) + -> sci_change_state(SCI_PHY_STARTING), 11 instances + +port.c: isci_port_perform_hard_reset() +spin_lock_irqsave(isci_host::scic_lock, ) + -> port.c: sci_port_hard_reset(), atomic (*) + -> phy.c: sci_phy_reset() + -> sci_change_state(SCI_PHY_RESETTING) + -> enter SCI PHY state: *SCI_PHY_RESETTING* + -> sci_phy_resetting_state_enter() + -> sci_change_state(SCI_PHY_STARTING) + +[2A] Call chains for entering SCI state: *SCI_PHY_SUB_FINAL* +------------------------------------------------------------ + +host.c: power_control_timeout(), atomic, timer callback (*) +spin_lock_irqsave(isci_host::scic_lock, ) + -> phy.c: sci_phy_consume_power_handler() + -> phy.c: sci_change_state(SCI_PHY_SUB_FINAL) + +host.c: sci_controller_error_handler(): atomic, irq handler (*) +OR host.c: sci_controller_completion_handler(), atomic, tasklet (*) + -> sci_controller_process_completions() + -> sci_controller_unsolicited_frame() + -> phy.c: sci_phy_frame_handler() + -> sci_change_state(SCI_PHY_SUB_AWAIT_SAS_POWER) + -> sci_phy_starting_await_sas_power_substate_enter() + -> host.c: sci_controller_power_control_queue_insert() + -> phy.c: sci_phy_consume_power_handler() + -> sci_change_state(SCI_PHY_SUB_FINAL) + -> sci_change_state(SCI_PHY_SUB_FINAL) + -> sci_controller_event_completion() + -> phy.c: sci_phy_event_handler() + -> sci_phy_start_sata_link_training() + -> sci_change_state(SCI_PHY_SUB_AWAIT_SATA_POWER) + -> sci_phy_starting_await_sata_power_substate_enter + -> host.c: sci_controller_power_control_queue_insert() + -> phy.c: sci_phy_consume_power_handler() + -> sci_change_state(SCI_PHY_SUB_FINAL) + +As can be seen from the "(*)" markers above, almost all the call-chains are +atomic. The only exception, marked with "(+)", is a PCI ->remove() and +PM_OPS ->suspend() cold path. Thus, pass GFP_ATOMIC to the libsas port +event notifier. + +Note, the now-replaced libsas APIs used in_interrupt() to implicitly decide +which memory allocation type to use. This was only partially correct, as +it fails to choose the correct GFP flags when just preemption or interrupts +are disabled. Such buggy code paths are marked with "(@)" in the call +chains above. + +Link: https://lore.kernel.org/r/20210118100955.1761652-8-a.darwish@linutronix.de +Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event lost") +Cc: Artur Paszkiewicz +Reviewed-by: John Garry +Signed-off-by: Ahmed S. Darwish +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +Signed-off-by: Chen Jun +Acked-by:  Weilong Chen +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/isci/port.c +--- + drivers/scsi/isci/port.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c +index 520200c06bf7..e50c3b0deeb3 100644 +--- a/drivers/scsi/isci/port.c ++++ b/drivers/scsi/isci/port.c +@@ -164,7 +164,8 @@ static void isci_port_bc_change_received(struct isci_host *ihost, + "%s: isci_phy = %p, sas_phy = %p\n", + __func__, iphy, &iphy->sas_phy); + +- ihost->sas_ha.notify_port_event(&iphy->sas_phy, PORTE_BROADCAST_RCVD); ++ sas_notify_port_event_gfp(&iphy->sas_phy, ++ PORTE_BROADCAST_RCVD, GFP_ATOMIC); + sci_port_bcn_enable(iport); + } + +-- +2.27.0 + diff --git a/patches/0471-scsi-libsas-Pass-gfp_t-flags-to-event-notifiers.patch b/patches/0471-scsi-libsas-Pass-gfp_t-flags-to-event-notifiers.patch new file mode 100644 index 00000000..336ba7cc --- /dev/null +++ b/patches/0471-scsi-libsas-Pass-gfp_t-flags-to-event-notifiers.patch @@ -0,0 +1,71 @@ +From 00f5871a8fa812d989a9bb3a47ab65dab7a000a9 Mon Sep 17 00:00:00 2001 +From: "Ahmed S. Darwish" +Date: Tue, 3 Aug 2021 14:47:36 +0800 +Subject: [PATCH 153/256] scsi: libsas: Pass gfp_t flags to event notifiers + +mainline inclusion +from mainline-v5.12-rc1 +commit 19a39831ff99f88ea8d01a2b6716084f14752529 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=19a39831ff99f88ea8d01a2b6716084f14752529 + +---------------------------------------------------------------------- + +Use the new libsas event notifiers API, which requires callers to +explicitly pass the gfp_t memory allocation flags. + +Context analysis: + + - sas_enable_revalidation(): process, acquires mutex + - sas_resume_ha(): process, calls wait_event_timeout() + +Link: https://lore.kernel.org/r/20210118100955.1761652-9-a.darwish@linutronix.de +Cc: Jason Yan +Reviewed-by: John Garry +Signed-off-by: Ahmed S. Darwish +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/libsas/sas_event.c +--- + drivers/scsi/libsas/sas_event.c | 3 ++- + drivers/scsi/libsas/sas_init.c | 3 ++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c +index 21b020f958b8..4bd200cc294b 100644 +--- a/drivers/scsi/libsas/sas_event.c ++++ b/drivers/scsi/libsas/sas_event.c +@@ -126,7 +126,8 @@ void sas_enable_revalidation(struct sas_ha_struct *ha) + + sas_phy = container_of(port->phy_list.next, struct asd_sas_phy, + port_phy_el); +- ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); ++ sas_notify_port_event_gfp(sas_phy, ++ PORTE_BROADCAST_RCVD, GFP_KERNEL); + } + mutex_unlock(&ha->disco_mutex); + } +diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c +index 1fcb8347901b..556f29233872 100644 +--- a/drivers/scsi/libsas/sas_init.c ++++ b/drivers/scsi/libsas/sas_init.c +@@ -427,7 +427,8 @@ void sas_resume_ha(struct sas_ha_struct *ha) + + if (phy->suspended) { + dev_warn(&phy->phy->dev, "resume timeout\n"); +- sas_notify_phy_event(phy, PHYE_RESUME_TIMEOUT); ++ sas_notify_phy_event_gfp(phy, PHYE_RESUME_TIMEOUT, ++ GFP_KERNEL); + } + } + +-- +2.27.0 + diff --git a/patches/0472-scsi-pm80xx-Pass-gfp_t-flags-to-libsas-event-notifie.patch b/patches/0472-scsi-pm80xx-Pass-gfp_t-flags-to-libsas-event-notifie.patch new file mode 100644 index 00000000..e9782e49 --- /dev/null +++ b/patches/0472-scsi-pm80xx-Pass-gfp_t-flags-to-libsas-event-notifie.patch @@ -0,0 +1,420 @@ +From 9f7199230ef2e234de43256b8138606847ed6ba7 Mon Sep 17 00:00:00 2001 +From: "Ahmed S. Darwish" +Date: Tue, 3 Aug 2021 14:47:37 +0800 +Subject: [PATCH 154/256] scsi: pm80xx: Pass gfp_t flags to libsas event + notifiers + +mainline inclusion +from mainline-v5.12-rc1 +commit cd4e8176989f4909550ac7b95f475e993ae67f8b +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cd4e8176989f4909550ac7b95f475e993ae67f8b + +---------------------------------------------------------------------- + +Use the new libsas event notifiers API, which requires callers to +explicitly pass the gfp_t memory allocation flags. + +Call chain analysis, pm8001_hwi.c: + + pm8001_interrupt_handler_msix() || pm8001_interrupt_handler_intx() || pm8001_tasklet() + -> PM8001_CHIP_DISP->isr() = pm80xx_chip_isr() + -> process_oq [spin_lock_irqsave(&pm8001_ha->lock, ...)] + -> process_one_iomb() + -> mpi_hw_event() + -> hw_event_sas_phy_up() + -> pm8001_bytes_dmaed() + -> hw_event_sata_phy_up + -> pm8001_bytes_dmaed() + +All functions are invoked by process_one_iomb(), which is invoked by the +interrupt service routine and the tasklet handler. A similar call chain is +also found at pm80xx_hwi.c. Pass GFP_ATOMIC. + +For pm8001_sas.c, pm8001_phy_control() runs in task context as it calls +wait_for_completion() and msleep(). Pass GFP_KERNEL. + +Link: https://lore.kernel.org/r/20210118100955.1761652-10-a.darwish@linutronix.de +Cc: Jack Wang +Reviewed-by: John Garry +Reviewed-by: Jack Wang +Signed-off-by: Ahmed S. Darwish +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/pm8001/pm8001_hwi.c + drivers/scsi/pm8001/pm8001_sas.c + drivers/scsi/pm8001/pm80xx_hwi.c +--- + drivers/scsi/pm8001/pm8001_hwi.c | 56 ++++++++++++++++++++------------ + drivers/scsi/pm8001/pm80xx_hwi.c | 45 ++++++++++++++----------- + 2 files changed, 61 insertions(+), 40 deletions(-) + +diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c +index 3e814c0469fb..258bc914fb32 100644 +--- a/drivers/scsi/pm8001/pm8001_hwi.c ++++ b/drivers/scsi/pm8001/pm8001_hwi.c +@@ -3270,7 +3270,7 @@ void pm8001_bytes_dmaed(struct pm8001_hba_info *pm8001_ha, int i) + PM8001_MSG_DBG(pm8001_ha, pm8001_printk("phy %d byte dmaded.\n", i)); + + sas_phy->frame_rcvd_size = phy->frame_rcvd_size; +- pm8001_ha->sas->notify_port_event(sas_phy, PORTE_BYTES_DMAED); ++ sas_notify_port_event_gfp(sas_phy, PORTE_BYTES_DMAED, GFP_ATOMIC); + } + + /* Get the link rate speed */ +@@ -3383,7 +3383,6 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) + u32 npip_portstate = le32_to_cpu(pPayload->npip_portstate); + u8 portstate = (u8)(npip_portstate & 0x0000000F); + struct pm8001_port *port = &pm8001_ha->port[port_id]; +- struct sas_ha_struct *sas_ha = pm8001_ha->sas; + struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; + unsigned long flags; + u8 deviceType = pPayload->sas_identify.dev_type; +@@ -3430,7 +3429,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) + else if (phy->identify.device_type != SAS_PHY_UNUSED) + phy->identify.target_port_protocols = SAS_PROTOCOL_SMP; + phy->sas_phy.oob_mode = SAS_OOB_MODE; +- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE); ++ sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_OOB_DONE, GFP_ATOMIC); + spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags); + memcpy(phy->frame_rcvd, &pPayload->sas_identify, + sizeof(struct sas_identify_frame)-4); +@@ -3462,7 +3461,6 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) + u32 npip_portstate = le32_to_cpu(pPayload->npip_portstate); + u8 portstate = (u8)(npip_portstate & 0x0000000F); + struct pm8001_port *port = &pm8001_ha->port[port_id]; +- struct sas_ha_struct *sas_ha = pm8001_ha->sas; + struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; + unsigned long flags; + PM8001_MSG_DBG(pm8001_ha, +@@ -3475,7 +3473,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) + phy->phy_type |= PORT_TYPE_SATA; + phy->phy_attached = 1; + phy->sas_phy.oob_mode = SATA_OOB_MODE; +- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE); ++ sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_OOB_DONE, GFP_ATOMIC); + spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags); + memcpy(phy->frame_rcvd, ((u8 *)&pPayload->sata_fis - 4), + sizeof(struct dev_to_host_fis)); +@@ -3840,12 +3838,14 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + case HW_EVENT_SATA_SPINUP_HOLD: + PM8001_MSG_DBG(pm8001_ha, + pm8001_printk("HW_EVENT_SATA_SPINUP_HOLD\n")); +- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD); ++ sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_SPINUP_HOLD, ++ GFP_ATOMIC); + break; + case HW_EVENT_PHY_DOWN: + PM8001_MSG_DBG(pm8001_ha, + pm8001_printk("HW_EVENT_PHY_DOWN\n")); +- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL); ++ sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL, ++ GFP_ATOMIC); + phy->phy_attached = 0; + phy->phy_state = 0; + hw_event_phy_down(pm8001_ha, piomb); +@@ -3855,7 +3855,8 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + pm8001_printk("HW_EVENT_PORT_INVALID\n")); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); ++ sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ GFP_ATOMIC); + break; + /* the broadcast change primitive received, tell the LIBSAS this event + to revalidate the sas domain*/ +@@ -3867,14 +3868,16 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); + sas_phy->sas_prim = HW_EVENT_BROADCAST_CHANGE; + spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); +- sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); ++ sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, ++ GFP_ATOMIC); + break; + case HW_EVENT_PHY_ERROR: + PM8001_MSG_DBG(pm8001_ha, + pm8001_printk("HW_EVENT_PHY_ERROR\n")); + sas_phy_disconnected(&phy->sas_phy); + phy->phy_attached = 0; +- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR); ++ sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_OOB_ERROR, ++ GFP_ATOMIC); + break; + case HW_EVENT_BROADCAST_EXP: + PM8001_MSG_DBG(pm8001_ha, +@@ -3882,7 +3885,8 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); + sas_phy->sas_prim = HW_EVENT_BROADCAST_EXP; + spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); +- sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); ++ sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, ++ GFP_ATOMIC); + break; + case HW_EVENT_LINK_ERR_INVALID_DWORD: + PM8001_MSG_DBG(pm8001_ha, +@@ -3891,7 +3895,8 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + HW_EVENT_LINK_ERR_INVALID_DWORD, port_id, phy_id, 0, 0); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); ++ sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ GFP_ATOMIC); + break; + case HW_EVENT_LINK_ERR_DISPARITY_ERROR: + PM8001_MSG_DBG(pm8001_ha, +@@ -3901,7 +3906,8 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + port_id, phy_id, 0, 0); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); ++ sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ GFP_ATOMIC); + break; + case HW_EVENT_LINK_ERR_CODE_VIOLATION: + PM8001_MSG_DBG(pm8001_ha, +@@ -3911,7 +3917,8 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + port_id, phy_id, 0, 0); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); ++ sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ GFP_ATOMIC); + break; + case HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH: + PM8001_MSG_DBG(pm8001_ha, +@@ -3921,7 +3928,8 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + port_id, phy_id, 0, 0); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); ++ sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ GFP_ATOMIC); + break; + case HW_EVENT_MALFUNCTION: + PM8001_MSG_DBG(pm8001_ha, +@@ -3933,7 +3941,8 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); + sas_phy->sas_prim = HW_EVENT_BROADCAST_SES; + spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); +- sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); ++ sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, ++ GFP_ATOMIC); + break; + case HW_EVENT_INBOUND_CRC_ERROR: + PM8001_MSG_DBG(pm8001_ha, +@@ -3945,14 +3954,16 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + case HW_EVENT_HARD_RESET_RECEIVED: + PM8001_MSG_DBG(pm8001_ha, + pm8001_printk("HW_EVENT_HARD_RESET_RECEIVED\n")); +- sas_ha->notify_port_event(sas_phy, PORTE_HARD_RESET); ++ sas_notify_port_event_gfp(sas_phy, PORTE_HARD_RESET, ++ GFP_ATOMIC); + break; + case HW_EVENT_ID_FRAME_TIMEOUT: + PM8001_MSG_DBG(pm8001_ha, + pm8001_printk("HW_EVENT_ID_FRAME_TIMEOUT\n")); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); ++ sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ GFP_ATOMIC); + break; + case HW_EVENT_LINK_ERR_PHY_RESET_FAILED: + PM8001_MSG_DBG(pm8001_ha, +@@ -3962,21 +3973,24 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + port_id, phy_id, 0, 0); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); ++ sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ GFP_ATOMIC); + break; + case HW_EVENT_PORT_RESET_TIMER_TMO: + PM8001_MSG_DBG(pm8001_ha, + pm8001_printk("HW_EVENT_PORT_RESET_TIMER_TMO\n")); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); ++ sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ GFP_ATOMIC); + break; + case HW_EVENT_PORT_RECOVERY_TIMER_TMO: + PM8001_MSG_DBG(pm8001_ha, + pm8001_printk("HW_EVENT_PORT_RECOVERY_TIMER_TMO\n")); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); ++ sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ GFP_ATOMIC); + break; + case HW_EVENT_PORT_RECOVER: + PM8001_MSG_DBG(pm8001_ha, +diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c +index 8627feb80261..67109070451d 100644 +--- a/drivers/scsi/pm8001/pm80xx_hwi.c ++++ b/drivers/scsi/pm8001/pm80xx_hwi.c +@@ -2929,7 +2929,6 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) + u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F); + + struct pm8001_port *port = &pm8001_ha->port[port_id]; +- struct sas_ha_struct *sas_ha = pm8001_ha->sas; + struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; + unsigned long flags; + u8 deviceType = pPayload->sas_identify.dev_type; +@@ -2978,7 +2977,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) + else if (phy->identify.device_type != SAS_PHY_UNUSED) + phy->identify.target_port_protocols = SAS_PROTOCOL_SMP; + phy->sas_phy.oob_mode = SAS_OOB_MODE; +- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE); ++ sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_OOB_DONE, GFP_ATOMIC); + spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags); + memcpy(phy->frame_rcvd, &pPayload->sas_identify, + sizeof(struct sas_identify_frame)-4); +@@ -3012,7 +3011,6 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) + u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F); + + struct pm8001_port *port = &pm8001_ha->port[port_id]; +- struct sas_ha_struct *sas_ha = pm8001_ha->sas; + struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; + unsigned long flags; + PM8001_MSG_DBG(pm8001_ha, pm8001_printk( +@@ -3026,7 +3024,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) + phy->phy_type |= PORT_TYPE_SATA; + phy->phy_attached = 1; + phy->sas_phy.oob_mode = SATA_OOB_MODE; +- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE); ++ sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_OOB_DONE, GFP_ATOMIC); + spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags); + memcpy(phy->frame_rcvd, ((u8 *)&pPayload->sata_fis - 4), + sizeof(struct dev_to_host_fis)); +@@ -3110,9 +3108,8 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb) + + } + if (port_sata && (portstate != PORT_IN_RESET)) { +- struct sas_ha_struct *sas_ha = pm8001_ha->sas; +- +- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL); ++ sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL, ++ GFP_ATOMIC); + } + } + +@@ -3211,7 +3208,8 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + case HW_EVENT_SATA_SPINUP_HOLD: + PM8001_MSG_DBG(pm8001_ha, + pm8001_printk("HW_EVENT_SATA_SPINUP_HOLD\n")); +- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD); ++ sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_SPINUP_HOLD, ++ GFP_ATOMIC); + break; + case HW_EVENT_PHY_DOWN: + PM8001_MSG_DBG(pm8001_ha, +@@ -3230,7 +3228,8 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + pm8001_printk("HW_EVENT_PORT_INVALID\n")); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); ++ sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ GFP_ATOMIC); + break; + /* the broadcast change primitive received, tell the LIBSAS this event + to revalidate the sas domain*/ +@@ -3242,14 +3241,16 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); + sas_phy->sas_prim = HW_EVENT_BROADCAST_CHANGE; + spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); +- sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); ++ sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, ++ GFP_ATOMIC); + break; + case HW_EVENT_PHY_ERROR: + PM8001_MSG_DBG(pm8001_ha, + pm8001_printk("HW_EVENT_PHY_ERROR\n")); + sas_phy_disconnected(&phy->sas_phy); + phy->phy_attached = 0; +- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR); ++ sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_OOB_ERROR, ++ GFP_ATOMIC); + break; + case HW_EVENT_BROADCAST_EXP: + PM8001_MSG_DBG(pm8001_ha, +@@ -3257,7 +3258,8 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); + sas_phy->sas_prim = HW_EVENT_BROADCAST_EXP; + spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); +- sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); ++ sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, ++ GFP_ATOMIC); + break; + case HW_EVENT_LINK_ERR_INVALID_DWORD: + PM8001_MSG_DBG(pm8001_ha, +@@ -3296,7 +3298,8 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); + sas_phy->sas_prim = HW_EVENT_BROADCAST_SES; + spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); +- sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); ++ sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, ++ GFP_ATOMIC); + break; + case HW_EVENT_INBOUND_CRC_ERROR: + PM8001_MSG_DBG(pm8001_ha, +@@ -3308,14 +3311,16 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + case HW_EVENT_HARD_RESET_RECEIVED: + PM8001_MSG_DBG(pm8001_ha, + pm8001_printk("HW_EVENT_HARD_RESET_RECEIVED\n")); +- sas_ha->notify_port_event(sas_phy, PORTE_HARD_RESET); ++ sas_notify_port_event_gfp(sas_phy, PORTE_HARD_RESET, ++ GFP_ATOMIC); + break; + case HW_EVENT_ID_FRAME_TIMEOUT: + PM8001_MSG_DBG(pm8001_ha, + pm8001_printk("HW_EVENT_ID_FRAME_TIMEOUT\n")); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); ++ sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ GFP_ATOMIC); + break; + case HW_EVENT_LINK_ERR_PHY_RESET_FAILED: + PM8001_MSG_DBG(pm8001_ha, +@@ -3325,7 +3330,8 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + port_id, phy_id, 0, 0); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); ++ sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ GFP_ATOMIC); + break; + case HW_EVENT_PORT_RESET_TIMER_TMO: + PM8001_MSG_DBG(pm8001_ha, +@@ -3334,7 +3340,8 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + port_id, phy_id, 0, 0); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); ++ sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ GFP_ATOMIC); + if (pm8001_ha->phy[phy_id].reset_completion) { + pm8001_ha->phy[phy_id].port_reset_status = + PORT_RESET_TMO; +@@ -3351,8 +3358,8 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + for (i = 0; i < pm8001_ha->chip->n_phy; i++) { + if (port->wide_port_phymap & (1 << i)) { + phy = &pm8001_ha->phy[i]; +- sas_ha->notify_phy_event(&phy->sas_phy, +- PHYE_LOSS_OF_SIGNAL); ++ sas_notify_phy_event_gfp(&phy->sas_phy, ++ PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC); + port->wide_port_phymap &= ~(1 << i); + } + } +-- +2.27.0 + diff --git a/patches/0473-scsi-aic94xx-Pass-gfp_t-flags-to-libsas-event-notifi.patch b/patches/0473-scsi-aic94xx-Pass-gfp_t-flags-to-libsas-event-notifi.patch new file mode 100644 index 00000000..59b23968 --- /dev/null +++ b/patches/0473-scsi-aic94xx-Pass-gfp_t-flags-to-libsas-event-notifi.patch @@ -0,0 +1,155 @@ +From eb0dcb1ba829f6113c8dbdf8ad48df1fd777111a Mon Sep 17 00:00:00 2001 +From: "Ahmed S. Darwish" +Date: Tue, 3 Aug 2021 14:47:38 +0800 +Subject: [PATCH 155/256] scsi: aic94xx: Pass gfp_t flags to libsas event + notifiers + +mainline inclusion +from mainline-v5.12-rc1 +commit 111d06ab77c9f45fc4b8fc8be918b45154dafd44 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=111d06ab77c9f45fc4b8fc8be918b45154dafd44 + +---------------------------------------------------------------------- + +Use the new libsas event notifiers API, which requires callers to +explicitly pass the gfp_t memory allocation flags. + +Context analysis: + + aic94xx_hwi.c: asd_dl_tasklet_handler() + -> asd_ascb::tasklet_complete() + == escb_tasklet_complete() + -> aic94xx_scb.c: asd_phy_event_tasklet() + -> aic94xx_scb.c: asd_bytes_dmaed_tasklet() + -> aic94xx_scb.c: asd_link_reset_err_tasklet() + -> aic94xx_scb.c: asd_primitive_rcvd_tasklet() + +All functions are invoked by escb_tasklet_complete(), which is invoked by +the tasklet handler. Pass GFP_ATOMIC. + +Link: https://lore.kernel.org/r/20210118100955.1761652-11-a.darwish@linutronix.de +Reviewed-by: John Garry +Signed-off-by: Ahmed S. Darwish +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/aic94xx/aic94xx_scb.c +--- + drivers/scsi/aic94xx/aic94xx_scb.c | 27 ++++++++++++++++----------- + 1 file changed, 16 insertions(+), 11 deletions(-) + +diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c +index 22873ce8bbfa..eac4aa9afb57 100644 +--- a/drivers/scsi/aic94xx/aic94xx_scb.c ++++ b/drivers/scsi/aic94xx/aic94xx_scb.c +@@ -86,7 +86,6 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb, + struct done_list_struct *dl) + { + struct asd_ha_struct *asd_ha = ascb->ha; +- struct sas_ha_struct *sas_ha = &asd_ha->sas_ha; + int phy_id = dl->status_block[0] & DL_PHY_MASK; + struct asd_phy *phy = &asd_ha->phys[phy_id]; + +@@ -99,7 +98,8 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb, + ASD_DPRINTK("phy%d: device unplugged\n", phy_id); + asd_turn_led(asd_ha, phy_id, 0); + sas_phy_disconnected(&phy->sas_phy); +- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL); ++ sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL, ++ GFP_ATOMIC); + break; + case CURRENT_OOB_DONE: + /* hot plugged device */ +@@ -107,12 +107,14 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb, + get_lrate_mode(phy, oob_mode); + ASD_DPRINTK("phy%d device plugged: lrate:0x%x, proto:0x%x\n", + phy_id, phy->sas_phy.linkrate, phy->sas_phy.iproto); +- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE); ++ sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_OOB_DONE, ++ GFP_ATOMIC); + break; + case CURRENT_SPINUP_HOLD: + /* hot plug SATA, no COMWAKE sent */ + asd_turn_led(asd_ha, phy_id, 1); +- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD); ++ sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_SPINUP_HOLD, ++ GFP_ATOMIC); + break; + case CURRENT_GTO_TIMEOUT: + case CURRENT_OOB_ERROR: +@@ -120,7 +122,8 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb, + dl->status_block[1]); + asd_turn_led(asd_ha, phy_id, 0); + sas_phy_disconnected(&phy->sas_phy); +- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR); ++ sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_OOB_ERROR, ++ GFP_ATOMIC); + break; + } + } +@@ -240,7 +243,6 @@ static void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb, + int edb_el = edb_id + ascb->edb_index; + struct asd_dma_tok *edb = ascb->ha->seq.edb_arr[edb_el]; + struct asd_phy *phy = &ascb->ha->phys[phy_id]; +- struct sas_ha_struct *sas_ha = phy->sas_phy.ha; + u16 size = ((dl->status_block[3] & 7) << 8) | dl->status_block[2]; + + size = min(size, (u16) sizeof(phy->frame_rcvd)); +@@ -252,7 +254,7 @@ static void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb, + spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags); + asd_dump_frame_rcvd(phy, dl); + asd_form_port(ascb->ha, phy); +- sas_ha->notify_port_event(&phy->sas_phy, PORTE_BYTES_DMAED); ++ sas_notify_port_event_gfp(&phy->sas_phy, PORTE_BYTES_DMAED, GFP_ATOMIC); + } + + static void asd_link_reset_err_tasklet(struct asd_ascb *ascb, +@@ -288,7 +290,7 @@ static void asd_link_reset_err_tasklet(struct asd_ascb *ascb, + asd_turn_led(asd_ha, phy_id, 0); + sas_phy_disconnected(sas_phy); + asd_deform_port(asd_ha, phy); +- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); ++ sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, GFP_ATOMIC); + + if (retries_left == 0) { + int num = 1; +@@ -333,7 +335,8 @@ static void asd_primitive_rcvd_tasklet(struct asd_ascb *ascb, + spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); + sas_phy->sas_prim = ffs(cont); + spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); +- sas_ha->notify_port_event(sas_phy,PORTE_BROADCAST_RCVD); ++ sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, ++ GFP_ATOMIC); + break; + + case LmUNKNOWNP: +@@ -354,7 +357,8 @@ static void asd_primitive_rcvd_tasklet(struct asd_ascb *ascb, + /* The sequencer disables all phys on that port. + * We have to re-enable the phys ourselves. */ + asd_deform_port(asd_ha, phy); +- sas_ha->notify_port_event(sas_phy, PORTE_HARD_RESET); ++ sas_notify_port_event_gfp(sas_phy, PORTE_HARD_RESET, ++ GFP_ATOMIC); + break; + + default: +@@ -585,7 +589,8 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, + /* the device is gone */ + sas_phy_disconnected(sas_phy); + asd_deform_port(asd_ha, phy); +- sas_ha->notify_port_event(sas_phy, PORTE_TIMER_EVENT); ++ sas_notify_port_event_gfp(sas_phy, PORTE_TIMER_EVENT, ++ GFP_ATOMIC); + break; + default: + ASD_DPRINTK("%s: phy%d: unknown event:0x%x\n", __func__, +-- +2.27.0 + diff --git a/patches/0474-scsi-hisi_sas-Pass-gfp_t-flags-to-libsas-event-notif.patch b/patches/0474-scsi-hisi_sas-Pass-gfp_t-flags-to-libsas-event-notif.patch new file mode 100644 index 00000000..a86d029d --- /dev/null +++ b/patches/0474-scsi-hisi_sas-Pass-gfp_t-flags-to-libsas-event-notif.patch @@ -0,0 +1,299 @@ +From cd266a7e447a9a7d45172c6520651b9345c83a2e Mon Sep 17 00:00:00 2001 +From: "Ahmed S. Darwish" +Date: Tue, 3 Aug 2021 14:47:39 +0800 +Subject: [PATCH 156/256] scsi: hisi_sas: Pass gfp_t flags to libsas event + notifiers + +mainline inclusion +from mainline-v5.12-rc1 +commit 26c7efc3f95260fd90e6cb268b47a58cf27ffc64 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=26c7efc3f95260fd90e6cb268b47a58cf27ffc64 + +---------------------------------------------------------------------- + +Use the new libsas event notifiers API, which requires callers to +explicitly pass the gfp_t memory allocation flags. + +Below are the context analysis for modified functions: + +=> hisi_sas_bytes_dmaed(): + +Since it is invoked from both process and atomic contexts, let its callers +pass the gfp_t flags: + + * hisi_sas_main.c: + ------------------ + + hisi_sas_phyup_work(): workqueue context + -> hisi_sas_bytes_dmaed(..., GFP_KERNEL) + + hisi_sas_controller_reset_done(): has an msleep() + -> hisi_sas_rescan_topology() + -> hisi_sas_phy_down() + -> hisi_sas_bytes_dmaed(..., GFP_KERNEL) + + hisi_sas_debug_I_T_nexus_reset(): calls wait_for_completion_timeout() + -> hisi_sas_phy_down() + -> hisi_sas_bytes_dmaed(..., GFP_KERNEL) + + * hisi_sas_v1_hw.c: + ------------------- + + int_abnormal_v1_hw(): irq handler + -> hisi_sas_phy_down() + -> hisi_sas_bytes_dmaed(..., GFP_ATOMIC) + + * hisi_sas_v[23]_hw.c: + ---------------------- + + int_phy_updown_v[23]_hw(): irq handler + -> phy_down_v[23]_hw() + -> hisi_sas_phy_down() + -> hisi_sas_bytes_dmaed(..., GFP_ATOMIC) + +=> int_bcast_v1_hw() and phy_bcast_v3_hw(): + +Both are invoked exclusively from irq handlers. Pass GFP_ATOMIC. + +Link: https://lore.kernel.org/r/20210118100955.1761652-12-a.darwish@linutronix.de +Reviewed-by: John Garry +Signed-off-by: Ahmed S. Darwish +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c + drivers/scsi/hisi_sas/hisi_sas_v1_hw.c + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 3 ++- + drivers/scsi/hisi_sas/hisi_sas_main.c | 30 +++++++++++++------------- + drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 7 +++--- + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 7 +++--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 7 +++--- + 5 files changed, 29 insertions(+), 25 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 48cde1d897d4..8a30c2ee5996 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -674,7 +674,8 @@ extern void hisi_sas_scan_start(struct Scsi_Host *shost); + extern int hisi_sas_host_reset(struct Scsi_Host *shost, int reset_type); + extern void hisi_sas_phy_enable(struct hisi_hba *hisi_hba, int phy_no, + int enable); +-extern void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy); ++extern void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy, ++ gfp_t gfp_flags); + extern void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, + struct sas_task *task, + struct hisi_sas_slot *slot, +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index f7bc6d4ddc20..5a4eb8eec036 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -628,17 +628,16 @@ static int hisi_sas_task_exec(struct sas_task *task, gfp_t gfp_flags, + return rc; + } + +-static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, int phy_no) ++static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, int phy_no, ++ gfp_t gfp_flags) + { + struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; + struct asd_sas_phy *sas_phy = &phy->sas_phy; +- struct sas_ha_struct *sas_ha; + + if (!phy->phy_attached) + return; + +- sas_ha = &hisi_hba->sha; +- sas_ha->notify_phy_event(sas_phy, PHYE_OOB_DONE); ++ sas_notify_phy_event_gfp(sas_phy, PHYE_OOB_DONE, gfp_flags); + + if (sas_phy->phy) { + struct sas_phy *sphy = sas_phy->phy; +@@ -666,7 +665,7 @@ static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, int phy_no) + } + + sas_phy->frame_rcvd_size = phy->frame_rcvd_size; +- sas_ha->notify_port_event(sas_phy, PORTE_BYTES_DMAED); ++ sas_notify_port_event_gfp(sas_phy, PORTE_BYTES_DMAED, gfp_flags); + } + + static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device) +@@ -881,7 +880,7 @@ static void hisi_sas_phyup_work(struct work_struct *work) + + if (phy->identify.target_port_protocols == SAS_PROTOCOL_SSP) + hisi_hba->hw->sl_notify_ssp(hisi_hba, phy_no); +- hisi_sas_bytes_dmaed(hisi_hba, phy_no); ++ hisi_sas_bytes_dmaed(hisi_hba, phy_no, GFP_KERNEL); + } + + static void hisi_sas_linkreset_work(struct work_struct *work) +@@ -1452,7 +1451,6 @@ static void hisi_sas_refresh_port_id(struct hisi_hba *hisi_hba) + + static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state) + { +- struct sas_ha_struct *sas_ha = &hisi_hba->sha; + struct asd_sas_port *_sas_port = NULL; + int phy_no; + +@@ -1473,11 +1471,12 @@ static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state) + _sas_port = sas_port; + + if (DEV_IS_EXPANDER(dev->dev_type)) +- sas_ha->notify_port_event(sas_phy, +- PORTE_BROADCAST_RCVD); ++ sas_notify_port_event_gfp(sas_phy, ++ PORTE_BROADCAST_RCVD, ++ GFP_KERNEL); + } + } else { +- hisi_sas_phy_down(hisi_hba, phy_no, 0); ++ hisi_sas_phy_down(hisi_hba, phy_no, 0, GFP_KERNEL); + } + } + } +@@ -1858,7 +1857,7 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device) + /* report PHY down if timed out */ + if (!ret) { + dev_warn(dev, "phy%d reset timeout\n", sas_phy->id); +- hisi_sas_phy_down(hisi_hba, sas_phy->id, 0); ++ hisi_sas_phy_down(hisi_hba, sas_phy->id, 0, GFP_KERNEL); + } + } else if (sas_dev->dev_status != HISI_SAS_DEV_INIT) + /* Sleep 2s, wait for I_T reset at expander env except fail */ +@@ -2268,16 +2267,16 @@ static void hisi_sas_phy_disconnected(struct hisi_sas_phy *phy) + spin_unlock_irqrestore(&phy->lock, flags); + } + +-void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy) ++void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy, ++ gfp_t gfp_flags) + { + struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; + struct asd_sas_phy *sas_phy = &phy->sas_phy; +- struct sas_ha_struct *sas_ha = &hisi_hba->sha; + struct device *dev = hisi_hba->dev; + + if (rdy) { + /* Phy down but ready */ +- hisi_sas_bytes_dmaed(hisi_hba, phy_no); ++ hisi_sas_bytes_dmaed(hisi_hba, phy_no, gfp_flags); + hisi_sas_port_notify_formed(sas_phy); + } else { + struct hisi_sas_port *port = phy->port; +@@ -2288,7 +2287,8 @@ void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy) + return; + } + /* Phy down and not ready */ +- sas_ha->notify_phy_event(sas_phy, PHYE_LOSS_OF_SIGNAL); ++ sas_notify_phy_event_gfp(sas_phy, ++ PHYE_LOSS_OF_SIGNAL, gfp_flags); + sas_phy_disconnected(sas_phy); + + if (port) { +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +index c82abcf2567c..0e2e1397c6b8 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +@@ -1412,7 +1412,6 @@ static irqreturn_t int_bcast_v1_hw(int irq, void *p) + struct hisi_sas_phy *phy = p; + struct hisi_hba *hisi_hba = phy->hisi_hba; + struct asd_sas_phy *sas_phy = &phy->sas_phy; +- struct sas_ha_struct *sha = &hisi_hba->sha; + struct device *dev = hisi_hba->dev; + int phy_no = sas_phy->id; + u32 irq_value; +@@ -1428,7 +1427,8 @@ static irqreturn_t int_bcast_v1_hw(int irq, void *p) + } + + if (!test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) +- sha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); ++ sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, ++ GFP_ATOMIC); + + end: + hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2, +@@ -1457,7 +1457,8 @@ static irqreturn_t int_abnormal_v1_hw(int irq, void *p) + u32 phy_state = hisi_sas_read32(hisi_hba, PHY_STATE); + + hisi_sas_phy_down(hisi_hba, phy_no, +- (phy_state & 1 << phy_no) ? 1 : 0); ++ (phy_state & 1 << phy_no) ? 1 : 0, ++ GFP_ATOMIC); + } + + if (irq_value & CHL_INT0_ID_TIMEOUT_MSK) +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +index 81ff9b76c344..d2c9186749ae 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -2755,7 +2755,8 @@ static int phy_down_v2_hw(int phy_no, struct hisi_hba *hisi_hba) + + phy_state = hisi_sas_read32(hisi_hba, PHY_STATE); + dev_info(dev, "phydown: phy%d phy_state=0x%x\n", phy_no, phy_state); +- hisi_sas_phy_down(hisi_hba, phy_no, (phy_state & 1 << phy_no) ? 1 : 0); ++ hisi_sas_phy_down(hisi_hba, phy_no, (phy_state & 1 << phy_no) ? 1 : 0, ++ GFP_ATOMIC); + + sl_ctrl = hisi_sas_phy_read32(hisi_hba, phy_no, SL_CONTROL); + hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, +@@ -2839,14 +2840,14 @@ static void phy_bcast_v2_hw(int phy_no, struct hisi_hba *hisi_hba) + { + struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; + struct asd_sas_phy *sas_phy = &phy->sas_phy; +- struct sas_ha_struct *sas_ha = &hisi_hba->sha; + u32 bcast_status; + + hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 1); + bcast_status = hisi_sas_phy_read32(hisi_hba, phy_no, RX_PRIMS_STATUS); + if ((bcast_status & RX_BCAST_CHG_MSK) && + !test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) +- sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); ++ sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, ++ GFP_ATOMIC); + hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, + CHL_INT0_SL_RX_BCST_ACK_MSK); + hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 0); +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index bf4fe277289c..b06d38cb9e41 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -1729,7 +1729,8 @@ static irqreturn_t phy_down_v3_hw(int phy_no, struct hisi_hba *hisi_hba) + + phy_state = hisi_sas_read32(hisi_hba, PHY_STATE); + dev_info(dev, "phydown: phy%d phy_state=0x%x\n", phy_no, phy_state); +- hisi_sas_phy_down(hisi_hba, phy_no, (phy_state & 1 << phy_no) ? 1 : 0); ++ hisi_sas_phy_down(hisi_hba, phy_no, (phy_state & 1 << phy_no) ? 1 : 0, ++ GFP_ATOMIC); + + sl_ctrl = hisi_sas_phy_read32(hisi_hba, phy_no, SL_CONTROL); + hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, +@@ -1749,14 +1750,14 @@ static irqreturn_t phy_bcast_v3_hw(int phy_no, struct hisi_hba *hisi_hba) + { + struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; + struct asd_sas_phy *sas_phy = &phy->sas_phy; +- struct sas_ha_struct *sas_ha = &hisi_hba->sha; + u32 bcast_status; + + hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 1); + bcast_status = hisi_sas_phy_read32(hisi_hba, phy_no, RX_PRIMS_STATUS); + if ((bcast_status & RX_BCAST_CHG_MSK) && + !test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) +- sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); ++ sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, ++ GFP_ATOMIC); + hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, + CHL_INT0_SL_RX_BCST_ACK_MSK); + hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 0); +-- +2.27.0 + diff --git a/patches/0475-scsi-libsas-Add-gfp_t-flags-parameter-to-event-notif.patch b/patches/0475-scsi-libsas-Add-gfp_t-flags-parameter-to-event-notif.patch new file mode 100644 index 00000000..89408655 --- /dev/null +++ b/patches/0475-scsi-libsas-Add-gfp_t-flags-parameter-to-event-notif.patch @@ -0,0 +1,288 @@ +From 49326b6fc45da1e543fb275ef8808256d73a7bab Mon Sep 17 00:00:00 2001 +From: "Ahmed S. Darwish" +Date: Tue, 3 Aug 2021 14:47:40 +0800 +Subject: [PATCH 157/256] scsi: libsas: Add gfp_t flags parameter to event + notifications + +mainline inclusion +from mainline-v5.12-rc1 +commit 5d6a75a1edf63ff243d937253ced62d8edea30b5 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5d6a75a1edf63ff243d937253ced62d8edea30b5 + +---------------------------------------------------------------------- + +All call-sites of below libsas APIs: + + - sas_alloc_event() + - sas_notify_port_event() + - sas_notify_phy_event() + +have been converted to use the _gfp()-suffixed version. Modify the +original APIs above to take a gfp_t flags parameter by default. + +For bisectability, call-sites will be modified again to use the original +libsas APIs (while passing gfp_t). The temporary _gfp()-suffixed versions +can then be removed. + +Link: https://lore.kernel.org/r/20210118100955.1761652-13-a.darwish@linutronix.de +Cc: Jason Yan +Reviewed-by: John Garry +Signed-off-by: Ahmed S. Darwish +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + Documentation/scsi/libsas.rst +--- + Documentation/scsi/libsas.txt | 4 +- + drivers/scsi/libsas/sas_event.c | 62 +++++++++--------------------- + drivers/scsi/libsas/sas_expander.c | 4 +- + drivers/scsi/libsas/sas_init.c | 12 ++---- + drivers/scsi/libsas/sas_internal.h | 5 ++- + include/scsi/libsas.h | 12 ++++-- + 6 files changed, 37 insertions(+), 62 deletions(-) + +diff --git a/Documentation/scsi/libsas.txt b/Documentation/scsi/libsas.txt +index 5c28e4727f2c..56a26b31fa6d 100644 +--- a/Documentation/scsi/libsas.txt ++++ b/Documentation/scsi/libsas.txt +@@ -154,8 +154,8 @@ The event interface: + + /* LLDD calls these to notify the class of an event. */ + void (*notify_ha_event)(struct sas_ha_struct *, enum ha_event); +- void (*notify_port_event)(struct sas_phy *, enum port_event); +- void (*notify_phy_event)(struct sas_phy *, enum phy_event); ++ void sas_notify_port_event(struct sas_phy *, enum port_event, gfp_t); ++ void sas_notify_phy_event(struct sas_phy *, enum phy_event, gfp_t); + void sas_notify_port_event_gfp(struct sas_phy *, enum port_event, gfp_t); + void sas_notify_phy_event_gfp(struct sas_phy *, enum phy_event, gfp_t); + +diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c +index 4bd200cc294b..06b0105be611 100644 +--- a/drivers/scsi/libsas/sas_event.c ++++ b/drivers/scsi/libsas/sas_event.c +@@ -149,15 +149,19 @@ static void sas_phy_event_worker(struct work_struct *work) + sas_free_event(ev); + } + +-static int __sas_notify_port_event(struct asd_sas_phy *phy, +- enum port_event event, +- struct asd_sas_event *ev) ++int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event, ++ gfp_t gfp_flags) + { + struct sas_ha_struct *ha = phy->ha; ++ struct asd_sas_event *ev; + int ret; + + BUG_ON(event >= PORT_NUM_EVENTS); + ++ ev = sas_alloc_event_gfp(phy, gfp_flags); ++ if (!ev) ++ return -ENOMEM; ++ + INIT_SAS_EVENT(ev, sas_port_event_worker, phy, event); + + ret = sas_queue_event(event, &ev->work, ha); +@@ -166,41 +170,28 @@ static int __sas_notify_port_event(struct asd_sas_phy *phy, + + return ret; + } ++EXPORT_SYMBOL_GPL(sas_notify_port_event); + + int sas_notify_port_event_gfp(struct asd_sas_phy *phy, enum port_event event, + gfp_t gfp_flags) + { +- struct asd_sas_event *ev; +- +- ev = sas_alloc_event_gfp(phy, gfp_flags); +- if (!ev) +- return -ENOMEM; +- +- return __sas_notify_port_event(phy, event, ev); ++ return sas_notify_port_event(phy, event, gfp_flags); + } + EXPORT_SYMBOL_GPL(sas_notify_port_event_gfp); + +-int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event) +-{ +- struct asd_sas_event *ev; +- +- ev = sas_alloc_event(phy); +- if (!ev) +- return -ENOMEM; +- +- return __sas_notify_port_event(phy, event, ev); +-} +-EXPORT_SYMBOL_GPL(sas_notify_port_event); +- +-static inline int __sas_notify_phy_event(struct asd_sas_phy *phy, +- enum phy_event event, +- struct asd_sas_event *ev) ++int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event, ++ gfp_t gfp_flags) + { + struct sas_ha_struct *ha = phy->ha; ++ struct asd_sas_event *ev; + int ret; + + BUG_ON(event >= PHY_NUM_EVENTS); + ++ ev = sas_alloc_event_gfp(phy, gfp_flags); ++ if (!ev) ++ return -ENOMEM; ++ + INIT_SAS_EVENT(ev, sas_phy_event_worker, phy, event); + + ret = sas_queue_event(event, &ev->work, ha); +@@ -209,6 +200,7 @@ static inline int __sas_notify_phy_event(struct asd_sas_phy *phy, + + return ret; + } ++EXPORT_SYMBOL_GPL(sas_notify_phy_event); + + int sas_init_events(struct sas_ha_struct *sas_ha) + { +@@ -221,24 +213,6 @@ int sas_init_events(struct sas_ha_struct *sas_ha) + int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event, + gfp_t gfp_flags) + { +- struct asd_sas_event *ev; +- +- ev = sas_alloc_event_gfp(phy, gfp_flags); +- if (!ev) +- return -ENOMEM; +- +- return __sas_notify_phy_event(phy, event, ev); ++ return sas_notify_phy_event(phy, event, gfp_flags); + } + EXPORT_SYMBOL_GPL(sas_notify_phy_event_gfp); +- +-int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event) +-{ +- struct asd_sas_event *ev; +- +- ev = sas_alloc_event(phy); +- if (!ev) +- return -ENOMEM; +- +- return __sas_notify_phy_event(phy, event, ev); +-} +-EXPORT_SYMBOL_GPL(sas_notify_phy_event); +diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c +index 911d0e1e8e3f..799eb400a174 100644 +--- a/drivers/scsi/libsas/sas_expander.c ++++ b/drivers/scsi/libsas/sas_expander.c +@@ -2273,7 +2273,6 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev) + * go again to pick up on any new devices on a separate pass + */ + if (unregistered > 0) { +- struct asd_sas_port *port = dev->port; + struct asd_sas_phy *sas_phy; + struct ex_phy *phy; + +@@ -2288,7 +2287,8 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev) + sas_phy = container_of(dev->port->phy_list.next, + struct asd_sas_phy, + port_phy_el); +- port->ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); ++ sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD, ++ in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); + + return 0; + } +diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c +index 556f29233872..239cf00a7bf7 100644 +--- a/drivers/scsi/libsas/sas_init.c ++++ b/drivers/scsi/libsas/sas_init.c +@@ -608,8 +608,8 @@ sas_domain_attach_transport(struct sas_domain_function_template *dft) + } + EXPORT_SYMBOL_GPL(sas_domain_attach_transport); + +-static struct asd_sas_event *__sas_alloc_event(struct asd_sas_phy *phy, +- gfp_t gfp_flags) ++struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy, ++ gfp_t gfp_flags) + { + struct asd_sas_event *event; + struct sas_ha_struct *sas_ha = phy->ha; +@@ -642,15 +642,11 @@ static struct asd_sas_event *__sas_alloc_event(struct asd_sas_phy *phy, + return event; + } + +-struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy) +-{ +- return __sas_alloc_event(phy, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); +-} +- + struct asd_sas_event *sas_alloc_event_gfp(struct asd_sas_phy *phy, + gfp_t gfp_flags) + { +- return __sas_alloc_event(phy, gfp_flags); ++ ++ return sas_alloc_event(phy, gfp_flags); + } + + void sas_free_event(struct asd_sas_event *event) +diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h +index 5ccaab295b09..2fae32a9156b 100644 +--- a/drivers/scsi/libsas/sas_internal.h ++++ b/drivers/scsi/libsas/sas_internal.h +@@ -61,7 +61,7 @@ int sas_show_oob_mode(enum sas_oob_mode oob_mode, char *buf); + int sas_register_phys(struct sas_ha_struct *sas_ha); + void sas_unregister_phys(struct sas_ha_struct *sas_ha); + +-struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy); ++struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy, gfp_t gfp_flags); + struct asd_sas_event *sas_alloc_event_gfp(struct asd_sas_phy *phy, + gfp_t gfp_flags); + void sas_free_event(struct asd_sas_event *event); +@@ -92,7 +92,8 @@ int sas_smp_phy_control(struct domain_device *dev, int phy_id, + enum phy_func phy_func, struct sas_phy_linkrates *); + int sas_smp_get_phy_events(struct sas_phy *phy); + +-int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event); ++int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event, ++ gfp_t flags); + int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event, + gfp_t flags); + void sas_device_set_phy(struct domain_device *dev, struct sas_port *port); +diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h +index 5b82e023bc90..3978717229bf 100644 +--- a/include/scsi/libsas.h ++++ b/include/scsi/libsas.h +@@ -404,8 +404,10 @@ struct sas_ha_struct { + * their siblings when forming wide ports */ + + /* LLDD calls these to notify the class of an event. */ +- int (*notify_port_event)(struct asd_sas_phy *, enum port_event); +- int (*notify_phy_event)(struct asd_sas_phy *, enum phy_event); ++ int (*notify_port_event)(struct asd_sas_phy *, enum port_event, ++ gfp_t gfp_flags); ++ int (*notify_phy_event)(struct asd_sas_phy *, enum phy_event, ++ gfp_t gfp_flags); + + void *lldd_ha; /* not touched by sas class code */ + +@@ -723,8 +725,10 @@ struct sas_phy *sas_get_local_phy(struct domain_device *dev); + + int sas_request_addr(struct Scsi_Host *shost, u8 *addr); + +-int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event); +-int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event); ++int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event, ++ gfp_t gfp_flags); ++int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event, ++ gfp_t gfp_flags); + int sas_notify_port_event_gfp(struct asd_sas_phy *phy, enum port_event event, + gfp_t gfp_flags); + int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event, +-- +2.27.0 + diff --git a/patches/0476-fix-kabi-broken-due-to-change-of-struct-sas_ha_struc.patch b/patches/0476-fix-kabi-broken-due-to-change-of-struct-sas_ha_struc.patch new file mode 100644 index 00000000..079ecaf6 --- /dev/null +++ b/patches/0476-fix-kabi-broken-due-to-change-of-struct-sas_ha_struc.patch @@ -0,0 +1,44 @@ +From 71c46f2c17503da291d5fbcf028246e43bb2570d Mon Sep 17 00:00:00 2001 +From: Algernon +Date: Tue, 20 Jun 2023 11:51:12 +0800 +Subject: [PATCH 158/256] fix kabi broken due to change of struct sas_ha_struct + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +---------------------------------------------------------------------------- + +Commit ("scsi: libsas: Add gfp_t flags parameter +to event notifications") changes some struct sas_ha_struct, so +we need to fix kabi broken problem. + +Signed-off-by: YunYi Yang +--- + include/scsi/libsas.h | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h +index 3978717229bf..7db79ca4037f 100644 +--- a/include/scsi/libsas.h ++++ b/include/scsi/libsas.h +@@ -404,11 +404,15 @@ struct sas_ha_struct { + * their siblings when forming wide ports */ + + /* LLDD calls these to notify the class of an event. */ ++#ifndef __GENKSYMS__ + int (*notify_port_event)(struct asd_sas_phy *, enum port_event, + gfp_t gfp_flags); + int (*notify_phy_event)(struct asd_sas_phy *, enum phy_event, + gfp_t gfp_flags); +- ++#else ++ int (*notify_port_event)(struct asd_sas_phy *, enum port_event); ++ int (*notify_phy_event)(struct asd_sas_phy *, enum phy_event); ++#endif + void *lldd_ha; /* not touched by sas class code */ + + struct list_head eh_done_q; /* complete via scsi_eh_flush_done_q */ +-- +2.27.0 + diff --git a/patches/0477-scsi-hisi_sas-Switch-back-to-original-libsas-event-n.patch b/patches/0477-scsi-hisi_sas-Switch-back-to-original-libsas-event-n.patch new file mode 100644 index 00000000..9e862467 --- /dev/null +++ b/patches/0477-scsi-hisi_sas-Switch-back-to-original-libsas-event-n.patch @@ -0,0 +1,133 @@ +From 4bdb2d6eb24600462320828773bb57417bcf971f Mon Sep 17 00:00:00 2001 +From: "Ahmed S. Darwish" +Date: Tue, 3 Aug 2021 14:47:41 +0800 +Subject: [PATCH 159/256] scsi: hisi_sas: Switch back to original libsas event + notifiers + +mainline inclusion +from mainline-v5.12-rc1 +commit 872a90b5b46646c6d4cdc15a265a55b1adb25b49 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=872a90b5b46646c6d4cdc15a265a55b1adb25b49 + +---------------------------------------------------------------------- + +libsas event notifiers required an extension where gfp_t flags must be +explicitly passed. For bisectability, a temporary _gfp() variant of such +functions were added. All call sites then got converted use the _gfp() +variants and explicitly pass GFP context. Having no callers left, the +original libsas notifiers were then modified to accept gfp_t flags by +default. + +Switch back to the original libas API, while still passing GFP context. +The libsas _gfp() variants will be removed afterwards. + +Link: https://lore.kernel.org/r/20210118100955.1761652-14-a.darwish@linutronix.de +Reviewed-by: John Garry +Signed-off-by: Ahmed S. Darwish +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 9 ++++----- + drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 4 ++-- + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 4 ++-- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 4 ++-- + 4 files changed, 10 insertions(+), 11 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 5a4eb8eec036..7c2602940dcb 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -637,7 +637,7 @@ static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, int phy_no, + if (!phy->phy_attached) + return; + +- sas_notify_phy_event_gfp(sas_phy, PHYE_OOB_DONE, gfp_flags); ++ sas_notify_phy_event(sas_phy, PHYE_OOB_DONE, gfp_flags); + + if (sas_phy->phy) { + struct sas_phy *sphy = sas_phy->phy; +@@ -665,7 +665,7 @@ static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, int phy_no, + } + + sas_phy->frame_rcvd_size = phy->frame_rcvd_size; +- sas_notify_port_event_gfp(sas_phy, PORTE_BYTES_DMAED, gfp_flags); ++ sas_notify_port_event(sas_phy, PORTE_BYTES_DMAED, gfp_flags); + } + + static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device) +@@ -1471,7 +1471,7 @@ static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state) + _sas_port = sas_port; + + if (DEV_IS_EXPANDER(dev->dev_type)) +- sas_notify_port_event_gfp(sas_phy, ++ sas_notify_port_event(sas_phy, + PORTE_BROADCAST_RCVD, + GFP_KERNEL); + } +@@ -2287,8 +2287,7 @@ void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy, + return; + } + /* Phy down and not ready */ +- sas_notify_phy_event_gfp(sas_phy, +- PHYE_LOSS_OF_SIGNAL, gfp_flags); ++ sas_notify_phy_event(sas_phy, PHYE_LOSS_OF_SIGNAL, gfp_flags); + sas_phy_disconnected(sas_phy); + + if (port) { +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +index 0e2e1397c6b8..b0f34cf16394 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +@@ -1427,8 +1427,8 @@ static irqreturn_t int_bcast_v1_hw(int irq, void *p) + } + + if (!test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) +- sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, +- GFP_ATOMIC); ++ sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD, ++ GFP_ATOMIC); + + end: + hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2, +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +index d2c9186749ae..885858453ed2 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -2846,8 +2846,8 @@ static void phy_bcast_v2_hw(int phy_no, struct hisi_hba *hisi_hba) + bcast_status = hisi_sas_phy_read32(hisi_hba, phy_no, RX_PRIMS_STATUS); + if ((bcast_status & RX_BCAST_CHG_MSK) && + !test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) +- sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, +- GFP_ATOMIC); ++ sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD, ++ GFP_ATOMIC); + hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, + CHL_INT0_SL_RX_BCST_ACK_MSK); + hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 0); +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index b06d38cb9e41..31ae62f49ca3 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -1756,8 +1756,8 @@ static irqreturn_t phy_bcast_v3_hw(int phy_no, struct hisi_hba *hisi_hba) + bcast_status = hisi_sas_phy_read32(hisi_hba, phy_no, RX_PRIMS_STATUS); + if ((bcast_status & RX_BCAST_CHG_MSK) && + !test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) +- sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, +- GFP_ATOMIC); ++ sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD, ++ GFP_ATOMIC); + hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, + CHL_INT0_SL_RX_BCST_ACK_MSK); + hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 0); +-- +2.27.0 + diff --git a/patches/0478-scsi-aic94xx-Switch-back-to-original-libsas-event-no.patch b/patches/0478-scsi-aic94xx-Switch-back-to-original-libsas-event-no.patch new file mode 100644 index 00000000..82e4afc2 --- /dev/null +++ b/patches/0478-scsi-aic94xx-Switch-back-to-original-libsas-event-no.patch @@ -0,0 +1,134 @@ +From 7f549c8dfe3e9109433a2bc0c5757157614cd103 Mon Sep 17 00:00:00 2001 +From: "Ahmed S. Darwish" +Date: Tue, 3 Aug 2021 14:47:42 +0800 +Subject: [PATCH 160/256] scsi: aic94xx: Switch back to original libsas event + notifiers + +mainline inclusion +from mainline-v5.12-rc1 +commit 093289e40b521e977ae0f3a4e7c0909b38c21193 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=093289e40b521e977ae0f3a4e7c0909b38c21193 + +---------------------------------------------------------------------- + +libsas event notifiers required an extension where gfp_t flags must be +explicitly passed. For bisectability, a temporary _gfp() variant of such +functions were added. All call sites then got converted use the _gfp() +variants and explicitly pass GFP context. Having no callers left, the +original libsas notifiers were then modified to accept gfp_t flags by +default. + +Switch back to the original libas API, while still passing GFP context. +The libsas _gfp() variants will be removed afterwards. + +Link: https://lore.kernel.org/r/20210118100955.1761652-15-a.darwish@linutronix.de +Reviewed-by: John Garry +Signed-off-by: Ahmed S. Darwish +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/aic94xx/aic94xx_scb.c | 29 +++++++++++++---------------- + 1 file changed, 13 insertions(+), 16 deletions(-) + +diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c +index eac4aa9afb57..868361f5dcb1 100644 +--- a/drivers/scsi/aic94xx/aic94xx_scb.c ++++ b/drivers/scsi/aic94xx/aic94xx_scb.c +@@ -98,8 +98,8 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb, + ASD_DPRINTK("phy%d: device unplugged\n", phy_id); + asd_turn_led(asd_ha, phy_id, 0); + sas_phy_disconnected(&phy->sas_phy); +- sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL, +- GFP_ATOMIC); ++ sas_notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL, ++ GFP_ATOMIC); + break; + case CURRENT_OOB_DONE: + /* hot plugged device */ +@@ -107,14 +107,13 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb, + get_lrate_mode(phy, oob_mode); + ASD_DPRINTK("phy%d device plugged: lrate:0x%x, proto:0x%x\n", + phy_id, phy->sas_phy.linkrate, phy->sas_phy.iproto); +- sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_OOB_DONE, +- GFP_ATOMIC); ++ sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE, GFP_ATOMIC); + break; + case CURRENT_SPINUP_HOLD: + /* hot plug SATA, no COMWAKE sent */ + asd_turn_led(asd_ha, phy_id, 1); +- sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_SPINUP_HOLD, +- GFP_ATOMIC); ++ sas_notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD, ++ GFP_ATOMIC); + break; + case CURRENT_GTO_TIMEOUT: + case CURRENT_OOB_ERROR: +@@ -122,8 +121,7 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb, + dl->status_block[1]); + asd_turn_led(asd_ha, phy_id, 0); + sas_phy_disconnected(&phy->sas_phy); +- sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_OOB_ERROR, +- GFP_ATOMIC); ++ sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR, GFP_ATOMIC); + break; + } + } +@@ -254,7 +252,7 @@ static void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb, + spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags); + asd_dump_frame_rcvd(phy, dl); + asd_form_port(ascb->ha, phy); +- sas_notify_port_event_gfp(&phy->sas_phy, PORTE_BYTES_DMAED, GFP_ATOMIC); ++ sas_notify_port_event(&phy->sas_phy, PORTE_BYTES_DMAED, GFP_ATOMIC); + } + + static void asd_link_reset_err_tasklet(struct asd_ascb *ascb, +@@ -290,7 +288,7 @@ static void asd_link_reset_err_tasklet(struct asd_ascb *ascb, + asd_turn_led(asd_ha, phy_id, 0); + sas_phy_disconnected(sas_phy); + asd_deform_port(asd_ha, phy); +- sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, GFP_ATOMIC); ++ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR, GFP_ATOMIC); + + if (retries_left == 0) { + int num = 1; +@@ -335,8 +333,8 @@ static void asd_primitive_rcvd_tasklet(struct asd_ascb *ascb, + spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); + sas_phy->sas_prim = ffs(cont); + spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); +- sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, +- GFP_ATOMIC); ++ sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD, ++ GFP_ATOMIC); + break; + + case LmUNKNOWNP: +@@ -357,8 +355,8 @@ static void asd_primitive_rcvd_tasklet(struct asd_ascb *ascb, + /* The sequencer disables all phys on that port. + * We have to re-enable the phys ourselves. */ + asd_deform_port(asd_ha, phy); +- sas_notify_port_event_gfp(sas_phy, PORTE_HARD_RESET, +- GFP_ATOMIC); ++ sas_notify_port_event(sas_phy, PORTE_HARD_RESET, ++ GFP_ATOMIC); + break; + + default: +@@ -589,8 +587,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, + /* the device is gone */ + sas_phy_disconnected(sas_phy); + asd_deform_port(asd_ha, phy); +- sas_notify_port_event_gfp(sas_phy, PORTE_TIMER_EVENT, +- GFP_ATOMIC); ++ sas_notify_port_event(sas_phy, PORTE_TIMER_EVENT, GFP_ATOMIC); + break; + default: + ASD_DPRINTK("%s: phy%d: unknown event:0x%x\n", __func__, +-- +2.27.0 + diff --git a/patches/0479-scsi-pm80xx-Switch-back-to-original-libsas-event-not.patch b/patches/0479-scsi-pm80xx-Switch-back-to-original-libsas-event-not.patch new file mode 100644 index 00000000..feb785aa --- /dev/null +++ b/patches/0479-scsi-pm80xx-Switch-back-to-original-libsas-event-not.patch @@ -0,0 +1,366 @@ +From 78a89108f27e9837e5bf1694270c883eb20991e8 Mon Sep 17 00:00:00 2001 +From: "Ahmed S. Darwish" +Date: Tue, 3 Aug 2021 14:47:43 +0800 +Subject: [PATCH 161/256] scsi: pm80xx: Switch back to original libsas event + notifiers + +mainline inclusion +from mainline-v5.12-rc1 +commit de6d7547ce1d78aa8d7bc6662d3a3dce023fbc6e +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=de6d7547ce1d78aa8d7bc6662d3a3dce023fbc6e + +---------------------------------------------------------------------- + +libsas event notifiers required an extension where gfp_t flags must be +explicitly passed. For bisectability, a temporary _gfp() variant of such +functions were added. All call sites then got converted use the _gfp() +variants and explicitly pass GFP context. Having no callers left, the +original libsas notifiers were then modified to accept gfp_t flags by +default. + +Switch back to the original libas API, while still passing GFP context. +The libsas _gfp() variants will be removed afterwards. + +Link: https://lore.kernel.org/r/20210118100955.1761652-16-a.darwish@linutronix.de +Cc: Jack Wang +Reviewed-by: John Garry +Reviewed-by: Jack Wang +Signed-off-by: Ahmed S. Darwish +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/pm8001/pm8001_hwi.c + drivers/scsi/pm8001/pm8001_sas.c + drivers/scsi/pm8001/pm80xx_hwi.c +--- + drivers/scsi/pm8001/pm8001_hwi.c | 39 ++++++++++++++++---------------- + drivers/scsi/pm8001/pm8001_sas.c | 1 - + drivers/scsi/pm8001/pm80xx_hwi.c | 31 ++++++++++++------------- + 3 files changed, 34 insertions(+), 37 deletions(-) + +diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c +index 258bc914fb32..4543a9d86ab3 100644 +--- a/drivers/scsi/pm8001/pm8001_hwi.c ++++ b/drivers/scsi/pm8001/pm8001_hwi.c +@@ -3270,7 +3270,7 @@ void pm8001_bytes_dmaed(struct pm8001_hba_info *pm8001_ha, int i) + PM8001_MSG_DBG(pm8001_ha, pm8001_printk("phy %d byte dmaded.\n", i)); + + sas_phy->frame_rcvd_size = phy->frame_rcvd_size; +- sas_notify_port_event_gfp(sas_phy, PORTE_BYTES_DMAED, GFP_ATOMIC); ++ sas_notify_port_event(sas_phy, PORTE_BYTES_DMAED, GFP_ATOMIC); + } + + /* Get the link rate speed */ +@@ -3429,7 +3429,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) + else if (phy->identify.device_type != SAS_PHY_UNUSED) + phy->identify.target_port_protocols = SAS_PROTOCOL_SMP; + phy->sas_phy.oob_mode = SAS_OOB_MODE; +- sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_OOB_DONE, GFP_ATOMIC); ++ sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE, GFP_ATOMIC); + spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags); + memcpy(phy->frame_rcvd, &pPayload->sas_identify, + sizeof(struct sas_identify_frame)-4); +@@ -3473,7 +3473,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) + phy->phy_type |= PORT_TYPE_SATA; + phy->phy_attached = 1; + phy->sas_phy.oob_mode = SATA_OOB_MODE; +- sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_OOB_DONE, GFP_ATOMIC); ++ sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE, GFP_ATOMIC); + spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags); + memcpy(phy->frame_rcvd, ((u8 *)&pPayload->sata_fis - 4), + sizeof(struct dev_to_host_fis)); +@@ -3838,13 +3838,13 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + case HW_EVENT_SATA_SPINUP_HOLD: + PM8001_MSG_DBG(pm8001_ha, + pm8001_printk("HW_EVENT_SATA_SPINUP_HOLD\n")); +- sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_SPINUP_HOLD, ++ sas_notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD, + GFP_ATOMIC); + break; + case HW_EVENT_PHY_DOWN: + PM8001_MSG_DBG(pm8001_ha, + pm8001_printk("HW_EVENT_PHY_DOWN\n")); +- sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL, ++ sas_notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL, + GFP_ATOMIC); + phy->phy_attached = 0; + phy->phy_state = 0; +@@ -3855,7 +3855,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + pm8001_printk("HW_EVENT_PORT_INVALID\n")); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR, + GFP_ATOMIC); + break; + /* the broadcast change primitive received, tell the LIBSAS this event +@@ -3868,7 +3868,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); + sas_phy->sas_prim = HW_EVENT_BROADCAST_CHANGE; + spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); +- sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, ++ sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD, + GFP_ATOMIC); + break; + case HW_EVENT_PHY_ERROR: +@@ -3876,8 +3876,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + pm8001_printk("HW_EVENT_PHY_ERROR\n")); + sas_phy_disconnected(&phy->sas_phy); + phy->phy_attached = 0; +- sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_OOB_ERROR, +- GFP_ATOMIC); ++ sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR, GFP_ATOMIC); + break; + case HW_EVENT_BROADCAST_EXP: + PM8001_MSG_DBG(pm8001_ha, +@@ -3885,7 +3884,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); + sas_phy->sas_prim = HW_EVENT_BROADCAST_EXP; + spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); +- sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, ++ sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD, + GFP_ATOMIC); + break; + case HW_EVENT_LINK_ERR_INVALID_DWORD: +@@ -3895,7 +3894,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + HW_EVENT_LINK_ERR_INVALID_DWORD, port_id, phy_id, 0, 0); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR, + GFP_ATOMIC); + break; + case HW_EVENT_LINK_ERR_DISPARITY_ERROR: +@@ -3906,7 +3905,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + port_id, phy_id, 0, 0); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR, + GFP_ATOMIC); + break; + case HW_EVENT_LINK_ERR_CODE_VIOLATION: +@@ -3917,7 +3916,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + port_id, phy_id, 0, 0); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR, + GFP_ATOMIC); + break; + case HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH: +@@ -3928,7 +3927,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + port_id, phy_id, 0, 0); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR, + GFP_ATOMIC); + break; + case HW_EVENT_MALFUNCTION: +@@ -3941,7 +3940,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); + sas_phy->sas_prim = HW_EVENT_BROADCAST_SES; + spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); +- sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, ++ sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD, + GFP_ATOMIC); + break; + case HW_EVENT_INBOUND_CRC_ERROR: +@@ -3954,7 +3953,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + case HW_EVENT_HARD_RESET_RECEIVED: + PM8001_MSG_DBG(pm8001_ha, + pm8001_printk("HW_EVENT_HARD_RESET_RECEIVED\n")); +- sas_notify_port_event_gfp(sas_phy, PORTE_HARD_RESET, ++ sas_notify_port_event(sas_phy, PORTE_HARD_RESET, + GFP_ATOMIC); + break; + case HW_EVENT_ID_FRAME_TIMEOUT: +@@ -3962,7 +3961,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + pm8001_printk("HW_EVENT_ID_FRAME_TIMEOUT\n")); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR, + GFP_ATOMIC); + break; + case HW_EVENT_LINK_ERR_PHY_RESET_FAILED: +@@ -3973,7 +3972,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + port_id, phy_id, 0, 0); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR, + GFP_ATOMIC); + break; + case HW_EVENT_PORT_RESET_TIMER_TMO: +@@ -3981,7 +3980,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + pm8001_printk("HW_EVENT_PORT_RESET_TIMER_TMO\n")); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR, + GFP_ATOMIC); + break; + case HW_EVENT_PORT_RECOVERY_TIMER_TMO: +@@ -3989,7 +3988,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) + pm8001_printk("HW_EVENT_PORT_RECOVERY_TIMER_TMO\n")); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR, + GFP_ATOMIC); + break; + case HW_EVENT_PORT_RECOVER: +diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c +index 59feda261e08..35e889330c11 100644 +--- a/drivers/scsi/pm8001/pm8001_sas.c ++++ b/drivers/scsi/pm8001/pm8001_sas.c +@@ -1319,4 +1319,3 @@ int pm8001_clear_task_set(struct domain_device *dev, u8 *lun) + rc = pm8001_issue_ssp_tmf(dev, lun, &tmf_task); + return rc; + } +- +diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c +index 67109070451d..04620a9088a5 100644 +--- a/drivers/scsi/pm8001/pm80xx_hwi.c ++++ b/drivers/scsi/pm8001/pm80xx_hwi.c +@@ -2977,7 +2977,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) + else if (phy->identify.device_type != SAS_PHY_UNUSED) + phy->identify.target_port_protocols = SAS_PROTOCOL_SMP; + phy->sas_phy.oob_mode = SAS_OOB_MODE; +- sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_OOB_DONE, GFP_ATOMIC); ++ sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE, GFP_ATOMIC); + spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags); + memcpy(phy->frame_rcvd, &pPayload->sas_identify, + sizeof(struct sas_identify_frame)-4); +@@ -3024,7 +3024,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) + phy->phy_type |= PORT_TYPE_SATA; + phy->phy_attached = 1; + phy->sas_phy.oob_mode = SATA_OOB_MODE; +- sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_OOB_DONE, GFP_ATOMIC); ++ sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE, GFP_ATOMIC); + spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags); + memcpy(phy->frame_rcvd, ((u8 *)&pPayload->sata_fis - 4), + sizeof(struct dev_to_host_fis)); +@@ -3108,8 +3108,8 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb) + + } + if (port_sata && (portstate != PORT_IN_RESET)) { +- sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL, +- GFP_ATOMIC); ++ sas_notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL, ++ GFP_ATOMIC); + } + } + +@@ -3208,7 +3208,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + case HW_EVENT_SATA_SPINUP_HOLD: + PM8001_MSG_DBG(pm8001_ha, + pm8001_printk("HW_EVENT_SATA_SPINUP_HOLD\n")); +- sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_SPINUP_HOLD, ++ sas_notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD, + GFP_ATOMIC); + break; + case HW_EVENT_PHY_DOWN: +@@ -3228,7 +3228,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + pm8001_printk("HW_EVENT_PORT_INVALID\n")); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR, + GFP_ATOMIC); + break; + /* the broadcast change primitive received, tell the LIBSAS this event +@@ -3241,7 +3241,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); + sas_phy->sas_prim = HW_EVENT_BROADCAST_CHANGE; + spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); +- sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, ++ sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD, + GFP_ATOMIC); + break; + case HW_EVENT_PHY_ERROR: +@@ -3249,8 +3249,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + pm8001_printk("HW_EVENT_PHY_ERROR\n")); + sas_phy_disconnected(&phy->sas_phy); + phy->phy_attached = 0; +- sas_notify_phy_event_gfp(&phy->sas_phy, PHYE_OOB_ERROR, +- GFP_ATOMIC); ++ sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR, GFP_ATOMIC); + break; + case HW_EVENT_BROADCAST_EXP: + PM8001_MSG_DBG(pm8001_ha, +@@ -3258,7 +3257,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); + sas_phy->sas_prim = HW_EVENT_BROADCAST_EXP; + spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); +- sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, ++ sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD, + GFP_ATOMIC); + break; + case HW_EVENT_LINK_ERR_INVALID_DWORD: +@@ -3298,7 +3297,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); + sas_phy->sas_prim = HW_EVENT_BROADCAST_SES; + spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); +- sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, ++ sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD, + GFP_ATOMIC); + break; + case HW_EVENT_INBOUND_CRC_ERROR: +@@ -3311,7 +3310,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + case HW_EVENT_HARD_RESET_RECEIVED: + PM8001_MSG_DBG(pm8001_ha, + pm8001_printk("HW_EVENT_HARD_RESET_RECEIVED\n")); +- sas_notify_port_event_gfp(sas_phy, PORTE_HARD_RESET, ++ sas_notify_port_event(sas_phy, PORTE_HARD_RESET, + GFP_ATOMIC); + break; + case HW_EVENT_ID_FRAME_TIMEOUT: +@@ -3319,7 +3318,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + pm8001_printk("HW_EVENT_ID_FRAME_TIMEOUT\n")); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR, + GFP_ATOMIC); + break; + case HW_EVENT_LINK_ERR_PHY_RESET_FAILED: +@@ -3330,7 +3329,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + port_id, phy_id, 0, 0); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR, + GFP_ATOMIC); + break; + case HW_EVENT_PORT_RESET_TIMER_TMO: +@@ -3340,7 +3339,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + port_id, phy_id, 0, 0); + sas_phy_disconnected(sas_phy); + phy->phy_attached = 0; +- sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, ++ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR, + GFP_ATOMIC); + if (pm8001_ha->phy[phy_id].reset_completion) { + pm8001_ha->phy[phy_id].port_reset_status = +@@ -3358,7 +3357,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + for (i = 0; i < pm8001_ha->chip->n_phy; i++) { + if (port->wide_port_phymap & (1 << i)) { + phy = &pm8001_ha->phy[i]; +- sas_notify_phy_event_gfp(&phy->sas_phy, ++ sas_notify_phy_event(&phy->sas_phy, + PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC); + port->wide_port_phymap &= ~(1 << i); + } +-- +2.27.0 + diff --git a/patches/0480-scsi-libsas-Switch-back-to-original-event-notifiers-.patch b/patches/0480-scsi-libsas-Switch-back-to-original-event-notifiers-.patch new file mode 100644 index 00000000..58723982 --- /dev/null +++ b/patches/0480-scsi-libsas-Switch-back-to-original-event-notifiers-.patch @@ -0,0 +1,103 @@ +From 57736cee0579625b4985bb379e747ede3e699b08 Mon Sep 17 00:00:00 2001 +From: "Ahmed S. Darwish" +Date: Tue, 3 Aug 2021 14:47:44 +0800 +Subject: [PATCH 162/256] scsi: libsas: Switch back to original event notifiers + API + +mainline inclusion +from mainline-v5.12-rc1 +commit f76d9f1a1511eeb8a10c8f88c3c73ec2e0cba992 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f76d9f1a1511eeb8a10c8f88c3c73ec2e0cba992 + +---------------------------------------------------------------------- + +libsas event notifiers required an extension where gfp_t flags must be +explicitly passed. For bisectability, a temporary _gfp() variant of such +functions were added. All call sites then got converted use the _gfp() +variants and explicitly pass GFP context. Having no callers left, the +original libsas notifiers were then modified to accept gfp_t flags by +default. + +Switch back to the original event notifiers API, while still passing GFP +context. The _gfp() notifier variants will be removed afterwards. + +Link: https://lore.kernel.org/r/20210118100955.1761652-17-a.darwish@linutronix.de +Cc: Jason Yan +Reviewed-by: John Garry +Signed-off-by: Ahmed S. Darwish +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/libsas/sas_init.c +--- + drivers/scsi/libsas/sas_event.c | 6 +++--- + drivers/scsi/libsas/sas_init.c | 8 ++++---- + 2 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c +index 06b0105be611..cd6ef88ef136 100644 +--- a/drivers/scsi/libsas/sas_event.c ++++ b/drivers/scsi/libsas/sas_event.c +@@ -126,7 +126,7 @@ void sas_enable_revalidation(struct sas_ha_struct *ha) + + sas_phy = container_of(port->phy_list.next, struct asd_sas_phy, + port_phy_el); +- sas_notify_port_event_gfp(sas_phy, ++ sas_notify_port_event(sas_phy, + PORTE_BROADCAST_RCVD, GFP_KERNEL); + } + mutex_unlock(&ha->disco_mutex); +@@ -158,7 +158,7 @@ int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event, + + BUG_ON(event >= PORT_NUM_EVENTS); + +- ev = sas_alloc_event_gfp(phy, gfp_flags); ++ ev = sas_alloc_event(phy, gfp_flags); + if (!ev) + return -ENOMEM; + +@@ -188,7 +188,7 @@ int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event, + + BUG_ON(event >= PHY_NUM_EVENTS); + +- ev = sas_alloc_event_gfp(phy, gfp_flags); ++ ev = sas_alloc_event(phy, gfp_flags); + if (!ev) + return -ENOMEM; + +diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c +index 239cf00a7bf7..ecd2a4cf6ee8 100644 +--- a/drivers/scsi/libsas/sas_init.c ++++ b/drivers/scsi/libsas/sas_init.c +@@ -427,8 +427,8 @@ void sas_resume_ha(struct sas_ha_struct *ha) + + if (phy->suspended) { + dev_warn(&phy->phy->dev, "resume timeout\n"); +- sas_notify_phy_event_gfp(phy, PHYE_RESUME_TIMEOUT, +- GFP_KERNEL); ++ sas_notify_phy_event(phy, PHYE_RESUME_TIMEOUT, ++ GFP_KERNEL); + } + } + +@@ -627,8 +627,8 @@ struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy, + if (cmpxchg(&phy->in_shutdown, 0, 1) == 0) { + sas_printk("The phy%02d bursting events, shut it down.\n", + phy->id); +- sas_notify_phy_event_gfp(phy, PHYE_SHUTDOWN, +- gfp_flags); ++ sas_notify_phy_event(phy, PHYE_SHUTDOWN, ++ gfp_flags); + } + } else { + /* Do not support PHY control, stop allocating events */ +-- +2.27.0 + diff --git a/patches/0481-scsi-isci-Switch-back-to-original-libsas-event-notif.patch b/patches/0481-scsi-isci-Switch-back-to-original-libsas-event-notif.patch new file mode 100644 index 00000000..50cdbbc6 --- /dev/null +++ b/patches/0481-scsi-isci-Switch-back-to-original-libsas-event-notif.patch @@ -0,0 +1,79 @@ +From 7fe6ea150a7100ed72dc74b1a0806cb927e5c49e Mon Sep 17 00:00:00 2001 +From: "Ahmed S. Darwish" +Date: Tue, 3 Aug 2021 14:47:45 +0800 +Subject: [PATCH 163/256] scsi: isci: Switch back to original libsas event + notifiers + +mainline inclusion +from mainline-v5.12-rc1 +commit c12208668aefd91f33e41183a3e6f85979ac953f +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c12208668aefd91f33e41183a3e6f85979ac953f + +---------------------------------------------------------------------- + +libsas event notifiers required an extension where gfp_t flags must be +explicitly passed. For bisectability, a temporary _gfp() variant of such +functions were added. All call sites then got converted use the _gfp() +variants and explicitly pass GFP context. Having no callers left, the +original libsas notifiers were then modified to accept gfp_t flags by +default. + +Switch back to the original libas API, while still passing GFP context. +The libsas _gfp() variants will be removed afterwards. + +Link: https://lore.kernel.org/r/20210118100955.1761652-18-a.darwish@linutronix.de +Cc: Artur Paszkiewicz +Reviewed-by: John Garry +Signed-off-by: Ahmed S. Darwish +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/isci/port.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c +index e50c3b0deeb3..448a8c31ba35 100644 +--- a/drivers/scsi/isci/port.c ++++ b/drivers/scsi/isci/port.c +@@ -164,8 +164,8 @@ static void isci_port_bc_change_received(struct isci_host *ihost, + "%s: isci_phy = %p, sas_phy = %p\n", + __func__, iphy, &iphy->sas_phy); + +- sas_notify_port_event_gfp(&iphy->sas_phy, +- PORTE_BROADCAST_RCVD, GFP_ATOMIC); ++ sas_notify_port_event(&iphy->sas_phy, ++ PORTE_BROADCAST_RCVD, GFP_ATOMIC); + sci_port_bcn_enable(iport); + } + +@@ -224,8 +224,8 @@ static void isci_port_link_up(struct isci_host *isci_host, + /* Notify libsas that we have an address frame, if indeed + * we've found an SSP, SMP, or STP target */ + if (success) +- sas_notify_port_event_gfp(&iphy->sas_phy, +- PORTE_BYTES_DMAED, GFP_ATOMIC); ++ sas_notify_port_event(&iphy->sas_phy, ++ PORTE_BYTES_DMAED, GFP_ATOMIC); + } + + +@@ -271,8 +271,8 @@ static void isci_port_link_down(struct isci_host *isci_host, + * isci_port_deformed and isci_dev_gone functions. + */ + sas_phy_disconnected(&isci_phy->sas_phy); +- sas_notify_phy_event_gfp(&isci_phy->sas_phy, +- PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC); ++ sas_notify_phy_event(&isci_phy->sas_phy, ++ PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC); + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_port = %p - Done\n", __func__, isci_port); +-- +2.27.0 + diff --git a/patches/0482-scsi-mvsas-Switch-back-to-original-libsas-event-noti.patch b/patches/0482-scsi-mvsas-Switch-back-to-original-libsas-event-noti.patch new file mode 100644 index 00000000..3233ed43 --- /dev/null +++ b/patches/0482-scsi-mvsas-Switch-back-to-original-libsas-event-noti.patch @@ -0,0 +1,81 @@ +From a09a3eaf19f687ba6209ea49c3445397a5707e27 Mon Sep 17 00:00:00 2001 +From: "Ahmed S. Darwish" +Date: Tue, 3 Aug 2021 14:47:46 +0800 +Subject: [PATCH 164/256] scsi: mvsas: Switch back to original libsas event + notifiers + +mainline inclusion +from mainline-v5.12-rc1 +commit 36cdfd0f7a8c99c5817bea2306613a966e67f0e2 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=36cdfd0f7a8c99c5817bea2306613a966e67f0e2 + +---------------------------------------------------------------------- + +libsas event notifiers required an extension where gfp_t flags must be +explicitly passed. For bisectability, a temporary _gfp() variant of such +functions were added. All call sites then got converted use the _gfp() +variants and explicitly pass GFP context. Having no callers left, the +original libsas notifiers were then modified to accept gfp_t flags by +default. + +Switch back to the original libas API, while still passing GFP context. +The libsas _gfp() variants will be removed afterwards. + +Link: https://lore.kernel.org/r/20210118100955.1761652-19-a.darwish@linutronix.de +Reviewed-by: John Garry +Signed-off-by: Ahmed S. Darwish +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/mvsas/mv_sas.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c +index f97d69ac18a4..d14b6856f592 100644 +--- a/drivers/scsi/mvsas/mv_sas.c ++++ b/drivers/scsi/mvsas/mv_sas.c +@@ -244,7 +244,7 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i, gfp_t gfp_flags) + return; + } + +- sas_notify_phy_event_gfp(sas_phy, PHYE_OOB_DONE, gfp_flags); ++ sas_notify_phy_event(sas_phy, PHYE_OOB_DONE, gfp_flags); + + if (sas_phy->phy) { + struct sas_phy *sphy = sas_phy->phy; +@@ -276,7 +276,7 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i, gfp_t gfp_flags) + + sas_phy->frame_rcvd_size = phy->frame_rcvd_size; + +- sas_notify_port_event_gfp(sas_phy, PORTE_BYTES_DMAED, gfp_flags); ++ sas_notify_port_event(sas_phy, PORTE_BYTES_DMAED, gfp_flags); + } + + void mvs_scan_start(struct Scsi_Host *shost) +@@ -1909,7 +1909,7 @@ static void mvs_work_queue(struct work_struct *work) + if (!(tmp & PHY_READY_MASK)) { + sas_phy_disconnected(sas_phy); + mvs_phy_disconnected(phy); +- sas_notify_phy_event_gfp(sas_phy, ++ sas_notify_phy_event(sas_phy, + PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC); + mv_dprintk("phy%d Removed Device\n", phy_no); + } else { +@@ -1922,7 +1922,7 @@ static void mvs_work_queue(struct work_struct *work) + } + } else if (mwq->handler & EXP_BRCT_CHG) { + phy->phy_event &= ~EXP_BRCT_CHG; +- sas_notify_port_event_gfp(sas_phy, ++ sas_notify_port_event(sas_phy, + PORTE_BROADCAST_RCVD, GFP_ATOMIC); + mv_dprintk("phy%d Got Broadcast Change\n", phy_no); + } +-- +2.27.0 + diff --git a/patches/0483-scsi-libsas-Remove-temporarily-added-_gfp-API-varian.patch b/patches/0483-scsi-libsas-Remove-temporarily-added-_gfp-API-varian.patch new file mode 100644 index 00000000..74e0a347 --- /dev/null +++ b/patches/0483-scsi-libsas-Remove-temporarily-added-_gfp-API-varian.patch @@ -0,0 +1,138 @@ +From 147e1a6300f02feb56cadeee5675da4248c69397 Mon Sep 17 00:00:00 2001 +From: "Ahmed S. Darwish" +Date: Tue, 3 Aug 2021 14:47:47 +0800 +Subject: [PATCH 165/256] scsi: libsas: Remove temporarily-added _gfp() API + variants + +mainline inclusion +from mainline-v5.12-rc1 +commit 65f7cfba6196baf2fc06ac0ab0be764377f3206a +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=65f7cfba6196baf2fc06ac0ab0be764377f3206a + +---------------------------------------------------------------------- + +These variants were added for bisectability. Remove them, as all call sites +have now been convertd to use the original API. + +Link: https://lore.kernel.org/r/20210118100955.1761652-20-a.darwish@linutronix.de +Cc: Jason Yan +Reviewed-by: John Garry +Signed-off-by: Ahmed S. Darwish +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + Documentation/scsi/libsas.rst + drivers/scsi/libsas/sas_event.c +--- + Documentation/scsi/libsas.txt | 2 -- + drivers/scsi/libsas/sas_event.c | 13 ------------- + drivers/scsi/libsas/sas_init.c | 7 ------- + drivers/scsi/libsas/sas_internal.h | 4 ---- + include/scsi/libsas.h | 4 ---- + 5 files changed, 30 deletions(-) + +diff --git a/Documentation/scsi/libsas.txt b/Documentation/scsi/libsas.txt +index 56a26b31fa6d..ff95aa2fcedf 100644 +--- a/Documentation/scsi/libsas.txt ++++ b/Documentation/scsi/libsas.txt +@@ -156,8 +156,6 @@ The event interface: + void (*notify_ha_event)(struct sas_ha_struct *, enum ha_event); + void sas_notify_port_event(struct sas_phy *, enum port_event, gfp_t); + void sas_notify_phy_event(struct sas_phy *, enum phy_event, gfp_t); +- void sas_notify_port_event_gfp(struct sas_phy *, enum port_event, gfp_t); +- void sas_notify_phy_event_gfp(struct sas_phy *, enum phy_event, gfp_t); + + When sas_register_ha() returns, those are set and can be + called by the LLDD to notify the SAS layer of such events +diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c +index cd6ef88ef136..4ceff8adf74f 100644 +--- a/drivers/scsi/libsas/sas_event.c ++++ b/drivers/scsi/libsas/sas_event.c +@@ -172,13 +172,6 @@ int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event, + } + EXPORT_SYMBOL_GPL(sas_notify_port_event); + +-int sas_notify_port_event_gfp(struct asd_sas_phy *phy, enum port_event event, +- gfp_t gfp_flags) +-{ +- return sas_notify_port_event(phy, event, gfp_flags); +-} +-EXPORT_SYMBOL_GPL(sas_notify_port_event_gfp); +- + int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event, + gfp_t gfp_flags) + { +@@ -210,9 +203,3 @@ int sas_init_events(struct sas_ha_struct *sas_ha) + return 0; + } + +-int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event, +- gfp_t gfp_flags) +-{ +- return sas_notify_phy_event(phy, event, gfp_flags); +-} +-EXPORT_SYMBOL_GPL(sas_notify_phy_event_gfp); +diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c +index ecd2a4cf6ee8..87bebd171652 100644 +--- a/drivers/scsi/libsas/sas_init.c ++++ b/drivers/scsi/libsas/sas_init.c +@@ -642,13 +642,6 @@ struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy, + return event; + } + +-struct asd_sas_event *sas_alloc_event_gfp(struct asd_sas_phy *phy, +- gfp_t gfp_flags) +-{ +- +- return sas_alloc_event(phy, gfp_flags); +-} +- + void sas_free_event(struct asd_sas_event *event) + { + struct asd_sas_phy *phy = event->phy; +diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h +index 2fae32a9156b..90049b3fbf68 100644 +--- a/drivers/scsi/libsas/sas_internal.h ++++ b/drivers/scsi/libsas/sas_internal.h +@@ -62,8 +62,6 @@ int sas_register_phys(struct sas_ha_struct *sas_ha); + void sas_unregister_phys(struct sas_ha_struct *sas_ha); + + struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy, gfp_t gfp_flags); +-struct asd_sas_event *sas_alloc_event_gfp(struct asd_sas_phy *phy, +- gfp_t gfp_flags); + void sas_free_event(struct asd_sas_event *event); + + int sas_register_ports(struct sas_ha_struct *sas_ha); +@@ -94,8 +92,6 @@ int sas_smp_get_phy_events(struct sas_phy *phy); + + int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event, + gfp_t flags); +-int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event, +- gfp_t flags); + void sas_device_set_phy(struct domain_device *dev, struct sas_port *port); + struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy); + struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id); +diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h +index 7db79ca4037f..be8ad849dfcd 100644 +--- a/include/scsi/libsas.h ++++ b/include/scsi/libsas.h +@@ -733,9 +733,5 @@ int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event, + gfp_t gfp_flags); + int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event, + gfp_t gfp_flags); +-int sas_notify_port_event_gfp(struct asd_sas_phy *phy, enum port_event event, +- gfp_t gfp_flags); +-int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event, +- gfp_t gfp_flags); + + #endif /* _SASLIB_H_ */ +-- +2.27.0 + diff --git a/patches/0484-scsi-hisi_sas-Remove-deferred-probe-check-in-hisi_sa.patch b/patches/0484-scsi-hisi_sas-Remove-deferred-probe-check-in-hisi_sa.patch new file mode 100644 index 00000000..6d89cdf8 --- /dev/null +++ b/patches/0484-scsi-hisi_sas-Remove-deferred-probe-check-in-hisi_sa.patch @@ -0,0 +1,60 @@ +From e55b153157b6c09f49ef5629667eb9151a27d538 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Tue, 3 Aug 2021 14:47:48 +0800 +Subject: [PATCH 166/256] scsi: hisi_sas: Remove deferred probe check in + hisi_sas_v2_probe() + +mainline inclusion +from mainline-v5.12-rc1 +commit 4d287d8bae1f395b5e5d79bc9673dacab7975e36 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4d287d8bae1f395b5e5d79bc9673dacab7975e36 + +---------------------------------------------------------------------- + +The platform_get_irq() check for -EPROBE_DEFER was to ensure that all the +steps to add the SCSI host are not done and then only to realise that the +probe needs to be deferred. + +However, since there is now an earlier check for this in +hisi_sas_interrupt_preinit(), this check is superfluous and may be removed. + +Link: https://lore.kernel.org/r/1611659068-131975-2-git-send-email-john.garry@huawei.com +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 12 ------------ + 1 file changed, 12 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +index 885858453ed2..abacd8a5369f 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -3645,18 +3645,6 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = { + + static int hisi_sas_v2_probe(struct platform_device *pdev) + { +- /* +- * Check if we should defer the probe before we probe the +- * upper layer, as it's hard to defer later on. +- */ +- int ret = platform_get_irq(pdev, 0); +- +- if (ret < 0) { +- if (ret != -EPROBE_DEFER) +- dev_err(&pdev->dev, "cannot obtain irq\n"); +- return ret; +- } +- + return hisi_sas_probe(pdev, &hisi_sas_v2_hw); + } + +-- +2.27.0 + diff --git a/patches/0485-scsi-hisi_sas-Don-t-check-.nr_hw_queues-in-hisi_sas_.patch b/patches/0485-scsi-hisi_sas-Don-t-check-.nr_hw_queues-in-hisi_sas_.patch new file mode 100644 index 00000000..0d251995 --- /dev/null +++ b/patches/0485-scsi-hisi_sas-Don-t-check-.nr_hw_queues-in-hisi_sas_.patch @@ -0,0 +1,65 @@ +From faae27b2fb216faf25bf06d3e7adafa618854c79 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Tue, 3 Aug 2021 14:47:49 +0800 +Subject: [PATCH 167/256] scsi: hisi_sas: Don't check .nr_hw_queues in + hisi_sas_task_prep() + +mainline inclusion +from mainline-v5.12-rc1 +commit 69bfa5fd7b448b2cd0cce6a301cf3fba8133ca0f +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=69bfa5fd7b448b2cd0cce6a301cf3fba8133ca0f + +---------------------------------------------------------------------- + +Now that v2 and v3 hw expose their HW queues (and so shost.nr_hw_queues is +set), remove the conditional checks in hisi_sas_task_prep(). + +This change would affect v1 HW performance (as it does not expose HW +queues), but nobody uses it and support may be dropped soon. + +Link: https://lore.kernel.org/r/1611659068-131975-3-git-send-email-john.garry@huawei.com +Reviewed-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 7c2602940dcb..dd52e792aa53 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -465,21 +465,19 @@ static int hisi_sas_task_prep(struct sas_task *task, + } + } + +- if (scmd && hisi_hba->shost->nr_hw_queues) { ++ if (scmd) { + unsigned int dq_index; + u32 blk_tag; + + blk_tag = blk_mq_unique_tag(scmd->request); + dq_index = blk_mq_unique_tag_to_hwq(blk_tag); + *dq_pointer = dq = &hisi_hba->dq[dq_index]; +- } else if (hisi_hba->shost->nr_hw_queues) { ++ } else { + struct Scsi_Host *shost = hisi_hba->shost; + struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT]; + int queue = qmap->mq_map[raw_smp_processor_id()]; + + *dq_pointer = dq = &hisi_hba->dq[queue]; +- } else { +- *dq_pointer = dq = sas_dev->dq; + } + + port = to_hisi_sas_port(sas_port); +-- +2.27.0 + diff --git a/patches/0486-scsi-hisi_sas-Enable-debugfs-support-by-default.patch b/patches/0486-scsi-hisi_sas-Enable-debugfs-support-by-default.patch new file mode 100644 index 00000000..8a06ba4a --- /dev/null +++ b/patches/0486-scsi-hisi_sas-Enable-debugfs-support-by-default.patch @@ -0,0 +1,81 @@ +From 726c29fd2b7ea2cffe019a44f6f96d6f995baf57 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Tue, 3 Aug 2021 14:47:50 +0800 +Subject: [PATCH 168/256] scsi: hisi_sas: Enable debugfs support by default + +mainline inclusion +from mainline-v5.12-rc1 +commit 1dbe61bf7d760547d16ccf057572e641a653ad4a +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81L + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1dbe61bf7d760547d16ccf057572e641a653ad4a + +---------------------------------------------------------------------- + +Add a config option to enable debugfs support by default. And if debugfs +support is enabled by default, dump count default value is increased to 50 +as generally users want something bigger than the current default in that +situation. + +Link: https://lore.kernel.org/r/1611659068-131975-4-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/Kconfig | 6 ++++++ + drivers/scsi/hisi_sas/hisi_sas_main.c | 13 +++++++++++-- + 2 files changed, 17 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/Kconfig b/drivers/scsi/hisi_sas/Kconfig +index 11c46b217caa..a8999964d3e9 100644 +--- a/drivers/scsi/hisi_sas/Kconfig ++++ b/drivers/scsi/hisi_sas/Kconfig +@@ -17,3 +17,9 @@ config SCSI_HISI_SAS_PCI + depends on ACPI + help + This driver supports HiSilicon's SAS HBA based on PCI device ++ ++config SCSI_HISI_SAS_DEBUGFS_DEFAULT_ENABLE ++ bool "HiSilicon SAS debugging default enable" ++ depends on SCSI_HISI_SAS ++ help ++ Set Y to default enable DEBUGFS for SCSI_HISI_SAS +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index dd52e792aa53..fc36388d6f04 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -2802,12 +2802,21 @@ int hisi_sas_remove(struct platform_device *pdev) + } + EXPORT_SYMBOL_GPL(hisi_sas_remove); + ++#if IS_ENABLED(CONFIG_SCSI_HISI_SAS_DEBUGFS_DEFAULT_ENABLE) ++#define DEBUGFS_ENABLE_DEFAULT "enabled" + bool hisi_sas_debugfs_enable = true; ++u32 hisi_sas_debugfs_dump_count = 50; ++#else ++#define DEBUGFS_ENABLE_DEFAULT "disabled" ++bool hisi_sas_debugfs_enable; ++u32 hisi_sas_debugfs_dump_count = 1; ++#endif ++ + EXPORT_SYMBOL_GPL(hisi_sas_debugfs_enable); + module_param_named(debugfs_enable, hisi_sas_debugfs_enable, bool, 0444); +-MODULE_PARM_DESC(hisi_sas_debugfs_enable, "Enable driver debugfs (default disabled)"); ++MODULE_PARM_DESC(hisi_sas_debugfs_enable, ++ "Enable driver debugfs (default "DEBUGFS_ENABLE_DEFAULT")"); + +-u32 hisi_sas_debugfs_dump_count = 1; + EXPORT_SYMBOL_GPL(hisi_sas_debugfs_dump_count); + module_param_named(debugfs_dump_count, hisi_sas_debugfs_dump_count, uint, 0444); + MODULE_PARM_DESC(hisi_sas_debugfs_dump_count, "Number of debugfs dumps to allow"); +-- +2.27.0 + diff --git a/patches/0487-scsi-hisi_sas-Add-trace-FIFO-debugfs-support.patch b/patches/0487-scsi-hisi_sas-Add-trace-FIFO-debugfs-support.patch new file mode 100644 index 00000000..1a2941ee --- /dev/null +++ b/patches/0487-scsi-hisi_sas-Add-trace-FIFO-debugfs-support.patch @@ -0,0 +1,385 @@ +From d236882a5659c5b19fa2944a005cfa3a765ab331 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Tue, 3 Aug 2021 14:47:52 +0800 +Subject: [PATCH 169/256] scsi: hisi_sas: Add trace FIFO debugfs support + +mainline inclusion +from mainline-v5.12-rc1 +commit cd96fe600cc4924d8d0cc6e3161870219c0d2c12 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F825 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cd96fe600cc4924d8d0cc6e3161870219c0d2c12 + +---------------------------------------------------------------------- + +The controller provides trace FIFO DFX tool to assist link fault debugging +and link optimization. This tool can be helpful when debugging link faults +without SAS analyzers. Each PHY has an independent trace FIFO interface. + +The user can configure the trace FIFO tool of one PHY by using the +following six interfaces: + +signal_sel: select signal group applies to different scenarios. + 0x0: linkrate negotiation + 0x1: Host 12G TX train + 0x2: Disk 12G TX train + 0x3: SAS PHY CTRL DFX 0 + 0x4: SAS PHY CTRL DFX 1 + 0x5: SAS PCS DFX + other: linkrate negotiation +dump_mask: The masked hardware status bit will not be updated. +dump_mode: determines how to dump data after trigger signal is generated. + 0x0: dump forever + 0x1: dump 32 data after trigger signal is generated + 0x2: no more dump after trigger signal is generated +trigger_mode: determines the trigger mode, level or edge. + 0x0: dump when trigger signal changed + 0x1: dump when trigger signal's level equal to trigger_level + 0x2: dump when trigger signal's level different from trigger_level +trigger_level: determines the trigger level. +trigger_msk: mask trigger signal + +The user can get 32-byte values from hardware by reading the rd_data. +These values consitute the status record of the hardware at different time +points. + +Link: https://lore.kernel.org/r/1611659068-131975-6-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas.h | 15 ++ + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 251 +++++++++++++++++++++++++ + 2 files changed, 266 insertions(+) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 8a30c2ee5996..bf36130b8e1c 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -50,6 +50,7 @@ + + #define HISI_SAS_IOST_ITCT_CACHE_NUM 64 + #define HISI_SAS_IOST_ITCT_CACHE_DW_SZ 10 ++#define HISI_SAS_FIFO_DATA_DW_SIZE 32 + + #define HISI_SAS_STATUS_BUF_SZ (sizeof(struct hisi_sas_status_buffer)) + #define HISI_SAS_COMMAND_TABLE_SZ (sizeof(union hisi_sas_command_table)) +@@ -172,6 +173,16 @@ enum hisi_sas_phy_event { + HISI_PHYES_NUM, + }; + ++struct hisi_sas_debugfs_fifo { ++ u32 signal_sel; ++ u32 dump_msk; ++ u32 dump_mode; ++ u32 trigger; ++ u32 trigger_msk; ++ u32 trigger_mode; ++ u32 rd_data[HISI_SAS_FIFO_DATA_DW_SIZE]; ++}; ++ + struct hisi_sas_phy { + struct work_struct works[HISI_PHYES_NUM]; + struct hisi_hba *hisi_hba; +@@ -194,6 +205,9 @@ struct hisi_sas_phy { + u32 code_error_count; + int enable; + atomic_t down_cnt; ++ ++ /* Trace FIFO */ ++ struct hisi_sas_debugfs_fifo fifo; + }; + + struct hisi_sas_port { +@@ -507,6 +521,7 @@ struct hisi_hba { + struct dentry *debugfs_dir; + struct dentry *debugfs_dump_dentry; + struct dentry *debugfs_bist_dentry; ++ struct dentry *debugfs_fifo_dentry; + + bool user_ctl_irq; + unsigned int dq_idx[NR_CPUS]; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 31ae62f49ca3..8ce0ff71aafc 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -312,6 +312,19 @@ + #define ERR_CNT_INVLD_DW (PORT_BASE + 0x390) + #define ERR_CNT_CODE_ERR (PORT_BASE + 0x394) + #define ERR_CNT_DISP_ERR (PORT_BASE + 0x398) ++#define DFX_FIFO_CTRL (PORT_BASE + 0x3a0) ++#define DFX_FIFO_CTRL_TRIGGER_MODE_OFF 0 ++#define DFX_FIFO_CTRL_TRIGGER_MODE_MSK (0x7 << DFX_FIFO_CTRL_TRIGGER_MODE_OFF) ++#define DFX_FIFO_CTRL_DUMP_MODE_OFF 3 ++#define DFX_FIFO_CTRL_DUMP_MODE_MSK (0x7 << DFX_FIFO_CTRL_DUMP_MODE_OFF) ++#define DFX_FIFO_CTRL_SIGNAL_SEL_OFF 6 ++#define DFX_FIFO_CTRL_SIGNAL_SEL_MSK (0xF << DFX_FIFO_CTRL_SIGNAL_SEL_OFF) ++#define DFX_FIFO_CTRL_DUMP_DISABLE_OFF 10 ++#define DFX_FIFO_CTRL_DUMP_DISABLE_MSK (0x1 << DFX_FIFO_CTRL_DUMP_DISABLE_OFF) ++#define DFX_FIFO_TRIGGER (PORT_BASE + 0x3a4) ++#define DFX_FIFO_TRIGGER_MSK (PORT_BASE + 0x3a8) ++#define DFX_FIFO_DUMP_MSK (PORT_BASE + 0x3aC) ++#define DFX_FIFO_RD_DATA (PORT_BASE + 0x3b0) + + #define DEFAULT_ITCT_HW 2048 /* reset value, not reprogrammed */ + #if (HISI_SAS_MAX_DEVICES > DEFAULT_ITCT_HW) +@@ -4547,6 +4560,243 @@ static const struct file_operations debugfs_phy_down_cnt_v3_hw_fops = { + .owner = THIS_MODULE, + }; + ++enum fifo_dump_mode_v3_hw { ++ FIFO_DUMP_FORVER = (1U << 0), ++ FIFO_DUMP_AFTER_TRIGGER = (1U << 1), ++ FIFO_DUMP_UNTILL_TRIGGER = (1U << 2), ++}; ++ ++enum fifo_trigger_mode_v3_hw { ++ FIFO_TRIGGER_EDGE = (1U << 0), ++ FIFO_TRIGGER_SAME_LEVEL = (1U << 1), ++ FIFO_TRIGGER_DIFF_LEVEL = (1U << 2), ++}; ++ ++static int debugfs_is_fifo_config_valid_v3_hw(struct hisi_sas_phy *phy) ++{ ++ struct hisi_hba *hisi_hba = phy->hisi_hba; ++ ++ if (phy->fifo.signal_sel > 0xf) { ++ dev_info(hisi_hba->dev, "Invalid signal select: %u\n", ++ phy->fifo.signal_sel); ++ return -EINVAL; ++ } ++ ++ switch (phy->fifo.dump_mode) { ++ case FIFO_DUMP_FORVER: ++ case FIFO_DUMP_AFTER_TRIGGER: ++ case FIFO_DUMP_UNTILL_TRIGGER: ++ break; ++ default: ++ dev_info(hisi_hba->dev, "Invalid dump mode: %u\n", ++ phy->fifo.dump_mode); ++ return -EINVAL; ++ } ++ ++ /* when FIFO_DUMP_FORVER, no need to check trigger_mode */ ++ if (phy->fifo.dump_mode == FIFO_DUMP_FORVER) ++ return 0; ++ ++ switch (phy->fifo.trigger_mode) { ++ case FIFO_TRIGGER_EDGE: ++ case FIFO_TRIGGER_SAME_LEVEL: ++ case FIFO_TRIGGER_DIFF_LEVEL: ++ break; ++ default: ++ dev_info(hisi_hba->dev, "Invalid trigger mode: %u\n", ++ phy->fifo.trigger_mode); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int debugfs_update_fifo_config_v3_hw(struct hisi_sas_phy *phy) ++{ ++ u32 trigger_mode = phy->fifo.trigger_mode; ++ u32 signal_sel = phy->fifo.signal_sel; ++ u32 dump_mode = phy->fifo.dump_mode; ++ struct hisi_hba *hisi_hba = phy->hisi_hba; ++ int phy_no = phy->sas_phy.id; ++ u32 reg_val; ++ int res; ++ ++ /* Check the validity of trace FIFO configuration */ ++ res = debugfs_is_fifo_config_valid_v3_hw(phy); ++ if (res) ++ return res; ++ ++ reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, DFX_FIFO_CTRL); ++ /* Disable trace FIFO before update configuration */ ++ reg_val |= DFX_FIFO_CTRL_DUMP_DISABLE_MSK; ++ ++ /* Update trace FIFO configuration */ ++ reg_val &= ~(DFX_FIFO_CTRL_DUMP_MODE_MSK | ++ DFX_FIFO_CTRL_SIGNAL_SEL_MSK | ++ DFX_FIFO_CTRL_TRIGGER_MODE_MSK); ++ ++ reg_val |= ((trigger_mode << DFX_FIFO_CTRL_TRIGGER_MODE_OFF) | ++ (dump_mode << DFX_FIFO_CTRL_DUMP_MODE_OFF) | ++ (signal_sel << DFX_FIFO_CTRL_SIGNAL_SEL_OFF)); ++ hisi_sas_phy_write32(hisi_hba, phy_no, DFX_FIFO_CTRL, reg_val); ++ ++ hisi_sas_phy_write32(hisi_hba, phy_no, DFX_FIFO_DUMP_MSK, ++ phy->fifo.dump_msk); ++ ++ hisi_sas_phy_write32(hisi_hba, phy_no, DFX_FIFO_TRIGGER, ++ phy->fifo.trigger); ++ ++ hisi_sas_phy_write32(hisi_hba, phy_no, DFX_FIFO_TRIGGER_MSK, ++ phy->fifo.trigger_msk); ++ ++ /* Enable trace FIFO after updated configuration */ ++ reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, DFX_FIFO_CTRL); ++ reg_val &= ~DFX_FIFO_CTRL_DUMP_DISABLE_MSK; ++ hisi_sas_phy_write32(hisi_hba, phy_no, DFX_FIFO_CTRL, reg_val); ++ ++ return 0; ++} ++ ++static ssize_t debugfs_fifo_update_cfg_v3_hw_write(struct file *filp, ++ const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct hisi_sas_phy *phy = filp->private_data; ++ bool update; ++ int val; ++ ++ val = kstrtobool_from_user(buf, count, &update); ++ if (val) ++ return val; ++ ++ if (update != 1) ++ return -EINVAL; ++ ++ val = debugfs_update_fifo_config_v3_hw(phy); ++ if (val) ++ return val; ++ ++ return count; ++} ++ ++static const struct file_operations debugfs_fifo_update_cfg_v3_hw_fops = { ++ .open = simple_open, ++ .write = debugfs_fifo_update_cfg_v3_hw_write, ++ .owner = THIS_MODULE, ++}; ++ ++static void debugfs_read_fifo_data_v3_hw(struct hisi_sas_phy *phy) ++{ ++ struct hisi_hba *hisi_hba = phy->hisi_hba; ++ u32 *buf = phy->fifo.rd_data; ++ int phy_no = phy->sas_phy.id; ++ u32 val; ++ int i; ++ ++ memset(buf, 0, sizeof(phy->fifo.rd_data)); ++ ++ /* Disable trace FIFO before read data */ ++ val = hisi_sas_phy_read32(hisi_hba, phy_no, DFX_FIFO_CTRL); ++ val |= DFX_FIFO_CTRL_DUMP_DISABLE_MSK; ++ hisi_sas_phy_write32(hisi_hba, phy_no, DFX_FIFO_CTRL, val); ++ ++ for (i = 0; i < HISI_SAS_FIFO_DATA_DW_SIZE; i++) { ++ val = hisi_sas_phy_read32(hisi_hba, phy_no, ++ DFX_FIFO_RD_DATA); ++ buf[i] = val; ++ } ++ ++ /* Enable trace FIFO after read data */ ++ val = hisi_sas_phy_read32(hisi_hba, phy_no, DFX_FIFO_CTRL); ++ val &= ~DFX_FIFO_CTRL_DUMP_DISABLE_MSK; ++ hisi_sas_phy_write32(hisi_hba, phy_no, DFX_FIFO_CTRL, val); ++} ++ ++static int debugfs_fifo_data_v3_hw_show(struct seq_file *s, void *p) ++{ ++ struct hisi_sas_phy *phy = s->private; ++ ++ debugfs_read_fifo_data_v3_hw(phy); ++ ++ debugfs_show_row_32_v3_hw(s, 0, HISI_SAS_FIFO_DATA_DW_SIZE * 4, ++ phy->fifo.rd_data); ++ ++ return 0; ++} ++DEFINE_SHOW_ATTRIBUTE(debugfs_fifo_data_v3_hw); ++ ++static void debugfs_fifo_init_v3_hw(struct hisi_hba *hisi_hba) ++{ ++ int phy_no; ++ ++ hisi_hba->debugfs_fifo_dentry = ++ debugfs_create_dir("fifo", hisi_hba->debugfs_dir); ++ ++ for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) { ++ struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; ++ struct dentry *port_dentry; ++ char name[256]; ++ u32 val; ++ ++ /* get default configuration for trace FIFO */ ++ val = hisi_sas_phy_read32(hisi_hba, phy_no, DFX_FIFO_CTRL); ++ val &= DFX_FIFO_CTRL_DUMP_MODE_MSK; ++ val >>= DFX_FIFO_CTRL_DUMP_MODE_OFF; ++ phy->fifo.dump_mode = val; ++ ++ val = hisi_sas_phy_read32(hisi_hba, phy_no, DFX_FIFO_CTRL); ++ val &= DFX_FIFO_CTRL_TRIGGER_MODE_MSK; ++ val >>= DFX_FIFO_CTRL_TRIGGER_MODE_OFF; ++ phy->fifo.trigger_mode = val; ++ ++ val = hisi_sas_phy_read32(hisi_hba, phy_no, DFX_FIFO_CTRL); ++ val &= DFX_FIFO_CTRL_SIGNAL_SEL_MSK; ++ val >>= DFX_FIFO_CTRL_SIGNAL_SEL_OFF; ++ phy->fifo.signal_sel = val; ++ ++ val = hisi_sas_phy_read32(hisi_hba, phy_no, DFX_FIFO_DUMP_MSK); ++ phy->fifo.dump_msk = val; ++ ++ val = hisi_sas_phy_read32(hisi_hba, phy_no, DFX_FIFO_TRIGGER); ++ phy->fifo.trigger = val; ++ val = hisi_sas_phy_read32(hisi_hba, phy_no, DFX_FIFO_TRIGGER_MSK); ++ phy->fifo.trigger_msk = val; ++ ++ snprintf(name, 256, "%d", phy_no); ++ port_dentry = debugfs_create_dir(name, ++ hisi_hba->debugfs_fifo_dentry); ++ ++ debugfs_create_file("update_config", 0200, port_dentry, phy, ++ &debugfs_fifo_update_cfg_v3_hw_fops); ++ ++ debugfs_create_file("signal_sel", 0600, port_dentry, ++ &phy->fifo.signal_sel, ++ &debugfs_v3_hw_fops); ++ ++ debugfs_create_file("dump_msk", 0600, port_dentry, ++ &phy->fifo.dump_msk, ++ &debugfs_v3_hw_fops); ++ ++ debugfs_create_file("dump_mode", 0600, port_dentry, ++ &phy->fifo.dump_mode, ++ &debugfs_v3_hw_fops); ++ ++ debugfs_create_file("trigger_mode", 0600, port_dentry, ++ &phy->fifo.trigger_mode, ++ &debugfs_v3_hw_fops); ++ ++ debugfs_create_file("trigger", 0600, port_dentry, ++ &phy->fifo.trigger, ++ &debugfs_v3_hw_fops); ++ ++ debugfs_create_file("trigger_msk", 0600, port_dentry, ++ &phy->fifo.trigger_msk, ++ &debugfs_v3_hw_fops); ++ ++ debugfs_create_file("fifo_data", 0400, port_dentry, phy, ++ &debugfs_fifo_data_v3_hw_fops); ++ } ++} ++ + static void debugfs_work_handler_v3_hw(struct work_struct *work) + { + struct hisi_hba *hisi_hba = +@@ -4784,6 +5034,7 @@ static void debugfs_init_v3_hw(struct hisi_hba *hisi_hba) + debugfs_create_dir("dump", hisi_hba->debugfs_dir); + + debugfs_phy_down_cnt_init_v3_hw(hisi_hba); ++ debugfs_fifo_init_v3_hw(hisi_hba); + + for (i = 0; i < hisi_sas_debugfs_dump_count; i++) { + if (debugfs_alloc_v3_hw(hisi_hba, i)) { +-- +2.27.0 + diff --git a/patches/0488-scsi-hisi_sas-Print-SAS-address-for-v3-hw-erroneous-.patch b/patches/0488-scsi-hisi_sas-Print-SAS-address-for-v3-hw-erroneous-.patch new file mode 100644 index 00000000..44b1605c --- /dev/null +++ b/patches/0488-scsi-hisi_sas-Print-SAS-address-for-v3-hw-erroneous-.patch @@ -0,0 +1,57 @@ +From 822d9bbd5b385690d8fdc5ecee354ccf165cfe44 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Tue, 3 Aug 2021 14:47:54 +0800 +Subject: [PATCH 170/256] scsi: hisi_sas: Print SAS address for v3 hw erroneous + completion print + +mainline inclusion +from mainline-v5.13-rc1 +commit 4da0b7f6fac331f2d2336df3ca88a335f545b4dc +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4da0b7f6fac331f2d2336df3ca88a335f545b4dc + +---------------------------------------------------------------------- + +To help debugging efforts, print the device SAS address for v3 hw erroneous +completion log. + +Here is an example print: + +hisi_sas_v3_hw 0000:b4:02.0: erroneous completion iptt=2193 task=000000002b0c13f8 dev id=17 addr=570fd45f9d17b001 + +Link: https://lore.kernel.org/r/1617709711-195853-3-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 8ce0ff71aafc..3e2414256bfa 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -2489,9 +2489,9 @@ static void slot_complete_v3_hw(struct hisi_hba *hisi_hba, + + set_aborted_iptt(hisi_hba, slot); + slot_err_v3_hw(hisi_hba, task, slot); +- dev_info(dev, "erroneous completion iptt=%d task=%pK dev id=%d sas_addr=0x%llx CQ hdr: 0x%x 0x%x 0x%x 0x%x Error info: 0x%x 0x%x 0x%x 0x%x\n", ++ dev_info(dev, "erroneous completion iptt=%d task=%pK dev id=%d addr%016llx sas_addr=0x%llx CQ hdr: 0x%x 0x%x 0x%x 0x%x Error info: 0x%x 0x%x 0x%x 0x%x\n", + slot->idx, task, sas_dev->device_id, +- itct->sas_addr, ++ SAS_ADDR(device->sas_addr), itct->sas_addr, + dw0, dw1, + complete_hdr->act, dw3, + error_info[0], error_info[1], +-- +2.27.0 + diff --git a/patches/0489-scsi-hisi_sas-Call-sas_unregister_ha-to-roll-back-if.patch b/patches/0489-scsi-hisi_sas-Call-sas_unregister_ha-to-roll-back-if.patch new file mode 100644 index 00000000..ac1c02eb --- /dev/null +++ b/patches/0489-scsi-hisi_sas-Call-sas_unregister_ha-to-roll-back-if.patch @@ -0,0 +1,78 @@ +From c85359ee99c55652e0f5d146c3a9466c39f6dd9e Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Tue, 3 Aug 2021 14:47:55 +0800 +Subject: [PATCH 171/256] scsi: hisi_sas: Call sas_unregister_ha() to roll back + if .hw_init() fails + +mainline inclusion +from mainline-v5.13-rc1 +commit f467666504bf0c7eae95b929d0c86f77ff9b4356 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f467666504bf0c7eae95b929d0c86f77ff9b4356 + +---------------------------------------------------------------------- + +Function sas_unregister_ha() needs to be called to roll back if +hisi_hba->hw->hw_init() fails in function hisi_sas_probe() or +hisi_sas_v3_probe(). Make that change. + +Link: https://lore.kernel.org/r/1617709711-195853-4-git-send-email-john.garry@huawei.com +Signed-off-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 4 +++- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 4 +++- + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index fc36388d6f04..6f1108e54e8a 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -2769,12 +2769,14 @@ int hisi_sas_probe(struct platform_device *pdev, + + rc = hisi_hba->hw->hw_init(hisi_hba); + if (rc) +- goto err_out_register_ha; ++ goto err_out_hw_init; + + scsi_scan_host(shost); + + return 0; + ++err_out_hw_init: ++ sas_unregister_ha(sha); + err_out_register_ha: + scsi_remove_host(shost); + err_out: +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 3e2414256bfa..de5f89ebef53 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -5156,7 +5156,7 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) + + rc = hisi_sas_v3_init(hisi_hba); + if (rc) +- goto err_out_register_ha; ++ goto err_out_hw_init; + + scsi_scan_host(shost); + +@@ -5173,6 +5173,8 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) + + return 0; + ++err_out_hw_init: ++ sas_unregister_ha(sha); + err_out_register_ha: + scsi_remove_host(shost); + err_out_free_irq_vectors: +-- +2.27.0 + diff --git a/patches/0490-scsi-hisi_sas-Directly-snapshot-registers-when-execu.patch b/patches/0490-scsi-hisi_sas-Directly-snapshot-registers-when-execu.patch new file mode 100644 index 00000000..36c45673 --- /dev/null +++ b/patches/0490-scsi-hisi_sas-Directly-snapshot-registers-when-execu.patch @@ -0,0 +1,175 @@ +From d011f62e4b5d7845e7739e7e5c28eb783db47161 Mon Sep 17 00:00:00 2001 +From: Jianqin Xie +Date: Tue, 3 Aug 2021 14:47:56 +0800 +Subject: [PATCH 172/256] scsi: hisi_sas: Directly snapshot registers when + executing a reset + +mainline inclusion +from mainline-v5.13-rc1 +commit 2c74cb1f9222ebfcc204c02018275ad167d25212 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2c74cb1f9222ebfcc204c02018275ad167d25212 + +---------------------------------------------------------------------- + +The debugfs snapshot should be executed before the reset occurs to ensure +that the register contents are saved properly. + +As such, it is incorrect to queue the debugfs dump when running a reset as +the reset will occur prior to the snapshot work item is handler. + +Therefore, directly snapshot registers in the reset work handler. + +Link: https://lore.kernel.org/r/1617709711-195853-5-git-send-email-john.garry@huawei.com +Signed-off-by: Jianqin Xie +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas.h | 1 + + drivers/scsi/hisi_sas/hisi_sas_main.c | 25 +++++++++++++++++++----- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 27 ++++++++++++++------------ + 3 files changed, 36 insertions(+), 17 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index bf36130b8e1c..d42a7782d525 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -377,6 +377,7 @@ struct hisi_sas_hw { + const struct cpumask *(*get_managed_irq_aff)(struct hisi_hba + *hisi_hba, int queue); + void (*debugfs_work_handler)(struct work_struct *work); ++ void (*debugfs_snapshot_regs)(struct hisi_hba *hisi_hba); + int complete_hdr_size; + struct scsi_host_template *sht; + }; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 6f1108e54e8a..c2336477a143 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1624,12 +1624,8 @@ void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba) + } + EXPORT_SYMBOL_GPL(hisi_sas_controller_reset_done); + +-static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba) ++static int hisi_sas_controller_prereset(struct hisi_hba *hisi_hba) + { +- struct device *dev = hisi_hba->dev; +- struct Scsi_Host *shost = hisi_hba->shost; +- int rc; +- + if (!hisi_hba->hw->soft_reset) + return -EINVAL; + +@@ -1639,6 +1635,18 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba) + if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct) + hisi_hba->hw->debugfs_work_handler(&hisi_hba->debugfs_work); + ++ if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct) ++ hisi_hba->hw->debugfs_snapshot_regs(hisi_hba); ++ ++ return 0; ++} ++ ++static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba) ++{ ++ struct device *dev = hisi_hba->dev; ++ struct Scsi_Host *shost = hisi_hba->shost; ++ int rc; ++ + dev_info(dev, "controller resetting...\n"); + hisi_sas_controller_reset_prepare(hisi_hba); + +@@ -2550,6 +2558,9 @@ void hisi_sas_rst_work_handler(struct work_struct *work) + struct hisi_hba *hisi_hba = + container_of(work, struct hisi_hba, rst_work); + ++ if (hisi_sas_controller_prereset(hisi_hba)) ++ return; ++ + hisi_sas_controller_reset(hisi_hba); + } + EXPORT_SYMBOL_GPL(hisi_sas_rst_work_handler); +@@ -2559,8 +2570,12 @@ void hisi_sas_sync_rst_work_handler(struct work_struct *work) + struct hisi_sas_rst *rst = + container_of(work, struct hisi_sas_rst, work); + ++ if (hisi_sas_controller_prereset(rst->hisi_hba)) ++ goto rst_complete; ++ + if (!hisi_sas_controller_reset(rst->hisi_hba)) + rst->done = true; ++rst_complete: + complete(rst->completion); + } + EXPORT_SYMBOL_GPL(hisi_sas_sync_rst_work_handler); +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index de5f89ebef53..8b0638520827 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -582,6 +582,7 @@ MODULE_PARM_DESC(user_ctl_irq, "Enable user control irq affinity:\n" + "default is auto-control irq affinity"); + + static void debugfs_work_handler_v3_hw(struct work_struct *work); ++static void debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba); + + static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off) + { +@@ -3579,6 +3580,7 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = { + .wait_cmds_complete_timeout = wait_cmds_complete_timeout_v3_hw, + .get_managed_irq_aff = get_managed_irq_aff_v3_hw, + .debugfs_work_handler = debugfs_work_handler_v3_hw, ++ .debugfs_snapshot_regs = debugfs_snapshot_regs_v3_hw, + }; + + static struct Scsi_Host * +@@ -4065,6 +4067,19 @@ static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba) + + static void debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba) + { ++ int debugfs_dump_index = hisi_hba->debugfs_dump_index; ++ struct device *dev = hisi_hba->dev; ++ u64 timestamp = local_clock(); ++ ++ if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) { ++ dev_warn(dev, "dump count exceeded!\n"); ++ return; ++ } ++ ++ do_div(timestamp, NSEC_PER_MSEC); ++ hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp; ++ hisi_hba->debugfs_dump_index++; ++ + debugfs_snapshot_prepare_v3_hw(hisi_hba); + + debugfs_snapshot_global_reg_v3_hw(hisi_hba); +@@ -4801,20 +4816,8 @@ static void debugfs_work_handler_v3_hw(struct work_struct *work) + { + struct hisi_hba *hisi_hba = + container_of(work, struct hisi_hba, debugfs_work); +- int debugfs_dump_index = hisi_hba->debugfs_dump_index; +- struct device *dev = hisi_hba->dev; +- u64 timestamp = local_clock(); +- +- if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) { +- dev_warn(dev, "dump count exceeded!\n"); +- return; +- } +- +- do_div(timestamp, NSEC_PER_MSEC); +- hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp; + + debugfs_snapshot_regs_v3_hw(hisi_hba); +- hisi_hba->debugfs_dump_index++; + } + + static void debugfs_release_v3_hw(struct hisi_hba *hisi_hba, int dump_index) +-- +2.27.0 + diff --git a/patches/0491-scsi-hisi_sas-Warn-in-v3-hw-channel-interrupt-handle.patch b/patches/0491-scsi-hisi_sas-Warn-in-v3-hw-channel-interrupt-handle.patch new file mode 100644 index 00000000..fad5550a --- /dev/null +++ b/patches/0491-scsi-hisi_sas-Warn-in-v3-hw-channel-interrupt-handle.patch @@ -0,0 +1,66 @@ +From e3153e408ca97d818e557755c77776e05073d3ce Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Tue, 3 Aug 2021 14:47:57 +0800 +Subject: [PATCH 173/256] scsi: hisi_sas: Warn in v3 hw channel interrupt + handler when status reg cleared + +mainline inclusion +from mainline-v5.13-rc1 +commit 2d31cb20a3cd611a9a544f9586eb3908ee2085cf +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2d31cb20a3cd611a9a544f9586eb3908ee2085cf + +---------------------------------------------------------------------- + +If a channel interrupt occurs without any status bit set, the handler will +return directly. However, if such redundant interrupts are received, it's +better to check what happen, so add logs for this. + +Link: https://lore.kernel.org/r/1617709711-195853-6-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: Yihang Li +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 8b0638520827..845666de1842 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -1873,8 +1873,11 @@ static void handle_chl_int1_v3_hw(struct hisi_hba *hisi_hba, int phy_no) + int i; + + irq_value &= ~irq_msk; +- if (!irq_value) ++ if (!irq_value) { ++ dev_warn(dev, "phy%d channel int 1 received with status bits cleared\n", ++ phy_no); + return; ++ } + + for (i = 0; i < ARRAY_SIZE(port_axi_error); i++) { + const struct hisi_sas_hw_error *error = &port_axi_error[i]; +@@ -1902,8 +1905,11 @@ static void handle_chl_int2_v3_hw(struct hisi_hba *hisi_hba, int phy_no) + BIT(CHL_INT2_RX_INVLD_DW_OFF); + + irq_value &= ~irq_msk; +- if (!irq_value) ++ if (!irq_value) { ++ dev_warn(dev, "phy%d channel int 2 received with status bits cleared\n", ++ phy_no); + return; ++ } + + if (irq_value & BIT(CHL_INT2_SL_IDAF_TOUT_CONF_OFF)) { + dev_warn(dev, "phy%d identify timeout\n", phy_no); +-- +2.27.0 + diff --git a/patches/0492-scsi-hisi_sas-Print-SATA-device-SAS-address-for-soft.patch b/patches/0492-scsi-hisi_sas-Print-SATA-device-SAS-address-for-soft.patch new file mode 100644 index 00000000..7fa20e7d --- /dev/null +++ b/patches/0492-scsi-hisi_sas-Print-SATA-device-SAS-address-for-soft.patch @@ -0,0 +1,53 @@ +From 8053f57940d6f526547a32da78df7a47ebaf32a7 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Tue, 3 Aug 2021 14:47:58 +0800 +Subject: [PATCH 174/256] scsi: hisi_sas: Print SATA device SAS address for + soft reset failure + +mainline inclusion +from mainline-v5.13-rc1 +commit f4df167ad5a2274c12680ba3e7d816d32d1fc375 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f4df167ad5a2274c12680ba3e7d816d32d1fc375 + +---------------------------------------------------------------------- + +Add (pseudo) SAS address for ATA software reset failure log to assist in +debugging. + +Link: https://lore.kernel.org/r/1617709711-195853-7-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index c2336477a143..41eaebe635f2 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1381,10 +1381,12 @@ static int hisi_sas_softreset_ata_disk(struct domain_device *device) + rc = hisi_sas_exec_internal_tmf_task(device, &fis, + s, NULL); + if (rc != TMF_RESP_FUNC_COMPLETE) +- dev_err(dev, "ata disk de-reset failed\n"); ++ dev_err(dev, "ata disk %016llx de-reset failed\n", ++ SAS_ADDR(device->sas_addr)); + } + } else { +- dev_err(dev, "ata disk reset failed\n"); ++ dev_err(dev, "ata disk %016llx reset failed\n", ++ SAS_ADDR(device->sas_addr)); + } + + if (rc == TMF_RESP_FUNC_COMPLETE) +-- +2.27.0 + diff --git a/patches/0493-scsi-hisi_sas-Put-a-limit-of-link-reset-retries.patch b/patches/0493-scsi-hisi_sas-Put-a-limit-of-link-reset-retries.patch new file mode 100644 index 00000000..81aa1b2e --- /dev/null +++ b/patches/0493-scsi-hisi_sas-Put-a-limit-of-link-reset-retries.patch @@ -0,0 +1,90 @@ +From a59b3e69ff539a0a7ac689ee6487d1bbeeaadc0f Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Tue, 3 Aug 2021 14:48:01 +0800 +Subject: [PATCH 175/256] scsi: hisi_sas: Put a limit of link reset retries + +mainline inclusion +from mainline-v5.14-rc1 +commit 366da0da1f5fe4e7e702f5864a557e57f485431f +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F82P + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=366da0da1f5fe4e7e702f5864a557e57f485431f + +---------------------------------------------------------------------- + +If an OOB event is received but the phy still fails to come up, a link +reset will be issued repeatedly at an interval of 20s until the phy comes +up. + +Set a limit for link reset issue retries to avoid printing the timeout +message endlessly. + +Link: https://lore.kernel.org/r/1623058179-80434-2-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas.h | 1 + + drivers/scsi/hisi_sas/hisi_sas_main.c | 15 +++++++++++++-- + 2 files changed, 14 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index d42a7782d525..1fce72c2244f 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -204,6 +204,7 @@ struct hisi_sas_phy { + enum sas_linkrate maximum_linkrate; + u32 code_error_count; + int enable; ++ int wait_phyup_cnt; + atomic_t down_cnt; + + /* Trace FIFO */ +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 41eaebe635f2..eba87f528d19 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -876,6 +876,7 @@ static void hisi_sas_phyup_work(struct work_struct *work) + struct asd_sas_phy *sas_phy = &phy->sas_phy; + int phy_no = sas_phy->id; + ++ phy->wait_phyup_cnt = 0; + if (phy->identify.target_port_protocols == SAS_PROTOCOL_SSP) + hisi_hba->hw->sl_notify_ssp(hisi_hba, phy_no); + hisi_sas_bytes_dmaed(hisi_hba, phy_no, GFP_KERNEL); +@@ -918,6 +919,8 @@ static void hisi_sas_wait_phyup_timedout(struct timer_list *t) + hisi_sas_notify_phy_event(phy, HISI_PHYE_LINK_RESET); + } + ++#define HISI_SAS_WAIT_PHYUP_RETRIES 10 ++ + void hisi_sas_phy_oob_ready(struct hisi_hba *hisi_hba, int phy_no) + { + struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; +@@ -928,8 +931,16 @@ void hisi_sas_phy_oob_ready(struct hisi_hba *hisi_hba, int phy_no) + return; + + if (!timer_pending(&phy->timer)) { +- phy->timer.expires = jiffies + HISI_SAS_WAIT_PHYUP_TIMEOUT * HZ; +- add_timer(&phy->timer); ++ if (phy->wait_phyup_cnt < HISI_SAS_WAIT_PHYUP_RETRIES) { ++ phy->wait_phyup_cnt++; ++ phy->timer.expires = jiffies + ++ HISI_SAS_WAIT_PHYUP_TIMEOUT * HZ; ++ add_timer(&phy->timer); ++ } else { ++ dev_warn(dev, "phy%d failed to come up %d times, giving up\n", ++ phy_no, phy->wait_phyup_cnt); ++ phy->wait_phyup_cnt = 0; ++ } + } + } + EXPORT_SYMBOL_GPL(hisi_sas_phy_oob_ready); +-- +2.27.0 + diff --git a/patches/0494-scsi-hisi_sas-Run-I_T-nexus-resets-in-parallel-for-c.patch b/patches/0494-scsi-hisi_sas-Run-I_T-nexus-resets-in-parallel-for-c.patch new file mode 100644 index 00000000..55899f3f --- /dev/null +++ b/patches/0494-scsi-hisi_sas-Run-I_T-nexus-resets-in-parallel-for-c.patch @@ -0,0 +1,98 @@ +From b174c8fbafb6e722f87f47161afcc3d093ec735d Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Tue, 3 Aug 2021 14:48:02 +0800 +Subject: [PATCH 176/256] scsi: hisi_sas: Run I_T nexus resets in parallel for + clear nexus reset + +mainline inclusion +from mainline-v5.14-rc1 +commit 0f757339919d31533aeadbbfd62f2dd4a49e851f +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F82P + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0f757339919d31533aeadbbfd62f2dd4a49e851f + +---------------------------------------------------------------------- + +For a clear nexus reset operation, the I_T nexus resets are executed +serially for each device. For devices attached through an expander, this +may take 2s per device; so, in total, could take a long time. + +Reduce the total time by running the I_T nexus resets in parallel through +async operations. + +Link: https://lore.kernel.org/r/1623058179-80434-3-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas.h | 1 + + drivers/scsi/hisi_sas/hisi_sas_main.c | 23 +++++++++++++++++------ + 2 files changed, 18 insertions(+), 6 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 1fce72c2244f..2bfbfeb08b22 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -13,6 +13,7 @@ + #define _HISI_SAS_H_ + + #include ++#include + #include + #include + #include +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index eba87f528d19..e9d05527bd33 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1959,12 +1959,24 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun) + return rc; + } + ++static void hisi_sas_async_I_T_nexus_reset(void *data, async_cookie_t cookie) ++{ ++ struct domain_device *device = data; ++ struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); ++ int rc; ++ ++ rc = hisi_sas_debug_I_T_nexus_reset(device); ++ if (rc != TMF_RESP_FUNC_COMPLETE) ++ dev_info(hisi_hba->dev, "I_T_nexus reset fail for dev:%016llx rc=%d\n", ++ SAS_ADDR(device->sas_addr), rc); ++} ++ + static int hisi_sas_clear_nexus_ha(struct sas_ha_struct *sas_ha) + { + struct hisi_hba *hisi_hba = sas_ha->lldd_ha; +- struct device *dev = hisi_hba->dev; + HISI_SAS_DECLARE_RST_WORK_ON_STACK(r); +- int rc, i; ++ ASYNC_DOMAIN_EXCLUSIVE(async); ++ int i; + + queue_work(hisi_hba->wq, &r.work); + wait_for_completion(r.completion); +@@ -1979,12 +1991,11 @@ static int hisi_sas_clear_nexus_ha(struct sas_ha_struct *sas_ha) + DEV_IS_EXPANDER(device->dev_type)) + continue; + +- rc = hisi_sas_debug_I_T_nexus_reset(device); +- if (rc != TMF_RESP_FUNC_COMPLETE) +- dev_info(dev, "clear nexus ha: for device[%d] rc=%d\n", +- sas_dev->device_id, rc); ++ async_schedule_domain(hisi_sas_async_I_T_nexus_reset, ++ device, &async); + } + ++ async_synchronize_full_domain(&async); + hisi_sas_release_tasks(hisi_hba); + + return TMF_RESP_FUNC_COMPLETE; +-- +2.27.0 + diff --git a/patches/0495-scsi-hisi_sas-Include-HZ-in-timer-macros.patch b/patches/0495-scsi-hisi_sas-Include-HZ-in-timer-macros.patch new file mode 100644 index 00000000..d014e561 --- /dev/null +++ b/patches/0495-scsi-hisi_sas-Include-HZ-in-timer-macros.patch @@ -0,0 +1,140 @@ +From 889c3cb3e3e411501e85aff44198a51f5b4c697b Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Tue, 3 Aug 2021 14:48:03 +0800 +Subject: [PATCH 177/256] scsi: hisi_sas: Include HZ in timer macros + +mainline inclusion +from mainline-v5.14-rc1 +commit 2f12a499511f40c268d6dfa4bf7fbe2344d2e6d3 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F82P + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2f12a499511f40c268d6dfa4bf7fbe2344d2e6d3 + +---------------------------------------------------------------------- + +Include HZ in timer macros to make the code more concise. + +Link: https://lore.kernel.org/r/1623058179-80434-4-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas.h + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas.h | 2 +- + drivers/scsi/hisi_sas/hisi_sas_main.c | 16 +++++++++------- + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2 +- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 2 +- + 4 files changed, 12 insertions(+), 10 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 2bfbfeb08b22..aa3ea25c25dc 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -103,7 +103,7 @@ + #define HISI_SAS_PROT_MASK (HISI_SAS_DIF_PROT_MASK | HISI_SAS_DIX_PROT_MASK) + + #define HISI_SAS_WAIT_PHYUP_TIMEOUT (30 * HZ) +-#define CLEAR_ITCT_TIMEOUT 20 ++#define HISI_SAS_CLEAR_ITCT_TIMEOUT (20 * HZ) + + struct hisi_hba; + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index e9d05527bd33..da87e614e946 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -934,7 +934,7 @@ void hisi_sas_phy_oob_ready(struct hisi_hba *hisi_hba, int phy_no) + if (phy->wait_phyup_cnt < HISI_SAS_WAIT_PHYUP_RETRIES) { + phy->wait_phyup_cnt++; + phy->timer.expires = jiffies + +- HISI_SAS_WAIT_PHYUP_TIMEOUT * HZ; ++ HISI_SAS_WAIT_PHYUP_TIMEOUT; + add_timer(&phy->timer); + } else { + dev_warn(dev, "phy%d failed to come up %d times, giving up\n", +@@ -1232,9 +1232,9 @@ static void hisi_sas_tmf_timedout(struct timer_list *t) + complete(&task->slow_task->completion); + } + +-#define TASK_TIMEOUT 20 +-#define TASK_RETRY 3 +-#define INTERNAL_ABORT_TIMEOUT 6 ++#define TASK_TIMEOUT (20 * HZ) ++#define TASK_RETRY 3 ++#define INTERNAL_ABORT_TIMEOUT (6 * HZ) + static int hisi_sas_exec_internal_tmf_task(struct domain_device *device, + void *parameter, u32 para_len, + struct hisi_sas_tmf_task *tmf) +@@ -1262,7 +1262,7 @@ static int hisi_sas_exec_internal_tmf_task(struct domain_device *device, + task->task_done = hisi_sas_task_done; + + task->slow_task->timer.function = hisi_sas_tmf_timedout; +- task->slow_task->timer.expires = jiffies + TASK_TIMEOUT * HZ; ++ task->slow_task->timer.expires = jiffies + TASK_TIMEOUT; + add_timer(&task->slow_task->timer); + + res = hisi_sas_task_exec(task, GFP_KERNEL, 1, tmf); +@@ -1830,6 +1830,8 @@ static int hisi_sas_clear_aca(struct domain_device *device, u8 *lun) + return rc; + } + ++#define I_T_NEXUS_RESET_PHYUP_TIMEOUT (2 * HZ) ++ + static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device) + { + struct sas_phy *local_phy = sas_get_local_phy(device); +@@ -1865,7 +1867,7 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device) + container_of(sas_phy, struct hisi_sas_phy, sas_phy); + /* Wait for I_T reset complete, time out after 2s */ + int ret = wait_for_completion_timeout(&phyreset, +- HISI_SAS_WAIT_PHYUP_TIMEOUT); ++ I_T_NEXUS_RESET_PHYUP_TIMEOUT); + unsigned long flags; + + spin_lock_irqsave(&phy->lock, flags); +@@ -2153,7 +2155,7 @@ _hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, + task->task_proto = device->tproto; + task->task_done = hisi_sas_task_done; + task->slow_task->timer.function = hisi_sas_tmf_timedout; +- task->slow_task->timer.expires = jiffies + INTERNAL_ABORT_TIMEOUT * HZ; ++ task->slow_task->timer.expires = jiffies + INTERNAL_ABORT_TIMEOUT; + add_timer(&task->slow_task->timer); + + res = hisi_sas_internal_abort_task_exec(hisi_hba, sas_dev->device_id, +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +index abacd8a5369f..d4a2db76b048 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -1000,7 +1000,7 @@ static int clear_itct_v2_hw(struct hisi_hba *hisi_hba, + reg_val = ITCT_CLR_EN_MSK | (dev_id & ITCT_DEV_MSK); + hisi_sas_write32(hisi_hba, ITCT_CLR, reg_val); + if (!wait_for_completion_timeout(sas_dev->completion, +- CLEAR_ITCT_TIMEOUT * HZ)) { ++ HISI_SAS_CLEAR_ITCT_TIMEOUT)) { + dev_warn(dev, "failed to clear ITCT\n"); + return -ETIMEDOUT; + } +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 845666de1842..c5d230e05ac4 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -934,7 +934,7 @@ static int clear_itct_v3_hw(struct hisi_hba *hisi_hba, + hisi_sas_write32(hisi_hba, ITCT_CLR, reg_val); + + if (!wait_for_completion_timeout(sas_dev->completion, +- CLEAR_ITCT_TIMEOUT * HZ)) { ++ HISI_SAS_CLEAR_ITCT_TIMEOUT)) { + dev_warn(dev, "failed to clear ITCT\n"); + return -ETIMEDOUT; + } +-- +2.27.0 + diff --git a/patches/0496-scsi-hisi_sas-Reset-controller-for-internal-abort-ti.patch b/patches/0496-scsi-hisi_sas-Reset-controller-for-internal-abort-ti.patch new file mode 100644 index 00000000..a6af5307 --- /dev/null +++ b/patches/0496-scsi-hisi_sas-Reset-controller-for-internal-abort-ti.patch @@ -0,0 +1,194 @@ +From ca3cb7653f5070e3a721f69cac0fd1819534afdc Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Tue, 3 Aug 2021 14:48:04 +0800 +Subject: [PATCH 178/256] scsi: hisi_sas: Reset controller for internal abort + timeout + +mainline inclusion +from mainline-v5.14-rc1 +commit 63ece9eb350312ee33327269480482dfac8555db +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F82P + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=63ece9eb350312ee33327269480482dfac8555db + +---------------------------------------------------------------------- + +If an internal task abort timeout occurs, the controller has developed a +fault, and needs to be reset to be recovered. However if a timeout occurs +during SCSI error handling, issuing a controller reset immediately may +conflict with the error handling. + +To handle internal abort in these two scenarios, only queue the reset when +not in an error handling function. In the case of a timeout during error +handling, do nothing and rely on the inevitable ha nexus reset to reset the +controller. + +Link: https://lore.kernel.org/r/1623058179-80434-5-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 45 ++++++++++++++++++--------- + 1 file changed, 30 insertions(+), 15 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index da87e614e946..cd84b5b076cb 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -20,7 +20,7 @@ static int hisi_sas_debug_issue_ssp_tmf(struct domain_device *device, + static int + hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, + struct domain_device *device, +- int abort_flag, int tag); ++ int abort_flag, int tag, bool rst_to_recover); + static int hisi_sas_softreset_ata_disk(struct domain_device *device); + static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func, + void *funcdata); +@@ -1102,7 +1102,7 @@ static void hisi_sas_dev_gone(struct domain_device *device) + down(&hisi_hba->sem); + if (!test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) { + rc0 = hisi_sas_internal_task_abort(hisi_hba, device, +- HISI_SAS_INT_ABT_DEV, 0); ++ HISI_SAS_INT_ABT_DEV, 0, true); + + hisi_sas_dereg_device(hisi_hba, device); + if (!list_empty(&sas_dev->list)) { +@@ -1569,7 +1569,8 @@ static void hisi_sas_terminate_stp_reject(struct hisi_hba *hisi_hba) + continue; + + rc = hisi_sas_internal_task_abort(hisi_hba, device, +- HISI_SAS_INT_ABT_DEV, 0); ++ HISI_SAS_INT_ABT_DEV, 0, ++ false); + if (rc < 0) + dev_err(dev, "STP reject: abort dev failed %d\n", rc); + } +@@ -1729,7 +1730,8 @@ static int hisi_sas_abort_task(struct sas_task *task) + &tmf_task); + + rc2 = hisi_sas_internal_task_abort(hisi_hba, device, +- HISI_SAS_INT_ABT_CMD, tag); ++ HISI_SAS_INT_ABT_CMD, tag, ++ false); + if (rc2 < 0) { + dev_err(dev, "abort task: internal abort (%d)\n", rc2); + return TMF_RESP_FUNC_FAILED; +@@ -1752,7 +1754,8 @@ static int hisi_sas_abort_task(struct sas_task *task) + struct ata_queued_cmd *qc = task->uldd_task; + + rc = hisi_sas_internal_task_abort(hisi_hba, device, +- HISI_SAS_INT_ABT_DEV, 0); ++ HISI_SAS_INT_ABT_DEV, ++ 0, false); + if (rc < 0) { + dev_err(dev, "abort task: internal abort failed\n"); + goto out; +@@ -1777,7 +1780,8 @@ static int hisi_sas_abort_task(struct sas_task *task) + struct hisi_sas_cq *cq = &hisi_hba->cq[slot->dlvry_queue]; + + rc = hisi_sas_internal_task_abort(hisi_hba, device, +- HISI_SAS_INT_ABT_CMD, tag); ++ HISI_SAS_INT_ABT_CMD, tag, ++ false); + if (((rc < 0) || (rc == TMF_RESP_FUNC_FAILED)) && + task->lldd_task) { + /* +@@ -1803,7 +1807,7 @@ static int hisi_sas_abort_task_set(struct domain_device *device, u8 *lun) + int rc; + + rc = hisi_sas_internal_task_abort(hisi_hba, device, +- HISI_SAS_INT_ABT_DEV, 0); ++ HISI_SAS_INT_ABT_DEV, 0, false); + if (rc < 0) { + dev_err(dev, "abort task set: internal abort rc=%d\n", rc); + return TMF_RESP_FUNC_FAILED; +@@ -1899,7 +1903,7 @@ static int hisi_sas_I_T_nexus_reset(struct domain_device *device) + sas_dev->dev_status = HISI_SAS_DEV_NORMAL; + + rc = hisi_sas_internal_task_abort(hisi_hba, device, +- HISI_SAS_INT_ABT_DEV, 0); ++ HISI_SAS_INT_ABT_DEV, 0, false); + if (rc < 0) { + dev_err(dev, "I_T nexus reset: internal abort (%d)\n", rc); + return TMF_RESP_FUNC_FAILED; +@@ -1930,7 +1934,7 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun) + + /* Clear internal IO and then lu reset */ + rc = hisi_sas_internal_task_abort(hisi_hba, device, +- HISI_SAS_INT_ABT_DEV, 0); ++ HISI_SAS_INT_ABT_DEV, 0, false); + if (rc < 0) { + dev_err(dev, "lu_reset: internal abort failed\n"); + goto out; +@@ -2127,11 +2131,14 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, + * @tag: tag of IO to be aborted (only relevant to single + * IO mode) + * @dq: delivery queue for this internal abort command ++ * @rst_to_recover: If rst_to_recover set, queue a controller ++ * reset if an internal abort times out. + */ + static int + _hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, +- struct domain_device *device, +- int abort_flag, int tag, struct hisi_sas_dq *dq) ++ struct domain_device *device, int abort_flag, ++ int tag, struct hisi_sas_dq *dq, ++ bool rst_to_recover) + { + struct sas_task *task; + struct hisi_sas_device *sas_dev = device->lldd_dev; +@@ -2187,7 +2194,13 @@ _hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, + synchronize_irq(cq->irq_no); + slot->task = NULL; + } +- dev_err(dev, "internal task abort: timeout and not done.\n"); ++ ++ if (rst_to_recover) { ++ dev_err(dev, "internal task abort: timeout and not done. Queuing reset.\n"); ++ queue_work(hisi_hba->wq, &hisi_hba->rst_work); ++ } else { ++ dev_err(dev, "internal task abort: timeout and not done.\n"); ++ } + + res = -EIO; + goto exit; +@@ -2220,7 +2233,7 @@ _hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, + static int + hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, + struct domain_device *device, +- int abort_flag, int tag) ++ int abort_flag, int tag, bool rst_to_recover) + { + struct hisi_sas_slot *slot; + struct device *dev = hisi_hba->dev; +@@ -2232,7 +2245,8 @@ hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, + slot = &hisi_hba->slot_info[tag]; + dq = &hisi_hba->dq[slot->dlvry_queue]; + return _hisi_sas_internal_task_abort(hisi_hba, device, +- abort_flag, tag, dq); ++ abort_flag, tag, dq, ++ rst_to_recover); + case HISI_SAS_INT_ABT_DEV: + for (i = 0; i < hisi_hba->nvecs; i++) { + struct hisi_sas_cq *cq = &hisi_hba->cq[i]; +@@ -2250,7 +2264,8 @@ hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, + continue; + dq = &hisi_hba->dq[i]; + rc = _hisi_sas_internal_task_abort(hisi_hba, device, +- abort_flag, tag, dq); ++ abort_flag, tag, ++ dq, rst_to_recover); + if (rc) + return rc; + } +-- +2.27.0 + diff --git a/patches/0497-scsi-hisi_sas-Speed-up-error-handling-when-internal-.patch b/patches/0497-scsi-hisi_sas-Speed-up-error-handling-when-internal-.patch new file mode 100644 index 00000000..7fa60c62 --- /dev/null +++ b/patches/0497-scsi-hisi_sas-Speed-up-error-handling-when-internal-.patch @@ -0,0 +1,90 @@ +From 6777ac10a1516928d930e462021d0dca0ab90a8e Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing +Date: Tue, 3 Aug 2021 14:48:05 +0800 +Subject: [PATCH 179/256] scsi: hisi_sas: Speed up error handling when internal + abort timeout occurs + +mainline inclusion +from mainline-v5.14-rc1 +commit e8a4d0daaef6fc8f965ca0b8e9585aa9698a0f24 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F82P + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e8a4d0daaef6fc8f965ca0b8e9585aa9698a0f24 + +---------------------------------------------------------------------- + +If an internal task abort timeout occurs, the controller has developed a +fault, and needs to be reset to be recovered. + +When this occurs during error handling, the current policy is to allow +error handling to continue, and the inevitable nexus ha reset will handle +the required reset. + +However various steps of error handling need to taken before this happens. +These also involve some level of HW interaction, which will also fail with +various timeouts. + +Speed up this process by recording a HW fault bit for an internal abort +timeout - when this is set, just automatically error any HW interaction, +and essentially go straight to clear nexus ha (to reset the controller). + +Link: https://lore.kernel.org/r/1623058179-80434-6-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas.h | 1 + + drivers/scsi/hisi_sas/hisi_sas_main.c | 6 ++++++ + 2 files changed, 7 insertions(+) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index aa3ea25c25dc..1fe7e3e7e6ed 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -44,6 +44,7 @@ + #define HISI_SAS_RESET_BIT 0 + #define HISI_SAS_REJECT_CMD_BIT 1 + #define HISI_SAS_PM_BIT 2 ++#define HISI_SAS_HW_FAULT_BIT 3 + #define HISI_SAS_MAX_COMMANDS (HISI_SAS_QUEUE_SLOTS) + #define HISI_SAS_RESERVED_IPTT 96 + #define HISI_SAS_UNRESERVED_IPTT \ +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index cd84b5b076cb..a2da57dda953 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1675,6 +1675,7 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba) + } + + hisi_sas_controller_reset_done(hisi_hba); ++ clear_bit(HISI_SAS_HW_FAULT_BIT, &hisi_hba->flags); + dev_info(dev, "controller reset complete\n"); + + return 0; +@@ -2154,6 +2155,9 @@ _hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, + if (!hisi_hba->hw->prep_abort) + return TMF_RESP_FUNC_FAILED; + ++ if (test_bit(HISI_SAS_HW_FAULT_BIT, &hisi_hba->flags)) ++ return -EIO; ++ + task = sas_alloc_slow_task(GFP_KERNEL); + if (!task) + return -ENOMEM; +@@ -2184,6 +2188,8 @@ _hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, + if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { + struct hisi_sas_slot *slot = task->lldd_task; + ++ set_bit(HISI_SAS_HW_FAULT_BIT, &hisi_hba->flags); ++ + if (slot) { + struct hisi_sas_cq *cq = + &hisi_hba->cq[slot->dlvry_queue]; +-- +2.27.0 + diff --git a/patches/0498-scsi-libsas-Export-sas_phy_enable.patch b/patches/0498-scsi-libsas-Export-sas_phy_enable.patch new file mode 100644 index 00000000..a9e3127d --- /dev/null +++ b/patches/0498-scsi-libsas-Export-sas_phy_enable.patch @@ -0,0 +1,73 @@ +From 822430cb8c763a5da5c155de93bf40085c760a17 Mon Sep 17 00:00:00 2001 +From: nifujia +Date: Tue, 18 Jan 2022 21:23:42 +0800 +Subject: [PATCH 180/256] scsi: libsas: Export sas_phy_enable() + +mainline inclusion +from mainline-v5.16-rc1 +commit 00aeaf329a3a1ea3d3606fefa1d29f69f828bd21 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 +CVE: NA + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=00aeaf329a3a1ea3d3606fefa1d29f69f828bd21 + +---------------------------------------------------------------------- + +Export sas_phy_enable() so LLDDs can directly use it to control remote phys. + +We already do this for companion function sas_phy_reset(). + +Link: https://lore.kernel.org/r/1634041588-74824-4-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + include/scsi/libsas.h +--- + drivers/scsi/libsas/sas_init.c | 3 ++- + include/scsi/libsas.h | 1 + + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c +index 87bebd171652..f25fcea471a6 100644 +--- a/drivers/scsi/libsas/sas_init.c ++++ b/drivers/scsi/libsas/sas_init.c +@@ -275,7 +275,7 @@ static int transport_sas_phy_reset(struct sas_phy *phy, int hard_reset) + } + } + +-static int sas_phy_enable(struct sas_phy *phy, int enable) ++int sas_phy_enable(struct sas_phy *phy, int enable) + { + int ret; + enum phy_func cmd; +@@ -307,6 +307,7 @@ static int sas_phy_enable(struct sas_phy *phy, int enable) + } + return ret; + } ++EXPORT_SYMBOL_GPL(sas_phy_enable); + + int sas_phy_reset(struct sas_phy *phy, int hard_reset) + { +diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h +index be8ad849dfcd..ce2c9426d103 100644 +--- a/include/scsi/libsas.h ++++ b/include/scsi/libsas.h +@@ -684,6 +684,7 @@ extern void sas_suspend_ha(struct sas_ha_struct *sas_ha); + int sas_set_phy_speed(struct sas_phy *phy, + struct sas_phy_linkrates *rates); + int sas_phy_reset(struct sas_phy *phy, int hard_reset); ++int sas_phy_enable(struct sas_phy *phy, int enable); + extern int sas_queuecommand(struct Scsi_Host * ,struct scsi_cmnd *); + extern int sas_target_alloc(struct scsi_target *); + extern int sas_slave_configure(struct scsi_device *); +-- +2.27.0 + diff --git a/patches/0499-scsi-hisi_sas-Initialise-devices-in-.slave_alloc-cal.patch b/patches/0499-scsi-hisi_sas-Initialise-devices-in-.slave_alloc-cal.patch new file mode 100644 index 00000000..5823e877 --- /dev/null +++ b/patches/0499-scsi-hisi_sas-Initialise-devices-in-.slave_alloc-cal.patch @@ -0,0 +1,127 @@ +From cb174f3ccb19e8981ef36d2cd20d154b698841b9 Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Tue, 19 Apr 2022 17:06:51 +0800 +Subject: [PATCH 181/256] scsi: hisi_sas: Initialise devices in .slave_alloc + callback + +mainline inclusion +from mainline-v5.16-rc1 +commit 36c6b7613ef1ffd88637315f11c71896f3ce4856 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=36c6b7613ef1ffd88637315f11c71896f3ce4856 + +---------------------------------------------------------------------- + +Perform driver-specific SCSI device initialization in the designated SCSI +midlayer callback instead of relying on the libsas "device found" callback. + +The SCSI midlayer .slave_alloc interface is called prior to sending any I/O +to the device. + +Link: https://lore.kernel.org/r/1634041588-74824-2-git-send-email-john.garry@huawei.com +Signed-off-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: Fujai Ni +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas.h | 1 + + drivers/scsi/hisi_sas/hisi_sas_main.c | 17 ++++++++++++++--- + drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 2 +- + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2 +- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 2 +- + 5 files changed, 18 insertions(+), 6 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 1fe7e3e7e6ed..46e096659823 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -688,6 +688,7 @@ extern int hisi_sas_probe(struct platform_device *pdev, + extern int hisi_sas_remove(struct platform_device *pdev); + + extern int hisi_sas_slave_configure(struct scsi_device *sdev); ++extern int hisi_sas_slave_alloc(struct scsi_device *sdev); + extern int hisi_sas_scan_finished(struct Scsi_Host *shost, unsigned long time); + extern void hisi_sas_scan_start(struct Scsi_Host *shost); + extern int hisi_sas_host_reset(struct Scsi_Host *shost, int reset_type); +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index a2da57dda953..2946c64e19fe 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -769,6 +769,20 @@ static int hisi_sas_init_device(struct domain_device *device) + return rc; + } + ++int hisi_sas_slave_alloc(struct scsi_device *sdev) ++{ ++ struct domain_device *ddev; ++ int rc; ++ ++ rc = sas_slave_alloc(sdev); ++ if (rc) ++ return rc; ++ ddev = sdev_to_domain_dev(sdev); ++ ++ return hisi_sas_init_device(ddev); ++} ++EXPORT_SYMBOL_GPL(hisi_sas_slave_alloc); ++ + static int hisi_sas_dev_found(struct domain_device *device) + { + struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); +@@ -815,9 +829,6 @@ static int hisi_sas_dev_found(struct domain_device *device) + dev_info(dev, "dev[%d:%x] found\n", + sas_dev->device_id, sas_dev->dev_type); + +- rc = hisi_sas_init_device(device); +- if (rc) +- goto err_out; + sas_dev->dev_status = HISI_SAS_DEV_NORMAL; + return 0; + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +index b0f34cf16394..9cb469b041cd 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +@@ -1773,7 +1773,7 @@ static struct scsi_host_template sht_v1_hw = { + .use_clustering = ENABLE_CLUSTERING, + .eh_device_reset_handler = sas_eh_device_reset_handler, + .eh_target_reset_handler = sas_eh_target_reset_handler, +- .slave_alloc = sas_slave_alloc, ++ .slave_alloc = hisi_sas_slave_alloc, + .target_destroy = sas_target_destroy, + .ioctl = sas_ioctl, + .shost_attrs = host_attrs_v1_hw, +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +index d4a2db76b048..81dc2b85ba5b 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -3604,7 +3604,7 @@ static struct scsi_host_template sht_v2_hw = { + .use_clustering = ENABLE_CLUSTERING, + .eh_device_reset_handler = sas_eh_device_reset_handler, + .eh_target_reset_handler = sas_eh_target_reset_handler, +- .slave_alloc = sas_slave_alloc, ++ .slave_alloc = hisi_sas_slave_alloc, + .target_destroy = sas_target_destroy, + .ioctl = sas_ioctl, + .shost_attrs = host_attrs_v2_hw, +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index c5d230e05ac4..3d80fbe13070 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -3552,7 +3552,7 @@ static struct scsi_host_template sht_v3_hw = { + .use_clustering = ENABLE_CLUSTERING, + .eh_device_reset_handler = sas_eh_device_reset_handler, + .eh_target_reset_handler = sas_eh_target_reset_handler, +- .slave_alloc = sas_slave_alloc, ++ .slave_alloc = hisi_sas_slave_alloc, + .target_destroy = sas_target_destroy, + .ioctl = sas_ioctl, + .shost_attrs = host_attrs_v3_hw, +-- +2.27.0 + diff --git a/patches/0500-scsi-hisi_sas-Wait-for-phyup-in-hisi_sas_control_phy.patch b/patches/0500-scsi-hisi_sas-Wait-for-phyup-in-hisi_sas_control_phy.patch new file mode 100644 index 00000000..7d0e42ed --- /dev/null +++ b/patches/0500-scsi-hisi_sas-Wait-for-phyup-in-hisi_sas_control_phy.patch @@ -0,0 +1,265 @@ +From 4612424d2e510d9fa5176a66d95952a6455e0ea9 Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Tue, 19 Apr 2022 17:06:52 +0800 +Subject: [PATCH 182/256] scsi: hisi_sas: Wait for phyup in + hisi_sas_control_phy() + +mainline inclusion +from mainline-v5.16-rc1 +commit 046ab7d0f5943dd74c351e1f3a771dea785fe25d +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=046ab7d0f5943dd74c351e1f3a771dea785fe25d + +---------------------------------------------------------------------- + +When issuing a hardreset/linkreset/phy_set_linkrate from sysfs, the phy +will be disabled and re-enabled for the directly attached scenario. + +It takes some time for the phy to come back up after re-enabling the phy. +If the controller becomes suspended while waiting for the phy to come back, +the phy up may be lost (along with the disk). + +To solve this problem, wait for the phy up to occur with a timeout. Indeed +this is already done in hisi_sas_debug_I_T_nexus_reset() for local phys, so +just relocate the functionality to hisi_sas_control_phy(). + +Since the HA workqueue is drained when suspending the controller, and the +phy control function is called from the same workqueue, we can guarantee +that the controller will not be suspended during this period. + +Link: https://lore.kernel.org/r/1634041588-74824-3-git-send-email-john.garry@huawei.com +Signed-off-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: Fujai Ni +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 44 +++++++++++++++++++------- + drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 11 ++----- + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 17 ++-------- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 9 ++---- + 4 files changed, 39 insertions(+), 42 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 2946c64e19fe..9f89796b37ac 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1184,9 +1184,17 @@ static int hisi_sas_phy_set_linkrate(struct hisi_hba *hisi_hba, int phy_no, + static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func, + void *funcdata) + { ++ struct hisi_sas_phy *phy = container_of(sas_phy, ++ struct hisi_sas_phy, sas_phy); + struct sas_ha_struct *sas_ha = sas_phy->ha; + struct hisi_hba *hisi_hba = sas_ha->lldd_ha; ++ struct device *dev = hisi_hba->dev; ++ DECLARE_COMPLETION_ONSTACK(completion); + int phy_no = sas_phy->id; ++ u8 sts = phy->phy_attached; ++ int ret = 0; ++ ++ phy->reset_completion = &completion; + + switch (func) { + case PHY_FUNC_HARD_RESET: +@@ -1202,21 +1210,35 @@ static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func, + + case PHY_FUNC_DISABLE: + hisi_sas_phy_enable(hisi_hba, phy_no, 0); +- break; ++ goto out; + + case PHY_FUNC_SET_LINK_RATE: +- return hisi_sas_phy_set_linkrate(hisi_hba, phy_no, funcdata); ++ ret = hisi_sas_phy_set_linkrate(hisi_hba, phy_no, funcdata); ++ break; ++ + case PHY_FUNC_GET_EVENTS: + if (hisi_hba->hw->get_events) { + hisi_hba->hw->get_events(hisi_hba, phy_no); +- break; ++ goto out; + } + /* fallthru */ + case PHY_FUNC_RELEASE_SPINUP_HOLD: + default: +- return -EOPNOTSUPP; ++ ret = -EOPNOTSUPP; ++ goto out; + } +- return 0; ++ ++ if (sts && !wait_for_completion_timeout(&completion, 2 * HZ)) { ++ dev_warn(dev, "phy%d wait phyup timed out for func %d\n", ++ phy_no, func); ++ if (phy->in_reset) ++ ret = -ETIMEDOUT; ++ } ++ ++out: ++ phy->reset_completion = NULL; ++ ++ return ret; + } + + static void hisi_sas_task_done(struct sas_task *task) +@@ -1857,7 +1879,6 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device) + struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); + struct device *dev = hisi_hba->dev; + struct sas_ha_struct *sas_ha = &hisi_hba->sha; +- DECLARE_COMPLETION_ONSTACK(phyreset); + + if (!local_phy->enabled) { + sas_put_local_phy(local_phy); +@@ -1869,8 +1890,11 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device) + sas_ha->sas_phy[local_phy->number]; + struct hisi_sas_phy *phy = + container_of(sas_phy, struct hisi_sas_phy, sas_phy); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&phy->lock, flags); + phy->in_reset = 1; +- phy->reset_completion = &phyreset; ++ spin_unlock_irqrestore(&phy->lock, flags); + } + + rc = sas_phy_reset(local_phy, reset_type); +@@ -1881,18 +1905,14 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device) + sas_ha->sas_phy[local_phy->number]; + struct hisi_sas_phy *phy = + container_of(sas_phy, struct hisi_sas_phy, sas_phy); +- /* Wait for I_T reset complete, time out after 2s */ +- int ret = wait_for_completion_timeout(&phyreset, +- I_T_NEXUS_RESET_PHYUP_TIMEOUT); + unsigned long flags; + + spin_lock_irqsave(&phy->lock, flags); +- phy->reset_completion = NULL; + phy->in_reset = 0; + spin_unlock_irqrestore(&phy->lock, flags); + + /* report PHY down if timed out */ +- if (!ret) { ++ if (rc == -ETIMEDOUT) { + dev_warn(dev, "phy%d reset timeout\n", sas_phy->id); + hisi_sas_phy_down(hisi_hba, sas_phy->id, 0, GFP_KERNEL); + } +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +index 9cb469b041cd..d82e642d7093 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +@@ -1331,7 +1331,6 @@ static irqreturn_t int_phyup_v1_hw(int irq_no, void *p) + u32 *frame_rcvd = (u32 *)sas_phy->frame_rcvd; + struct sas_identify_frame *id = (struct sas_identify_frame *)frame_rcvd; + irqreturn_t res = IRQ_HANDLED; +- unsigned long flags; + + irq_value = hisi_sas_phy_read32(hisi_hba, phy_no, CHL_INT2); + if (!(irq_value & CHL_INT2_SL_PHY_ENA_MSK)) { +@@ -1384,15 +1383,9 @@ static irqreturn_t int_phyup_v1_hw(int irq_no, void *p) + phy->identify.target_port_protocols = + SAS_PROTOCOL_SMP; + hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP); +- +- spin_lock_irqsave(&phy->lock, flags); +- if (phy->reset_completion) { +- phy->in_reset = 0; +- complete(phy->reset_completion); +- } +- spin_unlock_irqrestore(&phy->lock, flags); +- + end: ++ if (phy->reset_completion) ++ complete(phy->reset_completion); + hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2, + CHL_INT2_SL_PHY_ENA_MSK); + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +index 81dc2b85ba5b..43b98d732591 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -2662,7 +2662,6 @@ static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba) + struct device *dev = hisi_hba->dev; + u32 *frame_rcvd = (u32 *)sas_phy->frame_rcvd; + struct sas_identify_frame *id = (struct sas_identify_frame *)frame_rcvd; +- unsigned long flags; + + hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 1); + +@@ -2717,14 +2716,9 @@ static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba) + set_link_timer_quirk(hisi_hba); + } + hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP); +- spin_lock_irqsave(&phy->lock, flags); +- if (phy->reset_completion) { +- phy->in_reset = 0; +- complete(phy->reset_completion); +- } +- spin_unlock_irqrestore(&phy->lock, flags); +- + end: ++ if (phy->reset_completion) ++ complete(phy->reset_completion); + hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, + CHL_INT0_SL_PHY_ENABLE_MSK); + hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 0); +@@ -3219,7 +3213,6 @@ static irqreturn_t sata_int_v2_hw(int irq_no, void *p) + u32 ent_tmp, ent_msk, ent_int, port_id, link_rate, hard_phy_linkrate; + irqreturn_t res = IRQ_HANDLED; + u8 attached_sas_addr[SAS_ADDR_SIZE] = {0}; +- unsigned long flags; + int phy_no, offset; + + del_timer(&phy->timer); +@@ -3295,12 +3288,8 @@ static irqreturn_t sata_int_v2_hw(int irq_no, void *p) + phy->identify.target_port_protocols = SAS_PROTOCOL_SATA; + hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP); + +- spin_lock_irqsave(&phy->lock, flags); +- if (phy->reset_completion) { +- phy->in_reset = 0; ++ if (phy->reset_completion) + complete(phy->reset_completion); +- } +- spin_unlock_irqrestore(&phy->lock, flags); + end: + hisi_sas_write32(hisi_hba, ENT_INT_SRC1 + offset, ent_tmp); + hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1 + offset, ent_msk); +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 3d80fbe13070..6e3d18208408 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -1631,7 +1631,6 @@ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba) + struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; + struct asd_sas_phy *sas_phy = &phy->sas_phy; + struct device *dev = hisi_hba->dev; +- unsigned long flags; + + del_timer(&phy->timer); + hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 1); +@@ -1716,13 +1715,9 @@ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba) + phy->phy_attached = 1; + hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP); + res = IRQ_HANDLED; +- spin_lock_irqsave(&phy->lock, flags); +- if (phy->reset_completion) { +- phy->in_reset = 0; +- complete(phy->reset_completion); +- } +- spin_unlock_irqrestore(&phy->lock, flags); + end: ++ if (phy->reset_completion) ++ complete(phy->reset_completion); + hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, + CHL_INT0_SL_PHY_ENABLE_MSK); + hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 0); +-- +2.27.0 + diff --git a/patches/0501-scsi-libsas-Don-t-always-drain-event-workqueue-for-H.patch b/patches/0501-scsi-libsas-Don-t-always-drain-event-workqueue-for-H.patch new file mode 100644 index 00000000..1a92c611 --- /dev/null +++ b/patches/0501-scsi-libsas-Don-t-always-drain-event-workqueue-for-H.patch @@ -0,0 +1,127 @@ +From b089417d145c1f9f10c70d428ec5818c38b77a14 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Tue, 19 Apr 2022 17:06:53 +0800 +Subject: [PATCH 183/256] scsi: libsas: Don't always drain event workqueue for + HA resume + +mainline inclusion +from mainline-v5.17-rc1 +commit fbefe22811c3140a686e407e114789ebf328a9a2 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fbefe22811c3140a686e407e114789ebf328a9a2 + +---------------------------------------------------------------------- + +For the hisi_sas driver, if a directly attached disk is removed during +suspend, a hang will occur in the resume process: + +The background is that in commit 16fd4a7c5917 ("scsi: hisi_sas: Add device +link between SCSI devices and hisi_hba"), it is ensured that the HBA device +cannot be runtime suspended when any SCSI device associated is active. + +Other drivers which use libsas don't worry about this as none support +runtime suspend. + +The mentioned hang occurs when an disk is removed during suspend. In the +removal process - from PHYE_RESUME_TIMEOUT event processing - we call into +scsi_remove_device(), which is being processed in the HA event workqueue. +Here we wait for all suppliers of the SCSI device to resume, which includes +the HBA device (from the above commit). However the HBA device cannot +resume, as it is waiting for the PHYE_RESUME_TIMEOUT to be processed (from +calling sas_resume_ha() -> sas_drain_work()). This is the deadlock. + +There does not appear to be any need for the sas_drain_work() to be called +at all in sas_resume_ha() as it is not syncing against anything, so allow +LLDDs to avoid this by providing a variant of sas_resume_ha() which does +"sync", i.e. doesn't drain the event workqueue. + +Link: https://lore.kernel.org/r/1639999298-244569-2-git-send-email-chenxiang66@hisilicon.com +Signed-off-by: John Garry +Signed-off-by: Xiang Chen +Signed-off-by: Martin K. Petersen +Signed-off-by: Fujai Ni +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 10 +++++++++- + drivers/scsi/libsas/sas_init.c | 17 +++++++++++++++-- + include/scsi/libsas.h | 1 + + 3 files changed, 25 insertions(+), 3 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 6e3d18208408..27bd58a48774 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -5356,7 +5356,15 @@ static int _resume_v3_hw(struct device *device) + return rc; + } + phys_init_v3_hw(hisi_hba); +- sas_resume_ha(sha); ++ ++ /* ++ * If a directly-attached disk is removed during suspend, a deadlock ++ * may occur, as the PHYE_RESUME_TIMEOUT processing will require the ++ * hisi_hba->device to be active, which can only happen when resume ++ * completes. So don't wait for the HA event workqueue to drain upon ++ * resume. ++ */ ++ sas_resume_ha_no_sync(sha); + clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags); + + return 0; +diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c +index f25fcea471a6..78ef49450c23 100644 +--- a/drivers/scsi/libsas/sas_init.c ++++ b/drivers/scsi/libsas/sas_init.c +@@ -407,7 +407,7 @@ static int phys_suspended(struct sas_ha_struct *ha) + return rc; + } + +-void sas_resume_ha(struct sas_ha_struct *ha) ++static void _sas_resume_ha(struct sas_ha_struct *ha, bool drain) + { + const unsigned long tmo = msecs_to_jiffies(25000); + int i; +@@ -437,10 +437,23 @@ void sas_resume_ha(struct sas_ha_struct *ha) + * flush out disks that did not return + */ + scsi_unblock_requests(ha->core.shost); +- sas_drain_work(ha); ++ if (drain) ++ sas_drain_work(ha); ++} ++ ++void sas_resume_ha(struct sas_ha_struct *ha) ++{ ++ _sas_resume_ha(ha, true); + } + EXPORT_SYMBOL(sas_resume_ha); + ++/* A no-sync variant, which does not call sas_drain_ha(). */ ++void sas_resume_ha_no_sync(struct sas_ha_struct *ha) ++{ ++ _sas_resume_ha(ha, false); ++} ++EXPORT_SYMBOL(sas_resume_ha_no_sync); ++ + void sas_suspend_ha(struct sas_ha_struct *ha) + { + int i; +diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h +index ce2c9426d103..b6b8a5f60622 100644 +--- a/include/scsi/libsas.h ++++ b/include/scsi/libsas.h +@@ -679,6 +679,7 @@ extern int sas_register_ha(struct sas_ha_struct *); + extern int sas_unregister_ha(struct sas_ha_struct *); + extern void sas_prep_resume_ha(struct sas_ha_struct *sas_ha); + extern void sas_resume_ha(struct sas_ha_struct *sas_ha); ++extern void sas_resume_ha_no_sync(struct sas_ha_struct *sas_ha); + extern void sas_suspend_ha(struct sas_ha_struct *sas_ha); + + int sas_set_phy_speed(struct sas_phy *phy, +-- +2.27.0 + diff --git a/patches/0502-scsi-libsas-Add-spin_lock-unlock-to-protect-asd_sas_.patch b/patches/0502-scsi-libsas-Add-spin_lock-unlock-to-protect-asd_sas_.patch new file mode 100644 index 00000000..ee9287f5 --- /dev/null +++ b/patches/0502-scsi-libsas-Add-spin_lock-unlock-to-protect-asd_sas_.patch @@ -0,0 +1,56 @@ +From 7fbaf231038ba239b64f315e8220869f4b5bee13 Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Tue, 19 Apr 2022 17:06:56 +0800 +Subject: [PATCH 184/256] scsi: libsas: Add spin_lock/unlock() to protect + asd_sas_port->phy_list + +mainline inclusion +from mainline-v5.17-rc1 +commit 42159d3c8d879e8d5fc225733f0cedc8baf19002 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=42159d3c8d879e8d5fc225733f0cedc8baf19002 + +---------------------------------------------------------------------- + +Most places that use asd_sas_port->phy_list in libsas are protected by +spinlock asd_sas_port->phy_list_lock. However, there are still a few places +which miss the lock. Add it in those places. + +Link: https://lore.kernel.org/r/1639999298-244569-5-git-send-email-chenxiang66@hisilicon.com +Reviewed-by: John Garry +Signed-off-by: Xiang Chen +Signed-off-by: Martin K. Petersen +Signed-off-by: Fujai Ni +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/libsas/sas_event.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c +index 4ceff8adf74f..1840cd39bf38 100644 +--- a/drivers/scsi/libsas/sas_event.c ++++ b/drivers/scsi/libsas/sas_event.c +@@ -121,11 +121,15 @@ void sas_enable_revalidation(struct sas_ha_struct *ha) + if (!test_and_clear_bit(ev, &d->pending)) + continue; + +- if (list_empty(&port->phy_list)) ++ spin_lock(&port->phy_list_lock); ++ if (list_empty(&port->phy_list)) { ++ spin_unlock(&port->phy_list_lock); + continue; ++ } + + sas_phy = container_of(port->phy_list.next, struct asd_sas_phy, + port_phy_el); ++ spin_unlock(&port->phy_list_lock); + sas_notify_port_event(sas_phy, + PORTE_BROADCAST_RCVD, GFP_KERNEL); + } +-- +2.27.0 + diff --git a/patches/0503-scsi-hisi_sas-Fix-some-issues-related-to-asd_sas_por.patch b/patches/0503-scsi-hisi_sas-Fix-some-issues-related-to-asd_sas_por.patch new file mode 100644 index 00000000..947c2b2a --- /dev/null +++ b/patches/0503-scsi-hisi_sas-Fix-some-issues-related-to-asd_sas_por.patch @@ -0,0 +1,91 @@ +From f7795c1cb9db1a8cafde17ee751d6589050261d7 Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Tue, 19 Apr 2022 17:06:57 +0800 +Subject: [PATCH 185/256] scsi: hisi_sas: Fix some issues related to + asd_sas_port->phy_list + +mainline inclusion +from mainline-v5.17-rc1 +commit 29e2bac87421c613782ccb510c76c5efbecac0cf +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=29e2bac87421c613782ccb510c76c5efbecac0cf + +---------------------------------------------------------------------- + +Most places that use asd_sas_port->phy_list are protected by spinlock +asd_sas_port->phy_list_lock, however there are still some places which miss +grabbing the lock. Add it in function hisi_sas_refresh_port_id() when +accessing asd_sas_port->phy_list. This carries a risk that list mutates +while at the same time dropping the lock in function +hisi_sas_send_ata_reset_each_phy(). Read asd_sas_port->phy_mask instead of +accessing asd_sas_port->phy_list to avoid this risk. + +Link: https://lore.kernel.org/r/1639999298-244569-6-git-send-email-chenxiang66@hisilicon.com +Acked-by: John Garry +Signed-off-by: Xiang Chen +Signed-off-by: Martin K. Petersen +Signed-off-by: Fujai Ni +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 9f89796b37ac..4cd2f26caf52 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1474,11 +1474,13 @@ static void hisi_sas_refresh_port_id(struct hisi_hba *hisi_hba) + sas_port = device->port; + port = to_hisi_sas_port(sas_port); + ++ spin_lock(&sas_port->phy_list_lock); + list_for_each_entry(sas_phy, &sas_port->phy_list, port_phy_el) + if (state & BIT(sas_phy->id)) { + phy = sas_phy->lldd_phy; + break; + } ++ spin_unlock(&sas_port->phy_list_lock); + + if (phy) { + port->id = phy->port_id; +@@ -1566,23 +1568,27 @@ static void hisi_sas_send_ata_reset_each_phy(struct hisi_hba *hisi_hba, + struct asd_sas_phy *sas_phy; + struct ata_link *link; + u32 state; ++ int i; + + state = hisi_hba->hw->get_phys_state(hisi_hba); +- list_for_each_entry(sas_phy, &sas_port->phy_list, port_phy_el) { ++ for (i = 0; i < hisi_hba->n_phy; i++) { ++ sas_phy = &hisi_hba->phy[i].sas_phy; + if (!(state & BIT(sas_phy->id))) + continue; ++ if (!(sas_port->phy_mask & BIT(i))) ++ continue; + + ata_for_each_link(link, ap, EDGE) { + int pmp = sata_srst_pmp(link); + +- tmf_task.phy_id = sas_phy->id; ++ tmf_task.phy_id = i; + hisi_sas_fill_ata_reset_cmd(link->device, 1, + pmp, (u8 *)&fis); + rc = hisi_sas_exec_internal_tmf_task(device, &fis, s, + &tmf_task); + if (rc != TMF_RESP_FUNC_COMPLETE) { + dev_err(dev, "phy%d ata reset failed rc=%d\n", +- sas_phy->id, rc); ++ i, rc); + break; + } + } +-- +2.27.0 + diff --git a/patches/0504-scsi-mvsas-Add-spin_lock-unlock-to-protect-asd_sas_p.patch b/patches/0504-scsi-mvsas-Add-spin_lock-unlock-to-protect-asd_sas_p.patch new file mode 100644 index 00000000..82490aa5 --- /dev/null +++ b/patches/0504-scsi-mvsas-Add-spin_lock-unlock-to-protect-asd_sas_p.patch @@ -0,0 +1,65 @@ +From 355ba88743269ee4b959e4fe1be45b8d402aa693 Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Tue, 19 Apr 2022 17:06:58 +0800 +Subject: [PATCH 186/256] scsi: mvsas: Add spin_lock/unlock() to protect + asd_sas_port->phy_list + +mainline inclusion +from mainline-v5.17-rc1 +commit 133b688b2d03f7ae2a6c9d344f92c1949ec05a51 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=133b688b2d03f7ae2a6c9d344f92c1949ec05a51 + +---------------------------------------------------------------------- + +phy_list_lock is not held when using asd_sas_port->phy_list in the mvsas +driver. Add spin_lock/unlock in those places. + +Link: https://lore.kernel.org/r/1639999298-244569-7-git-send-email-chenxiang66@hisilicon.com +Signed-off-by: Xiang Chen +Signed-off-by: Martin K. Petersen +Signed-off-by: Fujai Ni +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/mvsas/mv_sas.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c +index d14b6856f592..7a0684c2a215 100644 +--- a/drivers/scsi/mvsas/mv_sas.c ++++ b/drivers/scsi/mvsas/mv_sas.c +@@ -83,8 +83,10 @@ static struct mvs_info *mvs_find_dev_mvi(struct domain_device *dev) + + while (sha->sas_port[i]) { + if (sha->sas_port[i] == dev->port) { ++ spin_lock(&sha->sas_port[i]->phy_list_lock); + phy = container_of(sha->sas_port[i]->phy_list.next, + struct asd_sas_phy, port_phy_el); ++ spin_unlock(&sha->sas_port[i]->phy_list_lock); + j = 0; + while (sha->sas_phy[j]) { + if (sha->sas_phy[j] == phy) +@@ -112,6 +114,8 @@ static int mvs_find_dev_phyno(struct domain_device *dev, int *phyno) + while (sha->sas_port[i]) { + if (sha->sas_port[i] == dev->port) { + struct asd_sas_phy *phy; ++ ++ spin_lock(&sha->sas_port[i]->phy_list_lock); + list_for_each_entry(phy, + &sha->sas_port[i]->phy_list, port_phy_el) { + j = 0; +@@ -125,6 +129,7 @@ static int mvs_find_dev_phyno(struct domain_device *dev, int *phyno) + num++; + n++; + } ++ spin_unlock(&sha->sas_port[i]->phy_list_lock); + break; + } + i++; +-- +2.27.0 + diff --git a/patches/0505-scsi-libsas-aic94xx-hisi_sas-mvsas-pm8001-Use-dev_is.patch b/patches/0505-scsi-libsas-aic94xx-hisi_sas-mvsas-pm8001-Use-dev_is.patch new file mode 100644 index 00000000..3cf01c45 --- /dev/null +++ b/patches/0505-scsi-libsas-aic94xx-hisi_sas-mvsas-pm8001-Use-dev_is.patch @@ -0,0 +1,502 @@ +From 4b5b51b7fd9336a122a0585a708b8b10dcb997c5 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Mon, 10 Jun 2019 20:41:41 +0800 +Subject: [PATCH 187/256] scsi: libsas: aic94xx: hisi_sas: mvsas: pm8001: Use + dev_is_expander() + +mainline inclusion +from mainline-v5.3-rc1 +commit 924a3541eab0d28101baf0831e4315593f06ba4a +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=924a3541eab0d28101baf0831e4315593f06ba4a + +---------------------------------------------------------------------- + +Many times in libsas, and in LLDDs which use libsas, the check for an +expander device is re-implemented or open coded. + +Use dev_is_expander() instead. We rename this from +sas_dev_type_is_expander() to not spill so many lines in referencing. + +Signed-off-by: John Garry +Reviewed-by: Jason Yan +Reviewed-by: Jack Wang +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c + drivers/scsi/libsas/sas_port.c + include/scsi/libsas.h +--- + drivers/scsi/aic94xx/aic94xx_dev.c | 4 +--- + drivers/scsi/hisi_sas/hisi_sas.h | 4 ---- + drivers/scsi/hisi_sas/hisi_sas_main.c | 8 +++---- + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 4 ++-- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 6 +++--- + drivers/scsi/isci/remote_device.c | 4 ++-- + drivers/scsi/isci/remote_device.h | 5 ----- + drivers/scsi/isci/request.c | 2 +- + drivers/scsi/isci/task.c | 6 +++--- + drivers/scsi/libsas/sas_discover.c | 5 ++--- + drivers/scsi/libsas/sas_expander.c | 29 +++++++++----------------- + drivers/scsi/libsas/sas_port.c | 2 +- + drivers/scsi/mvsas/mv_sas.c | 2 +- + drivers/scsi/mvsas/mv_sas.h | 3 --- + drivers/scsi/pm8001/pm8001_hwi.c | 4 ++-- + drivers/scsi/pm8001/pm8001_sas.c | 2 +- + drivers/scsi/pm8001/pm8001_sas.h | 1 - + drivers/scsi/pm8001/pm80xx_hwi.c | 4 ++-- + include/scsi/libsas.h | 6 ++++++ + 19 files changed, 41 insertions(+), 60 deletions(-) + +diff --git a/drivers/scsi/aic94xx/aic94xx_dev.c b/drivers/scsi/aic94xx/aic94xx_dev.c +index 33072388ea16..e528a2ce9602 100644 +--- a/drivers/scsi/aic94xx/aic94xx_dev.c ++++ b/drivers/scsi/aic94xx/aic94xx_dev.c +@@ -187,9 +187,7 @@ static int asd_init_target_ddb(struct domain_device *dev) + } + } else { + flags |= CONCURRENT_CONN_SUPP; +- if (!dev->parent && +- (dev->dev_type == SAS_EDGE_EXPANDER_DEVICE || +- dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE)) ++ if (!dev->parent && dev_is_expander(dev->dev_type)) + asd_ddbsite_write_byte(asd_ha, ddb, MAX_CCONN, + 4); + else +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 46e096659823..44118c4c807a 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -83,10 +83,6 @@ + #define HISI_SAS_MAX_SMP_RESP_SZ 1028 + #define HISI_SAS_MAX_STP_RESP_SZ 28 + +-#define DEV_IS_EXPANDER(type) \ +- ((type == SAS_EDGE_EXPANDER_DEVICE) || \ +- (type == SAS_FANOUT_EXPANDER_DEVICE)) +- + #define HISI_SAS_SATA_PROTOCOL_NONDATA 0x1 + #define HISI_SAS_SATA_PROTOCOL_PIO 0x2 + #define HISI_SAS_SATA_PROTOCOL_DMA 0x4 +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 4cd2f26caf52..f8e7d5a9d8b0 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -804,7 +804,7 @@ static int hisi_sas_dev_found(struct domain_device *device) + device->lldd_dev = sas_dev; + hisi_hba->hw->setup_itct(hisi_hba, sas_dev); + +- if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) { ++ if (parent_dev && dev_is_expander(parent_dev->dev_type)) { + int phy_no; + u8 phy_num = parent_dev->ex_dev.num_phys; + struct ex_phy *phy; +@@ -1516,7 +1516,7 @@ static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state) + + _sas_port = sas_port; + +- if (DEV_IS_EXPANDER(dev->dev_type)) ++ if (dev_is_expander(dev->dev_type)) + sas_notify_port_event(sas_phy, + PORTE_BROADCAST_RCVD, + GFP_KERNEL); +@@ -1620,7 +1620,7 @@ static void hisi_sas_terminate_stp_reject(struct hisi_hba *hisi_hba) + struct domain_device *port_dev = sas_port->port_dev; + struct domain_device *device; + +- if (!port_dev || !DEV_IS_EXPANDER(port_dev->dev_type)) ++ if (!port_dev || !dev_is_expander(port_dev->dev_type)) + continue; + + /* Try to find a SATA device */ +@@ -2032,7 +2032,7 @@ static int hisi_sas_clear_nexus_ha(struct sas_ha_struct *sas_ha) + struct domain_device *device = sas_dev->sas_device; + + if ((sas_dev->dev_type == SAS_PHY_UNUSED) || !device || +- DEV_IS_EXPANDER(device->dev_type)) ++ dev_is_expander(device->dev_type)) + continue; + + async_schedule_domain(hisi_sas_async_I_T_nexus_reset, +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +index 43b98d732591..2dec563be227 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -948,7 +948,7 @@ static void setup_itct_v2_hw(struct hisi_hba *hisi_hba, + break; + case SAS_SATA_DEV: + case SAS_SATA_PENDING: +- if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) ++ if (parent_dev && dev_is_expander(parent_dev->dev_type)) + qw0 = HISI_SAS_DEV_TYPE_STP << ITCT_HDR_DEV_TYPE_OFF; + else + qw0 = HISI_SAS_DEV_TYPE_SATA << ITCT_HDR_DEV_TYPE_OFF; +@@ -2516,7 +2516,7 @@ static void prep_ata_v2_hw(struct hisi_hba *hisi_hba, + /* create header */ + /* dw0 */ + hdr->dw0 = cpu_to_le32(port->id << CMD_HDR_PORT_OFF); +- if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) { ++ if (parent_dev && dev_is_expander(parent_dev->dev_type)) { + hdr->dw0 |= cpu_to_le32(3 << CMD_HDR_CMD_OFF); + } else { + int phy_id = device->phy->identify.phy_identifier; +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 27bd58a48774..457eb5b52567 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -885,7 +885,7 @@ static void setup_itct_v3_hw(struct hisi_hba *hisi_hba, + break; + case SAS_SATA_DEV: + case SAS_SATA_PENDING: +- if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) ++ if (parent_dev && dev_is_expander(parent_dev->dev_type)) + qw0 = HISI_SAS_DEV_TYPE_STP << ITCT_HDR_DEV_TYPE_OFF; + else + qw0 = HISI_SAS_DEV_TYPE_SATA << ITCT_HDR_DEV_TYPE_OFF; +@@ -1527,7 +1527,7 @@ static void prep_ata_v3_hw(struct hisi_hba *hisi_hba, + u32 dw1 = 0, dw2 = 0, hdr_tag = 0; + + hdr->dw0 = cpu_to_le32(port->id << CMD_HDR_PORT_OFF); +- if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) { ++ if (parent_dev && dev_is_expander(parent_dev->dev_type)) { + hdr->dw0 |= cpu_to_le32(3 << CMD_HDR_CMD_OFF); /* STP */ + } else { + int phy_id = device->phy->identify.phy_identifier; +@@ -2555,7 +2555,7 @@ static void slot_complete_v3_hw(struct hisi_hba *hisi_hba, + + sas_ssp_task_response(dev, task, iu); + if ((!(device->parent && +- DEV_IS_EXPANDER(device->parent->dev_type))) && ++ dev_is_expander(device->parent->dev_type))) && + ssp_need_spin_up(slot)) { + int phy_no; + +diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c +index cc51f38b116d..1eca877938dc 100644 +--- a/drivers/scsi/isci/remote_device.c ++++ b/drivers/scsi/isci/remote_device.c +@@ -1087,7 +1087,7 @@ static void sci_remote_device_ready_state_enter(struct sci_base_state_machine *s + + if (dev->dev_type == SAS_SATA_DEV || (dev->tproto & SAS_PROTOCOL_SATA)) { + sci_change_state(&idev->sm, SCI_STP_DEV_IDLE); +- } else if (dev_is_expander(dev)) { ++ } else if (dev_is_expander(dev->dev_type)) { + sci_change_state(&idev->sm, SCI_SMP_DEV_IDLE); + } else + isci_remote_device_ready(ihost, idev); +@@ -1478,7 +1478,7 @@ static enum sci_status isci_remote_device_construct(struct isci_port *iport, + struct domain_device *dev = idev->domain_dev; + enum sci_status status; + +- if (dev->parent && dev_is_expander(dev->parent)) ++ if (dev->parent && dev_is_expander(dev->parent->dev_type)) + status = sci_remote_device_ea_construct(iport, idev); + else + status = sci_remote_device_da_construct(iport, idev); +diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h +index 47a013fffae7..3ad681c4c20a 100644 +--- a/drivers/scsi/isci/remote_device.h ++++ b/drivers/scsi/isci/remote_device.h +@@ -295,11 +295,6 @@ static inline struct isci_remote_device *rnc_to_dev(struct sci_remote_node_conte + return idev; + } + +-static inline bool dev_is_expander(struct domain_device *dev) +-{ +- return dev->dev_type == SAS_EDGE_EXPANDER_DEVICE || dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE; +-} +- + static inline void sci_remote_device_decrement_request_count(struct isci_remote_device *idev) + { + /* XXX delete this voodoo when converting to the top-level device +diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c +index 2f151708b59a..45aaac95f986 100644 +--- a/drivers/scsi/isci/request.c ++++ b/drivers/scsi/isci/request.c +@@ -3101,7 +3101,7 @@ sci_io_request_construct(struct isci_host *ihost, + /* pass */; + else if (dev_is_sata(dev)) + memset(&ireq->stp.cmd, 0, sizeof(ireq->stp.cmd)); +- else if (dev_is_expander(dev)) ++ else if (dev_is_expander(dev->dev_type)) + /* pass */; + else + return SCI_FAILURE_UNSUPPORTED_PROTOCOL; +diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c +index fb6eba331ac6..dfcb92fc2415 100644 +--- a/drivers/scsi/isci/task.c ++++ b/drivers/scsi/isci/task.c +@@ -511,9 +511,9 @@ int isci_task_abort_task(struct sas_task *task) + "%s: dev = %p (%s%s), task = %p, old_request == %p\n", + __func__, idev, + (dev_is_sata(task->dev) ? "STP/SATA" +- : ((dev_is_expander(task->dev)) +- ? "SMP" +- : "SSP")), ++ : ((dev_is_expander(task->dev->dev_type)) ++ ? "SMP" ++ : "SSP")), + ((idev) ? ((test_bit(IDEV_GONE, &idev->flags)) + ? " IDEV_GONE" + : "") +diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c +index f76e4c19a677..ce95e1c9cb7c 100644 +--- a/drivers/scsi/libsas/sas_discover.c ++++ b/drivers/scsi/libsas/sas_discover.c +@@ -316,7 +316,7 @@ void sas_free_device(struct kref *kref) + dev->phy = NULL; + + /* remove the phys and ports, everything else should be gone */ +- if (dev->dev_type == SAS_EDGE_EXPANDER_DEVICE || dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE) ++ if (dev_is_expander(dev->dev_type)) + kfree(dev->ex_dev.ex_phy); + + if (dev_is_sata(dev) && dev->sata_dev.ap) { +@@ -526,8 +526,7 @@ static void sas_revalidate_domain(struct work_struct *work) + SAS_DPRINTK("REVALIDATING DOMAIN on port %d, pid:%d\n", port->id, + task_pid_nr(current)); + +- if (ddev && (ddev->dev_type == SAS_FANOUT_EXPANDER_DEVICE || +- ddev->dev_type == SAS_EDGE_EXPANDER_DEVICE)) ++ if (ddev && dev_is_expander(ddev->dev_type)) + res = sas_ex_revalidate_domain(ddev); + + SAS_DPRINTK("done REVALIDATING DOMAIN on port %d, pid:%d, res 0x%x\n", +diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c +index 799eb400a174..842021ab8c2f 100644 +--- a/drivers/scsi/libsas/sas_expander.c ++++ b/drivers/scsi/libsas/sas_expander.c +@@ -1161,8 +1161,7 @@ static int sas_find_sub_addr(struct domain_device *dev, u8 *sub_addr) + phy->phy_state == PHY_NOT_PRESENT) + continue; + +- if ((phy->attached_dev_type == SAS_EDGE_EXPANDER_DEVICE || +- phy->attached_dev_type == SAS_FANOUT_EXPANDER_DEVICE) && ++ if (dev_is_expander(phy->attached_dev_type) && + phy->routing_attr == SUBTRACTIVE_ROUTING) { + + memcpy(sub_addr, phy->attached_sas_addr, SAS_ADDR_SIZE); +@@ -1180,8 +1179,7 @@ static int sas_check_level_subtractive_boundary(struct domain_device *dev) + u8 sub_addr[SAS_ADDR_SIZE] = {0, }; + + list_for_each_entry(child, &ex->children, siblings) { +- if (child->dev_type != SAS_EDGE_EXPANDER_DEVICE && +- child->dev_type != SAS_FANOUT_EXPANDER_DEVICE) ++ if (!dev_is_expander(child->dev_type)) + continue; + if (sub_addr[0] == 0) { + sas_find_sub_addr(child, sub_addr); +@@ -1268,8 +1266,7 @@ static int sas_check_ex_subtractive_boundary(struct domain_device *dev) + phy->phy_state == PHY_NOT_PRESENT) + continue; + +- if ((phy->attached_dev_type == SAS_FANOUT_EXPANDER_DEVICE || +- phy->attached_dev_type == SAS_EDGE_EXPANDER_DEVICE) && ++ if (dev_is_expander(phy->attached_dev_type) && + phy->routing_attr == SUBTRACTIVE_ROUTING) { + + if (!sub_sas_addr) +@@ -1371,8 +1368,7 @@ static int sas_check_parent_topology(struct domain_device *child) + if (!child->parent) + return 0; + +- if (child->parent->dev_type != SAS_EDGE_EXPANDER_DEVICE && +- child->parent->dev_type != SAS_FANOUT_EXPANDER_DEVICE) ++ if (!dev_is_expander(child->parent->dev_type)) + return 0; + + parent_ex = &child->parent->ex_dev; +@@ -1670,8 +1666,7 @@ static int sas_ex_level_discovery(struct asd_sas_port *port, const int level) + struct domain_device *dev; + + list_for_each_entry(dev, &port->dev_list, dev_list_node) { +- if (dev->dev_type == SAS_EDGE_EXPANDER_DEVICE || +- dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE) { ++ if (dev_is_expander(dev->dev_type)) { + struct sas_expander_device *ex = + rphy_to_expander_device(dev->rphy); + +@@ -1901,7 +1896,7 @@ static int sas_find_bcast_dev(struct domain_device *dev, + SAS_DPRINTK("Expander phys DID NOT change\n"); + } + list_for_each_entry(ch, &ex->children, siblings) { +- if (ch->dev_type == SAS_EDGE_EXPANDER_DEVICE || ch->dev_type == SAS_FANOUT_EXPANDER_DEVICE) { ++ if (dev_is_expander(ch->dev_type)) { + res = sas_find_bcast_dev(ch, src_dev); + if (*src_dev) + return res; +@@ -1918,8 +1913,7 @@ static void sas_unregister_ex_tree(struct asd_sas_port *port, struct domain_devi + + list_for_each_entry_safe(child, n, &ex->children, siblings) { + set_bit(SAS_DEV_GONE, &child->state); +- if (child->dev_type == SAS_EDGE_EXPANDER_DEVICE || +- child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) ++ if (dev_is_expander(child->dev_type)) + sas_unregister_ex_tree(port, child); + else + sas_unregister_dev(port, child); +@@ -1939,8 +1933,7 @@ static void sas_unregister_devs_sas_addr(struct domain_device *parent, + if (SAS_ADDR(child->sas_addr) == + SAS_ADDR(phy->attached_sas_addr)) { + set_bit(SAS_DEV_GONE, &child->state); +- if (child->dev_type == SAS_EDGE_EXPANDER_DEVICE || +- child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) ++ if (dev_is_expander(child->dev_type)) + sas_unregister_ex_tree(parent->port, child); + else + sas_unregister_dev(parent->port, child); +@@ -1971,8 +1964,7 @@ static int sas_discover_bfs_by_root_level(struct domain_device *root, + int res = 0; + + list_for_each_entry(child, &ex_root->children, siblings) { +- if (child->dev_type == SAS_EDGE_EXPANDER_DEVICE || +- child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) { ++ if (dev_is_expander(child->dev_type)) { + struct sas_expander_device *ex = + rphy_to_expander_device(child->rphy); + +@@ -2025,8 +2017,7 @@ static int sas_discover_new(struct domain_device *dev, int phy_id) + list_for_each_entry(child, &dev->ex_dev.children, siblings) { + if (SAS_ADDR(child->sas_addr) == + SAS_ADDR(ex_phy->attached_sas_addr)) { +- if (child->dev_type == SAS_EDGE_EXPANDER_DEVICE || +- child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) ++ if (dev_is_expander(child->dev_type)) + res = sas_discover_bfs_by_root(child); + break; + } +diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c +index 32991f7ec2a1..f9788bded964 100644 +--- a/drivers/scsi/libsas/sas_port.c ++++ b/drivers/scsi/libsas/sas_port.c +@@ -70,7 +70,7 @@ static void sas_resume_port(struct asd_sas_phy *phy) + continue; + } + +- if (dev->dev_type == SAS_EDGE_EXPANDER_DEVICE || dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE) { ++ if (dev_is_expander(dev->dev_type)) { + dev->ex_dev.ex_change_count = -1; + for (i = 0; i < dev->ex_dev.num_phys; i++) { + struct ex_phy *phy = &dev->ex_dev.ex_phy[i]; +diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c +index 7a0684c2a215..4c63d543af4c 100644 +--- a/drivers/scsi/mvsas/mv_sas.c ++++ b/drivers/scsi/mvsas/mv_sas.c +@@ -1212,7 +1212,7 @@ static int mvs_dev_found_notify(struct domain_device *dev, int lock) + mvi_device->dev_type = dev->dev_type; + mvi_device->mvi_info = mvi; + mvi_device->sas_device = dev; +- if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) { ++ if (parent_dev && dev_is_expander(parent_dev->dev_type)) { + int phy_id; + u8 phy_num = parent_dev->ex_dev.num_phys; + struct ex_phy *phy; +diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h +index 080676c1c9e5..b391c03fe5f5 100644 +--- a/drivers/scsi/mvsas/mv_sas.h ++++ b/drivers/scsi/mvsas/mv_sas.h +@@ -66,9 +66,6 @@ extern struct mvs_info *tgt_mvi; + extern const struct mvs_dispatch mvs_64xx_dispatch; + extern const struct mvs_dispatch mvs_94xx_dispatch; + +-#define DEV_IS_EXPANDER(type) \ +- ((type == SAS_EDGE_EXPANDER_DEVICE) || (type == SAS_FANOUT_EXPANDER_DEVICE)) +- + #define bit(n) ((u64)1 << n) + + #define for_each_phy(__lseq_mask, __mc, __lseq) \ +diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c +index 4543a9d86ab3..2c1e2ded06b1 100644 +--- a/drivers/scsi/pm8001/pm8001_hwi.c ++++ b/drivers/scsi/pm8001/pm8001_hwi.c +@@ -2354,7 +2354,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) + if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) && + (status != IO_UNDERFLOW)) { + if (!((t->dev->parent) && +- (DEV_IS_EXPANDER(t->dev->parent->dev_type)))) { ++ (dev_is_expander(t->dev->parent->dev_type)))) { + for (i = 0 , j = 4; j <= 7 && i <= 3; i++ , j++) + sata_addr_low[i] = pm8001_ha->sas_addr[j]; + for (i = 0 , j = 0; j <= 3 && i <= 3; i++ , j++) +@@ -4574,7 +4574,7 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha, + pm8001_dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE) + stp_sspsmp_sata = 0x01; /*ssp or smp*/ + } +- if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) ++ if (parent_dev && dev_is_expander(parent_dev->dev_type)) + phy_id = parent_dev->ex_dev.ex_phy->phy_id; + else + phy_id = pm8001_dev->attached_phy; +diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c +index 35e889330c11..79e56074415c 100644 +--- a/drivers/scsi/pm8001/pm8001_sas.c ++++ b/drivers/scsi/pm8001/pm8001_sas.c +@@ -612,7 +612,7 @@ static int pm8001_dev_found_notify(struct domain_device *dev) + dev->lldd_dev = pm8001_device; + pm8001_device->dev_type = dev->dev_type; + pm8001_device->dcompletion = &completion; +- if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) { ++ if (parent_dev && dev_is_expander(parent_dev->dev_type)) { + int phy_id; + struct ex_phy *phy; + for (phy_id = 0; phy_id < parent_dev->ex_dev.num_phys; +diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h +index 1816e351071f..d9509a17042d 100644 +--- a/drivers/scsi/pm8001/pm8001_sas.h ++++ b/drivers/scsi/pm8001/pm8001_sas.h +@@ -103,7 +103,6 @@ do { \ + #define PM8001_READ_VPD + + +-#define DEV_IS_EXPANDER(type) ((type == SAS_EDGE_EXPANDER_DEVICE) || (type == SAS_FANOUT_EXPANDER_DEVICE)) + #define IS_SPCV_12G(dev) ((dev->device == 0X8074) \ + || (dev->device == 0X8076) \ + || (dev->device == 0X8077) \ +diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c +index 04620a9088a5..f3ec2e08411e 100644 +--- a/drivers/scsi/pm8001/pm80xx_hwi.c ++++ b/drivers/scsi/pm8001/pm80xx_hwi.c +@@ -2066,7 +2066,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) + if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) && + (status != IO_UNDERFLOW)) { + if (!((t->dev->parent) && +- (DEV_IS_EXPANDER(t->dev->parent->dev_type)))) { ++ (dev_is_expander(t->dev->parent->dev_type)))) { + for (i = 0 , j = 4; i <= 3 && j <= 7; i++ , j++) + sata_addr_low[i] = pm8001_ha->sas_addr[j]; + for (i = 0 , j = 0; i <= 3 && j <= 3; i++ , j++) +@@ -4567,7 +4567,7 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha, + pm8001_dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE) + stp_sspsmp_sata = 0x01; /*ssp or smp*/ + } +- if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) ++ if (parent_dev && dev_is_expander(parent_dev->dev_type)) + phy_id = parent_dev->ex_dev.ex_phy->phy_id; + else + phy_id = pm8001_dev->attached_phy; +diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h +index b6b8a5f60622..1253d8a26d96 100644 +--- a/include/scsi/libsas.h ++++ b/include/scsi/libsas.h +@@ -225,6 +225,12 @@ struct sas_work { + struct work_struct work; + }; + ++static inline bool dev_is_expander(enum sas_device_type type) ++{ ++ return type == SAS_EDGE_EXPANDER_DEVICE || ++ type == SAS_FANOUT_EXPANDER_DEVICE; ++} ++ + static inline void INIT_SAS_WORK(struct sas_work *sw, void (*fn)(struct work_struct *)) + { + INIT_WORK(&sw->work, fn); +-- +2.27.0 + diff --git a/patches/0506-scsi-libsas-Insert-PORTE_BROADCAST_RCVD-event-for-re.patch b/patches/0506-scsi-libsas-Insert-PORTE_BROADCAST_RCVD-event-for-re.patch new file mode 100644 index 00000000..e1b9e8e7 --- /dev/null +++ b/patches/0506-scsi-libsas-Insert-PORTE_BROADCAST_RCVD-event-for-re.patch @@ -0,0 +1,84 @@ +From 8431b48ed2c4f699b172c762c26076ab968afce2 Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Tue, 19 Apr 2022 17:06:59 +0800 +Subject: [PATCH 188/256] scsi: libsas: Insert PORTE_BROADCAST_RCVD event for + resuming host + +mainline inclusion +from mainline-v5.17-rc1 +commit e31e18128eb9dbcda8c169cb33421ae4813afa71 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e31e18128eb9dbcda8c169cb33421ae4813afa71 + +---------------------------------------------------------------------- + +If a new disk is inserted through an expander when the host was suspended, +it will not necessarily be detected as the topology is not re-scanned +during resume. To detect possible changes in topology during suspension, +insert a PORTE_BROADCAST_RCVD event per port when resuming to trigger a +revalidation. + +Link: https://lore.kernel.org/r/1639999298-244569-8-git-send-email-chenxiang66@hisilicon.com +Reviewed-by: John Garry +Signed-off-by: Xiang Chen +Signed-off-by: Martin K. Petersen +Signed-off-by: Fujai Ni +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/libsas/sas_init.c | 29 +++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c +index 78ef49450c23..eb7899f25145 100644 +--- a/drivers/scsi/libsas/sas_init.c ++++ b/drivers/scsi/libsas/sas_init.c +@@ -407,6 +407,30 @@ static int phys_suspended(struct sas_ha_struct *ha) + return rc; + } + ++static void sas_resume_insert_broadcast_ha(struct sas_ha_struct *ha) ++{ ++ int i; ++ ++ for (i = 0; i < ha->num_phys; i++) { ++ struct asd_sas_port *port = ha->sas_port[i]; ++ struct domain_device *dev = port->port_dev; ++ ++ if (dev && dev_is_expander(dev->dev_type)) { ++ struct asd_sas_phy *first_phy; ++ ++ spin_lock(&port->phy_list_lock); ++ first_phy = list_first_entry_or_null( ++ &port->phy_list, struct asd_sas_phy, ++ port_phy_el); ++ spin_unlock(&port->phy_list_lock); ++ ++ if (first_phy) ++ sas_notify_port_event(first_phy, ++ PORTE_BROADCAST_RCVD, GFP_KERNEL); ++ } ++ } ++} ++ + static void _sas_resume_ha(struct sas_ha_struct *ha, bool drain) + { + const unsigned long tmo = msecs_to_jiffies(25000); +@@ -439,6 +463,11 @@ static void _sas_resume_ha(struct sas_ha_struct *ha, bool drain) + scsi_unblock_requests(ha->core.shost); + if (drain) + sas_drain_work(ha); ++ ++ /* send event PORTE_BROADCAST_RCVD to identify some new inserted ++ * disks for expander ++ */ ++ sas_resume_insert_broadcast_ha(ha); + } + + void sas_resume_ha(struct sas_ha_struct *ha) +-- +2.27.0 + diff --git a/patches/0507-scsi-hisi_sas-Add-more-logs-for-runtime-suspend-resu.patch b/patches/0507-scsi-hisi_sas-Add-more-logs-for-runtime-suspend-resu.patch new file mode 100644 index 00000000..1845513a --- /dev/null +++ b/patches/0507-scsi-hisi_sas-Add-more-logs-for-runtime-suspend-resu.patch @@ -0,0 +1,68 @@ +From 0ea46da99237fc70e474ab76565b4be69182beab Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Tue, 19 Apr 2022 17:07:00 +0800 +Subject: [PATCH 189/256] scsi: hisi_sas: Add more logs for runtime + suspend/resume + +mainline inclusion +from mainline-v5.17-rc1 +commit 97f4100939844a6381ba61b99d6d2b1f2fccb79f +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 +CVE: NA + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=97f4100939844a6381ba61b99d6d2b1f2fccb79f + +---------------------------------------------------------------------- + +Add some logs at the beginning and end of suspend/resume. + +Link: https://lore.kernel.org/r/1639999298-244569-9-git-send-email-chenxiang66@hisilicon.com +Acked-by: John Garry +Signed-off-by: Xiang Chen +Signed-off-by: Martin K. Petersen +Signed-off-by: Fujai Ni +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 457eb5b52567..0be9f2a35931 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -5295,6 +5295,8 @@ static int _suspend_v3_hw(struct device *device) + if (test_and_set_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) + return -EPERM; + ++ dev_warn(dev, "entering suspend state\n"); ++ + scsi_block_requests(shost); + set_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); + flush_workqueue(hisi_hba->wq); +@@ -5320,6 +5322,8 @@ static int _suspend_v3_hw(struct device *device) + hisi_sas_release_tasks(hisi_hba); + + sas_suspend_ha(sha); ++ ++ dev_warn(dev, "end of suspending controller\n"); + return 0; + } + +@@ -5367,6 +5371,8 @@ static int _resume_v3_hw(struct device *device) + sas_resume_ha_no_sync(sha); + clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags); + ++ dev_warn(dev, "end of resuming controller\n"); ++ + return 0; + } + +-- +2.27.0 + diff --git a/patches/0508-scsi-libsas-Resume-host-while-sending-SMP-I-Os.patch b/patches/0508-scsi-libsas-Resume-host-while-sending-SMP-I-Os.patch new file mode 100644 index 00000000..8ff43b03 --- /dev/null +++ b/patches/0508-scsi-libsas-Resume-host-while-sending-SMP-I-Os.patch @@ -0,0 +1,71 @@ +From c66a05de26e1a703bafedc595099380bac8145fd Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Tue, 19 Apr 2022 17:07:01 +0800 +Subject: [PATCH 190/256] scsi: libsas: Resume host while sending SMP I/Os + +mainline inclusion +from mainline-v5.17-rc1 +commit 0da7ca4c4fd95d70d473dc07488ad94ba3ee9b82 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0da7ca4c4fd95d70d473dc07488ad94ba3ee9b82 + +---------------------------------------------------------------------- + +When sending SMP I/Os to the host we need to ensure that the host is not +suspended and can process the commands. This is a better approach than +replying on the host to resume itself to handle such commands. Use +pm_runtime_get_sync() and pm_runtime_put_sync() calls for the host when +executing SMP I/Os. + +Link: https://lore.kernel.org/r/1639999298-244569-10-git-send-email-chenxiang66@hisilicon.com +Reviewed-by: John Garry +Signed-off-by: Xiang Chen +Signed-off-by: Martin K. Petersen +Signed-off-by: Fujai Ni +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/libsas/sas_expander.c | 3 +++ + drivers/scsi/libsas/sas_internal.h | 1 + + 2 files changed, 4 insertions(+) + +diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c +index 842021ab8c2f..e436423600b1 100644 +--- a/drivers/scsi/libsas/sas_expander.c ++++ b/drivers/scsi/libsas/sas_expander.c +@@ -71,7 +71,9 @@ static int smp_execute_task_sg(struct domain_device *dev, + struct sas_task *task = NULL; + struct sas_internal *i = + to_sas_internal(dev->port->ha->core.shost->transportt); ++ struct sas_ha_struct *ha = dev->port->ha; + ++ pm_runtime_get_sync(ha->dev); + mutex_lock(&dev->ex_dev.cmd_mutex); + for (retry = 0; retry < 3; retry++) { + if (test_bit(SAS_DEV_GONE, &dev->state)) { +@@ -144,6 +146,7 @@ static int smp_execute_task_sg(struct domain_device *dev, + } + } + mutex_unlock(&dev->ex_dev.cmd_mutex); ++ pm_runtime_put_sync(ha->dev); + + BUG_ON(retry == 3 && task != NULL); + sas_free_task(task); +diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h +index 90049b3fbf68..1f314f1da994 100644 +--- a/drivers/scsi/libsas/sas_internal.h ++++ b/drivers/scsi/libsas/sas_internal.h +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + + #define sas_printk(fmt, ...) printk(KERN_NOTICE "sas: " fmt, ## __VA_ARGS__) + +-- +2.27.0 + diff --git a/patches/0509-scsi-libsas-Add-flag-SAS_HA_RESUMING.patch b/patches/0509-scsi-libsas-Add-flag-SAS_HA_RESUMING.patch new file mode 100644 index 00000000..d6703f22 --- /dev/null +++ b/patches/0509-scsi-libsas-Add-flag-SAS_HA_RESUMING.patch @@ -0,0 +1,66 @@ +From 042f943e9f77a98b2ec0c5dc3240781350a509d5 Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Tue, 19 Apr 2022 17:07:02 +0800 +Subject: [PATCH 191/256] scsi: libsas: Add flag SAS_HA_RESUMING + +mainline inclusion +from mainline-v5.17-rc1 +commit 4ea775abbb5c50c26edbf043d5a2ae7fde407f4a +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4ea775abbb5c50c26edbf043d5a2ae7fde407f4a + +---------------------------------------------------------------------- + +Add a flag SAS_HA_RESUMING and use it to indicate the state of resuming the +host controller. + +Link: https://lore.kernel.org/r/1639999298-244569-11-git-send-email-chenxiang66@hisilicon.com +Reviewed-by: John Garry +Signed-off-by: Xiang Chen +Signed-off-by: Martin K. Petersen +Signed-off-by: Fujai Ni +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/libsas/sas_init.c | 2 ++ + include/scsi/libsas.h | 1 + + 2 files changed, 3 insertions(+) + +diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c +index eb7899f25145..8871d7ff17d8 100644 +--- a/drivers/scsi/libsas/sas_init.c ++++ b/drivers/scsi/libsas/sas_init.c +@@ -382,6 +382,7 @@ void sas_prep_resume_ha(struct sas_ha_struct *ha) + int i; + + set_bit(SAS_HA_REGISTERED, &ha->state); ++ set_bit(SAS_HA_RESUMING, &ha->state); + + /* clear out any stale link events/data from the suspension path */ + for (i = 0; i < ha->num_phys; i++) { +@@ -463,6 +464,7 @@ static void _sas_resume_ha(struct sas_ha_struct *ha, bool drain) + scsi_unblock_requests(ha->core.shost); + if (drain) + sas_drain_work(ha); ++ clear_bit(SAS_HA_RESUMING, &ha->state); + + /* send event PORTE_BROADCAST_RCVD to identify some new inserted + * disks for expander +diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h +index 1253d8a26d96..5634a168fd54 100644 +--- a/include/scsi/libsas.h ++++ b/include/scsi/libsas.h +@@ -374,6 +374,7 @@ enum sas_ha_state { + SAS_HA_DRAINING, + SAS_HA_ATA_EH_ACTIVE, + SAS_HA_FROZEN, ++ SAS_HA_RESUMING, + }; + + struct sas_ha_struct { +-- +2.27.0 + diff --git a/patches/0510-scsi-libsas-Refactor-sas_queue_deferred_work.patch b/patches/0510-scsi-libsas-Refactor-sas_queue_deferred_work.patch new file mode 100644 index 00000000..88f299c3 --- /dev/null +++ b/patches/0510-scsi-libsas-Refactor-sas_queue_deferred_work.patch @@ -0,0 +1,95 @@ +From 99d7ed6b98179279c9f932f8f1ad3430ea99b9d1 Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Tue, 19 Apr 2022 17:07:03 +0800 +Subject: [PATCH 192/256] scsi: libsas: Refactor sas_queue_deferred_work() + +mainline inclusion +from mainline-v5.17-rc1 +commit 1bc35475c6bf6d078b3800e516978f37c1ecda36 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1bc35475c6bf6d078b3800e516978f37c1ecda36 + +---------------------------------------------------------------------- + +In the second part of function __sas_drain_work(), deferred work is queued. +This functionality is required other places so factor it out into the +function sas_queue_deferred_work(). + +Link: https://lore.kernel.org/r/1639999298-244569-12-git-send-email-chenxiang66@hisilicon.com +Reviewed-by: John Garry +Signed-off-by: Xiang Chen +Signed-off-by: Martin K. Petersen +Signed-off-by: Fujai Ni +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/libsas/sas_event.c | 25 ++++++++++++++----------- + drivers/scsi/libsas/sas_internal.h | 1 + + 2 files changed, 15 insertions(+), 11 deletions(-) + +diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c +index 1840cd39bf38..7846eb0e2ce0 100644 +--- a/drivers/scsi/libsas/sas_event.c ++++ b/drivers/scsi/libsas/sas_event.c +@@ -58,12 +58,23 @@ static int sas_queue_event(int event, struct sas_work *work, + return rc; + } + +- +-void __sas_drain_work(struct sas_ha_struct *ha) ++void sas_queue_deferred_work(struct sas_ha_struct *ha) + { + struct sas_work *sw, *_sw; + int ret; + ++ spin_lock_irq(&ha->lock); ++ list_for_each_entry_safe(sw, _sw, &ha->defer_q, drain_node) { ++ list_del_init(&sw->drain_node); ++ ret = sas_queue_work(ha, sw); ++ if (ret != 1) ++ sas_free_event(to_asd_sas_event(&sw->work)); ++ } ++ spin_unlock_irq(&ha->lock); ++} ++ ++void __sas_drain_work(struct sas_ha_struct *ha) ++{ + set_bit(SAS_HA_DRAINING, &ha->state); + /* flush submitters */ + spin_lock_irq(&ha->lock); +@@ -72,16 +83,8 @@ void __sas_drain_work(struct sas_ha_struct *ha) + drain_workqueue(ha->event_q); + drain_workqueue(ha->disco_q); + +- spin_lock_irq(&ha->lock); + clear_bit(SAS_HA_DRAINING, &ha->state); +- list_for_each_entry_safe(sw, _sw, &ha->defer_q, drain_node) { +- list_del_init(&sw->drain_node); +- ret = sas_queue_work(ha, sw); +- if (ret != 1) +- sas_free_event(to_asd_sas_event(&sw->work)); +- +- } +- spin_unlock_irq(&ha->lock); ++ sas_queue_deferred_work(ha); + } + + int sas_drain_work(struct sas_ha_struct *ha) +diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h +index 1f314f1da994..4427c15ccbf4 100644 +--- a/drivers/scsi/libsas/sas_internal.h ++++ b/drivers/scsi/libsas/sas_internal.h +@@ -71,6 +71,7 @@ void sas_unregister_ports(struct sas_ha_struct *sas_ha); + int sas_init_events(struct sas_ha_struct *sas_ha); + void sas_disable_revalidation(struct sas_ha_struct *ha); + void sas_enable_revalidation(struct sas_ha_struct *ha); ++void sas_queue_deferred_work(struct sas_ha_struct *ha); + void __sas_drain_work(struct sas_ha_struct *ha); + + void sas_deform_port(struct asd_sas_phy *phy, int gone); +-- +2.27.0 + diff --git a/patches/0511-scsi-libsas-Defer-works-of-new-phys-during-suspend.patch b/patches/0511-scsi-libsas-Defer-works-of-new-phys-during-suspend.patch new file mode 100644 index 00000000..d0c2c607 --- /dev/null +++ b/patches/0511-scsi-libsas-Defer-works-of-new-phys-during-suspend.patch @@ -0,0 +1,107 @@ +From 5b069701ffe1722885f49ca6ff52306a40c7055d Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Tue, 19 Apr 2022 17:07:04 +0800 +Subject: [PATCH 193/256] scsi: libsas: Defer works of new phys during suspend + +mainline inclusion +from mainline-v5.17-rc1 +commit bf19aea4607cb5f4a652ab70d8d8035a72a6b8da +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bf19aea4607cb5f4a652ab70d8d8035a72a6b8da + +---------------------------------------------------------------------- + +During the processing of event PORT_BYTES_DMAED, the driver queues work +DISCE_DISCOVER_DOMAIN and then flushes workqueue ha->disco_q. If a new +phyup event occurs during resuming the controller, the work +PORTE_BYTES_DMAED of new phy occurs before suspended phy's. The work +DISCE_DISCOVER_DOMAIN of new phy requires an active SAS controller (it +needs to resume SAS controller by function scsi_sysfs_add_sdev() and some +other functions such as function add_device_link()). However, the +activation of the SAS controller requires completion of work +PORTE_BYTES_DMAED of suspended phys while it is blocked by new phy's work +on ha->event_q. So there is a deadlock and it is released only after resume +timeout. + +To solve the issue, defer works of new phys during suspend and queue those +defer works after SAS controller becomes active. + +Link: https://lore.kernel.org/r/1639999298-244569-13-git-send-email-chenxiang66@hisilicon.com +Reviewed-by: John Garry +Signed-off-by: Xiang Chen +Signed-off-by: Martin K. Petersen +Signed-off-by: Fujai Ni +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/libsas/sas_event.c | 24 ++++++++++++++++++++++++ + drivers/scsi/libsas/sas_init.c | 1 + + 2 files changed, 25 insertions(+) + +diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c +index 7846eb0e2ce0..f3b8224da9cf 100644 +--- a/drivers/scsi/libsas/sas_event.c ++++ b/drivers/scsi/libsas/sas_event.c +@@ -156,6 +156,24 @@ static void sas_phy_event_worker(struct work_struct *work) + sas_free_event(ev); + } + ++/* defer works of new phys during suspend */ ++static bool sas_defer_event(struct asd_sas_phy *phy, struct asd_sas_event *ev) ++{ ++ struct sas_ha_struct *ha = phy->ha; ++ unsigned long flags; ++ bool deferred = false; ++ ++ spin_lock_irqsave(&ha->lock, flags); ++ if (test_bit(SAS_HA_RESUMING, &ha->state) && !phy->suspended) { ++ struct sas_work *sw = &ev->work; ++ ++ list_add_tail(&sw->drain_node, &ha->defer_q); ++ deferred = true; ++ } ++ spin_unlock_irqrestore(&ha->lock, flags); ++ return deferred; ++} ++ + int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event, + gfp_t gfp_flags) + { +@@ -171,6 +189,9 @@ int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event, + + INIT_SAS_EVENT(ev, sas_port_event_worker, phy, event); + ++ if (sas_defer_event(phy, ev)) ++ return 0; ++ + ret = sas_queue_event(event, &ev->work, ha); + if (ret != 1) + sas_free_event(ev); +@@ -194,6 +215,9 @@ int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event, + + INIT_SAS_EVENT(ev, sas_phy_event_worker, phy, event); + ++ if (sas_defer_event(phy, ev)) ++ return 0; ++ + ret = sas_queue_event(event, &ev->work, ha); + if (ret != 1) + sas_free_event(ev); +diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c +index 8871d7ff17d8..2c875f9c07a0 100644 +--- a/drivers/scsi/libsas/sas_init.c ++++ b/drivers/scsi/libsas/sas_init.c +@@ -466,6 +466,7 @@ static void _sas_resume_ha(struct sas_ha_struct *ha, bool drain) + sas_drain_work(ha); + clear_bit(SAS_HA_RESUMING, &ha->state); + ++ sas_queue_deferred_work(ha); + /* send event PORTE_BROADCAST_RCVD to identify some new inserted + * disks for expander + */ +-- +2.27.0 + diff --git a/patches/0512-scsi-hisi_sas-Keep-controller-active-between-ISR-of-.patch b/patches/0512-scsi-hisi_sas-Keep-controller-active-between-ISR-of-.patch new file mode 100644 index 00000000..ff21a566 --- /dev/null +++ b/patches/0512-scsi-hisi_sas-Keep-controller-active-between-ISR-of-.patch @@ -0,0 +1,121 @@ +From e0a4124363e1360ba9d0f57a39e0392a754be1ca Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Tue, 19 Apr 2022 17:07:05 +0800 +Subject: [PATCH 194/256] scsi: hisi_sas: Keep controller active between ISR of + phyup and the event being processed + +mainline inclusion +from mainline-v5.17-rc1 +commit ae9b69e85eb7ecb32ddce7c04a10a3c69ad60e52 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ae9b69e85eb7ecb32ddce7c04a10a3c69ad60e52 + +---------------------------------------------------------------------- + +It is possible that controller may become suspended between processing a +phyup interrupt and the event being processed by libsas. As such, we can't +ensure the controller is active when processing the phyup event - this may +cause the phyup event to be lost or other issues. To avoid any possible +issues, add pm_runtime_get_noresume() in phyup interrupt handler and +pm_runtime_put_sync() in the work handler exit to ensure that we stay +always active. Since we only want to call pm_runtime_get_noresume() for v3 +hw, signal this will a new event, HISI_PHYE_PHY_UP_PM. + +Link: https://lore.kernel.org/r/1639999298-244569-14-git-send-email-chenxiang66@hisilicon.com +Acked-by: John Garry +Signed-off-by: Xiang Chen +Signed-off-by: Martin K. Petersen +Signed-off-by: Fujai Ni +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas.h | 1 + + drivers/scsi/hisi_sas/hisi_sas_main.c | 22 ++++++++++++++++++++-- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 4 +++- + 3 files changed, 24 insertions(+), 3 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 44118c4c807a..3c728cdfc364 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -168,6 +168,7 @@ enum hisi_sas_bit_err_type { + enum hisi_sas_phy_event { + HISI_PHYE_PHY_UP = 0U, + HISI_PHYE_LINK_RESET, ++ HISI_PHYE_PHY_UP_PM, + HISI_PHYES_NUM, + }; + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index f8e7d5a9d8b0..bca2bb2a2992 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -879,10 +879,11 @@ int hisi_sas_scan_finished(struct Scsi_Host *shost, unsigned long time) + } + EXPORT_SYMBOL_GPL(hisi_sas_scan_finished); + +-static void hisi_sas_phyup_work(struct work_struct *work) ++static void hisi_sas_phyup_work_common(struct work_struct *work, ++ enum hisi_sas_phy_event event) + { + struct hisi_sas_phy *phy = +- container_of(work, typeof(*phy), works[HISI_PHYE_PHY_UP]); ++ container_of(work, typeof(*phy), works[event]); + struct hisi_hba *hisi_hba = phy->hisi_hba; + struct asd_sas_phy *sas_phy = &phy->sas_phy; + int phy_no = sas_phy->id; +@@ -893,6 +894,11 @@ static void hisi_sas_phyup_work(struct work_struct *work) + hisi_sas_bytes_dmaed(hisi_hba, phy_no, GFP_KERNEL); + } + ++static void hisi_sas_phyup_work(struct work_struct *work) ++{ ++ hisi_sas_phyup_work_common(work, HISI_PHYE_PHY_UP); ++} ++ + static void hisi_sas_linkreset_work(struct work_struct *work) + { + struct hisi_sas_phy *phy = +@@ -902,9 +908,21 @@ static void hisi_sas_linkreset_work(struct work_struct *work) + hisi_sas_control_phy(sas_phy, PHY_FUNC_LINK_RESET, NULL); + } + ++static void hisi_sas_phyup_pm_work(struct work_struct *work) ++{ ++ struct hisi_sas_phy *phy = ++ container_of(work, typeof(*phy), works[HISI_PHYE_PHY_UP_PM]); ++ struct hisi_hba *hisi_hba = phy->hisi_hba; ++ struct device *dev = hisi_hba->dev; ++ ++ hisi_sas_phyup_work_common(work, HISI_PHYE_PHY_UP_PM); ++ pm_runtime_put_sync(dev); ++} ++ + static const work_func_t hisi_sas_phye_fns[HISI_PHYES_NUM] = { + [HISI_PHYE_PHY_UP] = hisi_sas_phyup_work, + [HISI_PHYE_LINK_RESET] = hisi_sas_linkreset_work, ++ [HISI_PHYE_PHY_UP_PM] = hisi_sas_phyup_pm_work, + }; + + bool hisi_sas_notify_phy_event(struct hisi_sas_phy *phy, +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 0be9f2a35931..8698ac4c3a88 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -1713,7 +1713,9 @@ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba) + + phy->port_id = port_id; + phy->phy_attached = 1; +- hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP); ++ /* Call pm_runtime_put_sync() with pairs in hisi_sas_phyup_pm_work() */ ++ pm_runtime_get_noresume(dev); ++ hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP_PM); + res = IRQ_HANDLED; + end: + if (phy->reset_completion) +-- +2.27.0 + diff --git a/patches/0513-scsi-libsas-Keep-host-active-while-processing-events.patch b/patches/0513-scsi-libsas-Keep-host-active-while-processing-events.patch new file mode 100644 index 00000000..64a3d00f --- /dev/null +++ b/patches/0513-scsi-libsas-Keep-host-active-while-processing-events.patch @@ -0,0 +1,125 @@ +From cf8dd937b191df56e6ba13fbf72698a2b7c5d9e0 Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Tue, 19 Apr 2022 17:07:06 +0800 +Subject: [PATCH 195/256] scsi: libsas: Keep host active while processing + events + +mainline inclusion +from mainline-v5.17-rc1 +commit 307d9f49cce966c2ba969f58bd6227bc0092afaa +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=307d9f49cce966c2ba969f58bd6227bc0092afaa + +---------------------------------------------------------------------- + +Processing events such as PORTE_BROADCAST_RCVD may cause dependency issues +for runtime power management support. Such a problem would be that +handling a PORTE_BROADCAST_RCVD event requires that the host is resumed to +send SMP commands. However, in resuming the host, the phyup events +generated from re-enabling the phys are processed in the same workqueue as +the original PORTE_BROADCAST_RCVD event. As such, the host will never +finish resuming (as it waits for the phyup event processing), and then the +PORTE_BROADCAST_RCVD event can't be processed as the SMP commands are +blocked, and so we have a deadlock. Solve this problem by ensuring that +libsas keeps the host active until completely finished phy or port events, +such as PORTE_BYTES_DMAED. As such, we don't have to worry about resuming +the host for processing individual SMP commands in this example. + +Link: https://lore.kernel.org/r/1639999298-244569-15-git-send-email-chenxiang66@hisilicon.com +Reviewed-by: John Garry +Signed-off-by: Xiang Chen +Signed-off-by: Martin K. Petersen +Signed-off-by: Fujai Ni +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/libsas/sas_event.c | 24 +++++++++++++++++++++--- + 1 file changed, 21 insertions(+), 3 deletions(-) + +diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c +index f3b8224da9cf..135f68c606ee 100644 +--- a/drivers/scsi/libsas/sas_event.c ++++ b/drivers/scsi/libsas/sas_event.c +@@ -67,8 +67,10 @@ void sas_queue_deferred_work(struct sas_ha_struct *ha) + list_for_each_entry_safe(sw, _sw, &ha->defer_q, drain_node) { + list_del_init(&sw->drain_node); + ret = sas_queue_work(ha, sw); +- if (ret != 1) ++ if (ret != 1) { ++ pm_runtime_put(ha->dev); + sas_free_event(to_asd_sas_event(&sw->work)); ++ } + } + spin_unlock_irq(&ha->lock); + } +@@ -143,16 +145,22 @@ void sas_enable_revalidation(struct sas_ha_struct *ha) + static void sas_port_event_worker(struct work_struct *work) + { + struct asd_sas_event *ev = to_asd_sas_event(work); ++ struct asd_sas_phy *phy = ev->phy; ++ struct sas_ha_struct *ha = phy->ha; + + sas_port_event_fns[ev->event](work); ++ pm_runtime_put(ha->dev); + sas_free_event(ev); + } + + static void sas_phy_event_worker(struct work_struct *work) + { + struct asd_sas_event *ev = to_asd_sas_event(work); ++ struct asd_sas_phy *phy = ev->phy; ++ struct sas_ha_struct *ha = phy->ha; + + sas_phy_event_fns[ev->event](work); ++ pm_runtime_put(ha->dev); + sas_free_event(ev); + } + +@@ -187,14 +195,19 @@ int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event, + if (!ev) + return -ENOMEM; + ++ /* Call pm_runtime_put() with pairs in sas_port_event_worker() */ ++ pm_runtime_get_noresume(ha->dev); ++ + INIT_SAS_EVENT(ev, sas_port_event_worker, phy, event); + + if (sas_defer_event(phy, ev)) + return 0; + + ret = sas_queue_event(event, &ev->work, ha); +- if (ret != 1) ++ if (ret != 1) { ++ pm_runtime_put(ha->dev); + sas_free_event(ev); ++ } + + return ret; + } +@@ -213,14 +226,19 @@ int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event, + if (!ev) + return -ENOMEM; + ++ /* Call pm_runtime_put() with pairs in sas_phy_event_worker() */ ++ pm_runtime_get_noresume(ha->dev); ++ + INIT_SAS_EVENT(ev, sas_phy_event_worker, phy, event); + + if (sas_defer_event(phy, ev)) + return 0; + + ret = sas_queue_event(event, &ev->work, ha); +- if (ret != 1) ++ if (ret != 1) { ++ pm_runtime_put(ha->dev); + sas_free_event(ev); ++ } + + return ret; + } +-- +2.27.0 + diff --git a/patches/0514-scsi-hisi_sas-Use-autosuspend-for-the-host-controlle.patch b/patches/0514-scsi-hisi_sas-Use-autosuspend-for-the-host-controlle.patch new file mode 100644 index 00000000..a9ecde2c --- /dev/null +++ b/patches/0514-scsi-hisi_sas-Use-autosuspend-for-the-host-controlle.patch @@ -0,0 +1,50 @@ +From 87021e51285eed784f807497153837478cf46c57 Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Tue, 19 Apr 2022 17:07:07 +0800 +Subject: [PATCH 196/256] scsi: hisi_sas: Use autosuspend for the host + controller + +mainline inclusion +from mainline-v5.17-rc1 +commit b4cc09492263e07bad4fc4bf34fed3246fa95057 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b4cc09492263e07bad4fc4bf34fed3246fa95057 + +---------------------------------------------------------------------- + +The controller may frequently enter and exit suspend for each I/O which we +need to deal with. This is inefficient and may cause too much suspend and +resume activity for the controller. To avoid this, use a default 5s +autosuspend for the controller to stop frequently suspending and +resuming. This value may still be modified via sysfs interfaces. + +Link: https://lore.kernel.org/r/1639999298-244569-16-git-send-email-chenxiang66@hisilicon.com +Acked-by: John Garry +Signed-off-by: Xiang Chen +Signed-off-by: Martin K. Petersen +Signed-off-by: Fujai Ni +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 8698ac4c3a88..0e504dcdeb4c 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -5166,6 +5166,8 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) + + scsi_scan_host(shost); + ++ pm_runtime_set_autosuspend_delay(dev, 5000); ++ pm_runtime_use_autosuspend(dev); + /* + * For the situation that there are ATA disks connected with SAS + * controller, it additionally creates ata_port which will affect the +-- +2.27.0 + diff --git a/patches/0515-scsi-hisi_sas-Limit-users-changing-debugfs-BIST-coun.patch b/patches/0515-scsi-hisi_sas-Limit-users-changing-debugfs-BIST-coun.patch new file mode 100644 index 00000000..88d32ece --- /dev/null +++ b/patches/0515-scsi-hisi_sas-Limit-users-changing-debugfs-BIST-coun.patch @@ -0,0 +1,109 @@ +From 96df5ffd0b2b20772bcaeb85ec4af32faa0813ff Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Thu, 21 Apr 2022 21:50:06 +0800 +Subject: [PATCH 197/256] scsi: hisi_sas: Limit users changing debugfs BIST + count value + +mainline inclusion +from mainline-v5.17-rc1 +commit ae9b69e85eb7ecb32ddce7c04a10a3c69ad60e52 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ae9b69e85eb7ecb32ddce7c04a10a3c69ad60e52 + +---------------------------------------------------------------------- + +Add a file operation for "cnt" file under bist directory, so users can only +read "cnt" or clear "cnt" to zero, but cannot randomly modify. + +Link: https://lore.kernel.org/r/1645703489-87194-6-git-send-email-john.garry@huawei.com +Signed-off-by: Xiang Chen +Signed-off-by: Qi Liu +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: Fujai Ni +Reviewed-by: Jason Yan +Reviewed-by: Qi Liu +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 52 +++++++++++++++++++++++++- + 1 file changed, 50 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 0e504dcdeb4c..d32ad5f9f3e5 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -4348,6 +4348,54 @@ static const struct file_operations debugfs_bist_phy_v3_hw_fops = { + .owner = THIS_MODULE, + }; + ++static ssize_t debugfs_bist_cnt_v3_hw_write(struct file *filp, ++ const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct seq_file *m = filp->private_data; ++ struct hisi_hba *hisi_hba = m->private; ++ unsigned int cnt; ++ int val; ++ ++ if (hisi_hba->bist_loopback_enable) ++ return -EPERM; ++ ++ val = kstrtouint_from_user(buf, count, 0, &cnt); ++ if (val) ++ return val; ++ ++ if (cnt) ++ return -EINVAL; ++ ++ hisi_hba->bist_loopback_cnt = 0; ++ return count; ++} ++ ++static int debugfs_bist_cnt_v3_hw_show(struct seq_file *s, void *p) ++{ ++ struct hisi_hba *hisi_hba = s->private; ++ ++ seq_printf(s, "%u\n", hisi_hba->bist_loopback_cnt); ++ ++ return 0; ++} ++ ++static int debugfs_bist_cnt_v3_hw_open(struct inode *inode, ++ struct file *filp) ++{ ++ return single_open(filp, debugfs_bist_cnt_v3_hw_show, ++ inode->i_private); ++} ++ ++static const struct file_operations debugfs_bist_cnt_v3_hw_ops = { ++ .open = debugfs_bist_cnt_v3_hw_open, ++ .read = seq_read, ++ .write = debugfs_bist_cnt_v3_hw_write, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .owner = THIS_MODULE, ++}; ++ + static const struct { + int value; + char *name; +@@ -4986,8 +5034,8 @@ static void debugfs_bist_init_v3_hw(struct hisi_hba *hisi_hba) + debugfs_create_file("phy_id", 0600, hisi_hba->debugfs_bist_dentry, + hisi_hba, &debugfs_bist_phy_v3_hw_fops); + +- debugfs_create_u32("cnt", 0600, hisi_hba->debugfs_bist_dentry, +- &hisi_hba->bist_loopback_cnt); ++ debugfs_create_file("cnt", 0600, hisi_hba->debugfs_bist_dentry, ++ hisi_hba, &debugfs_bist_cnt_v3_hw_ops); + + debugfs_create_file("loopback_mode", 0600, + hisi_hba->debugfs_bist_dentry, +-- +2.27.0 + diff --git a/patches/0516-genirq-msi-Shutdown-managed-interrupts-with-unsatifi.patch b/patches/0516-genirq-msi-Shutdown-managed-interrupts-with-unsatifi.patch new file mode 100644 index 00000000..e0ec1458 --- /dev/null +++ b/patches/0516-genirq-msi-Shutdown-managed-interrupts-with-unsatifi.patch @@ -0,0 +1,76 @@ +From 49d6cb0118fdc1e0a1885d5cfc5cdebe0cb43aac Mon Sep 17 00:00:00 2001 +From: Marc Zyngier +Date: Wed, 6 Jul 2022 18:05:37 +0800 +Subject: [PATCH 198/256] genirq/msi: Shutdown managed interrupts with + unsatifiable affinities + +mainline inclusion +from mainline-v5.19-rc1 +commit d802057c7c553ad426520a053da9f9fe08e2c35a +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d802057c7c553ad426520a053da9f9fe08e2c35a + +---------------------------------------------------------------------- + +When booting with maxcpus=, interrupt controllers +such as the GICv3 ITS may not be able to satisfy the affinity of +some managed interrupts, as some of the HW resources are simply +not available. + +The same thing happens when loading a driver using managed interrupts +while CPUs are offline. + +In order to deal with this, do not try to activate such interrupt +if there is no online CPU capable of handling it. Instead, place +it in shutdown state. Once a capable CPU shows up, it will be +activated. + +Reported-by: John Garry +Reported-by: David Decotigny +Signed-off-by: Marc Zyngier +Signed-off-by: Thomas Gleixner +Tested-by: John Garry +Link: https://lore.kernel.org/r/20220405185040.206297-2-maz@kernel.org + +conflict: + kernel/irq/msi.c + +Signed-off-by: Chen Jiahao +Reviewed-by: Zhang Jianhua +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + kernel/irq/msi.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c +index b7e4c5999cc8..f2c8b9706f76 100644 +--- a/kernel/irq/msi.c ++++ b/kernel/irq/msi.c +@@ -457,6 +457,21 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, + irqd_clr_can_reserve(irq_data); + if (domain->flags & IRQ_DOMAIN_MSI_NOMASK_QUIRK) + irqd_set_msi_nomask_quirk(irq_data); ++ ++ /* ++ * If the interrupt is managed but no CPU is available ++ * to service it, shut it down until better times. Note ++ * that we only do this on the !RESERVE path as x86 ++ * (the only architecture using this flag) deals with ++ * this in a different way by using a catch-all vector. ++ */ ++ if ((info->flags & MSI_FLAG_ACTIVATE_EARLY) && ++ irqd_affinity_is_managed(irq_data) && ++ !cpumask_intersects(irq_data_get_affinity_mask(irq_data), ++ cpu_online_mask)) { ++ irqd_set_managed_shutdown(irq_data); ++ return 0; ++ } + } + ret = irq_domain_activate_irq(irq_data, can_reserve); + if (ret) +-- +2.27.0 + diff --git a/patches/0517-genirq-sched-isolation-Isolate-from-handling-managed.patch b/patches/0517-genirq-sched-isolation-Isolate-from-handling-managed.patch new file mode 100644 index 00000000..374ef45c --- /dev/null +++ b/patches/0517-genirq-sched-isolation-Isolate-from-handling-managed.patch @@ -0,0 +1,274 @@ +From be2ef5262e43bbff770c0064a48e718bf170b49a Mon Sep 17 00:00:00 2001 +From: Ming Lei +Date: Mon, 20 Jan 2020 17:16:25 +0800 +Subject: [PATCH 199/256] genirq, sched/isolation: Isolate from handling + managed interrupts + +mainline inclusion +from mainline-v5.6-rc1 +commit 11ea68f553e244851d15793a7fa33a97c46d8271 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=11ea68f553e244851d15793a7fa33a97c46d8271 + +---------------------------------------------------------------------- + +The affinity of managed interrupts is completely handled in the kernel and +cannot be changed via the /proc/irq/* interfaces from user space. As the +kernel tries to spread out interrupts evenly across CPUs on x86 to prevent +vector exhaustion, it can happen that a managed interrupt whose affinity +mask contains both isolated and housekeeping CPUs is routed to an isolated +CPU. As a consequence IO submitted on a housekeeping CPU causes interrupts +on the isolated CPU. + +Add a new sub-parameter 'managed_irq' for 'isolcpus' and the corresponding +logic in the interrupt affinity selection code. + +The subparameter indicates to the interrupt affinity selection logic that +it should try to avoid the above scenario. + +This isolation is best effort and only effective if the automatically +assigned interrupt mask of a device queue contains isolated and +housekeeping CPUs. If housekeeping CPUs are online then such interrupts are +directed to the housekeeping CPU so that IO submitted on the housekeeping +CPU cannot disturb the isolated CPU. + +If a queue's affinity mask contains only isolated CPUs then this parameter +has no effect on the interrupt routing decision, though interrupts are only +happening when tasks running on those isolated CPUs submit IO. IO submitted +on housekeeping CPUs has no influence on those queues. + +If the affinity mask contains both housekeeping and isolated CPUs, but none +of the contained housekeeping CPUs is online, then the interrupt is also +routed to an isolated CPU. Interrupts are only delivered when one of the +isolated CPUs in the affinity mask submits IO. If one of the contained +housekeeping CPUs comes online, the CPU hotplug logic migrates the +interrupt automatically back to the upcoming housekeeping CPU. Depending on +the type of interrupt controller, this can require that at least one +interrupt is delivered to the isolated CPU in order to complete the +migration. + +[ tglx: Removed unused parameter, added and edited comments/documentation + and rephrased the changelog so it contains more details. ] + +Signed-off-by: Ming Lei +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/r/20200120091625.17912-1-ming.lei@redhat.com +Signed-off-by: YunYi Yang +--- + .../admin-guide/kernel-parameters.txt | 26 +++++++++++- + include/linux/sched/isolation.h | 7 ++++ + kernel/irq/cpuhotplug.c | 21 +++++++++- + kernel/irq/manage.c | 41 ++++++++++++++++++- + kernel/sched/isolation.c | 12 ++++++ + 5 files changed, 102 insertions(+), 5 deletions(-) + +diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt +index 81c3e5e6447f..140079925980 100644 +--- a/Documentation/admin-guide/kernel-parameters.txt ++++ b/Documentation/admin-guide/kernel-parameters.txt +@@ -1931,9 +1931,31 @@ + begins at 0 and the maximum value is + "number of CPUs in system - 1". + +- The format of is described above. +- ++ managed_irq ++ ++ Isolate from being targeted by managed interrupts ++ which have an interrupt mask containing isolated ++ CPUs. The affinity of managed interrupts is ++ handled by the kernel and cannot be changed via ++ the /proc/irq/* interfaces. ++ ++ This isolation is best effort and only effective ++ if the automatically assigned interrupt mask of a ++ device queue contains isolated and housekeeping ++ CPUs. If housekeeping CPUs are online then such ++ interrupts are directed to the housekeeping CPU ++ so that IO submitted on the housekeeping CPU ++ cannot disturb the isolated CPU. ++ ++ If a queue's affinity mask contains only isolated ++ CPUs then this parameter has no effect on the ++ interrupt routing decision, though interrupts are ++ only delivered when tasks running on those ++ isolated CPUs submit IO. IO submitted on ++ housekeeping CPUs has no influence on those ++ queues. + ++ The format of is described above. + + iucv= [HW,NET] + +diff --git a/include/linux/sched/isolation.h b/include/linux/sched/isolation.h +index 4a6582c27dea..461e1f6ab3eb 100644 +--- a/include/linux/sched/isolation.h ++++ b/include/linux/sched/isolation.h +@@ -13,12 +13,14 @@ enum hk_flags { + HK_FLAG_TICK = (1 << 4), + HK_FLAG_DOMAIN = (1 << 5), + HK_FLAG_WQ = (1 << 6), ++ HK_FLAG_MANAGED_IRQ = (1 << 7), + }; + + #ifdef CONFIG_CPU_ISOLATION + DECLARE_STATIC_KEY_FALSE(housekeeping_overriden); + extern int housekeeping_any_cpu(enum hk_flags flags); + extern const struct cpumask *housekeeping_cpumask(enum hk_flags flags); ++extern bool housekeeping_enabled(enum hk_flags flags); + extern void housekeeping_affine(struct task_struct *t, enum hk_flags flags); + extern bool housekeeping_test_cpu(int cpu, enum hk_flags flags); + extern void __init housekeeping_init(void); +@@ -35,6 +37,11 @@ static inline const struct cpumask *housekeeping_cpumask(enum hk_flags flags) + return cpu_possible_mask; + } + ++static inline bool housekeeping_enabled(enum hk_flags flags) ++{ ++ return false; ++} ++ + static inline void housekeeping_affine(struct task_struct *t, + enum hk_flags flags) { } + static inline void housekeeping_init(void) { } +diff --git a/kernel/irq/cpuhotplug.c b/kernel/irq/cpuhotplug.c +index 6c7ca2e983a5..02236b13b359 100644 +--- a/kernel/irq/cpuhotplug.c ++++ b/kernel/irq/cpuhotplug.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + + #include "internals.h" + +@@ -171,6 +172,20 @@ void irq_migrate_all_off_this_cpu(void) + } + } + ++static bool hk_should_isolate(struct irq_data *data, unsigned int cpu) ++{ ++ const struct cpumask *hk_mask; ++ ++ if (!housekeeping_enabled(HK_FLAG_MANAGED_IRQ)) ++ return false; ++ ++ hk_mask = housekeeping_cpumask(HK_FLAG_MANAGED_IRQ); ++ if (cpumask_subset(irq_data_get_effective_affinity_mask(data), hk_mask)) ++ return false; ++ ++ return cpumask_test_cpu(cpu, hk_mask); ++} ++ + static void irq_restore_affinity_of_irq(struct irq_desc *desc, unsigned int cpu) + { + struct irq_data *data = irq_desc_get_irq_data(desc); +@@ -188,9 +203,11 @@ static void irq_restore_affinity_of_irq(struct irq_desc *desc, unsigned int cpu) + /* + * If the interrupt can only be directed to a single target + * CPU then it is already assigned to a CPU in the affinity +- * mask. No point in trying to move it around. ++ * mask. No point in trying to move it around unless the ++ * isolation mechanism requests to move it to an upcoming ++ * housekeeping CPU. + */ +- if (!irqd_is_single_target(data)) ++ if (!irqd_is_single_target(data) || hk_should_isolate(data, cpu)) + irq_set_affinity_locked(data, affinity, false); + } + +diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c +index 08ba1833c5bd..2d50c4bc8362 100644 +--- a/kernel/irq/manage.c ++++ b/kernel/irq/manage.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -227,7 +228,45 @@ int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask, + if (!chip || !chip->irq_set_affinity) + return -EINVAL; + +- ret = chip->irq_set_affinity(data, mask, force); ++ /* ++ * If this is a managed interrupt and housekeeping is enabled on ++ * it check whether the requested affinity mask intersects with ++ * a housekeeping CPU. If so, then remove the isolated CPUs from ++ * the mask and just keep the housekeeping CPU(s). This prevents ++ * the affinity setter from routing the interrupt to an isolated ++ * CPU to avoid that I/O submitted from a housekeeping CPU causes ++ * interrupts on an isolated one. ++ * ++ * If the masks do not intersect or include online CPU(s) then ++ * keep the requested mask. The isolated target CPUs are only ++ * receiving interrupts when the I/O operation was submitted ++ * directly from them. ++ * ++ * If all housekeeping CPUs in the affinity mask are offline, the ++ * interrupt will be migrated by the CPU hotplug code once a ++ * housekeeping CPU which belongs to the affinity mask comes ++ * online. ++ */ ++ if (irqd_affinity_is_managed(data) && ++ housekeeping_enabled(HK_FLAG_MANAGED_IRQ)) { ++ const struct cpumask *hk_mask, *prog_mask; ++ ++ static DEFINE_RAW_SPINLOCK(tmp_mask_lock); ++ static struct cpumask tmp_mask; ++ ++ hk_mask = housekeeping_cpumask(HK_FLAG_MANAGED_IRQ); ++ ++ raw_spin_lock(&tmp_mask_lock); ++ cpumask_and(&tmp_mask, mask, hk_mask); ++ if (!cpumask_intersects(&tmp_mask, cpu_online_mask)) ++ prog_mask = mask; ++ else ++ prog_mask = &tmp_mask; ++ ret = chip->irq_set_affinity(data, prog_mask, force); ++ raw_spin_unlock(&tmp_mask_lock); ++ } else { ++ ret = chip->irq_set_affinity(data, mask, force); ++ } + switch (ret) { + case IRQ_SET_MASK_OK: + case IRQ_SET_MASK_OK_DONE: +diff --git a/kernel/sched/isolation.c b/kernel/sched/isolation.c +index e6802181900f..6e85049d68cf 100644 +--- a/kernel/sched/isolation.c ++++ b/kernel/sched/isolation.c +@@ -13,6 +13,12 @@ EXPORT_SYMBOL_GPL(housekeeping_overriden); + static cpumask_var_t housekeeping_mask; + static unsigned int housekeeping_flags; + ++bool housekeeping_enabled(enum hk_flags flags) ++{ ++ return !!(housekeeping_flags & flags); ++} ++EXPORT_SYMBOL_GPL(housekeeping_enabled); ++ + int housekeeping_any_cpu(enum hk_flags flags) + { + if (static_branch_unlikely(&housekeeping_overriden)) +@@ -140,6 +146,12 @@ static int __init housekeeping_isolcpus_setup(char *str) + continue; + } + ++ if (!strncmp(str, "managed_irq,", 12)) { ++ str += 12; ++ flags |= HK_FLAG_MANAGED_IRQ; ++ continue; ++ } ++ + pr_warn("isolcpus: Error, unknown flag\n"); + return 0; + } +-- +2.27.0 + diff --git a/patches/0518-genirq-Always-limit-the-affinity-to-online-CPUs.patch b/patches/0518-genirq-Always-limit-the-affinity-to-online-CPUs.patch new file mode 100644 index 00000000..fde10d56 --- /dev/null +++ b/patches/0518-genirq-Always-limit-the-affinity-to-online-CPUs.patch @@ -0,0 +1,104 @@ +From 32ad70a86af5af58447a123e9d1498eec229f35d Mon Sep 17 00:00:00 2001 +From: Marc Zyngier +Date: Wed, 6 Jul 2022 18:05:38 +0800 +Subject: [PATCH 200/256] genirq: Always limit the affinity to online CPUs + +mainline inclusion +from mainline-v5.19-rc1 +commit 33de0aa4bae982ed6f7c777f86b5af3e627ac937 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=33de0aa4bae982ed6f7c777f86b5af3e627ac937 + +---------------------------------------------------------------------- + +When booting with maxcpus= (or even loading a driver +while most CPUs are offline), it is pretty easy to observe managed +affinities containing a mix of online and offline CPUs being passed +to the irqchip driver. + +This means that the irqchip cannot trust the affinity passed down +from the core code, which is a bit annoying and requires (at least +in theory) all drivers to implement some sort of affinity narrowing. + +In order to address this, always limit the cpumask to the set of +online CPUs. + +Signed-off-by: Marc Zyngier +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/r/20220405185040.206297-3-maz@kernel.org + +conflict: + kernel/irq/manage.c + +Signed-off-by: Chen Jiahao +Reviewed-by: Zhang Jianhua +Reviewed-by: Liao Chang +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + kernel/irq/manage.c | 25 +++++++++++++++++-------- + 1 file changed, 17 insertions(+), 8 deletions(-) + +diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c +index 2d50c4bc8362..3cc91a3587a4 100644 +--- a/kernel/irq/manage.c ++++ b/kernel/irq/manage.c +@@ -223,11 +223,16 @@ int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask, + { + struct irq_desc *desc = irq_data_to_desc(data); + struct irq_chip *chip = irq_data_get_irq_chip(data); ++ const struct cpumask *prog_mask; + int ret; + ++ static DEFINE_RAW_SPINLOCK(tmp_mask_lock); ++ static struct cpumask tmp_mask; ++ + if (!chip || !chip->irq_set_affinity) + return -EINVAL; + ++ raw_spin_lock(&tmp_mask_lock); + /* + * If this is a managed interrupt and housekeeping is enabled on + * it check whether the requested affinity mask intersects with +@@ -249,24 +254,28 @@ int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask, + */ + if (irqd_affinity_is_managed(data) && + housekeeping_enabled(HK_FLAG_MANAGED_IRQ)) { +- const struct cpumask *hk_mask, *prog_mask; +- +- static DEFINE_RAW_SPINLOCK(tmp_mask_lock); +- static struct cpumask tmp_mask; ++ const struct cpumask *hk_mask; + + hk_mask = housekeeping_cpumask(HK_FLAG_MANAGED_IRQ); + +- raw_spin_lock(&tmp_mask_lock); + cpumask_and(&tmp_mask, mask, hk_mask); + if (!cpumask_intersects(&tmp_mask, cpu_online_mask)) + prog_mask = mask; + else + prog_mask = &tmp_mask; +- ret = chip->irq_set_affinity(data, prog_mask, force); +- raw_spin_unlock(&tmp_mask_lock); + } else { +- ret = chip->irq_set_affinity(data, mask, force); ++ prog_mask = mask; + } ++ ++ /* Make sure we only provide online CPUs to the irqchip */ ++ cpumask_and(&tmp_mask, prog_mask, cpu_online_mask); ++ if (!cpumask_empty(&tmp_mask)) ++ ret = chip->irq_set_affinity(data, &tmp_mask, force); ++ else ++ ret = -EINVAL; ++ ++ raw_spin_unlock(&tmp_mask_lock); ++ + switch (ret) { + case IRQ_SET_MASK_OK: + case IRQ_SET_MASK_OK_DONE: +-- +2.27.0 + diff --git a/patches/0519-irqchip-gic-v3-Always-trust-the-managed-affinity-pro.patch b/patches/0519-irqchip-gic-v3-Always-trust-the-managed-affinity-pro.patch new file mode 100644 index 00000000..dc013734 --- /dev/null +++ b/patches/0519-irqchip-gic-v3-Always-trust-the-managed-affinity-pro.patch @@ -0,0 +1,48 @@ +From 79f2e8a2790fb9b34d56abf3bd0170eacebe1bc6 Mon Sep 17 00:00:00 2001 +From: Marc Zyngier +Date: Wed, 6 Jul 2022 18:05:39 +0800 +Subject: [PATCH 201/256] irqchip/gic-v3: Always trust the managed affinity + provided by the core code + +mainline inclusion +from mainline-v5.19-rc1 +commit 3f893a5962d31c0164efdbf6174ed0784f1d7603 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3f893a5962d31c0164efdbf6174ed0784f1d7603 + +---------------------------------------------------------------------- + +Now that the core code has been fixed to always give us an affinity +that only includes online CPUs, directly use this affinity when +computing a target CPU. + +Signed-off-by: Marc Zyngier +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/r/20220405185040.206297-4-maz@kernel.org +Signed-off-by: Chen Jiahao +Reviewed-by: Zhang Jianhua +Reviewed-by: Liao Chang +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/irqchip/irq-gic-v3-its.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c +index 463a77cef8a3..71e1689a32e7 100644 +--- a/drivers/irqchip/irq-gic-v3-its.c ++++ b/drivers/irqchip/irq-gic-v3-its.c +@@ -1274,7 +1274,7 @@ static int its_select_cpu(struct irq_data *d, + + cpu = cpumask_pick_least_loaded(d, tmpmask); + } else { +- cpumask_and(tmpmask, irq_data_get_affinity_mask(d), cpu_online_mask); ++ cpumask_copy(tmpmask, aff_mask); + + /* If we cannot cross sockets, limit the search to that node */ + if ((its_dev->its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) && +-- +2.27.0 + diff --git a/patches/0520-blk-mq-Fix-blk_mq_tagset_busy_iter-for-shared-tags.patch b/patches/0520-blk-mq-Fix-blk_mq_tagset_busy_iter-for-shared-tags.patch new file mode 100644 index 00000000..8c52473b --- /dev/null +++ b/patches/0520-blk-mq-Fix-blk_mq_tagset_busy_iter-for-shared-tags.patch @@ -0,0 +1,57 @@ +From c480e0e76967ea0c1155853d63efc17f33c35ecb Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 3 Nov 2022 18:48:54 +0800 +Subject: [PATCH 202/256] blk-mq: Fix blk_mq_tagset_busy_iter() for shared tags + +mainline inclusion +from mainline-v5.16-rc1 +commit 0994c64eb4159ba019e7fedc7ba0dd6a69235b40 +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0994c64eb4159ba019e7fedc7ba0dd6a69235b40 + +---------------------------------------------------------------------- + +Since it is now possible for a tagset to share a single set of tags, the +iter function should not re-iter the tags for the count of #hw queues in +that case. Rather it should just iter once. + +Fixes: e155b0c238b2 ("blk-mq: Use shared tags for shared sbitmap support") +Reported-by: Kashyap Desai +Signed-off-by: John Garry +Reviewed-by: Ming Lei +Tested-by: Kashyap Desai +Link: https://lore.kernel.org/r/1634550083-202815-1-git-send-email-john.garry@huawei.com +Signed-off-by: Jens Axboe +Signed-off-by: Zhang Wensheng +Reviewed-by: Yu Kuai +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + block/blk-mq-tag.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c +index 3a714775b588..8993da9fe175 100644 +--- a/block/blk-mq-tag.c ++++ b/block/blk-mq-tag.c +@@ -316,9 +316,12 @@ static void blk_mq_all_tag_busy_iter(struct blk_mq_tags *tags, + void blk_mq_tagset_busy_iter(struct blk_mq_tag_set *tagset, + busy_tag_iter_fn *fn, void *priv) + { +- int i; ++ unsigned int flags = tagset->flags; ++ int i, nr_tags; ++ ++ nr_tags = blk_mq_is_sbitmap_shared(flags) ? 1 : tagset->nr_hw_queues; + +- for (i = 0; i < tagset->nr_hw_queues; i++) { ++ for (i = 0; i < nr_tags; i++) { + if (tagset->tags && tagset->tags[i]) + blk_mq_all_tag_busy_iter(tagset->tags[i], fn, priv); + } +-- +2.27.0 + diff --git a/patches/0521-scsi-libsas-Resume-SAS-host-for-phy-reset-or-enable-.patch b/patches/0521-scsi-libsas-Resume-SAS-host-for-phy-reset-or-enable-.patch new file mode 100644 index 00000000..2d3ef075 --- /dev/null +++ b/patches/0521-scsi-libsas-Resume-SAS-host-for-phy-reset-or-enable-.patch @@ -0,0 +1,73 @@ +From 894592185e3517669a22988a1cda342bf24b2dae Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Thu, 3 Nov 2022 18:49:28 +0800 +Subject: [PATCH 203/256] scsi: libsas: Resume SAS host for phy reset or enable + via sysfs + +mainline inclusion +from mainline-v6.0-rc1 +commit 1e82e4627a795aa33af0309c8f526df09abad188 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1e82e4627a795aa33af0309c8f526df09abad188 + +---------------------------------------------------------------------- + +Currently if a phy reset or enable phy is issued via sysfs when controller +is suspended, those operations will be ignored as SAS_HA_REGISTERED is +cleared. If RPM is enabled then we may aggressively suspend automatically. +In this case it may be difficult to enable or reset a phy via sysfs, so +resume the host in these scenarios. + +Link: https://lore.kernel.org/r/1657823002-139010-6-git-send-email-john.garry@huawei.com +Signed-off-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: xiabing +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/libsas/sas_init.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c +index 2c875f9c07a0..a2d449385504 100644 +--- a/drivers/scsi/libsas/sas_init.c ++++ b/drivers/scsi/libsas/sas_init.c +@@ -551,6 +551,7 @@ static int queue_phy_reset(struct sas_phy *phy, int hard_reset) + if (!d) + return -ENOMEM; + ++ pm_runtime_get_sync(ha->dev); + /* libsas workqueue coordinates ata-eh reset with discovery */ + mutex_lock(&d->event_lock); + d->reset_result = 0; +@@ -564,6 +565,7 @@ static int queue_phy_reset(struct sas_phy *phy, int hard_reset) + if (rc == 0) + rc = d->reset_result; + mutex_unlock(&d->event_lock); ++ pm_runtime_put_sync(ha->dev); + + return rc; + } +@@ -578,6 +580,7 @@ static int queue_phy_enable(struct sas_phy *phy, int enable) + if (!d) + return -ENOMEM; + ++ pm_runtime_get_sync(ha->dev); + /* libsas workqueue coordinates ata-eh reset with discovery */ + mutex_lock(&d->event_lock); + d->enable_result = 0; +@@ -591,6 +594,7 @@ static int queue_phy_enable(struct sas_phy *phy, int enable) + if (rc == 0) + rc = d->enable_result; + mutex_unlock(&d->event_lock); ++ pm_runtime_put_sync(ha->dev); + + return rc; + } +-- +2.27.0 + diff --git a/patches/0522-scsi-hisi_sas-Prevent-parallel-controller-reset-and-.patch b/patches/0522-scsi-hisi_sas-Prevent-parallel-controller-reset-and-.patch new file mode 100644 index 00000000..da7ea3a3 --- /dev/null +++ b/patches/0522-scsi-hisi_sas-Prevent-parallel-controller-reset-and-.patch @@ -0,0 +1,62 @@ +From 806572628478a02eca1a4eb5b2fe8b2bdf9dbeb4 Mon Sep 17 00:00:00 2001 +From: Qi Liu +Date: Tue, 15 Nov 2022 23:03:40 +0800 +Subject: [PATCH 204/256] scsi: hisi_sas: Prevent parallel controller reset and + control phy command + +mainline inclusion +from mainline-v5.17-rc1 +commit 20c634932ae8978435645b466c99b3fc1a80545a +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F82X + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=20c634932ae8978435645b466c99b3fc1a80545a + +---------------------------------------------------------------------- + +A user may issue a control phy command from sysfs at any time, even if the +controller is resetting. + +If a phy is disabled by hardreset/linkreset command before calling +get_phys_state() in the reset path, the saved phy state may be incorrect. + +To avoid incorrectly recording the phy state, use hisi_hba.sem to ensure +that the controller reset may not run at the same time as when the phy +control function is running. + +Link: https://lore.kernel.org/r/1639579061-179473-6-git-send-email-john.garry@huawei.com +Signed-off-by: Qi Liu +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: xiabing +Reviewed-by: Xiang Chen +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index bca2bb2a2992..7ad3d4006275 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1212,6 +1212,7 @@ static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func, + u8 sts = phy->phy_attached; + int ret = 0; + ++ down(&hisi_hba->sem); + phy->reset_completion = &completion; + + switch (func) { +@@ -1256,6 +1257,7 @@ static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func, + out: + phy->reset_completion = NULL; + ++ up(&hisi_hba->sem); + return ret; + } + +-- +2.27.0 + diff --git a/patches/0523-scsi-hisi_sas-Fix-phyup-timeout-on-FPGA.patch b/patches/0523-scsi-hisi_sas-Fix-phyup-timeout-on-FPGA.patch new file mode 100644 index 00000000..a6d737ad --- /dev/null +++ b/patches/0523-scsi-hisi_sas-Fix-phyup-timeout-on-FPGA.patch @@ -0,0 +1,114 @@ +From a94e29d24ae4714d691d8ffa81135cd3a21c2506 Mon Sep 17 00:00:00 2001 +From: Qi Liu +Date: Tue, 15 Nov 2022 23:03:42 +0800 +Subject: [PATCH 205/256] scsi: hisi_sas: Fix phyup timeout on FPGA + +mainline inclusion +from mainline-v5.17-rc1 +commit 37310bad7fa645b21653fd7f13cb6b376d80c919 +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=37310bad7fa645b21653fd7f13cb6b376d80c919 + +---------------------------------------------------------------------- + +The OOB interrupt and phyup interrupt handlers may run out-of-order in high +CPU usage scenarios. Since the hisi_sas_phy.timer is added in +hisi_sas_phy_oob_ready() and disarmed in phy_up_v3_hw(), this out-of-order +execution will cause hisi_sas_phy.timer timeout to trigger. + +To solve, protect hisi_sas_phy.timer and .attached with a lock, and ensure +that the timer won't be added after phyup handler completes. + +Link: https://lore.kernel.org/r/1639579061-179473-8-git-send-email-john.garry@huawei.com +Signed-off-by: Qi Liu +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: xiabing +Reviewed-by: Xiang Chen +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 18 +++++++++++++----- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 10 ++++++++-- + 2 files changed, 21 insertions(+), 7 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 7ad3d4006275..453754f2b400 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -954,10 +954,14 @@ void hisi_sas_phy_oob_ready(struct hisi_hba *hisi_hba, int phy_no) + { + struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; + struct device *dev = hisi_hba->dev; ++ unsigned long flags; + + dev_dbg(dev, "phy%d OOB ready\n", phy_no); +- if (phy->phy_attached) ++ spin_lock_irqsave(&phy->lock, flags); ++ if (phy->phy_attached) { ++ spin_unlock_irqrestore(&phy->lock, flags); + return; ++ } + + if (!timer_pending(&phy->timer)) { + if (phy->wait_phyup_cnt < HISI_SAS_WAIT_PHYUP_RETRIES) { +@@ -965,13 +969,17 @@ void hisi_sas_phy_oob_ready(struct hisi_hba *hisi_hba, int phy_no) + phy->timer.expires = jiffies + + HISI_SAS_WAIT_PHYUP_TIMEOUT; + add_timer(&phy->timer); +- } else { +- dev_warn(dev, "phy%d failed to come up %d times, giving up\n", +- phy_no, phy->wait_phyup_cnt); +- phy->wait_phyup_cnt = 0; ++ spin_unlock_irqrestore(&phy->lock, flags); ++ return; + } ++ ++ dev_warn(dev, "phy%d failed to come up %d times, giving up\n", ++ phy_no, phy->wait_phyup_cnt); ++ phy->wait_phyup_cnt = 0; + } ++ spin_unlock_irqrestore(&phy->lock, flags); + } ++ + EXPORT_SYMBOL_GPL(hisi_sas_phy_oob_ready); + + static void hisi_sas_phy_init(struct hisi_hba *hisi_hba, int phy_no) +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index d32ad5f9f3e5..a07bb33176c8 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -1632,7 +1632,6 @@ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba) + struct asd_sas_phy *sas_phy = &phy->sas_phy; + struct device *dev = hisi_hba->dev; + +- del_timer(&phy->timer); + hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 1); + + /* Port id store in 4 bits */ +@@ -1712,11 +1711,18 @@ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba) + } + + phy->port_id = port_id; +- phy->phy_attached = 1; ++ + /* Call pm_runtime_put_sync() with pairs in hisi_sas_phyup_pm_work() */ + pm_runtime_get_noresume(dev); + hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP_PM); ++ + res = IRQ_HANDLED; ++ ++ spin_lock(&phy->lock); ++ /* Delete timer and set phy_attached atomically */ ++ del_timer(&phy->timer); ++ phy->phy_attached = 1; ++ spin_unlock(&phy->lock); + end: + if (phy->reset_completion) + complete(phy->reset_completion); +-- +2.27.0 + diff --git a/patches/0524-scsi-hisi_sas-Modify-v3-HW-SSP-underflow-error-proce.patch b/patches/0524-scsi-hisi_sas-Modify-v3-HW-SSP-underflow-error-proce.patch new file mode 100644 index 00000000..ae0f5008 --- /dev/null +++ b/patches/0524-scsi-hisi_sas-Modify-v3-HW-SSP-underflow-error-proce.patch @@ -0,0 +1,197 @@ +From 46a2f63fbfed237547cdb42502ca9d7e1bfff43d Mon Sep 17 00:00:00 2001 +From: Xingui Yang +Date: Tue, 15 Nov 2022 23:03:44 +0800 +Subject: [PATCH 206/256] scsi: hisi_sas: Modify v3 HW SSP underflow error + processing + +mainline inclusion +from mainline-v5.18-rc1 +commit 62413199cd6d2906c121c2dfa3d7b82fd05f08db +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F84O + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=62413199cd6d2906c121c2dfa3d7b82fd05f08db + +---------------------------------------------------------------------- + +In case of SSP underflow allow the response frame IU to be examined for +setting the response stat value rather than always setting +SAS_DATA_UNDERRUN. + +This will mean that we call sas_ssp_task_response() in those scenarios and +may send sense data to upper layer. + +Such a condition would be for bad blocks were we just reporting an +underflow error to upper layer, but now the sense data will tell +immediately that the media is faulty. + +Link: https://lore.kernel.org/r/1645703489-87194-7-git-send-email-john.garry@huawei.com +Signed-off-by: Xingui Yang +Signed-off-by: Qi Liu +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: xiabing +Reviewed-by: Xiang Chen +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 113 ++++++++++++++----------- + 1 file changed, 62 insertions(+), 51 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index a07bb33176c8..43aefd48a65e 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -2329,7 +2329,7 @@ static void set_aborted_iptt(struct hisi_hba *hisi_hba, + 1 << CFG_ABT_SET_IPTT_DONE_OFF); + } + +-static void ++static bool + slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task, + struct hisi_sas_slot *slot) + { +@@ -2349,6 +2349,15 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task, + switch (task->task_proto) { + case SAS_PROTOCOL_SSP: + if (dma_rx_err_type & RX_DATA_LEN_UNDERFLOW_MSK) { ++ /* ++ * If returned response frame is incorrect because of data underflow, ++ * but I/O information has been written to the host memory, we examine ++ * response IU. ++ */ ++ if (!(complete_hdr->dw0 & CMPLT_HDR_RSPNS_GOOD_MSK) && ++ (complete_hdr->dw0 & CMPLT_HDR_RSPNS_XFRD_MSK)) ++ return false; ++ + ts->residual = trans_tx_fail_type; + ts->stat = SAS_DATA_UNDERRUN; + if (!(dw0 & CMPLT_HDR_RSPNS_GOOD_MSK) && +@@ -2397,6 +2406,7 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task, + default: + break; + } ++ return true; + } + + static int ssp_need_spin_up(struct hisi_sas_slot *slot) +@@ -2498,61 +2508,62 @@ static void slot_complete_v3_hw(struct hisi_hba *hisi_hba, + struct hisi_sas_itct *itct = &hisi_hba->itct[device_id]; + + set_aborted_iptt(hisi_hba, slot); +- slot_err_v3_hw(hisi_hba, task, slot); +- dev_info(dev, "erroneous completion iptt=%d task=%pK dev id=%d addr%016llx sas_addr=0x%llx CQ hdr: 0x%x 0x%x 0x%x 0x%x Error info: 0x%x 0x%x 0x%x 0x%x\n", +- slot->idx, task, sas_dev->device_id, +- SAS_ADDR(device->sas_addr), itct->sas_addr, +- dw0, dw1, +- complete_hdr->act, dw3, +- error_info[0], error_info[1], +- error_info[2], error_info[3]); +- +- if ((dw0 & CMPLT_HDR_RSPNS_XFRD_MSK) && +- (task->task_proto & SAS_PROTOCOL_SATA || +- task->task_proto & SAS_PROTOCOL_STP)) { +- struct hisi_sas_status_buffer *status_buf = ++ if (slot_err_v3_hw(hisi_hba, task, slot)) { ++ dev_info(dev, "erroneous completion iptt=%d task=%pK dev id=%d addr%016llx sas_addr=0x%llx CQ hdr: 0x%x 0x%x 0x%x 0x%x Error info: 0x%x 0x%x 0x%x 0x%x\n", ++ slot->idx, task, sas_dev->device_id, ++ SAS_ADDR(device->sas_addr), itct->sas_addr, ++ dw0, dw1, ++ complete_hdr->act, dw3, ++ error_info[0], error_info[1], ++ error_info[2], error_info[3]); ++ ++ if ((dw0 & CMPLT_HDR_RSPNS_XFRD_MSK) && ++ (task->task_proto & SAS_PROTOCOL_SATA || ++ task->task_proto & SAS_PROTOCOL_STP)) { ++ struct hisi_sas_status_buffer *status_buf = + hisi_sas_status_buf_addr_mem(slot); +- u8 *iu = &status_buf->iu[0]; +- struct dev_to_host_fis *d2h = +- (struct dev_to_host_fis *)iu; ++ u8 *iu = &status_buf->iu[0]; ++ struct dev_to_host_fis *d2h = ++ (struct dev_to_host_fis *)iu; + +- dev_info(dev, "sata d2h status 0x%02x, error 0x%02x\n", +- d2h->status, d2h->error); +- } ++ dev_info(dev, "sata d2h status 0x%02x, error 0x%02x\n", ++ d2h->status, d2h->error); ++ } + +- if ((error_info[3] & RX_DATA_LEN_UNDERFLOW_MSK) && +- (task->task_proto == SAS_PROTOCOL_SSP)) { +- /*print detail sense info when data underflow happened*/ +- bool rc; +- int sb_len; +- u8 *sense_buffer; +- struct scsi_sense_hdr sshdr; +- struct ssp_response_iu *iu = +- hisi_sas_status_buf_addr_mem(slot) + +- sizeof(struct hisi_sas_err_record); +- +- sb_len = iu->sense_data_len; +- sense_buffer = iu->sense_data; +- rc = scsi_normalize_sense(sense_buffer, sb_len, &sshdr); +- if (rc) +- dev_info(dev, "data underflow, rsp_code:0x%x, sensekey:0x%x, ASC:0x%x, ASCQ:0x%x.\n", +- sshdr.response_code, +- sshdr.sense_key, +- sshdr.asc, +- sshdr.ascq); +- else +- dev_info(dev, "data underflow without sense, rsp_code:0x%02x.\n", +- iu->resp_data[0]); +- } +- if (unlikely(slot->abort)) { +- if (dev_is_sata(device) && task->ata_task.use_ncq) +- hisi_sas_ata_device_link_abort(device); +- else +- sas_task_abort(task); ++ if ((error_info[3] & RX_DATA_LEN_UNDERFLOW_MSK) && ++ (task->task_proto == SAS_PROTOCOL_SSP)) { ++ /*print detail sense info when data underflow happened*/ ++ bool rc; ++ int sb_len; ++ u8 *sense_buffer; ++ struct scsi_sense_hdr sshdr; ++ struct ssp_response_iu *iu = ++ hisi_sas_status_buf_addr_mem(slot) + ++ sizeof(struct hisi_sas_err_record); ++ ++ sb_len = iu->sense_data_len; ++ sense_buffer = iu->sense_data; ++ rc = scsi_normalize_sense(sense_buffer, sb_len, &sshdr); ++ if (rc) ++ dev_info(dev, "data underflow, rsp_code:0x%x, sensekey:0x%x, ASC:0x%x, ASCQ:0x%x.\n", ++ sshdr.response_code, ++ sshdr.sense_key, ++ sshdr.asc, ++ sshdr.ascq); ++ else ++ dev_info(dev, "data underflow without sense, rsp_code:0x%02x.\n", ++ iu->resp_data[0]); ++ } ++ if (unlikely(slot->abort)) { ++ if (dev_is_sata(device) && task->ata_task.use_ncq) ++ hisi_sas_ata_device_link_abort(device); ++ else ++ sas_task_abort(task); + +- return; ++ return; ++ } ++ goto out; + } +- goto out; + } + + switch (task->task_proto) { +-- +2.27.0 + diff --git a/patches/0525-scsi-libsas-Refactor-sas_ata_hard_reset.patch b/patches/0525-scsi-libsas-Refactor-sas_ata_hard_reset.patch new file mode 100644 index 00000000..515c602e --- /dev/null +++ b/patches/0525-scsi-libsas-Refactor-sas_ata_hard_reset.patch @@ -0,0 +1,124 @@ +From c7eaaddc6345e943fc39261f60e7c2ab274e55b4 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Tue, 15 Nov 2022 23:03:46 +0800 +Subject: [PATCH 207/256] scsi: libsas: Refactor sas_ata_hard_reset() + +mainline inclusion +from mainline-v5.19-rc1 +commit 057e5fc03369f8f2ed9b2ca884754b1d80b83620 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F85H + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=057e5fc03369f8f2ed9b2ca884754b1d80b83620 + +---------------------------------------------------------------------- + +Create function sas_ata_wait_after_reset() from sas_ata_hard_reset() as +some LLDDs may want to check for a remote ATA phy is up after reset. + +Link: https://lore.kernel.org/r/1652354134-171343-2-git-send-email-john.garry@huawei.com +Tested-by: Yihang Li +Reviewed-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: xiabing +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/libsas/sas_ata.c + include/scsi/sas_ata.h +--- + drivers/scsi/libsas/sas_ata.c | 41 +++++++++++++++++++++++------------ + include/scsi/sas_ata.h | 6 +++++ + 2 files changed, 33 insertions(+), 14 deletions(-) + +diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c +index 19a2b17876f5..93b1554f6757 100644 +--- a/drivers/scsi/libsas/sas_ata.c ++++ b/drivers/scsi/libsas/sas_ata.c +@@ -508,22 +508,14 @@ void sas_ata_check_topology(struct asd_sas_port *port) + + } + +-static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class, +- unsigned long deadline) ++int sas_ata_wait_after_reset(struct domain_device *dev, unsigned long deadline) + { +- int ret = 0, res; +- struct sas_phy *phy; +- struct ata_port *ap = link->ap; ++ struct sata_device *sata_dev = &dev->sata_dev; + int (*check_ready)(struct ata_link *link); +- struct domain_device *dev = ap->private_data; +- struct sas_internal *i = dev_to_sas_internal(dev); +- +- res = i->dft->lldd_I_T_nexus_reset(dev); +- if (res == -ENODEV) +- return res; +- +- if (res != TMF_RESP_FUNC_COMPLETE) +- sas_ata_printk(KERN_DEBUG, dev, "Unable to reset ata device?\n"); ++ struct ata_port *ap = sata_dev->ap; ++ struct ata_link *link = &ap->link; ++ struct sas_phy *phy; ++ int ret; + + phy = sas_get_local_phy(dev); + if (scsi_is_sas_phy_local(phy)) +@@ -536,6 +528,27 @@ static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class, + if (ret && ret != -EAGAIN) + sas_ata_printk(KERN_ERR, dev, "reset failed (errno=%d)\n", ret); + ++ return ret; ++} ++EXPORT_SYMBOL_GPL(sas_ata_wait_after_reset); ++ ++static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class, ++ unsigned long deadline) ++{ ++ struct ata_port *ap = link->ap; ++ struct domain_device *dev = ap->private_data; ++ struct sas_internal *i = dev_to_sas_internal(dev); ++ int ret; ++ ++ ret = i->dft->lldd_I_T_nexus_reset(dev); ++ if (ret == -ENODEV) ++ return ret; ++ ++ if (ret != TMF_RESP_FUNC_COMPLETE) ++ sas_ata_printk(KERN_DEBUG, dev, "Unable to reset ata device?\n"); ++ ++ ret = sas_ata_wait_after_reset(dev, deadline); ++ + *class = dev->sata_dev.class; + + ap->cbl = ATA_CBL_SATA; +diff --git a/include/scsi/sas_ata.h b/include/scsi/sas_ata.h +index 6eac6f2f38ca..df1af3f33792 100644 +--- a/include/scsi/sas_ata.h ++++ b/include/scsi/sas_ata.h +@@ -56,6 +56,7 @@ void sas_suspend_sata(struct asd_sas_port *port); + void sas_resume_sata(struct asd_sas_port *port); + void sas_ata_end_eh(struct ata_port *ap); + void sas_ata_check_topology(struct asd_sas_port *port); ++int sas_ata_wait_after_reset(struct domain_device *dev, unsigned long deadline); + #else + + +@@ -113,6 +114,11 @@ static inline void sas_ata_check_topology(struct asd_sas_port *port) + { + } + ++static inline int sas_ata_wait_after_reset(struct domain_device *dev, ++ unsigned long deadline) ++{ ++ return -ETIMEDOUT; ++} + #endif + + #endif /* _SAS_ATA_H_ */ +-- +2.27.0 + diff --git a/patches/0526-scsi-hisi_sas-Use-sas_ata_wait_after_reset-in-IT-nex.patch b/patches/0526-scsi-hisi_sas-Use-sas_ata_wait_after_reset-in-IT-nex.patch new file mode 100644 index 00000000..de4b3073 --- /dev/null +++ b/patches/0526-scsi-hisi_sas-Use-sas_ata_wait_after_reset-in-IT-nex.patch @@ -0,0 +1,75 @@ +From 63a82560e2d8ff1f749784745ef652255dac19ce Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Tue, 15 Nov 2022 23:03:47 +0800 +Subject: [PATCH 208/256] scsi: hisi_sas: Use sas_ata_wait_after_reset() in IT + nexus reset + +mainline inclusion +from mainline-v5.19-rc1 +commit 71453bd9d1bfa2a75f742ac8ad75c084097e9a50 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F85H + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=71453bd9d1bfa2a75f742ac8ad75c084097e9a50 + +---------------------------------------------------------------------- + +We have seen errors like this when a SATA device is probed: + +[524.566298] hisi_sas_v3_hw 0000L74:02.0: erroneous completion iptt=4096 ... +[524.582827] sas: TMF task open reject failed 500e004aaaaaaaa00 + +Since commit 21c7e972475e ("scsi: hisi_sas: Disable SATA disk phy for +severe I_T nexus reset failure"), we issue an ATA softreset to disks after +a phy reset to ensure that they are in sound working order. If the +softreset is issued before the remote phy has come back up then the +softreset will fail (errors as above). Remedy this by waiting for the phy +to come back up after the reset. + +Link: https://lore.kernel.org/r/1652354134-171343-3-git-send-email-john.garry@huawei.com +Tested-by: Yihang Li +Reviewed-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: xiabing +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 453754f2b400..084897309190 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1950,10 +1950,19 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device) + dev_warn(dev, "phy%d reset timeout\n", sas_phy->id); + hisi_sas_phy_down(hisi_hba, sas_phy->id, 0, GFP_KERNEL); + } +- } else if (sas_dev->dev_status != HISI_SAS_DEV_INIT) +- /* Sleep 2s, wait for I_T reset at expander env except fail */ +- if (!rc) +- msleep(2000); ++ return rc; ++ } ++ ++ if (rc) ++ return rc; ++ ++ /* Remote phy */ ++ if (dev_is_sata(device)) { ++ rc = sas_ata_wait_after_reset(device, ++ HISI_SAS_WAIT_PHYUP_TIMEOUT); ++ } else { ++ msleep(2000); ++ } + + return rc; + } +-- +2.27.0 + diff --git a/patches/0527-scsi-hisi_sas-Fix-rescan-after-deleting-a-disk.patch b/patches/0527-scsi-hisi_sas-Fix-rescan-after-deleting-a-disk.patch new file mode 100644 index 00000000..1a0adba4 --- /dev/null +++ b/patches/0527-scsi-hisi_sas-Fix-rescan-after-deleting-a-disk.patch @@ -0,0 +1,154 @@ +From cf4d1545dcc5605e1524b63849d24c7d7602928a Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Tue, 15 Nov 2022 23:03:48 +0800 +Subject: [PATCH 209/256] scsi: hisi_sas: Fix rescan after deleting a disk + +mainline inclusion +from mainline-v5.19-rc1 +commit e9dedc13bb11bc553754abecb322e5e41d1b4fef +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F85H + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e9dedc13bb11bc553754abecb322e5e41d1b4fef + +---------------------------------------------------------------------- + +Removing an ATA device via sysfs means that the device may not be found +through re-scanning: + +root@ubuntu:/home/john# lsscsi +[0:0:0:0] disk SanDisk LT0200MO P404 /dev/sda +[0:0:1:0] disk ATA HGST HUS724040AL A8B0 /dev/sdb +[0:0:8:0] enclosu 12G SAS Expander RevB - +root@ubuntu:/home/john# echo 1 > /sys/block/sdb/device/delete +root@ubuntu:/home/john# echo "- - -" > /sys/class/scsi_host/host0/scan +root@ubuntu:/home/john# lsscsi +[0:0:0:0] disk SanDisk LT0200MO P404 /dev/sda +[0:0:8:0] enclosu 12G SAS Expander RevB - +root@ubuntu:/home/john# + +The problem is that the rescan of the device may conflict with the device +in being re-initialized, as follows: + + - In the rescan we call hisi_sas_slave_alloc() in store_scan() -> + sas_user_scan() -> [__]scsi_scan_target() -> scsi_probe_and_add_lunc() + -> scsi_alloc_sdev() -> hisi_sas_slave_alloc() -> hisi_sas_init_device() + In hisi_sas_init_device() we issue an IT nexus reset for ATA devices + + - That IT nexus causes the remote PHY to go down and this triggers a bcast + event + + - In parallel libsas processes the bcast event, finds that the phy is down + and marks the device as gone + +The hard reset issued in hisi_sas_init_device() is unncessary - as +described in the code comment - so remove it. Also set dev status as +HISI_SAS_DEV_NORMAL as the hisi_sas_init_device() call. + +Link: https://lore.kernel.org/r/1652354134-171343-4-git-send-email-john.garry@huawei.com +Fixes: 36c6b7613ef1 ("scsi: hisi_sas: Initialise devices in .slave_alloc callback") +Tested-by: Yihang Li +Reviewed-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: xiabing +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 48 ++++++++++----------------- + 1 file changed, 18 insertions(+), 30 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 084897309190..3f438fe6c7ad 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -709,8 +709,6 @@ static int hisi_sas_init_device(struct domain_device *device) + struct hisi_sas_tmf_task tmf_task; + int retry = HISI_SAS_DISK_RECOVER_CNT; + struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); +- struct device *dev = hisi_hba->dev; +- struct sas_phy *local_phy; + + switch (device->dev_type) { + case SAS_END_DEVICE: +@@ -731,31 +729,18 @@ static int hisi_sas_init_device(struct domain_device *device) + case SAS_SATA_PM_PORT: + case SAS_SATA_PENDING: + /* +- * send HARD RESET to clear previous affiliation of +- * STP target port ++ * If an expander is swapped when a SATA disk is attached then ++ * we should issue a hard reset to clear previous affiliation ++ * of STP target port, see SPL (chapter 6.19.4). ++ * ++ * However we don't need to issue a hard reset here for these ++ * reasons: ++ * a. When probing the device, libsas/libata already issues a ++ * hard reset in sas_probe_sata() -> ata_sas_async_probe(). ++ * Note that in hisi_sas_debug_I_T_nexus_reset() we take care ++ * to issue a hard reset by checking the dev status (== INIT). ++ * b. When resetting the controller, this is simply unnecessary. + */ +- local_phy = sas_get_local_phy(device); +- if (!scsi_is_sas_phy_local(local_phy) && +- !test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) { +- unsigned long deadline = ata_deadline(jiffies, 20000); +- struct sata_device *sata_dev = &device->sata_dev; +- struct ata_host *ata_host = sata_dev->ata_host; +- struct ata_port_operations *ops = ata_host->ops; +- struct ata_port *ap = sata_dev->ap; +- struct ata_link *link; +- unsigned int classes; +- +- ata_for_each_link(link, ap, EDGE) +- rc = ops->hardreset(link, &classes, +- deadline); +- } +- sas_put_local_phy(local_phy); +- if (rc) { +- dev_warn(dev, "SATA disk hardreset fail: %d\n", +- rc); +- return rc; +- } +- + while (retry-- > 0) { + rc = hisi_sas_softreset_ata_disk(device); + if (!rc) +@@ -771,15 +756,19 @@ static int hisi_sas_init_device(struct domain_device *device) + + int hisi_sas_slave_alloc(struct scsi_device *sdev) + { +- struct domain_device *ddev; ++ struct domain_device *ddev = sdev_to_domain_dev(sdev); ++ struct hisi_sas_device *sas_dev = ddev->lldd_dev; + int rc; + + rc = sas_slave_alloc(sdev); + if (rc) + return rc; +- ddev = sdev_to_domain_dev(sdev); + +- return hisi_sas_init_device(ddev); ++ rc = hisi_sas_init_device(ddev); ++ if (rc) ++ return rc; ++ sas_dev->dev_status = HISI_SAS_DEV_NORMAL; ++ return 0; + } + EXPORT_SYMBOL_GPL(hisi_sas_slave_alloc); + +@@ -829,7 +818,6 @@ static int hisi_sas_dev_found(struct domain_device *device) + dev_info(dev, "dev[%d:%x] found\n", + sas_dev->device_id, sas_dev->dev_type); + +- sas_dev->dev_status = HISI_SAS_DEV_NORMAL; + return 0; + + err_out: +-- +2.27.0 + diff --git a/patches/0528-scsi-hisi_sas-Undo-RPM-resume-for-failed-notify-phy-.patch b/patches/0528-scsi-hisi_sas-Undo-RPM-resume-for-failed-notify-phy-.patch new file mode 100644 index 00000000..aa130200 --- /dev/null +++ b/patches/0528-scsi-hisi_sas-Undo-RPM-resume-for-failed-notify-phy-.patch @@ -0,0 +1,59 @@ +From 6a6f80fcb6de65231a779a0608bcf8e46dc9fc5e Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Tue, 15 Nov 2022 23:03:45 +0800 +Subject: [PATCH 210/256] scsi: hisi_sas: Undo RPM resume for failed notify phy + event for v3 HW + +mainline inclusion +from mainline-v5.19-rc1 +commit 9b5387fe5af38116b452259d87cd66594b6277c1 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9b5387fe5af38116b452259d87cd66594b6277c1 + +---------------------------------------------------------------------- + +If we fail to notify the phy up event then undo the RPM resume, as the phy +up notify event handling pairs with that RPM resume. + +Link: https://lore.kernel.org/r/1651839939-101188-1-git-send-email-john.garry@huawei.com +Reported-by: Yihang Li +Tested-by: Yihang Li +Signed-off-by: Xiang Chen +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: xiabing +Reviewed-by: Xiang Chen +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 43aefd48a65e..9fe6ac1b8d88 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -1712,9 +1712,15 @@ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba) + + phy->port_id = port_id; + +- /* Call pm_runtime_put_sync() with pairs in hisi_sas_phyup_pm_work() */ ++ /* ++ * Call pm_runtime_get_noresume() which pairs with ++ * hisi_sas_phyup_pm_work() -> pm_runtime_put_sync(). ++ * For failure call pm_runtime_put() as we are in a hardirq context. ++ */ + pm_runtime_get_noresume(dev); +- hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP_PM); ++ res = hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP_PM); ++ if (!res) ++ pm_runtime_put(dev); + + res = IRQ_HANDLED; + +-- +2.27.0 + diff --git a/patches/0529-scsi-hisi_sas-Use-abort-task-set-to-reset-SAS-disks-.patch b/patches/0529-scsi-hisi_sas-Use-abort-task-set-to-reset-SAS-disks-.patch new file mode 100644 index 00000000..176b4c69 --- /dev/null +++ b/patches/0529-scsi-hisi_sas-Use-abort-task-set-to-reset-SAS-disks-.patch @@ -0,0 +1,47 @@ +From b18e2bbcca9dff4bbbad8f5dd6e51ad74e446941 Mon Sep 17 00:00:00 2001 +From: Xingui Yang +Date: Thu, 16 Mar 2023 20:21:39 +0800 +Subject: [PATCH 211/256] scsi: hisi_sas: Use abort task set to reset SAS disks + when discovered + +mainline inclusion +from mainline-v6.2-rc4 +commit 037b48057e8b485a8d72f808122796aeadbbee32 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F82P + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=037b48057e8b485a8d72f808122796aeadbbee32 + +---------------------------------------------------------------------- + +Currently clear task set is used to abort all commands remaining in the +disk when the SAS disk is discovered, and if the disk is discovered by two +initiators, other I_T nexuses are also affected. So use abort task set +instead and take effect only on the specified I_T nexus. + +Signed-off-by: Xingui Yang +Signed-off-by: Xiang Chen +Link: https://lore.kernel.org/r/1672805000-141102-2-git-send-email-chenxiang66@hisilicon.com +Signed-off-by: Martin K. Petersen +Signed-off-by: xiabing +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 3f438fe6c7ad..1d406f71016b 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -714,7 +714,7 @@ static int hisi_sas_init_device(struct domain_device *device) + case SAS_END_DEVICE: + int_to_scsilun(0, &lun); + +- tmf_task.tmf = TMF_CLEAR_TASK_SET; ++ tmf_task.tmf = TMF_ABORT_TASK_SET; + while (retry-- > 0) { + rc = hisi_sas_debug_issue_ssp_tmf(device, lun.scsi_lun, + &tmf_task); +-- +2.27.0 + diff --git a/patches/0530-scsi-libsas-Update-SATA-dev-FIS-in-sas_ata_task_done.patch b/patches/0530-scsi-libsas-Update-SATA-dev-FIS-in-sas_ata_task_done.patch new file mode 100644 index 00000000..51312904 --- /dev/null +++ b/patches/0530-scsi-libsas-Update-SATA-dev-FIS-in-sas_ata_task_done.patch @@ -0,0 +1,49 @@ +From ab91af014dedda1e562dc76fcb4dc6f433fc939b Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 16 Mar 2023 20:21:40 +0800 +Subject: [PATCH 212/256] scsi: libsas: Update SATA dev FIS in + sas_ata_task_done() + +mainline inclusion +from mainline-v6.2-rc1 +commit cc22efbec0110181725b1f5f6778155a2e352522 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F82P + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cc22efbec0110181725b1f5f6778155a2e352522 + +---------------------------------------------------------------------- + +In sas_ata_task_done(), for commands which complete with error we set the +SATA dev FIS status field with ATA_ERR. In ata_eh_analyze_tf() this would +be interpreted as a HSM error. Set ATA_DRDY, which will lead libata to +judge as a device error, which is a safer bet. + +Signed-off-by: John Garry +Link: https://lore.kernel.org/r/1665998435-199946-9-git-send-email-john.garry@huawei.com +Reviewed-by: Niklas Cassel +Signed-off-by: Martin K. Petersen +Signed-off-by: xiabing +Signed-off-by: YunYi Yang +--- + drivers/scsi/libsas/sas_ata.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c +index 93b1554f6757..0cadbdcc4369 100644 +--- a/drivers/scsi/libsas/sas_ata.c ++++ b/drivers/scsi/libsas/sas_ata.c +@@ -161,8 +161,8 @@ static void sas_ata_task_done(struct sas_task *task) + qc->flags |= ATA_QCFLAG_FAILED; + } + +- dev->sata_dev.fis[3] = 0x04; /* status err */ +- dev->sata_dev.fis[2] = ATA_ERR; ++ dev->sata_dev.fis[2] = ATA_ERR | ATA_DRDY; /* tf status */ ++ dev->sata_dev.fis[3] = ATA_ABORTED; /* tf error */ + } + } + +-- +2.27.0 + diff --git a/patches/0531-scsi-libsas-Add-sas_ata_device_link_abort.patch b/patches/0531-scsi-libsas-Add-sas_ata_device_link_abort.patch new file mode 100644 index 00000000..b58234c6 --- /dev/null +++ b/patches/0531-scsi-libsas-Add-sas_ata_device_link_abort.patch @@ -0,0 +1,102 @@ +From f9d788c5afc0bcc4df426d15ea28384d05c846d9 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Fri, 17 Mar 2023 10:19:17 +0800 +Subject: [PATCH 213/256] scsi: libsas: Add sas_ata_device_link_abort() + +mainline inclusion +from mainline-v6.2-rc1 +commit 44112922674b94a7d699dfff6307fc830018df7c +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F82P + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=44112922674b94a7d699dfff6307fc830018df7c + +---------------------------------------------------------------------- + +Similar to how AHCI handles NCQ errors in ahci_error_intr() -> +ata_port_abort() -> ata_do_link_abort(), add an NCQ error handler for LLDDs +to call to initiate a link abort. + +This will mark all outstanding QCs as failed and kick-off EH. + +Note: + +A "force reset" argument is added for drivers which require the ATA error +handling to always reset the device. + +A driver may require this feature for when SATA device per-SCSI cmnd +resources are only released during reset for ATA EH. As such, we need an +option to force reset to be done, regardless of what any EH autopsy +decides. + +The SATA device FIS fields are set to indicate a device error from +ata_eh_analyze_tf(). + +Suggested-by: Damien Le Moal +Suggested-by: Niklas Cassel +Signed-off-by: John Garry +Link: https://lore.kernel.org/r/1665998435-199946-2-git-send-email-john.garry@huawei.com +Tested-by: Damien Le Moal +Tested-by: Niklas Cassel # pm80xx +Reviewed-by: Jason Yan +Signed-off-by: Martin K. Petersen +Signed-off-by: xiabing +Signed-off-by: YunYi Yang + + Conflicts: + include/scsi/sas_ata.h +--- + drivers/scsi/libsas/sas_ata.c | 15 +++++++++++++++ + include/scsi/sas_ata.h | 6 ++++++ + 2 files changed, 21 insertions(+) + +diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c +index 0cadbdcc4369..5cafaec45633 100644 +--- a/drivers/scsi/libsas/sas_ata.c ++++ b/drivers/scsi/libsas/sas_ata.c +@@ -1041,3 +1041,18 @@ void sas_ata_wait_eh(struct domain_device *dev) + ap = dev->sata_dev.ap; + ata_port_wait_eh(ap); + } ++ ++void sas_ata_device_link_abort(struct domain_device *device, bool force_reset) ++{ ++ struct ata_port *ap = device->sata_dev.ap; ++ struct ata_link *link = &ap->link; ++ ++ device->sata_dev.fis[2] = ATA_ERR | ATA_DRDY; /* tf status */ ++ device->sata_dev.fis[3] = ATA_ABORTED; /* tf error */ ++ ++ link->eh_info.err_mask |= AC_ERR_DEV; ++ if (force_reset) ++ link->eh_info.action |= ATA_EH_RESET; ++ ata_link_abort(link); ++} ++EXPORT_SYMBOL_GPL(sas_ata_device_link_abort); +diff --git a/include/scsi/sas_ata.h b/include/scsi/sas_ata.h +index df1af3f33792..e6a8649cc275 100644 +--- a/include/scsi/sas_ata.h ++++ b/include/scsi/sas_ata.h +@@ -56,6 +56,7 @@ void sas_suspend_sata(struct asd_sas_port *port); + void sas_resume_sata(struct asd_sas_port *port); + void sas_ata_end_eh(struct ata_port *ap); + void sas_ata_check_topology(struct asd_sas_port *port); ++void sas_ata_device_link_abort(struct domain_device *dev, bool force_reset); + int sas_ata_wait_after_reset(struct domain_device *dev, unsigned long deadline); + #else + +@@ -114,6 +115,11 @@ static inline void sas_ata_check_topology(struct asd_sas_port *port) + { + } + ++static inline void sas_ata_device_link_abort(struct domain_device *dev, ++ bool force_reset) ++{ ++} ++ + static inline int sas_ata_wait_after_reset(struct domain_device *dev, + unsigned long deadline) + { +-- +2.27.0 + diff --git a/patches/0532-scsi-libsas-Grab-the-ATA-port-lock-in-sas_ata_device.patch b/patches/0532-scsi-libsas-Grab-the-ATA-port-lock-in-sas_ata_device.patch new file mode 100644 index 00000000..26daff19 --- /dev/null +++ b/patches/0532-scsi-libsas-Grab-the-ATA-port-lock-in-sas_ata_device.patch @@ -0,0 +1,54 @@ +From 60aca9c3b258bb60f76a0c72fc4af75587073b34 Mon Sep 17 00:00:00 2001 +From: Xingui Yang +Date: Thu, 16 Mar 2023 20:21:41 +0800 +Subject: [PATCH 214/256] scsi: libsas: Grab the ATA port lock in + sas_ata_device_link_abort() + +mainline inclusion +from mainline-v6.2-rc4 +commit a67aad57d9aee41180aff36e54cb72fe4b8d5a5a +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F82P + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a67aad57d9aee41180aff36e54cb72fe4b8d5a5a + +---------------------------------------------------------------------- + +Grab the ATA port lock in sas_ata_device_link_abort() before calling +ata_link_abort() as outlined in this function's locking requirements. + +Fixes: 44112922674b ("scsi: libsas: Add sas_ata_device_link_abort()") +Signed-off-by: Xingui Yang +Reviewed-by: John Garry +Reviewed-by: Jason Yan +Signed-off-by: Martin K. Petersen +Signed-off-by: xiabing +Signed-off-by: YunYi Yang +--- + drivers/scsi/libsas/sas_ata.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c +index 5cafaec45633..c65bd5c82347 100644 +--- a/drivers/scsi/libsas/sas_ata.c ++++ b/drivers/scsi/libsas/sas_ata.c +@@ -1046,7 +1046,9 @@ void sas_ata_device_link_abort(struct domain_device *device, bool force_reset) + { + struct ata_port *ap = device->sata_dev.ap; + struct ata_link *link = &ap->link; ++ unsigned long flags; + ++ spin_lock_irqsave(ap->lock, flags); + device->sata_dev.fis[2] = ATA_ERR | ATA_DRDY; /* tf status */ + device->sata_dev.fis[3] = ATA_ABORTED; /* tf error */ + +@@ -1054,5 +1056,6 @@ void sas_ata_device_link_abort(struct domain_device *device, bool force_reset) + if (force_reset) + link->eh_info.action |= ATA_EH_RESET; + ata_link_abort(link); ++ spin_unlock_irqrestore(ap->lock, flags); + } + EXPORT_SYMBOL_GPL(sas_ata_device_link_abort); +-- +2.27.0 + diff --git a/patches/0533-Disable-SATA-disk-phy-for-severe-I_T-nexus-reset-fai.patch b/patches/0533-Disable-SATA-disk-phy-for-severe-I_T-nexus-reset-fai.patch new file mode 100644 index 00000000..9241e97f --- /dev/null +++ b/patches/0533-Disable-SATA-disk-phy-for-severe-I_T-nexus-reset-fai.patch @@ -0,0 +1,90 @@ +From adebf4647cdfd314977593c269e2d0b550dcacc7 Mon Sep 17 00:00:00 2001 +From: nifujia +Date: Tue, 18 Jan 2022 21:23:43 +0800 +Subject: [PATCH 215/256] Disable-SATA-disk-phy-for-severe-I_T-nexus reset + failure + +mainline inclusion +from mainline-v5.16-rc1 +commit 21c7e972475e6a975fbe97f8974c96fe4713077c +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F82P +CVE: NA + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=21c7e972475e6a975fbe97f8974c96fe4713077c + +---------------------------------------------------------------------- + +If the softreset fails in the I_T reset, libsas will then continue to issue +a controller reset to try to recover. + +However a faulty disk may cause the softreset to fail, and resetting the +controller will not help this scenario. Indeed, we will just continue the +cycle of error handle handling to try to recover. + +So if the softreset fails upon certain conditions, just disable the phy +associated with the disk. The user needs to handle this problem. + +Link: https://lore.kernel.org/r/1634041588-74824-5-git-send-email-john.garry@huawei.com +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 27 ++++++++++++++++++++++++--- + 1 file changed, 24 insertions(+), 3 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 1d406f71016b..24f0877ccbe5 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1973,15 +1973,36 @@ static int hisi_sas_I_T_nexus_reset(struct domain_device *device) + } + hisi_sas_dereg_device(hisi_hba, device); + +- if (dev_is_sata(device)) { ++ rc = hisi_sas_debug_I_T_nexus_reset(device); ++ if (rc == TMF_RESP_FUNC_COMPLETE && dev_is_sata(device)) { ++ struct sas_phy *local_phy; ++ + rc = hisi_sas_softreset_ata_disk(device); + if (rc) + dev_err(dev, "I_T nexus reset: softreset failed (%d)\n", + rc); ++ switch (rc) { ++ case -ECOMM: ++ rc = -ENODEV; ++ break; ++ case TMF_RESP_FUNC_FAILED: ++ case -EMSGSIZE: ++ case -EIO: ++ local_phy = sas_get_local_phy(device); ++ rc = sas_phy_enable(local_phy, 0); ++ if (!rc) { ++ local_phy->enabled = 0; ++ dev_err(dev, "Disabled local phy of ATA disk %016llx due to softreset fail (%d)\n", ++ SAS_ADDR(device->sas_addr), rc); ++ rc = -ENODEV; ++ } ++ sas_put_local_phy(local_phy); ++ break; ++ default: ++ break; ++ } + } + +- rc = hisi_sas_debug_I_T_nexus_reset(device); +- + if ((rc == TMF_RESP_FUNC_COMPLETE) || (rc == -ENODEV)) + hisi_sas_release_task(hisi_hba, device); + +-- +2.27.0 + diff --git a/patches/0534-Revert-scsi-hisi_sas-Disable-SATA-disk-phy-for-sever.patch b/patches/0534-Revert-scsi-hisi_sas-Disable-SATA-disk-phy-for-sever.patch new file mode 100644 index 00000000..e57737b1 --- /dev/null +++ b/patches/0534-Revert-scsi-hisi_sas-Disable-SATA-disk-phy-for-sever.patch @@ -0,0 +1,87 @@ +From e89f8ee7dd23dee3b2598c97405c21fed93b91af Mon Sep 17 00:00:00 2001 +From: Yihang Li +Date: Fri, 17 Mar 2023 15:04:19 +0800 +Subject: [PATCH 216/256] Revert "scsi: hisi_sas: Disable SATA disk phy for + severe I_T nexus reset failure" + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F82P +CVE: NA + +---------------------------------------------------------------------- + +In that commit, if the softreset fails upon certain conditions, just +disable the PHY associated with the disk. The user needs to restore the +PHY. + +SATA disks do not support simultaneous connection of multiple hosts. +Therefore, when multiple controllers are connected to a SATA disk at the +same time, the controller which is connected later failed to issue an ATA +softreset to the SATA disk. As a result, the PHY associated with the disk +is disabled and cannot be automatically recovered. + +Now that, we will not focus on the execution result of softreset. No +matter whether the execution is successful or not, we will directly carry +out I_T_nexus_reset. + +Fixes: c723ada86707 ("scsi: hisi_sas: Disable SATA disk phy for severe I_T nexus reset failure") +Signed-off-by: Yihang Li +Signed-off-by: xiabing +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 29 +++++---------------------- + 1 file changed, 5 insertions(+), 24 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 24f0877ccbe5..2dc53b3d4c86 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1973,36 +1973,17 @@ static int hisi_sas_I_T_nexus_reset(struct domain_device *device) + } + hisi_sas_dereg_device(hisi_hba, device); + +- rc = hisi_sas_debug_I_T_nexus_reset(device); +- if (rc == TMF_RESP_FUNC_COMPLETE && dev_is_sata(device)) { +- struct sas_phy *local_phy; +- ++ if (dev_is_sata(device)) { + rc = hisi_sas_softreset_ata_disk(device); + if (rc) + dev_err(dev, "I_T nexus reset: softreset failed (%d)\n", + rc); +- switch (rc) { +- case -ECOMM: +- rc = -ENODEV; +- break; +- case TMF_RESP_FUNC_FAILED: +- case -EMSGSIZE: +- case -EIO: +- local_phy = sas_get_local_phy(device); +- rc = sas_phy_enable(local_phy, 0); +- if (!rc) { +- local_phy->enabled = 0; +- dev_err(dev, "Disabled local phy of ATA disk %016llx due to softreset fail (%d)\n", +- SAS_ADDR(device->sas_addr), rc); +- rc = -ENODEV; +- } +- sas_put_local_phy(local_phy); +- break; +- default: +- break; +- } ++ if (rc == TMF_RESP_FUNC_FAILED) ++ dev_err(dev, "ata disk %016llx reset (%d)\n", ++ SAS_ADDR(device->sas_addr), rc); + } + ++ rc = hisi_sas_debug_I_T_nexus_reset(device); + if ((rc == TMF_RESP_FUNC_COMPLETE) || (rc == -ENODEV)) + hisi_sas_release_task(hisi_hba, device); + +-- +2.27.0 + diff --git a/patches/0535-scsi-libsas-Add-smp_ata_check_ready_type.patch b/patches/0535-scsi-libsas-Add-smp_ata_check_ready_type.patch new file mode 100644 index 00000000..c48bcd0a --- /dev/null +++ b/patches/0535-scsi-libsas-Add-smp_ata_check_ready_type.patch @@ -0,0 +1,121 @@ +From 9c3c15176b851ae6c44024d384b3626f30580ca7 Mon Sep 17 00:00:00 2001 +From: Jie Zhan +Date: Fri, 14 Apr 2023 16:20:37 +0800 +Subject: [PATCH 217/256] scsi: libsas: Add smp_ata_check_ready_type() + +mainline inclusion +from mainline-v6.2-rc1 +commit 9181ce3cb5d96f0ee28246a857ca651830fa3746 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F85H + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9181ce3cb5d96f0ee28246a857ca651830fa3746 + +---------------------------------------------------------------------- + +Create function smp_ata_check_ready_type() for LLDDs to wait for SATA +devices to come up after a link reset. + +Signed-off-by: Jie Zhan +Link: https://lore.kernel.org/r/20221118083714.4034612-4-zhanjie9@hisilicon.com +Signed-off-by: Martin K. Petersen +Signed-off-by: xiabing +Signed-off-by: YunYi Yang +--- + drivers/scsi/libsas/sas_ata.c | 25 +++++++++++++++++++++++++ + drivers/scsi/libsas/sas_expander.c | 4 ++-- + drivers/scsi/libsas/sas_internal.h | 2 ++ + include/scsi/sas_ata.h | 6 ++++++ + 4 files changed, 35 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c +index c65bd5c82347..d9bae167c6ba 100644 +--- a/drivers/scsi/libsas/sas_ata.c ++++ b/drivers/scsi/libsas/sas_ata.c +@@ -314,6 +314,31 @@ static int sas_ata_clear_pending(struct domain_device *dev, struct ex_phy *phy) + return 1; + } + ++int smp_ata_check_ready_type(struct ata_link *link) ++{ ++ struct domain_device *dev = link->ap->private_data; ++ struct sas_phy *phy = sas_get_local_phy(dev); ++ struct domain_device *ex_dev = dev->parent; ++ enum sas_device_type type = SAS_PHY_UNUSED; ++ u8 sas_addr[SAS_ADDR_SIZE]; ++ int res; ++ ++ res = sas_get_phy_attached_dev(ex_dev, phy->number, sas_addr, &type); ++ sas_put_local_phy(phy); ++ if (res) ++ return res; ++ ++ switch (type) { ++ case SAS_SATA_PENDING: ++ return 0; ++ case SAS_END_DEVICE: ++ return 1; ++ default: ++ return -ENODEV; ++ } ++} ++EXPORT_SYMBOL_GPL(smp_ata_check_ready_type); ++ + static int smp_ata_check_ready(struct ata_link *link) + { + int res; +diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c +index e436423600b1..4fae938377e1 100644 +--- a/drivers/scsi/libsas/sas_expander.c ++++ b/drivers/scsi/libsas/sas_expander.c +@@ -1768,8 +1768,8 @@ static int sas_get_phy_change_count(struct domain_device *dev, + return res; + } + +-static int sas_get_phy_attached_dev(struct domain_device *dev, int phy_id, +- u8 *sas_addr, enum sas_device_type *type) ++int sas_get_phy_attached_dev(struct domain_device *dev, int phy_id, ++ u8 *sas_addr, enum sas_device_type *type) + { + int res; + struct smp_resp *disc_resp; +diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h +index 4427c15ccbf4..f0c10217c586 100644 +--- a/drivers/scsi/libsas/sas_internal.h ++++ b/drivers/scsi/libsas/sas_internal.h +@@ -100,6 +100,8 @@ struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id); + int sas_ex_phy_discover(struct domain_device *dev, int single); + int sas_get_report_phy_sata(struct domain_device *dev, int phy_id, + struct smp_resp *rps_resp); ++int sas_get_phy_attached_dev(struct domain_device *dev, int phy_id, ++ u8 *sas_addr, enum sas_device_type *type); + int sas_try_ata_reset(struct asd_sas_phy *phy); + void sas_hae_reset(struct work_struct *work); + +diff --git a/include/scsi/sas_ata.h b/include/scsi/sas_ata.h +index e6a8649cc275..83edf4e1aece 100644 +--- a/include/scsi/sas_ata.h ++++ b/include/scsi/sas_ata.h +@@ -58,6 +58,7 @@ void sas_ata_end_eh(struct ata_port *ap); + void sas_ata_check_topology(struct asd_sas_port *port); + void sas_ata_device_link_abort(struct domain_device *dev, bool force_reset); + int sas_ata_wait_after_reset(struct domain_device *dev, unsigned long deadline); ++int smp_ata_check_ready_type(struct ata_link *link); + #else + + +@@ -125,6 +126,11 @@ static inline int sas_ata_wait_after_reset(struct domain_device *dev, + { + return -ETIMEDOUT; + } ++ ++static inline int smp_ata_check_ready_type(struct ata_link *link) ++{ ++ return 0; ++} + #endif + + #endif /* _SAS_ATA_H_ */ +-- +2.27.0 + diff --git a/patches/0536-scsi-hisi_sas-Fix-SATA-devices-missing-issue-during-.patch b/patches/0536-scsi-hisi_sas-Fix-SATA-devices-missing-issue-during-.patch new file mode 100644 index 00000000..cae60205 --- /dev/null +++ b/patches/0536-scsi-hisi_sas-Fix-SATA-devices-missing-issue-during-.patch @@ -0,0 +1,84 @@ +From d9ac9ceef5f4b150ab07b44085c3f90a5a90d625 Mon Sep 17 00:00:00 2001 +From: Jie Zhan +Date: Fri, 14 Apr 2023 16:20:38 +0800 +Subject: [PATCH 218/256] scsi: hisi_sas: Fix SATA devices missing issue during + I_T nexus reset + +mainline inclusion +from mainline-v6.2-rc1 +commit 3c2673a09cf1181318c07b7dbc1bc532ba3d33e3 +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F85H + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3c2673a09cf1181318c07b7dbc1bc532ba3d33e3 + +---------------------------------------------------------------------- + +SATA devices on an expander may be removed and not be found again when I_T +nexus reset and revalidation are processed simultaneously. + +The issue comes from: + + - Revalidation can remove SATA devices in link reset, e.g. in + hisi_sas_clear_nexus_ha(). + + - However, hisi_sas_debug_I_T_nexus_reset() polls the state of a SATA + device on an expander after sending link_reset, where it calls: + hisi_sas_debug_I_T_nexus_reset + sas_ata_wait_after_reset + ata_wait_after_reset + ata_wait_ready + smp_ata_check_ready + sas_ex_phy_discover + sas_ex_phy_discover_helper + sas_set_ex_phy + + The ex_phy's change count is updated in sas_set_ex_phy(), so SATA + devices after a link reset may not be found later through revalidation. + +A similar issue was reported in: +commit 0f3fce5cc77e ("[SCSI] libsas: fix ata_eh clobbering ex_phys via +smp_ata_check_ready") +commit 87c8331fcf72 ("[SCSI] libsas: prevent domain rediscovery competing +with ata error handling"). + +To address this issue, in hisi_sas_debug_I_T_nexus_reset(), we now call +smp_ata_check_ready_type() that only polls the device type while not +updating the ex_phy's data of libsas. + +Fixes: 71453bd9d1bf ("scsi: hisi_sas: Use sas_ata_wait_after_reset() in IT nexus reset") +Signed-off-by: Jie Zhan +Link: https://lore.kernel.org/r/20221118083714.4034612-5-zhanjie9@hisilicon.com +Signed-off-by: Martin K. Petersen +Signed-off-by: xiabing +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 2dc53b3d4c86..99a27a36ad50 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1941,13 +1941,15 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device) + return rc; + } + ++ /* Remote phy */ + if (rc) + return rc; + +- /* Remote phy */ + if (dev_is_sata(device)) { +- rc = sas_ata_wait_after_reset(device, +- HISI_SAS_WAIT_PHYUP_TIMEOUT); ++ struct ata_link *link = &device->sata_dev.ap->link; ++ ++ rc = ata_wait_after_reset(link, HISI_SAS_WAIT_PHYUP_TIMEOUT, ++ smp_ata_check_ready_type); + } else { + msleep(2000); + } +-- +2.27.0 + diff --git a/patches/0537-scsi-libsas-Do-not-export-sas_ata_wait_after_reset.patch b/patches/0537-scsi-libsas-Do-not-export-sas_ata_wait_after_reset.patch new file mode 100644 index 00000000..78cbb90a --- /dev/null +++ b/patches/0537-scsi-libsas-Do-not-export-sas_ata_wait_after_reset.patch @@ -0,0 +1,82 @@ +From e5b74c307f004bb735b2ef89e860f3d032890820 Mon Sep 17 00:00:00 2001 +From: Jie Zhan +Date: Fri, 14 Apr 2023 16:20:39 +0800 +Subject: [PATCH 219/256] scsi: libsas: Do not export + sas_ata_wait_after_reset() + +mainline inclusion +from mainline-v6.2-rc1 +commit 4d450cf2b00d34b53f52d93216dd23af57bdca73 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F85H + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4d450cf2b00d34b53f52d93216dd23af57bdca73 + +---------------------------------------------------------------------- + +sas_ata_wait_after_reset() does not need to be exported since it is no +longer referenced outside libsas. + +Signed-off-by: Jie Zhan +Link: https://lore.kernel.org/r/20221118083714.4034612-6-zhanjie9@hisilicon.com +Reviewed-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: xiabing +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/libsas/sas_ata.c +--- + drivers/scsi/libsas/sas_ata.c | 3 +-- + include/scsi/sas_ata.h | 7 ------- + 2 files changed, 1 insertion(+), 9 deletions(-) + +diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c +index d9bae167c6ba..ba4dc7770d61 100644 +--- a/drivers/scsi/libsas/sas_ata.c ++++ b/drivers/scsi/libsas/sas_ata.c +@@ -533,7 +533,7 @@ void sas_ata_check_topology(struct asd_sas_port *port) + + } + +-int sas_ata_wait_after_reset(struct domain_device *dev, unsigned long deadline) ++static int sas_ata_wait_after_reset(struct domain_device *dev, unsigned long deadline) + { + struct sata_device *sata_dev = &dev->sata_dev; + int (*check_ready)(struct ata_link *link); +@@ -555,7 +555,6 @@ int sas_ata_wait_after_reset(struct domain_device *dev, unsigned long deadline) + + return ret; + } +-EXPORT_SYMBOL_GPL(sas_ata_wait_after_reset); + + static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class, + unsigned long deadline) +diff --git a/include/scsi/sas_ata.h b/include/scsi/sas_ata.h +index 83edf4e1aece..89905be88c97 100644 +--- a/include/scsi/sas_ata.h ++++ b/include/scsi/sas_ata.h +@@ -57,7 +57,6 @@ void sas_resume_sata(struct asd_sas_port *port); + void sas_ata_end_eh(struct ata_port *ap); + void sas_ata_check_topology(struct asd_sas_port *port); + void sas_ata_device_link_abort(struct domain_device *dev, bool force_reset); +-int sas_ata_wait_after_reset(struct domain_device *dev, unsigned long deadline); + int smp_ata_check_ready_type(struct ata_link *link); + #else + +@@ -121,12 +120,6 @@ static inline void sas_ata_device_link_abort(struct domain_device *dev, + { + } + +-static inline int sas_ata_wait_after_reset(struct domain_device *dev, +- unsigned long deadline) +-{ +- return -ETIMEDOUT; +-} +- + static inline int smp_ata_check_ready_type(struct ata_link *link) + { + return 0; +-- +2.27.0 + diff --git a/patches/0538-scsi-hisi_sas-Set-a-port-invalid-only-if-there-are-n.patch b/patches/0538-scsi-hisi_sas-Set-a-port-invalid-only-if-there-are-n.patch new file mode 100644 index 00000000..4ccf6253 --- /dev/null +++ b/patches/0538-scsi-hisi_sas-Set-a-port-invalid-only-if-there-are-n.patch @@ -0,0 +1,50 @@ +From 456b46b17e6c08a3e03c01a0feb3b8076d9e0575 Mon Sep 17 00:00:00 2001 +From: Yihang Li +Date: Fri, 14 Apr 2023 16:20:40 +0800 +Subject: [PATCH 220/256] scsi: hisi_sas: Set a port invalid only if there are + no devices attached when refreshing port id + +mainline inclusion +from mainline-v6.2-rc4 +commit f58c89700630da6554b24fd3df293a24874c10c1 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F82P + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f58c89700630da6554b24fd3df293a24874c10c1 + +---------------------------------------------------------------------- + +Currently the driver sets the port invalid if one phy in the port is not +enabled, which may cause issues in expander situation. In directly attached +situation, if phy up doesn't occur in time when refreshing port id, the +port is incorrectly set to invalid which will also cause disk lost. + +Therefore set a port invalid only if there are no devices attached to the +port. + +Signed-off-by: Yihang Li +Signed-off-by: Xiang Chen +Link: https://lore.kernel.org/r/1672805000-141102-3-git-send-email-chenxiang66@hisilicon.com +Signed-off-by: Martin K. Petersen +Signed-off-by: xiabing +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 99a27a36ad50..75425d03fd2a 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1506,7 +1506,7 @@ static void hisi_sas_refresh_port_id(struct hisi_hba *hisi_hba) + device->linkrate = phy->sas_phy.linkrate; + + hisi_hba->hw->setup_itct(hisi_hba, sas_dev); +- } else ++ } else if (!port->port_attached) + port->id = 0xff; + } + } +-- +2.27.0 + diff --git a/patches/0539-scsi-hisi_sas-Exit-suspending-state-when-usage-count.patch b/patches/0539-scsi-hisi_sas-Exit-suspending-state-when-usage-count.patch new file mode 100644 index 00000000..842faf8a --- /dev/null +++ b/patches/0539-scsi-hisi_sas-Exit-suspending-state-when-usage-count.patch @@ -0,0 +1,291 @@ +From a9e8237025e8bb04e33c299ef0550bbac55c3d5c Mon Sep 17 00:00:00 2001 +From: Yihang Li +Date: Fri, 14 Apr 2023 16:20:41 +0800 +Subject: [PATCH 221/256] scsi: hisi_sas: Exit suspending state when usage + count is greater than 0 + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F82P +CVE: NA + +---------------------------------------------------------------------- + +When the current status of the host controller is suspended, enabling a +local PHY just after disabling all local PHYs in expander envirnment, +a hung as follows occurs. + +[ 486.854655] INFO: task kworker/u256:1:899 blocked for more than 120 seconds. +[ 486.862207] Not tainted 6.1.0-rc4+ #1 +[ 486.870545] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +[ 486.878893] task:kworker/u256:1 state:D stack:0 pid:899 ppid:2 flags:0x00000008 +[ 486.887745] Workqueue: 0000:74:02.0_disco_q sas_discover_domain [libsas] +[ 486.894704] Call trace: +[ 486.897400] __switch_to+0xf0/0x170 +[ 486.901146] __schedule+0x3e4/0x1160 +[ 486.904970] schedule+0x64/0x104 +[ 486.908442] rpm_resume+0x158/0x6a0 +[ 486.912163] __pm_runtime_resume+0x5c/0x84 +[ 486.916489] smp_execute_task_sg+0x1f8/0x264 [libsas] +[ 486.921773] sas_discover_expander.part.0+0xbc/0x720 [libsas] +[ 486.927750] sas_discover_root_expander+0x90/0x154 [libsas] +[ 486.933552] sas_discover_domain+0x444/0x6d0 [libsas] +[ 486.938826] process_one_work+0x1e0/0x450 +[ 486.943057] worker_thread+0x150/0x44c +[ 486.947015] kthread+0x114/0x120 +[ 486.950447] ret_from_fork+0x10/0x20 +[ 486.954292] INFO: task kworker/u256:2:1780 blocked for more than 120 seconds. +[ 486.961637] Not tainted 6.1.0-rc4+ #1 +[ 486.966087] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +[ 486.974356] task:kworker/u256:2 state:D stack:0 pid:1780 ppid:2 flags:0x00000208 +[ 486.983141] Workqueue: 0000:74:02.0_event_q sas_port_event_worker [libsas] +[ 486.990252] Call trace: +[ 486.992930] __switch_to+0xf0/0x170 +[ 486.996645] __schedule+0x3e4/0x1160 +[ 487.000439] schedule+0x64/0x104 +[ 487.003886] schedule_timeout+0x17c/0x1c0 +[ 487.008102] wait_for_completion+0x7c/0x160 +[ 487.012488] __flush_workqueue+0x104/0x3e0 +[ 487.016782] sas_porte_bytes_dmaed+0x414/0x454 [libsas] +[ 487.022203] sas_port_event_worker+0x38/0x60 [libsas] +[ 487.027449] process_one_work+0x1e0/0x450 +[ 487.031645] worker_thread+0x150/0x44c +[ 487.035594] kthread+0x114/0x120 +[ 487.039017] ret_from_fork+0x10/0x20 +[ 487.042828] INFO: task bash:11488 blocked for more than 121 seconds. +[ 487.049366] Not tainted 6.1.0-rc4+ #1 +[ 487.053746] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +[ 487.061953] task:bash state:D stack:0 pid:11488 ppid:10977 flags:0x00000204 +[ 487.070698] Call trace: +[ 487.073355] __switch_to+0xf0/0x170 +[ 487.077050] __schedule+0x3e4/0x1160 +[ 487.080833] schedule+0x64/0x104 +[ 487.084270] schedule_timeout+0x17c/0x1c0 +[ 487.088474] wait_for_completion+0x7c/0x160 +[ 487.092851] __flush_workqueue+0x104/0x3e0 +[ 487.097137] drain_workqueue+0xb8/0x160 +[ 487.101159] __sas_drain_work+0x50/0x90 [libsas] +[ 487.105963] sas_suspend_ha+0x64/0xd4 [libsas] +[ 487.110590] suspend_v3_hw+0x198/0x1e8 [hisi_sas_v3_hw] +[ 487.115989] pci_pm_runtime_suspend+0x5c/0x1d0 +[ 487.120606] __rpm_callback+0x50/0x150 +[ 487.124535] rpm_callback+0x74/0x80 +[ 487.128204] rpm_suspend+0x110/0x640 +[ 487.131955] rpm_idle+0x1f4/0x2d0 +[ 487.135447] __pm_runtime_idle+0x58/0x94 +[ 487.139538] queue_phy_enable+0xcc/0xf0 [libsas] +[ 487.144330] store_sas_phy_enable+0x74/0x100 +[ 487.148770] dev_attr_store+0x20/0x34 +[ 487.152606] sysfs_kf_write+0x4c/0x5c +[ 487.156437] kernfs_fop_write_iter+0x120/0x1b0 +[ 487.161049] vfs_write+0x2d0/0x36c +[ 487.164625] ksys_write+0x70/0x100 +[ 487.168194] __arm64_sys_write+0x24/0x30 +[ 487.172280] invoke_syscall+0x50/0x120 +[ 487.176186] el0_svc_common.constprop.0+0x168/0x190 +[ 487.181214] do_el0_svc+0x34/0xc0 +[ 487.184680] el0_svc+0x2c/0xb4 +[ 487.187879] el0t_64_sync_handler+0xb8/0xbc +[ 487.192205] el0t_64_sync+0x19c/0x1a0 + +We find that when all local PHYs are disabled, all the devices will be +removed, the ->runtime_suspend() callback suspend_v3_hw() directly execute +since the controller usage count drop to 0. On the other side, the first +local PHY is enabled through the sysfs interface, and ensures that +function phy_up_v3_hw() is completed due to suspend_v3_hw()-> +interrupt_disable_v3_hw(). In the expander scenario, +sas_discover_root_expander() is executed in event work +DISCE_DISCOVER_DOMAIN, which will increases the controller usage count and +carry out a resume and sends SMPIO, it cannot be completed because the +runtime PM status of the controller is RPM_SUSPENDING. At the same time, +the ->runtime_suspend() callback suspend_v3_hw() also cannot complete the +process because of drain libsas event queue in sas_suspend_ha(), so hung +occurs. + + (thread 1) | (thread 2) +... | +rpm_idle() | + ... | + __update_runtime_status(RPM_SUSPENDING)| + ... | ... + suspend_v3_hw() | smp_execute_task_sg() + ... | ... + interrupt_disable_v3_hw() | pm_runtime_get_sync() + | ... + ... | rpm_resume() //RPM_SUSPENDING + | + __sas_drain_work() | + +To fix it, check if the current runtime PM status of the controller allows +to be suspended continue after interrupt_disable_v3_hw(), return +immediately if not. + +Signed-off-by: Yihang Li +Signed-off-by: Xiang Chen +Signed-off-by: xiabing +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 71 ++++++++++++++++++++------ + 1 file changed, 56 insertions(+), 15 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 9fe6ac1b8d88..8133f043c2f1 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -630,6 +630,27 @@ static u32 hisi_sas_phy_read32(struct hisi_hba *hisi_hba, + readl_poll_timeout_atomic(regs, val, cond, delay_us, timeout_us);\ + }) + ++static void interrupt_enable_v3_hw(struct hisi_hba *hisi_hba) ++{ ++ int i; ++ ++ for (i = 0; i < hisi_hba->queue_count; i++) ++ hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK + 0x4 * i, 0); ++ ++ hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, 0xfefefefe); ++ hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK2, 0xfefefefe); ++ hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0xffc220ff); ++ hisi_sas_write32(hisi_hba, SAS_ECC_INTR_MSK, 0x155555); ++ ++ for (i = 0; i < hisi_hba->n_phy; i++) { ++ hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK, 0xf2057fff); ++ hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0xffffbfe); ++ hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_NOT_RDY_MSK, 0x0); ++ hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_PHY_ENA_MSK, 0x0); ++ hisi_sas_phy_write32(hisi_hba, i, SL_RX_BCAST_CHK_MSK, 0x0); ++ } ++} ++ + static void init_reg_v3_hw(struct hisi_hba *hisi_hba) + { + int i, j; +@@ -652,18 +673,11 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) + hisi_sas_write32(hisi_hba, ENT_INT_SRC1, 0xffffffff); + hisi_sas_write32(hisi_hba, ENT_INT_SRC2, 0xffffffff); + hisi_sas_write32(hisi_hba, ENT_INT_SRC3, 0xffffffff); +- hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, 0xfefefefe); +- hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK2, 0xfefefefe); +- hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0xffc220ff); + hisi_sas_write32(hisi_hba, CHNL_PHYUPDOWN_INT_MSK, 0x0); + hisi_sas_write32(hisi_hba, CHNL_ENT_INT_MSK, 0x0); + hisi_sas_write32(hisi_hba, HGC_COM_INT_MSK, 0x0); +- hisi_sas_write32(hisi_hba, SAS_ECC_INTR_MSK, 0x155555); + hisi_sas_write32(hisi_hba, AWQOS_AWCACHE_CFG, 0xf0f0); + hisi_sas_write32(hisi_hba, ARQOS_ARCACHE_CFG, 0xf0f0); +- for (i = 0; i < hisi_hba->queue_count; i++) +- hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK + 0x4 * i, 0); +- + hisi_sas_write32(hisi_hba, HYPER_STREAM_ID_EN_CFG, 1); + + if (skip_bus_flag) { +@@ -672,6 +686,7 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) + hisi_sas_write32(hisi_hba, AXI_MASTER_CFG_BASE, 0x10000); + } + ++ interrupt_enable_v3_hw(hisi_hba); + for (i = 0; i < hisi_hba->n_phy; i++) { + enum sas_linkrate max; + struct hisi_sas_phy *phy = &hisi_hba->phy[i]; +@@ -704,10 +719,7 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) + hisi_sas_phy_write32(hisi_hba, i, CHL_INT1, 0xffffffff); + hisi_sas_phy_write32(hisi_hba, i, CHL_INT2, 0xffffffff); + hisi_sas_phy_write32(hisi_hba, i, RXOP_CHECK_CFG_H, 0x1000); +- hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK, 0xf2057fff); +- hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0xffffbfe); + hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL_RDY_MSK, 0x0); +- hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_NOT_RDY_MSK, 0x0); + hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_DWS_RESET_MSK, 0x0); + hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_PHY_ENA_MSK, 0x0); + hisi_sas_phy_write32(hisi_hba, i, SL_RX_BCAST_CHK_MSK, 0x0); +@@ -2935,7 +2947,6 @@ static int disable_host_v3_hw(struct hisi_hba *hisi_hba) + u32 status, reg_val; + int rc; + +- interrupt_disable_v3_hw(hisi_hba); + hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0x0); + + hisi_sas_stop_phys(hisi_hba); +@@ -2966,6 +2977,7 @@ static int soft_reset_v3_hw(struct hisi_hba *hisi_hba) + struct device *dev = hisi_hba->dev; + int rc; + ++ interrupt_disable_v3_hw(hisi_hba); + rc = disable_host_v3_hw(hisi_hba); + if (rc) { + dev_err(dev, "soft reset: disable host failed rc=%d\n", rc); +@@ -5323,6 +5335,7 @@ static void hisi_sas_reset_prepare_v3_hw(struct pci_dev *pdev) + set_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags); + hisi_sas_controller_reset_prepare(hisi_hba); + ++ interrupt_disable_v3_hw(hisi_hba); + rc = disable_host_v3_hw(hisi_hba); + if (rc) + dev_err(dev, "FLR: disable host failed rc=%d\n", rc); +@@ -5352,6 +5365,21 @@ enum { + hip08, + }; + ++static void enable_host_v3_hw(struct hisi_hba *hisi_hba) ++{ ++ u32 reg_val; ++ ++ hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, ++ (u32)((1ULL << hisi_hba->queue_count) - 1)); ++ ++ phys_init_v3_hw(hisi_hba); ++ reg_val = hisi_sas_read32(hisi_hba, AXI_MASTER_CFG_BASE + ++ AM_CTRL_GLOBAL); ++ reg_val &= ~AM_CTRL_SHUTDOWN_REQ_MSK; ++ hisi_sas_write32(hisi_hba, AXI_MASTER_CFG_BASE + ++ AM_CTRL_GLOBAL, reg_val); ++} ++ + static int _suspend_v3_hw(struct device *device) + { + struct pci_dev *pdev = to_pci_dev(device); +@@ -5375,14 +5403,18 @@ static int _suspend_v3_hw(struct device *device) + scsi_block_requests(shost); + set_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); + flush_workqueue(hisi_hba->wq); ++ interrupt_disable_v3_hw(hisi_hba); ++ ++ if (atomic_read(&device->power.usage_count)) { ++ dev_err(dev, "PM suspend: host status cannot be suspended\n"); ++ rc = -EBUSY; ++ goto err_out; ++ } + + rc = disable_host_v3_hw(hisi_hba); + if (rc) { + dev_err(dev, "PM suspend: disable host failed rc=%d\n", rc); +- clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); +- clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags); +- scsi_unblock_requests(shost); +- return rc; ++ goto err_out_recover_host; + } + + hisi_sas_init_mem(hisi_hba); +@@ -5400,6 +5432,15 @@ static int _suspend_v3_hw(struct device *device) + + dev_warn(dev, "end of suspending controller\n"); + return 0; ++ ++err_out_recover_host: ++ enable_host_v3_hw(hisi_hba); ++err_out: ++ interrupt_enable_v3_hw(hisi_hba); ++ clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); ++ clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags); ++ scsi_unblock_requests(shost); ++ return rc; + } + + static int _resume_v3_hw(struct device *device) +-- +2.27.0 + diff --git a/patches/0540-scsi-hisi_sas-Ensure-all-enabled-PHYs-up-during-cont.patch b/patches/0540-scsi-hisi_sas-Ensure-all-enabled-PHYs-up-during-cont.patch new file mode 100644 index 00000000..4b02fa19 --- /dev/null +++ b/patches/0540-scsi-hisi_sas-Ensure-all-enabled-PHYs-up-during-cont.patch @@ -0,0 +1,113 @@ +From ac17390e78704b3c56922296504c93a82b4c99dc Mon Sep 17 00:00:00 2001 +From: Yihang Li +Date: Fri, 14 Apr 2023 16:20:42 +0800 +Subject: [PATCH 222/256] scsi: hisi_sas: Ensure all enabled PHYs up during + controller reset + +mainline inclusion +from mainline-v6.4-rc1 +commit 89954f024c3ae5e8674d9b5313a7cc08e79c6f6d +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F82P + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=89954f024c3ae5e8674d9b5313a7cc08e79c6f6d + +---------------------------------------------------------------------- + +For the controller reset operation, hisi_sas_phy_enable() is executed for +each enabled local PHY, and refresh the port id of each device based on +the latest hisi_sas_phy->port_id after 1 second sleep, +hisi_sas_phy->port_id is configured in the interrupt processing function +phy_up_v3_hw(). However, in directly attached scenario, for some SATA +disks the amount of time for phyup more than 1s sometimes. In this case, +incorrect port id may be configured in hisi_sas_refresh_port_id(). +As a result, all the internal IOs fail and disk lost, such as follows: + +[10717.666565] hisi_sas_v3_hw 0000:74:02.0: phyup: phy1 link_rate=10(sata) +[10718.826813] hisi_sas_v3_hw 0000:74:02.0: erroneous completion iptt=63 +task=00000000c1ab1c2b dev id=200 addr=5000000000000501 CQ hdr: 0x8000007 0xc8003f 0x0 +0x0 Error info: 0x0 0x0 0x0 0x0 +[10718.843428] sas: TMF task open reject failed 5000000000000501 +[10718.849242] hisi_sas_v3_hw 0000:74:02.0: erroneous completion iptt=64 +task=00000000c1ab1c2b dev id=200 addr=5000000000000501 CQ hdr: 0x8000007 0xc80040 0x0 +0x0 Error info: 0x0 0x0 0x0 0x0 +[10718.865856] sas: TMF task open reject failed 5000000000000501 +[10718.871670] hisi_sas_v3_hw 0000:74:02.0: erroneous completion iptt=65 +task=00000000c1ab1c2b dev id=200 addr=5000000000000501 CQ hdr: 0x8000007 0xc80041 0x0 +0x0 Error info: 0x0 0x0 0x0 0x0 +[10718.888284] sas: TMF task open reject failed 5000000000000501 +[10718.894093] sas: executing TMF for 5000000000000501 failed after 3 attempts! +[10718.901114] hisi_sas_v3_hw 0000:74:02.0: ata disk 5000000000000501 reset failed +[10718.908410] hisi_sas_v3_hw 0000:74:02.0: controller reset complete +..... +[10773.298633] ata216.00: revalidation failed (errno=-19) +[10773.303753] ata216.00: disable device + +So the time of waitting for PHYs up is 1s which may be not enough. To +solve the issue, running hisi_sas_phy_enable() in parallel through +async operations and use wait_for_completion_timeout() to wait for PHYs +come up instead of directly sleep for 1 second. + +Signed-off-by: Yihang Li +Signed-off-by: Xiang Chen +Signed-off-by: xiabing +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_main.c +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 33 ++++++++++++++++++++++++--- + 1 file changed, 30 insertions(+), 3 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 75425d03fd2a..6eb70bf01369 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1671,14 +1671,41 @@ void hisi_sas_controller_reset_prepare(struct hisi_hba *hisi_hba) + } + EXPORT_SYMBOL_GPL(hisi_sas_controller_reset_prepare); + ++static void hisi_sas_async_init_wait_phyup(void *data, async_cookie_t cookie) ++{ ++ struct hisi_sas_phy *phy = data; ++ struct hisi_hba *hisi_hba = phy->hisi_hba; ++ struct device *dev = hisi_hba->dev; ++ DECLARE_COMPLETION_ONSTACK(completion); ++ int phy_no = phy->sas_phy.id; ++ ++ phy->reset_completion = &completion; ++ hisi_sas_phy_enable(hisi_hba, phy_no, 1); ++ if (!wait_for_completion_timeout(&completion, ++ HISI_SAS_WAIT_PHYUP_TIMEOUT)) ++ dev_warn(dev, "phy%d wait phyup timed out\n", phy_no); ++ ++ phy->reset_completion = NULL; ++} ++ + void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba) + { + struct Scsi_Host *shost = hisi_hba->shost; ++ ASYNC_DOMAIN_EXCLUSIVE(async); ++ int phy_no; + + /* Init and wait for PHYs to come up and all libsas event finished. */ +- hisi_hba->hw->phys_init(hisi_hba); +- /* Sleep 1s to wait for phy up */ +- msleep(1000); ++ for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) { ++ struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; ++ ++ if (!(hisi_hba->phy_state & BIT(phy_no))) ++ continue; ++ ++ async_schedule_domain(hisi_sas_async_init_wait_phyup, ++ phy, &async); ++ } ++ ++ async_synchronize_full_domain(&async); + hisi_sas_refresh_port_id(hisi_hba); + clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); + +-- +2.27.0 + diff --git a/patches/0541-scsi-sd-Reorganize-DIF-DIX-code-to-avoid-calling-rev.patch b/patches/0541-scsi-sd-Reorganize-DIF-DIX-code-to-avoid-calling-rev.patch new file mode 100644 index 00000000..95131ed5 --- /dev/null +++ b/patches/0541-scsi-sd-Reorganize-DIF-DIX-code-to-avoid-calling-rev.patch @@ -0,0 +1,170 @@ +From dfacb380f483ce71882981cb9ee3bacce46c7039 Mon Sep 17 00:00:00 2001 +From: "Martin K. Petersen" +Date: Fri, 14 Apr 2023 16:20:43 +0800 +Subject: [PATCH 223/256] scsi: sd: Reorganize DIF/DIX code to avoid calling + revalidate twice + +mainline inclusion +from mainline-v5.19-rc1 +commit 1e029397d12f9085840691f4f12991a80d89888c +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F85N + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1e029397d12f9085840691f4f12991a80d89888c + +---------------------------------------------------------------------- + +During device discovery we ended up calling revalidate twice and thus +requested the same parameters multiple times. This was originally necessary +due to the request_queue and gendisk needing to be instantiated to +configure the block integrity profile. + +Since this dependency no longer exists, reorganize the integrity probing +code so it can be run once at the end of discovery and drop the superfluous +revalidate call. Postponing the registration step involves splitting +sd_read_protection() into two functions, one to read the device protection +type and one to configure the mode of operation. + +As part of this cleanup, make the printing code a bit less verbose. + +Link: https://lore.kernel.org/r/20220302053559.32147-14-martin.petersen@oracle.com +Reviewed-by: Christoph Hellwig +Reviewed-by: Johannes Thumshirn +Signed-off-by: Martin K. Petersen +Signed-off-by: xiabing +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/sd.c +--- + drivers/scsi/sd.c | 61 +++++++++++++++++++++++-------------------- + drivers/scsi/sd_dif.c | 8 +++--- + 2 files changed, 36 insertions(+), 33 deletions(-) + +diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c +index 871f31e5e5d1..203bd0de14c7 100644 +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -2213,40 +2213,48 @@ static int sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer + { + struct scsi_device *sdp = sdkp->device; + u8 type; +- int ret = 0; + + if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0) { + sdkp->protection_type = 0; +- return ret; ++ return 0; + } + + type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */ + +- if (type > T10_PI_TYPE3_PROTECTION) +- ret = -ENODEV; +- else if (scsi_host_dif_capable(sdp->host, type)) +- ret = 1; +- +- if (sdkp->first_scan || type != sdkp->protection_type) +- switch (ret) { +- case -ENODEV: +- sd_printk(KERN_ERR, sdkp, "formatted with unsupported" \ +- " protection type %u. Disabling disk!\n", +- type); +- break; +- case 1: +- sd_printk(KERN_NOTICE, sdkp, +- "Enabling DIF Type %u protection\n", type); +- break; +- case 0: +- sd_printk(KERN_NOTICE, sdkp, +- "Disabling DIF Type %u protection\n", type); +- break; +- } ++ if (type > T10_PI_TYPE3_PROTECTION) { ++ sd_printk(KERN_ERR, sdkp, "formatted with unsupported" \ ++ " protection type %u. Disabling disk!\n", ++ type); ++ sdkp->protection_type = 0; ++ return -ENODEV; ++ } + + sdkp->protection_type = type; + +- return ret; ++ return 0; ++} ++ ++static void sd_config_protection(struct scsi_disk *sdkp) ++{ ++ struct scsi_device *sdp = sdkp->device; ++ ++ if (!sdkp->first_scan) ++ return; ++ ++ sd_dif_config_host(sdkp); ++ ++ if (!sdkp->protection_type) ++ return; ++ ++ if (!scsi_host_dif_capable(sdp->host, sdkp->protection_type)) { ++ sd_printk(KERN_NOTICE, sdkp, ++ "Disabling DIF Type %u protection\n", ++ sdkp->protection_type); ++ sdkp->protection_type = 0; ++ } ++ ++ sd_printk(KERN_NOTICE, sdkp, "Enabling DIF Type %u protection\n", ++ sdkp->protection_type); + } + + static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp, +@@ -3198,6 +3206,7 @@ static int sd_revalidate_disk(struct gendisk *disk) + sd_read_app_tag_own(sdkp, buffer); + sd_read_write_same(sdkp, buffer); + sd_read_security(sdkp, buffer); ++ sd_config_protection(sdkp); + } + + /* +@@ -3356,10 +3365,6 @@ static void sd_probe_async(void *data, async_cookie_t cookie) + blk_pm_runtime_init(sdp->request_queue, dev); + device_add_disk(dev, gd); + blk_delete_region(disk_devt(sdkp->disk), SD_MINORS, sd_default_probe); +- if (sdkp->capacity) +- sd_dif_config_host(sdkp); +- +- sd_revalidate_disk(gd); + + if (sdkp->security) { + sdkp->opal_dev = init_opal_dev(sdp, &sd_sec_submit); +diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c +index db72c82486e3..61b9f935604a 100644 +--- a/drivers/scsi/sd_dif.c ++++ b/drivers/scsi/sd_dif.c +@@ -73,8 +73,6 @@ void sd_dif_config_host(struct scsi_disk *sdkp) + bi.profile = &t10_pi_type1_crc; + + bi.tuple_size = sizeof(struct t10_pi_tuple); +- sd_printk(KERN_NOTICE, sdkp, +- "Enabling DIX %s protection\n", bi.profile->name); + + if (dif && type) { + bi.flags |= BLK_INTEGRITY_DEVICE_CAPABLE; +@@ -86,11 +84,11 @@ void sd_dif_config_host(struct scsi_disk *sdkp) + bi.tag_size = sizeof(u16) + sizeof(u32); + else + bi.tag_size = sizeof(u16); +- +- sd_printk(KERN_NOTICE, sdkp, "DIF application tag size %u\n", +- bi.tag_size); + } + ++ sd_printk(KERN_NOTICE, sdkp, ++ "Enabling DIX %s, application tag size %u bytes\n", ++ bi.profile->name, bi.tag_size); + out: + blk_integrity_register(disk, &bi); + } +-- +2.27.0 + diff --git a/patches/0542-scsi-sd-Update-DIX-config-every-time-sd_revalidate_d.patch b/patches/0542-scsi-sd-Update-DIX-config-every-time-sd_revalidate_d.patch new file mode 100644 index 00000000..8fe5e68e --- /dev/null +++ b/patches/0542-scsi-sd-Update-DIX-config-every-time-sd_revalidate_d.patch @@ -0,0 +1,116 @@ +From 113a0e315ecfb410c8598a415bb4b2c74282e50a Mon Sep 17 00:00:00 2001 +From: Xingui Yang +Date: Fri, 14 Apr 2023 16:20:44 +0800 +Subject: [PATCH 224/256] scsi: sd: Update DIX config every time + sd_revalidate_disk() is called + +mainline inclusion +from mainline-v6.3-rc1 +commit 26a02d972bad946ecbaa12131736c8b6d28893f8 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F85N + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=26a02d972bad946ecbaa12131736c8b6d28893f8 + +---------------------------------------------------------------------- + +If a controller has DIX is enabled and an attached disk is formatted using +a protection type supported by the controller, a block integrity profile is +registered to enable protected transfers. + +If the disk is subsequently reformatted to disable PI, and the controller +does not support DIX Type 0, this can lead to failures such as this: + +[142829.032340] hisi_sas_v3_hw 0000:b4:04.0: erroneous completion iptt=2375 task=00000000bea0970c dev id=5 direct-attached phy4 addr=51c20dbaf642a000 CQ hdr: 0x1023 0x50947 0x0 0x20000 Error info: 0x0 0x0 0x4 0x0 +[142829.073883] sas: Enter sas_scsi_recover_host busy: 1 failed: 1 +[142829.079783] sas: sas_scsi_find_task: aborting task 0x00000000bea0970c +[142829.102342] sas: Internal abort: task to dev 51c20dbaf642a000 response: 0x0 status 0x5 +[142829.110319] sas: sas_eh_handle_sas_errors: task 0x00000000bea0970c is done +[142829.117275] sd 7:0:5:0: [sdc] tag#2375 UNKNOWN(0x2003) Result: hostbyte=0x05 driverbyte=DRIVER_OK cmd_age=0s +[142829.127171] sd 7:0:5:0: [sdc] tag#2375 CDB: opcode=0x2a 2a 00 00 00 00 00 00 00 08 00 +[142829.135059] I/O error, dev sdc, sector 0 op 0x1:(WRITE) flags 0x18800 phys_seg 1 prio class 2 + +This is because the block layer integrity profile is currently only set up +the first time a disk is discovered. + +To address this, remove the first_scan check when configuring protection +information during revalidate. Also unregister the block integrity profile +if DIX is not supported with a given protection type. + +[mkp: commit description + printk dedup] + +Link: https://lore.kernel.org/r/20230221081026.24736-1-yangxingui@huawei.com +Signed-off-by: Xingui Yang +Signed-off-by: Martin K. Petersen +Signed-off-by: xiabing +Signed-off-by: YunYi Yang +--- + drivers/scsi/sd.c | 13 +++++-------- + drivers/scsi/sd_dif.c | 10 ++++++---- + 2 files changed, 11 insertions(+), 12 deletions(-) + +diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c +index 203bd0de14c7..668be9ce6243 100644 +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -2238,23 +2238,20 @@ static void sd_config_protection(struct scsi_disk *sdkp) + { + struct scsi_device *sdp = sdkp->device; + +- if (!sdkp->first_scan) +- return; +- + sd_dif_config_host(sdkp); + + if (!sdkp->protection_type) + return; + + if (!scsi_host_dif_capable(sdp->host, sdkp->protection_type)) { +- sd_printk(KERN_NOTICE, sdkp, +- "Disabling DIF Type %u protection\n", +- sdkp->protection_type); ++ sd_first_printk(KERN_NOTICE, sdkp, ++ "Disabling DIF Type %u protection\n", ++ sdkp->protection_type); + sdkp->protection_type = 0; + } + +- sd_printk(KERN_NOTICE, sdkp, "Enabling DIF Type %u protection\n", +- sdkp->protection_type); ++ sd_first_printk(KERN_NOTICE, sdkp, "Enabling DIF Type %u protection\n", ++ sdkp->protection_type); + } + + static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp, +diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c +index 61b9f935604a..a620e0c002aa 100644 +--- a/drivers/scsi/sd_dif.c ++++ b/drivers/scsi/sd_dif.c +@@ -53,8 +53,10 @@ void sd_dif_config_host(struct scsi_disk *sdkp) + dif = 0; dix = 1; + } + +- if (!dix) ++ if (!dix) { ++ blk_integrity_unregister(disk); + return; ++ } + + memset(&bi, 0, sizeof(bi)); + +@@ -86,9 +88,9 @@ void sd_dif_config_host(struct scsi_disk *sdkp) + bi.tag_size = sizeof(u16); + } + +- sd_printk(KERN_NOTICE, sdkp, +- "Enabling DIX %s, application tag size %u bytes\n", +- bi.profile->name, bi.tag_size); ++ sd_first_printk(KERN_NOTICE, sdkp, ++ "Enabling DIX %s, application tag size %u bytes\n", ++ bi.profile->name, bi.tag_size); + out: + blk_integrity_register(disk, &bi); + } +-- +2.27.0 + diff --git a/patches/0543-scsi-hisi_sas-Increase-debugfs_dump_index-after-dump.patch b/patches/0543-scsi-hisi_sas-Increase-debugfs_dump_index-after-dump.patch new file mode 100644 index 00000000..b02697ca --- /dev/null +++ b/patches/0543-scsi-hisi_sas-Increase-debugfs_dump_index-after-dump.patch @@ -0,0 +1,55 @@ +From 28ba59b17fb693e7aafd1cd895707d1c6347023b Mon Sep 17 00:00:00 2001 +From: Ni Fujia +Date: Wed, 12 Jan 2022 15:17:15 +0800 +Subject: [PATCH 225/256] scsi: hisi_sas: Increase debugfs_dump_index after + dump is completed + +mainline inclusion +from mainline-v5.16-rc1 +commit 9aec5ffa6e39926cff1a6b576c815a9cee90e259 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F81U + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9aec5ffa6e39926cff1a6b576c815a9cee90e259 + +---------------------------------------------------------------------- + +The hisi_hba debugfs_dump_index member should increased after a dump +insertion completed, and not before it has started, so fix the code to do +so. + +Signed-off-by: Luo Jiaxing +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Reviewed-by: Wei Li +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 8133f043c2f1..4b7a58f17036 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -4116,7 +4116,6 @@ static void debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba) + + do_div(timestamp, NSEC_PER_MSEC); + hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp; +- hisi_hba->debugfs_dump_index++; + + debugfs_snapshot_prepare_v3_hw(hisi_hba); + +@@ -4132,6 +4131,7 @@ static void debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba) + debugfs_create_files_v3_hw(hisi_hba); + + debugfs_snapshot_restore_v3_hw(hisi_hba); ++ hisi_hba->debugfs_dump_index++; + } + + static ssize_t debugfs_trigger_dump_v3_hw_write(struct file *file, +-- +2.27.0 + diff --git a/patches/0544-scsi-hisi_sas-Configure-the-initialization-registers.patch b/patches/0544-scsi-hisi_sas-Configure-the-initialization-registers.patch new file mode 100644 index 00000000..71bd2b3a --- /dev/null +++ b/patches/0544-scsi-hisi_sas-Configure-the-initialization-registers.patch @@ -0,0 +1,103 @@ +From 06b51a86cf25bc47bd5d42d32de0808ab9d1ae75 Mon Sep 17 00:00:00 2001 +From: Yihang Li +Date: Fri, 28 Apr 2023 14:39:18 +0800 +Subject: [PATCH 226/256] scsi: hisi_sas: Configure the initialization + registers according to HBA model + +mainline inclusion +from mainline-v6.5-rc1 +commit b68daae9660b45a0bb3ac9df1f1746d15693d254 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F81U + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b68daae9660b45a0bb3ac9df1f1746d15693d254 + +---------------------------------------------------------------------- + +We use init_reg_v3_hw() to set some registers, for the latest HBA devices, +some of these HW registers are set through firmware. Therefore, different +HBA models are distinguished through pci_dev->revision. + +Signed-off-by: Yihang Li +Reviewed-by: Xiang Chen +Signed-off-by: xiabing +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 4b7a58f17036..eb248289468a 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -653,12 +653,12 @@ static void interrupt_enable_v3_hw(struct hisi_hba *hisi_hba) + + static void init_reg_v3_hw(struct hisi_hba *hisi_hba) + { ++ struct pci_dev *pdev = hisi_hba->pci_dev; + int i, j; + + /* Global registers init */ + hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, + (u32)((1ULL << hisi_hba->queue_count) - 1)); +- hisi_sas_write32(hisi_hba, SAS_AXI_USER3, 0); + hisi_sas_write32(hisi_hba, CFG_MAX_TAG, 0xfff0400); + /* time / CLK_AHB = 2.5s / 2ns = 0x4A817C80 */ + hisi_sas_write32(hisi_hba, TRANS_LOCK_ICT_TIME, 0x4A817C80); +@@ -686,6 +686,9 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) + hisi_sas_write32(hisi_hba, AXI_MASTER_CFG_BASE, 0x10000); + } + ++ if (pdev->revision < 0x30) ++ hisi_sas_write32(hisi_hba, SAS_AXI_USER3, 0); ++ + interrupt_enable_v3_hw(hisi_hba); + for (i = 0; i < hisi_hba->n_phy; i++) { + enum sas_linkrate max; +@@ -714,7 +717,6 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) + SAS_RX_TRAIN_TIMER, 0x13e80); + } + +- hisi_sas_phy_write32(hisi_hba, i, SERDES_CFG, 0xffc00); + hisi_sas_phy_write32(hisi_hba, i, CHL_INT0, 0xffffffff); + hisi_sas_phy_write32(hisi_hba, i, CHL_INT1, 0xffffffff); + hisi_sas_phy_write32(hisi_hba, i, CHL_INT2, 0xffffffff); +@@ -741,13 +743,18 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) + hisi_sas_phy_write32(hisi_hba, i, CON_CFG_DRIVER, 0x2a0a01); + hisi_sas_phy_write32(hisi_hba, i, SAS_EC_INT_COAL_TIME, + 0x30f4240); +- hisi_sas_phy_write32(hisi_hba, i, +- SAS_SSP_CON_TIMER_CFG, 0x32); +- +- /* used for 12G negotiate */ +- hisi_sas_phy_write32(hisi_hba, i, COARSETUNE_TIME, 0x1e); + hisi_sas_phy_write32(hisi_hba, i, AIP_LIMIT, 0x2ffff); + ++ /* set value through firmware for the latest HBA */ ++ if (pdev->revision < 0x30) { ++ hisi_sas_phy_write32(hisi_hba, i, ++ SAS_SSP_CON_TIMER_CFG, 0x32); ++ hisi_sas_phy_write32(hisi_hba, i, SERDES_CFG, 0xffc00); ++ /* used for 12G negotiate */ ++ hisi_sas_phy_write32(hisi_hba, i, ++ COARSETUNE_TIME, 0x1e); ++ } ++ + /* get default FFE configuration for BIST */ + for (j = 0; j < FFE_CFG_MAX; j++) { + u32 val = hisi_sas_phy_read32(hisi_hba, i, +@@ -759,7 +766,7 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) + for (i = 0; i < hisi_hba->queue_count; i++) { + /* Delivery queue */ + hisi_sas_write32(hisi_hba, +- DLVRY_Q_0_BASE_ADDR_HI + ++ DLVRY_Q_0_BASE_ADDR_HI + + (i * NEXT_DQCQ_REG_OFF), + upper_32_bits(hisi_hba->cmd_hdr_dma[i])); + +-- +2.27.0 + diff --git a/patches/0545-scsi-hisi_sas-Add-slave_destroy-interface-for-v3-hw.patch b/patches/0545-scsi-hisi_sas-Add-slave_destroy-interface-for-v3-hw.patch new file mode 100644 index 00000000..12b05d50 --- /dev/null +++ b/patches/0545-scsi-hisi_sas-Add-slave_destroy-interface-for-v3-hw.patch @@ -0,0 +1,87 @@ +From 271e746bc3aff18487180122b78096b6e38a3a13 Mon Sep 17 00:00:00 2001 +From: Qi Liu +Date: Thu, 8 Jun 2023 11:04:48 +0800 +Subject: [PATCH 227/256] scsi: hisi_sas: Add slave_destroy interface for v3 hw + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81U +CVE: NA + +---------------------------------------------------------------------- + +A WARNING is triggered when executing link reset of remote PHY +and rmmod SAS driver simultaneously. Following is the WARNING log: + +WARNING: CPU: 61 PID: 21818 at drivers/base/core.c:1347 __device_links_no_driver+0xb4/0xc0 + Call trace: + __device_links_no_driver+0xb4/0xc0 + device_links_driver_cleanup+0xb0/0xfc + __device_release_driver+0x198/0x23c + device_release_driver+0x38/0x50 + bus_remove_device+0x130/0x140 + device_del+0x184/0x434 + __scsi_remove_device+0x118/0x150 + scsi_remove_target+0x1bc/0x240 + sas_rphy_remove+0x90/0x94 + sas_rphy_delete+0x24/0x3c + sas_destruct_devices+0x64/0xa0 [libsas] + sas_revalidate_domain+0xe4/0x150 [libsas] + process_one_work+0x1e0/0x46c + worker_thread+0x15c/0x464 + kthread+0x160/0x170 + ret_from_fork+0x10/0x20 + ---[ end trace 71e059eb58f85d4a ]--- + +During SAS phy up, link->status is set to DL_STATE_AVAILABLE in +device_links_driver_bound, then this setting influences +__device_links_no_driver() before driver rmmod and caused WARNING. + +So we add the slave_destroy interface, to make sure link is removed +after flush workque. + +Fixes: 16fd4a7c59170 ("scsi: hisi_sas: Add device link between SCSI devices and hisi_hba") +Signed-off-by: Qi Liu +Signed-off-by: John Garry +Signed-off-by: xiabing +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index eb248289468a..2fc6d537c1ea 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -3181,6 +3181,17 @@ static int slave_configure_v3_hw(struct scsi_device *sdev) + + return 0; + } ++ ++static void slave_destroy_v3_hw(struct scsi_device *sdev) ++{ ++ struct Scsi_Host *shost = dev_to_shost(&sdev->sdev_gendev); ++ struct hisi_hba *hisi_hba = shost_priv(shost); ++ struct device *dev = hisi_hba->dev; ++ ++ device_link_remove(&sdev->sdev_gendev, dev); ++} ++ ++ + #define HISI_SAS_DEBUGFS_REG(x) {#x, x} + + struct hisi_sas_debugfs_reg_lu { +@@ -3592,6 +3603,7 @@ static struct scsi_host_template sht_v3_hw = { + .eh_device_reset_handler = sas_eh_device_reset_handler, + .eh_target_reset_handler = sas_eh_target_reset_handler, + .slave_alloc = hisi_sas_slave_alloc, ++ .slave_destroy = slave_destroy_v3_hw, + .target_destroy = sas_target_destroy, + .ioctl = sas_ioctl, + .shost_attrs = host_attrs_v3_hw, +-- +2.27.0 + diff --git a/patches/0546-scsi-hisi_sas-Block-requests-before-take-debugfs-sna.patch b/patches/0546-scsi-hisi_sas-Block-requests-before-take-debugfs-sna.patch new file mode 100644 index 00000000..a469ec8f --- /dev/null +++ b/patches/0546-scsi-hisi_sas-Block-requests-before-take-debugfs-sna.patch @@ -0,0 +1,68 @@ +From 1322de4b70b27dd714cae4c21e0c9c8382fbbffe Mon Sep 17 00:00:00 2001 +From: Yihang Li +Date: Thu, 8 Jun 2023 11:04:49 +0800 +Subject: [PATCH 228/256] scsi: hisi_sas: Block requests before take debugfs + snapshot + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F82P +CVE: NA + +---------------------------------------------------------------------- + +When the FIO is running and the dump is triggered continuously, some SATA +I/Os fail to be returned to the upper layer due to the setting of +HISI_SAS_REJECT_CMD_BIT. The SCSI layer invokes the error processing +thread. However, sas_ata_hard_reset() also fails to be reset due to the +setting of HISI_SAS_REJECT_CMD_BIT. As a result, the device is disabled. +Call scsi_block_requests() and wait command complete before setting +HISI_SAS_REJECT_CMD_BIT to avoid SATA I/O failures. + +Signed-off-by: Yihang Li +Signed-off-by: xiabing +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 2fc6d537c1ea..662d68d5da90 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -3378,22 +3378,25 @@ static const struct hisi_sas_debugfs_reg debugfs_ras_reg = { + + static void debugfs_snapshot_prepare_v3_hw(struct hisi_hba *hisi_hba) + { +- set_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); +- +- hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0); ++ struct Scsi_Host *shost = hisi_hba->shost; + ++ scsi_block_requests(shost); + /* delay:100ms, timeout:5s */ + wait_cmds_complete_timeout_v3_hw(hisi_hba, 100, 5000); +- ++ set_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); + hisi_sas_sync_irqs(hisi_hba); ++ hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0); + } + + static void debugfs_snapshot_restore_v3_hw(struct hisi_hba *hisi_hba) + { ++ struct Scsi_Host *shost = hisi_hba->shost; ++ + hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, + (u32)((1ULL << hisi_hba->queue_count) - 1)); + + clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); ++ scsi_unblock_requests(shost); + } + + static void hisi_sas_bist_test_prep_v3_hw(struct hisi_hba *hisi_hba) +-- +2.27.0 + diff --git a/patches/0547-scsi-hisi_sas-Work-around-build-failure-in-suspend-f.patch b/patches/0547-scsi-hisi_sas-Work-around-build-failure-in-suspend-f.patch new file mode 100644 index 00000000..cac49865 --- /dev/null +++ b/patches/0547-scsi-hisi_sas-Work-around-build-failure-in-suspend-f.patch @@ -0,0 +1,81 @@ +From 680001b30324113814ddb83ed26b414acd521645 Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Thu, 8 Jun 2023 20:00:00 +0800 +Subject: [PATCH 229/256] scsi: hisi_sas: Work around build failure in suspend + function + +mainline inclusion +from mainline-v6.4-rc1 +commit e01e2290f0948ea6d383a5b715738911308b4d2b +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e01e2290f0948ea6d383a5b715738911308b4d2b + +---------------------------------------------------------------------- + +The suspend/resume functions in this driver seem to have multiple problems, +the latest one just got introduced by a bugfix: + +drivers/scsi/hisi_sas/hisi_sas_v3_hw.c: In function '_suspend_v3_hw': +drivers/scsi/hisi_sas/hisi_sas_v3_hw.c:5142:39: error: 'struct dev_pm_info' has no member named 'usage_count' + 5142 | if (atomic_read(&device->power.usage_count)) { +drivers/scsi/hisi_sas/hisi_sas_v3_hw.c: In function '_suspend_v3_hw': +drivers/scsi/hisi_sas/hisi_sas_v3_hw.c:5142:39: error: 'struct dev_pm_info' has no member named 'usage_count' + 5142 | if (atomic_read(&device->power.usage_count)) { + +As far as I can tell, the 'usage_count' is not meant to be accessed by +device drivers at all, though I don't know what the driver is supposed to +do instead. + +Another problem is the use of the deprecated UNIVERSAL_DEV_PM_OPS(), and +marking functions as __maybe_unused to avoid warnings about unused +functions. This should probably be changed to using +DEFINE_RUNTIME_DEV_PM_OPS(). + +Both changes require actually understanding what the driver needs to do, +and being able to test this, so instead here is the simplest patch to make +it pass the randconfig builds instead. + +Fixes: e368d38cb952 ("scsi: hisi_sas: Exit suspend state when usage count is greater than 0") +Signed-off-by: Arnd Bergmann +Link: https://lore.kernel.org/r/20230405083611.3376739-1-arnd@kernel.org +Reviewed-by: Xiang Chen +Signed-off-by: Martin K. Petersen +Signed-off-by: xiabing +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 662d68d5da90..eb66ea7ea5b5 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -5427,11 +5427,13 @@ static int _suspend_v3_hw(struct device *device) + flush_workqueue(hisi_hba->wq); + interrupt_disable_v3_hw(hisi_hba); + ++#ifdef CONFIG_PM + if (atomic_read(&device->power.usage_count)) { + dev_err(dev, "PM suspend: host status cannot be suspended\n"); + rc = -EBUSY; + goto err_out; + } ++#endif + + rc = disable_host_v3_hw(hisi_hba); + if (rc) { +@@ -5457,7 +5459,9 @@ static int _suspend_v3_hw(struct device *device) + + err_out_recover_host: + enable_host_v3_hw(hisi_hba); ++#ifdef CONFIG_PM + err_out: ++#endif + interrupt_enable_v3_hw(hisi_hba); + clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); + clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags); +-- +2.27.0 + diff --git a/patches/0548-scsi-hisi_sas-Check-usage-count-only-when-the-runtim.patch b/patches/0548-scsi-hisi_sas-Check-usage-count-only-when-the-runtim.patch new file mode 100644 index 00000000..86f96f0f --- /dev/null +++ b/patches/0548-scsi-hisi_sas-Check-usage-count-only-when-the-runtim.patch @@ -0,0 +1,62 @@ +From a095fa88bd931525323202eea19719d579820cb5 Mon Sep 17 00:00:00 2001 +From: Yihang Li +Date: Thu, 8 Jun 2023 11:04:51 +0800 +Subject: [PATCH 230/256] scsi: hisi_sas: Check usage count only when the + runtime PM status is RPM_SUSPENDING + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 +CVE: NA + +---------------------------------------------------------------------- + +Users can suspend the machine with 'echo disk > /sys/power/state', but the +suspend will fail because the SAS controller cannot be suspended: + +[root@localhost ~]# echo freeze > /sys/power/state +-bash: echo: write error: Device or resource busy +[15104.142955] PM: suspend entry (s2idle) +... +[15104.283465] hisi_sas_v3_hw 0000:32:04.0: entering suspend state +[15104.283480] hisi_sas_v3_hw 0000:30:04.0: entering suspend state +[15104.283500] hisi_sas_v3_hw 0000:32:04.0: PM suspend: host status cannot be suspended +[15104.283508] hisi_sas_v3_hw 0000:30:04.0: PM suspend: host status cannot be suspended +[15104.283516] hisi_sas_v3_hw 0000:32:04.0: PM: pci_pm_suspend(): suspend_v3_hw+0x0/0x210 [hisi_sas_v3_hw] returns -16 +[15104.283527] hisi_sas_v3_hw 0000:32:04.0: PM: dpm_run_callback(): pci_pm_suspend+0x0/0x1c0 returns -16 +[15104.283524] hisi_sas_v3_hw 0000:30:04.0: PM: pci_pm_suspend(): suspend_v3_hw+0x0/0x210 [hisi_sas_v3_hw] returns -16 +[15104.283533] hisi_sas_v3_hw 0000:32:04.0: PM: failed to suspend async: error -16 +[15104.283536] hisi_sas_v3_hw 0000:30:04.0: PM: dpm_run_callback(): pci_pm_suspend+0x0/0x1c0 returns -16 +[15104.283542] hisi_sas_v3_hw 0000:30:04.0: PM: failed to suspend async: error -16 + +The problem is that when the ->runtime_suspend() callback suspend_v3_hw() +is executing, the current runtime PM status is RPM_ACTIVE and the usage +count of the controller is not 0, so return immediately. + +To fix it, Check the device usage count only when the runtime PM status is +RPM_SUSPENDING. + +Signed-off-by: Yihang Li +Signed-off-by: xiabing +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index eb66ea7ea5b5..1cf9855c5969 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -5428,7 +5428,8 @@ static int _suspend_v3_hw(struct device *device) + interrupt_disable_v3_hw(hisi_hba); + + #ifdef CONFIG_PM +- if (atomic_read(&device->power.usage_count)) { ++ if ((device->power.runtime_status == RPM_SUSPENDING) && ++ atomic_read(&device->power.usage_count)) { + dev_err(dev, "PM suspend: host status cannot be suspended\n"); + rc = -EBUSY; + goto err_out; +-- +2.27.0 + diff --git a/patches/0549-scsi-sd-try-more-retries-of-START_STOP-when-resuming.patch b/patches/0549-scsi-sd-try-more-retries-of-START_STOP-when-resuming.patch new file mode 100644 index 00000000..3a5377dd --- /dev/null +++ b/patches/0549-scsi-sd-try-more-retries-of-START_STOP-when-resuming.patch @@ -0,0 +1,87 @@ +From 3e8b8625d1484cfff13178b29f13042ad02e818a Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Thu, 8 Jun 2023 11:04:47 +0800 +Subject: [PATCH 231/256] scsi: sd: try more retries of START_STOP when + resuming scsi device + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 +CVE: NA + +---------------------------------------------------------------------- + +When sending START_STOP commands to resume scsi_device, it may be +interrupted by exception operations such as host reset or FLR. +Once the command of START_STOP is failed, the runtime_status of +scsi device will be error and it is difficult for user to recover it. +So try more retries to increase robustness as the process of +command SYNCHRONIZE_CACHE in function sd_sync_cache() when suspending +scsi device. + +Signed-off-by: Xiang Chen +Signed-off-by: xiabing +Signed-off-by: YunYi Yang +--- + drivers/scsi/sd.c | 24 ++++++++++++++++++------ + 1 file changed, 18 insertions(+), 6 deletions(-) + +diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c +index 668be9ce6243..c93029b32005 100644 +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -3622,6 +3622,7 @@ static int sd_suspend_common(struct device *dev, bool ignore_stop_errors) + { + struct scsi_disk *sdkp = dev_get_drvdata(dev); + struct scsi_sense_hdr sshdr; ++ int retries; + int ret = 0; + + if (!sdkp) /* E.g.: runtime suspend following sd_remove() */ +@@ -3652,9 +3653,15 @@ static int sd_suspend_common(struct device *dev, bool ignore_stop_errors) + if (sdkp->device->manage_start_stop) { + sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n"); + /* an error is not worth aborting a system sleep */ +- ret = sd_start_stop_device(sdkp, 0); +- if (ignore_stop_errors) +- ret = 0; ++ for (retries = 3; retries > 0; --retries) { ++ ret = sd_start_stop_device(sdkp, 0); ++ if (!ret) ++ break; ++ if (ignore_stop_errors) { ++ ret = 0; ++ break; ++ } ++ } + } + + return ret; +@@ -3673,6 +3680,7 @@ static int sd_suspend_runtime(struct device *dev) + static int sd_resume(struct device *dev) + { + struct scsi_disk *sdkp = dev_get_drvdata(dev); ++ int retries; + int ret; + + if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */ +@@ -3682,9 +3690,13 @@ static int sd_resume(struct device *dev) + return 0; + + sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); +- ret = sd_start_stop_device(sdkp, 1); +- if (!ret) +- opal_unlock_from_suspend(sdkp->opal_dev); ++ for (retries = 3; retries > 0; --retries) { ++ ret = sd_start_stop_device(sdkp, 1); ++ if (!ret) { ++ opal_unlock_from_suspend(sdkp->opal_dev); ++ break; ++ } ++ } + return ret; + } + +-- +2.27.0 + diff --git a/patches/0550-scsi-hisi_sas_v3_hw-Don-t-use-PCI-helper-functions.patch b/patches/0550-scsi-hisi_sas_v3_hw-Don-t-use-PCI-helper-functions.patch new file mode 100644 index 00000000..0474bbcb --- /dev/null +++ b/patches/0550-scsi-hisi_sas_v3_hw-Don-t-use-PCI-helper-functions.patch @@ -0,0 +1,91 @@ +From 15ae52e091cbe4ca434be24e6dcef9049d86e654 Mon Sep 17 00:00:00 2001 +From: Vaibhav Gupta +Date: Tue, 3 Aug 2021 14:47:24 +0800 +Subject: [PATCH 232/256] scsi: hisi_sas_v3_hw: Don't use PCI helper functions + +mainline inclusion +from mainline-v5.11-rc1 +commit 027e508aea458719390eb6a83a297940e8ae79f1 +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81U +CVE: NA + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=027e508aea458719390eb6a83a297940e8ae79f1 + +------------------------------------------------------------------------ + +Drivers using new-framework/generic-framework should not handle standard +power management operations. These operations were performed by legacy +framework through PCI helper functions like pci_save/restore_state(), +pci_set_power_state(), etc. + +Drivers should not use them now. + +Link: https://lore.kernel.org/r/20201102164730.324035-14-vaibhavgupta40@gmail.com +Signed-off-by: Vaibhav Gupta +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 18 +----------------- + 1 file changed, 1 insertion(+), 17 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 1cf9855c5969..6c93b3f0557e 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -5409,7 +5409,6 @@ static int _suspend_v3_hw(struct device *device) + struct hisi_hba *hisi_hba = sha->lldd_ha; + struct device *dev = hisi_hba->dev; + struct Scsi_Host *shost = hisi_hba->shost; +- u32 device_state; + int rc; + + if (!pdev->pm_cap) { +@@ -5444,12 +5443,7 @@ static int _suspend_v3_hw(struct device *device) + + hisi_sas_init_mem(hisi_hba); + +- device_state = pci_choose_state(pdev, PMSG_SUSPEND); +- dev_warn(dev, "entering operating state [D%d]\n", +- device_state); +- pci_save_state(pdev); +- pci_disable_device(pdev); +- pci_set_power_state(pdev, device_state); ++ dev_warn(dev, "entering suspend state\n"); + + hisi_sas_release_tasks(hisi_hba); + +@@ -5482,16 +5476,7 @@ static int _resume_v3_hw(struct device *device) + + dev_warn(dev, "resuming from operating state [D%d]\n", + device_state); +- pci_set_power_state(pdev, PCI_D0); +- pci_enable_wake(pdev, PCI_D0, 0); +- pci_restore_state(pdev); +- rc = pci_enable_device(pdev); +- if (rc) { +- dev_err(dev, "enable device failed during resume (%d)\n", rc); +- return rc; +- } + +- pci_set_master(pdev); + scsi_unblock_requests(shost); + clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); + +@@ -5499,7 +5484,6 @@ static int _resume_v3_hw(struct device *device) + rc = hw_init_v3_hw(hisi_hba); + if (rc) { + scsi_remove_host(shost); +- pci_disable_device(pdev); + return rc; + } + phys_init_v3_hw(hisi_hba); +-- +2.27.0 + diff --git a/patches/0551-scsi-hisi_sas_v3_hw-Remove-extra-function-calls-for-.patch b/patches/0551-scsi-hisi_sas_v3_hw-Remove-extra-function-calls-for-.patch new file mode 100644 index 00000000..b6e31888 --- /dev/null +++ b/patches/0551-scsi-hisi_sas_v3_hw-Remove-extra-function-calls-for-.patch @@ -0,0 +1,89 @@ +From 1b68f29afba6d4828da79c4546f8fd6687faf571 Mon Sep 17 00:00:00 2001 +From: Vaibhav Gupta +Date: Tue, 3 Aug 2021 14:47:25 +0800 +Subject: [PATCH 233/256] scsi: hisi_sas_v3_hw: Remove extra function calls for + runtime pm + +mainline inclusion +from mainline-v5.11-rc1 +commit 71c8f15e1dbcd202f0b27d7560ce191c5a3b7286 +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F81U +CVE: NA + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=71c8f15e1dbcd202f0b27d7560ce191c5a3b7286 + +------------------------------------------------------------------------ + +Both runtime_suspend_v3_hw() and runtime_resume_v3_hw() do nothing else but +invoke suspend_v3_hw() and resume_v3_hw() respectively. This is the case of +unnecessary function calls. To use those functions for runtime pm as well, +simply use UNIVERSAL_DEV_PM_OPS. + +make -j$(nproc) W=1, with CONFIG_PM disabled, throws '-Wunused-function' +warning for runtime_suspend_v3_hw() and runtime_resume_v3_hw(). After +dropping those function definitions, the warning was thrown for +suspend_v3_hw() and resume_v3_hw(). Hence, mark them as '__maybe_unused'. + +Link: https://lore.kernel.org/r/20201102164730.324035-15-vaibhavgupta40@gmail.com +Signed-off-by: Vaibhav Gupta +Signed-off-by: Martin K. Petersen +Reviewed-by: Ouyangdelong +Signed-off-by: Nifujia +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 23 ++++++----------------- + 1 file changed, 6 insertions(+), 17 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 6c93b3f0557e..f8a065409d3f 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -5503,7 +5503,7 @@ static int _resume_v3_hw(struct device *device) + return 0; + } + +-static int suspend_v3_hw(struct device *device) ++static int __maybe_unused suspend_v3_hw(struct device *device) + { + struct pci_dev *pdev = to_pci_dev(device); + struct sas_ha_struct *sha = pci_get_drvdata(pdev); +@@ -5519,7 +5519,7 @@ static int suspend_v3_hw(struct device *device) + return rc; + } + +-static int resume_v3_hw(struct device *device) ++static int __maybe_unused resume_v3_hw(struct device *device) + { + struct pci_dev *pdev = to_pci_dev(device); + struct sas_ha_struct *sha = pci_get_drvdata(pdev); +@@ -5542,21 +5542,10 @@ static const struct pci_error_handlers hisi_sas_err_handler = { + .reset_done = hisi_sas_reset_done_v3_hw, + }; + +-static int runtime_suspend_v3_hw(struct device *dev) +-{ +- return suspend_v3_hw(dev); +-} +- +-static int runtime_resume_v3_hw(struct device *dev) +-{ +- return resume_v3_hw(dev); +-} +- +-static const struct dev_pm_ops hisi_sas_v3_pm_ops = { +- SET_SYSTEM_SLEEP_PM_OPS(suspend_v3_hw, resume_v3_hw) +- SET_RUNTIME_PM_OPS(runtime_suspend_v3_hw, +- runtime_resume_v3_hw, NULL) +-}; ++static UNIVERSAL_DEV_PM_OPS(hisi_sas_v3_pm_ops, ++ suspend_v3_hw, ++ resume_v3_hw, ++ NULL); + + static struct pci_driver sas_v3_pci_driver = { + .name = DRV_NAME, +-- +2.27.0 + diff --git a/patches/0552-scsi-block-pm-Simplify-resume-handling.patch b/patches/0552-scsi-block-pm-Simplify-resume-handling.patch new file mode 100644 index 00000000..d10b4b60 --- /dev/null +++ b/patches/0552-scsi-block-pm-Simplify-resume-handling.patch @@ -0,0 +1,131 @@ +From d3f50dd778db514d3f78eb30c84d88843d66e7eb Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Mon, 6 Jul 2020 11:14:36 -0400 +Subject: [PATCH 234/256] scsi: block: pm: Simplify resume handling + +mainline inclusion +from mainline-v5.9-rc1 +commit 8f38f8e0a30e1c33cdfc48eba2bd63ac2eae373a +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8f38f8e0a30e1c33cdfc48eba2bd63ac2eae373a + +---------------------------------------------------------------------- + +Commit 05d18ae1cc8a ("scsi: pm: Balance pm_only counter of request queue +during system resume") fixed a problem in the block layer's runtime-PM +code: blk_set_runtime_active() failed to call blk_clear_pm_only(). +However, the commit's implementation was awkward; it forced the SCSI +system-resume handler to choose whether to call blk_post_runtime_resume() +or blk_set_runtime_active(), depending on whether or not the SCSI device +had previously been runtime suspended. + +This patch simplifies the situation considerably by adding the missing +function call directly into blk_set_runtime_active() (under the condition +that the queue is not already in the RPM_ACTIVE state). This allows the +SCSI routine to revert back to its original form. Furthermore, making this +change reveals that blk_post_runtime_resume() (in its success pathway) does +exactly the same thing as blk_set_runtime_active(). The duplicate code is +easily removed by making one routine call the other. + +No functional changes are intended. + +Link: https://lore.kernel.org/r/20200706151436.GA702867@rowland.harvard.edu +CC: Can Guo +CC: Bart Van Assche +Reviewed-by: Bart Van Assche +Signed-off-by: Alan Stern +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + block/blk-pm.c + drivers/scsi/scsi_pm.c +--- + block/blk-pm.c | 29 +++++++++++++++++------------ + drivers/scsi/scsi_pm.c | 3 +-- + 2 files changed, 18 insertions(+), 14 deletions(-) + +diff --git a/block/blk-pm.c b/block/blk-pm.c +index f8fdae01bea2..8f186fad14f8 100644 +--- a/block/blk-pm.c ++++ b/block/blk-pm.c +@@ -164,9 +164,8 @@ EXPORT_SYMBOL(blk_pre_runtime_resume); + * + * Description: + * Update the queue's runtime status according to the return value of the +- * device's runtime_resume function. If it is successfully resumed, process +- * the requests that are queued into the device's queue when it is resuming +- * and then mark last busy and initiate autosuspend for it. ++ * device's runtime_resume function. If the resume was successful, call ++ * blk_set_runtime_active() to do the real work of restarting the queue. + * + * This function should be called near the end of the device's + * runtime_resume callback. +@@ -175,19 +174,13 @@ void blk_post_runtime_resume(struct request_queue *q, int err) + { + if (!q->dev) + return; +- +- spin_lock_irq(q->queue_lock); + if (!err) { +- q->rpm_status = RPM_ACTIVE; +- pm_runtime_mark_last_busy(q->dev); +- pm_request_autosuspend(q->dev); ++ blk_set_runtime_active(q); + } else { ++ spin_lock_irq(q->queue_lock); + q->rpm_status = RPM_SUSPENDED; ++ spin_unlock_irq(q->queue_lock); + } +- spin_unlock_irq(q->queue_lock); +- +- if (!err) +- blk_clear_pm_only(q); + } + EXPORT_SYMBOL(blk_post_runtime_resume); + +@@ -204,13 +197,25 @@ EXPORT_SYMBOL(blk_post_runtime_resume); + * This function can be used in driver's resume hook to correct queue + * runtime PM status and re-enable peeking requests from the queue. It + * should be called before first request is added to the queue. ++ * ++ * This function is also called by blk_post_runtime_resume() for successful ++ * runtime resumes. It does everything necessary to restart the queue. + */ + void blk_set_runtime_active(struct request_queue *q) + { ++ int old_status; ++ ++ if (!q->dev) ++ return; ++ + spin_lock_irq(q->queue_lock); ++ old_status = q->rpm_status; + q->rpm_status = RPM_ACTIVE; + pm_runtime_mark_last_busy(q->dev); + pm_request_autosuspend(q->dev); + spin_unlock_irq(q->queue_lock); ++ ++ if (old_status != RPM_ACTIVE) ++ blk_clear_pm_only(q); + } + EXPORT_SYMBOL(blk_set_runtime_active); +diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c +index 7639df91b110..f0b16a4ec5f6 100644 +--- a/drivers/scsi/scsi_pm.c ++++ b/drivers/scsi/scsi_pm.c +@@ -93,8 +93,7 @@ static int scsi_dev_type_resume(struct device *dev, + if (!err && scsi_is_sdev_device(dev)) { + struct scsi_device *sdev = to_scsi_device(dev); + +- if (sdev->request_queue->dev) +- blk_set_runtime_active(sdev->request_queue); ++ blk_set_runtime_active(sdev->request_queue); + } + } + +-- +2.27.0 + diff --git a/patches/0553-scsi-block-pm-Always-set-request-queue-runtime-activ.patch b/patches/0553-scsi-block-pm-Always-set-request-queue-runtime-activ.patch new file mode 100644 index 00000000..f09ba4a9 --- /dev/null +++ b/patches/0553-scsi-block-pm-Always-set-request-queue-runtime-activ.patch @@ -0,0 +1,134 @@ +From b37ed4b3d06bbac8ff0595db95174b38c399075d Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Tue, 19 Apr 2022 17:06:55 +0800 +Subject: [PATCH 235/256] scsi: block: pm: Always set request queue runtime + active in blk_post_runtime_resume() + +mainline inclusion +from mainline-v5.17-rc1 +commit 6e1fcab00a23f7fe9f4fe9704905a790efa1eeab +category: bugfix +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 +CVE: NA + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6e1fcab00a23f7fe9f4fe9704905a790efa1eeab + +---------------------------------------------------------------------- + +John Garry reported a deadlock that occurs when trying to access a +runtime-suspended SATA device. For obscure reasons, the rescan procedure +causes the link to be hard-reset, which disconnects the device. + +The rescan tries to carry out a runtime resume when accessing the device. +scsi_rescan_device() holds the SCSI device lock and won't release it until +it can put commands onto the device's block queue. This can't happen until +the queue is successfully runtime-resumed or the device is unregistered. +But the runtime resume fails because the device is disconnected, and +__scsi_remove_device() can't do the unregistration because it can't get the +device lock. + +The best way to resolve this deadlock appears to be to allow the block +queue to start running again even after an unsuccessful runtime resume. +The idea is that the driver or the SCSI error handler will need to be able +to use the queue to resolve the runtime resume failure. + +This patch removes the err argument to blk_post_runtime_resume() and makes +the routine act as though the resume was successful always. This fixes the +deadlock. + +Link: https://lore.kernel.org/r/1639999298-244569-4-git-send-email-chenxiang66@hisilicon.com +Fixes: e27829dc92e5 ("scsi: serialize ->rescan against ->remove") +Reported-and-tested-by: John Garry +Reviewed-by: Bart Van Assche +Signed-off-by: Alan Stern +Signed-off-by: Xiang Chen +Signed-off-by: Martin K. Petersen +Signed-off-by: Fujai Ni +Reviewed-by: Jason Yan +Signed-off-by: Zheng Zengkai +Signed-off-by: YunYi Yang + + Conflicts: + block/blk-pm.c +--- + block/blk-pm.c | 22 +++++++--------------- + drivers/scsi/scsi_pm.c | 2 +- + include/linux/blk-pm.h | 2 +- + 3 files changed, 9 insertions(+), 17 deletions(-) + +diff --git a/block/blk-pm.c b/block/blk-pm.c +index 8f186fad14f8..d8c1eeba96b1 100644 +--- a/block/blk-pm.c ++++ b/block/blk-pm.c +@@ -160,27 +160,19 @@ EXPORT_SYMBOL(blk_pre_runtime_resume); + /** + * blk_post_runtime_resume - Post runtime resume processing + * @q: the queue of the device +- * @err: return value of the device's runtime_resume function + * + * Description: +- * Update the queue's runtime status according to the return value of the +- * device's runtime_resume function. If the resume was successful, call +- * blk_set_runtime_active() to do the real work of restarting the queue. ++ * For historical reasons, this routine merely calls blk_set_runtime_active() ++ * to do the real work of restarting the queue. It does this regardless of ++ * whether the device's runtime-resume succeeded; even if it failed the ++ * driver or error handler will need to communicate with the device. + * + * This function should be called near the end of the device's + * runtime_resume callback. + */ +-void blk_post_runtime_resume(struct request_queue *q, int err) ++void blk_post_runtime_resume(struct request_queue *q) + { +- if (!q->dev) +- return; +- if (!err) { +- blk_set_runtime_active(q); +- } else { +- spin_lock_irq(q->queue_lock); +- q->rpm_status = RPM_SUSPENDED; +- spin_unlock_irq(q->queue_lock); +- } ++ blk_set_runtime_active(q); + } + EXPORT_SYMBOL(blk_post_runtime_resume); + +@@ -198,7 +190,7 @@ EXPORT_SYMBOL(blk_post_runtime_resume); + * runtime PM status and re-enable peeking requests from the queue. It + * should be called before first request is added to the queue. + * +- * This function is also called by blk_post_runtime_resume() for successful ++ * This function is also called by blk_post_runtime_resume() for + * runtime resumes. It does everything necessary to restart the queue. + */ + void blk_set_runtime_active(struct request_queue *q) +diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c +index f0b16a4ec5f6..723da36d12b2 100644 +--- a/drivers/scsi/scsi_pm.c ++++ b/drivers/scsi/scsi_pm.c +@@ -265,7 +265,7 @@ static int sdev_runtime_resume(struct device *dev) + blk_pre_runtime_resume(sdev->request_queue); + if (pm && pm->runtime_resume) + err = pm->runtime_resume(dev); +- blk_post_runtime_resume(sdev->request_queue, err); ++ blk_post_runtime_resume(sdev->request_queue); + + return err; + } +diff --git a/include/linux/blk-pm.h b/include/linux/blk-pm.h +index b80c65aba249..2580e05a8ab6 100644 +--- a/include/linux/blk-pm.h ++++ b/include/linux/blk-pm.h +@@ -14,7 +14,7 @@ extern void blk_pm_runtime_init(struct request_queue *q, struct device *dev); + extern int blk_pre_runtime_suspend(struct request_queue *q); + extern void blk_post_runtime_suspend(struct request_queue *q, int err); + extern void blk_pre_runtime_resume(struct request_queue *q); +-extern void blk_post_runtime_resume(struct request_queue *q, int err); ++extern void blk_post_runtime_resume(struct request_queue *q); + extern void blk_set_runtime_active(struct request_queue *q); + #else + static inline void blk_pm_runtime_init(struct request_queue *q, +-- +2.27.0 + diff --git a/patches/0554-block-don-t-lose-track-of-REQ_INTEGRITY-flag.patch b/patches/0554-block-don-t-lose-track-of-REQ_INTEGRITY-flag.patch new file mode 100644 index 00000000..8fc1113a --- /dev/null +++ b/patches/0554-block-don-t-lose-track-of-REQ_INTEGRITY-flag.patch @@ -0,0 +1,53 @@ +From 940cc74337b8f5525fe9b5cc6659ec1b5372c29a Mon Sep 17 00:00:00 2001 +From: Ming Lei +Date: Wed, 16 Jan 2019 19:08:15 +0800 +Subject: [PATCH 236/256] block: don't lose track of REQ_INTEGRITY flag + +mainline inclusion +from mainline-v5.0-rc3 +commit 7809167da5c86fd6bf309b33dee7a797e263342f +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7809167da5c86fd6bf309b33dee7a797e263342f + +---------------------------------------------------------------------- + +We need to pass bio->bi_opf after bio intergrity preparing, otherwise +the flag of REQ_INTEGRITY may not be set on the allocated request, then +breaks block integrity. + +Fixes: f9afca4d367b ("blk-mq: pass in request/bio flags to queue mapping") +Cc: Hannes Reinecke +Cc: Keith Busch +Signed-off-by: Ming Lei +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang +--- + block/blk-mq.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/block/blk-mq.c b/block/blk-mq.c +index bec2190a64dd..2f65e1625a8d 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -1979,7 +1979,7 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio) + { + const int is_sync = op_is_sync(bio->bi_opf); + const int is_flush_fua = op_is_flush(bio->bi_opf); +- struct blk_mq_alloc_data data = { .flags = 0, .cmd_flags = bio->bi_opf }; ++ struct blk_mq_alloc_data data = { .flags = 0}; + struct request *rq; + unsigned int request_count = 0; + struct blk_plug *plug; +@@ -2007,6 +2007,7 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio) + + rq_qos_throttle(q, bio, NULL); + ++ data.cmd_flags = bio->bi_opf; + rq = blk_mq_get_request(q, bio, &data); + if (unlikely(!rq)) { + rq_qos_cleanup(q, bio); +-- +2.27.0 + diff --git a/patches/0555-block-Fix-blk_mq_-_map_queues-kernel-doc-headers.patch b/patches/0555-block-Fix-blk_mq_-_map_queues-kernel-doc-headers.patch new file mode 100644 index 00000000..72130f30 --- /dev/null +++ b/patches/0555-block-Fix-blk_mq_-_map_queues-kernel-doc-headers.patch @@ -0,0 +1,81 @@ +From 3331cbab9720ca36413a5e6a501ae78b8a043abc Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Thu, 30 May 2019 17:00:49 -0700 +Subject: [PATCH 237/256] block: Fix blk_mq_*_map_queues() kernel-doc headers + +mainline inclusion +from mainline-v5.2-rc3 +commit 0542cd57d266074114d70791ab245e18f750cd32 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0542cd57d266074114d70791ab245e18f750cd32 + +---------------------------------------------------------------------- + +This patch avoids that the kernel-doc script complains about these +function headers when building with W=1. + +Cc: Hannes Reinecke +Cc: Keith Busch +Fixes: ed76e329d74a ("blk-mq: abstract out queue map") # v5.0. +Fixes: e42b3867de4b ("blk-mq-rdma: pass in queue map to blk_mq_rdma_map_queues") # v5.0. +Reviewed-by: Chaitanya Kulkarni +Signed-off-by: Bart Van Assche +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang + + Conflicts: + block/blk-mq-pci.c +--- + block/blk-mq-pci.c | 2 +- + block/blk-mq-rdma.c | 4 ++-- + block/blk-mq-virtio.c | 4 ++-- + 3 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/block/blk-mq-pci.c b/block/blk-mq-pci.c +index 04b5f6a1fa20..e92b584de006 100644 +--- a/block/blk-mq-pci.c ++++ b/block/blk-mq-pci.c +@@ -47,7 +47,7 @@ EXPORT_SYMBOL_GPL(blk_mq_pci_map_queues_by_qmap); + + /** + * blk_mq_pci_map_queues - provide a default queue mapping for PCI device +- * @set: tagset to provide the mapping for ++ * @qmap: CPU to hardware queue map. + * @pdev: PCI device associated with @set. + * @offset: Offset to use for the pci irq vector + * +diff --git a/block/blk-mq-rdma.c b/block/blk-mq-rdma.c +index 7a7690023484..5f6623f2b2c0 100644 +--- a/block/blk-mq-rdma.c ++++ b/block/blk-mq-rdma.c +@@ -16,8 +16,8 @@ + + /** + * blk_mq_rdma_map_queues - provide a default queue mapping for rdma device +- * @set: tagset to provide the mapping for +- * @dev: rdma device associated with @set. ++ * @map: CPU to hardware queue map. ++ * @dev: rdma device to provide a mapping for. + * @first_vec: first interrupt vectors to use for queues (usually 0) + * + * This function assumes the rdma device @dev has at least as many available +diff --git a/block/blk-mq-virtio.c b/block/blk-mq-virtio.c +index b67d52e4cddf..79c44d687ff3 100644 +--- a/block/blk-mq-virtio.c ++++ b/block/blk-mq-virtio.c +@@ -19,8 +19,8 @@ + + /** + * blk_mq_virtio_map_queues - provide a default queue mapping for virtio device +- * @set: tagset to provide the mapping for +- * @vdev: virtio device associated with @set. ++ * @qmap: CPU to hardware queue map. ++ * @vdev: virtio device to provide a mapping for. + * @first_vec: first interrupt vectors to use for queues (usually 0) + * + * This function assumes the virtio device @vdev has at least as many available +-- +2.27.0 + diff --git a/patches/0556-blk-mq-Keep-set-nr_hw_queues-and-set-map-.nr_queues-.patch b/patches/0556-blk-mq-Keep-set-nr_hw_queues-and-set-map-.nr_queues-.patch new file mode 100644 index 00000000..c4ddc61c --- /dev/null +++ b/patches/0556-blk-mq-Keep-set-nr_hw_queues-and-set-map-.nr_queues-.patch @@ -0,0 +1,67 @@ +From 08c9808b21f2264c5c90dc493ddc4855bf9bd126 Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Mon, 9 Mar 2020 21:26:17 -0700 +Subject: [PATCH 238/256] blk-mq: Keep set->nr_hw_queues and + set->map[].nr_queues in sync + +mainline inclusion +from mainline-v5.7-rc1 +commit 6e66b49392419f3fe134e1be583323ef75da1e4b +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6e66b49392419f3fe134e1be583323ef75da1e4b + +---------------------------------------------------------------------- + +blk_mq_map_queues() and multiple .map_queues() implementations expect that +set->map[HCTX_TYPE_DEFAULT].nr_queues is set to the number of hardware +queues. Hence set .nr_queues before calling these functions. This patch +fixes the following kernel warning: + +WARNING: CPU: 0 PID: 2501 at include/linux/cpumask.h:137 +Call Trace: + blk_mq_run_hw_queue+0x19d/0x350 block/blk-mq.c:1508 + blk_mq_run_hw_queues+0x112/0x1a0 block/blk-mq.c:1525 + blk_mq_requeue_work+0x502/0x780 block/blk-mq.c:775 + process_one_work+0x9af/0x1740 kernel/workqueue.c:2269 + worker_thread+0x98/0xe40 kernel/workqueue.c:2415 + kthread+0x361/0x430 kernel/kthread.c:255 + +Fixes: ed76e329d74a ("blk-mq: abstract out queue map") # v5.0 +Reported-by: syzbot+d44e1b26ce5c3e77458d@syzkaller.appspotmail.com +Signed-off-by: Bart Van Assche +Reviewed-by: Ming Lei +Reviewed-by: Chaitanya Kulkarni +Cc: Johannes Thumshirn +Cc: Hannes Reinecke +Cc: Ming Lei +Cc: Christoph Hellwig +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang +--- + block/blk-mq.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/block/blk-mq.c b/block/blk-mq.c +index 2f65e1625a8d..a0a72f1591c8 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -3079,6 +3079,14 @@ static int blk_mq_alloc_rq_maps(struct blk_mq_tag_set *set) + + static int blk_mq_update_queue_map(struct blk_mq_tag_set *set) + { ++ /* ++ * blk_mq_map_queues() and multiple .map_queues() implementations ++ * expect that set->map[HCTX_TYPE_DEFAULT].nr_queues is set to the ++ * number of hardware queues. ++ */ ++ if (set->nr_maps == 1) ++ set->map[HCTX_TYPE_DEFAULT].nr_queues = set->nr_hw_queues; ++ + if (set->ops->map_queues && !is_kdump_kernel()) { + int i; + +-- +2.27.0 + diff --git a/patches/0557-blk-mq-docs-add-kernel-doc-description-for-a-new-str.patch b/patches/0557-blk-mq-docs-add-kernel-doc-description-for-a-new-str.patch new file mode 100644 index 00000000..86ccceb5 --- /dev/null +++ b/patches/0557-blk-mq-docs-add-kernel-doc-description-for-a-new-str.patch @@ -0,0 +1,52 @@ +From dcb01e1c10fc79865c1ed8e4403f1547b302691c Mon Sep 17 00:00:00 2001 +From: Mauro Carvalho Chehab +Date: Tue, 27 Oct 2020 10:51:13 +0100 +Subject: [PATCH 239/256] blk-mq: docs: add kernel-doc description for a new + struct member + +mainline inclusion +from mainline-v5.10-rc3 +commit 6a6223ec7779dfdabb9c2567bb42079bc300cf27 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6a6223ec7779dfdabb9c2567bb42079bc300cf27 + +---------------------------------------------------------------------- + +As reported by kernel-doc: + ./include/linux/blk-mq.h:267: warning: Function parameter or member 'active_queues_shared_sbitmap' not described in 'blk_mq_tag_set' + +There is now a new member for struct blk_mq_tag_set. Add a +description for it, based on the commit that introduced it. + +Fixes: f1b49fdc1c64 ("blk-mq: Record active_queues_shared_sbitmap per tag_set for when using shared sbitmap") +Signed-off-by: Mauro Carvalho Chehab +Reviewed-by: Jens Axboe +Reviewed-by: John Garry +Link: https://lore.kernel.org/r/8e513153b83eefc05e358f51f2632b592c3f6772.1603791716.git.mchehab+huawei@kernel.org +Signed-off-by: Jonathan Corbet +Signed-off-by: YunYi Yang + + Conflicts: + include/linux/blk-mq.h +--- + include/linux/blk-mq.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h +index e5b1debe272b..648dc5563805 100644 +--- a/include/linux/blk-mq.h ++++ b/include/linux/blk-mq.h +@@ -108,6 +108,8 @@ enum hctx_type { + + /** + * struct blk_mq_tag_set - tag set that can be shared between request queues ++ * @active_queues_shared_sbitmap: ++ * number of active request queues per tag set. + * @__bitmap_tags: A shared tags sbitmap, used over all hctx's + * @__breserved_tags: + * A shared reserved tags sbitmap, used over all hctx's +-- +2.27.0 + diff --git a/patches/0558-blk-mq-debugfs-Add-decode-for-BLK_MQ_F_TAG_HCTX_SHAR.patch b/patches/0558-blk-mq-debugfs-Add-decode-for-BLK_MQ_F_TAG_HCTX_SHAR.patch new file mode 100644 index 00000000..6060862a --- /dev/null +++ b/patches/0558-blk-mq-debugfs-Add-decode-for-BLK_MQ_F_TAG_HCTX_SHAR.patch @@ -0,0 +1,50 @@ +From ee03df3b38d35a47440b31e810da5a23bcac005d Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Fri, 8 Jan 2021 16:55:37 +0800 +Subject: [PATCH 240/256] blk-mq-debugfs: Add decode for + BLK_MQ_F_TAG_HCTX_SHARED + +mainline inclusion +from mainline-v5.11-rc3 +commit 02f938e9fed1681791605ca8b96c2d9da9355f6a +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=02f938e9fed1681791605ca8b96c2d9da9355f6a + +---------------------------------------------------------------------- + +Showing the hctx flags for when BLK_MQ_F_TAG_HCTX_SHARED is set gives +something like: + +root@debian:/home/john# more /sys/kernel/debug/block/sda/hctx0/flags +alloc_policy=FIFO SHOULD_MERGE|TAG_QUEUE_SHARED|3 + +Add the decoding for that flag. + +Fixes: 32bc15afed04b ("blk-mq: Facilitate a shared sbitmap per tagset") +Signed-off-by: John Garry +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang + + Conflicts: + block/blk-mq-debugfs.c +--- + block/blk-mq-debugfs.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c +index 8fb54b625e41..e9cdcc266938 100644 +--- a/block/blk-mq-debugfs.c ++++ b/block/blk-mq-debugfs.c +@@ -255,6 +255,7 @@ static const char *const hctx_flag_name[] = { + HCTX_FLAG_NAME(SG_MERGE), + HCTX_FLAG_NAME(BLOCKING), + HCTX_FLAG_NAME(NO_SCHED), ++ HCTX_FLAG_NAME(TAG_HCTX_SHARED), + }; + #undef HCTX_FLAG_NAME + +-- +2.27.0 + diff --git a/patches/0559-blk-mq-plug-request-for-shared-sbitmap.patch b/patches/0559-blk-mq-plug-request-for-shared-sbitmap.patch new file mode 100644 index 00000000..740f7170 --- /dev/null +++ b/patches/0559-blk-mq-plug-request-for-shared-sbitmap.patch @@ -0,0 +1,60 @@ +From 208df0f9f8d5b9eb62351b838683cd1a27168e3b Mon Sep 17 00:00:00 2001 +From: Ming Lei +Date: Fri, 14 May 2021 10:20:52 +0800 +Subject: [PATCH 241/256] blk-mq: plug request for shared sbitmap + +mainline inclusion +from mainline-v5.13-rc2 +commit 03f26d8f11403295de445b6e4e0e57ac57755791 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=03f26d8f11403295de445b6e4e0e57ac57755791 + +---------------------------------------------------------------------- + +In case of shared sbitmap, request won't be held in plug list any more +sine commit 32bc15afed04 ("blk-mq: Facilitate a shared sbitmap per +tagset"), this way makes request merge from flush plug list & batching +submission not possible, so cause performance regression. + +Yanhui reports performance regression when running sequential IO +test(libaio, 16 jobs, 8 depth for each job) in VM, and the VM disk +is emulated with image stored on xfs/megaraid_sas. + +Fix the issue by recovering original behavior to allow to hold request +in plug list. + +Cc: Yanhui Ma +Cc: John Garry +Cc: Bart Van Assche +Cc: kashyap.desai@broadcom.com +Fixes: 32bc15afed04 ("blk-mq: Facilitate a shared sbitmap per tagset") +Signed-off-by: Ming Lei +Link: https://lore.kernel.org/r/20210514022052.1047665-1-ming.lei@redhat.com +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang + + Conflicts: + block/blk-mq.c +--- + block/blk-mq.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/block/blk-mq.c b/block/blk-mq.c +index a0a72f1591c8..8f4d7ae81e25 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -2030,7 +2030,8 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio) + /* bypass scheduler for flush rq */ + blk_insert_flush(rq); + blk_mq_run_hw_queue(data.hctx, true); +- } else if (plug && q->nr_hw_queues == 1) { ++ } else if (plug && (q->nr_hw_queues == 1 || ++ blk_mq_is_sbitmap_shared(rq->mq_hctx->flags))) { + struct request *last = NULL; + + blk_mq_put_ctx(data.ctx); +-- +2.27.0 + diff --git a/patches/0560-blk-mq-debugfs-Show-active-requests-per-queue-for-sh.patch b/patches/0560-blk-mq-debugfs-Show-active-requests-per-queue-for-sh.patch new file mode 100644 index 00000000..c4d91e4d --- /dev/null +++ b/patches/0560-blk-mq-debugfs-Show-active-requests-per-queue-for-sh.patch @@ -0,0 +1,50 @@ +From 01675e611d3d9b613e57c545794343be3f7067a1 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Fri, 29 Oct 2021 16:40:23 +0800 +Subject: [PATCH 242/256] blk-mq-debugfs: Show active requests per queue for + shared tags + +mainline inclusion +from mainline-v5.16-rc1 +commit 9b84c629c90374498ab5825dede74a06ea1c775b +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9b84c629c90374498ab5825dede74a06ea1c775b + +---------------------------------------------------------------------- + +Currently we show the hctx.active value for the per-hctx "active" file. + +However this is not maintained for shared tags, and we instead keep a +record of the number active requests per request queue - see commit +f1b49fdc1c64 ("blk-mq: Record active_queues_shared_sbitmap per tag_set for +when using shared sbitmap). + +Change for the case of shared tags to show the active requests per request +queue by using __blk_mq_active_requests() helper. + +Signed-off-by: John Garry +Link: https://lore.kernel.org/r/1635496823-33515-1-git-send-email-john.garry@huawei.com +Signed-off-by: Jens Axboe +Signed-off-by: YunYi Yang +--- + block/blk-mq-debugfs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c +index e9cdcc266938..8ab6b3ace432 100644 +--- a/block/blk-mq-debugfs.c ++++ b/block/blk-mq-debugfs.c +@@ -627,7 +627,7 @@ static int hctx_active_show(void *data, struct seq_file *m) + { + struct blk_mq_hw_ctx *hctx = data; + +- seq_printf(m, "%d\n", atomic_read(&hctx->nr_active)); ++ seq_printf(m, "%d\n", __blk_mq_active_requests(hctx)); + return 0; + } + +-- +2.27.0 + diff --git a/patches/0561-scsi-block-Fix-a-race-in-the-runtime-power-managemen.patch b/patches/0561-scsi-block-Fix-a-race-in-the-runtime-power-managemen.patch new file mode 100644 index 00000000..f3fcf801 --- /dev/null +++ b/patches/0561-scsi-block-Fix-a-race-in-the-runtime-power-managemen.patch @@ -0,0 +1,94 @@ +From 0f3e56133f5782862ed4e69f0cbb4df2d94efdbf Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Tue, 8 Dec 2020 21:29:44 -0800 +Subject: [PATCH 243/256] scsi: block: Fix a race in the runtime power + management code + +mainline inclusion +from mainline-v5.11-rc2 +commit fa4d0f1992a96f6d7c988ef423e3127e613f6ac9 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fa4d0f1992a96f6d7c988ef423e3127e613f6ac9 + +---------------------------------------------------------------------- + +With the current implementation the following race can happen: + + * blk_pre_runtime_suspend() calls blk_freeze_queue_start() and + blk_mq_unfreeze_queue(). + + * blk_queue_enter() calls blk_queue_pm_only() and that function returns + true. + + * blk_queue_enter() calls blk_pm_request_resume() and that function does + not call pm_request_resume() because the queue runtime status is + RPM_ACTIVE. + + * blk_pre_runtime_suspend() changes the queue status into RPM_SUSPENDING. + +Fix this race by changing the queue runtime status into RPM_SUSPENDING +before switching q_usage_counter to atomic mode. + +Link: https://lore.kernel.org/r/20201209052951.16136-2-bvanassche@acm.org +Fixes: 986d413b7c15 ("blk-mq: Enable support for runtime power management") +Cc: Ming Lei +Cc: Rafael J. Wysocki +Cc: stable +Reviewed-by: Christoph Hellwig +Reviewed-by: Hannes Reinecke +Reviewed-by: Jens Axboe +Acked-by: Alan Stern +Acked-by: Stanley Chu +Co-developed-by: Can Guo +Signed-off-by: Can Guo +Signed-off-by: Bart Van Assche +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang + + Conflicts: + block/blk-pm.c +--- + block/blk-pm.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/block/blk-pm.c b/block/blk-pm.c +index d8c1eeba96b1..9adfc26bc114 100644 +--- a/block/blk-pm.c ++++ b/block/blk-pm.c +@@ -67,6 +67,10 @@ int blk_pre_runtime_suspend(struct request_queue *q) + + WARN_ON_ONCE(q->rpm_status != RPM_ACTIVE); + ++ spin_lock_irq(q->queue_lock); ++ q->rpm_status = RPM_SUSPENDING; ++ spin_unlock_irq(q->queue_lock); ++ + /* + * Increase the pm_only counter before checking whether any + * non-PM blk_queue_enter() calls are in progress to avoid that any +@@ -89,15 +93,14 @@ int blk_pre_runtime_suspend(struct request_queue *q) + /* Switch q_usage_counter back to per-cpu mode. */ + blk_mq_unfreeze_queue(q); + +- spin_lock_irq(q->queue_lock); +- if (ret < 0) ++ if (ret < 0) { ++ spin_lock_irq(q->queue_lock); ++ q->rpm_status = RPM_ACTIVE; + pm_runtime_mark_last_busy(q->dev); +- else +- q->rpm_status = RPM_SUSPENDING; +- spin_unlock_irq(q->queue_lock); ++ spin_unlock_irq(q->queue_lock); + +- if (ret) + blk_clear_pm_only(q); ++ } + + return ret; + } +-- +2.27.0 + diff --git a/patches/0562-scsi-megaraid_sas-Enable-msix_load_balance-for-Invad.patch b/patches/0562-scsi-megaraid_sas-Enable-msix_load_balance-for-Invad.patch new file mode 100644 index 00000000..95de4b0b --- /dev/null +++ b/patches/0562-scsi-megaraid_sas-Enable-msix_load_balance-for-Invad.patch @@ -0,0 +1,46 @@ +From d8a541fb129863d1720c26a9e79450adaf720601 Mon Sep 17 00:00:00 2001 +From: Shivasharan S +Date: Fri, 28 Jun 2019 02:50:39 -0700 +Subject: [PATCH 244/256] scsi: megaraid_sas: Enable msix_load_balance for + Invader and later controllers + +mainline inclusion +from mainline-v5.3-rc1 +commit 1175b88452cad208894412b955ee698934968aed +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1175b88452cad208894412b955ee698934968aed + +---------------------------------------------------------------------- + +Load balancing IO completions across all available MSI-X vectors should be +enabled for Invader and later generation controllers only. This needs to +be disabled for older controllers. Add an adapter type check before +setting msix_load_balance flag. + +Fixes: 1d15d9098ad1 ("scsi: megaraid_sas: Load balance completions across all MSI-X") +Signed-off-by: Shivasharan S +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/megaraid/megaraid_sas_base.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c +index daf5b08ab066..c65edb5cd132 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_base.c ++++ b/drivers/scsi/megaraid/megaraid_sas_base.c +@@ -5481,7 +5481,8 @@ static int megasas_init_fw(struct megasas_instance *instance) + (scratch_pad_1 & MR_RDPQ_MODE_OFFSET) ? + 1 : 0; + +- if (!instance->msix_combined) { ++ if (instance->adapter_type >= INVADER_SERIES && ++ !instance->msix_combined) { + instance->msix_load_balance = true; + instance->smp_affinity_enable = false; + } +-- +2.27.0 + diff --git a/patches/0563-scsi-pm80xx-Replace-open-coded-check-with-dev_is_exp.patch b/patches/0563-scsi-pm80xx-Replace-open-coded-check-with-dev_is_exp.patch new file mode 100644 index 00000000..d0e77ac2 --- /dev/null +++ b/patches/0563-scsi-pm80xx-Replace-open-coded-check-with-dev_is_exp.patch @@ -0,0 +1,61 @@ +From ef57e0e70ecbac07dca1df0e8b5bc61cc10dad63 Mon Sep 17 00:00:00 2001 +From: Igor Pylypiv +Date: Tue, 28 Sep 2021 19:58:07 -0700 +Subject: [PATCH 245/256] scsi: pm80xx: Replace open coded check with + dev_is_expander() + +mainline inclusion +from mainline-v5.16-rc1 +commit 4f632918e7a87d0da7c0bcb3f8242f62725dad44 +category: feature +bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4f632918e7a87d0da7c0bcb3f8242f62725dad44 + +---------------------------------------------------------------------- + +This is a follow up cleanup to the commit 924a3541eab0 ("scsi: libsas: +aic94xx: hisi_sas: mvsas: pm8001: Use dev_is_expander()") + +Link: https://lore.kernel.org/r/20210929025807.646589-1-ipylypiv@google.com +Reviewed-by: Vishakha Channapattan +Acked-by: Jack Wang +Signed-off-by: Igor Pylypiv +Signed-off-by: Martin K. Petersen +Signed-off-by: YunYi Yang +--- + drivers/scsi/pm8001/pm8001_hwi.c | 3 +-- + drivers/scsi/pm8001/pm80xx_hwi.c | 3 +-- + 2 files changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c +index 2c1e2ded06b1..de8359bbf2a5 100644 +--- a/drivers/scsi/pm8001/pm8001_hwi.c ++++ b/drivers/scsi/pm8001/pm8001_hwi.c +@@ -4570,8 +4570,7 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha, + if (pm8001_dev->dev_type == SAS_SATA_DEV) + stp_sspsmp_sata = 0x00; /* stp*/ + else if (pm8001_dev->dev_type == SAS_END_DEVICE || +- pm8001_dev->dev_type == SAS_EDGE_EXPANDER_DEVICE || +- pm8001_dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE) ++ dev_is_expander(pm8001_dev->dev_type)) + stp_sspsmp_sata = 0x01; /*ssp or smp*/ + } + if (parent_dev && dev_is_expander(parent_dev->dev_type)) +diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c +index f3ec2e08411e..85ed6946747f 100644 +--- a/drivers/scsi/pm8001/pm80xx_hwi.c ++++ b/drivers/scsi/pm8001/pm80xx_hwi.c +@@ -4563,8 +4563,7 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha, + if (pm8001_dev->dev_type == SAS_SATA_DEV) + stp_sspsmp_sata = 0x00; /* stp*/ + else if (pm8001_dev->dev_type == SAS_END_DEVICE || +- pm8001_dev->dev_type == SAS_EDGE_EXPANDER_DEVICE || +- pm8001_dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE) ++ dev_is_expander(pm8001_dev->dev_type)) + stp_sspsmp_sata = 0x01; /*ssp or smp*/ + } + if (parent_dev && dev_is_expander(parent_dev->dev_type)) +-- +2.27.0 + diff --git a/patches/0564-x86-vector-Remove-warning-on-managed-interrupt-migra.patch b/patches/0564-x86-vector-Remove-warning-on-managed-interrupt-migra.patch new file mode 100644 index 00000000..5552df29 --- /dev/null +++ b/patches/0564-x86-vector-Remove-warning-on-managed-interrupt-migra.patch @@ -0,0 +1,102 @@ +From e1be0fb270fa33c58bb0b760f6daeb0cdfbb7a41 Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Thu, 12 Mar 2020 16:58:30 -0400 +Subject: [PATCH 246/256] x86/vector: Remove warning on managed interrupt + migration + +mainline inclusion +from mainline-v5.6-rc6 +commit 469ff207b4c4033540b50bc59587dc915faa1367 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=469ff207b4c4033540b50bc59587dc915faa1367 + +---------------------------------------------------------------------- + +The vector management code assumes that managed interrupts cannot be +migrated away from an online CPU. free_moved_vector() has a WARN_ON_ONCE() +which triggers when a managed interrupt vector association on a online CPU +is cleared. The CPU offline code uses a different mechanism which cannot +trigger this. + +This assumption is not longer correct because the new CPU isolation feature +which affects the placement of managed interrupts must be able to move a +managed interrupt away from an online CPU. + +There are two reasons why this can happen: + + 1) When the interrupt is activated the affinity mask which was + established in irq_create_affinity_masks() is handed in to + the vector allocation code. This mask contains all CPUs to which + the interrupt can be made affine to, but this does not take the + CPU isolation 'managed_irq' mask into account. + + When the interrupt is finally requested by the device driver then the + affinity is checked again and the CPU isolation 'managed_irq' mask is + taken into account, which moves the interrupt to a non-isolated CPU if + possible. + + 2) The interrupt can be affine to an isolated CPU because the + non-isolated CPUs in the calculated affinity mask are not online. + + Once a non-isolated CPU which is in the mask comes online the + interrupt is migrated to this non-isolated CPU + +In both cases the regular online migration mechanism is used which triggers +the WARN_ON_ONCE() in free_moved_vector(). + +Case #1 could have been addressed by taking the isolation mask into +account, but that would require a massive code change in the activation +logic and the eventual migration event was accepted as a reasonable +tradeoff when the isolation feature was developed. But even if #1 would be +addressed, #2 would still trigger it. + +Of course the warning in free_moved_vector() was overlooked at that time +and the above two cases which have been discussed during patch review have +obviously never been tested before the final submission. + +So keep it simple and remove the warning. + +[ tglx: Rewrote changelog and added a comment to free_moved_vector() ] + +Fixes: 11ea68f553e2 ("genirq, sched/isolation: Isolate from handling managed interrupts") +Signed-off-by: Peter Xu +Signed-off-by: Thomas Gleixner +Reviewed-by: Ming Lei +Link: https://lkml.kernel.org/r/20200312205830.81796-1-peterx@redhat.com + +Signed-off-by: YunYi Yang +--- + arch/x86/kernel/apic/vector.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c +index e6988481437c..8ddcd266a7c7 100644 +--- a/arch/x86/kernel/apic/vector.c ++++ b/arch/x86/kernel/apic/vector.c +@@ -862,13 +862,15 @@ static void free_moved_vector(struct apic_chip_data *apicd) + bool managed = apicd->is_managed; + + /* +- * This should never happen. Managed interrupts are not +- * migrated except on CPU down, which does not involve the +- * cleanup vector. But try to keep the accounting correct +- * nevertheless. ++ * Managed interrupts are usually not migrated away ++ * from an online CPU, but CPU isolation 'managed_irq' ++ * can make that happen. ++ * 1) Activation does not take the isolation into account ++ * to keep the code simple ++ * 2) Migration away from an isolated CPU can happen when ++ * a non-isolated CPU which is in the calculated ++ * affinity mask comes online. + */ +- WARN_ON_ONCE(managed); +- + trace_vector_free_moved(apicd->irq, cpu, vector, managed); + irq_matrix_free(vector_matrix, cpu, vector, managed); + per_cpu(vector_irq, cpu)[vector] = VECTOR_UNUSED; +-- +2.27.0 + diff --git a/patches/0565-genirq-Fix-the-kerneldoc-comment-for-struct-irq_affi.patch b/patches/0565-genirq-Fix-the-kerneldoc-comment-for-struct-irq_affi.patch new file mode 100644 index 00000000..d8e2620e --- /dev/null +++ b/patches/0565-genirq-Fix-the-kerneldoc-comment-for-struct-irq_affi.patch @@ -0,0 +1,48 @@ +From 3cbd5e788d12c824fd685369ad8b0c70dcd80c26 Mon Sep 17 00:00:00 2001 +From: Jonathan Corbet +Date: Tue, 8 Jan 2019 17:04:32 -0700 +Subject: [PATCH 247/256] genirq: Fix the kerneldoc comment for struct + irq_affinity_desc + +mainline inclusion +from mainline-v5.0-rc4 +commit 70921ae25f944423f0abf096f73455c586da0652 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=70921ae25f944423f0abf096f73455c586da0652 + +---------------------------------------------------------------------- + +A recent commit added a new field but did not update the kerneldoc comment, +leading to this build warning: + + ./include/linux/interrupt.h:268: warning: Function parameter or member 'is_managed' not described in 'irq_affinity_desc' + +Add the missing information, making the docs build 0.001% quieter. + +Fixes: c410abbbacb9 ("genirq/affinity: Add is_managed to struct irq_affinity_desc") +Signed-off-by: Jonathan Corbet +Signed-off-by: Thomas Gleixner +Cc: Dou Liyang +Link: https://lkml.kernel.org/r/20190108170432.59bae8a6@lwn.net +Signed-off-by: YunYi Yang +--- + include/linux/interrupt.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h +index 862b5f158d36..ed66e130d574 100644 +--- a/include/linux/interrupt.h ++++ b/include/linux/interrupt.h +@@ -276,6 +276,7 @@ struct irq_affinity { + /** + * struct irq_affinity_desc - Interrupt affinity descriptor + * @mask: cpumask to hold the affinity assignment ++ * @is_managed: 1 if the interrupt is managed internally + */ + struct irq_affinity_desc { + struct cpumask mask; +-- +2.27.0 + diff --git a/patches/0566-genirq-irqdesc-Fix-double-increment-in-alloc_descs.patch b/patches/0566-genirq-irqdesc-Fix-double-increment-in-alloc_descs.patch new file mode 100644 index 00000000..c5d076cd --- /dev/null +++ b/patches/0566-genirq-irqdesc-Fix-double-increment-in-alloc_descs.patch @@ -0,0 +1,53 @@ +From 9a2bfd220ce393da5bd2d786ecfd6c05a80837fa Mon Sep 17 00:00:00 2001 +From: Huacai Chen +Date: Thu, 17 Jan 2019 11:00:09 +0800 +Subject: [PATCH 248/256] genirq/irqdesc: Fix double increment in alloc_descs() + +mainline inclusion +from mainline-v5.0-rc4 +commit 12fee4cd5be2c4a73cc13d7ad76eb2d2feda8a71 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=12fee4cd5be2c4a73cc13d7ad76eb2d2feda8a71 + +---------------------------------------------------------------------- + +The recent rework of alloc_descs() introduced a double increment of the +loop counter. As a consequence only every second affinity mask is +validated. + +Remove it. + +[ tglx: Massaged changelog ] + +Fixes: c410abbbacb9 ("genirq/affinity: Add is_managed to struct irq_affinity_desc") +Signed-off-by: Huacai Chen +Signed-off-by: Thomas Gleixner +Cc: Fuxin Zhang +Cc: Zhangjin Wu +Cc: Huacai Chen +Cc: Dou Liyang +Link: https://lkml.kernel.org/r/1547694009-16261-1-git-send-email-chenhc@lemote.com + +Signed-off-by: YunYi Yang +--- + kernel/irq/irqdesc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c +index 1591040b52ea..d1f58ec5acde 100644 +--- a/kernel/irq/irqdesc.c ++++ b/kernel/irq/irqdesc.c +@@ -472,7 +472,7 @@ static int alloc_descs(unsigned int start, unsigned int cnt, int node, + + /* Validate affinity mask(s) */ + if (affinity) { +- for (i = 0; i < cnt; i++, i++) { ++ for (i = 0; i < cnt; i++) { + if (cpumask_empty(&affinity[i].mask)) + return -EINVAL; + } +-- +2.27.0 + diff --git a/patches/0567-genirq-Take-the-proposed-affinity-at-face-value-if-f.patch b/patches/0567-genirq-Take-the-proposed-affinity-at-face-value-if-f.patch new file mode 100644 index 00000000..1468179f --- /dev/null +++ b/patches/0567-genirq-Take-the-proposed-affinity-at-face-value-if-f.patch @@ -0,0 +1,67 @@ +From dfb00f290f2b68c2cf784ef46646fb6fb680d7bb Mon Sep 17 00:00:00 2001 +From: Marc Zyngier +Date: Thu, 14 Apr 2022 15:00:11 +0100 +Subject: [PATCH 249/256] genirq: Take the proposed affinity at face value if + force==true + +mainline inclusion +from mainline-v5.19-rc1 +commit c48c8b829d2b966a6649827426bcdba082ccf922 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8EKNE + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c48c8b829d2b966a6649827426bcdba082ccf922 + +---------------------------------------------------------------------- + +Although setting the affinity of an interrupt to a set of CPUs that doesn't +have any online CPU is generally frowned apon, there are a few limited +cases where such affinity is set from a CPUHP notifier, setting the +affinity to a CPU that isn't online yet. + +The saving grace is that this is always done using the 'force' attribute, +which gives a hint that the affinity setting can be outside of the online +CPU mask and the callsite set this flag with the knowledge that the +underlying interrupt controller knows to handle it. + +This restores the expected behaviour on Marek's system. + +Fixes: 33de0aa4bae9 ("genirq: Always limit the affinity to online CPUs") +Reported-by: Marek Szyprowski +Signed-off-by: Marc Zyngier +Signed-off-by: Thomas Gleixner +Tested-by: Marek Szyprowski +Link: https://lore.kernel.org/r/4b7fc13c-887b-a664-26e8-45aed13f048a@samsung.com +Link: https://lore.kernel.org/r/20220414140011.541725-1-maz@kernel.org + +Signed-off-by: YunYi Yang +--- + kernel/irq/manage.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c +index 3cc91a3587a4..22021a455e92 100644 +--- a/kernel/irq/manage.c ++++ b/kernel/irq/manage.c +@@ -267,10 +267,16 @@ int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask, + prog_mask = mask; + } + +- /* Make sure we only provide online CPUs to the irqchip */ ++ /* ++ * Make sure we only provide online CPUs to the irqchip, ++ * unless we are being asked to force the affinity (in which ++ * case we do as we are told). ++ */ + cpumask_and(&tmp_mask, prog_mask, cpu_online_mask); +- if (!cpumask_empty(&tmp_mask)) ++ if (!force && !cpumask_empty(&tmp_mask)) + ret = chip->irq_set_affinity(data, &tmp_mask, force); ++ else if (force) ++ ret = chip->irq_set_affinity(data, mask, force); + else + ret = -EINVAL; + +-- +2.27.0 + diff --git a/patches/0568-driver-core-Update-device-link-status-correctly-for-.patch b/patches/0568-driver-core-Update-device-link-status-correctly-for-.patch new file mode 100644 index 00000000..e95538ef --- /dev/null +++ b/patches/0568-driver-core-Update-device-link-status-correctly-for-.patch @@ -0,0 +1,126 @@ +From f7152ea72bc76560e3e0858797304baabf7f16fe Mon Sep 17 00:00:00 2001 +From: Saravana Kannan +Date: Tue, 26 May 2020 15:09:27 -0700 +Subject: [PATCH 250/256] driver core: Update device link status correctly for + SYNC_STATE_ONLY links + +mainline inclusion +from mainline-v5.8-rc1 +commit 8c3e315d4296421cd26b3300ee0ac117f0877f20 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8c3e315d4296421cd26b3300ee0ac117f0877f20 + +---------------------------------------------------------------------- + +When SYNC_STATE_ONLY support was added in commit 05ef983e0d65 ("driver +core: Add device link support for SYNC_STATE_ONLY flag"), +SYNC_STATE_ONLY links were treated similar to STATELESS links in terms +of not blocking consumer probe if the supplier hasn't probed yet. + +That caused a SYNC_STATE_ONLY device link's status to not get updated. +Since SYNC_STATE_ONLY device link is no longer useful once the +consumer probes, commit 21c27f06587d ("driver core: Fix +SYNC_STATE_ONLY device link implementation") addresses the status +update issue by deleting the SYNC_STATE_ONLY device link instead of +complicating the status update code. + +However, there are still some cases where we need to update the status +of a SYNC_STATE_ONLY device link. This is because a SYNC_STATE_ONLY +device link can later get converted into a normal MANAGED device link +when a normal MANAGED device link is created between a supplier and +consumer that already have a SYNC_STATE_ONLY device link between them. + +If a SYNC_STATE_ONLY device link's status isn't maintained correctly +till it's converted to a normal MANAGED device link, then the normal +MANAGED device link will end up with a wrong link status. This can cause +a warning stack trace[1] when the consumer device probes successfully. + +This commit fixes the SYNC_STATE_ONLY device link status update issue +where it wouldn't transition correctly from DL_STATE_DORMANT or +DL_STATE_AVAILABLE to DL_STATE_CONSUMER_PROBE. It also resets the status +back to DL_STATE_DORMANT or DL_STATE_AVAILABLE if the consumer probe +fails. + +[1] - https://lore.kernel.org/lkml/20200522204120.3b3c9ed6@apollo/ +Fixes: 05ef983e0d65 ("driver core: Add device link support for SYNC_STATE_ONLY flag") +Fixes: 21c27f06587d ("driver core: Fix SYNC_STATE_ONLY device link implementation") +Reported-by: Michael Walle +Tested-by: Michael Walle +Signed-off-by: Saravana Kannan +Reviewed-by: Rafael J. Wysocki +Link: https://lore.kernel.org/r/20200526220928.49939-1-saravanak@google.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: YunYi Yang +--- + drivers/base/core.c | 34 ++++++++++++++++++++++++++-------- + 1 file changed, 26 insertions(+), 8 deletions(-) + +diff --git a/drivers/base/core.c b/drivers/base/core.c +index 4e7c9df73e8e..c2a04f607904 100644 +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -783,9 +783,17 @@ static void device_links_missing_supplier(struct device *dev) + { + struct device_link *link; + +- list_for_each_entry(link, &dev->links.suppliers, c_node) +- if (link->status == DL_STATE_CONSUMER_PROBE) ++ list_for_each_entry(link, &dev->links.suppliers, c_node) { ++ if (link->status != DL_STATE_CONSUMER_PROBE) ++ continue; ++ ++ if (link->supplier->links.status == DL_DEV_DRIVER_BOUND) { + WRITE_ONCE(link->status, DL_STATE_AVAILABLE); ++ } else { ++ WARN_ON(!(link->flags & DL_FLAG_SYNC_STATE_ONLY)); ++ WRITE_ONCE(link->status, DL_STATE_DORMANT); ++ } ++ } + } + + /** +@@ -812,11 +820,11 @@ int device_links_check_suppliers(struct device *dev) + device_links_write_lock(); + + list_for_each_entry(link, &dev->links.suppliers, c_node) { +- if (!(link->flags & DL_FLAG_MANAGED) || +- link->flags & DL_FLAG_SYNC_STATE_ONLY) ++ if (!(link->flags & DL_FLAG_MANAGED)) + continue; + +- if (link->status != DL_STATE_AVAILABLE) { ++ if (link->status != DL_STATE_AVAILABLE && ++ !(link->flags & DL_FLAG_SYNC_STATE_ONLY)) { + device_links_missing_supplier(dev); + ret = -EPROBE_DEFER; + break; +@@ -907,11 +915,21 @@ static void __device_links_no_driver(struct device *dev) + if (!(link->flags & DL_FLAG_MANAGED)) + continue; + +- if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) ++ if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) { + device_link_drop_managed(link); +- else if (link->status == DL_STATE_CONSUMER_PROBE || +- link->status == DL_STATE_ACTIVE) ++ continue; ++ } ++ ++ if (link->status != DL_STATE_CONSUMER_PROBE && ++ link->status != DL_STATE_ACTIVE) ++ continue; ++ ++ if (link->supplier->links.status == DL_DEV_DRIVER_BOUND) { + WRITE_ONCE(link->status, DL_STATE_AVAILABLE); ++ } else { ++ WARN_ON(!(link->flags & DL_FLAG_SYNC_STATE_ONLY)); ++ WRITE_ONCE(link->status, DL_STATE_DORMANT); ++ } + } + + dev->links.status = DL_DEV_NO_DRIVER; +-- +2.27.0 + diff --git a/patches/0569-driver-core-Fix-device_pm_lock-locking-for-device-li.patch b/patches/0569-driver-core-Fix-device_pm_lock-locking-for-device-li.patch new file mode 100644 index 00000000..63f0d4ad --- /dev/null +++ b/patches/0569-driver-core-Fix-device_pm_lock-locking-for-device-li.patch @@ -0,0 +1,86 @@ +From d74457e6b1d9bf695d25e1c8d1cf7bad978af046 Mon Sep 17 00:00:00 2001 +From: Saravana Kannan +Date: Tue, 1 Sep 2020 11:44:44 -0700 +Subject: [PATCH 251/256] driver core: Fix device_pm_lock() locking for device + links + +mainline inclusion +from mainline-v5.9-rc5 +commit 6b57b15abe11aa334ebf726e02c0deaf123ba040 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6b57b15abe11aa334ebf726e02c0deaf123ba040 + +---------------------------------------------------------------------- + +This commit fixes two issues: + +1. The lockdep warning reported by Dong Aisheng [1]. + +It is a warning about a cycle (dpm_list_mtx --> kn->active#3 --> fw_lock) +that was introduced when device-link devices were added to expose device +link information in sysfs. + +The patch that "introduced" this cycle can't be reverted because it's fixes +a real SRCU issue and also ensures that the device-link device is deleted +as soon as the device-link is deleted. This is important to avoid sysfs +name collisions if the device-link is create again immediately (this can +happen a lot with deferred probing). + +2. Inconsistency in grabbing device_pm_lock() during device link deletion + +Some device link deletion code paths grab device_pm_lock(), while others +don't. The device_pm_lock() is grabbed during device_link_add() because it +checks if the supplier is in the dpm_list and also reorders the dpm_list. +However, when a device link is deleted, it does not do either of those and +therefore device_pm_lock() is not necessary. Dropping the device_pm_lock() +in all the device link deletion paths removes the inconsistency in locking. + +Thanks to Stephen Boyd for helping me understand the lockdep splat. + +Fixes: 843e600b8a2b ("driver core: Fix sleeping in invalid context during device link deletion") +[1] - https://lore.kernel.org/lkml/CAA+hA=S4eAreb7vo69LAXSk2t5=DEKNxHaiY1wSpk4xTp9urLg@mail.gmail.com/ +Reported-by: Dong Aisheng +Signed-off-by: Saravana Kannan +Tested-by: Peng Fan +Link: https://lore.kernel.org/r/20200901184445.1736658-1-saravanak@google.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: YunYi Yang +--- + drivers/base/core.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/base/core.c b/drivers/base/core.c +index c2a04f607904..f628c1517958 100644 +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -742,9 +742,7 @@ static void device_link_put_kref(struct device_link *link) + void device_link_del(struct device_link *link) + { + device_links_write_lock(); +- device_pm_lock(); + device_link_put_kref(link); +- device_pm_unlock(); + device_links_write_unlock(); + } + EXPORT_SYMBOL_GPL(device_link_del); +@@ -765,7 +763,6 @@ void device_link_remove(void *consumer, struct device *supplier) + return; + + device_links_write_lock(); +- device_pm_lock(); + + list_for_each_entry(link, &supplier->links.consumers, s_node) { + if (link->consumer == consumer) { +@@ -774,7 +771,6 @@ void device_link_remove(void *consumer, struct device *supplier) + } + } + +- device_pm_unlock(); + device_links_write_unlock(); + } + EXPORT_SYMBOL_GPL(device_link_remove); +-- +2.27.0 + diff --git a/patches/0570-driver-core-platform-Add-extra-error-check-in-devm_p.patch b/patches/0570-driver-core-platform-Add-extra-error-check-in-devm_p.patch new file mode 100644 index 00000000..54fd7d81 --- /dev/null +++ b/patches/0570-driver-core-platform-Add-extra-error-check-in-devm_p.patch @@ -0,0 +1,52 @@ +From a3d3c2c98932dec913b734981732810cb0400566 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Mon, 21 Dec 2020 22:30:55 +0800 +Subject: [PATCH 252/256] driver core: platform: Add extra error check in + devm_platform_get_irqs_affinity() + +mainline inclusion +from mainline-v5.11-rc5 +commit e1dc20995cb9fa04b46e8f37113a7203c906d2bf +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F7ZR + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e1dc20995cb9fa04b46e8f37113a7203c906d2bf + +---------------------------------------------------------------------- + +The current check of nvec < minvec for nvec returned from +platform_irq_count() will not detect a negative error code in nvec. + +This is because minvec is unsigned, and, as such, nvec is promoted to +unsigned in that check, which will make it a huge number (if it contained +-EPROBE_DEFER). + +In practice, an error should not occur in nvec for the only in-tree +user, but add a check anyway. + +Fixes: e15f2fa959f2 ("driver core: platform: Add devm_platform_get_irqs_affinity()") +Reported-by: Dan Carpenter +Signed-off-by: John Garry +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/1608561055-231244-1-git-send-email-john.garry@huawei.com +Signed-off-by: YunYi Yang +--- + drivers/base/platform.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/base/platform.c b/drivers/base/platform.c +index 2a17ffd89d78..0e31fffeafb4 100644 +--- a/drivers/base/platform.c ++++ b/drivers/base/platform.c +@@ -253,6 +253,8 @@ int devm_platform_get_irqs_affinity(struct platform_device *dev, + return -ERANGE; + + nvec = platform_irq_count(dev); ++ if (nvec < 0) ++ return nvec; + + if (nvec < minvec) + return -ENOSPC; +-- +2.27.0 + diff --git a/patches/0571-driver-core-Fix-device-link-device-name-collision.patch b/patches/0571-driver-core-Fix-device-link-device-name-collision.patch new file mode 100644 index 00000000..cdd28bfc --- /dev/null +++ b/patches/0571-driver-core-Fix-device-link-device-name-collision.patch @@ -0,0 +1,185 @@ +From b23532689a4d2ea54e839a5b024c97fdd7088fd6 Mon Sep 17 00:00:00 2001 +From: Saravana Kannan +Date: Sun, 10 Jan 2021 09:54:07 -0800 +Subject: [PATCH 253/256] driver core: Fix device link device name collision + +mainline inclusion +from mainline-v5.11-rc5 +commit e020ff611ba9be54e959e6b548038f8a020da1c9 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e020ff611ba9be54e959e6b548038f8a020da1c9 + +---------------------------------------------------------------------- + +The device link device's name was of the form: +-- + +This can cause name collision as reported here [1] as device names are +not globally unique. Since device names have to be unique within the +bus/class, add the bus/class name as a prefix to the device names used to +construct the device link device name. + +So the devuce link device's name will be of the form: +:--: + +[1] - https://lore.kernel.org/lkml/20201229033440.32142-1-michael@walle.cc/ + +Fixes: 287905e68dd2 ("driver core: Expose device link details in sysfs") +Cc: stable@vger.kernel.org +Reported-by: Michael Walle +Tested-by: Michael Walle +Signed-off-by: Saravana Kannan +Link: https://lore.kernel.org/r/20210110175408.1465657-1-saravanak@google.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: YunYi Yang + + Conflicts: + Documentation/ABI/testing/sysfs-class-devlink + drivers/base/core.c + include/linux/device.h +--- + .../ABI/testing/sysfs-devices-consumer | 5 ++-- + .../ABI/testing/sysfs-devices-supplier | 5 ++-- + drivers/base/core.c | 27 ++++++++++--------- + include/linux/device.h | 12 +++++++++ + 4 files changed, 33 insertions(+), 16 deletions(-) + +diff --git a/Documentation/ABI/testing/sysfs-devices-consumer b/Documentation/ABI/testing/sysfs-devices-consumer +index 1f06d74d1c3c..0809fda092e6 100644 +--- a/Documentation/ABI/testing/sysfs-devices-consumer ++++ b/Documentation/ABI/testing/sysfs-devices-consumer +@@ -4,5 +4,6 @@ Contact: Saravana Kannan + Description: + The /sys/devices/.../consumer: are symlinks to device + links where this device is the supplier. denotes the +- name of the consumer in that device link. There can be zero or +- more of these symlinks for a given device. ++ name of the consumer in that device link and is of the form ++ bus:device name. There can be zero or more of these symlinks ++ for a given device. +diff --git a/Documentation/ABI/testing/sysfs-devices-supplier b/Documentation/ABI/testing/sysfs-devices-supplier +index a919e0db5e90..207f5972e98d 100644 +--- a/Documentation/ABI/testing/sysfs-devices-supplier ++++ b/Documentation/ABI/testing/sysfs-devices-supplier +@@ -4,5 +4,6 @@ Contact: Saravana Kannan + Description: + The /sys/devices/.../supplier: are symlinks to device + links where this device is the consumer. denotes the +- name of the supplier in that device link. There can be zero or +- more of these symlinks for a given device. ++ name of the supplier in that device link and is of the form ++ bus:device name. There can be zero or more of these symlinks ++ for a given device. +diff --git a/drivers/base/core.c b/drivers/base/core.c +index f628c1517958..35753bbca592 100644 +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -359,7 +359,9 @@ static int devlink_add_symlinks(struct device *dev, + struct device *con = link->consumer; + char *buf; + +- len = max(strlen(dev_name(sup)), strlen(dev_name(con))); ++ len = max(strlen(dev_bus_name(sup)) + strlen(dev_name(sup)), ++ strlen(dev_bus_name(con)) + strlen(dev_name(con))); ++ len += strlen(":"); + len += strlen("supplier:") + 1; + buf = kzalloc(len, GFP_KERNEL); + if (!buf) +@@ -373,12 +375,12 @@ static int devlink_add_symlinks(struct device *dev, + if (ret) + goto err_con; + +- snprintf(buf, len, "consumer:%s", dev_name(con)); ++ snprintf(buf, len, "consumer:%s:%s", dev_bus_name(con), dev_name(con)); + ret = sysfs_create_link(&sup->kobj, &link->link_dev.kobj, buf); + if (ret) + goto err_con_dev; + +- snprintf(buf, len, "supplier:%s", dev_name(sup)); ++ snprintf(buf, len, "supplier:%s:%s", dev_bus_name(sup), dev_name(sup)); + ret = sysfs_create_link(&con->kobj, &link->link_dev.kobj, buf); + if (ret) + goto err_sup_dev; +@@ -386,7 +388,7 @@ static int devlink_add_symlinks(struct device *dev, + goto out; + + err_sup_dev: +- snprintf(buf, len, "consumer:%s", dev_name(con)); ++ snprintf(buf, len, "consumer:%s:%s", dev_bus_name(con), dev_name(con)); + sysfs_remove_link(&sup->kobj, buf); + err_con_dev: + sysfs_remove_link(&link->link_dev.kobj, "consumer"); +@@ -409,7 +411,9 @@ static void devlink_remove_symlinks(struct device *dev, + sysfs_remove_link(&link->link_dev.kobj, "consumer"); + sysfs_remove_link(&link->link_dev.kobj, "supplier"); + +- len = max(strlen(dev_name(sup)), strlen(dev_name(con))); ++ len = max(strlen(dev_bus_name(sup)) + strlen(dev_name(sup)), ++ strlen(dev_bus_name(con)) + strlen(dev_name(con))); ++ len += strlen(":"); + len += strlen("supplier:") + 1; + buf = kzalloc(len, GFP_KERNEL); + if (!buf) { +@@ -417,9 +421,9 @@ static void devlink_remove_symlinks(struct device *dev, + return; + } + +- snprintf(buf, len, "supplier:%s", dev_name(sup)); ++ snprintf(buf, len, "supplier:%s:%s", dev_bus_name(sup), dev_name(sup)); + sysfs_remove_link(&con->kobj, buf); +- snprintf(buf, len, "consumer:%s", dev_name(con)); ++ snprintf(buf, len, "consumer:%s:%s", dev_bus_name(con), dev_name(con)); + sysfs_remove_link(&sup->kobj, buf); + kfree(buf); + } +@@ -628,8 +632,9 @@ struct device_link *device_link_add(struct device *consumer, + + link->link_dev.class = &devlink_class; + device_set_pm_not_required(&link->link_dev); +- dev_set_name(&link->link_dev, "%s:%s", +- dev_name(supplier), dev_name(consumer)); ++ dev_set_name(&link->link_dev, "%s:%s--%s:%s", ++ dev_bus_name(supplier), dev_name(supplier), ++ dev_bus_name(consumer), dev_name(consumer)); + if (device_register(&link->link_dev)) { + put_device(consumer); + put_device(supplier); +@@ -1192,9 +1197,7 @@ const char *dev_driver_string(const struct device *dev) + * never change once they are set, so they don't need special care. + */ + drv = READ_ONCE(dev->driver); +- return drv ? drv->name : +- (dev->bus ? dev->bus->name : +- (dev->class ? dev->class->name : "")); ++ return drv ? drv->name : dev_bus_name(dev); + } + EXPORT_SYMBOL(dev_driver_string); + +diff --git a/include/linux/device.h b/include/linux/device.h +index 9c850a68fd2f..4476b400ea8b 100644 +--- a/include/linux/device.h ++++ b/include/linux/device.h +@@ -1125,6 +1125,18 @@ static inline const char *dev_name(const struct device *dev) + return kobject_name(&dev->kobj); + } + ++/** ++ * dev_bus_name - Return a device's bus/class name, if at all possible ++ * @dev: struct device to get the bus/class name of ++ * ++ * Will return the name of the bus/class the device is attached to. If it is ++ * not attached to a bus/class, an empty string will be returned. ++ */ ++static inline const char *dev_bus_name(const struct device *dev) ++{ ++ return dev->bus ? dev->bus->name : (dev->class ? dev->class->name : ""); ++} ++ + extern __printf(2, 3) + int dev_set_name(struct device *dev, const char *name, ...); + +-- +2.27.0 + diff --git a/patches/0572-driver-core-Prevent-warning-when-removing-a-device-l.patch b/patches/0572-driver-core-Prevent-warning-when-removing-a-device-l.patch new file mode 100644 index 00000000..b451fcc0 --- /dev/null +++ b/patches/0572-driver-core-Prevent-warning-when-removing-a-device-l.patch @@ -0,0 +1,51 @@ +From a68b6fc68aad9a38d59af391df57583eaaf8ec44 Mon Sep 17 00:00:00 2001 +From: Adrian Hunter +Date: Fri, 16 Jul 2021 14:44:07 +0300 +Subject: [PATCH 254/256] driver core: Prevent warning when removing a device + link from unregistered consumer + +mainline inclusion +from mainline-v5.14-rc3 +commit e64daad660a0c9ace3acdc57099fffe5ed83f977 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e64daad660a0c9ace3acdc57099fffe5ed83f977 + +---------------------------------------------------------------------- + +sysfs_remove_link() causes a warning if the parent directory does not +exist. That can happen if the device link consumer has not been registered. +So do not attempt sysfs_remove_link() in that case. + +Fixes: 287905e68dd29 ("driver core: Expose device link details in sysfs") +Signed-off-by: Adrian Hunter +Cc: stable@vger.kernel.org # 5.9+ +Reviewed-by: Rafael J. Wysocki +Link: https://lore.kernel.org/r/20210716114408.17320-2-adrian.hunter@intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: YunYi Yang +--- + drivers/base/core.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/base/core.c b/drivers/base/core.c +index 35753bbca592..1f803dce1493 100644 +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -421,8 +421,10 @@ static void devlink_remove_symlinks(struct device *dev, + return; + } + +- snprintf(buf, len, "supplier:%s:%s", dev_bus_name(sup), dev_name(sup)); +- sysfs_remove_link(&con->kobj, buf); ++ if (device_is_registered(con)) { ++ snprintf(buf, len, "supplier:%s:%s", dev_bus_name(sup), dev_name(sup)); ++ sysfs_remove_link(&con->kobj, buf); ++ } + snprintf(buf, len, "consumer:%s:%s", dev_bus_name(con), dev_name(con)); + sysfs_remove_link(&sup->kobj, buf); + kfree(buf); +-- +2.27.0 + diff --git a/patches/0573-driver-core-Reject-pointless-SYNC_STATE_ONLY-device-.patch b/patches/0573-driver-core-Reject-pointless-SYNC_STATE_ONLY-device-.patch new file mode 100644 index 00000000..261a1800 --- /dev/null +++ b/patches/0573-driver-core-Reject-pointless-SYNC_STATE_ONLY-device-.patch @@ -0,0 +1,56 @@ +From 7266e20cade116bab8cbf29316c9f68539cbf5fb Mon Sep 17 00:00:00 2001 +From: Saravana Kannan +Date: Wed, 29 Sep 2021 12:05:49 -0700 +Subject: [PATCH 255/256] driver core: Reject pointless SYNC_STATE_ONLY device + links + +mainline inclusion +from mainline-v5.15-rc6 +commit f729a592adb6760013c3e48622a5bf256b992452 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f729a592adb6760013c3e48622a5bf256b992452 + +---------------------------------------------------------------------- + +SYNC_STATE_ONLY device links intentionally allow cycles because cyclic +sync_state() dependencies are valid and necessary. + +However a SYNC_STATE_ONLY device link where the consumer and the supplier +are the same device is pointless because the device link would be deleted +as soon as the device probes (because it's also the consumer) and won't +affect when the sync_state() callback is called. It's a waste of CPU cycles +and memory to create this device link. So reject any attempts to create +such a device link. + +Fixes: 05ef983e0d65 ("driver core: Add device link support for SYNC_STATE_ONLY flag") +Cc: stable +Reported-by: Ulf Hansson +Reviewed-by: Rafael J. Wysocki +Reviewed-by: Ulf Hansson +Signed-off-by: Saravana Kannan +Link: https://lore.kernel.org/r/20210929190549.860541-1-saravanak@google.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: YunYi Yang +--- + drivers/base/core.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/base/core.c b/drivers/base/core.c +index 1f803dce1493..7e54688d7235 100644 +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -521,7 +521,8 @@ struct device_link *device_link_add(struct device *consumer, + { + struct device_link *link; + +- if (!consumer || !supplier || flags & ~DL_ADD_VALID_FLAGS || ++ if (!consumer || !supplier || consumer == supplier || ++ flags & ~DL_ADD_VALID_FLAGS || + (flags & DL_FLAG_STATELESS && flags & DL_MANAGED_LINK_FLAGS) || + (flags & DL_FLAG_SYNC_STATE_ONLY && + flags != DL_FLAG_SYNC_STATE_ONLY) || +-- +2.27.0 + diff --git a/patches/0574-driver-core-Fix-possible-memory-leak-in-device_link_.patch b/patches/0574-driver-core-Fix-possible-memory-leak-in-device_link_.patch new file mode 100644 index 00000000..de3c2acb --- /dev/null +++ b/patches/0574-driver-core-Fix-possible-memory-leak-in-device_link_.patch @@ -0,0 +1,76 @@ +From 41b860a32a28ba0c754a8000cd424c05da6dbafb Mon Sep 17 00:00:00 2001 +From: Yang Yingliang +Date: Thu, 30 Sep 2021 16:57:14 +0800 +Subject: [PATCH 256/256] driver core: Fix possible memory leak in + device_link_add() + +mainline inclusion +from mainline-v5.16-rc1 +commit df0a18149474c7e6b21f6367fbc6bc8d0f192444 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8F803 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=df0a18149474c7e6b21f6367fbc6bc8d0f192444 + +---------------------------------------------------------------------- + +I got memory leak as follows: + +unreferenced object 0xffff88801f0b2200 (size 64): + comm "i2c-lis2hh12-21", pid 5455, jiffies 4294944606 (age 15.224s) + hex dump (first 32 bytes): + 72 65 67 75 6c 61 74 6f 72 3a 72 65 67 75 6c 61 regulator:regula + 74 6f 72 2e 30 2d 2d 69 32 63 3a 31 2d 30 30 31 tor.0--i2c:1-001 + backtrace: + [<00000000bf5b0c3b>] __kmalloc_track_caller+0x19f/0x3a0 + [<0000000050da42d9>] kvasprintf+0xb5/0x150 + [<000000004bbbed13>] kvasprintf_const+0x60/0x190 + [<00000000cdac7480>] kobject_set_name_vargs+0x56/0x150 + [<00000000bf83f8e8>] dev_set_name+0xc0/0x100 + [<00000000cc1cf7e3>] device_link_add+0x6b4/0x17c0 + [<000000009db9faed>] _regulator_get+0x297/0x680 + [<00000000845e7f2b>] _devm_regulator_get+0x5b/0xe0 + [<000000003958ee25>] st_sensors_power_enable+0x71/0x1b0 [st_sensors] + [<000000005f450f52>] st_accel_i2c_probe+0xd9/0x150 [st_accel_i2c] + [<00000000b5f2ab33>] i2c_device_probe+0x4d8/0xbe0 + [<0000000070fb977b>] really_probe+0x299/0xc30 + [<0000000088e226ce>] __driver_probe_device+0x357/0x500 + [<00000000c21dda32>] driver_probe_device+0x4e/0x140 + [<000000004e650441>] __device_attach_driver+0x257/0x340 + [<00000000cf1891b8>] bus_for_each_drv+0x166/0x1e0 + +When device_register() returns an error, the name allocated in dev_set_name() +will be leaked, the put_device() should be used instead of kfree() to give up +the device reference, then the name will be freed in kobject_cleanup() and the +references of consumer and supplier will be decreased in device_link_release_fn(). + +Fixes: 287905e68dd2 ("driver core: Expose device link details in sysfs") +Reported-by: Hulk Robot +Reviewed-by: Saravana Kannan +Reviewed-by: Rafael J. Wysocki +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20210930085714.2057460-1-yangyingliang@huawei.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: YunYi Yang +--- + drivers/base/core.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/base/core.c b/drivers/base/core.c +index 7e54688d7235..a70325253cc9 100644 +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -639,9 +639,7 @@ struct device_link *device_link_add(struct device *consumer, + dev_bus_name(supplier), dev_name(supplier), + dev_bus_name(consumer), dev_name(consumer)); + if (device_register(&link->link_dev)) { +- put_device(consumer); +- put_device(supplier); +- kfree(link); ++ put_device(&link->link_dev); + link = NULL; + goto out; + } +-- +2.27.0 + diff --git a/series.conf b/series.conf index 894f274f..d7a9a513 100644 --- a/series.conf +++ b/series.conf @@ -319,3 +319,259 @@ patches/0315-perf-metricgroup-Return-error-code-from-metricgroup_.patch patches/0316-perf-metricgroup-Fix-system-PMU-metrics.patch patches/0317-perf-metricgroup-Fix-for-metrics-containing-duration.patch patches/0318-perf-metricgroup-Fix-find_evsel_group-event-selector.patch +patches/0319-block-Move-power-management-code-into-a-new-source-f.patch +patches/0320-block-Split-blk_pm_add_request-and-blk_pm_put_reques.patch +patches/0321-block-Schedule-runtime-resume-earlier.patch +patches/0322-block-Allow-unfreezing-of-a-queue-while-requests-are.patch +patches/0323-block-Make-blk_get_request-block-for-non-PM-requests.patch +patches/0324-blk-mq-Enable-support-for-runtime-power-management.patch +patches/0325-scsi-hisi_sas-No-need-to-check-return-value-of-debug.patch +patches/0326-scsi-hisi_sas-Fix-type-casting-and-missing-static-qu.patch +patches/0327-scsi-hisi_sas-Fix-losing-directly-attached-disk-when.patch +patches/0328-scsi-hisi_sas-Use-pci_irq_get_affinity-for-v3-hw-as-.patch +patches/0329-scsi-hisi_sas-Some-misc-tidy-up.patch +patches/0330-scsi-hisi_sas-Make-max-IPTT-count-equal-for-all-hw-r.patch +patches/0331-scsi-hisi_sas-Fix-pointer-usage-error-in-show-debugf.patch +patches/0332-scsi-hisi_sas-Snapshot-HW-cache-of-IOST-and-ITCT-at-.patch +patches/0333-scsi-hisi_sas-Snapshot-AXI-and-RAS-register-at-debug.patch +patches/0334-scsi-hisi_sas-Drop-kmap_atomic-in-SMP-command-comple.patch +patches/0335-scsi-hisi_sas-Drop-SMP-resp-frame-DMA-mapping.patch +patches/0336-scsi-hisi_sas-Drop-free_irq-when-devm_request_irq-fa.patch +patches/0337-scsi-hisi_sas-Modify-return-type-of-debugfs-function.patch +patches/0338-scsi-hisi_sas-Remove-some-unnecessary-code.patch +patches/0339-scsi-hisi_sas-remove-set-but-not-used-variable-irq_v.patch +patches/0340-scsi-hisi_sas-use-devm_platform_ioremap_resource-to-.patch +patches/0341-scsi-hisi_sas-add-debugfs-auto-trigger-for-internal-.patch +patches/0342-scsi-hisi_sas-Remove-hisi_sas_hw.slot_complete.patch +patches/0343-scsi-hisi_sas-Remove-redundant-work-declaration.patch +patches/0344-scsi-hisi_sas-Remove-some-unused-function-arguments.patch +patches/0345-scsi-hisi_sas-Add-hisi_sas_debugfs_alloc-to-centrali.patch +patches/0346-scsi-hisi_sas-fix-spelling-mistake-digial-digital.patch +patches/0347-scsi-hisi_sas-Make-three-functions-static.patch +patches/0348-scsi-hisi_sas-Don-t-create-debugfs-dump-folder-twice.patch +patches/0349-scsi-hisi_sas-Add-timestamp-for-a-debugfs-dump.patch +patches/0350-scsi-hisi_sas-Add-debugfs-file-structure-for-CQ.patch +patches/0351-scsi-hisi_sas-Add-debugfs-file-structure-for-DQ.patch +patches/0352-scsi-hisi_sas-Add-debugfs-file-structure-for-registe.patch +patches/0353-scsi-hisi_sas-Add-debugfs-file-structure-for-port.patch +patches/0354-scsi-hisi_sas-Add-debugfs-file-structure-for-IOST.patch +patches/0355-scsi-hisi_sas-Add-debugfs-file-structure-for-ITCT.patch +patches/0356-scsi-hisi_sas-Add-debugfs-file-structure-for-IOST-ca.patch +patches/0357-scsi-hisi_sas-Add-debugfs-file-structure-for-ITCT-ca.patch +patches/0358-scsi-hisi_sas-Allocate-memory-for-multiple-dumps-of-.patch +patches/0359-scsi-hisi_sas-Add-module-parameter-for-debugfs-dump-.patch +patches/0360-scsi-hisi_sas-Add-ability-to-have-multiple-debugfs-d.patch +patches/0361-scsi-hisi_sas-Delete-the-debugfs-folder-of-hisi_sas-.patch +patches/0362-scsi-hisi_sas-Record-the-phy-down-event-in-debugfs.patch +patches/0363-scsi-hisi_sas-Return-directly-if-init-hardware-faile.patch +patches/0364-scsi-hisi_sas-Stop-converting-a-bool-into-a-bool.patch +patches/0365-scsi-hisi_sas-Replace-magic-number-when-handle-chann.patch +patches/0366-scsi-hisi_sas-Modify-the-file-permissions-of-trigger.patch +patches/0367-scsi-hisi_sas-Add-prints-for-v3-hw-interrupt-converg.patch +patches/0368-scsi-hisi_sas-Rename-hisi_sas_cq.pci_irq_mask.patch +patches/0369-scsi-hisi_sas-Use-dev_err-in-read_iost_itct_cache_v3.patch +patches/0370-scsi-hisi_sas-Fix-build-error-without-SATA_HOST.patch +patches/0371-scsi-hisi_sas-Display-proc_name-in-sysfs.patch +patches/0372-scsi-hisi_sas-Modify-the-commit-information-for-DSM-.patch +patches/0373-scsi-hisi_sas-Add-SAS_RAS_INTR0-to-debugfs-register-.patch +patches/0374-scsi-hisi_sas-Stop-returning-error-code-from-slot_co.patch +patches/0375-scsi-hisi_sas-Do-not-reset-phy-timer-to-wait-for-str.patch +patches/0376-scsi-hisi_sas-Remove-one-kerneldoc-comment.patch +patches/0377-block-add-REQ_HIPRI-and-inherit-it-from-IOCB_HIPRI.patch +patches/0378-blk-mq-kill-q-mq_map.patch +patches/0379-fix-kabi-broken-due-to-change-of-struct-struct-reque.patch +patches/0380-blk-mq-abstract-out-queue-map.patch +patches/0381-fix-kabi-broken-due-to-change-of-function-blk_mq_map.patch +patches/0382-blk-mq-provide-dummy-blk_mq_map_queue_type-helper.patch +patches/0383-blk-mq-pass-in-request-bio-flags-to-queue-mapping.patch +patches/0384-fix-kabi-broken-due-to-change-of-struct-blk_mq_alloc.patch +patches/0385-blk-mq-allow-software-queue-to-map-to-multiple-hardw.patch +patches/0386-fix-kabi-broken-due-to-change-of-struct-blk_mq_hw_ct.patch +patches/0387-blk-mq-add-type-attribute-to-the-sysfs-hctx-director.patch +patches/0388-blk-mq-support-multiple-hctx-maps.patch +patches/0389-fix-kabi-broken-due-to-change-of-struct-blk_mq_tag_s.patch +patches/0390-blk-mq-separate-number-of-hardware-queues-from-nr_cp.patch +patches/0391-blk-mq-cache-request-hardware-queue-mapping.patch +patches/0392-fix-kabi-broken-due-to-change-of-struct-request.patch +patches/0393-blk-mq-cleanup-and-improve-list-insertion.patch +patches/0394-blk-mq-improve-plug-list-sorting.patch +patches/0395-blk-mq-initial-support-for-multiple-queue-maps.patch +patches/0396-block-move-queues-types-to-the-block-layer.patch +patches/0397-blk-mq-Rename-BLK_MQ_F_TAG_SHARED-as-BLK_MQ_F_TAG_QU.patch +patches/0398-blk-mq-Rename-blk_mq_update_tag_set_depth.patch +patches/0399-blk-mq-Free-tags-in-blk_mq_init_tags-upon-error.patch +patches/0400-blk-mq-Pass-flags-for-tag-init-free.patch +patches/0401-blk-mq-Use-pointers-for-blk_mq_tags-bitmap-tags.patch +patches/0402-fix-kabi-broken-due-to-change-of-struct-blk_mq_tags.patch +patches/0403-blk-mq-Facilitate-a-shared-sbitmap-per-tagset.patch +patches/0404-fix-kabi-broken-due-to-change-of-struct-blk_mq_tag_s.patch +patches/0405-blk-mq-Relocate-hctx_may_queue.patch +patches/0406-blk-mq-Record-nr_active_requests-per-queue-for-when-.patch +patches/0407-fix-kabi-broken-due-to-change-of-struct-request_queu.patch +patches/0408-blk-mq-Record-active_queues_shared_sbitmap-per-tag_s.patch +patches/0409-fix-kabi-broken-due-to-change-of-struct-blk_mq_tag_s.patch +patches/0410-scsi-Add-host-and-host-template-flag-host_tagset.patch +patches/0411-fix-kabi-broken-due-to-change-of-struct-scsi_host_te.patch +patches/0412-scsi-core-Show-nr_hw_queues-in-sysfs.patch +patches/0413-scsi-hisi_sas-Switch-v3-hw-to-MQ.patch +patches/0414-scsi-scsi_debug-Support-hostwide-tags.patch +patches/0415-scsi-scsi_debug-Support-host-tagset.patch +patches/0416-scsi-hisi_sas-Modify-macro-name-for-OOB-phy-linkrate.patch +patches/0417-scsi-hisi_sas-Do-not-modify-upper-fields-of-PROG_PHY.patch +patches/0418-scsi-hisi_sas-Make-phy-index-variable-name-consisten.patch +patches/0419-scsi-hisi_sas-Add-BIST-support-for-phy-FFE.patch +patches/0420-scsi-hisi_sas-Add-BIST-support-for-fixed-code-patter.patch +patches/0421-scsi-hisi_sas-Add-missing-newlines.patch +patches/0422-scsi-hisi_sas-Code-style-cleanup.patch +patches/0423-PM-runtime-Remove-link-state-checks-in-rpm_get-put_s.patch +patches/0424-scsi-hisi_sas-Use-hisi_hba-cq_nvecs-for-calling-call.patch +patches/0425-scsi-hisi_sas-Switch-to-new-framework-to-support-sus.patch +patches/0426-scsi-hisi_sas-Add-controller-runtime-PM-support-for-.patch +patches/0427-scsi-hisi_sas-Add-check-for-methods-_PS0-and-_PR0.patch +patches/0428-scsi-hisi_sas-Add-device-link-between-SCSI-devices-a.patch +patches/0429-scsi-hisi_sas-Recover-PHY-state-according-to-the-sta.patch +patches/0430-scsi-hisi_sas-Stop-using-queue-0-always-for-v2-hw.patch +patches/0431-PM-runtime-Drop-runtime-PM-references-to-supplier-on.patch +patches/0432-PM-runtime-Drop-pm_runtime_clean_up_links.patch +patches/0433-PM-runtime-Resume-the-device-earlier-in-__device_rel.patch +patches/0434-scsi-hisi_sas-Select-a-suitable-queue-for-internal-I.patch +patches/0435-scsi-hisi_sas-Fix-up-probe-error-handling-for-v3-hw.patch +patches/0436-PM-core-Add-support-to-skip-power-management-in-devi.patch +patches/0437-fix-kabi-broken-due-to-change-of-struct-dev_pm_info.patch +patches/0438-driver-core-Add-device-link-support-for-SYNC_STATE_O.patch +patches/0439-driver-core-Expose-device-link-details-in-sysfs.patch +patches/0440-fix-kabi-broken-due-to-change-of-struct-device_link.patch +patches/0441-driver-core-Fix-sleeping-in-invalid-context-during-d.patch +patches/0442-drivers-base-Fix-device-link-removal.patch +patches/0443-fix-kabi-broken-due-to-change-of-struct-dev_link.patch +patches/0444-scsi-megaraid_sas-Rename-scratch_pad-registers.patch +patches/0445-scsi-megaraid_sas-Introduce-new-Aero-adapter-type.patch +patches/0446-scsi-megaraid_sas-Load-balance-completions-across-al.patch +patches/0447-scsi-megaraid_sas-RAID1-PCI-bandwidth-limit-algorith.patch +patches/0448-scsi-megaraid_sas-Add-support-for-High-IOPS-queues.patch +patches/0449-scsi-megaraid_sas-Enable-coalescing-for-high-IOPS-qu.patch +patches/0450-scsi-megaraid_sas-Use-high-IOPS-queues-based-on-IO-w.patch +patches/0451-scsi-megaraid_sas-Introduce-various-Aero-performance.patch +patches/0452-scsi-megaraid_sas-Use-Block-layer-API-to-check-SCSI-.patch +patches/0453-scsi-megaraid_sas-Added-support-for-shared-host-tags.patch +patches/0454-scsi-hisi_sas-Reduce-some-indirection-in-v3-hw-drive.patch +patches/0455-scsi-hisi_sas-Move-debugfs-code-to-v3-hw-driver.patch +patches/0456-scsi-hisi_sas-Remove-preemptible.patch +patches/0457-scsi-hisi_sas-use-threaded-irq-to-process-CQ-interru.patch +patches/0458-genirq-core-Introduce-struct-irq_affinity_desc.patch +patches/0459-fix-kabi-broken-due-to-change-of-struct-msi_desc.patch +patches/0460-resource-Add-irqresource_disabled.patch +patches/0461-genirq-affinity-Add-is_managed-to-struct-irq_affinit.patch +patches/0462-genirq-affinity-Add-irq_update_affinity_desc.patch +patches/0463-driver-core-platform-Add-devm_platform_get_irqs_affi.patch +patches/0464-scsi-hisi_sas-Expose-HW-queues-for-v2-hw.patch +patches/0465-scsi-hisi_sas-Remove-auto_affine_msi_experimental-mo.patch +patches/0466-scsi-libsas-Introduce-a-_gfp-variant-of-event-notifi.patch +patches/0467-scsi-mvsas-Pass-gfp_t-flags-to-libsas-event-notifier.patch +patches/0468-scsi-isci-Pass-gfp_t-flags-in-isci_port_link_down.patch +patches/0469-scsi-isci-Pass-gfp_t-flags-in-isci_port_link_up.patch +patches/0470-scsi-isci-Pass-gfp_t-flags-in-isci_port_bc_change_re.patch +patches/0471-scsi-libsas-Pass-gfp_t-flags-to-event-notifiers.patch +patches/0472-scsi-pm80xx-Pass-gfp_t-flags-to-libsas-event-notifie.patch +patches/0473-scsi-aic94xx-Pass-gfp_t-flags-to-libsas-event-notifi.patch +patches/0474-scsi-hisi_sas-Pass-gfp_t-flags-to-libsas-event-notif.patch +patches/0475-scsi-libsas-Add-gfp_t-flags-parameter-to-event-notif.patch +patches/0476-fix-kabi-broken-due-to-change-of-struct-sas_ha_struc.patch +patches/0477-scsi-hisi_sas-Switch-back-to-original-libsas-event-n.patch +patches/0478-scsi-aic94xx-Switch-back-to-original-libsas-event-no.patch +patches/0479-scsi-pm80xx-Switch-back-to-original-libsas-event-not.patch +patches/0480-scsi-libsas-Switch-back-to-original-event-notifiers-.patch +patches/0481-scsi-isci-Switch-back-to-original-libsas-event-notif.patch +patches/0482-scsi-mvsas-Switch-back-to-original-libsas-event-noti.patch +patches/0483-scsi-libsas-Remove-temporarily-added-_gfp-API-varian.patch +patches/0484-scsi-hisi_sas-Remove-deferred-probe-check-in-hisi_sa.patch +patches/0485-scsi-hisi_sas-Don-t-check-.nr_hw_queues-in-hisi_sas_.patch +patches/0486-scsi-hisi_sas-Enable-debugfs-support-by-default.patch +patches/0487-scsi-hisi_sas-Add-trace-FIFO-debugfs-support.patch +patches/0488-scsi-hisi_sas-Print-SAS-address-for-v3-hw-erroneous-.patch +patches/0489-scsi-hisi_sas-Call-sas_unregister_ha-to-roll-back-if.patch +patches/0490-scsi-hisi_sas-Directly-snapshot-registers-when-execu.patch +patches/0491-scsi-hisi_sas-Warn-in-v3-hw-channel-interrupt-handle.patch +patches/0492-scsi-hisi_sas-Print-SATA-device-SAS-address-for-soft.patch +patches/0493-scsi-hisi_sas-Put-a-limit-of-link-reset-retries.patch +patches/0494-scsi-hisi_sas-Run-I_T-nexus-resets-in-parallel-for-c.patch +patches/0495-scsi-hisi_sas-Include-HZ-in-timer-macros.patch +patches/0496-scsi-hisi_sas-Reset-controller-for-internal-abort-ti.patch +patches/0497-scsi-hisi_sas-Speed-up-error-handling-when-internal-.patch +patches/0498-scsi-libsas-Export-sas_phy_enable.patch +patches/0499-scsi-hisi_sas-Initialise-devices-in-.slave_alloc-cal.patch +patches/0500-scsi-hisi_sas-Wait-for-phyup-in-hisi_sas_control_phy.patch +patches/0501-scsi-libsas-Don-t-always-drain-event-workqueue-for-H.patch +patches/0502-scsi-libsas-Add-spin_lock-unlock-to-protect-asd_sas_.patch +patches/0503-scsi-hisi_sas-Fix-some-issues-related-to-asd_sas_por.patch +patches/0504-scsi-mvsas-Add-spin_lock-unlock-to-protect-asd_sas_p.patch +patches/0505-scsi-libsas-aic94xx-hisi_sas-mvsas-pm8001-Use-dev_is.patch +patches/0506-scsi-libsas-Insert-PORTE_BROADCAST_RCVD-event-for-re.patch +patches/0507-scsi-hisi_sas-Add-more-logs-for-runtime-suspend-resu.patch +patches/0508-scsi-libsas-Resume-host-while-sending-SMP-I-Os.patch +patches/0509-scsi-libsas-Add-flag-SAS_HA_RESUMING.patch +patches/0510-scsi-libsas-Refactor-sas_queue_deferred_work.patch +patches/0511-scsi-libsas-Defer-works-of-new-phys-during-suspend.patch +patches/0512-scsi-hisi_sas-Keep-controller-active-between-ISR-of-.patch +patches/0513-scsi-libsas-Keep-host-active-while-processing-events.patch +patches/0514-scsi-hisi_sas-Use-autosuspend-for-the-host-controlle.patch +patches/0515-scsi-hisi_sas-Limit-users-changing-debugfs-BIST-coun.patch +patches/0516-genirq-msi-Shutdown-managed-interrupts-with-unsatifi.patch +patches/0517-genirq-sched-isolation-Isolate-from-handling-managed.patch +patches/0518-genirq-Always-limit-the-affinity-to-online-CPUs.patch +patches/0519-irqchip-gic-v3-Always-trust-the-managed-affinity-pro.patch +patches/0520-blk-mq-Fix-blk_mq_tagset_busy_iter-for-shared-tags.patch +patches/0521-scsi-libsas-Resume-SAS-host-for-phy-reset-or-enable-.patch +patches/0522-scsi-hisi_sas-Prevent-parallel-controller-reset-and-.patch +patches/0523-scsi-hisi_sas-Fix-phyup-timeout-on-FPGA.patch +patches/0524-scsi-hisi_sas-Modify-v3-HW-SSP-underflow-error-proce.patch +patches/0525-scsi-libsas-Refactor-sas_ata_hard_reset.patch +patches/0526-scsi-hisi_sas-Use-sas_ata_wait_after_reset-in-IT-nex.patch +patches/0527-scsi-hisi_sas-Fix-rescan-after-deleting-a-disk.patch +patches/0528-scsi-hisi_sas-Undo-RPM-resume-for-failed-notify-phy-.patch +patches/0529-scsi-hisi_sas-Use-abort-task-set-to-reset-SAS-disks-.patch +patches/0530-scsi-libsas-Update-SATA-dev-FIS-in-sas_ata_task_done.patch +patches/0531-scsi-libsas-Add-sas_ata_device_link_abort.patch +patches/0532-scsi-libsas-Grab-the-ATA-port-lock-in-sas_ata_device.patch +patches/0533-Disable-SATA-disk-phy-for-severe-I_T-nexus-reset-fai.patch +patches/0534-Revert-scsi-hisi_sas-Disable-SATA-disk-phy-for-sever.patch +patches/0535-scsi-libsas-Add-smp_ata_check_ready_type.patch +patches/0536-scsi-hisi_sas-Fix-SATA-devices-missing-issue-during-.patch +patches/0537-scsi-libsas-Do-not-export-sas_ata_wait_after_reset.patch +patches/0538-scsi-hisi_sas-Set-a-port-invalid-only-if-there-are-n.patch +patches/0539-scsi-hisi_sas-Exit-suspending-state-when-usage-count.patch +patches/0540-scsi-hisi_sas-Ensure-all-enabled-PHYs-up-during-cont.patch +patches/0541-scsi-sd-Reorganize-DIF-DIX-code-to-avoid-calling-rev.patch +patches/0542-scsi-sd-Update-DIX-config-every-time-sd_revalidate_d.patch +patches/0543-scsi-hisi_sas-Increase-debugfs_dump_index-after-dump.patch +patches/0544-scsi-hisi_sas-Configure-the-initialization-registers.patch +patches/0545-scsi-hisi_sas-Add-slave_destroy-interface-for-v3-hw.patch +patches/0546-scsi-hisi_sas-Block-requests-before-take-debugfs-sna.patch +patches/0547-scsi-hisi_sas-Work-around-build-failure-in-suspend-f.patch +patches/0548-scsi-hisi_sas-Check-usage-count-only-when-the-runtim.patch +patches/0549-scsi-sd-try-more-retries-of-START_STOP-when-resuming.patch +patches/0550-scsi-hisi_sas_v3_hw-Don-t-use-PCI-helper-functions.patch +patches/0551-scsi-hisi_sas_v3_hw-Remove-extra-function-calls-for-.patch +patches/0552-scsi-block-pm-Simplify-resume-handling.patch +patches/0553-scsi-block-pm-Always-set-request-queue-runtime-activ.patch +patches/0554-block-don-t-lose-track-of-REQ_INTEGRITY-flag.patch +patches/0555-block-Fix-blk_mq_-_map_queues-kernel-doc-headers.patch +patches/0556-blk-mq-Keep-set-nr_hw_queues-and-set-map-.nr_queues-.patch +patches/0557-blk-mq-docs-add-kernel-doc-description-for-a-new-str.patch +patches/0558-blk-mq-debugfs-Add-decode-for-BLK_MQ_F_TAG_HCTX_SHAR.patch +patches/0559-blk-mq-plug-request-for-shared-sbitmap.patch +patches/0560-blk-mq-debugfs-Show-active-requests-per-queue-for-sh.patch +patches/0561-scsi-block-Fix-a-race-in-the-runtime-power-managemen.patch +patches/0562-scsi-megaraid_sas-Enable-msix_load_balance-for-Invad.patch +patches/0563-scsi-pm80xx-Replace-open-coded-check-with-dev_is_exp.patch +patches/0564-x86-vector-Remove-warning-on-managed-interrupt-migra.patch +patches/0565-genirq-Fix-the-kerneldoc-comment-for-struct-irq_affi.patch +patches/0566-genirq-irqdesc-Fix-double-increment-in-alloc_descs.patch +patches/0567-genirq-Take-the-proposed-affinity-at-face-value-if-f.patch +patches/0568-driver-core-Update-device-link-status-correctly-for-.patch +patches/0569-driver-core-Fix-device_pm_lock-locking-for-device-li.patch +patches/0570-driver-core-platform-Add-extra-error-check-in-devm_p.patch +patches/0571-driver-core-Fix-device-link-device-name-collision.patch +patches/0572-driver-core-Prevent-warning-when-removing-a-device-l.patch +patches/0573-driver-core-Reject-pointless-SYNC_STATE_ONLY-device-.patch +patches/0574-driver-core-Fix-possible-memory-leak-in-device_link_.patch -- Gitee