Home Home > GIT Browse > SLE12-SP4-AZURE
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2018-08-08 21:31:27 +0200
committerTakashi Iwai <tiwai@suse.de>2018-08-08 21:31:27 +0200
commit942604c436ef6c88284d73923a9d84c28502de0f (patch)
tree570836432d216e1f4e22e1dbdc1c1cbc2d23bab8
parent332f08c70b63e90fa18b271dad811a87fb37a137 (diff)
parent281cdfc910562dc19cf2ba223fa4c0fc95f69fc9 (diff)
Merge branch 'SLE15' into openSUSE-15.0rpm-4.12.14-lp150.12.13
Conflicts: config/ppc64le/vanilla config/s390x/default config/s390x/vanilla config/x86_64/vanilla
-rw-r--r--config/arm64/default2
-rw-r--r--config/arm64/vanilla1
-rw-r--r--config/armv7hl/default1
-rw-r--r--config/armv7hl/lpae1
-rw-r--r--config/armv7hl/vanilla1
-rw-r--r--config/ppc64le/default1
-rw-r--r--config/ppc64le/vanilla1
-rw-r--r--config/s390x/default28
-rw-r--r--config/s390x/vanilla1
-rw-r--r--config/s390x/zfcpdump1
-rw-r--r--config/x86_64/default2
-rw-r--r--config/x86_64/vanilla1
-rw-r--r--kabi/severities1
-rw-r--r--patches.drivers/clk-at91-fix-clk-generated-compilation33
-rw-r--r--patches.drivers/ibmvnic-Remove-code-to-request-error-information.patch292
-rw-r--r--patches.drivers/ibmvnic-Revise-RX-TX-queue-error-messages.patch107
-rw-r--r--patches.drivers/ibmvnic-Update-firmware-error-reporting-with-cause-s.patch74
-rw-r--r--patches.drivers/pinctrl-intel-Add-Intel-Lewisburg-GPIO-support.patch404
-rw-r--r--patches.drivers/scsi-ata-enhance-the-definition-of-set-max-feature-field-value.patch33
-rw-r--r--patches.drivers/scsi-hisi_sas-add-an-mechanism-to-do-reset-work-synchronously.patch110
-rw-r--r--patches.drivers/scsi-hisi_sas-add-check-of-device-in-hisi_sas_task_exec.patch95
-rw-r--r--patches.drivers/scsi-hisi_sas-add-internal-abort-dev-in-some-places.patch73
-rw-r--r--patches.drivers/scsi-hisi_sas-add-led-feature-for-v3-hw.patch95
-rw-r--r--patches.drivers/scsi-hisi_sas-add-ras-feature-for-v3-hw.patch200
-rw-r--r--patches.drivers/scsi-hisi_sas-add-readl-poll-timeout-helper-wrappers.patch78
-rw-r--r--patches.drivers/scsi-hisi_sas-add-some-checks-to-avoid-free-ing-a-sas_task-twice.patch161
-rw-r--r--patches.drivers/scsi-hisi_sas-add-some-print-to-enhance-debugging.patch240
-rw-r--r--patches.drivers/scsi-hisi_sas-add-v2-hw-force-phy-function-for-internal-ata-command.patch73
-rw-r--r--patches.drivers/scsi-hisi_sas-add-v2-hw-port-axi-error-handling-support.patch106
-rw-r--r--patches.drivers/scsi-hisi_sas-add-v3-hw-module_device_table.patch39
-rw-r--r--patches.drivers/scsi-hisi_sas-add-v3-hw-suspend-and-resume.patch172
-rw-r--r--patches.drivers/scsi-hisi_sas-allocate-slot-buffer-earlier.patch141
-rw-r--r--patches.drivers/scsi-hisi_sas-change-common-allocation-mode-of-device-id.patch61
-rw-r--r--patches.drivers/scsi-hisi_sas-change-frame-type-for-set-max-commands.patch106
-rw-r--r--patches.drivers/scsi-hisi_sas-change-ncq-process-for-v3-hw.patch78
-rw-r--r--patches.drivers/scsi-hisi_sas-change-slot-index-allocation-mode.patch64
-rw-r--r--patches.drivers/scsi-hisi_sas-check-host-frozen-before-calling-done-function.patch164
-rw-r--r--patches.drivers/scsi-hisi_sas-check-iptt-is-valid-before-using-it-for-v3-hw.patch53
-rw-r--r--patches.drivers/scsi-hisi_sas-check-sas_dev-gone-earlier-in-hisi_sas_abort_task.patch55
-rw-r--r--patches.drivers/scsi-hisi_sas-code-cleanup-and-minor-bug-fixes.patch244
-rw-r--r--patches.drivers/scsi-hisi_sas-config-ata-de-reset-as-an-constrained-command-for-v3-hw.patch62
-rw-r--r--patches.drivers/scsi-hisi_sas-consolidate-command-check-in-hisi_sas_get_ata_protocol.patch63
-rw-r--r--patches.drivers/scsi-hisi_sas-create-a-scsi_host_template-per-hw-module.patch287
-rw-r--r--patches.drivers/scsi-hisi_sas-delete-timer-when-removing-hisi_sas-driver.patch62
-rw-r--r--patches.drivers/scsi-hisi_sas-directly-attached-disk-LED-feature-for.patch28
-rw-r--r--patches.drivers/scsi-hisi_sas-do-link-reset-for-some-chl_int2-ints.patch180
-rw-r--r--patches.drivers/scsi-hisi_sas-don-t-lock-dq-for-complete-task-sending.patch338
-rw-r--r--patches.drivers/scsi-hisi_sas-dt-bindings-add-an-property-of-signal-attenuation.patch44
-rw-r--r--patches.drivers/scsi-hisi_sas-fix-a-bug-in-hisi_sas_dev_gone.patch35
-rw-r--r--patches.drivers/scsi-hisi_sas-fix-a-typo-in-hisi_sas_task_prep.patch31
-rw-r--r--patches.drivers/scsi-hisi_sas-fix-dma_unmap_sg-parameter.patch45
-rw-r--r--patches.drivers/scsi-hisi_sas-fix-pi-memory-size.patch35
-rw-r--r--patches.drivers/scsi-hisi_sas-fix-return-value-of-hisi_sas_task_prep.patch58
-rw-r--r--patches.drivers/scsi-hisi_sas-fix-return-value-when-get_free_slot-failed.patch43
-rw-r--r--patches.drivers/scsi-hisi_sas-fix-sas_queue_full-problem-while-running-io.patch42
-rw-r--r--patches.drivers/scsi-hisi_sas-fix-the-issue-of-link-rate-inconsistency.patch124
-rw-r--r--patches.drivers/scsi-hisi_sas-fix-the-issue-of-setting-linkrate-register.patch77
-rw-r--r--patches.drivers/scsi-hisi_sas-improve-int_chnl_int_v2_hw-consistency-with-v3-hw.patch92
-rw-r--r--patches.drivers/scsi-hisi_sas-include-tmf-elements-in-struct-hisi_sas_slot.patch256
-rw-r--r--patches.drivers/scsi-hisi_sas-increase-timer-expire-of-internal-abort-task.patch44
-rw-r--r--patches.drivers/scsi-hisi_sas-init-disks-after-controller-reset.patch79
-rw-r--r--patches.drivers/scsi-hisi_sas-initialize-dq-spinlock-before-use.patch32
-rw-r--r--patches.drivers/scsi-hisi_sas-introduce-hisi_sas_phy_set_linkrate.patch191
-rw-r--r--patches.drivers/scsi-hisi_sas-judge-result-of-internal-abort.patch137
-rw-r--r--patches.drivers/scsi-hisi_sas-make-local-symbol-host_attrs-static.patch34
-rw-r--r--patches.drivers/scsi-hisi_sas-make-return-type-of-prep-functions-void.patch532
-rw-r--r--patches.drivers/scsi-hisi_sas-make-sas-address-of-sata-disks-unique.patch31
-rw-r--r--patches.drivers/scsi-hisi_sas-mark-phy-as-in-reset-for-nexus-reset.patch202
-rw-r--r--patches.drivers/scsi-hisi_sas-modify-hisi_sas_dev_gone-for-reset.patch54
-rw-r--r--patches.drivers/scsi-hisi_sas-modify-some-register-config-for-hip08.patch81
-rw-r--r--patches.drivers/scsi-hisi_sas-optimise-port-id-refresh-function.patch115
-rw-r--r--patches.drivers/scsi-hisi_sas-optimise-the-usage-of-dq-locking.patch78
-rw-r--r--patches.drivers/scsi-hisi_sas-print-device-id-for-errors.patch54
-rw-r--r--patches.drivers/scsi-hisi_sas-re-add-the-lldd_port_deformed.patch47
-rw-r--r--patches.drivers/scsi-hisi_sas-relocate-clearing-itct-and-freeing-device.patch161
-rw-r--r--patches.drivers/scsi-hisi_sas-relocate-smp-sg-map.patch309
-rw-r--r--patches.drivers/scsi-hisi_sas-remove-depends-on-has_dma-in-case-of-platform-dependency.patch42
-rw-r--r--patches.drivers/scsi-hisi_sas-remove-redundant-handling-to-event95-for-v3.patch49
-rw-r--r--patches.drivers/scsi-hisi_sas-remove-some-unneeded-structure-members.patch104
-rw-r--r--patches.drivers/scsi-hisi_sas-remove-unused-variable-hisi_sas_devices-running_req.patch89
-rw-r--r--patches.drivers/scsi-hisi_sas-reset-disks-when-discovered.patch111
-rw-r--r--patches.drivers/scsi-hisi_sas-some-optimizations-of-host-controller-reset.patch77
-rw-r--r--patches.drivers/scsi-hisi_sas-stop-controller-timer-for-reset.patch33
-rw-r--r--patches.drivers/scsi-hisi_sas-support-the-property-of-signal-attenuation-for-v2-hw.patch93
-rw-r--r--patches.drivers/scsi-hisi_sas-terminate-stp-reject-quickly-for-v2-hw.patch127
-rw-r--r--patches.drivers/scsi-hisi_sas-try-wait-commands-before-before-controller-reset.patch148
-rw-r--r--patches.drivers/scsi-hisi_sas-update-phy-linkrate-after-a-controller-reset.patch181
-rw-r--r--patches.drivers/scsi-hisi_sas-update-ras-feature-for-later-revision-of-v3-hw.patch158
-rw-r--r--patches.drivers/scsi-hisi_sas-use-an-general-way-to-delay-phy-work.patch142
-rw-r--r--patches.drivers/scsi-hisi_sas-use-device-lock-to-protect-slot-alloc-free.patch246
-rw-r--r--patches.drivers/scsi-hisi_sas-use-dma_zalloc_coherent.patch38
-rw-r--r--patches.drivers/scsi-hisi_sas-workaround-a-v3-hw-hilink-bug.patch91
-rw-r--r--patches.drivers/scsi-lpfc-Add-Buffer-overflow-check-when-nvme_info-l.patch550
-rw-r--r--patches.drivers/scsi-lpfc-Correct-LCB-ACCept-payload.patch46
-rw-r--r--patches.drivers/scsi-lpfc-Fix-ELS-abort-on-SLI-3-adapters.patch89
-rw-r--r--patches.drivers/scsi-lpfc-Fix-NVME-Target-crash-in-defer-rcv-logic.patch61
-rw-r--r--patches.drivers/scsi-lpfc-Fix-abort-error-path-for-NVMET.patch94
-rw-r--r--patches.drivers/scsi-lpfc-Fix-driver-crash-when-re-registering-NVME-.patch109
-rw-r--r--patches.drivers/scsi-lpfc-Fix-driver-not-setting-dpp-bits-correctly-.patch54
-rw-r--r--patches.drivers/scsi-lpfc-Fix-list-corruption-on-the-completion-queu.patch143
-rw-r--r--patches.drivers/scsi-lpfc-Fix-panic-if-driver-unloaded-when-port-is-.patch50
-rw-r--r--patches.drivers/scsi-lpfc-Fix-sysfs-Speed-value-on-CNA-ports.patch52
-rw-r--r--patches.drivers/scsi-lpfc-Limit-tracking-of-tgt-queue-depth-in-fast-.patch325
-rw-r--r--patches.drivers/scsi-lpfc-Make-PBDE-optimizations-configurable.patch257
-rw-r--r--patches.drivers/scsi-lpfc-Remove-lpfc_enable_pbde-as-module-paramete.patch68
-rw-r--r--patches.drivers/scsi-lpfc-Revise-copyright-for-new-company-language.patch412
-rw-r--r--patches.drivers/scsi-lpfc-Support-duration-field-in-Link-Cable-Beaco.patch294
-rw-r--r--patches.drivers/scsi-lpfc-devloss-timeout-race-condition-caused-null.patch94
-rw-r--r--patches.drivers/scsi-lpfc-update-driver-version-to-12.0.0.5.patch34
-rw-r--r--patches.drivers/scsi-lpfc-update-driver-version-to-12.0.0.6.patch34
-rw-r--r--patches.drivers/scsi-smartpqi-add-in-new-supported-controllers.patch88
-rw-r--r--patches.drivers/scsi-smartpqi-add-inspur-advantech-ids.patch61
-rw-r--r--patches.drivers/scsi-smartpqi-bump-driver-version-to-1.1.4-130.patch38
-rw-r--r--patches.drivers/scsi-smartpqi-fix-critical-ARM-issue-reading-PQI-ind.patch224
-rw-r--r--patches.drivers/scsi-smartpqi-improve-error-checking-for-sync-reques.patch130
-rw-r--r--patches.drivers/scsi-smartpqi-improve-handling-for-sync-requests.patch125
-rw-r--r--patches.drivers/scsi-smartpqi-update-driver-version.patch40
-rw-r--r--patches.drivers/scsi-smartpqi-workaround-fw-bug-for-oq-deletion.patch100
-rw-r--r--patches.fixes/dax-check-for-queue_flag_dax-in-bdev_dax_supported.patch17
-rw-r--r--patches.fixes/dm-prevent-dax-mounts-if-not-supported.patch69
-rw-r--r--patches.fixes/fs-allow-per-device-dax-status-checking-for-filesystems.patch223
-rw-r--r--patches.fixes/libnvdimm-dimm-fix-dpa-reservation-vs-uninitialized-.patch53
-rw-r--r--patches.fixes/linvdimm-pmem-Preserve-read-only-setting-for-pmem-de.patch77
-rw-r--r--patches.fixes/nvme-fabrics-Ignore-nr_io_queues-option-for-discover.patch47
-rw-r--r--patches.fixes/nvme-fixup-crash-on-failed-discovery.patch34
-rw-r--r--patches.fixes/nvme-use-hw-qid-in-trace-events.patch214
-rw-r--r--patches.fixes/nvme.h-fixup-ANA-group-descriptor-format.patch35
-rw-r--r--patches.fixes/pmem-only-set-queue_flag_dax-for-fsdax-mode.patch37
-rw-r--r--patches.kabi/kabi-fixup-bdev_dax_supported.patch141
-rw-r--r--patches.suse/0201-dax-dm-allow-device-mapper-to-operate-without-dax-su.patch291
-rw-r--r--patches.suse/sched-fair-Consider-RT-IRQ-pressure-in-capacity_spare_wake.patch126
-rw-r--r--patches.suse/sched-fair-Fix-find_idlest_group-when-local-group-is-not-allowed.patch50
-rw-r--r--patches.suse/sched-fair-Fix-usage-of-find_idlest_group-when-no-groups-are-allowed.patch61
-rw-r--r--patches.suse/sched-fair-Fix-usage-of-find_idlest_group-when-the-local-group-is-idlest.patch49
-rw-r--r--patches.suse/sched-fair-Move-select_task_rq_fair-slow-path-into-its-own-function.patch147
-rw-r--r--patches.suse/sched-fair-Remove-impossible-condition-from-find_idlest_group_cpu.patch65
-rw-r--r--patches.suse/sched-fair-Remove-unnecessary-comparison-with-1.patch47
-rw-r--r--patches.suse/sched-fair-Restructure-wake_affine-to-return-a-CPU-id.patch2
-rw-r--r--patches.suse/sched-fair-Spare-idle-load-balancing-on-nohz_full-CPUs.patch46
-rw-r--r--patches.suse/sched-fair-Use-a-recently-used-CPU-as-an-idle-candidate-and-the-basis-for-SIS.patch6
-rw-r--r--patches.suse/sched-fair-Use-unsigned-long-for-utilization-consistently.patch86
-rw-r--r--patches.suse/xfs-unsupported-features.patch21
-rwxr-xr-xscripts/git_sort/git_sort.py5
-rw-r--r--series.conf131
-rw-r--r--supported.conf1
145 files changed, 14489 insertions, 369 deletions
diff --git a/config/arm64/default b/config/arm64/default
index 59fd3e15fb..521a32e044 100644
--- a/config/arm64/default
+++ b/config/arm64/default
@@ -3955,6 +3955,7 @@ CONFIG_PINCTRL_INTEL=m
CONFIG_PINCTRL_CANNONLAKE=m
# CONFIG_PINCTRL_DENVERTON is not set
# CONFIG_PINCTRL_GEMINILAKE is not set
+# CONFIG_PINCTRL_LEWISBURG is not set
# CONFIG_PINCTRL_SUNRISEPOINT is not set
CONFIG_PINCTRL_ARMADA_37XX=y
CONFIG_PINCTRL_MSM=y
@@ -4145,7 +4146,6 @@ CONFIG_AXP288_CHARGER=m
CONFIG_AXP288_FUEL_GAUGE=m
CONFIG_BATTERY_MAX17040=m
CONFIG_BATTERY_MAX17042=m
-CONFIG_CHARGER_CPCAP=m
CONFIG_CHARGER_ISP1704=m
CONFIG_CHARGER_MAX8903=m
CONFIG_CHARGER_LP8727=m
diff --git a/config/arm64/vanilla b/config/arm64/vanilla
index 5bfd3efcf5..b5b9a33132 100644
--- a/config/arm64/vanilla
+++ b/config/arm64/vanilla
@@ -1,5 +1,6 @@
CONFIG_BLK_CPQ_CISS_DA=m
# CONFIG_BLK_DEV_NVME_SCSI is not set
+CONFIG_CHARGER_CPCAP=m
# CONFIG_CISS_SCSI_TAPE is not set
# CONFIG_DEVKMEM is not set
# CONFIG_HAVE_ARCH_VMAP_STACK is not set
diff --git a/config/armv7hl/default b/config/armv7hl/default
index dfe6dc1770..3065eea9ac 100644
--- a/config/armv7hl/default
+++ b/config/armv7hl/default
@@ -7857,7 +7857,6 @@ CONFIG_KEYSTONE_NAVIGATOR_DMA=m
# CONFIG_WKUP_M3_IPC is not set
CONFIG_TI_SCI_PM_DOMAINS=m
CONFIG_UX500_SOC_ID=y
-# CONFIG_SOC_ZTE is not set
CONFIG_PM_DEVFREQ=y
#
diff --git a/config/armv7hl/lpae b/config/armv7hl/lpae
index d5c44236bd..ee7c13e5d1 100644
--- a/config/armv7hl/lpae
+++ b/config/armv7hl/lpae
@@ -7512,7 +7512,6 @@ CONFIG_SOC_TI=y
# CONFIG_KEYSTONE_NAVIGATOR_QMSS is not set
CONFIG_KEYSTONE_NAVIGATOR_DMA=m
CONFIG_TI_SCI_PM_DOMAINS=m
-# CONFIG_SOC_ZTE is not set
CONFIG_PM_DEVFREQ=y
#
diff --git a/config/armv7hl/vanilla b/config/armv7hl/vanilla
index 062f53f2ed..b415608c9b 100644
--- a/config/armv7hl/vanilla
+++ b/config/armv7hl/vanilla
@@ -5,6 +5,7 @@ CONFIG_CHECK_SIGNATURE=y
# CONFIG_INTEL_SOC_PMIC is not set
CONFIG_LOCALVERSION="-vanilla"
CONFIG_MMC_QCOM_DML=m
+# CONFIG_SOC_ZTE is not set
# CONFIG_TREE_RCU_TRACE is not set
CONFIG_MODULES=y
# CONFIG_MODULE_SIG is not set
diff --git a/config/ppc64le/default b/config/ppc64le/default
index dbc9c40cdf..7280d61373 100644
--- a/config/ppc64le/default
+++ b/config/ppc64le/default
@@ -5756,7 +5756,6 @@ CONFIG_REMOTEPROC=m
#
# CONFIG_SUNXI_SRAM is not set
# CONFIG_SOC_TI is not set
-# CONFIG_SOC_ZTE is not set
CONFIG_PM_DEVFREQ=y
#
diff --git a/config/ppc64le/vanilla b/config/ppc64le/vanilla
index b2ec9f8756..391ab4647f 100644
--- a/config/ppc64le/vanilla
+++ b/config/ppc64le/vanilla
@@ -8,6 +8,7 @@ CONFIG_PPC_ICSWX=y
CONFIG_PPC_ICSWX_PID=y
# CONFIG_PPC_ICSWX_USE_SIGILL is not set
CONFIG_PPC_STD_MMU_64=y
+# CONFIG_SOC_ZTE is not set
CONFIG_TREE_RCU_TRACE=y
CONFIG_MODULES=y
# CONFIG_MODULE_SIG is not set
diff --git a/config/s390x/default b/config/s390x/default
index da4620b00d..187d4992cb 100644
--- a/config/s390x/default
+++ b/config/s390x/default
@@ -2517,31 +2517,9 @@ CONFIG_S390_IOMMU=y
#
# CONFIG_SUNXI_SRAM is not set
# CONFIG_SOC_TI is not set
-# CONFIG_SOC_ZTE is not set
-CONFIG_PM_DEVFREQ=y
-
-#
-# DEVFREQ Governors
-#
-CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=m
-CONFIG_DEVFREQ_GOV_PERFORMANCE=m
-CONFIG_DEVFREQ_GOV_POWERSAVE=m
-CONFIG_DEVFREQ_GOV_USERSPACE=m
-CONFIG_DEVFREQ_GOV_PASSIVE=m
-
-#
-# DEVFREQ Drivers
-#
-CONFIG_PM_DEVFREQ_EVENT=y
-CONFIG_EXTCON=y
-
-#
-# Extcon Device Drivers
-#
-# CONFIG_EXTCON_QCOM_SPMI_MISC is not set
-# CONFIG_EXTCON_RT8973A is not set
-# CONFIG_EXTCON_SM5502 is not set
-CONFIG_MEMORY=y
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
# CONFIG_IIO is not set
# CONFIG_NTB is not set
# CONFIG_VME_BUS is not set
diff --git a/config/s390x/vanilla b/config/s390x/vanilla
index d1624bf7f1..38e04efb2c 100644
--- a/config/s390x/vanilla
+++ b/config/s390x/vanilla
@@ -4,6 +4,7 @@ CONFIG_CHECK_SIGNATURE=y
# CONFIG_CISS_SCSI_TAPE is not set
# CONFIG_DP83867_PHY is not set
CONFIG_LOCALVERSION="-vanilla"
+# CONFIG_SOC_ZTE is not set
CONFIG_TREE_RCU_TRACE=y
CONFIG_MODULES=y
# CONFIG_MODULE_SIG is not set
diff --git a/config/s390x/zfcpdump b/config/s390x/zfcpdump
index c6a491ab9e..23e799cb96 100644
--- a/config/s390x/zfcpdump
+++ b/config/s390x/zfcpdump
@@ -884,7 +884,6 @@ CONFIG_VIRTIO=y
#
# CONFIG_SUNXI_SRAM is not set
# CONFIG_SOC_TI is not set
-# CONFIG_SOC_ZTE is not set
# CONFIG_PM_DEVFREQ is not set
CONFIG_EXTCON=y
diff --git a/config/x86_64/default b/config/x86_64/default
index 1529e680ef..b888841186 100644
--- a/config/x86_64/default
+++ b/config/x86_64/default
@@ -4108,6 +4108,7 @@ CONFIG_PINCTRL_BROXTON=m
CONFIG_PINCTRL_CANNONLAKE=m
CONFIG_PINCTRL_DENVERTON=m
CONFIG_PINCTRL_GEMINILAKE=m
+CONFIG_PINCTRL_LEWISBURG=m
CONFIG_PINCTRL_SUNRISEPOINT=m
CONFIG_GPIOLIB=y
CONFIG_GPIO_ACPI=y
@@ -6983,7 +6984,6 @@ CONFIG_REMOTEPROC=m
#
# CONFIG_SUNXI_SRAM is not set
# CONFIG_SOC_TI is not set
-# CONFIG_SOC_ZTE is not set
CONFIG_PM_DEVFREQ=y
#
diff --git a/config/x86_64/vanilla b/config/x86_64/vanilla
index e38b98c02d..dffacad463 100644
--- a/config/x86_64/vanilla
+++ b/config/x86_64/vanilla
@@ -9,6 +9,7 @@ CONFIG_HFI1_VERBS_31BIT_PSN=y
CONFIG_INTEL_RDT_A=y
# CONFIG_KEXEC_VERIFY_SIG is not set
CONFIG_LOCALVERSION="-vanilla"
+# CONFIG_SOC_ZTE is not set
CONFIG_TREE_RCU_TRACE=y
CONFIG_UCSI=m
CONFIG_MODULES=y
diff --git a/kabi/severities b/kabi/severities
index 8ef0fda35b..4724ec7c86 100644
--- a/kabi/severities
+++ b/kabi/severities
@@ -35,6 +35,7 @@ drivers/infiniband/hw/qede/* PASS
drivers/scsi/qedf/* PASS
drivers/scsi/qedi/* PASS
include/linux/qed/* PASS
+drivers/scsi/hisi_sas/* PASS
# only inter-module local symbols
drivers/nvdimm/btt.h PASS
diff --git a/patches.drivers/clk-at91-fix-clk-generated-compilation b/patches.drivers/clk-at91-fix-clk-generated-compilation
new file mode 100644
index 0000000000..3adcf6b42e
--- /dev/null
+++ b/patches.drivers/clk-at91-fix-clk-generated-compilation
@@ -0,0 +1,33 @@
+From 4a5f06a01cfd1f7a9141bdb760bf5b68cca7f224 Mon Sep 17 00:00:00 2001
+From: Alexandre Belloni <alexandre.belloni@free-electrons.com>
+Date: Mon, 5 Jun 2017 00:02:57 +0200
+Subject: [PATCH] clk: at91: fix clk-generated compilation
+Git-commit: 4a5f06a01cfd1f7a9141bdb760bf5b68cca7f224
+Patch-mainline: v4.13-rc1
+References: bsc#1051510
+
+Fix missing }
+
+Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+Acked-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ drivers/clk/at91/clk-generated.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c
+index 70474bd97a10..07c8f701e51c 100644
+--- a/drivers/clk/at91/clk-generated.c
++++ b/drivers/clk/at91/clk-generated.c
+@@ -266,6 +266,7 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
+ if (ret) {
+ kfree(gck);
+ hw = ERR_PTR(ret);
++ }
+
+ return hw;
+ }
+--
+2.18.0
+
diff --git a/patches.drivers/ibmvnic-Remove-code-to-request-error-information.patch b/patches.drivers/ibmvnic-Remove-code-to-request-error-information.patch
new file mode 100644
index 0000000000..5d19a52db7
--- /dev/null
+++ b/patches.drivers/ibmvnic-Remove-code-to-request-error-information.patch
@@ -0,0 +1,292 @@
+From 79dabbb7161f43ed29ca888a2488f59e47171aee Mon Sep 17 00:00:00 2001
+From: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
+Date: Mon, 6 Aug 2018 21:39:58 -0500
+Subject: [PATCH] ibmvnic: Remove code to request error information
+
+References: bsc#1104174
+Patch-mainline: queued
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
+Git-commit: 79dabbb7161f43ed29ca888a2488f59e47171aee
+
+When backing device firmware reports an error, it provides an
+error ID, which is meant to be queried for more detailed error
+information. Currently, however, an error ID is not provided by
+the Virtual I/O server and there are not any plans to do so. For
+now, it is always unfilled or zero, so request_error_information
+will never be called. Remove it.
+
+Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Acked-by: Michal Suchanek <msuchanek@suse.de>
+---
+ drivers/net/ethernet/ibm/ibmvnic.c | 144 +------------------------------------
+ drivers/net/ethernet/ibm/ibmvnic.h | 33 ---------
+ 2 files changed, 1 insertion(+), 176 deletions(-)
+
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
+index ffe7acbeaa22..109e4a58efad 100644
+--- a/drivers/net/ethernet/ibm/ibmvnic.c
++++ b/drivers/net/ethernet/ibm/ibmvnic.c
+@@ -718,23 +718,6 @@ static int init_tx_pools(struct net_device *netdev)
+ return 0;
+ }
+
+-static void release_error_buffers(struct ibmvnic_adapter *adapter)
+-{
+- struct device *dev = &adapter->vdev->dev;
+- struct ibmvnic_error_buff *error_buff, *tmp;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&adapter->error_list_lock, flags);
+- list_for_each_entry_safe(error_buff, tmp, &adapter->errors, list) {
+- list_del(&error_buff->list);
+- dma_unmap_single(dev, error_buff->dma, error_buff->len,
+- DMA_FROM_DEVICE);
+- kfree(error_buff->buff);
+- kfree(error_buff);
+- }
+- spin_unlock_irqrestore(&adapter->error_list_lock, flags);
+-}
+-
+ static void ibmvnic_napi_enable(struct ibmvnic_adapter *adapter)
+ {
+ int i;
+@@ -896,7 +879,6 @@ static void release_resources(struct ibmvnic_adapter *adapter)
+ release_tx_pools(adapter);
+ release_rx_pools(adapter);
+
+- release_error_buffers(adapter);
+ release_napi(adapter);
+ release_login_rsp_buffer(adapter);
+ }
+@@ -3843,133 +3825,16 @@ static void handle_query_ip_offload_rsp(struct ibmvnic_adapter *adapter)
+ ibmvnic_send_crq(adapter, &crq);
+ }
+
+-static void handle_error_info_rsp(union ibmvnic_crq *crq,
+- struct ibmvnic_adapter *adapter)
+-{
+- struct device *dev = &adapter->vdev->dev;
+- struct ibmvnic_error_buff *error_buff, *tmp;
+- unsigned long flags;
+- bool found = false;
+- int i;
+-
+- if (!crq->request_error_rsp.rc.code) {
+- dev_info(dev, "Request Error Rsp returned with rc=%x\n",
+- crq->request_error_rsp.rc.code);
+- return;
+- }
+-
+- spin_lock_irqsave(&adapter->error_list_lock, flags);
+- list_for_each_entry_safe(error_buff, tmp, &adapter->errors, list)
+- if (error_buff->error_id == crq->request_error_rsp.error_id) {
+- found = true;
+- list_del(&error_buff->list);
+- break;
+- }
+- spin_unlock_irqrestore(&adapter->error_list_lock, flags);
+-
+- if (!found) {
+- dev_err(dev, "Couldn't find error id %x\n",
+- be32_to_cpu(crq->request_error_rsp.error_id));
+- return;
+- }
+-
+- dev_err(dev, "Detailed info for error id %x:",
+- be32_to_cpu(crq->request_error_rsp.error_id));
+-
+- for (i = 0; i < error_buff->len; i++) {
+- pr_cont("%02x", (int)error_buff->buff[i]);
+- if (i % 8 == 7)
+- pr_cont(" ");
+- }
+- pr_cont("\n");
+-
+- dma_unmap_single(dev, error_buff->dma, error_buff->len,
+- DMA_FROM_DEVICE);
+- kfree(error_buff->buff);
+- kfree(error_buff);
+-}
+-
+-static void request_error_information(struct ibmvnic_adapter *adapter,
+- union ibmvnic_crq *err_crq)
+-{
+- struct device *dev = &adapter->vdev->dev;
+- struct net_device *netdev = adapter->netdev;
+- struct ibmvnic_error_buff *error_buff;
+- unsigned long timeout = msecs_to_jiffies(30000);
+- union ibmvnic_crq crq;
+- unsigned long flags;
+- int rc, detail_len;
+-
+- error_buff = kmalloc(sizeof(*error_buff), GFP_ATOMIC);
+- if (!error_buff)
+- return;
+-
+- detail_len = be32_to_cpu(err_crq->error_indication.detail_error_sz);
+- error_buff->buff = kmalloc(detail_len, GFP_ATOMIC);
+- if (!error_buff->buff) {
+- kfree(error_buff);
+- return;
+- }
+-
+- error_buff->dma = dma_map_single(dev, error_buff->buff, detail_len,
+- DMA_FROM_DEVICE);
+- if (dma_mapping_error(dev, error_buff->dma)) {
+- netdev_err(netdev, "Couldn't map error buffer\n");
+- kfree(error_buff->buff);
+- kfree(error_buff);
+- return;
+- }
+-
+- error_buff->len = detail_len;
+- error_buff->error_id = err_crq->error_indication.error_id;
+-
+- spin_lock_irqsave(&adapter->error_list_lock, flags);
+- list_add_tail(&error_buff->list, &adapter->errors);
+- spin_unlock_irqrestore(&adapter->error_list_lock, flags);
+-
+- memset(&crq, 0, sizeof(crq));
+- crq.request_error_info.first = IBMVNIC_CRQ_CMD;
+- crq.request_error_info.cmd = REQUEST_ERROR_INFO;
+- crq.request_error_info.ioba = cpu_to_be32(error_buff->dma);
+- crq.request_error_info.len = cpu_to_be32(detail_len);
+- crq.request_error_info.error_id = err_crq->error_indication.error_id;
+-
+- rc = ibmvnic_send_crq(adapter, &crq);
+- if (rc) {
+- netdev_err(netdev, "failed to request error information\n");
+- goto err_info_fail;
+- }
+-
+- if (!wait_for_completion_timeout(&adapter->init_done, timeout)) {
+- netdev_err(netdev, "timeout waiting for error information\n");
+- goto err_info_fail;
+- }
+-
+- return;
+-
+-err_info_fail:
+- spin_lock_irqsave(&adapter->error_list_lock, flags);
+- list_del(&error_buff->list);
+- spin_unlock_irqrestore(&adapter->error_list_lock, flags);
+-
+- kfree(error_buff->buff);
+- kfree(error_buff);
+-}
+-
+ static void handle_error_indication(union ibmvnic_crq *crq,
+ struct ibmvnic_adapter *adapter)
+ {
+ struct device *dev = &adapter->vdev->dev;
+
+- dev_err(dev, "Firmware reports %serror id %x, cause %d\n",
++ dev_err(dev, "Firmware reports %serror, cause %d\n",
+ crq->error_indication.flags
+ & IBMVNIC_FATAL_ERROR ? "FATAL " : "",
+- be32_to_cpu(crq->error_indication.error_id),
+ be16_to_cpu(crq->error_indication.error_cause));
+
+- if (be32_to_cpu(crq->error_indication.error_id))
+- request_error_information(adapter, crq);
+-
+ if (crq->error_indication.flags & IBMVNIC_FATAL_ERROR)
+ ibmvnic_reset(adapter, VNIC_RESET_FATAL);
+ else
+@@ -4468,10 +4333,6 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
+ netdev_dbg(netdev, "Got Error Indication\n");
+ handle_error_indication(crq, adapter);
+ break;
+- case REQUEST_ERROR_RSP:
+- netdev_dbg(netdev, "Got Error Detail Response\n");
+- handle_error_info_rsp(crq, adapter);
+- break;
+ case REQUEST_STATISTICS_RSP:
+ netdev_dbg(netdev, "Got Statistics Response\n");
+ complete(&adapter->stats_done);
+@@ -4830,9 +4691,6 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
+
+ spin_lock_init(&adapter->stats_lock);
+
+- INIT_LIST_HEAD(&adapter->errors);
+- spin_lock_init(&adapter->error_list_lock);
+-
+ INIT_WORK(&adapter->ibmvnic_reset, __ibmvnic_reset);
+ INIT_LIST_HEAD(&adapter->rwi_list);
+ mutex_init(&adapter->reset_lock);
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/ethernet/ibm/ibmvnic.h
+index f9fb780102ac..f06eec145ca6 100644
+--- a/drivers/net/ethernet/ibm/ibmvnic.h
++++ b/drivers/net/ethernet/ibm/ibmvnic.h
+@@ -512,24 +512,6 @@ struct ibmvnic_error_indication {
+ u8 reserved2[2];
+ } __packed __aligned(8);
+
+-struct ibmvnic_request_error_info {
+- u8 first;
+- u8 cmd;
+- u8 reserved[2];
+- __be32 ioba;
+- __be32 len;
+- __be32 error_id;
+-} __packed __aligned(8);
+-
+-struct ibmvnic_request_error_rsp {
+- u8 first;
+- u8 cmd;
+- u8 reserved[2];
+- __be32 error_id;
+- __be32 len;
+- struct ibmvnic_rc rc;
+-} __packed __aligned(8);
+-
+ struct ibmvnic_link_state_indication {
+ u8 first;
+ u8 cmd;
+@@ -709,8 +691,6 @@ union ibmvnic_crq {
+ struct ibmvnic_request_debug_stats request_debug_stats;
+ struct ibmvnic_request_debug_stats request_debug_stats_rsp;
+ struct ibmvnic_error_indication error_indication;
+- struct ibmvnic_request_error_info request_error_info;
+- struct ibmvnic_request_error_rsp request_error_rsp;
+ struct ibmvnic_link_state_indication link_state_indication;
+ struct ibmvnic_change_mac_addr change_mac_addr;
+ struct ibmvnic_change_mac_addr change_mac_addr_rsp;
+@@ -809,8 +789,6 @@ enum ibmvnic_commands {
+ SET_PHYS_PARMS = 0x07,
+ SET_PHYS_PARMS_RSP = 0x87,
+ ERROR_INDICATION = 0x08,
+- REQUEST_ERROR_INFO = 0x09,
+- REQUEST_ERROR_RSP = 0x89,
+ LOGICAL_LINK_STATE = 0x0C,
+ LOGICAL_LINK_STATE_RSP = 0x8C,
+ REQUEST_STATISTICS = 0x0D,
+@@ -945,14 +923,6 @@ struct ibmvnic_rx_pool {
+ struct ibmvnic_long_term_buff long_term_buff;
+ };
+
+-struct ibmvnic_error_buff {
+- char *buff;
+- dma_addr_t dma;
+- int len;
+- struct list_head list;
+- __be32 error_id;
+-};
+-
+ struct ibmvnic_vpd {
+ unsigned char *buff;
+ dma_addr_t dma_addr;
+@@ -1047,9 +1017,6 @@ struct ibmvnic_adapter {
+ struct completion init_done;
+ int init_done_rc;
+
+- struct list_head errors;
+- spinlock_t error_list_lock;
+-
+ struct completion fw_done;
+ int fw_done_rc;
+
+--
+2.13.7
+
diff --git a/patches.drivers/ibmvnic-Revise-RX-TX-queue-error-messages.patch b/patches.drivers/ibmvnic-Revise-RX-TX-queue-error-messages.patch
new file mode 100644
index 0000000000..fff3f0c3af
--- /dev/null
+++ b/patches.drivers/ibmvnic-Revise-RX-TX-queue-error-messages.patch
@@ -0,0 +1,107 @@
+From 2d14d3795294d42aacc278948984a480569bcc23 Mon Sep 17 00:00:00 2001
+From: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
+Date: Fri, 13 Jul 2018 12:03:32 -0500
+Subject: [PATCH] ibmvnic: Revise RX/TX queue error messages
+
+References: bsc#1101331
+Patch-mainline: v4.18-rc6
+Git-commit: 2d14d3795294d42aacc278948984a480569bcc23
+
+During a device failover, there may be latency between the loss
+of the current backing device and a notification from firmware that
+a failover has occurred. This latency can result in a large amount of
+error printouts as firmware returns outgoing traffic with a generic
+error code. These are not necessarily errors in this case as the
+firmware is busy swapping in a new backing adapter and is not ready
+to send packets yet. This patch reclassifies those error codes as
+warnings with an explanation that a failover may be pending. All
+other return codes will be considered errors.
+
+Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Acked-by: Michal Suchanek <msuchanek@suse.de>
+---
+ drivers/net/ethernet/ibm/ibmvnic.c | 39 ++++++++++++++++++++++++++------------
+ 1 file changed, 27 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
+index d0e196bff081..c50963680f30 100644
+--- a/drivers/net/ethernet/ibm/ibmvnic.c
++++ b/drivers/net/ethernet/ibm/ibmvnic.c
+@@ -329,7 +329,8 @@ static void replenish_rx_pool(struct ibmvnic_adapter *adapter,
+ return;
+
+ failure:
+- dev_info(dev, "replenish pools failure\n");
++ if (lpar_rc != H_PARAMETER && lpar_rc != H_CLOSED)
++ dev_err_ratelimited(dev, "rx: replenish packet buffer failed\n");
+ pool->free_map[pool->next_free] = index;
+ pool->rx_buff[index].skb = NULL;
+
+@@ -1617,7 +1618,8 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
+ &tx_crq);
+ }
+ if (lpar_rc != H_SUCCESS) {
+- dev_err(dev, "tx failed with code %ld\n", lpar_rc);
++ if (lpar_rc != H_CLOSED && lpar_rc != H_PARAMETER)
++ dev_err_ratelimited(dev, "tx: send failed\n");
+ dev_kfree_skb_any(skb);
+ tx_buff->skb = NULL;
+
+@@ -3204,6 +3206,25 @@ static union ibmvnic_crq *ibmvnic_next_crq(struct ibmvnic_adapter *adapter)
+ return crq;
+ }
+
++static void print_subcrq_error(struct device *dev, int rc, const char *func)
++{
++ switch (rc) {
++ case H_PARAMETER:
++ dev_warn_ratelimited(dev,
++ "%s failed: Send request is malformed or adapter failover pending. (rc=%d)\n",
++ func, rc);
++ break;
++ case H_CLOSED:
++ dev_warn_ratelimited(dev,
++ "%s failed: Backing queue closed. Adapter is down or failover pending. (rc=%d)\n",
++ func, rc);
++ break;
++ default:
++ dev_err_ratelimited(dev, "%s failed: (rc=%d)\n", func, rc);
++ break;
++ }
++}
++
+ static int send_subcrq(struct ibmvnic_adapter *adapter, u64 remote_handle,
+ union sub_crq *sub_crq)
+ {
+@@ -3230,11 +3251,8 @@ static int send_subcrq(struct ibmvnic_adapter *adapter, u64 remote_handle,
+ cpu_to_be64(u64_crq[2]),
+ cpu_to_be64(u64_crq[3]));
+
+- if (rc) {
+- if (rc == H_CLOSED)
+- dev_warn(dev, "CRQ Queue closed\n");
+- dev_err(dev, "Send error (rc=%d)\n", rc);
+- }
++ if (rc)
++ print_subcrq_error(dev, rc, __func__);
+
+ return rc;
+ }
+@@ -3252,11 +3270,8 @@ static int send_subcrq_indirect(struct ibmvnic_adapter *adapter,
+ cpu_to_be64(remote_handle),
+ ioba, num_entries);
+
+- if (rc) {
+- if (rc == H_CLOSED)
+- dev_warn(dev, "CRQ Queue closed\n");
+- dev_err(dev, "Send (indirect) error (rc=%d)\n", rc);
+- }
++ if (rc)
++ print_subcrq_error(dev, rc, __func__);
+
+ return rc;
+ }
+--
+2.13.7
+
diff --git a/patches.drivers/ibmvnic-Update-firmware-error-reporting-with-cause-s.patch b/patches.drivers/ibmvnic-Update-firmware-error-reporting-with-cause-s.patch
new file mode 100644
index 0000000000..5bf44ade54
--- /dev/null
+++ b/patches.drivers/ibmvnic-Update-firmware-error-reporting-with-cause-s.patch
@@ -0,0 +1,74 @@
+From c9008d339bc40301a486ea62f36f106c4b2aad0e Mon Sep 17 00:00:00 2001
+From: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
+Date: Mon, 6 Aug 2018 21:39:59 -0500
+Subject: [PATCH] ibmvnic: Update firmware error reporting with cause string
+
+References: bsc#1104174
+Patch-mainline: queued
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
+Git-commit: c9008d339bc40301a486ea62f36f106c4b2aad0e
+
+Print a string instead of the error code. Since there is a
+possibility that the driver can recover, classify it as a
+warning instead of an error.
+
+Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Acked-by: Michal Suchanek <msuchanek@suse.de>
+---
+ drivers/net/ethernet/ibm/ibmvnic.c | 34 ++++++++++++++++++++++++++++++----
+ 1 file changed, 30 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
+index 109e4a58efad..dafdd4ade705 100644
+--- a/drivers/net/ethernet/ibm/ibmvnic.c
++++ b/drivers/net/ethernet/ibm/ibmvnic.c
+@@ -3825,15 +3825,41 @@ static void handle_query_ip_offload_rsp(struct ibmvnic_adapter *adapter)
+ ibmvnic_send_crq(adapter, &crq);
+ }
+
++static const char *ibmvnic_fw_err_cause(u16 cause)
++{
++ switch (cause) {
++ case ADAPTER_PROBLEM:
++ return "adapter problem";
++ case BUS_PROBLEM:
++ return "bus problem";
++ case FW_PROBLEM:
++ return "firmware problem";
++ case DD_PROBLEM:
++ return "device driver problem";
++ case EEH_RECOVERY:
++ return "EEH recovery";
++ case FW_UPDATED:
++ return "firmware updated";
++ case LOW_MEMORY:
++ return "low Memory";
++ default:
++ return "unknown";
++ }
++}
++
+ static void handle_error_indication(union ibmvnic_crq *crq,
+ struct ibmvnic_adapter *adapter)
+ {
+ struct device *dev = &adapter->vdev->dev;
++ u16 cause;
++
++ cause = be16_to_cpu(crq->error_indication.error_cause);
+
+- dev_err(dev, "Firmware reports %serror, cause %d\n",
+- crq->error_indication.flags
+- & IBMVNIC_FATAL_ERROR ? "FATAL " : "",
+- be16_to_cpu(crq->error_indication.error_cause));
++ dev_warn_ratelimited(dev,
++ "Firmware reports %serror, cause: %s. Starting recovery...\n",
++ crq->error_indication.flags
++ & IBMVNIC_FATAL_ERROR ? "FATAL " : "",
++ ibmvnic_fw_err_cause(cause));
+
+ if (crq->error_indication.flags & IBMVNIC_FATAL_ERROR)
+ ibmvnic_reset(adapter, VNIC_RESET_FATAL);
+--
+2.13.7
+
diff --git a/patches.drivers/pinctrl-intel-Add-Intel-Lewisburg-GPIO-support.patch b/patches.drivers/pinctrl-intel-Add-Intel-Lewisburg-GPIO-support.patch
new file mode 100644
index 0000000000..d5d213a58f
--- /dev/null
+++ b/patches.drivers/pinctrl-intel-Add-Intel-Lewisburg-GPIO-support.patch
@@ -0,0 +1,404 @@
+From e480b745386e3911c45e5b281f3471c7aff8cc3b Mon Sep 17 00:00:00 2001
+From: Mika Westerberg <mika.westerberg@linux.intel.com>
+Date: Fri, 18 Aug 2017 13:05:55 +0300
+Subject: [PATCH] pinctrl: intel: Add Intel Lewisburg GPIO support
+Git-commit: e480b745386e3911c45e5b281f3471c7aff8cc3b
+Patch-mainline: v4.14-rc1
+References: FATE#325120
+
+Intel Lewisburg has the same GPIO hardware than Intel Sunrisepoint-H
+except few differences in register offsets and pin lists. Because of
+this we add a separate pinctrl driver for Lewisburg.
+
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Acked-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ drivers/pinctrl/intel/Kconfig | 8 +
+ drivers/pinctrl/intel/Makefile | 1 +
+ drivers/pinctrl/intel/pinctrl-lewisburg.c | 343 ++++++++++++++++++++++
+ 3 files changed, 352 insertions(+)
+ create mode 100644 drivers/pinctrl/intel/pinctrl-lewisburg.c
+
+diff --git a/drivers/pinctrl/intel/Kconfig b/drivers/pinctrl/intel/Kconfig
+index 9613c2a9e2b3..f30720a752f3 100644
+--- a/drivers/pinctrl/intel/Kconfig
++++ b/drivers/pinctrl/intel/Kconfig
+@@ -81,6 +81,14 @@ config PINCTRL_GEMINILAKE
+ This pinctrl driver provides an interface that allows configuring
+ of Intel Gemini Lake SoC pins and using them as GPIOs.
+
++config PINCTRL_LEWISBURG
++ tristate "Intel Lewisburg pinctrl and GPIO driver"
++ depends on ACPI
++ select PINCTRL_INTEL
++ help
++ This pinctrl driver provides an interface that allows configuring
++ of Intel Lewisburg pins and using them as GPIOs.
++
+ config PINCTRL_SUNRISEPOINT
+ tristate "Intel Sunrisepoint pinctrl and GPIO driver"
+ depends on ACPI
+diff --git a/drivers/pinctrl/intel/Makefile b/drivers/pinctrl/intel/Makefile
+index d9b31f7e2b1b..c12874da5992 100644
+--- a/drivers/pinctrl/intel/Makefile
++++ b/drivers/pinctrl/intel/Makefile
+@@ -8,4 +8,5 @@ obj-$(CONFIG_PINCTRL_BROXTON) += pinctrl-broxton.o
+ obj-$(CONFIG_PINCTRL_CANNONLAKE) += pinctrl-cannonlake.o
+ obj-$(CONFIG_PINCTRL_DENVERTON) += pinctrl-denverton.o
+ obj-$(CONFIG_PINCTRL_GEMINILAKE) += pinctrl-geminilake.o
++obj-$(CONFIG_PINCTRL_LEWISBURG) += pinctrl-lewisburg.o
+ obj-$(CONFIG_PINCTRL_SUNRISEPOINT) += pinctrl-sunrisepoint.o
+diff --git a/drivers/pinctrl/intel/pinctrl-lewisburg.c b/drivers/pinctrl/intel/pinctrl-lewisburg.c
+new file mode 100644
+index 000000000000..14d56ea6cfdc
+--- /dev/null
++++ b/drivers/pinctrl/intel/pinctrl-lewisburg.c
+@@ -0,0 +1,343 @@
++/*
++ * Intel Lewisburg pinctrl/GPIO driver
++ *
++ * Copyright (C) 2017, Intel Corporation
++ * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/acpi.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/pm.h>
++#include <linux/pinctrl/pinctrl.h>
++
++#include "pinctrl-intel.h"
++
++#define LBG_PAD_OWN 0x020
++#define LBG_PADCFGLOCK 0x060
++#define LBG_HOSTSW_OWN 0x080
++#define LBG_GPI_IE 0x110
++
++#define LBG_COMMUNITY(b, s, e) \
++ { \
++ .barno = (b), \
++ .padown_offset = LBG_PAD_OWN, \
++ .padcfglock_offset = LBG_PADCFGLOCK, \
++ .hostown_offset = LBG_HOSTSW_OWN, \
++ .ie_offset = LBG_GPI_IE, \
++ .gpp_size = 24, \
++ .pin_base = (s), \
++ .npins = ((e) - (s) + 1), \
++ }
++
++static const struct pinctrl_pin_desc lbg_pins[] = {
++ /* GPP_A */
++ PINCTRL_PIN(0, "RCINB"),
++ PINCTRL_PIN(1, "LAD_0"),
++ PINCTRL_PIN(2, "LAD_1"),
++ PINCTRL_PIN(3, "LAD_2"),
++ PINCTRL_PIN(4, "LAD_3"),
++ PINCTRL_PIN(5, "LFRAMEB"),
++ PINCTRL_PIN(6, "SERIRQ"),
++ PINCTRL_PIN(7, "PIRQAB"),
++ PINCTRL_PIN(8, "CLKRUNB"),
++ PINCTRL_PIN(9, "CLKOUT_LPC_0"),
++ PINCTRL_PIN(10, "CLKOUT_LPC_1"),
++ PINCTRL_PIN(11, "PMEB"),
++ PINCTRL_PIN(12, "BM_BUSYB"),
++ PINCTRL_PIN(13, "SUSWARNB_SUSPWRDNACK"),
++ PINCTRL_PIN(14, "ESPI_RESETB"),
++ PINCTRL_PIN(15, "SUSACKB"),
++ PINCTRL_PIN(16, "CLKOUT_LPC_2"),
++ PINCTRL_PIN(17, "GPP_A_17"),
++ PINCTRL_PIN(18, "GPP_A_18"),
++ PINCTRL_PIN(19, "GPP_A_19"),
++ PINCTRL_PIN(20, "GPP_A_20"),
++ PINCTRL_PIN(21, "GPP_A_21"),
++ PINCTRL_PIN(22, "GPP_A_22"),
++ PINCTRL_PIN(23, "GPP_A_23"),
++ /* GPP_B */
++ PINCTRL_PIN(24, "CORE_VID_0"),
++ PINCTRL_PIN(25, "CORE_VID_1"),
++ PINCTRL_PIN(26, "VRALERTB"),
++ PINCTRL_PIN(27, "CPU_GP_2"),
++ PINCTRL_PIN(28, "CPU_GP_3"),
++ PINCTRL_PIN(29, "SRCCLKREQB_0"),
++ PINCTRL_PIN(30, "SRCCLKREQB_1"),
++ PINCTRL_PIN(31, "SRCCLKREQB_2"),
++ PINCTRL_PIN(32, "SRCCLKREQB_3"),
++ PINCTRL_PIN(33, "SRCCLKREQB_4"),
++ PINCTRL_PIN(34, "SRCCLKREQB_5"),
++ PINCTRL_PIN(35, "GPP_B_11"),
++ PINCTRL_PIN(36, "GLB_RST_WARN_N"),
++ PINCTRL_PIN(37, "PLTRSTB"),
++ PINCTRL_PIN(38, "SPKR"),
++ PINCTRL_PIN(39, "GPP_B_15"),
++ PINCTRL_PIN(40, "GPP_B_16"),
++ PINCTRL_PIN(41, "GPP_B_17"),
++ PINCTRL_PIN(42, "GPP_B_18"),
++ PINCTRL_PIN(43, "GPP_B_19"),
++ PINCTRL_PIN(44, "GPP_B_20"),
++ PINCTRL_PIN(45, "GPP_B_21"),
++ PINCTRL_PIN(46, "GPP_B_22"),
++ PINCTRL_PIN(47, "SML1ALERTB"),
++ /* GPP_F */
++ PINCTRL_PIN(48, "SATAXPCIE_3"),
++ PINCTRL_PIN(49, "SATAXPCIE_4"),
++ PINCTRL_PIN(50, "SATAXPCIE_5"),
++ PINCTRL_PIN(51, "SATAXPCIE_6"),
++ PINCTRL_PIN(52, "SATAXPCIE_7"),
++ PINCTRL_PIN(53, "SATA_DEVSLP_3"),
++ PINCTRL_PIN(54, "SATA_DEVSLP_4"),
++ PINCTRL_PIN(55, "SATA_DEVSLP_5"),
++ PINCTRL_PIN(56, "SATA_DEVSLP_6"),
++ PINCTRL_PIN(57, "SATA_DEVSLP_7"),
++ PINCTRL_PIN(58, "SATA_SCLOCK"),
++ PINCTRL_PIN(59, "SATA_SLOAD"),
++ PINCTRL_PIN(60, "SATA_SDATAOUT1"),
++ PINCTRL_PIN(61, "SATA_SDATAOUT0"),
++ PINCTRL_PIN(62, "SSATA_LEDB"),
++ PINCTRL_PIN(63, "USB2_OCB_4"),
++ PINCTRL_PIN(64, "USB2_OCB_5"),
++ PINCTRL_PIN(65, "USB2_OCB_6"),
++ PINCTRL_PIN(66, "USB2_OCB_7"),
++ PINCTRL_PIN(67, "GBE_SMBUS_CLK"),
++ PINCTRL_PIN(68, "GBE_SMBDATA"),
++ PINCTRL_PIN(69, "GBE_SMBALRTN"),
++ PINCTRL_PIN(70, "SSATA_SCLOCK"),
++ PINCTRL_PIN(71, "SSATA_SLOAD"),
++ /* GPP_C */
++ PINCTRL_PIN(72, "SMBCLK"),
++ PINCTRL_PIN(73, "SMBDATA"),
++ PINCTRL_PIN(74, "SMBALERTB"),
++ PINCTRL_PIN(75, "SML0CLK"),
++ PINCTRL_PIN(76, "SML0DATA"),
++ PINCTRL_PIN(77, "SML0ALERTB"),
++ PINCTRL_PIN(78, "SML1CLK"),
++ PINCTRL_PIN(79, "SML1DATA"),
++ PINCTRL_PIN(80, "GPP_C_8"),
++ PINCTRL_PIN(81, "GPP_C_9"),
++ PINCTRL_PIN(82, "GPP_C_10"),
++ PINCTRL_PIN(83, "GPP_C_11"),
++ PINCTRL_PIN(84, "GPP_C_12"),
++ PINCTRL_PIN(85, "GPP_C_13"),
++ PINCTRL_PIN(86, "GPP_C_14"),
++ PINCTRL_PIN(87, "GPP_C_15"),
++ PINCTRL_PIN(88, "GPP_C_16"),
++ PINCTRL_PIN(89, "GPP_C_17"),
++ PINCTRL_PIN(90, "GPP_C_18"),
++ PINCTRL_PIN(91, "GPP_C_19"),
++ PINCTRL_PIN(92, "GPP_C_20"),
++ PINCTRL_PIN(93, "GPP_C_21"),
++ PINCTRL_PIN(94, "GPP_C_22"),
++ PINCTRL_PIN(95, "GPP_C_23"),
++ /* GPP_D */
++ PINCTRL_PIN(96, "GPP_D_0"),
++ PINCTRL_PIN(97, "GPP_D_1"),
++ PINCTRL_PIN(98, "GPP_D_2"),
++ PINCTRL_PIN(99, "GPP_D_3"),
++ PINCTRL_PIN(100, "GPP_D_4"),
++ PINCTRL_PIN(101, "SSP0_SFRM"),
++ PINCTRL_PIN(102, "SSP0_TXD"),
++ PINCTRL_PIN(103, "SSP0_RXD"),
++ PINCTRL_PIN(104, "SSP0_SCLK"),
++ PINCTRL_PIN(105, "SSATA_DEVSLP_3"),
++ PINCTRL_PIN(106, "SSATA_DEVSLP_4"),
++ PINCTRL_PIN(107, "SSATA_DEVSLP_5"),
++ PINCTRL_PIN(108, "SSATA_SDATAOUT1"),
++ PINCTRL_PIN(109, "SML0BCLK_SML0BCLKIE"),
++ PINCTRL_PIN(110, "SML0BDATA_SML0BDATAIE"),
++ PINCTRL_PIN(111, "SSATA_SDATAOUT0"),
++ PINCTRL_PIN(112, "SML0BALERTB_SML0BALERTBIE"),
++ PINCTRL_PIN(113, "DMIC_CLK_1"),
++ PINCTRL_PIN(114, "DMIC_DATA_1"),
++ PINCTRL_PIN(115, "DMIC_CLK_0"),
++ PINCTRL_PIN(116, "DMIC_DATA_0"),
++ PINCTRL_PIN(117, "IE_UART_RXD"),
++ PINCTRL_PIN(118, "IE_UART_TXD"),
++ PINCTRL_PIN(119, "GPP_D_23"),
++ /* GPP_E */
++ PINCTRL_PIN(120, "SATAXPCIE_0"),
++ PINCTRL_PIN(121, "SATAXPCIE_1"),
++ PINCTRL_PIN(122, "SATAXPCIE_2"),
++ PINCTRL_PIN(123, "CPU_GP_0"),
++ PINCTRL_PIN(124, "SATA_DEVSLP_0"),
++ PINCTRL_PIN(125, "SATA_DEVSLP_1"),
++ PINCTRL_PIN(126, "SATA_DEVSLP_2"),
++ PINCTRL_PIN(127, "CPU_GP_1"),
++ PINCTRL_PIN(128, "SATA_LEDB"),
++ PINCTRL_PIN(129, "USB2_OCB_0"),
++ PINCTRL_PIN(130, "USB2_OCB_1"),
++ PINCTRL_PIN(131, "USB2_OCB_2"),
++ PINCTRL_PIN(132, "USB2_OCB_3"),
++ /* GPP_I */
++ PINCTRL_PIN(133, "GBE_TDO"),
++ PINCTRL_PIN(134, "GBE_TCK"),
++ PINCTRL_PIN(135, "GBE_TMS"),
++ PINCTRL_PIN(136, "GBE_TDI"),
++ PINCTRL_PIN(137, "DO_RESET_INB"),
++ PINCTRL_PIN(138, "DO_RESET_OUTB"),
++ PINCTRL_PIN(139, "RESET_DONE"),
++ PINCTRL_PIN(140, "GBE_TRST_N"),
++ PINCTRL_PIN(141, "GBE_PCI_DIS"),
++ PINCTRL_PIN(142, "GBE_LAN_DIS"),
++ PINCTRL_PIN(143, "GPP_I_10"),
++ PINCTRL_PIN(144, "GPIO_RCOMP_3P3"),
++ /* GPP_J */
++ PINCTRL_PIN(145, "GBE_LED_0_0"),
++ PINCTRL_PIN(146, "GBE_LED_0_1"),
++ PINCTRL_PIN(147, "GBE_LED_1_0"),
++ PINCTRL_PIN(148, "GBE_LED_1_1"),
++ PINCTRL_PIN(149, "GBE_LED_2_0"),
++ PINCTRL_PIN(150, "GBE_LED_2_1"),
++ PINCTRL_PIN(151, "GBE_LED_3_0"),
++ PINCTRL_PIN(152, "GBE_LED_3_1"),
++ PINCTRL_PIN(153, "GBE_SCL_0"),
++ PINCTRL_PIN(154, "GBE_SDA_0"),
++ PINCTRL_PIN(155, "GBE_SCL_1"),
++ PINCTRL_PIN(156, "GBE_SDA_1"),
++ PINCTRL_PIN(157, "GBE_SCL_2"),
++ PINCTRL_PIN(158, "GBE_SDA_2"),
++ PINCTRL_PIN(159, "GBE_SCL_3"),
++ PINCTRL_PIN(160, "GBE_SDA_3"),
++ PINCTRL_PIN(161, "GBE_SDP_0_0"),
++ PINCTRL_PIN(162, "GBE_SDP_0_1"),
++ PINCTRL_PIN(163, "GBE_SDP_1_0"),
++ PINCTRL_PIN(164, "GBE_SDP_1_1"),
++ PINCTRL_PIN(165, "GBE_SDP_2_0"),
++ PINCTRL_PIN(166, "GBE_SDP_2_1"),
++ PINCTRL_PIN(167, "GBE_SDP_3_0"),
++ PINCTRL_PIN(168, "GBE_SDP_3_1"),
++ /* GPP_K */
++ PINCTRL_PIN(169, "GBE_RMIICLK"),
++ PINCTRL_PIN(170, "GBE_RMII_TXD_0"),
++ PINCTRL_PIN(171, "GBE_RMII_TXD_1"),
++ PINCTRL_PIN(172, "GBE_RMII_TX_EN"),
++ PINCTRL_PIN(173, "GBE_RMII_CRS_DV"),
++ PINCTRL_PIN(174, "GBE_RMII_RXD_0"),
++ PINCTRL_PIN(175, "GBE_RMII_RXD_1"),
++ PINCTRL_PIN(176, "GBE_RMII_RX_ER"),
++ PINCTRL_PIN(177, "GBE_RMII_ARBIN"),
++ PINCTRL_PIN(178, "GBE_RMII_ARB_OUT"),
++ PINCTRL_PIN(179, "PE_RST_N"),
++ PINCTRL_PIN(180, "GPIO_RCOMP_1P8_3P3"),
++ /* GPP_G */
++ PINCTRL_PIN(181, "FAN_TACH_0"),
++ PINCTRL_PIN(182, "FAN_TACH_1"),
++ PINCTRL_PIN(183, "FAN_TACH_2"),
++ PINCTRL_PIN(184, "FAN_TACH_3"),
++ PINCTRL_PIN(185, "FAN_TACH_4"),
++ PINCTRL_PIN(186, "FAN_TACH_5"),
++ PINCTRL_PIN(187, "FAN_TACH_6"),
++ PINCTRL_PIN(188, "FAN_TACH_7"),
++ PINCTRL_PIN(189, "FAN_PWM_0"),
++ PINCTRL_PIN(190, "FAN_PWM_1"),
++ PINCTRL_PIN(191, "FAN_PWM_2"),
++ PINCTRL_PIN(192, "FAN_PWM_3"),
++ PINCTRL_PIN(193, "GSXDOUT"),
++ PINCTRL_PIN(194, "GSXSLOAD"),
++ PINCTRL_PIN(195, "GSXDIN"),
++ PINCTRL_PIN(196, "GSXSRESETB"),
++ PINCTRL_PIN(197, "GSXCLK"),
++ PINCTRL_PIN(198, "ADR_COMPLETE"),
++ PINCTRL_PIN(199, "NMIB"),
++ PINCTRL_PIN(200, "SMIB"),
++ PINCTRL_PIN(201, "SSATA_DEVSLP_0"),
++ PINCTRL_PIN(202, "SSATA_DEVSLP_1"),
++ PINCTRL_PIN(203, "SSATA_DEVSLP_2"),
++ PINCTRL_PIN(204, "SSATAXPCIE0_SSATAGP0"),
++ /* GPP_H */
++ PINCTRL_PIN(205, "SRCCLKREQB_6"),
++ PINCTRL_PIN(206, "SRCCLKREQB_7"),
++ PINCTRL_PIN(207, "SRCCLKREQB_8"),
++ PINCTRL_PIN(208, "SRCCLKREQB_9"),
++ PINCTRL_PIN(209, "SRCCLKREQB_10"),
++ PINCTRL_PIN(210, "SRCCLKREQB_11"),
++ PINCTRL_PIN(211, "SRCCLKREQB_12"),
++ PINCTRL_PIN(212, "SRCCLKREQB_13"),
++ PINCTRL_PIN(213, "SRCCLKREQB_14"),
++ PINCTRL_PIN(214, "SRCCLKREQB_15"),
++ PINCTRL_PIN(215, "SML2CLK"),
++ PINCTRL_PIN(216, "SML2DATA"),
++ PINCTRL_PIN(217, "SML2ALERTB"),
++ PINCTRL_PIN(218, "SML3CLK"),
++ PINCTRL_PIN(219, "SML3DATA"),
++ PINCTRL_PIN(220, "SML3ALERTB"),
++ PINCTRL_PIN(221, "SML4CLK"),
++ PINCTRL_PIN(222, "SML4DATA"),
++ PINCTRL_PIN(223, "SML4ALERTB"),
++ PINCTRL_PIN(224, "SSATAXPCIE1_SSATAGP1"),
++ PINCTRL_PIN(225, "SSATAXPCIE2_SSATAGP2"),
++ PINCTRL_PIN(226, "SSATAXPCIE3_SSATAGP3"),
++ PINCTRL_PIN(227, "SSATAXPCIE4_SSATAGP4"),
++ PINCTRL_PIN(228, "SSATAXPCIE5_SSATAGP5"),
++ /* GPP_L */
++ PINCTRL_PIN(229, "VISA2CH0_D0"),
++ PINCTRL_PIN(230, "VISA2CH0_D1"),
++ PINCTRL_PIN(231, "VISA2CH0_D2"),
++ PINCTRL_PIN(232, "VISA2CH0_D3"),
++ PINCTRL_PIN(233, "VISA2CH0_D4"),
++ PINCTRL_PIN(234, "VISA2CH0_D5"),
++ PINCTRL_PIN(235, "VISA2CH0_D6"),
++ PINCTRL_PIN(236, "VISA2CH0_D7"),
++ PINCTRL_PIN(237, "VISA2CH0_CLK"),
++ PINCTRL_PIN(238, "VISA2CH1_D0"),
++ PINCTRL_PIN(239, "VISA2CH1_D1"),
++ PINCTRL_PIN(240, "VISA2CH1_D2"),
++ PINCTRL_PIN(241, "VISA2CH1_D3"),
++ PINCTRL_PIN(242, "VISA2CH1_D4"),
++ PINCTRL_PIN(243, "VISA2CH1_D5"),
++ PINCTRL_PIN(244, "VISA2CH1_D6"),
++ PINCTRL_PIN(245, "VISA2CH1_D7"),
++ PINCTRL_PIN(246, "VISA2CH1_CLK"),
++};
++
++static const struct intel_community lbg_communities[] = {
++ LBG_COMMUNITY(0, 0, 71),
++ LBG_COMMUNITY(1, 72, 132),
++ LBG_COMMUNITY(3, 133, 144),
++ LBG_COMMUNITY(4, 145, 180),
++ LBG_COMMUNITY(5, 181, 246),
++};
++
++static const struct intel_pinctrl_soc_data lbg_soc_data = {
++ .pins = lbg_pins,
++ .npins = ARRAY_SIZE(lbg_pins),
++ .communities = lbg_communities,
++ .ncommunities = ARRAY_SIZE(lbg_communities),
++};
++
++static int lbg_pinctrl_probe(struct platform_device *pdev)
++{
++ return intel_pinctrl_probe(pdev, &lbg_soc_data);
++}
++
++static const struct dev_pm_ops lbg_pinctrl_pm_ops = {
++ SET_LATE_SYSTEM_SLEEP_PM_OPS(intel_pinctrl_suspend,
++ intel_pinctrl_resume)
++};
++
++static const struct acpi_device_id lbg_pinctrl_acpi_match[] = {
++ { "INT3536" },
++ { }
++};
++MODULE_DEVICE_TABLE(acpi, lbg_pinctrl_acpi_match);
++
++static struct platform_driver lbg_pinctrl_driver = {
++ .probe = lbg_pinctrl_probe,
++ .driver = {
++ .name = "lewisburg-pinctrl",
++ .acpi_match_table = lbg_pinctrl_acpi_match,
++ .pm = &lbg_pinctrl_pm_ops,
++ },
++};
++
++module_platform_driver(lbg_pinctrl_driver);
++
++MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
++MODULE_DESCRIPTION("Intel Lewisburg pinctrl/GPIO driver");
++MODULE_LICENSE("GPL v2");
+--
+2.18.0
+
diff --git a/patches.drivers/scsi-ata-enhance-the-definition-of-set-max-feature-field-value.patch b/patches.drivers/scsi-ata-enhance-the-definition-of-set-max-feature-field-value.patch
new file mode 100644
index 0000000000..7b58fc0a5a
--- /dev/null
+++ b/patches.drivers/scsi-ata-enhance-the-definition-of-set-max-feature-field-value.patch
@@ -0,0 +1,33 @@
+From: chenxiang <chenxiang66@hisilicon.com>
+Date: Thu, 28 Dec 2017 18:20:46 +0800
+Subject: scsi: ata: enhance the definition of SET MAX feature field value
+Git-commit: d5c15c2c22a8d4e0e82ca95eac5a6ccd175c0762
+Patch-mainline: v4.16-rc1
+References: FATE#326253
+
+There are two other values for SET MAX feature field according to ata
+protocol. So definite them.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Acked-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ include/linux/ata.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/include/linux/ata.h b/include/linux/ata.h
+index c7a353825450..40d150ad7e07 100644
+--- a/include/linux/ata.h
++++ b/include/linux/ata.h
+@@ -448,6 +448,8 @@ enum {
+ ATA_SET_MAX_LOCK = 0x02,
+ ATA_SET_MAX_UNLOCK = 0x03,
+ ATA_SET_MAX_FREEZE_LOCK = 0x04,
++ ATA_SET_MAX_PASSWD_DMA = 0x05,
++ ATA_SET_MAX_UNLOCK_DMA = 0x06,
+
+ /* feature values for DEVICE CONFIGURATION OVERLAY */
+ ATA_DCO_RESTORE = 0xC0,
+
diff --git a/patches.drivers/scsi-hisi_sas-add-an-mechanism-to-do-reset-work-synchronously.patch b/patches.drivers/scsi-hisi_sas-add-an-mechanism-to-do-reset-work-synchronously.patch
new file mode 100644
index 0000000000..82614d20b0
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-add-an-mechanism-to-do-reset-work-synchronously.patch
@@ -0,0 +1,110 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Sat, 9 Dec 2017 01:16:38 +0800
+Subject: scsi: hisi_sas: add an mechanism to do reset work synchronously
+Git-commit: e402acdb664134f948b62d13b7db866295689f38
+Patch-mainline: v4.16-rc1
+References: FATE#326253
+
+Sometimes it is required to know when the controller reset has completed and
+also if it has completed successfully. For such places, we call
+hisi_sas_controller_reset() directly before. That may lead to multiple calls
+to this function.
+
+This patch create a per-reset structure which contains a completion structure
+and status flag to know when the reset completes and also the status. It is
+also in hisi_hba.wq to do reset work.
+
+As all host reset works are done in hisi_hba.wq, we don't worry multiple calls
+to hisi_sas_controller_reset().
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas.h | 26 ++++++++++++++++++++++++++
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 19 ++++++++++++++++++-
+ 2 files changed, 44 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
+index b2534caed45a..71bc8eaac99e 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas.h
++++ b/drivers/scsi/hisi_sas/hisi_sas.h
+@@ -99,6 +99,31 @@ struct hisi_sas_hw_error {
+ const struct hisi_sas_hw_error *sub;
+ };
+
++struct hisi_sas_rst {
++ struct hisi_hba *hisi_hba;
++ struct completion *completion;
++ struct work_struct work;
++ bool done;
++};
++
++#define HISI_SAS_RST_WORK_INIT(r, c) \
++ { .hisi_hba = hisi_hba, \
++ .completion = &c, \
++ .work = __WORK_INITIALIZER(r.work, \
++ hisi_sas_sync_rst_work_handler), \
++ .done = false, \
++ }
++
++#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 {
++ HISI_SAS_ERR_SINGLE_BIT_ECC = 0x0,
++ HISI_SAS_ERR_MULTI_BIT_ECC = 0x1,
++};
++
+ struct hisi_sas_phy {
+ struct hisi_hba *hisi_hba;
+ struct hisi_sas_port *port;
+@@ -426,5 +451,6 @@ extern void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot);
+ 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);
+ #endif
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index e4b30922a75d..fb162c06ac83 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -1299,8 +1299,14 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun)
+ static int hisi_sas_clear_nexus_ha(struct sas_ha_struct *sas_ha)
+ {
+ struct hisi_hba *hisi_hba = sas_ha->lldd_ha;
++ HISI_SAS_DECLARE_RST_WORK_ON_STACK(r);
+
+- return hisi_sas_controller_reset(hisi_hba);
++ queue_work(hisi_hba->wq, &r.work);
++ wait_for_completion(r.completion);
++ if (r.done)
++ return TMF_RESP_FUNC_COMPLETE;
++
++ return TMF_RESP_FUNC_FAILED;
+ }
+
+ static int hisi_sas_query_task(struct sas_task *task)
+@@ -1820,6 +1826,17 @@ void hisi_sas_rst_work_handler(struct work_struct *work)
+ }
+ EXPORT_SYMBOL_GPL(hisi_sas_rst_work_handler);
+
++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_reset(rst->hisi_hba))
++ rst->done = true;
++ complete(rst->completion);
++}
++EXPORT_SYMBOL_GPL(hisi_sas_sync_rst_work_handler);
++
+ int hisi_sas_get_fw_info(struct hisi_hba *hisi_hba)
+ {
+ struct device *dev = hisi_hba->dev;
+
diff --git a/patches.drivers/scsi-hisi_sas-add-check-of-device-in-hisi_sas_task_exec.patch b/patches.drivers/scsi-hisi_sas-add-check-of-device-in-hisi_sas_task_exec.patch
new file mode 100644
index 0000000000..06615292dd
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-add-check-of-device-in-hisi_sas_task_exec.patch
@@ -0,0 +1,95 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Wed, 9 May 2018 23:10:50 +0800
+Subject: scsi: hisi_sas: add check of device in hisi_sas_task_exec()
+Git-commit: 2f6bca202b78e2b63a62b46ff5dc26f300785e23
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+Currently we don't check that device is not gone before dereferencing
+its elements in the function hisi_sas_task_exec() (specifically, the DQ
+pointer).
+
+This patch fixes this issue by filling in the DQ pointer in
+hisi_sas_task_prep() after we check that the device pointer is still
+safe to reference.
+
+[mkp: typo]
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 23 +++++++++++++----------
+ 1 file changed, 13 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index a451625b8253..39f694eb7b00 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -310,12 +310,13 @@ static void hisi_sas_slot_abort(struct work_struct *work)
+ task->task_done(task);
+ }
+
+-static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq *dq,
++static int hisi_sas_task_prep(struct sas_task *task,
++ struct hisi_sas_dq **dq_pointer,
+ int is_tmf, struct hisi_sas_tmf_task *tmf,
+ int *pass)
+ {
+- struct hisi_hba *hisi_hba = dq->hisi_hba;
+ struct domain_device *device = task->dev;
++ struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
+ struct hisi_sas_device *sas_dev = device->lldd_dev;
+ struct hisi_sas_port *port;
+ struct hisi_sas_slot *slot;
+@@ -323,8 +324,9 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq *dq,
+ 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_req = 0, n_elem_resp = 0;
++ int n_elem = 0, n_elem_req = 0, n_elem_resp = 0;
+ unsigned long flags, flags_dq;
++ struct hisi_sas_dq *dq;
+ int wr_q_index;
+
+ if (!sas_port) {
+@@ -352,6 +354,8 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq *dq,
+ return -ECOMM;
+ }
+
++ *dq_pointer = dq = sas_dev->dq;
++
+ port = to_hisi_sas_port(sas_port);
+ if (port && !port->port_attached) {
+ dev_info(dev, "task prep: %s port%d not attach device\n",
+@@ -520,22 +524,21 @@ static int hisi_sas_task_exec(struct sas_task *task, gfp_t gfp_flags,
+ unsigned long flags;
+ struct hisi_hba *hisi_hba = dev_to_hisi_hba(task->dev);
+ struct device *dev = hisi_hba->dev;
+- struct domain_device *device = task->dev;
+- struct hisi_sas_device *sas_dev = device->lldd_dev;
+- struct hisi_sas_dq *dq = sas_dev->dq;
++ struct hisi_sas_dq *dq = NULL;
+
+ if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags)))
+ return -EINVAL;
+
+ /* protect task_prep and start_delivery sequence */
+- rc = hisi_sas_task_prep(task, dq, is_tmf, tmf, &pass);
++ rc = hisi_sas_task_prep(task, &dq, is_tmf, tmf, &pass);
+ if (rc)
+ dev_err(dev, "task exec: failed[%d]!\n", rc);
+
+- spin_lock_irqsave(&dq->lock, flags);
+- if (likely(pass))
++ if (likely(pass)) {
++ spin_lock_irqsave(&dq->lock, flags);
+ hisi_hba->hw->start_delivery(dq);
+- spin_unlock_irqrestore(&dq->lock, flags);
++ spin_unlock_irqrestore(&dq->lock, flags);
++ }
+
+ return rc;
+ }
+
diff --git a/patches.drivers/scsi-hisi_sas-add-internal-abort-dev-in-some-places.patch b/patches.drivers/scsi-hisi_sas-add-internal-abort-dev-in-some-places.patch
new file mode 100644
index 0000000000..dd9e47990b
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-add-internal-abort-dev-in-some-places.patch
@@ -0,0 +1,73 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Sat, 9 Dec 2017 01:16:47 +0800
+Subject: scsi: hisi_sas: add internal abort dev in some places
+Git-commit: 2a03813123c4beb0b60be6b3b65a6b30f7124579
+Patch-mainline: v4.16-rc1
+References: FATE#326253
+
+We should do internal abort dev before TMF_ABORT_TASK_SET and TMF_LU_RESET.
+Because we may only have done internal abort for single IO in the earlier part
+of SCSI EH process. Even the internal abort to the single IO, we also don't
+know whether it is successful.
+
+Besides, we should release slots of the device in hisi_sas_abort_task_set() if
+the abort is successful.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 25 +++++++++++++++++++++++++
+ 1 file changed, 25 insertions(+)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 1b9c48c99968..302da84bf9ef 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -1238,12 +1238,29 @@ static int hisi_sas_abort_task(struct sas_task *task)
+
+ static int hisi_sas_abort_task_set(struct domain_device *device, u8 *lun)
+ {
++ struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
++ struct device *dev = hisi_hba->dev;
+ struct hisi_sas_tmf_task tmf_task;
+ int rc = TMF_RESP_FUNC_FAILED;
++ unsigned long flags;
++
++ rc = hisi_sas_internal_task_abort(hisi_hba, device,
++ HISI_SAS_INT_ABT_DEV, 0);
++ if (rc < 0) {
++ dev_err(dev, "abort task set: internal abort rc=%d\n", rc);
++ return TMF_RESP_FUNC_FAILED;
++ }
++ hisi_sas_dereg_device(hisi_hba, device);
+
+ tmf_task.tmf = TMF_ABORT_TASK_SET;
+ rc = hisi_sas_debug_issue_ssp_tmf(device, lun, &tmf_task);
+
++ if (rc == TMF_RESP_FUNC_COMPLETE) {
++ spin_lock_irqsave(&hisi_hba->lock, flags);
++ hisi_sas_release_task(hisi_hba, device);
++ spin_unlock_irqrestore(&hisi_hba->lock, flags);
++ }
++
+ return rc;
+ }
+
+@@ -1333,6 +1350,14 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun)
+ } else {
+ struct hisi_sas_tmf_task tmf_task = { .tmf = TMF_LU_RESET };
+
++ rc = hisi_sas_internal_task_abort(hisi_hba, device,
++ HISI_SAS_INT_ABT_DEV, 0);
++ if (rc < 0) {
++ dev_err(dev, "lu_reset: internal abort failed\n");
++ goto out;
++ }
++ hisi_sas_dereg_device(hisi_hba, device);
++
+ rc = hisi_sas_debug_issue_ssp_tmf(device, lun, &tmf_task);
+ if (rc == TMF_RESP_FUNC_COMPLETE) {
+ spin_lock_irqsave(&hisi_hba->lock, flags);
+
diff --git a/patches.drivers/scsi-hisi_sas-add-led-feature-for-v3-hw.patch b/patches.drivers/scsi-hisi_sas-add-led-feature-for-v3-hw.patch
new file mode 100644
index 0000000000..0afd673947
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-add-led-feature-for-v3-hw.patch
@@ -0,0 +1,95 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Mon, 21 May 2018 18:09:16 +0800
+Subject: scsi: hisi_sas: Add LED feature for v3 hw
+Git-commit: 428f1b3424f4fe750943d8cdd1b0dafad99b0b75
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+This patch implements LED feature of directly attached disk for v3 hw.
+
+In fact, this hw has created an SGPIO component for LED feature, and we can
+control LEDs just by internal registers.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 42 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 42 insertions(+)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+index 0a80a39eccdd..a043d9cdbf48 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -107,6 +107,10 @@
+ #define AWQOS_AWCACHE_CFG 0xc84
+ #define ARQOS_ARCACHE_CFG 0xc88
+ #define HILINK_ERR_DFX 0xe04
++#define SAS_GPIO_CFG_0 0x1000
++#define SAS_GPIO_CFG_1 0x1004
++#define SAS_GPIO_TX_0_1 0x1040
++#define SAS_CFG_DRIVE_VLD 0x1070
+
+ /* phy registers requiring init */
+ #define PORT_BASE (0x2000)
+@@ -549,6 +553,14 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
+ hisi_sas_write32(hisi_hba, SAS_RAS_INTR1_MASK, 0x0);
+ hisi_sas_write32(hisi_hba, SAS_RAS_INTR2_MASK, 0x0);
+ hisi_sas_write32(hisi_hba, CFG_SAS_RAS_INTR_MASK, 0x0);
++
++ /* LED registers init */
++ hisi_sas_write32(hisi_hba, SAS_CFG_DRIVE_VLD, 0x80000ff);
++ hisi_sas_write32(hisi_hba, SAS_GPIO_TX_0_1, 0x80808080);
++ hisi_sas_write32(hisi_hba, SAS_GPIO_TX_0_1 + 0x4, 0x80808080);
++ /* Configure blink generator rate A to 1Hz and B to 4Hz */
++ hisi_sas_write32(hisi_hba, SAS_GPIO_CFG_1, 0x121700);
++ hisi_sas_write32(hisi_hba, SAS_GPIO_CFG_0, 0x800000);
+ }
+
+ static void config_phy_opt_mode_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
+@@ -1974,6 +1986,35 @@ static int soft_reset_v3_hw(struct hisi_hba *hisi_hba)
+ return hw_init_v3_hw(hisi_hba);
+ }
+
++static int write_gpio_v3_hw(struct hisi_hba *hisi_hba, u8 reg_type,
++ u8 reg_index, u8 reg_count, u8 *write_data)
++{
++ struct device *dev = hisi_hba->dev;
++ u32 *data = (u32 *)write_data;
++ int i;
++
++ switch (reg_type) {
++ case SAS_GPIO_REG_TX:
++ if ((reg_index + reg_count) > ((hisi_hba->n_phy + 3) / 4)) {
++ dev_err(dev, "write gpio: invalid reg range[%d, %d]\n",
++ reg_index, reg_index + reg_count - 1);
++ return -EINVAL;
++ }
++
++ for (i = 0; i < reg_count; i++)
++ hisi_sas_write32(hisi_hba,
++ SAS_GPIO_TX_0_1 + (reg_index + i) * 4,
++ data[i]);
++ break;
++ default:
++ dev_err(dev, "write gpio: unsupported or bad reg type %d\n",
++ reg_type);
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
+ static const struct hisi_sas_hw hisi_sas_v3_hw = {
+ .hw_init = hisi_sas_v3_init,
+ .setup_itct = setup_itct_v3_hw,
+@@ -1999,6 +2040,7 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = {
+ .soft_reset = soft_reset_v3_hw,
+ .get_phys_state = get_phys_state_v3_hw,
+ .get_events = phy_get_events_v3_hw,
++ .write_gpio = write_gpio_v3_hw,
+ };
+
+ static struct Scsi_Host *
+
diff --git a/patches.drivers/scsi-hisi_sas-add-ras-feature-for-v3-hw.patch b/patches.drivers/scsi-hisi_sas-add-ras-feature-for-v3-hw.patch
new file mode 100644
index 0000000000..f148241156
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-add-ras-feature-for-v3-hw.patch
@@ -0,0 +1,200 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Sat, 9 Dec 2017 01:16:40 +0800
+Subject: scsi: hisi_sas: add RAS feature for v3 hw
+Git-commit: 1aaf81e0e34988ff56b317b568f92fe6ca447da2
+Patch-mainline: v4.16-rc1
+References: FATE#326253
+
+We use PCIe AER to support RAS feature for v3 hw. This driver should do
+following two things to support this:
+
+1. Enable RAS interrupts, so that errors can be reported to RAS module.
+
+2. Realize err_handler for sas_v3_pci_driver. Then if non-fatal error is
+ detected, print error source and try to recover SAS controller.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 139 +++++++++++++++++++++++++++++++++
+ 1 file changed, 139 insertions(+)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+index 69aa7bc15783..d356e12d7b98 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -204,6 +204,13 @@
+ #define AM_ROB_ECC_MULBIT_ERR_ADDR_OFF 8
+ #define AM_ROB_ECC_MULBIT_ERR_ADDR_MSK (0xff << AM_ROB_ECC_MULBIT_ERR_ADDR_OFF)
+
++/* RAS registers need init */
++#define RAS_BASE (0x6000)
++#define SAS_RAS_INTR0 (RAS_BASE)
++#define SAS_RAS_INTR1 (RAS_BASE + 0x04)
++#define SAS_RAS_INTR0_MASK (RAS_BASE + 0x08)
++#define SAS_RAS_INTR1_MASK (RAS_BASE + 0x0c)
++
+ /* HW dma structures */
+ /* Delivery queue header */
+ /* dw0 */
+@@ -496,6 +503,10 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
+
+ hisi_sas_write32(hisi_hba, SATA_INITI_D2H_STORE_ADDR_HI,
+ upper_32_bits(hisi_hba->initial_fis_dma));
++
++ /* RAS registers init */
++ hisi_sas_write32(hisi_hba, SAS_RAS_INTR0_MASK, 0x0);
++ hisi_sas_write32(hisi_hba, SAS_RAS_INTR1_MASK, 0x0);
+ }
+
+ static void config_phy_opt_mode_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
+@@ -2129,6 +2140,127 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev)
+ scsi_host_put(shost);
+ }
+
++static const struct hisi_sas_hw_error sas_ras_intr0_nfe[] = {
++ { .irq_msk = BIT(19), .msg = "HILINK_INT" },
++ { .irq_msk = BIT(20), .msg = "HILINK_PLL0_OUT_OF_LOCK" },
++ { .irq_msk = BIT(21), .msg = "HILINK_PLL1_OUT_OF_LOCK" },
++ { .irq_msk = BIT(22), .msg = "HILINK_LOSS_OF_REFCLK0" },
++ { .irq_msk = BIT(23), .msg = "HILINK_LOSS_OF_REFCLK1" },
++ { .irq_msk = BIT(24), .msg = "DMAC0_TX_POISON" },
++ { .irq_msk = BIT(25), .msg = "DMAC1_TX_POISON" },
++ { .irq_msk = BIT(26), .msg = "DMAC2_TX_POISON" },
++ { .irq_msk = BIT(27), .msg = "DMAC3_TX_POISON" },
++ { .irq_msk = BIT(28), .msg = "DMAC4_TX_POISON" },
++ { .irq_msk = BIT(29), .msg = "DMAC5_TX_POISON" },
++ { .irq_msk = BIT(30), .msg = "DMAC6_TX_POISON" },
++ { .irq_msk = BIT(31), .msg = "DMAC7_TX_POISON" },
++};
++
++static const struct hisi_sas_hw_error sas_ras_intr1_nfe[] = {
++ { .irq_msk = BIT(0), .msg = "RXM_CFG_MEM3_ECC2B_INTR" },
++ { .irq_msk = BIT(1), .msg = "RXM_CFG_MEM2_ECC2B_INTR" },
++ { .irq_msk = BIT(2), .msg = "RXM_CFG_MEM1_ECC2B_INTR" },
++ { .irq_msk = BIT(3), .msg = "RXM_CFG_MEM0_ECC2B_INTR" },
++ { .irq_msk = BIT(4), .msg = "HGC_CQE_ECC2B_INTR" },
++ { .irq_msk = BIT(5), .msg = "LM_CFG_IOSTL_ECC2B_INTR" },
++ { .irq_msk = BIT(6), .msg = "LM_CFG_ITCTL_ECC2B_INTR" },
++ { .irq_msk = BIT(7), .msg = "HGC_ITCT_ECC2B_INTR" },
++ { .irq_msk = BIT(8), .msg = "HGC_IOST_ECC2B_INTR" },
++ { .irq_msk = BIT(9), .msg = "HGC_DQE_ECC2B_INTR" },
++ { .irq_msk = BIT(10), .msg = "DMAC0_RAM_ECC2B_INTR" },
++ { .irq_msk = BIT(11), .msg = "DMAC1_RAM_ECC2B_INTR" },
++ { .irq_msk = BIT(12), .msg = "DMAC2_RAM_ECC2B_INTR" },
++ { .irq_msk = BIT(13), .msg = "DMAC3_RAM_ECC2B_INTR" },
++ { .irq_msk = BIT(14), .msg = "DMAC4_RAM_ECC2B_INTR" },
++ { .irq_msk = BIT(15), .msg = "DMAC5_RAM_ECC2B_INTR" },
++ { .irq_msk = BIT(16), .msg = "DMAC6_RAM_ECC2B_INTR" },
++ { .irq_msk = BIT(17), .msg = "DMAC7_RAM_ECC2B_INTR" },
++ { .irq_msk = BIT(18), .msg = "OOO_RAM_ECC2B_INTR" },
++ { .irq_msk = BIT(20), .msg = "HGC_DQE_POISON_INTR" },
++ { .irq_msk = BIT(21), .msg = "HGC_IOST_POISON_INTR" },
++ { .irq_msk = BIT(22), .msg = "HGC_ITCT_POISON_INTR" },
++ { .irq_msk = BIT(23), .msg = "HGC_ITCT_NCQ_POISON_INTR" },
++ { .irq_msk = BIT(24), .msg = "DMAC0_RX_POISON" },
++ { .irq_msk = BIT(25), .msg = "DMAC1_RX_POISON" },
++ { .irq_msk = BIT(26), .msg = "DMAC2_RX_POISON" },
++ { .irq_msk = BIT(27), .msg = "DMAC3_RX_POISON" },
++ { .irq_msk = BIT(28), .msg = "DMAC4_RX_POISON" },
++ { .irq_msk = BIT(29), .msg = "DMAC5_RX_POISON" },
++ { .irq_msk = BIT(30), .msg = "DMAC6_RX_POISON" },
++ { .irq_msk = BIT(31), .msg = "DMAC7_RX_POISON" },
++};
++
++static bool process_non_fatal_error_v3_hw(struct hisi_hba *hisi_hba)
++{
++ struct device *dev = hisi_hba->dev;
++ const struct hisi_sas_hw_error *ras_error;
++ bool need_reset = false;
++ u32 irq_value;
++ int i;
++
++ irq_value = hisi_sas_read32(hisi_hba, SAS_RAS_INTR0);
++ for (i = 0; i < ARRAY_SIZE(sas_ras_intr0_nfe); i++) {
++ ras_error = &sas_ras_intr0_nfe[i];
++ if (ras_error->irq_msk & irq_value) {
++ dev_warn(dev, "SAS_RAS_INTR0: %s(irq_value=0x%x) found.\n",
++ ras_error->msg, irq_value);
++ need_reset = true;
++ }
++ }
++ hisi_sas_write32(hisi_hba, SAS_RAS_INTR0, irq_value);
++
++ irq_value = hisi_sas_read32(hisi_hba, SAS_RAS_INTR1);
++ for (i = 0; i < ARRAY_SIZE(sas_ras_intr1_nfe); i++) {
++ ras_error = &sas_ras_intr1_nfe[i];
++ if (ras_error->irq_msk & irq_value) {
++ dev_warn(dev, "SAS_RAS_INTR1: %s(irq_value=0x%x) found.\n",
++ ras_error->msg, irq_value);
++ need_reset = true;
++ }
++ }
++ hisi_sas_write32(hisi_hba, SAS_RAS_INTR1, irq_value);
++
++ return need_reset;
++}
++
++static pci_ers_result_t hisi_sas_error_detected_v3_hw(struct pci_dev *pdev,
++ pci_channel_state_t state)
++{
++ struct sas_ha_struct *sha = pci_get_drvdata(pdev);
++ struct hisi_hba *hisi_hba = sha->lldd_ha;
++ struct device *dev = hisi_hba->dev;
++
++ dev_info(dev, "PCI error: detected callback, state(%d)!!\n", state);
++ if (state == pci_channel_io_perm_failure)
++ return PCI_ERS_RESULT_DISCONNECT;
++
++ if (process_non_fatal_error_v3_hw(hisi_hba))
++ return PCI_ERS_RESULT_NEED_RESET;
++
++ return PCI_ERS_RESULT_CAN_RECOVER;
++}
++
++static pci_ers_result_t hisi_sas_mmio_enabled_v3_hw(struct pci_dev *pdev)
++{
++ return PCI_ERS_RESULT_RECOVERED;
++}
++
++static pci_ers_result_t hisi_sas_slot_reset_v3_hw(struct pci_dev *pdev)
++{
++ struct sas_ha_struct *sha = pci_get_drvdata(pdev);
++ struct hisi_hba *hisi_hba = sha->lldd_ha;
++ struct device *dev = hisi_hba->dev;
++ HISI_SAS_DECLARE_RST_WORK_ON_STACK(r);
++
++ dev_info(dev, "PCI error: slot reset callback!!\n");
++ queue_work(hisi_hba->wq, &r.work);
++ wait_for_completion(r.completion);
++ if (r.done)
++ return PCI_ERS_RESULT_RECOVERED;
++
++ return PCI_ERS_RESULT_DISCONNECT;
++}
++
+ enum {
+ /* instances of the controller */
+ hip08,
+@@ -2139,11 +2271,18 @@ static const struct pci_device_id sas_v3_pci_table[] = {
+ {}
+ };
+
++static const struct pci_error_handlers hisi_sas_err_handler = {
++ .error_detected = hisi_sas_error_detected_v3_hw,
++ .mmio_enabled = hisi_sas_mmio_enabled_v3_hw,
++ .slot_reset = hisi_sas_slot_reset_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,
++ .err_handler = &hisi_sas_err_handler,
+ };
+
+ module_pci_driver(sas_v3_pci_driver);
+
diff --git a/patches.drivers/scsi-hisi_sas-add-readl-poll-timeout-helper-wrappers.patch b/patches.drivers/scsi-hisi_sas-add-readl-poll-timeout-helper-wrappers.patch
new file mode 100644
index 0000000000..c5e2d92e2f
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-add-readl-poll-timeout-helper-wrappers.patch
@@ -0,0 +1,78 @@
+From: John Garry <john.garry@huawei.com>
+Date: Wed, 2 May 2018 23:56:33 +0800
+Subject: scsi: hisi_sas: add readl poll timeout helper wrappers
+Git-commit: 9b8addf3024eb57a215d0af2e1c95cd44b94ccab
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+It is common to use readl poll timeout helpers in the driver, so create
+custom wrappers.
+
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 28 ++++++++++++++++++++++------
+ 1 file changed, 22 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+index d6e705ff9dad..28bb71e3b093 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -394,6 +394,20 @@ static u32 hisi_sas_phy_read32(struct hisi_hba *hisi_hba,
+ return readl(regs);
+ }
+
++#define hisi_sas_read32_poll_timeout(off, val, cond, delay_us, \
++ timeout_us) \
++({ \
++ void __iomem *regs = hisi_hba->regs + off; \
++ readl_poll_timeout(regs, val, cond, delay_us, timeout_us); \
++})
++
++#define hisi_sas_read32_poll_timeout_atomic(off, val, cond, delay_us, \
++ timeout_us) \
++({ \
++ void __iomem *regs = hisi_hba->regs + off; \
++ readl_poll_timeout_atomic(regs, val, cond, delay_us, timeout_us);\
++})
++
+ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
+ {
+ struct pci_dev *pdev = hisi_hba->pci_dev;
+@@ -684,8 +698,8 @@ static int reset_hw_v3_hw(struct hisi_hba *hisi_hba)
+ udelay(50);
+
+ /* Ensure axi bus idle */
+- ret = readl_poll_timeout(hisi_hba->regs + AXI_CFG, val, !val,
+- 20000, 1000000);
++ ret = hisi_sas_read32_poll_timeout(AXI_CFG, val, !val,
++ 20000, 1000000);
+ if (ret) {
+ dev_err(dev, "axi bus is not idle, ret = %d!\n", ret);
+ return -EIO;
+@@ -1977,8 +1991,9 @@ static int soft_reset_v3_hw(struct hisi_hba *hisi_hba)
+ hisi_sas_write32(hisi_hba, AXI_MASTER_CFG_BASE + AM_CTRL_GLOBAL, 0x1);
+
+ /* wait until bus idle */
+- rc = readl_poll_timeout(hisi_hba->regs + AXI_MASTER_CFG_BASE +
+- AM_CURR_TRANS_RETURN, status, status == 0x3, 10, 100);
++ rc = hisi_sas_read32_poll_timeout(AXI_MASTER_CFG_BASE +
++ AM_CURR_TRANS_RETURN, status,
++ status == 0x3, 10, 100);
+ if (rc) {
+ dev_err(dev, "axi bus is not idle, rc = %d\n", rc);
+ return rc;
+@@ -2396,8 +2411,9 @@ static int hisi_sas_v3_suspend(struct pci_dev *pdev, pm_message_t state)
+ AM_CTRL_GLOBAL, reg_val);
+
+ /* wait until bus idle */
+- rc = readl_poll_timeout(hisi_hba->regs + AXI_MASTER_CFG_BASE +
+- AM_CURR_TRANS_RETURN, status, status == 0x3, 10, 100);
++ rc = hisi_sas_read32_poll_timeout(AXI_MASTER_CFG_BASE +
++ AM_CURR_TRANS_RETURN, status,
++ status == 0x3, 10, 100);
+ if (rc) {
+ dev_err(dev, "axi bus is not idle, rc = %d\n", rc);
+ clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
+
diff --git a/patches.drivers/scsi-hisi_sas-add-some-checks-to-avoid-free-ing-a-sas_task-twice.patch b/patches.drivers/scsi-hisi_sas-add-some-checks-to-avoid-free-ing-a-sas_task-twice.patch
new file mode 100644
index 0000000000..5cd9fdfcae
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-add-some-checks-to-avoid-free-ing-a-sas_task-twice.patch
@@ -0,0 +1,161 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Wed, 2 May 2018 23:56:25 +0800
+Subject: scsi: hisi_sas: Add some checks to avoid free'ing a sas_task twice
+Git-commit: b81b6cce58b7912e0d35f0b5bf526cb798f8e7aa
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+If the SCSI host enters EH, any pending IO will be processed by SCSI
+EH. However it is possible that SCSI EH will try to abort the IO and
+also at the same time the IO completes in the driver. In this situation
+there is a small chance of freeing the sas_task twice.
+
+Then if another IO re-uses freed sas_task before the second time of
+free'ing sas_task, it is possible to free incorrect sas_task.
+
+To avoid this situation, add some checks to increase reliability. The
+sas_task task state flag SAS_TASK_STATE_ABORTED is used to mutually
+protect the LLDD and libsas freeing the task.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 4 ++++
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 22 +++++++---------------
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 21 +++++++--------------
+ 3 files changed, 18 insertions(+), 29 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index d1a61b1e591b..52746e2e7f6f 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -1174,10 +1174,14 @@ static int hisi_sas_abort_task(struct sas_task *task)
+ return TMF_RESP_FUNC_FAILED;
+ }
+
++ spin_lock_irqsave(&task->task_state_lock, flags);
+ if (task->task_state_flags & SAS_TASK_STATE_DONE) {
++ spin_unlock_irqrestore(&task->task_state_lock, flags);
+ rc = TMF_RESP_FUNC_COMPLETE;
+ goto out;
+ }
++ task->task_state_flags |= SAS_TASK_STATE_ABORTED;
++ spin_unlock_irqrestore(&task->task_state_lock, flags);
+
+ sas_dev->dev_status = HISI_SAS_DEV_EH;
+ if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) {
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+index 384e4ef50b24..8ca0044e09be 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -2386,7 +2386,6 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
+ struct hisi_sas_complete_v2_hdr *complete_hdr =
+ &complete_queue[slot->cmplt_queue_slot];
+ unsigned long flags;
+- int aborted;
+
+ if (unlikely(!task || !task->lldd_task || !task->dev))
+ return -EINVAL;
+@@ -2396,7 +2395,6 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
+ sas_dev = device->lldd_dev;
+
+ spin_lock_irqsave(&task->task_state_lock, flags);
+- aborted = task->task_state_flags & SAS_TASK_STATE_ABORTED;
+ task->task_state_flags &=
+ ~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR);
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
+@@ -2404,15 +2402,6 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
+ memset(ts, 0, sizeof(*ts));
+ ts->resp = SAS_TASK_COMPLETE;
+
+- if (unlikely(aborted)) {
+- dev_dbg(dev, "slot_complete: task(%p) aborted\n", task);
+- ts->stat = SAS_ABORTED_TASK;
+- spin_lock_irqsave(&hisi_hba->lock, flags);
+- hisi_sas_slot_task_free(hisi_hba, task, slot);
+- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+- return ts->stat;
+- }
+-
+ if (unlikely(!sas_dev)) {
+ dev_dbg(dev, "slot complete: port has no device\n");
+ ts->stat = SAS_PHY_DOWN;
+@@ -2523,13 +2512,16 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
+ }
+
+ out:
++ hisi_sas_slot_task_free(hisi_hba, task, slot);
++ 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(%p) aborted\n", task);
++ return SAS_ABORTED_TASK;
++ }
+ task->task_state_flags |= SAS_TASK_STATE_DONE;
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
+- spin_lock_irqsave(&hisi_hba->lock, flags);
+- hisi_sas_slot_task_free(hisi_hba, task, slot);
+- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+- sts = ts->stat;
+
+ if (task->task_done)
+ task->task_done(task);
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+index afc1242abdcf..734611046d3e 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -1576,7 +1576,6 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
+ hisi_hba->complete_hdr[slot->cmplt_queue];
+ struct hisi_sas_complete_v3_hdr *complete_hdr =
+ &complete_queue[slot->cmplt_queue_slot];
+- int aborted;
+ unsigned long flags;
+
+ if (unlikely(!task || !task->lldd_task || !task->dev))
+@@ -1587,21 +1586,12 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
+ sas_dev = device->lldd_dev;
+
+ spin_lock_irqsave(&task->task_state_lock, flags);
+- aborted = task->task_state_flags & SAS_TASK_STATE_ABORTED;
+ task->task_state_flags &=
+ ~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR);
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
+
+ memset(ts, 0, sizeof(*ts));
+ ts->resp = SAS_TASK_COMPLETE;
+- if (unlikely(aborted)) {
+- dev_dbg(dev, "slot complete: task(%p) aborted\n", task);
+- ts->stat = SAS_ABORTED_TASK;
+- spin_lock_irqsave(&hisi_hba->lock, flags);
+- hisi_sas_slot_task_free(hisi_hba, task, slot);
+- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+- return ts->stat;
+- }
+
+ if (unlikely(!sas_dev)) {
+ dev_dbg(dev, "slot complete: port has not device\n");
+@@ -1699,13 +1689,16 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
+ }
+
+ out:
++ hisi_sas_slot_task_free(hisi_hba, task, slot);
++ 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(%p) aborted\n", task);
++ return SAS_ABORTED_TASK;
++ }
+ task->task_state_flags |= SAS_TASK_STATE_DONE;
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
+- spin_lock_irqsave(&hisi_hba->lock, flags);
+- hisi_sas_slot_task_free(hisi_hba, task, slot);
+- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+- sts = ts->stat;
+
+ if (task->task_done)
+ task->task_done(task);
+
diff --git a/patches.drivers/scsi-hisi_sas-add-some-print-to-enhance-debugging.patch b/patches.drivers/scsi-hisi_sas-add-some-print-to-enhance-debugging.patch
new file mode 100644
index 0000000000..c9e3755c7f
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-add-some-print-to-enhance-debugging.patch
@@ -0,0 +1,240 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Sat, 9 Dec 2017 01:16:41 +0800
+Subject: scsi: hisi_sas: add some print to enhance debugging
+Git-commit: f1c88211454ff8063b358f9ebe250f0fe429319c
+Patch-mainline: v4.16-rc1
+References: FATE#326253
+
+Add some print at some places such as error info and cq of exception IO,
+device found etc, and also adjust some log levels.
+
+All this to assist debugging ability.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 15 ++++++++++-----
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 24 +++++++++++++++++++-----
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 22 +++++++++++++++++-----
+ 3 files changed, 46 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index fb162c06ac83..1f6f06321c5a 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -580,6 +580,9 @@ 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);
++
+ return 0;
+ }
+
+@@ -735,7 +738,7 @@ static void hisi_sas_dev_gone(struct domain_device *device)
+ struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
+ struct device *dev = hisi_hba->dev;
+
+- dev_info(dev, "found dev[%d:%x] is gone\n",
++ dev_info(dev, "dev[%d:%x] is gone\n",
+ sas_dev->device_id, sas_dev->dev_type);
+
+ if (!test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) {
+@@ -866,12 +869,13 @@ static int hisi_sas_exec_internal_tmf_task(struct domain_device *device,
+ if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
+ struct hisi_sas_slot *slot = task->lldd_task;
+
+- dev_err(dev, "abort tmf: TMF task timeout\n");
++ dev_err(dev, "abort tmf: TMF task timeout and not done\n");
+ if (slot)
+ slot->task = NULL;
+
+ goto ex_err;
+- }
++ } else
++ dev_err(dev, "abort tmf: TMF task timeout\n");
+ }
+
+ if (task->task_status.resp == SAS_TASK_COMPLETE &&
+@@ -1495,9 +1499,10 @@ hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
+
+ if (slot)
+ slot->task = NULL;
+- dev_err(dev, "internal task abort: timeout.\n");
++ dev_err(dev, "internal task abort: timeout and not done.\n");
+ goto exit;
+- }
++ } else
++ dev_err(dev, "internal task abort: timeout.\n");
+ }
+
+ if (task->task_status.resp == SAS_TASK_COMPLETE &&
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+index cd9cd8468829..8d6886a452ef 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -2361,6 +2361,7 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
+ ts->resp = SAS_TASK_COMPLETE;
+
+ if (unlikely(aborted)) {
++ dev_dbg(dev, "slot_complete: task(%p) aborted\n", task);
+ ts->stat = SAS_ABORTED_TASK;
+ spin_lock_irqsave(&hisi_hba->lock, flags);
+ hisi_sas_slot_task_free(hisi_hba, task, slot);
+@@ -2405,6 +2406,7 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
+ (!(complete_hdr->dw0 & CMPLT_HDR_RSPNS_XFRD_MSK))) {
+ u32 err_phase = (complete_hdr->dw0 & CMPLT_HDR_ERR_PHASE_MSK)
+ >> CMPLT_HDR_ERR_PHASE_OFF;
++ u32 *error_info = hisi_sas_status_buf_addr_mem(slot);
+
+ /* Analyse error happens on which phase TX or RX */
+ if (ERR_ON_TX_PHASE(err_phase))
+@@ -2412,6 +2414,16 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
+ else if (ERR_ON_RX_PHASE(err_phase))
+ slot_err_v2_hw(hisi_hba, task, slot, 2);
+
++ if (ts->stat != SAS_DATA_UNDERRUN)
++ dev_info(dev, "erroneous completion iptt=%d task=%p "
++ "CQ hdr: 0x%x 0x%x 0x%x 0x%x "
++ "Error info: 0x%x 0x%x 0x%x 0x%x\n",
++ slot->idx, task,
++ complete_hdr->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))
+ return ts->stat;
+ goto out;
+@@ -2461,7 +2473,7 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
+ }
+
+ if (!slot->port->port_attached) {
+- dev_err(dev, "slot complete: port %d has removed\n",
++ dev_warn(dev, "slot complete: port %d has removed\n",
+ slot->port->sas_port.id);
+ ts->stat = SAS_PHY_DOWN;
+ }
+@@ -2718,10 +2730,12 @@ static int phy_down_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
+ u32 phy_state, sl_ctrl, txid_auto;
+ struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
+ struct hisi_sas_port *port = phy->port;
++ struct device *dev = hisi_hba->dev;
+
+ hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 1);
+
+ 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);
+
+ sl_ctrl = hisi_sas_phy_read32(hisi_hba, phy_no, SL_CONTROL);
+@@ -2911,7 +2925,7 @@ static void multi_bit_ecc_error_process_v2_hw(struct hisi_hba *hisi_hba,
+ val = hisi_sas_read32(hisi_hba, ecc_error->reg);
+ val &= ecc_error->msk;
+ val >>= ecc_error->shift;
+- dev_warn(dev, ecc_error->msg, irq_value, val);
++ dev_err(dev, ecc_error->msg, irq_value, val);
+ queue_work(hisi_hba->wq, &hisi_hba->rst_work);
+ }
+ }
+@@ -3020,12 +3034,12 @@ static irqreturn_t fatal_axi_int_v2_hw(int irq_no, void *p)
+ for (; sub->msk || sub->msg; sub++) {
+ if (!(err_value & sub->msk))
+ continue;
+- dev_warn(dev, "%s (0x%x) found!\n",
++ dev_err(dev, "%s (0x%x) found!\n",
+ sub->msg, irq_value);
+ queue_work(hisi_hba->wq, &hisi_hba->rst_work);
+ }
+ } else {
+- dev_warn(dev, "%s (0x%x) found!\n",
++ dev_err(dev, "%s (0x%x) found!\n",
+ axi_error->msg, irq_value);
+ queue_work(hisi_hba->wq, &hisi_hba->rst_work);
+ }
+@@ -3397,7 +3411,7 @@ static int soft_reset_v2_hw(struct hisi_hba *hisi_hba)
+
+ udelay(10);
+ if (cnt++ > 10) {
+- dev_info(dev, "wait axi bus state to idle timeout!\n");
++ dev_err(dev, "wait axi bus state to idle timeout!\n");
+ return -1;
+ }
+ }
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+index d356e12d7b98..67020bdf19c1 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -1149,7 +1149,7 @@ static int phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
+ struct dev_to_host_fis *fis;
+ u8 attached_sas_addr[SAS_ADDR_SIZE] = {0};
+
+- dev_info(dev, "phyup: phy%d link_rate=%d\n", phy_no, link_rate);
++ dev_info(dev, "phyup: phy%d link_rate=%d(sata)\n", phy_no, link_rate);
+ initial_fis = &hisi_hba->initial_fis[phy_no];
+ fis = &initial_fis->fis;
+ sas_phy->oob_mode = SATA_OOB_MODE;
+@@ -1333,7 +1333,7 @@ static irqreturn_t int_chnl_int_v3_hw(int irq_no, void *p)
+ if (!(irq_value1 & error->irq_msk))
+ continue;
+
+- dev_warn(dev, "%s error (phy%d 0x%x) found!\n",
++ dev_err(dev, "%s error (phy%d 0x%x) found!\n",
+ error->msg, phy_no, irq_value1);
+ queue_work(hisi_hba->wq, &hisi_hba->rst_work);
+ }
+@@ -1443,12 +1443,12 @@ static irqreturn_t fatal_axi_int_v3_hw(int irq_no, void *p)
+ if (!(err_value & sub->msk))
+ continue;
+
+- dev_warn(dev, "%s error (0x%x) found!\n",
++ dev_err(dev, "%s error (0x%x) found!\n",
+ sub->msg, irq_value);
+ queue_work(hisi_hba->wq, &hisi_hba->rst_work);
+ }
+ } else {
+- dev_warn(dev, "%s error (0x%x) found!\n",
++ dev_err(dev, "%s error (0x%x) found!\n",
+ error->msg, irq_value);
+ queue_work(hisi_hba->wq, &hisi_hba->rst_work);
+ }
+@@ -1553,6 +1553,7 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
+ memset(ts, 0, sizeof(*ts));
+ ts->resp = SAS_TASK_COMPLETE;
+ if (unlikely(aborted)) {
++ dev_dbg(dev, "slot complete: task(%p) aborted\n", task);
+ ts->stat = SAS_ABORTED_TASK;
+ spin_lock_irqsave(&hisi_hba->lock, flags);
+ hisi_sas_slot_task_free(hisi_hba, task, slot);
+@@ -1594,7 +1595,18 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
+
+ /* check for erroneous completion */
+ if ((complete_hdr->dw0 & CMPLT_HDR_CMPLT_MSK) == 0x3) {
++ u32 *error_info = hisi_sas_status_buf_addr_mem(slot);
++
+ slot_err_v3_hw(hisi_hba, task, slot);
++ if (ts->stat != SAS_DATA_UNDERRUN)
++ dev_info(dev, "erroneous completion iptt=%d task=%p "
++ "CQ hdr: 0x%x 0x%x 0x%x 0x%x "
++ "Error info: 0x%x 0x%x 0x%x 0x%x\n",
++ slot->idx, task,
++ complete_hdr->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))
+ return ts->stat;
+ goto out;
+@@ -1639,7 +1651,7 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
+ }
+
+ if (!slot->port->port_attached) {
+- dev_err(dev, "slot complete: port %d has removed\n",
++ dev_warn(dev, "slot complete: port %d has removed\n",
+ slot->port->sas_port.id);
+ ts->stat = SAS_PHY_DOWN;
+ }
+
diff --git a/patches.drivers/scsi-hisi_sas-add-v2-hw-force-phy-function-for-internal-ata-command.patch b/patches.drivers/scsi-hisi_sas-add-v2-hw-force-phy-function-for-internal-ata-command.patch
new file mode 100644
index 0000000000..56b3042041
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-add-v2-hw-force-phy-function-for-internal-ata-command.patch
@@ -0,0 +1,73 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Mon, 21 May 2018 18:09:22 +0800
+Subject: scsi: hisi_sas: Add v2 hw force PHY function for internal ATA command
+Git-commit: b09fcd09e9767f81187aa4036fb16d14e2f2fc79
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+This patch adds a force PHY function for internal ATA command for v2 hw.
+
+Because there is an SoC bug in v2 hw, and need send an IO through each PHY
+of a port to work around a bug which occurs after a controller reset.
+
+This force PHY function will be used in the later patch.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas.h | 2 ++
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 11 +++++++++++
+ 2 files changed, 13 insertions(+)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
+index 60bd652534fe..9400824f23ad 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas.h
++++ b/drivers/scsi/hisi_sas/hisi_sas.h
+@@ -180,6 +180,8 @@ struct hisi_sas_device {
+ };
+
+ struct hisi_sas_tmf_task {
++ int force_phy;
++ int phy_id;
+ u8 tmf;
+ u16 tag_of_task_to_be_managed;
+ };
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+index fafb3f1835be..369ef7ebb1e0 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -296,6 +296,10 @@
+ #define CMD_HDR_RESP_REPORT_MSK (0x1 << CMD_HDR_RESP_REPORT_OFF)
+ #define CMD_HDR_TLR_CTRL_OFF 6
+ #define CMD_HDR_TLR_CTRL_MSK (0x3 << CMD_HDR_TLR_CTRL_OFF)
++#define CMD_HDR_PHY_ID_OFF 8
++#define CMD_HDR_PHY_ID_MSK (0x1ff << CMD_HDR_PHY_ID_OFF)
++#define CMD_HDR_FORCE_PHY_OFF 17
++#define CMD_HDR_FORCE_PHY_MSK (0x1 << CMD_HDR_FORCE_PHY_OFF)
+ #define CMD_HDR_PORT_OFF 18
+ #define CMD_HDR_PORT_MSK (0xf << CMD_HDR_PORT_OFF)
+ #define CMD_HDR_PRIORITY_OFF 27
+@@ -2512,6 +2516,7 @@ static void prep_ata_v2_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
+ struct asd_sas_port *sas_port = device->port;
+ struct hisi_sas_port *port = to_hisi_sas_port(sas_port);
++ struct hisi_sas_tmf_task *tmf = slot->tmf;
+ u8 *buf_cmd;
+ int has_data = 0, hdr_tag = 0;
+ u32 dw1 = 0, dw2 = 0;
+@@ -2524,6 +2529,12 @@ static void prep_ata_v2_hw(struct hisi_hba *hisi_hba,
+ else
+ hdr->dw0 |= cpu_to_le32(4 << CMD_HDR_CMD_OFF);
+
++ if (tmf && tmf->force_phy) {
++ hdr->dw0 |= CMD_HDR_FORCE_PHY_MSK;
++ hdr->dw0 |= cpu_to_le32((1 << tmf->phy_id)
++ << CMD_HDR_PHY_ID_OFF);
++ }
++
+ /* dw1 */
+ switch (task->data_dir) {
+ case DMA_TO_DEVICE:
+
diff --git a/patches.drivers/scsi-hisi_sas-add-v2-hw-port-axi-error-handling-support.patch b/patches.drivers/scsi-hisi_sas-add-v2-hw-port-axi-error-handling-support.patch
new file mode 100644
index 0000000000..08582a8f8d
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-add-v2-hw-port-axi-error-handling-support.patch
@@ -0,0 +1,106 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Sat, 9 Dec 2017 01:16:43 +0800
+Subject: scsi: hisi_sas: add v2 hw port AXI error handling support
+Git-commit: 72f7fc3050d55e9877ecc56f33b7a434fca186f5
+Patch-mainline: v4.16-rc1
+References: FATE#326253
+
+Add port AXI errors handling for v2 hw. We do host controller reset for such
+errors.
+
+Besides, change port muli-bits ECC error handling, and we should also do host
+reset for such error. So, this patch put them in the same struct with port AXI
+error.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 51 ++++++++++++++++++++++++++++++----
+ 1 file changed, 45 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+index 4c4a000c5db0..725731125177 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -240,6 +240,10 @@
+ #define CHL_INT1_DMAC_TX_ECC_ERR_MSK (0x1 << CHL_INT1_DMAC_TX_ECC_ERR_OFF)
+ #define CHL_INT1_DMAC_RX_ECC_ERR_OFF 17
+ #define CHL_INT1_DMAC_RX_ECC_ERR_MSK (0x1 << CHL_INT1_DMAC_RX_ECC_ERR_OFF)
++#define CHL_INT1_DMAC_TX_AXI_WR_ERR_OFF 19
++#define CHL_INT1_DMAC_TX_AXI_RD_ERR_OFF 20
++#define CHL_INT1_DMAC_RX_AXI_WR_ERR_OFF 21
++#define CHL_INT1_DMAC_RX_AXI_RD_ERR_OFF 22
+ #define CHL_INT2 (PORT_BASE + 0x1bc)
+ #define CHL_INT0_MSK (PORT_BASE + 0x1c0)
+ #define CHL_INT1_MSK (PORT_BASE + 0x1c4)
+@@ -1182,7 +1186,7 @@ static void init_reg_v2_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, 0xfff87fff);
+ hisi_sas_phy_write32(hisi_hba, i, RXOP_CHECK_CFG_H, 0x1000);
+- hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK, 0xffffffff);
++ hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK, 0xff857fff);
+ hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0x8ffffbff);
+ hisi_sas_phy_write32(hisi_hba, i, SL_CFG, 0x13f801fc);
+ hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL_RDY_MSK, 0x0);
+@@ -2832,6 +2836,33 @@ static void phy_bcast_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
+ hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 0);
+ }
+
++static const struct hisi_sas_hw_error port_ecc_axi_error[] = {
++ {
++ .irq_msk = BIT(CHL_INT1_DMAC_TX_ECC_ERR_OFF),
++ .msg = "dmac_tx_ecc_bad_err",
++ },
++ {
++ .irq_msk = BIT(CHL_INT1_DMAC_RX_ECC_ERR_OFF),
++ .msg = "dmac_rx_ecc_bad_err",
++ },
++ {
++ .irq_msk = BIT(CHL_INT1_DMAC_TX_AXI_WR_ERR_OFF),
++ .msg = "dma_tx_axi_wr_err",
++ },
++ {
++ .irq_msk = BIT(CHL_INT1_DMAC_TX_AXI_RD_ERR_OFF),
++ .msg = "dma_tx_axi_rd_err",
++ },
++ {
++ .irq_msk = BIT(CHL_INT1_DMAC_RX_AXI_WR_ERR_OFF),
++ .msg = "dma_rx_axi_wr_err",
++ },
++ {
++ .irq_msk = BIT(CHL_INT1_DMAC_RX_AXI_RD_ERR_OFF),
++ .msg = "dma_rx_axi_rd_err",
++ },
++};
++
+ static irqreturn_t int_chnl_int_v2_hw(int irq_no, void *p)
+ {
+ struct hisi_hba *hisi_hba = p;
+@@ -2856,11 +2887,19 @@ static irqreturn_t int_chnl_int_v2_hw(int irq_no, void *p)
+ CHL_INT2);
+
+ if ((irq_msk & (1 << phy_no)) && irq_value1) {
+- if (irq_value1 & (CHL_INT1_DMAC_RX_ECC_ERR_MSK |
+- CHL_INT1_DMAC_TX_ECC_ERR_MSK))
+- panic("%s: DMAC RX/TX ecc bad error!\
+- (0x%x)",
+- dev_name(dev), irq_value1);
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(port_ecc_axi_error); i++) {
++ const struct hisi_sas_hw_error *error =
++ &port_ecc_axi_error[i];
++
++ if (!(irq_value1 & error->irq_msk))
++ continue;
++
++ dev_warn(dev, "%s error (phy%d 0x%x) found!\n",
++ error->msg, phy_no, irq_value1);
++ queue_work(hisi_hba->wq, &hisi_hba->rst_work);
++ }
+
+ hisi_sas_phy_write32(hisi_hba, phy_no,
+ CHL_INT1, irq_value1);
+
diff --git a/patches.drivers/scsi-hisi_sas-add-v3-hw-module_device_table.patch b/patches.drivers/scsi-hisi_sas-add-v3-hw-module_device_table.patch
new file mode 100644
index 0000000000..422361689b
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-add-v3-hw-module_device_table.patch
@@ -0,0 +1,39 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Wed, 7 Mar 2018 20:25:14 +0800
+Subject: scsi: hisi_sas: add v3 hw MODULE_DEVICE_TABLE()
+Git-commit: 40ec66b1bf4352315025b821f7a5aead3d8ea645
+Patch-mainline: v4.17-rc1
+References: FATE#326253
+
+Export device table of v3 hw to userspace, or auto probe will fail for v3
+hw.
+
+Also change the module alias to include "pci", instead of "platform".
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ 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 5ce5ef2caabe..6f3e5ba6b472 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -2394,6 +2394,7 @@ static const struct pci_device_id sas_v3_pci_table[] = {
+ { PCI_VDEVICE(HUAWEI, 0xa230), hip08 },
+ {}
+ };
++MODULE_DEVICE_TABLE(pci, sas_v3_pci_table);
+
+ static const struct pci_error_handlers hisi_sas_err_handler = {
+ .error_detected = hisi_sas_error_detected_v3_hw,
+@@ -2416,4 +2417,4 @@ module_pci_driver(sas_v3_pci_driver);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("John Garry <john.garry@huawei.com>");
+ MODULE_DESCRIPTION("HISILICON SAS controller v3 hw driver based on pci device");
+-MODULE_ALIAS("platform:" DRV_NAME);
++MODULE_ALIAS("pci:" DRV_NAME);
+
diff --git a/patches.drivers/scsi-hisi_sas-add-v3-hw-suspend-and-resume.patch b/patches.drivers/scsi-hisi_sas-add-v3-hw-suspend-and-resume.patch
new file mode 100644
index 0000000000..6c0b07b7ee
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-add-v3-hw-suspend-and-resume.patch
@@ -0,0 +1,172 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Sat, 9 Dec 2017 01:16:50 +0800
+Subject: scsi: hisi_sas: add v3 hw suspend and resume
+Git-commit: 4d0951ee70d348b694ce2bbdcc65b684239da4b4
+Patch-mainline: v4.16-rc1
+References: FATE#326253
+
+For v3 hw SAS, it supports configuring power state from D0 to D3 for entering
+Low Power status and power state from D3 to D0 for quit Low Power status.
+
+When power state from D0 to D3, HW will send FLR to clear the registers of
+ECAM and BAR space, and when power state from D3 to D0, it will clear the
+registers of ECAM space only.
+
+So when suspend, need to do like controller reset (including disable
+interrupts/DQ/PHY/BUS), and also release slots after FLR. When resume,
+re-config the registers of BAR space.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas.h | 1 +
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 3 +-
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 94 ++++++++++++++++++++++++++++++++++
+ 3 files changed, 97 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
+index 4343c4ce338d..cc050299cc0b 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas.h
++++ b/drivers/scsi/hisi_sas/hisi_sas.h
+@@ -461,4 +461,5 @@ extern void hisi_sas_sync_rst_work_handler(struct work_struct *work);
+ extern void hisi_sas_kill_tasklets(struct hisi_hba *hisi_hba);
+ 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);
+ #endif
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index ad122378b84a..04e1172b0bc5 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -737,7 +737,7 @@ static void hisi_sas_release_task(struct hisi_hba *hisi_hba,
+ hisi_sas_do_release_task(hisi_hba, slot->task, slot);
+ }
+
+-static void hisi_sas_release_tasks(struct hisi_hba *hisi_hba)
++void hisi_sas_release_tasks(struct hisi_hba *hisi_hba)
+ {
+ struct hisi_sas_device *sas_dev;
+ struct domain_device *device;
+@@ -754,6 +754,7 @@ static void hisi_sas_release_tasks(struct hisi_hba *hisi_hba)
+ hisi_sas_release_task(hisi_hba, device);
+ }
+ }
++EXPORT_SYMBOL_GPL(hisi_sas_release_tasks);
+
+ static void hisi_sas_dereg_device(struct hisi_hba *hisi_hba,
+ struct domain_device *device)
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+index 9e321050cdc2..6a408d2e92f5 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -2303,6 +2303,98 @@ enum {
+ hip08,
+ };
+
++static int hisi_sas_v3_suspend(struct pci_dev *pdev, pm_message_t state)
++{
++ struct sas_ha_struct *sha = pci_get_drvdata(pdev);
++ struct hisi_hba *hisi_hba = sha->lldd_ha;
++ struct device *dev = hisi_hba->dev;
++ struct Scsi_Host *shost = hisi_hba->shost;
++ u32 device_state, status;
++ int rc;
++ u32 reg_val;
++ unsigned long flags;
++
++ if (!pdev->pm_cap) {
++ dev_err(dev, "PCI PM not supported\n");
++ return -ENODEV;
++ }
++
++ set_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags);
++ scsi_block_requests(shost);
++ set_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
++ flush_workqueue(hisi_hba->wq);
++ /* disable DQ/PHY/bus */
++ 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);
++
++ reg_val = hisi_sas_read32(hisi_hba, AXI_MASTER_CFG_BASE +
++ AM_CTRL_GLOBAL);
++ reg_val |= 0x1;
++ hisi_sas_write32(hisi_hba, AXI_MASTER_CFG_BASE +
++ AM_CTRL_GLOBAL, reg_val);
++
++ /* wait until bus idle */
++ rc = readl_poll_timeout(hisi_hba->regs + AXI_MASTER_CFG_BASE +
++ AM_CURR_TRANS_RETURN, status, status == 0x3, 10, 100);
++ if (rc) {
++ dev_err(dev, "axi bus is not idle, 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;
++ }
++
++ hisi_sas_init_mem(hisi_hba);
++
++ device_state = pci_choose_state(pdev, state);
++ 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);
++
++ spin_lock_irqsave(&hisi_hba->lock, flags);
++ hisi_sas_release_tasks(hisi_hba);
++ spin_unlock_irqrestore(&hisi_hba->lock, flags);
++
++ sas_suspend_ha(sha);
++ return 0;
++}
++
++static int hisi_sas_v3_resume(struct pci_dev *pdev)
++{
++ struct sas_ha_struct *sha = pci_get_drvdata(pdev);
++ struct hisi_hba *hisi_hba = sha->lldd_ha;
++ struct Scsi_Host *shost = hisi_hba->shost;
++ struct device *dev = hisi_hba->dev;
++ unsigned int rc;
++ u32 device_state = pdev->current_state;
++
++ 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);
++
++ pci_set_master(pdev);
++ scsi_unblock_requests(shost);
++ clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
++
++ sas_prep_resume_ha(sha);
++ init_reg_v3_hw(hisi_hba);
++ hisi_hba->hw->phys_init(hisi_hba);
++ sas_resume_ha(sha);
++ clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags);
++
++ return 0;
++}
++
+ static const struct pci_device_id sas_v3_pci_table[] = {
+ { PCI_VDEVICE(HUAWEI, 0xa230), hip08 },
+ {}
+@@ -2319,6 +2411,8 @@ static struct pci_driver sas_v3_pci_driver = {
+ .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,
+ };
+
+
diff --git a/patches.drivers/scsi-hisi_sas-allocate-slot-buffer-earlier.patch b/patches.drivers/scsi-hisi_sas-allocate-slot-buffer-earlier.patch
new file mode 100644
index 0000000000..54bfb0443f
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-allocate-slot-buffer-earlier.patch
@@ -0,0 +1,141 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Wed, 9 May 2018 23:10:47 +0800
+Subject: scsi: hisi_sas: allocate slot buffer earlier
+Git-commit: 3de0026dad6b8e83d8a699aef92638c50ba966f7
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+Currently we allocate the slot's memory buffer after allocating the DQ
+slot.
+
+To aid DQ lockout reduction, and allow slots to be built in parallel,
+move this step (which can fail) prior to allocating the slot.
+
+Also a stray spin_unlock_irqrestore() is removed from internal task exec
+function.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 55 ++++++++++++++++++++---------------
+ 1 file changed, 31 insertions(+), 24 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 2772e920572d..58cbe1f0e0b6 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -412,14 +412,22 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
+ if (rc)
+ goto err_out_dma_unmap;
+
++ slot = &hisi_hba->slot_info[slot_idx];
++ memset(slot, 0, sizeof(struct hisi_sas_slot));
++
++ slot->buf = dma_pool_alloc(hisi_hba->buffer_pool,
++ GFP_ATOMIC, &slot->buf_dma);
++ if (!slot->buf) {
++ rc = -ENOMEM;
++ goto err_out_tag;
++ }
++
+ rc = hisi_hba->hw->get_free_slot(hisi_hba, dq);
+ if (rc)
+- goto err_out_tag;
++ goto err_out_buf;
+
+ dlvry_queue = dq->id;
+ dlvry_queue_slot = dq->wr_point;
+- slot = &hisi_hba->slot_info[slot_idx];
+- memset(slot, 0, sizeof(struct hisi_sas_slot));
+
+ slot->idx = slot_idx;
+ slot->n_elem = n_elem;
+@@ -434,12 +442,6 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
+ task->lldd_task = slot;
+ INIT_WORK(&slot->abort_slot, hisi_sas_slot_abort);
+
+- slot->buf = dma_pool_alloc(hisi_hba->buffer_pool,
+- GFP_ATOMIC, &slot->buf_dma);
+- if (!slot->buf) {
+- rc = -ENOMEM;
+- goto err_out_slot_buf;
+- }
+ memset(slot->cmd_hdr, 0, sizeof(struct hisi_sas_cmd_hdr));
+ memset(hisi_sas_cmd_hdr_addr_mem(slot), 0, HISI_SAS_COMMAND_TABLE_SZ);
+ memset(hisi_sas_status_buf_addr_mem(slot), 0, HISI_SAS_STATUS_BUF_SZ);
+@@ -474,8 +476,9 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
+
+ return 0;
+
+-err_out_slot_buf:
+- /* Nothing to be done */
++err_out_buf:
++ dma_pool_free(hisi_hba->buffer_pool, slot->buf,
++ slot->buf_dma);
+ err_out_tag:
+ spin_lock_irqsave(&hisi_hba->lock, flags);
+ hisi_sas_slot_index_free(hisi_hba, slot_idx);
+@@ -1519,17 +1522,26 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id,
+ }
+ spin_unlock_irqrestore(&hisi_hba->lock, flags);
+
++ slot = &hisi_hba->slot_info[slot_idx];
++ memset(slot, 0, sizeof(struct hisi_sas_slot));
++
++ slot->buf = dma_pool_alloc(hisi_hba->buffer_pool,
++ GFP_ATOMIC, &slot->buf_dma);
++ if (!slot->buf) {
++ rc = -ENOMEM;
++ goto err_out_tag;
++ }
+ spin_lock_irqsave(&dq->lock, flags_dq);
+ rc = hisi_hba->hw->get_free_slot(hisi_hba, dq);
+- if (rc)
+- goto err_out_tag;
++ if (rc) {
++ rc = -ENOMEM;
++ spin_unlock_irqrestore(&dq->lock, flags_dq);
++ goto err_out_buf;
++ }
+
+ dlvry_queue = dq->id;
+ dlvry_queue_slot = dq->wr_point;
+
+- slot = &hisi_hba->slot_info[slot_idx];
+- memset(slot, 0, sizeof(struct hisi_sas_slot));
+-
+ slot->idx = slot_idx;
+ slot->n_elem = n_elem;
+ slot->dlvry_queue = dlvry_queue;
+@@ -1541,13 +1553,6 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id,
+ slot->is_internal = true;
+ task->lldd_task = slot;
+
+- slot->buf = dma_pool_alloc(hisi_hba->buffer_pool,
+- GFP_ATOMIC, &slot->buf_dma);
+- if (!slot->buf) {
+- rc = -ENOMEM;
+- goto err_out_tag;
+- }
+-
+ memset(slot->cmd_hdr, 0, sizeof(struct hisi_sas_cmd_hdr));
+ memset(hisi_sas_cmd_hdr_addr_mem(slot), 0, HISI_SAS_COMMAND_TABLE_SZ);
+ memset(hisi_sas_status_buf_addr_mem(slot), 0, HISI_SAS_STATUS_BUF_SZ);
+@@ -1570,11 +1575,13 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id,
+
+ return 0;
+
++err_out_buf:
++ dma_pool_free(hisi_hba->buffer_pool, slot->buf,
++ slot->buf_dma);
+ err_out_tag:
+ spin_lock_irqsave(&hisi_hba->lock, flags);
+ hisi_sas_slot_index_free(hisi_hba, slot_idx);
+ spin_unlock_irqrestore(&hisi_hba->lock, flags);
+- spin_unlock_irqrestore(&dq->lock, flags_dq);
+ err_out:
+ dev_err(dev, "internal abort task prep: failed[%d]!\n", rc);
+
+
diff --git a/patches.drivers/scsi-hisi_sas-change-common-allocation-mode-of-device-id.patch b/patches.drivers/scsi-hisi_sas-change-common-allocation-mode-of-device-id.patch
new file mode 100644
index 0000000000..f51196e11e
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-change-common-allocation-mode-of-device-id.patch
@@ -0,0 +1,61 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Mon, 21 May 2018 18:09:15 +0800
+Subject: scsi: hisi_sas: Change common allocation mode of device id
+Git-commit: 1b86518581f6111f5996ff8d4304bde2e3b05eb9
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+To reduce possibility of hitting unknown SoC bugs and aid debugging and
+test, change allocation mode of device id from last used device id instead
+of lowest available index.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas.h | 1 +
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 6 +++++-
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
+index 3c8840089cd5..b4717bd8af3f 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas.h
++++ b/drivers/scsi/hisi_sas/hisi_sas.h
+@@ -275,6 +275,7 @@ struct hisi_hba {
+
+ int slot_index_count;
+ int last_slot_index;
++ int last_dev_id;
+ unsigned long *slot_index_tags;
+ unsigned long reject_stp_links_msk;
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 796fdfc73c75..a7e4c6e77068 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -596,10 +596,12 @@ static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device)
+ struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
+ struct hisi_sas_device *sas_dev = NULL;
+ unsigned long flags;
++ int last = hisi_hba->last_dev_id;
++ int first = (hisi_hba->last_dev_id + 1) % HISI_SAS_MAX_DEVICES;
+ int i;
+
+ spin_lock_irqsave(&hisi_hba->lock, flags);
+- for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
++ for (i = first; i != last; i %= HISI_SAS_MAX_DEVICES) {
+ if (hisi_hba->devices[i].dev_type == SAS_PHY_UNUSED) {
+ int queue = i % hisi_hba->queue_count;
+ struct hisi_sas_dq *dq = &hisi_hba->dq[queue];
+@@ -614,7 +616,9 @@ static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device)
+ INIT_LIST_HEAD(&hisi_hba->devices[i].list);
+ break;
+ }
++ i++;
+ }
++ hisi_hba->last_dev_id = i;
+ spin_unlock_irqrestore(&hisi_hba->lock, flags);
+
+ return sas_dev;
+
diff --git a/patches.drivers/scsi-hisi_sas-change-frame-type-for-set-max-commands.patch b/patches.drivers/scsi-hisi_sas-change-frame-type-for-set-max-commands.patch
new file mode 100644
index 0000000000..5438917ed1
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-change-frame-type-for-set-max-commands.patch
@@ -0,0 +1,106 @@
+From: chenxiang <chenxiang66@hisilicon.com>
+Date: Thu, 28 Dec 2017 18:20:47 +0800
+Subject: scsi: hisi_sas: Change frame type for SET MAX commands
+Git-commit: 468f4b8d0711146f0075513e6047079a26fc3903
+Patch-mainline: v4.16-rc1
+References: FATE#326253
+
+According to ATA protocol, SET MAX commands belong to different frame
+types. So judge features field of SET MAX commands to decide which
+frame type they belongs to.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas.h | 3 ++-
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 20 ++++++++++++++++++--
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2 +-
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 2 +-
+ 4 files changed, 22 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
+index cc050299cc0b..4000de429430 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas.h
++++ b/drivers/scsi/hisi_sas/hisi_sas.h
+@@ -441,7 +441,8 @@ extern void hisi_sas_stop_phys(struct hisi_hba *hisi_hba);
+ extern void hisi_sas_init_add(struct hisi_hba *hisi_hba);
+ extern int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost);
+ extern void hisi_sas_free(struct hisi_hba *hisi_hba);
+-extern u8 hisi_sas_get_ata_protocol(u8 cmd, int direction);
++extern u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis,
++ int direction);
+ extern struct hisi_sas_port *to_hisi_sas_port(struct asd_sas_port *sas_port);
+ extern void hisi_sas_sata_done(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 819b1d0ded89..360ecefba10a 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -25,9 +25,9 @@ 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);
+
+-u8 hisi_sas_get_ata_protocol(u8 cmd, int direction)
++u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction)
+ {
+- switch (cmd) {
++ switch (fis->command) {
+ case ATA_CMD_FPDMA_WRITE:
+ case ATA_CMD_FPDMA_READ:
+ case ATA_CMD_FPDMA_RECV:
+@@ -79,10 +79,26 @@ u8 hisi_sas_get_ata_protocol(u8 cmd, int direction)
+ case ATA_CMD_ZAC_MGMT_OUT:
+ return HISI_SAS_SATA_PROTOCOL_NONDATA;
+ default:
++ {
++ if (fis->command == ATA_CMD_SET_MAX) {
++ switch (fis->features) {
++ case ATA_SET_MAX_PASSWD:
++ case ATA_SET_MAX_LOCK:
++ return HISI_SAS_SATA_PROTOCOL_PIO;
++
++ case ATA_SET_MAX_PASSWD_DMA:
++ case ATA_SET_MAX_UNLOCK_DMA:
++ return HISI_SAS_SATA_PROTOCOL_DMA;
++
++ default:
++ return HISI_SAS_SATA_PROTOCOL_NONDATA;
++ }
++ }
+ if (direction == DMA_NONE)
+ return HISI_SAS_SATA_PROTOCOL_NONDATA;
+ return HISI_SAS_SATA_PROTOCOL_PIO;
+ }
++ }
+ }
+ EXPORT_SYMBOL_GPL(hisi_sas_get_ata_protocol);
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+index b8fe08d9b1ce..ebee2e463245 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -2539,7 +2539,7 @@ static int prep_ata_v2_hw(struct hisi_hba *hisi_hba,
+ dw1 |= 1 << CMD_HDR_RESET_OFF;
+
+ dw1 |= (hisi_sas_get_ata_protocol(
+- task->ata_task.fis.command, task->data_dir))
++ &task->ata_task.fis, task->data_dir))
+ << CMD_HDR_FRAME_TYPE_OFF;
+ dw1 |= sas_dev->device_id << CMD_HDR_DEV_ID_OFF;
+ hdr->dw1 = cpu_to_le32(dw1);
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+index 6a408d2e92f5..a1f18689729a 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -1047,7 +1047,7 @@ static int prep_ata_v3_hw(struct hisi_hba *hisi_hba,
+ dw1 |= 1 << CMD_HDR_RESET_OFF;
+
+ dw1 |= (hisi_sas_get_ata_protocol(
+- task->ata_task.fis.command, task->data_dir))
++ &task->ata_task.fis, task->data_dir))
+ << CMD_HDR_FRAME_TYPE_OFF;
+ dw1 |= sas_dev->device_id << CMD_HDR_DEV_ID_OFF;
+
+
diff --git a/patches.drivers/scsi-hisi_sas-change-ncq-process-for-v3-hw.patch b/patches.drivers/scsi-hisi_sas-change-ncq-process-for-v3-hw.patch
new file mode 100644
index 0000000000..76a8610ab5
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-change-ncq-process-for-v3-hw.patch
@@ -0,0 +1,78 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Sat, 9 Dec 2017 01:16:39 +0800
+Subject: scsi: hisi_sas: change ncq process for v3 hw
+Git-commit: 9f347b2face51d782d1e03f2f05b7c3f93a6dc9a
+Patch-mainline: v4.16-rc1
+References: FATE#326253
+
+For v3 hw, each NCQ will return a CQ, so it is no need to acquire IPTT from
+ITCT, just acquire it from IPTT field of CQ.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 40 +++++-----------------------------
+ 1 file changed, 6 insertions(+), 34 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+index 44f07bc37177..69aa7bc15783 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -1653,9 +1653,8 @@ static void cq_tasklet_v3_hw(unsigned long val)
+ struct hisi_sas_cq *cq = (struct hisi_sas_cq *)val;
+ struct hisi_hba *hisi_hba = cq->hisi_hba;
+ struct hisi_sas_slot *slot;
+- struct hisi_sas_itct *itct;
+ struct hisi_sas_complete_v3_hdr *complete_queue;
+- u32 rd_point = cq->rd_point, wr_point, dev_id;
++ u32 rd_point = cq->rd_point, wr_point;
+ int queue = cq->id;
+ struct hisi_sas_dq *dq = &hisi_hba->dq[queue];
+
+@@ -1671,38 +1670,11 @@ static void cq_tasklet_v3_hw(unsigned long val)
+
+ complete_hdr = &complete_queue[rd_point];
+
+- /* Check for NCQ completion */
+- if (complete_hdr->act) {
+- u32 act_tmp = complete_hdr->act;
+- int ncq_tag_count = ffs(act_tmp);
+-
+- dev_id = (complete_hdr->dw1 & CMPLT_HDR_DEV_ID_MSK) >>
+- CMPLT_HDR_DEV_ID_OFF;
+- itct = &hisi_hba->itct[dev_id];
+-
+- /* The NCQ tags are held in the itct header */
+- while (ncq_tag_count) {
+- __le64 *ncq_tag = &itct->qw4_15[0];
+-
+- ncq_tag_count -= 1;
+- iptt = (ncq_tag[ncq_tag_count / 5]
+- >> (ncq_tag_count % 5) * 12) & 0xfff;
+-
+- slot = &hisi_hba->slot_info[iptt];
+- slot->cmplt_queue_slot = rd_point;
+- slot->cmplt_queue = queue;
+- slot_complete_v3_hw(hisi_hba, slot);
+-
+- act_tmp &= ~(1 << ncq_tag_count);
+- ncq_tag_count = ffs(act_tmp);
+- }
+- } else {
+- iptt = (complete_hdr->dw1) & CMPLT_HDR_IPTT_MSK;
+- slot = &hisi_hba->slot_info[iptt];
+- slot->cmplt_queue_slot = rd_point;
+- slot->cmplt_queue = queue;
+- slot_complete_v3_hw(hisi_hba, slot);
+- }
++ iptt = (complete_hdr->dw1) & CMPLT_HDR_IPTT_MSK;
++ slot = &hisi_hba->slot_info[iptt];
++ slot->cmplt_queue_slot = rd_point;
++ slot->cmplt_queue = queue;
++ slot_complete_v3_hw(hisi_hba, slot);
+
+ if (++rd_point >= HISI_SAS_QUEUE_SLOTS)
+ rd_point = 0;
+
diff --git a/patches.drivers/scsi-hisi_sas-change-slot-index-allocation-mode.patch b/patches.drivers/scsi-hisi_sas-change-slot-index-allocation-mode.patch
new file mode 100644
index 0000000000..07ba557e18
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-change-slot-index-allocation-mode.patch
@@ -0,0 +1,64 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Mon, 21 May 2018 18:09:14 +0800
+Subject: scsi: hisi_sas: change slot index allocation mode
+Git-commit: fa3be0f23139ddc4dffbfdef6bbd118e30dfcafe
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+Currently we find the lowest available empty bit in the IPTT bitmap to
+allocate the IPTT for a command.
+
+To reduce possibility of hitting unknown SoC bugs and also aid in the
+debugging of those same bugs, change the allocation mode.
+
+The next allocation method is to use the next free slot adjacent to the
+most recently allocated slot, in a round-robin fashion.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas.h | 1 +
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 13 ++++++++++---
+ 2 files changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
+index 52fc709dd862..3c8840089cd5 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas.h
++++ b/drivers/scsi/hisi_sas/hisi_sas.h
+@@ -274,6 +274,7 @@ struct hisi_hba {
+ struct workqueue_struct *wq;
+
+ int slot_index_count;
++ int last_slot_index;
+ unsigned long *slot_index_tags;
+ unsigned long reject_stp_links_msk;
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 66388741e73c..796fdfc73c75 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -195,11 +195,18 @@ static int hisi_sas_slot_index_alloc(struct hisi_hba *hisi_hba, int *slot_idx)
+ unsigned int index;
+ void *bitmap = hisi_hba->slot_index_tags;
+
+- index = find_first_zero_bit(bitmap, hisi_hba->slot_index_count);
+- if (index >= hisi_hba->slot_index_count)
+- return -SAS_QUEUE_FULL;
++ index = find_next_zero_bit(bitmap, hisi_hba->slot_index_count,
++ hisi_hba->last_slot_index + 1);
++ if (index >= hisi_hba->slot_index_count) {
++ index = find_next_zero_bit(bitmap, hisi_hba->slot_index_count,
++ 0);
++ if (index >= hisi_hba->slot_index_count)
++ return -SAS_QUEUE_FULL;
++ }
+ hisi_sas_slot_index_set(hisi_hba, index);
+ *slot_idx = index;
++ hisi_hba->last_slot_index = index;
++
+ return 0;
+ }
+
+
diff --git a/patches.drivers/scsi-hisi_sas-check-host-frozen-before-calling-done-function.patch b/patches.drivers/scsi-hisi_sas-check-host-frozen-before-calling-done-function.patch
new file mode 100644
index 0000000000..f84bb379ae
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-check-host-frozen-before-calling-done-function.patch
@@ -0,0 +1,164 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Wed, 2 May 2018 23:56:26 +0800
+Subject: scsi: hisi_sas: check host frozen before calling "done" function
+Git-commit: cd938e535e909b80948f26d284ba7475adee0c08
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+When the host is frozen in SCSI EH state, at any point after the LLDD
+sets SAS_TASK_STATE_DONE for the sas_task task state, libsas may free
+the task; see sas_scsi_find_task().
+
+This puts the LLDD in a difficult position, in that once it sets
+SAS_TASK_STATE_DONE for the task state it should not reference the
+sas_task again. But the LLDD needs will check the sas_task indirectly in
+calling task->task_done()->sas_scsi_task_done() or sas_ata_task_done()
+(to check if the host is frozen state actually).
+
+And the LLDD cannot set SAS_TASK_STATE_DONE for the task state after
+task->task_done() is called (as the sas_task is free'd at this point).
+
+This situation would seem to be a problem made by libsas.
+
+To work around, check in the LLDD whether the host is in frozen state to
+ensure it is ok to call task->task_done() function. If in the frozen
+state, we rely on SCSI EH and libsas to free the sas_task directly.
+
+We do not do this for the following IO types:
+
+ - SMP - they are managed in libsas directly, outside SCSI EH
+ - Any internally originated IO, for similar reason
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas.h | 1 +
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 3 +++
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 14 ++++++++++++++
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 14 ++++++++++++++
+ 4 files changed, 32 insertions(+)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
+index d413d05fda26..147cfafdad9f 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas.h
++++ b/drivers/scsi/hisi_sas/hisi_sas.h
+@@ -196,6 +196,7 @@ struct hisi_sas_slot {
+ dma_addr_t cmd_hdr_dma;
+ struct work_struct abort_slot;
+ struct timer_list internal_abort_timer;
++ bool is_internal;
+ };
+
+ struct hisi_sas_tmf_task {
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 52746e2e7f6f..8f8e6424ee1d 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -382,6 +382,8 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
+ slot->cmd_hdr = &cmd_hdr_base[dlvry_queue_slot];
+ slot->task = task;
+ slot->port = port;
++ if (is_tmf)
++ slot->is_internal = true;
+ task->lldd_task = slot;
+ INIT_WORK(&slot->abort_slot, hisi_sas_slot_abort);
+
+@@ -1486,6 +1488,7 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id,
+ slot->cmd_hdr = &cmd_hdr_base[dlvry_queue_slot];
+ slot->task = task;
+ slot->port = port;
++ slot->is_internal = true;
+ task->lldd_task = slot;
+
+ slot->buf = dma_pool_alloc(hisi_hba->buffer_pool,
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+index 8ca0044e09be..6dda6eb50918 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -2380,18 +2380,21 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
+ struct device *dev = hisi_hba->dev;
+ 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 =
+ &complete_queue[slot->cmplt_queue_slot];
+ unsigned long flags;
++ bool is_internal = slot->is_internal;
+
+ if (unlikely(!task || !task->lldd_task || !task->dev))
+ return -EINVAL;
+
+ ts = &task->task_status;
+ device = task->dev;
++ ha = device->port->ha;
+ sas_dev = device->lldd_dev;
+
+ spin_lock_irqsave(&task->task_state_lock, flags);
+@@ -2523,6 +2526,17 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
+ task->task_state_flags |= SAS_TASK_STATE_DONE;
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
+
++ if (!is_internal && (task->task_proto != SAS_PROTOCOL_SMP)) {
++ 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(%p) ignored\n ",
++ task);
++ return sts;
++ }
++ spin_unlock_irqrestore(&device->done_lock, flags);
++ }
++
+ if (task->task_done)
+ task->task_done(task);
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+index 734611046d3e..5c0d9683630b 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -1571,18 +1571,21 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
+ struct device *dev = hisi_hba->dev;
+ 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 =
+ &complete_queue[slot->cmplt_queue_slot];
+ unsigned long flags;
++ bool is_internal = slot->is_internal;
+
+ if (unlikely(!task || !task->lldd_task || !task->dev))
+ return -EINVAL;
+
+ ts = &task->task_status;
+ device = task->dev;
++ ha = device->port->ha;
+ sas_dev = device->lldd_dev;
+
+ spin_lock_irqsave(&task->task_state_lock, flags);
+@@ -1700,6 +1703,17 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
+ task->task_state_flags |= SAS_TASK_STATE_DONE;
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
+
++ if (!is_internal && (task->task_proto != SAS_PROTOCOL_SMP)) {
++ 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(%p) ignored\n ",
++ task);
++ return sts;
++ }
++ spin_unlock_irqrestore(&device->done_lock, flags);
++ }
++
+ if (task->task_done)
+ task->task_done(task);
+
+
diff --git a/patches.drivers/scsi-hisi_sas-check-iptt-is-valid-before-using-it-for-v3-hw.patch b/patches.drivers/scsi-hisi_sas-check-iptt-is-valid-before-using-it-for-v3-hw.patch
new file mode 100644
index 0000000000..d12338aa2a
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-check-iptt-is-valid-before-using-it-for-v3-hw.patch
@@ -0,0 +1,53 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Sat, 24 Mar 2018 00:05:13 +0800
+Subject: scsi: hisi_sas: check IPTT is valid before using it for v3 hw
+Git-commit: 327f242fa806c199a183c2197592e94d336c8266
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+There is a bug of v3 hw development version. When AXI error happen, hw
+may return an abnormal CQ that IPTT value is 0xffff. This will cause
+IPTT out-of-bounds reference.
+
+This patch adds a check of IPTT in cq_tasklet_v3_hw() and discards
+invalid slot. This workaround scheme is just to enhance fault-tolerance
+of the driver. So, we will apply this scheme for all version of v3 hw,
+although release version has fixed this SoC bug.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 12 ++++++++----
+ 1 file changed, 8 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 efe64bcfa4f2..aa52d5e424f7 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -1731,15 +1731,19 @@ static void cq_tasklet_v3_hw(unsigned long val)
+
+ while (rd_point != wr_point) {
+ struct hisi_sas_complete_v3_hdr *complete_hdr;
++ struct device *dev = hisi_hba->dev;
+ int iptt;
+
+ complete_hdr = &complete_queue[rd_point];
+
+ iptt = (complete_hdr->dw1) & CMPLT_HDR_IPTT_MSK;
+- slot = &hisi_hba->slot_info[iptt];
+- slot->cmplt_queue_slot = rd_point;
+- slot->cmplt_queue = queue;
+- slot_complete_v3_hw(hisi_hba, slot);
++ if (likely(iptt < HISI_SAS_COMMAND_ENTRIES_V3_HW)) {
++ slot = &hisi_hba->slot_info[iptt];
++ slot->cmplt_queue_slot = rd_point;
++ slot->cmplt_queue = queue;
++ slot_complete_v3_hw(hisi_hba, slot);
++ } else
++ dev_err(dev, "IPTT %d is invalid, discard it.\n", iptt);
+
+ if (++rd_point >= HISI_SAS_QUEUE_SLOTS)
+ rd_point = 0;
+
diff --git a/patches.drivers/scsi-hisi_sas-check-sas_dev-gone-earlier-in-hisi_sas_abort_task.patch b/patches.drivers/scsi-hisi_sas-check-sas_dev-gone-earlier-in-hisi_sas_abort_task.patch
new file mode 100644
index 0000000000..63b876d1bc
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-check-sas_dev-gone-earlier-in-hisi_sas_abort_task.patch
@@ -0,0 +1,55 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Wed, 2 May 2018 23:56:28 +0800
+Subject: scsi: hisi_sas: check sas_dev gone earlier in hisi_sas_abort_task()
+Git-commit: c6ef895472696cac8e50f0ce69b301cc10233a67
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+It is possible to dereference a NULL-pointer in hisi_sas_abort_task() in
+special scenario when the device has been removed.
+
+If an SMP task times-out, it will call hisi_sas_abort_task() to
+recover. And currently there is a check in hisi_sas_abort_task() to
+avoid the situation of processing the abort for the removed device.
+
+However we have an ordering problem, in that we may reference a task for
+the removed device before checking if the device has been removed.
+
+Fix this by only referencing the sas_dev after we know it is still
+present.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 8f8e6424ee1d..24416bb66027 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -1166,15 +1166,16 @@ static int hisi_sas_abort_task(struct sas_task *task)
+ struct hisi_sas_tmf_task tmf_task;
+ struct domain_device *device = task->dev;
+ struct hisi_sas_device *sas_dev = device->lldd_dev;
+- struct hisi_hba *hisi_hba = dev_to_hisi_hba(task->dev);
+- struct device *dev = hisi_hba->dev;
++ struct hisi_hba *hisi_hba;
++ struct device *dev;
+ int rc = TMF_RESP_FUNC_FAILED;
+ unsigned long flags;
+
+- if (!sas_dev) {
+- dev_warn(dev, "Device has been removed\n");
++ if (!sas_dev)
+ return TMF_RESP_FUNC_FAILED;
+- }
++
++ hisi_hba = dev_to_hisi_hba(task->dev);
++ dev = hisi_hba->dev;
+
+ spin_lock_irqsave(&task->task_state_lock, flags);
+ if (task->task_state_flags & SAS_TASK_STATE_DONE) {
+
diff --git a/patches.drivers/scsi-hisi_sas-code-cleanup-and-minor-bug-fixes.patch b/patches.drivers/scsi-hisi_sas-code-cleanup-and-minor-bug-fixes.patch
new file mode 100644
index 0000000000..2b24bee100
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-code-cleanup-and-minor-bug-fixes.patch
@@ -0,0 +1,244 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Wed, 7 Mar 2018 20:25:12 +0800
+Subject: scsi: hisi_sas: Code cleanup and minor bug fixes
+Git-commit: edafeef4f28ded4ea9ba7876cc35861d43c7b2b1
+Patch-mainline: v4.17-rc1
+References: FATE#326253
+
+The patch does some code cleanup and fixes some small bugs:
+
+- Correct return status of phy_up_v3_hw() and phy_bcast_v3_hw()
+- Add static for function phy_get_max_linkrate_v3_hw()
+- Change exception return status when no reset method
+- Change magic value to ts->stat in slot_complete_vx_hw()
+- Remove unnecessary check for dev_is_sata()
+- Fix some issues of alignment and indents (Authored by Xiaofei Tan in
+ another patch, but added here to be practical)
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 14 +++++++-------
+ drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 4 +++-
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 10 ++++++----
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 28 +++++++++++++++++-----------
+ 4 files changed, 33 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index dff972393086..49c1fa643803 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -33,7 +33,7 @@ u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction)
+ case ATA_CMD_FPDMA_RECV:
+ case ATA_CMD_FPDMA_SEND:
+ case ATA_CMD_NCQ_NON_DATA:
+- return HISI_SAS_SATA_PROTOCOL_FPDMA;
++ return HISI_SAS_SATA_PROTOCOL_FPDMA;
+
+ case ATA_CMD_DOWNLOAD_MICRO:
+ case ATA_CMD_ID_ATA:
+@@ -45,7 +45,7 @@ u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction)
+ case ATA_CMD_WRITE_LOG_EXT:
+ case ATA_CMD_PIO_WRITE:
+ case ATA_CMD_PIO_WRITE_EXT:
+- return HISI_SAS_SATA_PROTOCOL_PIO;
++ return HISI_SAS_SATA_PROTOCOL_PIO;
+
+ case ATA_CMD_DSM:
+ case ATA_CMD_DOWNLOAD_MICRO_DMA:
+@@ -64,7 +64,7 @@ u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction)
+ case ATA_CMD_WRITE_LOG_DMA_EXT:
+ case ATA_CMD_WRITE_STREAM_DMA_EXT:
+ case ATA_CMD_ZAC_MGMT_IN:
+- return HISI_SAS_SATA_PROTOCOL_DMA;
++ return HISI_SAS_SATA_PROTOCOL_DMA;
+
+ case ATA_CMD_CHK_POWER:
+ case ATA_CMD_DEV_RESET:
+@@ -77,21 +77,21 @@ u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction)
+ case ATA_CMD_STANDBY:
+ case ATA_CMD_STANDBYNOW1:
+ case ATA_CMD_ZAC_MGMT_OUT:
+- return HISI_SAS_SATA_PROTOCOL_NONDATA;
++ return HISI_SAS_SATA_PROTOCOL_NONDATA;
+ default:
+ {
+ if (fis->command == ATA_CMD_SET_MAX) {
+ switch (fis->features) {
+ case ATA_SET_MAX_PASSWD:
+ case ATA_SET_MAX_LOCK:
+- return HISI_SAS_SATA_PROTOCOL_PIO;
++ return HISI_SAS_SATA_PROTOCOL_PIO;
+
+ case ATA_SET_MAX_PASSWD_DMA:
+ case ATA_SET_MAX_UNLOCK_DMA:
+- return HISI_SAS_SATA_PROTOCOL_DMA;
++ return HISI_SAS_SATA_PROTOCOL_DMA;
+
+ default:
+- return HISI_SAS_SATA_PROTOCOL_NONDATA;
++ return HISI_SAS_SATA_PROTOCOL_NONDATA;
+ }
+ }
+ if (direction == DMA_NONE)
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+index 8dd0e6a6ff8a..84a0ccc4daf5 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+@@ -651,8 +651,10 @@ static int reset_hw_v1_hw(struct hisi_hba *hisi_hba)
+ dev_err(dev, "De-reset failed\n");
+ return -EIO;
+ }
+- } else
++ } else {
+ dev_warn(dev, "no reset method\n");
++ return -EINVAL;
++ }
+
+ return 0;
+ }
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+index bd1a48a590bc..f89fb9a49ea9 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -1095,8 +1095,10 @@ static int reset_hw_v2_hw(struct hisi_hba *hisi_hba)
+ dev_err(dev, "SAS de-reset fail.\n");
+ return -EIO;
+ }
+- } else
+- dev_warn(dev, "no reset method\n");
++ } else {
++ dev_err(dev, "no reset method\n");
++ return -EINVAL;
++ }
+
+ return 0;
+ }
+@@ -2408,7 +2410,7 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
+ spin_lock_irqsave(&hisi_hba->lock, flags);
+ hisi_sas_slot_task_free(hisi_hba, task, slot);
+ spin_unlock_irqrestore(&hisi_hba->lock, flags);
+- return -1;
++ return ts->stat;
+ }
+
+ if (unlikely(!sas_dev)) {
+@@ -2667,7 +2669,7 @@ static int prep_abort_v2_hw(struct hisi_hba *hisi_hba,
+ /* dw0 */
+ hdr->dw0 = cpu_to_le32((5 << CMD_HDR_CMD_OFF) | /*abort*/
+ (port->id << CMD_HDR_PORT_OFF) |
+- ((dev_is_sata(dev) ? 1:0) <<
++ (dev_is_sata(dev) <<
+ CMD_HDR_ABORT_DEVICE_TYPE_OFF) |
+ (abort_flag << CMD_HDR_ABORT_FLAG_OFF));
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+index 8da9de7d67e5..4023fcbc3f04 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -670,8 +670,10 @@ static int reset_hw_v3_hw(struct hisi_hba *hisi_hba)
+ dev_err(dev, "Reset failed\n");
+ return -EIO;
+ }
+- } else
++ } else {
+ dev_err(dev, "no reset method!\n");
++ return -EINVAL;
++ }
+
+ return 0;
+ }
+@@ -731,7 +733,7 @@ static void phy_hard_reset_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
+ start_phy_v3_hw(hisi_hba, phy_no);
+ }
+
+-enum sas_linkrate phy_get_max_linkrate_v3_hw(void)
++static enum sas_linkrate phy_get_max_linkrate_v3_hw(void)
+ {
+ return SAS_LINK_RATE_12_0_GBPS;
+ }
+@@ -1096,7 +1098,7 @@ static int prep_abort_v3_hw(struct hisi_hba *hisi_hba,
+ /* dw0 */
+ hdr->dw0 = cpu_to_le32((5 << CMD_HDR_CMD_OFF) | /*abort*/
+ (port->id << CMD_HDR_PORT_OFF) |
+- ((dev_is_sata(dev) ? 1:0)
++ (dev_is_sata(dev)
+ << CMD_HDR_ABORT_DEVICE_TYPE_OFF) |
+ (abort_flag
+ << CMD_HDR_ABORT_FLAG_OFF));
+@@ -1112,9 +1114,9 @@ static int prep_abort_v3_hw(struct hisi_hba *hisi_hba,
+ return 0;
+ }
+
+-static int phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
++static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
+ {
+- int i, res = 0;
++ int i, res;
+ u32 context, port_id, link_rate;
+ struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
+ struct asd_sas_phy *sas_phy = &phy->sas_phy;
+@@ -1186,7 +1188,7 @@ static int 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);
+-
++ res = IRQ_HANDLED;
+ end:
+ hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
+ CHL_INT0_SL_PHY_ENABLE_MSK);
+@@ -1195,7 +1197,7 @@ static int phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
+ return res;
+ }
+
+-static int phy_down_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
++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;
+@@ -1217,10 +1219,10 @@ static int phy_down_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
+ hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, CHL_INT0_NOT_RDY_MSK);
+ hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 0);
+
+- return 0;
++ return IRQ_HANDLED;
+ }
+
+-static void phy_bcast_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
++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;
+@@ -1231,6 +1233,8 @@ static void phy_bcast_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
+ 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);
++
++ return IRQ_HANDLED;
+ }
+
+ static irqreturn_t int_phy_up_down_bcast_v3_hw(int irq_no, void *p)
+@@ -1257,7 +1261,9 @@ static irqreturn_t int_phy_up_down_bcast_v3_hw(int irq_no, void *p)
+ res = IRQ_HANDLED;
+ if (irq_value & CHL_INT0_SL_RX_BCST_ACK_MSK)
+ /* phy bcast */
+- phy_bcast_v3_hw(phy_no, hisi_hba);
++ if (phy_bcast_v3_hw(phy_no, hisi_hba)
++ == IRQ_HANDLED)
++ res = IRQ_HANDLED;
+ } else {
+ if (irq_value & CHL_INT0_NOT_RDY_MSK)
+ /* phy down */
+@@ -1573,7 +1579,7 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
+ spin_lock_irqsave(&hisi_hba->lock, flags);
+ hisi_sas_slot_task_free(hisi_hba, task, slot);
+ spin_unlock_irqrestore(&hisi_hba->lock, flags);
+- return -1;
++ return ts->stat;
+ }
+
+ if (unlikely(!sas_dev)) {
+
diff --git a/patches.drivers/scsi-hisi_sas-config-ata-de-reset-as-an-constrained-command-for-v3-hw.patch b/patches.drivers/scsi-hisi_sas-config-ata-de-reset-as-an-constrained-command-for-v3-hw.patch
new file mode 100644
index 0000000000..261bf20b2c
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-config-ata-de-reset-as-an-constrained-command-for-v3-hw.patch
@@ -0,0 +1,62 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Wed, 2 May 2018 23:56:31 +0800
+Subject: scsi: hisi_sas: config ATA de-reset as an constrained command for v3
+ hw
+Git-commit: 9413532788df7470297dd0475995c5dc5b07f362
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+As a unconstrained command, a command can be sent to SATA disk even if
+SATA disk status is BUSY, ERR or DRQ.
+
+If an ATA reset assert is successful but ATA reset de-assert fails, then
+it will retry the reset de-assert. If reset de- assert retry is
+successful, we think it is okay to probe the device but actually it
+still has Err status.
+
+Apparently we need to retry the ATA reset assertion and de- assertion
+instead for this mentioned scenario.
+
+As such, we config ATA reset assert as a constrained command, if ATA
+reset de-assert fails, then ATA reset de-assert retry will also
+fail. Then we will retry the proper process of ATA reset assert and
+de-assert again.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 11 ++++++-----
+ 1 file changed, 6 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 ffa3cea5ca8f..026faeee5ead 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -351,10 +351,11 @@ struct hisi_sas_err_record_v3 {
+ #define DIR_TO_DEVICE 2
+ #define DIR_RESERVED 3
+
+-#define CMD_IS_UNCONSTRAINT(cmd) \
+- ((cmd == ATA_CMD_READ_LOG_EXT) || \
+- (cmd == ATA_CMD_READ_LOG_DMA_EXT) || \
+- (cmd == ATA_CMD_DEV_RESET))
++#define FIS_CMD_IS_UNCONSTRAINED(fis) \
++ ((fis.command == ATA_CMD_READ_LOG_EXT) || \
++ (fis.command == ATA_CMD_READ_LOG_DMA_EXT) || \
++ ((fis.command == ATA_CMD_DEV_RESET) && \
++ ((fis.control & ATA_SRST) != 0)))
+
+ static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
+ {
+@@ -1075,7 +1076,7 @@ static int prep_ata_v3_hw(struct hisi_hba *hisi_hba,
+ << CMD_HDR_FRAME_TYPE_OFF;
+ dw1 |= sas_dev->device_id << CMD_HDR_DEV_ID_OFF;
+
+- if (CMD_IS_UNCONSTRAINT(task->ata_task.fis.command))
++ if (FIS_CMD_IS_UNCONSTRAINED(task->ata_task.fis))
+ dw1 |= 1 << CMD_HDR_UNCON_CMD_OFF;
+
+ hdr->dw1 = cpu_to_le32(dw1);
+
diff --git a/patches.drivers/scsi-hisi_sas-consolidate-command-check-in-hisi_sas_get_ata_protocol.patch b/patches.drivers/scsi-hisi_sas-consolidate-command-check-in-hisi_sas_get_ata_protocol.patch
new file mode 100644
index 0000000000..32e5261d07
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-consolidate-command-check-in-hisi_sas_get_ata_protocol.patch
@@ -0,0 +1,63 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Sat, 24 Mar 2018 00:05:12 +0800
+Subject: scsi: hisi_sas: consolidate command check in
+ hisi_sas_get_ata_protocol()
+Git-commit: 3ff0f0b657eb414c1f8f1f22b91d52b892d8a850
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+Currently we check the fis->command value in 2 locations in
+hisi_sas_get_ata_protocol() switch statement. Fix this by consolidating
+the check for fis->command value to 1 location only.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 29 +++++++++++++++--------------
+ 1 file changed, 15 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 9563dfa72181..8557fd08ed8e 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -78,22 +78,23 @@ u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction)
+ case ATA_CMD_STANDBYNOW1:
+ case ATA_CMD_ZAC_MGMT_OUT:
+ return HISI_SAS_SATA_PROTOCOL_NONDATA;
++
++ case ATA_CMD_SET_MAX:
++ switch (fis->features) {
++ case ATA_SET_MAX_PASSWD:
++ case ATA_SET_MAX_LOCK:
++ return HISI_SAS_SATA_PROTOCOL_PIO;
++
++ case ATA_SET_MAX_PASSWD_DMA:
++ case ATA_SET_MAX_UNLOCK_DMA:
++ return HISI_SAS_SATA_PROTOCOL_DMA;
++
++ default:
++ return HISI_SAS_SATA_PROTOCOL_NONDATA;
++ }
++
+ default:
+ {
+- if (fis->command == ATA_CMD_SET_MAX) {
+- switch (fis->features) {
+- case ATA_SET_MAX_PASSWD:
+- case ATA_SET_MAX_LOCK:
+- return HISI_SAS_SATA_PROTOCOL_PIO;
+-
+- case ATA_SET_MAX_PASSWD_DMA:
+- case ATA_SET_MAX_UNLOCK_DMA:
+- return HISI_SAS_SATA_PROTOCOL_DMA;
+-
+- default:
+- return HISI_SAS_SATA_PROTOCOL_NONDATA;
+- }
+- }
+ if (direction == DMA_NONE)
+ return HISI_SAS_SATA_PROTOCOL_NONDATA;
+ return HISI_SAS_SATA_PROTOCOL_PIO;
+
diff --git a/patches.drivers/scsi-hisi_sas-create-a-scsi_host_template-per-hw-module.patch b/patches.drivers/scsi-hisi_sas-create-a-scsi_host_template-per-hw-module.patch
new file mode 100644
index 0000000000..63fbf76537
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-create-a-scsi_host_template-per-hw-module.patch
@@ -0,0 +1,287 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Mon, 21 May 2018 18:09:18 +0800
+Subject: scsi: hisi_sas: Create a scsi_host_template per HW module
+Git-commit: 235bfc7ff63027e90c25663ed7a976083f5afb47
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+When a SCSI host is registered, the SCSI mid-layer takes a reference to a
+module in Scsi_host.hostt.module. In doing this, we are prevented from
+removing the driver module for the host in dangerous scenario, like when a
+disk is mounted.
+
+Currently there is only one scsi_host_template (sht) for all HW versions,
+and this is the main.c module. So this means that we can possibly remove
+the HW module in this dangerous scenario, as SCSI mid-layer is only
+referencing the main.c module.
+
+To fix this, create a sht per module, referencing that same module to
+create the Scsi host.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas.h | 8 +++++--
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 40 +++++++++-------------------------
+ drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 23 +++++++++++++++++++
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 24 ++++++++++++++++++++
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 24 +++++++++++++++++++-
+ 5 files changed, 86 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
+index b4717bd8af3f..37c9a6246dc8 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas.h
++++ b/drivers/scsi/hisi_sas/hisi_sas.h
+@@ -248,6 +248,7 @@ struct hisi_sas_hw {
+ u8 reg_index, u8 reg_count, u8 *write_data);
+ int max_command_entries;
+ int complete_hdr_size;
++ struct scsi_host_template *sht;
+ };
+
+ struct hisi_hba {
+@@ -440,8 +441,6 @@ struct hisi_sas_slot_buf_table {
+ };
+
+ extern struct scsi_transport_template *hisi_sas_stt;
+-extern struct scsi_host_template *hisi_sas_sht;
+-
+ extern void hisi_sas_stop_phys(struct hisi_hba *hisi_hba);
+ extern int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost);
+ extern void hisi_sas_free(struct hisi_hba *hisi_hba);
+@@ -456,6 +455,11 @@ extern int hisi_sas_probe(struct platform_device *pdev,
+ const struct hisi_sas_hw *ops);
+ extern int hisi_sas_remove(struct platform_device *pdev);
+
++extern int hisi_sas_slave_configure(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 struct device_attribute *host_attrs[];
++extern int hisi_sas_host_reset(struct Scsi_Host *shost, int reset_type);
+ extern void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy);
+ extern void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba,
+ struct sas_task *task,
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index c8e647a65b30..664aaf7f5147 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -719,7 +719,7 @@ static int hisi_sas_dev_found(struct domain_device *device)
+ return rc;
+ }
+
+-static int hisi_sas_slave_configure(struct scsi_device *sdev)
++int hisi_sas_slave_configure(struct scsi_device *sdev)
+ {
+ struct domain_device *dev = sdev_to_domain_dev(sdev);
+ int ret = sas_slave_configure(sdev);
+@@ -731,15 +731,17 @@ static int hisi_sas_slave_configure(struct scsi_device *sdev)
+
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(hisi_sas_slave_configure);
+
+-static void hisi_sas_scan_start(struct Scsi_Host *shost)
++void hisi_sas_scan_start(struct Scsi_Host *shost)
+ {
+ struct hisi_hba *hisi_hba = shost_priv(shost);
+
+ hisi_hba->hw->phys_init(hisi_hba);
+ }
++EXPORT_SYMBOL_GPL(hisi_sas_scan_start);
+
+-static int hisi_sas_scan_finished(struct Scsi_Host *shost, unsigned long time)
++int hisi_sas_scan_finished(struct Scsi_Host *shost, unsigned long time)
+ {
+ struct hisi_hba *hisi_hba = shost_priv(shost);
+ struct sas_ha_struct *sha = &hisi_hba->sha;
+@@ -751,6 +753,7 @@ static int hisi_sas_scan_finished(struct Scsi_Host *shost, unsigned long time)
+ sas_drain_work(sha);
+ return 1;
+ }
++EXPORT_SYMBOL_GPL(hisi_sas_scan_finished);
+
+ static void hisi_sas_phyup_work(struct work_struct *work)
+ {
+@@ -1824,34 +1827,11 @@ EXPORT_SYMBOL_GPL(hisi_sas_kill_tasklets);
+ struct scsi_transport_template *hisi_sas_stt;
+ EXPORT_SYMBOL_GPL(hisi_sas_stt);
+
+-static struct device_attribute *host_attrs[] = {
++struct device_attribute *host_attrs[] = {
+ &dev_attr_phy_event_threshold,
+ NULL,
+ };
+-
+-static struct scsi_host_template _hisi_sas_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .queuecommand = sas_queuecommand,
+- .target_alloc = sas_target_alloc,
+- .slave_configure = hisi_sas_slave_configure,
+- .scan_finished = hisi_sas_scan_finished,
+- .scan_start = hisi_sas_scan_start,
+- .change_queue_depth = sas_change_queue_depth,
+- .bios_param = sas_bios_param,
+- .can_queue = 1,
+- .this_id = -1,
+- .sg_tablesize = SG_ALL,
+- .max_sectors = SCSI_DEFAULT_MAX_SECTORS,
+- .use_clustering = ENABLE_CLUSTERING,
+- .eh_device_reset_handler = sas_eh_device_reset_handler,
+- .eh_target_reset_handler = sas_eh_target_reset_handler,
+- .target_destroy = sas_target_destroy,
+- .ioctl = sas_ioctl,
+- .shost_attrs = host_attrs,
+-};
+-struct scsi_host_template *hisi_sas_sht = &_hisi_sas_sht;
+-EXPORT_SYMBOL_GPL(hisi_sas_sht);
++EXPORT_SYMBOL_GPL(host_attrs);
+
+ static struct sas_domain_function_template hisi_sas_transport_ops = {
+ .lldd_dev_found = hisi_sas_dev_found,
+@@ -2161,7 +2141,7 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
+ struct hisi_hba *hisi_hba;
+ struct device *dev = &pdev->dev;
+
+- shost = scsi_host_alloc(hisi_sas_sht, sizeof(*hisi_hba));
++ shost = scsi_host_alloc(hw->sht, sizeof(*hisi_hba));
+ if (!shost) {
+ dev_err(dev, "scsi host alloc failed\n");
+ return NULL;
+@@ -2211,7 +2191,7 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
+ }
+
+ int hisi_sas_probe(struct platform_device *pdev,
+- const struct hisi_sas_hw *hw)
++ const struct hisi_sas_hw *hw)
+ {
+ struct Scsi_Host *shost;
+ struct hisi_hba *hisi_hba;
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+index 8fa79d0968a6..8d5d8575d939 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+@@ -1788,6 +1788,28 @@ static int hisi_sas_v1_init(struct hisi_hba *hisi_hba)
+ return 0;
+ }
+
++static struct scsi_host_template sht_v1_hw = {
++ .name = DRV_NAME,
++ .module = THIS_MODULE,
++ .queuecommand = sas_queuecommand,
++ .target_alloc = sas_target_alloc,
++ .slave_configure = hisi_sas_slave_configure,
++ .scan_finished = hisi_sas_scan_finished,
++ .scan_start = hisi_sas_scan_start,
++ .change_queue_depth = sas_change_queue_depth,
++ .bios_param = sas_bios_param,
++ .can_queue = 1,
++ .this_id = -1,
++ .sg_tablesize = SG_ALL,
++ .max_sectors = SCSI_DEFAULT_MAX_SECTORS,
++ .use_clustering = ENABLE_CLUSTERING,
++ .eh_device_reset_handler = sas_eh_device_reset_handler,
++ .eh_target_reset_handler = sas_eh_target_reset_handler,
++ .target_destroy = sas_target_destroy,
++ .ioctl = sas_ioctl,
++ .shost_attrs = host_attrs,
++};
++
+ static const struct hisi_sas_hw hisi_sas_v1_hw = {
+ .hw_init = hisi_sas_v1_init,
+ .setup_itct = setup_itct_v1_hw,
+@@ -1807,6 +1829,7 @@ static const struct hisi_sas_hw hisi_sas_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,
+ };
+
+ static int hisi_sas_v1_probe(struct platform_device *pdev)
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+index fb0e966a44a8..8def327c4f46 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -3501,6 +3501,29 @@ static int write_gpio_v2_hw(struct hisi_hba *hisi_hba, u8 reg_type,
+ return 0;
+ }
+
++
++static struct scsi_host_template sht_v2_hw = {
++ .name = DRV_NAME,
++ .module = THIS_MODULE,
++ .queuecommand = sas_queuecommand,
++ .target_alloc = sas_target_alloc,
++ .slave_configure = hisi_sas_slave_configure,
++ .scan_finished = hisi_sas_scan_finished,
++ .scan_start = hisi_sas_scan_start,
++ .change_queue_depth = sas_change_queue_depth,
++ .bios_param = sas_bios_param,
++ .can_queue = 1,
++ .this_id = -1,
++ .sg_tablesize = SG_ALL,
++ .max_sectors = SCSI_DEFAULT_MAX_SECTORS,
++ .use_clustering = ENABLE_CLUSTERING,
++ .eh_device_reset_handler = sas_eh_device_reset_handler,
++ .eh_target_reset_handler = sas_eh_target_reset_handler,
++ .target_destroy = sas_target_destroy,
++ .ioctl = sas_ioctl,
++ .shost_attrs = host_attrs,
++};
++
+ static const struct hisi_sas_hw hisi_sas_v2_hw = {
+ .hw_init = hisi_sas_v2_init,
+ .setup_itct = setup_itct_v2_hw,
+@@ -3529,6 +3552,7 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = {
+ .soft_reset = soft_reset_v2_hw,
+ .get_phys_state = get_phys_state_v2_hw,
+ .write_gpio = write_gpio_v2_hw,
++ .sht = &sht_v2_hw,
+ };
+
+ static int hisi_sas_v2_probe(struct platform_device *pdev)
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+index a043d9cdbf48..13d21349d1ba 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -2015,6 +2015,28 @@ static int write_gpio_v3_hw(struct hisi_hba *hisi_hba, u8 reg_type,
+ return 0;
+ }
+
++static struct scsi_host_template sht_v3_hw = {
++ .name = DRV_NAME,
++ .module = THIS_MODULE,
++ .queuecommand = sas_queuecommand,
++ .target_alloc = sas_target_alloc,
++ .slave_configure = hisi_sas_slave_configure,
++ .scan_finished = hisi_sas_scan_finished,
++ .scan_start = hisi_sas_scan_start,
++ .change_queue_depth = sas_change_queue_depth,
++ .bios_param = sas_bios_param,
++ .can_queue = 1,
++ .this_id = -1,
++ .sg_tablesize = SG_ALL,
++ .max_sectors = SCSI_DEFAULT_MAX_SECTORS,
++ .use_clustering = ENABLE_CLUSTERING,
++ .eh_device_reset_handler = sas_eh_device_reset_handler,
++ .eh_target_reset_handler = sas_eh_target_reset_handler,
++ .target_destroy = sas_target_destroy,
++ .ioctl = sas_ioctl,
++ .shost_attrs = host_attrs,
++};
++
+ static const struct hisi_sas_hw hisi_sas_v3_hw = {
+ .hw_init = hisi_sas_v3_init,
+ .setup_itct = setup_itct_v3_hw,
+@@ -2050,7 +2072,7 @@ hisi_sas_shost_alloc_pci(struct pci_dev *pdev)
+ struct hisi_hba *hisi_hba;
+ struct device *dev = &pdev->dev;
+
+- shost = scsi_host_alloc(hisi_sas_sht, sizeof(*hisi_hba));
++ shost = scsi_host_alloc(&sht_v3_hw, sizeof(*hisi_hba));
+ if (!shost) {
+ dev_err(dev, "shost alloc failed\n");
+ return NULL;
+
diff --git a/patches.drivers/scsi-hisi_sas-delete-timer-when-removing-hisi_sas-driver.patch b/patches.drivers/scsi-hisi_sas-delete-timer-when-removing-hisi_sas-driver.patch
new file mode 100644
index 0000000000..d744232073
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-delete-timer-when-removing-hisi_sas-driver.patch
@@ -0,0 +1,62 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Sat, 24 Mar 2018 00:05:10 +0800
+Subject: scsi: hisi_sas: delete timer when removing hisi_sas driver
+Git-commit: 5df41af4b18720061b1024f93f54b957864cdd44
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+Delete timer for v1 and v3 hw when removing hisi_sas driver.
+
+Signed-off-by: Xiang chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 3 +++
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 3 ---
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 3 +++
+ 3 files changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 49c1fa643803..a21679574142 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -2177,6 +2177,9 @@ int hisi_sas_remove(struct platform_device *pdev)
+ struct hisi_hba *hisi_hba = sha->lldd_ha;
+ struct Scsi_Host *shost = sha->core.shost;
+
++ if (timer_pending(&hisi_hba->timer))
++ del_timer(&hisi_hba->timer);
++
+ sas_unregister_ha(sha);
+ sas_remove_host(sha->core.shost);
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+index 89b9505c0654..bed6afb324a1 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -3599,9 +3599,6 @@ 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;
+
+- if (timer_pending(&hisi_hba->timer))
+- del_timer(&hisi_hba->timer);
+-
+ 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 df5414a0bdd9..efe64bcfa4f2 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -2183,6 +2183,9 @@ 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;
+
++ if (timer_pending(&hisi_hba->timer))
++ del_timer(&hisi_hba->timer);
++
+ sas_unregister_ha(sha);
+ sas_remove_host(sha->core.shost);
+
+
diff --git a/patches.drivers/scsi-hisi_sas-directly-attached-disk-LED-feature-for.patch b/patches.drivers/scsi-hisi_sas-directly-attached-disk-LED-feature-for.patch
index 83c049b30e..8236268774 100644
--- a/patches.drivers/scsi-hisi_sas-directly-attached-disk-LED-feature-for.patch
+++ b/patches.drivers/scsi-hisi_sas-directly-attached-disk-LED-feature-for.patch
@@ -24,7 +24,7 @@ Signed-off-by: Matthias Brugger <mbrugger@suse.com>
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
-@@ -213,6 +213,8 @@ struct hisi_sas_hw {
+@@ -245,6 +245,8 @@ struct hisi_sas_hw {
struct domain_device *device);
int (*soft_reset)(struct hisi_hba *hisi_hba);
u32 (*get_phys_state)(struct hisi_hba *hisi_hba);
@@ -33,7 +33,7 @@ Signed-off-by: Matthias Brugger <mbrugger@suse.com>
int max_command_entries;
int complete_hdr_size;
};
-@@ -226,6 +228,7 @@ struct hisi_hba {
+@@ -258,6 +260,7 @@ struct hisi_hba {
struct device *dev;
void __iomem *regs;
@@ -43,8 +43,8 @@ Signed-off-by: Matthias Brugger <mbrugger@suse.com>
u32 ctrl_reset_sts_reg;
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
-@@ -1509,6 +1509,18 @@ static void hisi_sas_port_formed(struct
- hisi_sas_port_notify_formed(sas_phy);
+@@ -1636,6 +1636,18 @@ static void hisi_sas_port_deformed(struc
+ {
}
+static int hisi_sas_write_gpio(struct sas_ha_struct *sha, u8 reg_type,
@@ -62,15 +62,15 @@ Signed-off-by: Matthias Brugger <mbrugger@suse.com>
static void hisi_sas_phy_disconnected(struct hisi_sas_phy *phy)
{
phy->phy_attached = 0;
-@@ -1599,6 +1611,7 @@ static struct sas_domain_function_templa
- .lldd_query_task = hisi_sas_query_task,
- .lldd_clear_nexus_ha = hisi_sas_clear_nexus_ha,
- .lldd_port_formed = hisi_sas_port_formed,
+@@ -1726,6 +1738,7 @@ static struct sas_domain_function_templa
+ .lldd_control_phy = hisi_sas_control_phy,
+ .lldd_abort_task = hisi_sas_abort_task,
+ .lldd_abort_task_set = hisi_sas_abort_task_set,
+ .lldd_write_gpio = hisi_sas_write_gpio,
- };
-
- void hisi_sas_init_mem(struct hisi_hba *hisi_hba)
-@@ -1911,6 +1924,13 @@ static struct Scsi_Host *hisi_sas_shost_
+ .lldd_clear_aca = hisi_sas_clear_aca,
+ .lldd_I_T_nexus_reset = hisi_sas_I_T_nexus_reset,
+ .lldd_lu_reset = hisi_sas_lu_reset,
+@@ -2057,6 +2070,13 @@ static struct Scsi_Host *hisi_sas_shost_
if (IS_ERR(hisi_hba->regs))
goto err_out;
@@ -86,7 +86,7 @@ Signed-off-by: Matthias Brugger <mbrugger@suse.com>
goto err_out;
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
-@@ -3410,6 +3410,44 @@ static int soft_reset_v2_hw(struct hisi_
+@@ -3476,6 +3476,44 @@ static int soft_reset_v2_hw(struct hisi_
return 0;
}
@@ -131,7 +131,7 @@ Signed-off-by: Matthias Brugger <mbrugger@suse.com>
static const struct hisi_sas_hw hisi_sas_v2_hw = {
.hw_init = hisi_sas_v2_init,
.setup_itct = setup_itct_v2_hw,
-@@ -3436,6 +3474,7 @@ static const struct hisi_sas_hw hisi_sas
+@@ -3503,6 +3541,7 @@ static const struct hisi_sas_hw hisi_sas
.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/patches.drivers/scsi-hisi_sas-do-link-reset-for-some-chl_int2-ints.patch b/patches.drivers/scsi-hisi_sas-do-link-reset-for-some-chl_int2-ints.patch
new file mode 100644
index 0000000000..e4fd59c581
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-do-link-reset-for-some-chl_int2-ints.patch
@@ -0,0 +1,180 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Sat, 9 Dec 2017 01:16:45 +0800
+Subject: scsi: hisi_sas: do link reset for some CHL_INT2 ints
+Git-commit: 057c3d1f07617049671a41bf05652d20071eb639
+Patch-mainline: v4.16-rc1
+References: FATE#326253
+
+We should do link reset of PHY when identify timeout or STP link timeout. They
+are internal events of SOC and are notified to driver through interrupts of
+CHL_INT2.
+
+Besides, we should add an delay work to do link reset as it needs sleep. So,
+this patch add an new PHY event HISI_PHYE_LINK_RESET for this.
+
+Notes: v2 HW doesn't report the event of STP link timeout. So, we only need
+to handle event of identify timeout for v2 HW.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas.h | 1 +
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 12 ++++++++++++
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 18 ++++++++++++++----
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 29 +++++++++++++++++++++++++++--
+ 4 files changed, 54 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
+index aa14638ab08f..4343c4ce338d 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas.h
++++ b/drivers/scsi/hisi_sas/hisi_sas.h
+@@ -126,6 +126,7 @@ enum hisi_sas_bit_err_type {
+
+ enum hisi_sas_phy_event {
+ HISI_PHYE_PHY_UP = 0U,
++ HISI_PHYE_LINK_RESET,
+ HISI_PHYES_NUM,
+ };
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 326dc8169073..7446a39f9442 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -22,6 +22,8 @@ hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
+ struct domain_device *device,
+ int abort_flag, int tag);
+ 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);
+
+ u8 hisi_sas_get_ata_protocol(u8 cmd, int direction)
+ {
+@@ -631,8 +633,18 @@ static void hisi_sas_phyup_work(struct work_struct *work)
+ hisi_sas_bytes_dmaed(hisi_hba, phy_no);
+ }
+
++static void hisi_sas_linkreset_work(struct work_struct *work)
++{
++ struct hisi_sas_phy *phy =
++ container_of(work, typeof(*phy), works[HISI_PHYE_LINK_RESET]);
++ struct asd_sas_phy *sas_phy = &phy->sas_phy;
++
++ hisi_sas_control_phy(sas_phy, PHY_FUNC_LINK_RESET, NULL);
++}
++
+ 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,
+ };
+
+ bool hisi_sas_notify_phy_event(struct hisi_sas_phy *phy,
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+index e521c420efee..b8fe08d9b1ce 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -245,6 +245,7 @@
+ #define CHL_INT1_DMAC_RX_AXI_WR_ERR_OFF 21
+ #define CHL_INT1_DMAC_RX_AXI_RD_ERR_OFF 22
+ #define CHL_INT2 (PORT_BASE + 0x1bc)
++#define CHL_INT2_SL_IDAF_TOUT_CONF_OFF 0
+ #define CHL_INT0_MSK (PORT_BASE + 0x1c0)
+ #define CHL_INT1_MSK (PORT_BASE + 0x1c4)
+ #define CHL_INT2_MSK (PORT_BASE + 0x1c8)
+@@ -1187,7 +1188,7 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba)
+ hisi_sas_phy_write32(hisi_hba, i, CHL_INT2, 0xfff87fff);
+ hisi_sas_phy_write32(hisi_hba, i, RXOP_CHECK_CFG_H, 0x1000);
+ hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK, 0xff857fff);
+- hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0x8ffffbff);
++ hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0x8ffffbfe);
+ hisi_sas_phy_write32(hisi_hba, i, SL_CFG, 0x13f801fc);
+ hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL_RDY_MSK, 0x0);
+ hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_NOT_RDY_MSK, 0x0);
+@@ -2905,10 +2906,19 @@ static irqreturn_t int_chnl_int_v2_hw(int irq_no, void *p)
+ CHL_INT1, irq_value1);
+ }
+
+- if ((irq_msk & (1 << phy_no)) && irq_value2)
+- hisi_sas_phy_write32(hisi_hba, phy_no,
+- CHL_INT2, irq_value2);
++ if ((irq_msk & (1 << phy_no)) && irq_value2) {
++ struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
++
++ if (irq_value2 & BIT(CHL_INT2_SL_IDAF_TOUT_CONF_OFF)) {
++ dev_warn(dev, "phy%d identify timeout\n",
++ phy_no);
++ hisi_sas_notify_phy_event(phy,
++ HISI_PHYE_LINK_RESET);
++ }
+
++ hisi_sas_phy_write32(hisi_hba, phy_no,
++ CHL_INT2, irq_value2);
++ }
+
+ if ((irq_msk & (1 << phy_no)) && irq_value0) {
+ if (irq_value0 & CHL_INT0_SL_RX_BCST_ACK_MSK)
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+index 4b7f251edbd2..9e321050cdc2 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -140,6 +140,7 @@
+ #define RX_IDAF_DWORD0 (PORT_BASE + 0xc4)
+ #define RXOP_CHECK_CFG_H (PORT_BASE + 0xfc)
+ #define STP_LINK_TIMER (PORT_BASE + 0x120)
++#define STP_LINK_TIMEOUT_STATE (PORT_BASE + 0x124)
+ #define CON_CFG_DRIVER (PORT_BASE + 0x130)
+ #define SAS_SSP_CON_TIMER_CFG (PORT_BASE + 0x134)
+ #define SAS_SMP_CON_TIMER_CFG (PORT_BASE + 0x138)
+@@ -165,6 +166,8 @@
+ #define CHL_INT1_DMAC_RX_AXI_WR_ERR_OFF 21
+ #define CHL_INT1_DMAC_RX_AXI_RD_ERR_OFF 22
+ #define CHL_INT2 (PORT_BASE + 0x1bc)
++#define CHL_INT2_SL_IDAF_TOUT_CONF_OFF 0
++#define CHL_INT2_STP_LINK_TIMEOUT_OFF 31
+ #define CHL_INT0_MSK (PORT_BASE + 0x1c0)
+ #define CHL_INT1_MSK (PORT_BASE + 0x1c4)
+ #define CHL_INT2_MSK (PORT_BASE + 0x1c8)
+@@ -429,7 +432,7 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
+ 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, 0xff87ffff);
+- hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0x8ffffbff);
++ 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);
+@@ -1342,9 +1345,31 @@ static irqreturn_t int_chnl_int_v3_hw(int irq_no, void *p)
+ CHL_INT1, irq_value1);
+ }
+
+- if (irq_msk & (8 << (phy_no * 4)) && irq_value2)
++ if (irq_msk & (8 << (phy_no * 4)) && irq_value2) {
++ struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
++
++ if (irq_value2 & BIT(CHL_INT2_SL_IDAF_TOUT_CONF_OFF)) {
++ dev_warn(dev, "phy%d identify timeout\n",
++ phy_no);
++ hisi_sas_notify_phy_event(phy,
++ HISI_PHYE_LINK_RESET);
++
++ }
++
++ if (irq_value2 & BIT(CHL_INT2_STP_LINK_TIMEOUT_OFF)) {
++ u32 reg_value = hisi_sas_phy_read32(hisi_hba,
++ phy_no, STP_LINK_TIMEOUT_STATE);
++
++ dev_warn(dev, "phy%d stp link timeout (0x%x)\n",
++ phy_no, reg_value);
++ if (reg_value & BIT(4))
++ hisi_sas_notify_phy_event(phy,
++ HISI_PHYE_LINK_RESET);
++ }
++
+ hisi_sas_phy_write32(hisi_hba, phy_no,
+ CHL_INT2, irq_value2);
++ }
+
+
+ if (irq_msk & (2 << (phy_no * 4)) && irq_value0) {
+
diff --git a/patches.drivers/scsi-hisi_sas-don-t-lock-dq-for-complete-task-sending.patch b/patches.drivers/scsi-hisi_sas-don-t-lock-dq-for-complete-task-sending.patch
new file mode 100644
index 0000000000..64864fbe7d
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-don-t-lock-dq-for-complete-task-sending.patch
@@ -0,0 +1,338 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Wed, 9 May 2018 23:10:48 +0800
+Subject: scsi: hisi_sas: Don't lock DQ for complete task sending
+Git-commit: fa222db0b036899cd4020a380568699ffb1de08d
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+Currently we lock the DQ to protect whole delivery process. So this
+stops us building slots for the same queue in parallel, and can affect
+performance.
+
+To optimise it, only lock the DQ during special periods, specifically
+when allocating a slot from the DQ and when delivering a slot to the HW.
+
+This approach is now safe, thanks to the previous patches to ensure that
+we always deliver a slot to the HW once allocated.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas.h | 4 ++-
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 49 ++++++++++++++++++++--------------
+ drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 27 ++++++++++++++-----
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 29 +++++++++++++++-----
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 28 ++++++++++++++-----
+ 5 files changed, 96 insertions(+), 41 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
+index 3a1caa04407e..52fc709dd862 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas.h
++++ b/drivers/scsi/hisi_sas/hisi_sas.h
+@@ -161,7 +161,7 @@ struct hisi_sas_cq {
+
+ struct hisi_sas_dq {
+ struct hisi_hba *hisi_hba;
+- struct hisi_sas_slot *slot_prep;
++ struct list_head list;
+ spinlock_t lock;
+ int wr_point;
+ int id;
+@@ -181,6 +181,7 @@ struct hisi_sas_device {
+
+ struct hisi_sas_slot {
+ struct list_head entry;
++ struct list_head delivery;
+ struct sas_task *task;
+ struct hisi_sas_port *port;
+ u64 n_elem;
+@@ -190,6 +191,7 @@ struct hisi_sas_slot {
+ int cmplt_queue_slot;
+ int idx;
+ int abort;
++ int ready;
+ void *buf;
+ dma_addr_t buf_dma;
+ void *cmd_hdr;
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 58cbe1f0e0b6..bf374a795962 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -307,9 +307,9 @@ static void hisi_sas_slot_abort(struct work_struct *work)
+ task->task_done(task);
+ }
+
+-static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
+- *dq, int is_tmf, struct hisi_sas_tmf_task *tmf,
+- int *pass)
++static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq *dq,
++ int is_tmf, struct hisi_sas_tmf_task *tmf,
++ int *pass)
+ {
+ struct hisi_hba *hisi_hba = dq->hisi_hba;
+ struct domain_device *device = task->dev;
+@@ -321,7 +321,8 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
+ struct device *dev = hisi_hba->dev;
+ int dlvry_queue_slot, dlvry_queue, rc, slot_idx;
+ int n_elem = 0, n_elem_req = 0, n_elem_resp = 0;
+- unsigned long flags;
++ unsigned long flags, flags_dq;
++ int wr_q_index;
+
+ if (!sas_port) {
+ struct task_status_struct *ts = &task->task_status;
+@@ -422,12 +423,18 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
+ goto err_out_tag;
+ }
+
+- rc = hisi_hba->hw->get_free_slot(hisi_hba, dq);
+- if (rc)
++ spin_lock_irqsave(&dq->lock, flags_dq);
++ wr_q_index = hisi_hba->hw->get_free_slot(hisi_hba, dq);
++ if (wr_q_index < 0) {
++ spin_unlock_irqrestore(&dq->lock, flags_dq);
+ goto err_out_buf;
++ }
++
++ list_add_tail(&slot->delivery, &dq->list);
++ spin_unlock_irqrestore(&dq->lock, flags_dq);
+
+ dlvry_queue = dq->id;
+- dlvry_queue_slot = dq->wr_point;
++ dlvry_queue_slot = wr_q_index;
+
+ slot->idx = slot_idx;
+ slot->n_elem = n_elem;
+@@ -471,8 +478,8 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
+ task->task_state_flags |= SAS_TASK_AT_INITIATOR;
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
+
+- dq->slot_prep = slot;
+ ++(*pass);
++ slot->ready = 1;
+
+ return 0;
+
+@@ -518,11 +525,11 @@ static int hisi_sas_task_exec(struct sas_task *task, gfp_t gfp_flags,
+ return -EINVAL;
+
+ /* protect task_prep and start_delivery sequence */
+- spin_lock_irqsave(&dq->lock, flags);
+ rc = hisi_sas_task_prep(task, dq, is_tmf, tmf, &pass);
+ if (rc)
+ dev_err(dev, "task exec: failed[%d]!\n", rc);
+
++ spin_lock_irqsave(&dq->lock, flags);
+ if (likely(pass))
+ hisi_hba->hw->start_delivery(dq);
+ spin_unlock_irqrestore(&dq->lock, flags);
+@@ -1503,7 +1510,8 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id,
+ struct hisi_sas_cmd_hdr *cmd_hdr_base;
+ struct hisi_sas_dq *dq = sas_dev->dq;
+ int dlvry_queue_slot, dlvry_queue, n_elem = 0, rc, slot_idx;
+- unsigned long flags, flags_dq;
++ unsigned long flags, flags_dq = 0;
++ int wr_q_index;
+
+ if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags)))
+ return -EINVAL;
+@@ -1531,16 +1539,18 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id,
+ rc = -ENOMEM;
+ goto err_out_tag;
+ }
++
+ spin_lock_irqsave(&dq->lock, flags_dq);
+- rc = hisi_hba->hw->get_free_slot(hisi_hba, dq);
+- if (rc) {
+- rc = -ENOMEM;
++ wr_q_index = hisi_hba->hw->get_free_slot(hisi_hba, dq);
++ if (wr_q_index < 0) {
+ spin_unlock_irqrestore(&dq->lock, flags_dq);
+ goto err_out_buf;
+ }
++ list_add_tail(&slot->delivery, &dq->list);
++ spin_unlock_irqrestore(&dq->lock, flags_dq);
+
+ dlvry_queue = dq->id;
+- dlvry_queue_slot = dq->wr_point;
++ dlvry_queue_slot = wr_q_index;
+
+ slot->idx = slot_idx;
+ slot->n_elem = n_elem;
+@@ -1560,18 +1570,16 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id,
+ hisi_sas_task_prep_abort(hisi_hba, slot, device_id,
+ abort_flag, task_tag);
+
+- spin_lock_irqsave(&hisi_hba->lock, flags);
+- list_add_tail(&slot->entry, &sas_dev->list);
+- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+ spin_lock_irqsave(&task->task_state_lock, flags);
+ task->task_state_flags |= SAS_TASK_AT_INITIATOR;
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
+
+- dq->slot_prep = slot;
+-
++ slot->ready = 1;
+ /* send abort command to the chip */
++ spin_lock_irqsave(&dq->lock, flags);
++ list_add_tail(&slot->entry, &sas_dev->list);
+ hisi_hba->hw->start_delivery(dq);
+- spin_unlock_irqrestore(&dq->lock, flags_dq);
++ spin_unlock_irqrestore(&dq->lock, flags);
+
+ return 0;
+
+@@ -1856,6 +1864,7 @@ int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost)
+
+ /* Delivery queue structure */
+ spin_lock_init(&dq->lock);
++ INIT_LIST_HEAD(&dq->list);
+ dq->id = i;
+ dq->hisi_hba = hisi_hba;
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+index 7781a011a750..abe175fddb86 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+@@ -921,18 +921,33 @@ get_free_slot_v1_hw(struct hisi_hba *hisi_hba, struct hisi_sas_dq *dq)
+ return -EAGAIN;
+ }
+
+- return 0;
++ dq->wr_point = (dq->wr_point + 1) % HISI_SAS_QUEUE_SLOTS;
++
++ return w;
+ }
+
++/* DQ lock must be taken here */
+ static void start_delivery_v1_hw(struct hisi_sas_dq *dq)
+ {
+ struct hisi_hba *hisi_hba = dq->hisi_hba;
+- int dlvry_queue = dq->slot_prep->dlvry_queue;
+- int dlvry_queue_slot = dq->slot_prep->dlvry_queue_slot;
++ struct hisi_sas_slot *s, *s1;
++ struct list_head *dq_list;
++ int dlvry_queue = dq->id;
++ int wp, count = 0;
++
++ dq_list = &dq->list;
++ list_for_each_entry_safe(s, s1, &dq->list, delivery) {
++ if (!s->ready)
++ break;
++ count++;
++ wp = (s->dlvry_queue_slot + 1) % HISI_SAS_QUEUE_SLOTS;
++ list_del(&s->delivery);
++ }
++
++ if (!count)
++ return;
+
+- dq->wr_point = ++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS;
+- hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14),
+- dq->wr_point);
++ hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14), wp);
+ }
+
+ static void prep_prd_sge_v1_hw(struct hisi_hba *hisi_hba,
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+index 9f77fd8223f7..911bb76a4d0a 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -1663,23 +1663,38 @@ get_free_slot_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_dq *dq)
+ r = hisi_sas_read32_relaxed(hisi_hba,
+ DLVRY_Q_0_RD_PTR + (queue * 0x14));
+ if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) {
+- dev_warn(dev, "full queue=%d r=%d w=%d\n\n",
++ dev_warn(dev, "full queue=%d r=%d w=%d\n",
+ queue, r, w);
+ return -EAGAIN;
+ }
+
+- return 0;
++ dq->wr_point = (dq->wr_point + 1) % HISI_SAS_QUEUE_SLOTS;
++
++ return w;
+ }
+
++/* DQ lock must be taken here */
+ static void start_delivery_v2_hw(struct hisi_sas_dq *dq)
+ {
+ struct hisi_hba *hisi_hba = dq->hisi_hba;
+- int dlvry_queue = dq->slot_prep->dlvry_queue;
+- int dlvry_queue_slot = dq->slot_prep->dlvry_queue_slot;
++ struct hisi_sas_slot *s, *s1;
++ struct list_head *dq_list;
++ int dlvry_queue = dq->id;
++ int wp, count = 0;
++
++ dq_list = &dq->list;
++ list_for_each_entry_safe(s, s1, &dq->list, delivery) {
++ if (!s->ready)
++ break;
++ count++;
++ wp = (s->dlvry_queue_slot + 1) % HISI_SAS_QUEUE_SLOTS;
++ list_del(&s->delivery);
++ }
++
++ if (!count)
++ return;
+
+- dq->wr_point = ++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS;
+- hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14),
+- dq->wr_point);
++ hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14), wp);
+ }
+
+ static void prep_prd_sge_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 8cd13744a090..56f1046b244c 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -840,23 +840,37 @@ get_free_slot_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_dq *dq)
+ r = hisi_sas_read32_relaxed(hisi_hba,
+ DLVRY_Q_0_RD_PTR + (queue * 0x14));
+ if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) {
+- dev_warn(dev, "full queue=%d r=%d w=%d\n\n",
++ dev_warn(dev, "full queue=%d r=%d w=%d\n",
+ queue, r, w);
+ return -EAGAIN;
+ }
+
+- return 0;
++ dq->wr_point = (dq->wr_point + 1) % HISI_SAS_QUEUE_SLOTS;
++
++ return w;
+ }
+
+ static void start_delivery_v3_hw(struct hisi_sas_dq *dq)
+ {
+ struct hisi_hba *hisi_hba = dq->hisi_hba;
+- int dlvry_queue = dq->slot_prep->dlvry_queue;
+- int dlvry_queue_slot = dq->slot_prep->dlvry_queue_slot;
++ struct hisi_sas_slot *s, *s1;
++ struct list_head *dq_list;
++ int dlvry_queue = dq->id;
++ int wp, count = 0;
++
++ dq_list = &dq->list;
++ list_for_each_entry_safe(s, s1, &dq->list, delivery) {
++ if (!s->ready)
++ break;
++ count++;
++ wp = (s->dlvry_queue_slot + 1) % HISI_SAS_QUEUE_SLOTS;
++ list_del(&s->delivery);
++ }
++
++ if (!count)
++ return;
+
+- dq->wr_point = ++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS;
+- hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14),
+- dq->wr_point);
++ hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14), wp);
+ }
+
+ static void prep_prd_sge_v3_hw(struct hisi_hba *hisi_hba,
+
diff --git a/patches.drivers/scsi-hisi_sas-dt-bindings-add-an-property-of-signal-attenuation.patch b/patches.drivers/scsi-hisi_sas-dt-bindings-add-an-property-of-signal-attenuation.patch
new file mode 100644
index 0000000000..80e930a4c0
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-dt-bindings-add-an-property-of-signal-attenuation.patch
@@ -0,0 +1,44 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Wed, 7 Mar 2018 20:25:05 +0800
+Subject: scsi: hisi_sas: dt-bindings: add an property of signal attenuation
+Git-commit: 4c40db995eb54c3ee8cb5a8340640f49395d5f9e
+Patch-mainline: v4.17-rc1
+References: FATE#326253
+
+For some new boards with hip07 chipset we are required to set PHY config
+registers differently. The hw property which determines how to set these
+registers is in the PHY signal attenuation readings.
+
+This patch add an devicetree property, "hisilicon,signal-attenuation", which
+is used to describe the signal attenuation of an board.
+
+Cc: Rob Herring <robh+dt@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Reviewed-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ Documentation/devicetree/bindings/scsi/hisilicon-sas.txt | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
+index df3bef7998fa..8c6659ed2cfc 100644
+--- a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
++++ b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
+@@ -53,6 +53,13 @@ Main node required properties:
+ Optional main node properties:
+ - hip06-sas-v2-quirk-amt : when set, indicates that the v2 controller has the
+ "am-max-transmissions" limitation.
++ - hisilicon,signal-attenuation : array of 3 32-bit values, containing de-emphasis,
++ preshoot, and boost attenuation readings for the board. They
++ are used to describe the signal attenuation of the board. These
++ values' range is 7600 to 12400, and used to represent -24dB to
++ 24dB.
++ The formula is "y = (x-10000)/10000". For example, 10478
++ means 4.78dB.
+
+ Example:
+ sas0: sas@c1000000 {
+
diff --git a/patches.drivers/scsi-hisi_sas-fix-a-bug-in-hisi_sas_dev_gone.patch b/patches.drivers/scsi-hisi_sas-fix-a-bug-in-hisi_sas_dev_gone.patch
new file mode 100644
index 0000000000..2c4bf4d84d
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-fix-a-bug-in-hisi_sas_dev_gone.patch
@@ -0,0 +1,35 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Thu, 18 Jan 2018 00:46:54 +0800
+Subject: scsi: hisi_sas: fix a bug in hisi_sas_dev_gone()
+Git-commit: 0d762b3af2a5b5095fec18aa4d61f408638aa9ca
+Patch-mainline: v4.16-rc1
+References: FATE#326253
+
+When device gone, NULL pointer can be accessed in free_device callback
+if during SAS controller reset as we clear structure sas_dev prior.
+
+Actually we can only set dev_type as SAS_PHY_UNUSED and not clear
+structure sas_dev as all the members of structure sas_dev will be
+re-initialized after device found.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 791462d7fbfc..2d4dbed03ee3 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -796,7 +796,6 @@ static void hisi_sas_dev_gone(struct domain_device *device)
+
+ hisi_hba->hw->clear_itct(hisi_hba, sas_dev);
+ device->lldd_dev = NULL;
+- memset(sas_dev, 0, sizeof(*sas_dev));
+ }
+
+ if (hisi_hba->hw->free_device)
+
diff --git a/patches.drivers/scsi-hisi_sas-fix-a-typo-in-hisi_sas_task_prep.patch b/patches.drivers/scsi-hisi_sas-fix-a-typo-in-hisi_sas_task_prep.patch
new file mode 100644
index 0000000000..0598fd6f81
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-fix-a-typo-in-hisi_sas_task_prep.patch
@@ -0,0 +1,31 @@
+From: Wei Yongjun <weiyongjun1@huawei.com>
+Date: Sat, 26 May 2018 09:34:22 +0000
+Subject: scsi: hisi_sas: fix a typo in hisi_sas_task_prep()
+Git-commit: eb217359ebeae7b9ac51045d50f7a516925bc5c2
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+Fix a typo in hisi_sas_task_prep().
+
+Fixes: 7eee4b921822 ("scsi: hisi_sas: relocate smp sg map")
+Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ 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 39f694eb7b00..6d3796553272 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -390,7 +390,7 @@ static int hisi_sas_task_prep(struct sas_task *task,
+ }
+ n_elem_resp = dma_map_sg(dev, &task->smp_task.smp_resp,
+ 1, DMA_FROM_DEVICE);
+- if (!n_elem_req) {
++ if (!n_elem_resp) {
+ rc = -ENOMEM;
+ goto err_out_dma_unmap;
+ }
+
diff --git a/patches.drivers/scsi-hisi_sas-fix-dma_unmap_sg-parameter.patch b/patches.drivers/scsi-hisi_sas-fix-dma_unmap_sg-parameter.patch
new file mode 100644
index 0000000000..0e96cd5448
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-fix-dma_unmap_sg-parameter.patch
@@ -0,0 +1,45 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Sat, 9 Dec 2017 01:16:33 +0800
+Subject: scsi: hisi_sas: fix dma_unmap_sg() parameter
+Git-commit: dc1e4730e2b636065628f8427b675788bca83d34
+Patch-mainline: v4.16-rc1
+References: FATE#326253
+
+For function dma_unmap_sg(), the <nents> parameter should be number of
+elements in the scatterlist prior to the mapping, not after the mapping.
+
+Fix this usage.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ 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 359ec52fc2fb..d8425303eadd 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -192,7 +192,8 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
+
+ if (!sas_protocol_ata(task->task_proto))
+ if (slot->n_elem)
+- dma_unmap_sg(dev, task->scatter, slot->n_elem,
++ dma_unmap_sg(dev, task->scatter,
++ task->num_scatter,
+ task->data_dir);
+
+ if (sas_dev)
+@@ -431,7 +432,8 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
+ dev_err(dev, "task prep: failed[%d]!\n", rc);
+ if (!sas_protocol_ata(task->task_proto))
+ if (n_elem)
+- dma_unmap_sg(dev, task->scatter, n_elem,
++ dma_unmap_sg(dev, task->scatter,
++ task->num_scatter,
+ task->data_dir);
+ prep_out:
+ return rc;
+
diff --git a/patches.drivers/scsi-hisi_sas-fix-pi-memory-size.patch b/patches.drivers/scsi-hisi_sas-fix-pi-memory-size.patch
new file mode 100644
index 0000000000..e66a9d1e8e
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-fix-pi-memory-size.patch
@@ -0,0 +1,35 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Wed, 2 May 2018 23:56:27 +0800
+Subject: scsi: hisi_sas: fix PI memory size
+Git-commit: a14da7a20d499c54ebe53e430283e3bc17d3e89f
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+There are 28 bytes of protection information record of SSP for v3 hw, 16
+bytes for v2 hw, and probably 24 for v1 hw (forgotten now).
+
+So use a value big enough in hisi_sas_command_table_ssp.prot to cover
+all cases.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
+index 147cfafdad9f..04a40c427a20 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas.h
++++ b/drivers/scsi/hisi_sas/hisi_sas.h
+@@ -410,7 +410,7 @@ struct hisi_sas_command_table_ssp {
+ union {
+ struct {
+ struct ssp_command_iu task;
+- u32 prot[6];
++ u32 prot[7];
+ };
+ struct ssp_tmf_iu ssp_task;
+ struct xfer_rdy_iu xfer_rdy;
+
diff --git a/patches.drivers/scsi-hisi_sas-fix-return-value-of-hisi_sas_task_prep.patch b/patches.drivers/scsi-hisi_sas-fix-return-value-of-hisi_sas_task_prep.patch
new file mode 100644
index 0000000000..2708ab82bf
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-fix-return-value-of-hisi_sas_task_prep.patch
@@ -0,0 +1,58 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Wed, 7 Mar 2018 20:25:11 +0800
+Subject: scsi: hisi_sas: fix return value of hisi_sas_task_prep()
+Git-commit: 6bf6db518cd10ad57e659607d0abece1b81956c6
+Patch-mainline: v4.17-rc1
+References: FATE#326253
+
+It is an implicit regulation that error code that function returned should
+be negative. But hisi_sas_task_prep() doesn't follow this. This may cause
+problems in the upper layer code.
+
+For example, in sas_expander.c of libsas, smp_execute_task_sg() may return
+the number of bytes of underrun. It will be conflicted with the scenaio
+lldd_execute_task() return an positive error code.
+
+This patch change the return value from SAS_PHY_DOWN to -ECOMM in
+hisi_sas_task_prep().
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 88ad8d42ef6f..dff972393086 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -316,7 +316,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
+ */
+ if (device->dev_type != SAS_SATA_DEV)
+ task->task_done(task);
+- return SAS_PHY_DOWN;
++ return -ECOMM;
+ }
+
+ if (DEV_IS_GONE(sas_dev)) {
+@@ -327,7 +327,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
+ dev_info(dev, "task prep: device %016llx not ready\n",
+ SAS_ADDR(device->sas_addr));
+
+- return SAS_PHY_DOWN;
++ return -ECOMM;
+ }
+
+ port = to_hisi_sas_port(sas_port);
+@@ -337,7 +337,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
+ "SATA/STP" : "SAS",
+ device->port->id);
+
+- return SAS_PHY_DOWN;
++ return -ECOMM;
+ }
+
+ if (!sas_protocol_ata(task->task_proto)) {
+
diff --git a/patches.drivers/scsi-hisi_sas-fix-return-value-when-get_free_slot-failed.patch b/patches.drivers/scsi-hisi_sas-fix-return-value-when-get_free_slot-failed.patch
new file mode 100644
index 0000000000..4389c77ff5
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-fix-return-value-when-get_free_slot-failed.patch
@@ -0,0 +1,43 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Mon, 21 May 2018 18:09:24 +0800
+Subject: scsi: hisi_sas: Fix return value when get_free_slot() failed
+Git-commit: d87e72fb4fda6c48909e870811ae5252d0520f99
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+It is an step of executing task to get free slot. If the step fails, we
+will cleanup LLDD resources and should return failure to upper layer or
+internal caller to abort task execution of this time.
+
+But in the current code, the caller of get_free_slot() doesn't return
+failure when get_free_slot() failed. This patch is to fix it.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ 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 cd55849bcd07..3028024cb437 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -443,6 +443,7 @@ static int hisi_sas_task_prep(struct sas_task *task,
+ wr_q_index = hisi_hba->hw->get_free_slot(hisi_hba, dq);
+ if (wr_q_index < 0) {
+ spin_unlock_irqrestore(&dq->lock, flags_dq);
++ rc = -EAGAIN;
+ goto err_out_buf;
+ }
+
+@@ -1708,6 +1709,7 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id,
+ wr_q_index = hisi_hba->hw->get_free_slot(hisi_hba, dq);
+ if (wr_q_index < 0) {
+ spin_unlock_irqrestore(&dq->lock, flags_dq);
++ rc = -EAGAIN;
+ goto err_out_buf;
+ }
+ list_add_tail(&slot->delivery, &dq->list);
+
diff --git a/patches.drivers/scsi-hisi_sas-fix-sas_queue_full-problem-while-running-io.patch b/patches.drivers/scsi-hisi_sas-fix-sas_queue_full-problem-while-running-io.patch
new file mode 100644
index 0000000000..e42ad65592
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-fix-sas_queue_full-problem-while-running-io.patch
@@ -0,0 +1,42 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Sat, 9 Dec 2017 01:16:48 +0800
+Subject: scsi: hisi_sas: fix SAS_QUEUE_FULL problem while running IO
+Git-commit: 9960a24a1c96a40d6ab984ffefdd0e3003a3377e
+Patch-mainline: v4.16-rc1
+References: FATE#326253
+
+This patch fix SAS_QUEUE_FULL problem. The test situation is close port while
+running IO.
+
+In sas_eh_handle_sas_errors(), SCSI EH will free sas_task of the device if
+lldd_I_T_nexus_reset() return TMF_RESP_FUNC_COMPLETE or -ENODEV. But in our
+SAS driver, we only free slots of the device when the return value is
+TMF_RESP_FUNC_COMPLETE. So if the return value is -ENODEV, the slot resource
+will not free any more.
+
+As an solution, we should also free slots of the device in
+lldd_I_T_nexus_reset() if the return value is -ENODEV.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ 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 302da84bf9ef..9bd98e5be78e 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -1308,7 +1308,7 @@ static int hisi_sas_I_T_nexus_reset(struct domain_device *device)
+
+ rc = hisi_sas_debug_I_T_nexus_reset(device);
+
+- if (rc == TMF_RESP_FUNC_COMPLETE) {
++ if ((rc == TMF_RESP_FUNC_COMPLETE) || (rc == -ENODEV)) {
+ spin_lock_irqsave(&hisi_hba->lock, flags);
+ hisi_sas_release_task(hisi_hba, device);
+ spin_unlock_irqrestore(&hisi_hba->lock, flags);
+
diff --git a/patches.drivers/scsi-hisi_sas-fix-the-issue-of-link-rate-inconsistency.patch b/patches.drivers/scsi-hisi_sas-fix-the-issue-of-link-rate-inconsistency.patch
new file mode 100644
index 0000000000..5272a4bbcf
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-fix-the-issue-of-link-rate-inconsistency.patch
@@ -0,0 +1,124 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Wed, 7 Mar 2018 20:25:07 +0800
+Subject: scsi: hisi_sas: fix the issue of link rate inconsistency
+Git-commit: eba8c20c7178af9673ad842b0f68251c891c8546
+Patch-mainline: v4.17-rc1
+References: FATE#326253
+
+In sysfs, there are two files about minimum linkrate, and also two files for
+maximum linkrate. Take maximum linkrate example, maximum_linkrate_hw is
+read-only and indicated by the register HARD_PHY_LINKRATE, and
+maximum_linkrate is read-write and corresponding to the register
+PROG_PHY_LINK_RATE.
+
+But in the function phy_up_v*_hw(), we get *_linkrate value from
+HARD_PHY_LINKRATE. It is not right. This patch is to fix this issue.
+
+Unreferenced PHY-interrupt enum is also removed for v3 hw.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 2 ++
+ drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 1 -
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 8 +-------
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 13 +------------
+ 4 files changed, 4 insertions(+), 20 deletions(-)
+
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -683,6 +683,8 @@ static void hisi_sas_phy_init(struct his
+
+ phy->hisi_hba = hisi_hba;
+ phy->port = NULL;
++ phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
++ phy->maximum_linkrate = hisi_hba->hw->phy_get_max_linkrate();
+ init_timer(&phy->timer);
+ sas_phy->enabled = (phy_no < hisi_hba->n_phy) ? 1 : 0;
+ sas_phy->class = SAS;
+--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+@@ -873,7 +873,6 @@ static void phy_set_linkrate_v1_hw(struc
+ sas_phy->phy->maximum_linkrate = max;
+ sas_phy->phy->minimum_linkrate = min;
+
+- min -= SAS_LINK_RATE_1_5_GBPS;
+ max -= SAS_LINK_RATE_1_5_GBPS;
+
+ for (i = 0; i <= max; i++)
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -1604,7 +1604,6 @@ static void phy_set_linkrate_v2_hw(struc
+ sas_phy->phy->maximum_linkrate = max;
+ sas_phy->phy->minimum_linkrate = min;
+
+- min -= SAS_LINK_RATE_1_5_GBPS;
+ max -= SAS_LINK_RATE_1_5_GBPS;
+
+ for (i = 0; i <= max; i++)
+@@ -2686,7 +2685,7 @@ static int prep_abort_v2_hw(struct hisi_
+ static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
+ {
+ int i, res = IRQ_HANDLED;
+- u32 port_id, link_rate, hard_phy_linkrate;
++ u32 port_id, link_rate;
+ 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;
+@@ -2725,11 +2724,6 @@ static int phy_up_v2_hw(int phy_no, stru
+ }
+
+ sas_phy->linkrate = link_rate;
+- hard_phy_linkrate = hisi_sas_phy_read32(hisi_hba, phy_no,
+- HARD_PHY_LINKRATE);
+- phy->maximum_linkrate = hard_phy_linkrate & 0xf;
+- phy->minimum_linkrate = (hard_phy_linkrate >> 4) & 0xf;
+-
+ sas_phy->oob_mode = SAS_OOB_MODE;
+ memcpy(sas_phy->attached_sas_addr, &id->sas_addr, SAS_ADDR_SIZE);
+ dev_info(dev, "phyup: phy%d link_rate=%d\n", phy_no, link_rate);
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -340,12 +340,6 @@ struct hisi_sas_err_record_v3 {
+ #define HISI_SAS_COMMAND_ENTRIES_V3_HW 4096
+ #define HISI_SAS_MSI_COUNT_V3_HW 32
+
+-enum {
+- HISI_SAS_PHY_PHY_UPDOWN,
+- HISI_SAS_PHY_CHNL_INT,
+- HISI_SAS_PHY_INT_NR
+-};
+-
+ #define DIR_NO_DATA 0
+ #define DIR_TO_INI 1
+ #define DIR_TO_DEVICE 2
+@@ -1121,7 +1115,7 @@ static int prep_abort_v3_hw(struct hisi_
+ static int phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
+ {
+ int i, res = 0;
+- u32 context, port_id, link_rate, hard_phy_linkrate;
++ u32 context, port_id, link_rate;
+ 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;
+@@ -1139,10 +1133,6 @@ static int phy_up_v3_hw(int phy_no, stru
+ goto end;
+ }
+ sas_phy->linkrate = link_rate;
+- hard_phy_linkrate = hisi_sas_phy_read32(hisi_hba, phy_no,
+- HARD_PHY_LINKRATE);
+- phy->maximum_linkrate = hard_phy_linkrate & 0xf;
+- phy->minimum_linkrate = (hard_phy_linkrate >> 4) & 0xf;
+ phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA);
+
+ /* Check for SATA dev */
+@@ -1864,7 +1854,6 @@ static void phy_set_linkrate_v3_hw(struc
+ sas_phy->phy->maximum_linkrate = max;
+ sas_phy->phy->minimum_linkrate = min;
+
+- min -= SAS_LINK_RATE_1_5_GBPS;
+ max -= SAS_LINK_RATE_1_5_GBPS;
+
+ for (i = 0; i <= max; i++)
diff --git a/patches.drivers/scsi-hisi_sas-fix-the-issue-of-setting-linkrate-register.patch b/patches.drivers/scsi-hisi_sas-fix-the-issue-of-setting-linkrate-register.patch
new file mode 100644
index 0000000000..c10758c638
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-fix-the-issue-of-setting-linkrate-register.patch
@@ -0,0 +1,77 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Wed, 7 Mar 2018 20:25:08 +0800
+Subject: scsi: hisi_sas: fix the issue of setting linkrate register
+Git-commit: 0006ce29e87ba357f64ee73e92c8aefc270fd315
+Patch-mainline: v4.17-rc1
+References: FATE#326253
+
+It is not right to set the register PROG_PHY_LINK_RATE while PHY is still
+enabled. So if we want to change PHY linkrate, we need to disable PHY before
+setting the register PROG_PHY_LINK_RATE, and then start-up PHY. This patch
+is to fix this issue.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 5 +++--
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 5 +++--
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 5 +++--
+ 3 files changed, 9 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+index 38bbda938bc1..2eb89806c512 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+@@ -881,10 +881,11 @@ static void phy_set_linkrate_v1_hw(struct hisi_hba *hisi_hba, int phy_no,
+ prog_phy_link_rate &= ~0xff;
+ prog_phy_link_rate |= rate_mask;
+
++ disable_phy_v1_hw(hisi_hba, phy_no);
++ msleep(100);
+ hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE,
+ prog_phy_link_rate);
+-
+- phy_hard_reset_v1_hw(hisi_hba, phy_no);
++ start_phy_v1_hw(hisi_hba, phy_no);
+ }
+
+ static int get_wideport_bitmap_v1_hw(struct hisi_hba *hisi_hba, int port_id)
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+index 67be346db239..bd1a48a590bc 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -1611,10 +1611,11 @@ static void phy_set_linkrate_v2_hw(struct hisi_hba *hisi_hba, int phy_no,
+ prog_phy_link_rate &= ~0xff;
+ prog_phy_link_rate |= rate_mask;
+
++ disable_phy_v2_hw(hisi_hba, phy_no);
++ msleep(100);
+ hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE,
+ prog_phy_link_rate);
+-
+- phy_hard_reset_v2_hw(hisi_hba, phy_no);
++ start_phy_v2_hw(hisi_hba, phy_no);
+ }
+
+ static int get_wideport_bitmap_v2_hw(struct hisi_hba *hisi_hba, int port_id)
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+index 1ee95abda1c5..8da9de7d67e5 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -1862,10 +1862,11 @@ static void phy_set_linkrate_v3_hw(struct hisi_hba *hisi_hba, int phy_no,
+ prog_phy_link_rate &= ~0xff;
+ prog_phy_link_rate |= rate_mask;
+
++ disable_phy_v3_hw(hisi_hba, phy_no);
++ msleep(100);
+ hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE,
+ prog_phy_link_rate);
+-
+- phy_hard_reset_v3_hw(hisi_hba, phy_no);
++ start_phy_v3_hw(hisi_hba, phy_no);
+ }
+
+ static void interrupt_disable_v3_hw(struct hisi_hba *hisi_hba)
+
diff --git a/patches.drivers/scsi-hisi_sas-improve-int_chnl_int_v2_hw-consistency-with-v3-hw.patch b/patches.drivers/scsi-hisi_sas-improve-int_chnl_int_v2_hw-consistency-with-v3-hw.patch
new file mode 100644
index 0000000000..71b625268a
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-improve-int_chnl_int_v2_hw-consistency-with-v3-hw.patch
@@ -0,0 +1,92 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Sat, 9 Dec 2017 01:16:42 +0800
+Subject: scsi: hisi_sas: improve int_chnl_int_v2_hw() consistency with v3 hw
+Git-commit: f64715d2837bee8fcd71f3e13acc7f02c9e9d98a
+Patch-mainline: v4.16-rc1
+References: FATE#326253
+
+Change code format of int_chnl_int_v2_hw() to be consistent with v3 hw to
+reduce an tag indent.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 58 ++++++++++++++++------------------
+ 1 file changed, 28 insertions(+), 30 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+index 8d6886a452ef..4c4a000c5db0 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -2848,40 +2848,38 @@ static irqreturn_t int_chnl_int_v2_hw(int irq_no, void *p)
+ HGC_INVLD_DQE_INFO_FB_CH3_OFF) & 0x1ff;
+
+ while (irq_msk) {
+- if (irq_msk & (1 << phy_no)) {
+- u32 irq_value0 = hisi_sas_phy_read32(hisi_hba, phy_no,
+- CHL_INT0);
+- u32 irq_value1 = hisi_sas_phy_read32(hisi_hba, phy_no,
+- CHL_INT1);
+- u32 irq_value2 = hisi_sas_phy_read32(hisi_hba, phy_no,
+- CHL_INT2);
+-
+- if (irq_value1) {
+- if (irq_value1 & (CHL_INT1_DMAC_RX_ECC_ERR_MSK |
+- CHL_INT1_DMAC_TX_ECC_ERR_MSK))
+- panic("%s: DMAC RX/TX ecc bad error!\
+- (0x%x)",
+- dev_name(dev), irq_value1);
+-
+- hisi_sas_phy_write32(hisi_hba, phy_no,
+- CHL_INT1, irq_value1);
+- }
++ u32 irq_value0 = hisi_sas_phy_read32(hisi_hba, phy_no,
++ CHL_INT0);
++ u32 irq_value1 = hisi_sas_phy_read32(hisi_hba, phy_no,
++ CHL_INT1);
++ u32 irq_value2 = hisi_sas_phy_read32(hisi_hba, phy_no,
++ CHL_INT2);
++
++ if ((irq_msk & (1 << phy_no)) && irq_value1) {
++ if (irq_value1 & (CHL_INT1_DMAC_RX_ECC_ERR_MSK |
++ CHL_INT1_DMAC_TX_ECC_ERR_MSK))
++ panic("%s: DMAC RX/TX ecc bad error!\
++ (0x%x)",
++ dev_name(dev), irq_value1);
+
+- if (irq_value2)
+- hisi_sas_phy_write32(hisi_hba, phy_no,
+- CHL_INT2, irq_value2);
++ hisi_sas_phy_write32(hisi_hba, phy_no,
++ CHL_INT1, irq_value1);
++ }
+
++ if ((irq_msk & (1 << phy_no)) && irq_value2)
++ hisi_sas_phy_write32(hisi_hba, phy_no,
++ CHL_INT2, irq_value2);
+
+- if (irq_value0) {
+- if (irq_value0 & CHL_INT0_SL_RX_BCST_ACK_MSK)
+- phy_bcast_v2_hw(phy_no, hisi_hba);
+
+- hisi_sas_phy_write32(hisi_hba, phy_no,
+- CHL_INT0, irq_value0
+- & (~CHL_INT0_HOTPLUG_TOUT_MSK)
+- & (~CHL_INT0_SL_PHY_ENABLE_MSK)
+- & (~CHL_INT0_NOT_RDY_MSK));
+- }
++ if ((irq_msk & (1 << phy_no)) && irq_value0) {
++ if (irq_value0 & CHL_INT0_SL_RX_BCST_ACK_MSK)
++ phy_bcast_v2_hw(phy_no, hisi_hba);
++
++ hisi_sas_phy_write32(hisi_hba, phy_no,
++ CHL_INT0, irq_value0
++ & (~CHL_INT0_HOTPLUG_TOUT_MSK)
++ & (~CHL_INT0_SL_PHY_ENABLE_MSK)
++ & (~CHL_INT0_NOT_RDY_MSK));
+ }
+ irq_msk &= ~(1 << phy_no);
+ phy_no++;
+
diff --git a/patches.drivers/scsi-hisi_sas-include-tmf-elements-in-struct-hisi_sas_slot.patch b/patches.drivers/scsi-hisi_sas-include-tmf-elements-in-struct-hisi_sas_slot.patch
new file mode 100644
index 0000000000..9a7af9c49d
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-include-tmf-elements-in-struct-hisi_sas_slot.patch
@@ -0,0 +1,256 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Mon, 21 May 2018 18:09:21 +0800
+Subject: scsi: hisi_sas: Include TMF elements in struct hisi_sas_slot
+Git-commit: 78bd2b4f6e7c0522cc8bc8ad651f20813ae06f6c
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+In future scenarios we will want to use the TMF struct for more task types
+than SSP.
+
+As such, we can add struct hisi_sas_tmf_task directly into struct
+hisi_sas_slot, and this will mean we can remove the TMF parameters from the
+task prep functions.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas.h | 14 +++++++-------
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 15 +++++++--------
+ drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 12 ++++++------
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 10 +++++-----
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 10 +++++-----
+ 5 files changed, 30 insertions(+), 31 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
+index 8ce6abb48867..60bd652534fe 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas.h
++++ b/drivers/scsi/hisi_sas/hisi_sas.h
+@@ -179,6 +179,11 @@ struct hisi_sas_device {
+ u8 dev_status;
+ };
+
++struct hisi_sas_tmf_task {
++ u8 tmf;
++ u16 tag_of_task_to_be_managed;
++};
++
+ struct hisi_sas_slot {
+ struct list_head entry;
+ struct list_head delivery;
+@@ -199,11 +204,7 @@ struct hisi_sas_slot {
+ struct work_struct abort_slot;
+ struct timer_list internal_abort_timer;
+ bool is_internal;
+-};
+-
+-struct hisi_sas_tmf_task {
+- u8 tmf;
+- u16 tag_of_task_to_be_managed;
++ struct hisi_sas_tmf_task *tmf;
+ };
+
+ struct hisi_sas_hw {
+@@ -217,8 +218,7 @@ struct hisi_sas_hw {
+ int (*get_free_slot)(struct hisi_hba *hisi_hba, struct hisi_sas_dq *dq);
+ void (*start_delivery)(struct hisi_sas_dq *dq);
+ void (*prep_ssp)(struct hisi_hba *hisi_hba,
+- struct hisi_sas_slot *slot, int is_tmf,
+- struct hisi_sas_tmf_task *tmf);
++ struct hisi_sas_slot *slot);
+ void (*prep_smp)(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot);
+ void (*prep_stp)(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 5bc522c35690..4e8046ecf477 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -266,10 +266,9 @@ static void hisi_sas_task_prep_smp(struct hisi_hba *hisi_hba,
+ }
+
+ static void hisi_sas_task_prep_ssp(struct hisi_hba *hisi_hba,
+- struct hisi_sas_slot *slot, int is_tmf,
+- struct hisi_sas_tmf_task *tmf)
++ struct hisi_sas_slot *slot)
+ {
+- hisi_hba->hw->prep_ssp(hisi_hba, slot, is_tmf, tmf);
++ hisi_hba->hw->prep_ssp(hisi_hba, slot);
+ }
+
+ static void hisi_sas_task_prep_ata(struct hisi_hba *hisi_hba,
+@@ -322,7 +321,7 @@ static void hisi_sas_slot_abort(struct work_struct *work)
+
+ static int hisi_sas_task_prep(struct sas_task *task,
+ struct hisi_sas_dq **dq_pointer,
+- int is_tmf, struct hisi_sas_tmf_task *tmf,
++ bool is_tmf, struct hisi_sas_tmf_task *tmf,
+ int *pass)
+ {
+ struct domain_device *device = task->dev;
+@@ -461,8 +460,8 @@ static int hisi_sas_task_prep(struct sas_task *task,
+ slot->cmd_hdr = &cmd_hdr_base[dlvry_queue_slot];
+ slot->task = task;
+ slot->port = port;
+- if (is_tmf)
+- slot->is_internal = true;
++ slot->tmf = tmf;
++ slot->is_internal = is_tmf;
+ task->lldd_task = slot;
+ INIT_WORK(&slot->abort_slot, hisi_sas_slot_abort);
+
+@@ -475,7 +474,7 @@ static int hisi_sas_task_prep(struct sas_task *task,
+ hisi_sas_task_prep_smp(hisi_hba, slot);
+ break;
+ case SAS_PROTOCOL_SSP:
+- hisi_sas_task_prep_ssp(hisi_hba, slot, is_tmf, tmf);
++ hisi_sas_task_prep_ssp(hisi_hba, slot);
+ break;
+ case SAS_PROTOCOL_SATA:
+ case SAS_PROTOCOL_STP:
+@@ -527,7 +526,7 @@ static int hisi_sas_task_prep(struct sas_task *task,
+ }
+
+ static int hisi_sas_task_exec(struct sas_task *task, gfp_t gfp_flags,
+- int is_tmf, struct hisi_sas_tmf_task *tmf)
++ bool is_tmf, struct hisi_sas_tmf_task *tmf)
+ {
+ u32 rc;
+ u32 pass = 0;
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+index 8d5d8575d939..05609ac1b31d 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+@@ -986,8 +986,7 @@ static void prep_smp_v1_hw(struct hisi_hba *hisi_hba,
+ }
+
+ static void prep_ssp_v1_hw(struct hisi_hba *hisi_hba,
+- struct hisi_sas_slot *slot, int is_tmf,
+- struct hisi_sas_tmf_task *tmf)
++ struct hisi_sas_slot *slot)
+ {
+ struct sas_task *task = slot->task;
+ struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
+@@ -996,7 +995,8 @@ static void prep_ssp_v1_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_port *port = slot->port;
+ struct sas_ssp_task *ssp_task = &task->ssp_task;
+ struct scsi_cmnd *scsi_cmnd = ssp_task->cmd;
+- int has_data = 0, priority = is_tmf;
++ struct hisi_sas_tmf_task *tmf = slot->tmf;
++ int has_data = 0, priority = !!tmf;
+ u8 *buf_cmd, fburst = 0;
+ u32 dw1, dw2;
+
+@@ -1010,7 +1010,7 @@ static void prep_ssp_v1_hw(struct hisi_hba *hisi_hba,
+
+ dw1 = 1 << CMD_HDR_VERIFY_DTL_OFF;
+
+- if (is_tmf) {
++ if (tmf) {
+ dw1 |= 3 << CMD_HDR_SSP_FRAME_TYPE_OFF;
+ } else {
+ switch (scsi_cmnd->sc_data_direction) {
+@@ -1031,7 +1031,7 @@ static void prep_ssp_v1_hw(struct hisi_hba *hisi_hba,
+ dw1 |= sas_dev->device_id << CMD_HDR_DEVICE_ID_OFF;
+ hdr->dw1 = cpu_to_le32(dw1);
+
+- if (is_tmf) {
++ if (tmf) {
+ dw2 = ((sizeof(struct ssp_tmf_iu) +
+ sizeof(struct ssp_frame_hdr)+3)/4) <<
+ CMD_HDR_CFL_OFF;
+@@ -1062,7 +1062,7 @@ static void prep_ssp_v1_hw(struct hisi_hba *hisi_hba,
+ hdr->dw2 = cpu_to_le32(dw2);
+
+ memcpy(buf_cmd, &task->ssp_task.LUN, 8);
+- if (!is_tmf) {
++ if (!tmf) {
+ buf_cmd[9] = fburst | task->ssp_task.task_attr |
+ (task->ssp_task.task_prio << 3);
+ memcpy(buf_cmd + 12, task->ssp_task.cmd->cmnd,
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+index 18dbaffc9988..fafb3f1835be 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -1745,8 +1745,7 @@ static void prep_smp_v2_hw(struct hisi_hba *hisi_hba,
+ }
+
+ static void prep_ssp_v2_hw(struct hisi_hba *hisi_hba,
+- struct hisi_sas_slot *slot, int is_tmf,
+- struct hisi_sas_tmf_task *tmf)
++ struct hisi_sas_slot *slot)
+ {
+ struct sas_task *task = slot->task;
+ struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
+@@ -1755,7 +1754,8 @@ static void prep_ssp_v2_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_port *port = slot->port;
+ struct sas_ssp_task *ssp_task = &task->ssp_task;
+ struct scsi_cmnd *scsi_cmnd = ssp_task->cmd;
+- int has_data = 0, priority = is_tmf;
++ struct hisi_sas_tmf_task *tmf = slot->tmf;
++ int has_data = 0, priority = !!tmf;
+ u8 *buf_cmd;
+ u32 dw1 = 0, dw2 = 0;
+
+@@ -1766,7 +1766,7 @@ static void prep_ssp_v2_hw(struct hisi_hba *hisi_hba,
+ (1 << CMD_HDR_CMD_OFF)); /* ssp */
+
+ dw1 = 1 << CMD_HDR_VDTL_OFF;
+- if (is_tmf) {
++ if (tmf) {
+ dw1 |= 2 << CMD_HDR_FRAME_TYPE_OFF;
+ dw1 |= DIR_NO_DATA << CMD_HDR_DIR_OFF;
+ } else {
+@@ -1809,7 +1809,7 @@ static void prep_ssp_v2_hw(struct hisi_hba *hisi_hba,
+ sizeof(struct ssp_frame_hdr);
+
+ memcpy(buf_cmd, &task->ssp_task.LUN, 8);
+- if (!is_tmf) {
++ if (!tmf) {
+ buf_cmd[9] = task->ssp_task.task_attr |
+ (task->ssp_task.task_prio << 3);
+ memcpy(buf_cmd + 12, task->ssp_task.cmd->cmnd,
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+index dd5f542bbc45..8c996aa42528 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -911,8 +911,7 @@ static void prep_prd_sge_v3_hw(struct hisi_hba *hisi_hba,
+ }
+
+ static void prep_ssp_v3_hw(struct hisi_hba *hisi_hba,
+- struct hisi_sas_slot *slot, int is_tmf,
+- struct hisi_sas_tmf_task *tmf)
++ struct hisi_sas_slot *slot)
+ {
+ struct sas_task *task = slot->task;
+ struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
+@@ -921,7 +920,8 @@ static void prep_ssp_v3_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_port *port = slot->port;
+ struct sas_ssp_task *ssp_task = &task->ssp_task;
+ struct scsi_cmnd *scsi_cmnd = ssp_task->cmd;
+- int has_data = 0, priority = is_tmf;
++ struct hisi_sas_tmf_task *tmf = slot->tmf;
++ int has_data = 0, priority = !!tmf;
+ u8 *buf_cmd;
+ u32 dw1 = 0, dw2 = 0;
+
+@@ -932,7 +932,7 @@ static void prep_ssp_v3_hw(struct hisi_hba *hisi_hba,
+ (1 << CMD_HDR_CMD_OFF)); /* ssp */
+
+ dw1 = 1 << CMD_HDR_VDTL_OFF;
+- if (is_tmf) {
++ if (tmf) {
+ dw1 |= 2 << CMD_HDR_FRAME_TYPE_OFF;
+ dw1 |= DIR_NO_DATA << CMD_HDR_DIR_OFF;
+ } else {
+@@ -974,7 +974,7 @@ static void prep_ssp_v3_hw(struct hisi_hba *hisi_hba,
+ sizeof(struct ssp_frame_hdr);
+
+ memcpy(buf_cmd, &task->ssp_task.LUN, 8);
+- if (!is_tmf) {
++ if (!tmf) {
+ buf_cmd[9] = ssp_task->task_attr | (ssp_task->task_prio << 3);
+ memcpy(buf_cmd + 12, scsi_cmnd->cmnd, scsi_cmnd->cmd_len);
+ } else {
+
diff --git a/patches.drivers/scsi-hisi_sas-increase-timer-expire-of-internal-abort-task.patch b/patches.drivers/scsi-hisi_sas-increase-timer-expire-of-internal-abort-task.patch
new file mode 100644
index 0000000000..26dafefa9d
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-increase-timer-expire-of-internal-abort-task.patch
@@ -0,0 +1,44 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Wed, 7 Mar 2018 20:25:09 +0800
+Subject: scsi: hisi_sas: increase timer expire of internal abort task
+Git-commit: bb9abc4af5449d2a72cda876be950988e8b2b888
+Patch-mainline: v4.17-rc1
+References: FATE#326253
+
+The current 110ms expiry time is not long enough for the internal abort
+task.
+
+The reason is that the internal abort task could be blocked in HW if the HW
+is retrying to set up link. The internal abort task will be executed only
+when the retry process finished.
+
+The maximum time is 5s for the retry of setting up link. So, the timer
+expire should be more than 5s. This patch increases it from 110ms to 6s.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -871,6 +871,7 @@ static void hisi_sas_tmf_timedout(unsign
+
+ #define TASK_TIMEOUT 20
+ #define TASK_RETRY 3
++#define INTERNAL_ABORT_TIMEOUT 6
+ static int hisi_sas_exec_internal_tmf_task(struct domain_device *device,
+ void *parameter, u32 para_len,
+ struct hisi_sas_tmf_task *tmf)
+@@ -1576,7 +1577,7 @@ hisi_sas_internal_task_abort(struct hisi
+ task->task_done = hisi_sas_task_done;
+ task->slow_task->timer.data = (unsigned long)task;
+ task->slow_task->timer.function = hisi_sas_tmf_timedout;
+- task->slow_task->timer.expires = jiffies + msecs_to_jiffies(110);
++ task->slow_task->timer.expires = jiffies + INTERNAL_ABORT_TIMEOUT*HZ;
+ add_timer(&task->slow_task->timer);
+
+ res = hisi_sas_internal_abort_task_exec(hisi_hba, sas_dev->device_id,
diff --git a/patches.drivers/scsi-hisi_sas-init-disks-after-controller-reset.patch b/patches.drivers/scsi-hisi_sas-init-disks-after-controller-reset.patch
new file mode 100644
index 0000000000..8e04434fc2
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-init-disks-after-controller-reset.patch
@@ -0,0 +1,79 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Mon, 21 May 2018 18:09:19 +0800
+Subject: scsi: hisi_sas: Init disks after controller reset
+Git-commit: 6175abdeaeaf2602f3e92bd4eca5916e98efe996
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+After the controller is reset, it is possible that the disks attached still
+have outstanding IO to complete.
+
+Thus, when the PHYs come back up after controller reset, it is possible
+that these IOs complete at some unknown point later.
+
+We want to ensure that all IOs are complete after the controller reset so
+that all associated IPTT and other resources can be recycled safely.
+
+To achieve this, re-init the disks by TMF or softreset (in case of ATA
+devices).
+
+If the init fails - maybe because the device was removed or link has not
+come up - then do not release the device resources, but rather rely on SCSI
+EH to handle the timeout for these resources later on.
+
+This patch also does some cleanup to hisi_sas_init_disk(), including
+removing superfluous cases in the switch statement.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 19 ++++++++++++++++++-
+ 1 file changed, 18 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 664aaf7f5147..dc67bd7c7ab0 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -1259,6 +1259,23 @@ static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 old_state,
+ }
+ }
+
++static void hisi_sas_reset_init_all_devices(struct hisi_hba *hisi_hba)
++{
++ struct hisi_sas_device *sas_dev;
++ struct domain_device *device;
++ int i;
++
++ for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
++ sas_dev = &hisi_hba->devices[i];
++ device = sas_dev->sas_device;
++
++ if ((sas_dev->dev_type == SAS_PHY_UNUSED) || !device)
++ continue;
++
++ hisi_sas_init_device(device);
++ }
++}
++
+ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
+ {
+ struct device *dev = hisi_hba->dev;
+@@ -1287,7 +1304,6 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
+ scsi_unblock_requests(shost);
+ goto out;
+ }
+- hisi_sas_release_tasks(hisi_hba);
+
+ clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
+
+@@ -1295,6 +1311,7 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
+ hisi_hba->hw->phys_init(hisi_hba);
+ msleep(1000);
+ hisi_sas_refresh_port_id(hisi_hba);
++ hisi_sas_reset_init_all_devices(hisi_hba);
+ scsi_unblock_requests(shost);
+
+ state = hisi_hba->hw->get_phys_state(hisi_hba);
+
diff --git a/patches.drivers/scsi-hisi_sas-initialize-dq-spinlock-before-use.patch b/patches.drivers/scsi-hisi_sas-initialize-dq-spinlock-before-use.patch
new file mode 100644
index 0000000000..36c894c024
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-initialize-dq-spinlock-before-use.patch
@@ -0,0 +1,32 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Sat, 9 Dec 2017 01:16:32 +0800
+Subject: scsi: hisi_sas: initialize dq spinlock before use
+Git-commit: 39bade0c9fb11e04945a5749e01e65a376e4eb02
+Patch-mainline: v4.16-rc1
+References: FATE#326253
+
+It is required to initialize the dq spinlock before use, which was not being
+done, so fix it. This issue can be detected when CONFIG_DEBUG_SPINLOCK is
+enabled.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 5f503cb09508..359ec52fc2fb 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -1657,6 +1657,7 @@ int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost)
+ cq->hisi_hba = hisi_hba;
+
+ /* Delivery queue structure */
++ spin_lock_init(&dq->lock);
+ dq->id = i;
+ dq->hisi_hba = hisi_hba;
+
+
diff --git a/patches.drivers/scsi-hisi_sas-introduce-hisi_sas_phy_set_linkrate.patch b/patches.drivers/scsi-hisi_sas-introduce-hisi_sas_phy_set_linkrate.patch
new file mode 100644
index 0000000000..eb9a166471
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-introduce-hisi_sas_phy_set_linkrate.patch
@@ -0,0 +1,191 @@
+From: John Garry <john.garry@huawei.com>
+Date: Mon, 21 May 2018 18:09:13 +0800
+Subject: scsi: hisi_sas: Introduce hisi_sas_phy_set_linkrate()
+Git-commit: 757db2dae2c79b1f713043fcc13542683963fa82
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+There is much common code and functionality between the HW versions to set
+the PHY linkrate.
+
+As such, this patch factors out the common code into a generic function
+hisi_sas_phy_set_linkrate().
+
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 29 +++++++++++++++++++++++++++-
+ drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 35 ++++------------------------------
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 21 ++------------------
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 21 ++------------------
+ 4 files changed, 36 insertions(+), 70 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 6d3796553272..66388741e73c 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -866,6 +866,33 @@ static int hisi_sas_queue_command(struct sas_task *task, gfp_t gfp_flags)
+ return hisi_sas_task_exec(task, gfp_flags, 0, NULL);
+ }
+
++static void hisi_sas_phy_set_linkrate(struct hisi_hba *hisi_hba, int phy_no,
++ struct sas_phy_linkrates *r)
++{
++ struct sas_phy_linkrates _r;
++
++ struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
++ struct asd_sas_phy *sas_phy = &phy->sas_phy;
++ enum sas_linkrate min, max;
++
++ if (r->maximum_linkrate == SAS_LINK_RATE_UNKNOWN) {
++ max = sas_phy->phy->maximum_linkrate;
++ min = r->minimum_linkrate;
++ } else if (r->minimum_linkrate == SAS_LINK_RATE_UNKNOWN) {
++ max = r->maximum_linkrate;
++ min = sas_phy->phy->minimum_linkrate;
++ } else
++ return;
++
++ _r.maximum_linkrate = max;
++ _r.minimum_linkrate = min;
++
++ hisi_hba->hw->phy_disable(hisi_hba, phy_no);
++ msleep(100);
++ hisi_hba->hw->phy_set_linkrate(hisi_hba, phy_no, &_r);
++ hisi_hba->hw->phy_start(hisi_hba, phy_no);
++}
++
+ static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func,
+ void *funcdata)
+ {
+@@ -889,7 +916,7 @@ static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func,
+ break;
+
+ case PHY_FUNC_SET_LINK_RATE:
+- hisi_hba->hw->phy_set_linkrate(hisi_hba, phy_no, funcdata);
++ hisi_sas_phy_set_linkrate(hisi_hba, phy_no, funcdata);
+ break;
+ case PHY_FUNC_GET_EVENTS:
+ if (hisi_hba->hw->get_events) {
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+index abe175fddb86..8fa79d0968a6 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+@@ -855,39 +855,12 @@ static enum sas_linkrate phy_get_max_linkrate_v1_hw(void)
+ static void phy_set_linkrate_v1_hw(struct hisi_hba *hisi_hba, int phy_no,
+ struct sas_phy_linkrates *r)
+ {
+- u32 prog_phy_link_rate =
+- hisi_sas_phy_read32(hisi_hba, phy_no, PROG_PHY_LINK_RATE);
+- struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
+- struct asd_sas_phy *sas_phy = &phy->sas_phy;
+- int i;
+- enum sas_linkrate min, max;
+- u32 rate_mask = 0;
+-
+- if (r->maximum_linkrate == SAS_LINK_RATE_UNKNOWN) {
+- max = sas_phy->phy->maximum_linkrate;
+- min = r->minimum_linkrate;
+- } else if (r->minimum_linkrate == SAS_LINK_RATE_UNKNOWN) {
+- max = r->maximum_linkrate;
+- min = sas_phy->phy->minimum_linkrate;
+- } else
+- return;
+-
+- sas_phy->phy->maximum_linkrate = max;
+- sas_phy->phy->minimum_linkrate = min;
+-
+- max -= SAS_LINK_RATE_1_5_GBPS;
++ enum sas_linkrate max = r->maximum_linkrate;
++ u32 prog_phy_link_rate = 0x800;
+
+- for (i = 0; i <= max; i++)
+- rate_mask |= 1 << (i * 2);
+-
+- prog_phy_link_rate &= ~0xff;
+- prog_phy_link_rate |= rate_mask;
+-
+- disable_phy_v1_hw(hisi_hba, phy_no);
+- msleep(100);
++ 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);
+- start_phy_v1_hw(hisi_hba, phy_no);
++ prog_phy_link_rate);
+ }
+
+ static int get_wideport_bitmap_v1_hw(struct hisi_hba *hisi_hba, int port_id)
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+index 911bb76a4d0a..fb0e966a44a8 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -1600,29 +1600,12 @@ static enum sas_linkrate phy_get_max_linkrate_v2_hw(void)
+ static void phy_set_linkrate_v2_hw(struct hisi_hba *hisi_hba, int phy_no,
+ struct sas_phy_linkrates *r)
+ {
+- struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
+- struct asd_sas_phy *sas_phy = &phy->sas_phy;
+- enum sas_linkrate min, max;
++ enum sas_linkrate max = r->maximum_linkrate;
+ u32 prog_phy_link_rate = 0x800;
+
+- if (r->maximum_linkrate == SAS_LINK_RATE_UNKNOWN) {
+- max = sas_phy->phy->maximum_linkrate;
+- min = r->minimum_linkrate;
+- } else if (r->minimum_linkrate == SAS_LINK_RATE_UNKNOWN) {
+- max = r->maximum_linkrate;
+- min = sas_phy->phy->minimum_linkrate;
+- } else
+- return;
+-
+- sas_phy->phy->maximum_linkrate = max;
+- sas_phy->phy->minimum_linkrate = min;
+ prog_phy_link_rate |= hisi_sas_get_prog_phy_linkrate_mask(max);
+-
+- disable_phy_v2_hw(hisi_hba, phy_no);
+- msleep(100);
+ hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE,
+- prog_phy_link_rate);
+- start_phy_v2_hw(hisi_hba, phy_no);
++ prog_phy_link_rate);
+ }
+
+ static int get_wideport_bitmap_v2_hw(struct hisi_hba *hisi_hba, int port_id)
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+index c013673ee8ac..0a80a39eccdd 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -1879,29 +1879,12 @@ static int hisi_sas_v3_init(struct hisi_hba *hisi_hba)
+ static void phy_set_linkrate_v3_hw(struct hisi_hba *hisi_hba, int phy_no,
+ struct sas_phy_linkrates *r)
+ {
+- struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
+- struct asd_sas_phy *sas_phy = &phy->sas_phy;
+- enum sas_linkrate min, max;
++ enum sas_linkrate max = r->maximum_linkrate;
+ u32 prog_phy_link_rate = 0x800;
+
+- if (r->maximum_linkrate == SAS_LINK_RATE_UNKNOWN) {
+- max = sas_phy->phy->maximum_linkrate;
+- min = r->minimum_linkrate;
+- } else if (r->minimum_linkrate == SAS_LINK_RATE_UNKNOWN) {
+- max = r->maximum_linkrate;
+- min = sas_phy->phy->minimum_linkrate;
+- } else
+- return;
+-
+- sas_phy->phy->maximum_linkrate = max;
+- sas_phy->phy->minimum_linkrate = min;
+ prog_phy_link_rate |= hisi_sas_get_prog_phy_linkrate_mask(max);
+-
+- disable_phy_v3_hw(hisi_hba, phy_no);
+- msleep(100);
+ hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE,
+- prog_phy_link_rate);
+- start_phy_v3_hw(hisi_hba, phy_no);
++ prog_phy_link_rate);
+ }
+
+ static void interrupt_disable_v3_hw(struct hisi_hba *hisi_hba)
+
diff --git a/patches.drivers/scsi-hisi_sas-judge-result-of-internal-abort.patch b/patches.drivers/scsi-hisi_sas-judge-result-of-internal-abort.patch
new file mode 100644
index 0000000000..a85c1c3306
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-judge-result-of-internal-abort.patch
@@ -0,0 +1,137 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Sat, 9 Dec 2017 01:16:46 +0800
+Subject: scsi: hisi_sas: judge result of internal abort
+Git-commit: 813709f2e1e07fa872c05f43801a05828d33a70a
+Patch-mainline: v4.16-rc1
+References: FATE#326253
+
+Normally, hardware should ensure that internal abort timeout will never
+happen. If happen, it would be an SoC failure. What's more, HW will not
+process any other commands if an internal abort hasn't return CQ, and they
+will time out also.
+
+So, we should judge the result of internal abort in SCSI EH, if it is failed,
+we should give up to do TMF/softreset and return failure to the upper layer
+directly.
+
+This patch do following things to achieve this:
+
+1. When internal abort timeout happened, we set return value to -EIO in
+ hisi_sas_internal_task_abort().
+
+2. If prep_abort() is not support, let hisi_sas_internal_task_abort() return
+ TMF_RESP_FUNC_FAILED.
+
+3. If hisi_sas_internal_task_abort() return an negative number, it can be
+ thought that it not executed properly or internal abort timeout. Then we
+ won't do behind TMF or softreset, and return failure directly.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 38 ++++++++++++++++++++++++++++-------
+ 1 file changed, 31 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 7446a39f9442..1b9c48c99968 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -1184,6 +1184,11 @@ static int hisi_sas_abort_task(struct sas_task *task)
+
+ rc2 = hisi_sas_internal_task_abort(hisi_hba, device,
+ HISI_SAS_INT_ABT_CMD, tag);
++ if (rc2 < 0) {
++ dev_err(dev, "abort task: internal abort (%d)\n", rc2);
++ return TMF_RESP_FUNC_FAILED;
++ }
++
+ /*
+ * If the TMF finds that the IO is not in the device and also
+ * the internal abort does not succeed, then it is safe to
+@@ -1201,8 +1206,12 @@ static int hisi_sas_abort_task(struct sas_task *task)
+ } else if (task->task_proto & SAS_PROTOCOL_SATA ||
+ task->task_proto & SAS_PROTOCOL_STP) {
+ if (task->dev->dev_type == SAS_SATA_DEV) {
+- hisi_sas_internal_task_abort(hisi_hba, device,
+- HISI_SAS_INT_ABT_DEV, 0);
++ rc = hisi_sas_internal_task_abort(hisi_hba, device,
++ HISI_SAS_INT_ABT_DEV, 0);
++ if (rc < 0) {
++ dev_err(dev, "abort task: internal abort failed\n");
++ goto out;
++ }
+ hisi_sas_dereg_device(hisi_hba, device);
+ rc = hisi_sas_softreset_ata_disk(device);
+ }
+@@ -1213,7 +1222,8 @@ static int hisi_sas_abort_task(struct sas_task *task)
+
+ rc = hisi_sas_internal_task_abort(hisi_hba, device,
+ HISI_SAS_INT_ABT_CMD, tag);
+- if (rc == TMF_RESP_FUNC_FAILED && task->lldd_task) {
++ if (((rc < 0) || (rc == TMF_RESP_FUNC_FAILED)) &&
++ task->lldd_task) {
+ spin_lock_irqsave(&hisi_hba->lock, flags);
+ hisi_sas_do_release_task(hisi_hba, task, slot);
+ spin_unlock_irqrestore(&hisi_hba->lock, flags);
+@@ -1263,15 +1273,20 @@ static int hisi_sas_I_T_nexus_reset(struct domain_device *device)
+ {
+ struct hisi_sas_device *sas_dev = device->lldd_dev;
+ struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
+- unsigned long flags;
++ struct device *dev = hisi_hba->dev;
+ int rc = TMF_RESP_FUNC_FAILED;
++ unsigned long flags;
+
+ if (sas_dev->dev_status != HISI_SAS_DEV_EH)
+ return TMF_RESP_FUNC_FAILED;
+ sas_dev->dev_status = HISI_SAS_DEV_NORMAL;
+
+- hisi_sas_internal_task_abort(hisi_hba, device,
++ rc = hisi_sas_internal_task_abort(hisi_hba, device,
+ HISI_SAS_INT_ABT_DEV, 0);
++ if (rc < 0) {
++ dev_err(dev, "I_T nexus reset: internal abort (%d)\n", rc);
++ return TMF_RESP_FUNC_FAILED;
++ }
+ hisi_sas_dereg_device(hisi_hba, device);
+
+ rc = hisi_sas_debug_I_T_nexus_reset(device);
+@@ -1299,8 +1314,10 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun)
+ /* Clear internal IO and then hardreset */
+ rc = hisi_sas_internal_task_abort(hisi_hba, device,
+ HISI_SAS_INT_ABT_DEV, 0);
+- if (rc == TMF_RESP_FUNC_FAILED)
++ if (rc < 0) {
++ dev_err(dev, "lu_reset: internal abort failed\n");
+ goto out;
++ }
+ hisi_sas_dereg_device(hisi_hba, device);
+
+ phy = sas_get_local_phy(device);
+@@ -1497,8 +1514,14 @@ hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
+ struct device *dev = hisi_hba->dev;
+ int res;
+
++ /*
++ * The interface is not realized means this HW don't support internal
++ * abort, or don't need to do internal abort. Then here, we return
++ * TMF_RESP_FUNC_FAILED and let other steps go on, which depends that
++ * the internal abort has been executed and returned CQ.
++ */
+ if (!hisi_hba->hw->prep_abort)
+- return -EOPNOTSUPP;
++ return TMF_RESP_FUNC_FAILED;
+
+ task = sas_alloc_slow_task(GFP_KERNEL);
+ if (!task)
+@@ -1530,6 +1553,7 @@ hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
+ if (slot)
+ slot->task = NULL;
+ dev_err(dev, "internal task abort: timeout and not done.\n");
++ res = -EIO;
+ goto exit;
+ } else
+ dev_err(dev, "internal task abort: timeout.\n");
+
diff --git a/patches.drivers/scsi-hisi_sas-make-local-symbol-host_attrs-static.patch b/patches.drivers/scsi-hisi_sas-make-local-symbol-host_attrs-static.patch
new file mode 100644
index 0000000000..cb6ac05472
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-make-local-symbol-host_attrs-static.patch
@@ -0,0 +1,34 @@
+From: Wei Yongjun <weiyongjun1@huawei.com>
+Date: Thu, 11 Jan 2018 11:13:58 +0000
+Subject: scsi: hisi_sas: make local symbol host_attrs static
+Git-commit: 1e15feacb9d3743ca0b314a6daf8cc59c90b1046
+Patch-mainline: v4.16-rc1
+References: FATE#326253
+
+Fixes the following sparse warning:
+
+drivers/scsi/hisi_sas/hisi_sas_main.c:1691:25: warning:
+ symbol 'host_attrs' was not declared. Should it be static?
+
+Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
+Acked-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ 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 360ecefba10a..e3e7285f5eb1 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -1688,7 +1688,7 @@ EXPORT_SYMBOL_GPL(hisi_sas_kill_tasklets);
+ struct scsi_transport_template *hisi_sas_stt;
+ EXPORT_SYMBOL_GPL(hisi_sas_stt);
+
+-struct device_attribute *host_attrs[] = {
++static struct device_attribute *host_attrs[] = {
+ &dev_attr_phy_event_threshold,
+ NULL,
+ };
+
diff --git a/patches.drivers/scsi-hisi_sas-make-return-type-of-prep-functions-void.patch b/patches.drivers/scsi-hisi_sas-make-return-type-of-prep-functions-void.patch
new file mode 100644
index 0000000000..1c0c860b4d
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-make-return-type-of-prep-functions-void.patch
@@ -0,0 +1,532 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Wed, 9 May 2018 23:10:46 +0800
+Subject: scsi: hisi_sas: make return type of prep functions void
+Git-commit: a2b3820bddfbffcfbf0e8170e77de65d8b8def98
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+Since the task prep functions now should not fail, adjust the return
+types to void.
+
+In addition, some checks in the task prep functions are relocated to the
+main module; this is specifically the check for the number of elements
+in an sg list exceeded the HW SGE limit.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas.h | 8 ++---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 45 +++++++++++++--------------------
+ drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 28 ++++----------------
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 45 ++++++++-------------------------
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 43 ++++++++-----------------------
+ 5 files changed, 51 insertions(+), 118 deletions(-)
+
+--- a/drivers/scsi/hisi_sas/hisi_sas.h
++++ b/drivers/scsi/hisi_sas/hisi_sas.h
+@@ -215,14 +215,14 @@ struct hisi_sas_hw {
+ void (*sl_notify)(struct hisi_hba *hisi_hba, int phy_no);
+ int (*get_free_slot)(struct hisi_hba *hisi_hba, struct hisi_sas_dq *dq);
+ void (*start_delivery)(struct hisi_sas_dq *dq);
+- int (*prep_ssp)(struct hisi_hba *hisi_hba,
++ void (*prep_ssp)(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot, int is_tmf,
+ struct hisi_sas_tmf_task *tmf);
+- int (*prep_smp)(struct hisi_hba *hisi_hba,
++ void (*prep_smp)(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot);
+- int (*prep_stp)(struct hisi_hba *hisi_hba,
++ void (*prep_stp)(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot);
+- int (*prep_abort)(struct hisi_hba *hisi_hba,
++ void (*prep_abort)(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot,
+ int device_id, int abort_flag, int tag_to_abort);
+ int (*slot_complete)(struct hisi_hba *hisi_hba,
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -243,30 +243,30 @@ void hisi_sas_slot_task_free(struct hisi
+ }
+ EXPORT_SYMBOL_GPL(hisi_sas_slot_task_free);
+
+-static int hisi_sas_task_prep_smp(struct hisi_hba *hisi_hba,
++static void hisi_sas_task_prep_smp(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot)
+ {
+- return hisi_hba->hw->prep_smp(hisi_hba, slot);
++ hisi_hba->hw->prep_smp(hisi_hba, slot);
+ }
+
+-static int hisi_sas_task_prep_ssp(struct hisi_hba *hisi_hba,
++static void hisi_sas_task_prep_ssp(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot, int is_tmf,
+ struct hisi_sas_tmf_task *tmf)
+ {
+- return hisi_hba->hw->prep_ssp(hisi_hba, slot, is_tmf, tmf);
++ hisi_hba->hw->prep_ssp(hisi_hba, slot, is_tmf, tmf);
+ }
+
+-static int hisi_sas_task_prep_ata(struct hisi_hba *hisi_hba,
++static void hisi_sas_task_prep_ata(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot)
+ {
+- return hisi_hba->hw->prep_stp(hisi_hba, slot);
++ hisi_hba->hw->prep_stp(hisi_hba, slot);
+ }
+
+-static int hisi_sas_task_prep_abort(struct hisi_hba *hisi_hba,
++static void hisi_sas_task_prep_abort(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot,
+ int device_id, int abort_flag, int tag_to_abort)
+ {
+- return hisi_hba->hw->prep_abort(hisi_hba, slot,
++ hisi_hba->hw->prep_abort(hisi_hba, slot,
+ device_id, abort_flag, tag_to_abort);
+ }
+
+@@ -395,6 +395,13 @@ static int hisi_sas_task_prep(struct sas
+ } else
+ 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",
++ n_elem);
++ rc = -EINVAL;
++ goto err_out_dma_unmap;
++ }
++
+ spin_lock_irqsave(&hisi_hba->lock, flags);
+ if (hisi_hba->hw->slot_index_alloc)
+ rc = hisi_hba->hw->slot_index_alloc(hisi_hba, &slot_idx,
+@@ -439,28 +446,22 @@ static int hisi_sas_task_prep(struct sas
+
+ switch (task->task_proto) {
+ case SAS_PROTOCOL_SMP:
+- rc = hisi_sas_task_prep_smp(hisi_hba, slot);
++ hisi_sas_task_prep_smp(hisi_hba, slot);
+ break;
+ case SAS_PROTOCOL_SSP:
+- rc = hisi_sas_task_prep_ssp(hisi_hba, slot, is_tmf, tmf);
++ hisi_sas_task_prep_ssp(hisi_hba, slot, is_tmf, tmf);
+ break;
+ case SAS_PROTOCOL_SATA:
+ case SAS_PROTOCOL_STP:
+ case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
+- rc = hisi_sas_task_prep_ata(hisi_hba, slot);
++ hisi_sas_task_prep_ata(hisi_hba, slot);
+ break;
+ default:
+ dev_err(dev, "task prep: unknown/unsupported proto (0x%x)\n",
+ task->task_proto);
+- rc = -EINVAL;
+ break;
+ }
+
+- if (rc) {
+- dev_err(dev, "task prep: rc = 0x%x\n", rc);
+- goto err_out_buf;
+- }
+-
+ spin_lock_irqsave(&hisi_hba->lock, flags);
+ list_add_tail(&slot->entry, &sas_dev->list);
+ spin_unlock_irqrestore(&hisi_hba->lock, flags);
+@@ -473,9 +474,6 @@ static int hisi_sas_task_prep(struct sas
+
+ return 0;
+
+-err_out_buf:
+- dma_pool_free(hisi_hba->buffer_pool, slot->buf,
+- slot->buf_dma);
+ err_out_slot_buf:
+ /* Nothing to be done */
+ err_out_tag:
+@@ -1555,10 +1553,8 @@ hisi_sas_internal_abort_task_exec(struct
+ memset(hisi_sas_cmd_hdr_addr_mem(slot), 0, HISI_SAS_COMMAND_TABLE_SZ);
+ memset(hisi_sas_status_buf_addr_mem(slot), 0, HISI_SAS_STATUS_BUF_SZ);
+
+- rc = hisi_sas_task_prep_abort(hisi_hba, slot, device_id,
++ hisi_sas_task_prep_abort(hisi_hba, slot, device_id,
+ abort_flag, task_tag);
+- if (rc)
+- goto err_out_buf;
+
+ spin_lock_irqsave(&hisi_hba->lock, flags);
+ list_add_tail(&slot->entry, &sas_dev->list);
+@@ -1575,9 +1571,6 @@ hisi_sas_internal_abort_task_exec(struct
+
+ return 0;
+
+-err_out_buf:
+- dma_pool_free(hisi_hba->buffer_pool, slot->buf,
+- slot->buf_dma);
+ err_out_tag:
+ spin_lock_irqsave(&hisi_hba->lock, flags);
+ hisi_sas_slot_index_free(hisi_hba, slot_idx);
+--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+@@ -935,23 +935,16 @@ static void start_delivery_v1_hw(struct
+ dq->wr_point);
+ }
+
+-static int prep_prd_sge_v1_hw(struct hisi_hba *hisi_hba,
++static void prep_prd_sge_v1_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot,
+ struct hisi_sas_cmd_hdr *hdr,
+ struct scatterlist *scatter,
+ int n_elem)
+ {
+ struct hisi_sas_sge_page *sge_page = hisi_sas_sge_addr_mem(slot);
+- struct device *dev = hisi_hba->dev;
+ struct scatterlist *sg;
+ int i;
+
+- if (n_elem > HISI_SAS_SGE_PAGE_CNT) {
+- dev_err(dev, "prd err: n_elem(%d) > HISI_SAS_SGE_PAGE_CNT",
+- n_elem);
+- return -EINVAL;
+- }
+-
+ for_each_sg(scatter, sg, n_elem, i) {
+ struct hisi_sas_sge *entry = &sge_page->sge[i];
+
+@@ -964,11 +957,9 @@ static int prep_prd_sge_v1_hw(struct his
+ hdr->prd_table_addr = cpu_to_le64(hisi_sas_sge_addr_dma(slot));
+
+ hdr->sg_len = cpu_to_le32(n_elem << CMD_HDR_DATA_SGL_LEN_OFF);
+-
+- return 0;
+ }
+
+-static int prep_smp_v1_hw(struct hisi_hba *hisi_hba,
++static void prep_smp_v1_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot)
+ {
+ struct sas_task *task = slot->task;
+@@ -1004,11 +995,9 @@ static int prep_smp_v1_hw(struct hisi_hb
+
+ hdr->cmd_table_addr = cpu_to_le64(req_dma_addr);
+ hdr->sts_buffer_addr = cpu_to_le64(hisi_sas_status_buf_addr_dma(slot));
+-
+- return 0;
+ }
+
+-static int prep_ssp_v1_hw(struct hisi_hba *hisi_hba,
++static void prep_ssp_v1_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot, int is_tmf,
+ struct hisi_sas_tmf_task *tmf)
+ {
+@@ -1019,7 +1008,7 @@ static int prep_ssp_v1_hw(struct hisi_hb
+ struct hisi_sas_port *port = slot->port;
+ struct sas_ssp_task *ssp_task = &task->ssp_task;
+ struct scsi_cmnd *scsi_cmnd = ssp_task->cmd;
+- int has_data = 0, rc, priority = is_tmf;
++ int has_data = 0, priority = is_tmf;
+ u8 *buf_cmd, fburst = 0;
+ u32 dw1, dw2;
+
+@@ -1068,12 +1057,9 @@ static int prep_ssp_v1_hw(struct hisi_hb
+
+ hdr->transfer_tags = cpu_to_le32(slot->idx << CMD_HDR_IPTT_OFF);
+
+- if (has_data) {
+- rc = prep_prd_sge_v1_hw(hisi_hba, slot, hdr, task->scatter,
++ if (has_data)
++ prep_prd_sge_v1_hw(hisi_hba, slot, hdr, task->scatter,
+ slot->n_elem);
+- if (rc)
+- return rc;
+- }
+
+ hdr->data_transfer_len = cpu_to_le32(task->total_xfer_len);
+ hdr->cmd_table_addr = cpu_to_le64(hisi_sas_cmd_hdr_addr_dma(slot));
+@@ -1107,8 +1093,6 @@ static int prep_ssp_v1_hw(struct hisi_hb
+ break;
+ }
+ }
+-
+- return 0;
+ }
+
+ /* by default, task resp is complete */
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -1683,23 +1683,16 @@ static void start_delivery_v2_hw(struct
+ dq->wr_point);
+ }
+
+-static int prep_prd_sge_v2_hw(struct hisi_hba *hisi_hba,
++static void prep_prd_sge_v2_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot,
+ struct hisi_sas_cmd_hdr *hdr,
+ struct scatterlist *scatter,
+ int n_elem)
+ {
+ struct hisi_sas_sge_page *sge_page = hisi_sas_sge_addr_mem(slot);
+- struct device *dev = hisi_hba->dev;
+ struct scatterlist *sg;
+ int i;
+
+- if (n_elem > HISI_SAS_SGE_PAGE_CNT) {
+- dev_err(dev, "prd err: n_elem(%d) > HISI_SAS_SGE_PAGE_CNT",
+- n_elem);
+- return -EINVAL;
+- }
+-
+ for_each_sg(scatter, sg, n_elem, i) {
+ struct hisi_sas_sge *entry = &sge_page->sge[i];
+
+@@ -1712,11 +1705,9 @@ static int prep_prd_sge_v2_hw(struct his
+ hdr->prd_table_addr = cpu_to_le64(hisi_sas_sge_addr_dma(slot));
+
+ hdr->sg_len = cpu_to_le32(n_elem << CMD_HDR_DATA_SGL_LEN_OFF);
+-
+- return 0;
+ }
+
+-static int prep_smp_v2_hw(struct hisi_hba *hisi_hba,
++static void prep_smp_v2_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot)
+ {
+ struct sas_task *task = slot->task;
+@@ -1753,11 +1744,9 @@ static int prep_smp_v2_hw(struct hisi_hb
+
+ hdr->cmd_table_addr = cpu_to_le64(req_dma_addr);
+ hdr->sts_buffer_addr = cpu_to_le64(hisi_sas_status_buf_addr_dma(slot));
+-
+- return 0;
+ }
+
+-static int prep_ssp_v2_hw(struct hisi_hba *hisi_hba,
++static void prep_ssp_v2_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot, int is_tmf,
+ struct hisi_sas_tmf_task *tmf)
+ {
+@@ -1768,7 +1757,7 @@ static int prep_ssp_v2_hw(struct hisi_hb
+ struct hisi_sas_port *port = slot->port;
+ struct sas_ssp_task *ssp_task = &task->ssp_task;
+ struct scsi_cmnd *scsi_cmnd = ssp_task->cmd;
+- int has_data = 0, rc, priority = is_tmf;
++ int has_data = 0, priority = is_tmf;
+ u8 *buf_cmd;
+ u32 dw1 = 0, dw2 = 0;
+
+@@ -1810,12 +1799,9 @@ static int prep_ssp_v2_hw(struct hisi_hb
+
+ hdr->transfer_tags = cpu_to_le32(slot->idx);
+
+- if (has_data) {
+- rc = prep_prd_sge_v2_hw(hisi_hba, slot, hdr, task->scatter,
++ if (has_data)
++ prep_prd_sge_v2_hw(hisi_hba, slot, hdr, task->scatter,
+ slot->n_elem);
+- if (rc)
+- return rc;
+- }
+
+ hdr->data_transfer_len = cpu_to_le32(task->total_xfer_len);
+ hdr->cmd_table_addr = cpu_to_le64(hisi_sas_cmd_hdr_addr_dma(slot));
+@@ -1844,8 +1830,6 @@ static int prep_ssp_v2_hw(struct hisi_hb
+ break;
+ }
+ }
+-
+- return 0;
+ }
+
+ #define TRANS_TX_ERR 0
+@@ -2520,7 +2504,7 @@ out:
+ return sts;
+ }
+
+-static int prep_ata_v2_hw(struct hisi_hba *hisi_hba,
++static void prep_ata_v2_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot)
+ {
+ struct sas_task *task = slot->task;
+@@ -2531,7 +2515,7 @@ static int prep_ata_v2_hw(struct hisi_hb
+ struct asd_sas_port *sas_port = device->port;
+ struct hisi_sas_port *port = to_hisi_sas_port(sas_port);
+ u8 *buf_cmd;
+- int has_data = 0, rc = 0, hdr_tag = 0;
++ int has_data = 0, hdr_tag = 0;
+ u32 dw1 = 0, dw2 = 0;
+
+ /* create header */
+@@ -2579,12 +2563,9 @@ static int prep_ata_v2_hw(struct hisi_hb
+ /* dw3 */
+ hdr->transfer_tags = cpu_to_le32(slot->idx);
+
+- if (has_data) {
+- rc = prep_prd_sge_v2_hw(hisi_hba, slot, hdr, task->scatter,
++ if (has_data)
++ prep_prd_sge_v2_hw(hisi_hba, slot, hdr, task->scatter,
+ slot->n_elem);
+- if (rc)
+- return rc;
+- }
+
+ hdr->data_transfer_len = cpu_to_le32(task->total_xfer_len);
+ hdr->cmd_table_addr = cpu_to_le64(hisi_sas_cmd_hdr_addr_dma(slot));
+@@ -2596,8 +2577,6 @@ static int prep_ata_v2_hw(struct hisi_hb
+ task->ata_task.fis.flags |= 0x80; /* C=1: update ATA cmd reg */
+ /* fill in command FIS */
+ memcpy(buf_cmd, &task->ata_task.fis, sizeof(struct host_to_dev_fis));
+-
+- return 0;
+ }
+
+ static void hisi_sas_internal_abort_quirk_timeout(unsigned long data)
+@@ -2634,7 +2613,7 @@ static void hisi_sas_internal_abort_quir
+ }
+ }
+
+-static int prep_abort_v2_hw(struct hisi_hba *hisi_hba,
++static void prep_abort_v2_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot,
+ int device_id, int abort_flag, int tag_to_abort)
+ {
+@@ -2663,8 +2642,6 @@ static int prep_abort_v2_hw(struct hisi_
+ /* dw7 */
+ hdr->dw7 = cpu_to_le32(tag_to_abort << CMD_HDR_ABORT_IPTT_OFF);
+ hdr->transfer_tags = cpu_to_le32(slot->idx);
+-
+- return 0;
+ }
+
+ static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -859,23 +859,16 @@ static void start_delivery_v3_hw(struct
+ dq->wr_point);
+ }
+
+-static int prep_prd_sge_v3_hw(struct hisi_hba *hisi_hba,
++static void prep_prd_sge_v3_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot,
+ struct hisi_sas_cmd_hdr *hdr,
+ struct scatterlist *scatter,
+ int n_elem)
+ {
+ struct hisi_sas_sge_page *sge_page = hisi_sas_sge_addr_mem(slot);
+- struct device *dev = hisi_hba->dev;
+ struct scatterlist *sg;
+ int i;
+
+- if (n_elem > HISI_SAS_SGE_PAGE_CNT) {
+- dev_err(dev, "prd err: n_elem(%d) > HISI_SAS_SGE_PAGE_CNT",
+- n_elem);
+- return -EINVAL;
+- }
+-
+ for_each_sg(scatter, sg, n_elem, i) {
+ struct hisi_sas_sge *entry = &sge_page->sge[i];
+
+@@ -888,11 +881,9 @@ static int prep_prd_sge_v3_hw(struct his
+ hdr->prd_table_addr = cpu_to_le64(hisi_sas_sge_addr_dma(slot));
+
+ hdr->sg_len = cpu_to_le32(n_elem << CMD_HDR_DATA_SGL_LEN_OFF);
+-
+- return 0;
+ }
+
+-static int prep_ssp_v3_hw(struct hisi_hba *hisi_hba,
++static void prep_ssp_v3_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot, int is_tmf,
+ struct hisi_sas_tmf_task *tmf)
+ {
+@@ -903,7 +894,7 @@ static int prep_ssp_v3_hw(struct hisi_hb
+ struct hisi_sas_port *port = slot->port;
+ struct sas_ssp_task *ssp_task = &task->ssp_task;
+ struct scsi_cmnd *scsi_cmnd = ssp_task->cmd;
+- int has_data = 0, rc, priority = is_tmf;
++ int has_data = 0, priority = is_tmf;
+ u8 *buf_cmd;
+ u32 dw1 = 0, dw2 = 0;
+
+@@ -944,12 +935,9 @@ static int prep_ssp_v3_hw(struct hisi_hb
+ hdr->dw2 = cpu_to_le32(dw2);
+ hdr->transfer_tags = cpu_to_le32(slot->idx);
+
+- if (has_data) {
+- rc = prep_prd_sge_v3_hw(hisi_hba, slot, hdr, task->scatter,
++ if (has_data)
++ prep_prd_sge_v3_hw(hisi_hba, slot, hdr, task->scatter,
+ slot->n_elem);
+- if (rc)
+- return rc;
+- }
+
+ hdr->data_transfer_len = cpu_to_le32(task->total_xfer_len);
+ hdr->cmd_table_addr = cpu_to_le64(hisi_sas_cmd_hdr_addr_dma(slot));
+@@ -976,11 +964,9 @@ static int prep_ssp_v3_hw(struct hisi_hb
+ break;
+ }
+ }
+-
+- return 0;
+ }
+
+-static int prep_smp_v3_hw(struct hisi_hba *hisi_hba,
++static void prep_smp_v3_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot)
+ {
+ struct sas_task *task = slot->task;
+@@ -1018,10 +1004,9 @@ static int prep_smp_v3_hw(struct hisi_hb
+ hdr->cmd_table_addr = cpu_to_le64(req_dma_addr);
+ hdr->sts_buffer_addr = cpu_to_le64(hisi_sas_status_buf_addr_dma(slot));
+
+- return 0;
+ }
+
+-static int prep_ata_v3_hw(struct hisi_hba *hisi_hba,
++static void prep_ata_v3_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot)
+ {
+ struct sas_task *task = slot->task;
+@@ -1032,7 +1017,7 @@ static int prep_ata_v3_hw(struct hisi_hb
+ struct asd_sas_port *sas_port = device->port;
+ struct hisi_sas_port *port = to_hisi_sas_port(sas_port);
+ u8 *buf_cmd;
+- int has_data = 0, rc = 0, hdr_tag = 0;
++ int has_data = 0, hdr_tag = 0;
+ u32 dw1 = 0, dw2 = 0;
+
+ hdr->dw0 = cpu_to_le32(port->id << CMD_HDR_PORT_OFF);
+@@ -1081,12 +1066,9 @@ static int prep_ata_v3_hw(struct hisi_hb
+ /* dw3 */
+ hdr->transfer_tags = cpu_to_le32(slot->idx);
+
+- if (has_data) {
+- rc = prep_prd_sge_v3_hw(hisi_hba, slot, hdr, task->scatter,
++ if (has_data)
++ prep_prd_sge_v3_hw(hisi_hba, slot, hdr, task->scatter,
+ slot->n_elem);
+- if (rc)
+- return rc;
+- }
+
+ hdr->data_transfer_len = cpu_to_le32(task->total_xfer_len);
+ hdr->cmd_table_addr = cpu_to_le64(hisi_sas_cmd_hdr_addr_dma(slot));
+@@ -1098,11 +1080,9 @@ static int prep_ata_v3_hw(struct hisi_hb
+ task->ata_task.fis.flags |= 0x80; /* C=1: update ATA cmd reg */
+ /* fill in command FIS */
+ memcpy(buf_cmd, &task->ata_task.fis, sizeof(struct host_to_dev_fis));
+-
+- return 0;
+ }
+
+-static int prep_abort_v3_hw(struct hisi_hba *hisi_hba,
++static void prep_abort_v3_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot,
+ int device_id, int abort_flag, int tag_to_abort)
+ {
+@@ -1127,7 +1107,6 @@ static int prep_abort_v3_hw(struct hisi_
+ hdr->dw7 = cpu_to_le32(tag_to_abort << CMD_HDR_ABORT_IPTT_OFF);
+ hdr->transfer_tags = cpu_to_le32(slot->idx);
+
+- return 0;
+ }
+
+ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
diff --git a/patches.drivers/scsi-hisi_sas-make-sas-address-of-sata-disks-unique.patch b/patches.drivers/scsi-hisi_sas-make-sas-address-of-sata-disks-unique.patch
new file mode 100644
index 0000000000..ca57d65c9e
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-make-sas-address-of-sata-disks-unique.patch
@@ -0,0 +1,31 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Sat, 24 Mar 2018 00:05:08 +0800
+Subject: scsi: hisi_sas: make SAS address of SATA disks unique
+Git-commit: 8b8d66531555006a18d1532546dadbea8d16df95
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+When directly connected with SATA disks in different SAS cores, fill SAS
+address with scsi_host's id to make it's fake SAS address unique.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+index f89fb9a49ea9..89b9505c0654 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -3295,6 +3295,7 @@ static irqreturn_t sata_int_v2_hw(int irq_no, void *p)
+ sas_phy->oob_mode = SATA_OOB_MODE;
+ /* Make up some unique SAS address */
+ attached_sas_addr[0] = 0x50;
++ attached_sas_addr[6] = hisi_hba->shost->host_no;
+ attached_sas_addr[7] = phy_no;
+ memcpy(sas_phy->attached_sas_addr, attached_sas_addr, SAS_ADDR_SIZE);
+ memcpy(sas_phy->frame_rcvd, fis, sizeof(struct dev_to_host_fis));
+
diff --git a/patches.drivers/scsi-hisi_sas-mark-phy-as-in-reset-for-nexus-reset.patch b/patches.drivers/scsi-hisi_sas-mark-phy-as-in-reset-for-nexus-reset.patch
new file mode 100644
index 0000000000..ac7847a3b5
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-mark-phy-as-in-reset-for-nexus-reset.patch
@@ -0,0 +1,202 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Mon, 21 May 2018 18:09:25 +0800
+Subject: scsi: hisi_sas: Mark PHY as in reset for nexus reset
+Git-commit: 3e1fb1b8abf0c862a7f5d39cb3354a1fd5e9f96a
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+When issuing a nexus reset for directly attached device, we want to ignore
+the PHY down events so libsas will not deform and reform the port.
+
+In the case that the attached SAS changes for the reset, libsas will deform
+and form a port.
+
+For scenario that the PHY does not come up after a timeout period, then
+report the PHY down to libsas.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas.h | 5 +++-
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 40 +++++++++++++++++++++++++++++----
+ drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 8 ++++++
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 14 +++++++++++
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 7 +++++
+ 5 files changed, 69 insertions(+), 5 deletions(-)
+
+--- a/drivers/scsi/hisi_sas/hisi_sas.h
++++ b/drivers/scsi/hisi_sas/hisi_sas.h
+@@ -137,11 +137,14 @@ struct hisi_sas_phy {
+ struct asd_sas_phy sas_phy;
+ struct sas_identify identify;
+ struct timer_list timer;
++ struct completion *reset_completion;
++ spinlock_t lock;
+ u64 port_id; /* from hw */
+ u64 frame_rcvd_size;
+ u8 frame_rcvd[32];
+ u8 phy_attached;
+- u8 reserved[3];
++ u8 in_reset;
++ u8 reserved[2];
+ u32 phy_type;
+ enum sas_linkrate minimum_linkrate;
+ enum sas_linkrate maximum_linkrate;
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -1530,12 +1530,39 @@ static int hisi_sas_clear_aca(struct dom
+
+ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device)
+ {
+- struct sas_phy *phy = sas_get_local_phy(device);
++ struct sas_phy *local_phy = sas_get_local_phy(device);
+ int rc, reset_type = (device->dev_type == SAS_SATA_DEV ||
+ (device->tproto & SAS_PROTOCOL_STP)) ? 0 : 1;
+- rc = sas_phy_reset(phy, reset_type);
+- sas_put_local_phy(phy);
+- msleep(2000);
++ struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
++ struct sas_ha_struct *sas_ha = &hisi_hba->sha;
++ struct asd_sas_phy *sas_phy = sas_ha->sas_phy[local_phy->number];
++ struct hisi_sas_phy *phy = container_of(sas_phy,
++ struct hisi_sas_phy, sas_phy);
++ DECLARE_COMPLETION_ONSTACK(phyreset);
++
++ if (scsi_is_sas_phy_local(local_phy)) {
++ phy->in_reset = 1;
++ phy->reset_completion = &phyreset;
++ }
++
++ rc = sas_phy_reset(local_phy, reset_type);
++ sas_put_local_phy(local_phy);
++
++ if (scsi_is_sas_phy_local(local_phy)) {
++ int ret = wait_for_completion_timeout(&phyreset, 2 * HZ);
++ 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)
++ hisi_sas_phy_down(hisi_hba, sas_phy->id, 0);
++ } else
++ msleep(2000);
++
+ return rc;
+ }
+
+@@ -1885,6 +1912,7 @@ void hisi_sas_phy_down(struct 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;
++ struct device *dev = hisi_hba->dev;
+
+ if (rdy) {
+ /* Phy down but ready */
+@@ -1893,6 +1921,10 @@ void hisi_sas_phy_down(struct hisi_hba *
+ } else {
+ struct hisi_sas_port *port = phy->port;
+
++ if (phy->in_reset) {
++ dev_info(dev, "ignore flutter phy%d down\n", phy_no);
++ return;
++ }
+ /* Phy down and not ready */
+ sas_ha->notify_phy_event(sas_phy, PHYE_LOSS_OF_SIGNAL);
+ sas_phy_disconnected(sas_phy);
+--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+@@ -1373,6 +1373,7 @@ static irqreturn_t int_phyup_v1_hw(int i
+ 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)) {
+@@ -1426,6 +1427,13 @@ static irqreturn_t int_phyup_v1_hw(int i
+ 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:
+ hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2,
+ CHL_INT2_SL_PHY_ENA_MSK);
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -2663,6 +2663,7 @@ static int phy_up_v2_hw(int phy_no, stru
+ 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);
+
+@@ -2715,6 +2716,12 @@ static int phy_up_v2_hw(int phy_no, stru
+ 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:
+ hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
+@@ -3203,6 +3210,7 @@ static irqreturn_t sata_int_v2_hw(int ir
+ 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;
+
+ phy_no = sas_phy->id;
+@@ -3277,6 +3285,12 @@ static irqreturn_t sata_int_v2_hw(int ir
+ 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;
++ 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);
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -1143,6 +1143,7 @@ static irqreturn_t phy_up_v3_hw(int phy_
+ 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;
+
+ hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 1);
+
+@@ -1211,6 +1212,12 @@ static irqreturn_t phy_up_v3_hw(int phy_
+ 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:
+ hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
+ CHL_INT0_SL_PHY_ENABLE_MSK);
diff --git a/patches.drivers/scsi-hisi_sas-modify-hisi_sas_dev_gone-for-reset.patch b/patches.drivers/scsi-hisi_sas-modify-hisi_sas_dev_gone-for-reset.patch
new file mode 100644
index 0000000000..e0ab457915
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-modify-hisi_sas_dev_gone-for-reset.patch
@@ -0,0 +1,54 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Sat, 9 Dec 2017 01:16:37 +0800
+Subject: scsi: hisi_sas: modify hisi_sas_dev_gone() for reset
+Git-commit: f8e45ec226e2c00c1da9cf156ea59a159e9b4ea6
+Patch-mainline: v4.16-rc1
+References: FATE#326253
+
+Do a couple of changes for when HISI_SAS_RESET_BIT is set for HBA:
+
+ - Clearing ITCT is not necessary
+
+ - Remove internal abort as it will fail during reset
+
+Flag sas_dev->dev_type is kept as SAS_PHY_UNUSED.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 64d51a839187..e4b30922a75d 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -738,17 +738,19 @@ static void hisi_sas_dev_gone(struct domain_device *device)
+ dev_info(dev, "found dev[%d:%x] is gone\n",
+ sas_dev->device_id, sas_dev->dev_type);
+
+- hisi_sas_internal_task_abort(hisi_hba, device,
++ if (!test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) {
++ hisi_sas_internal_task_abort(hisi_hba, device,
+ HISI_SAS_INT_ABT_DEV, 0);
+
+- hisi_sas_dereg_device(hisi_hba, device);
++ hisi_sas_dereg_device(hisi_hba, device);
++
++ hisi_hba->hw->clear_itct(hisi_hba, sas_dev);
++ device->lldd_dev = NULL;
++ memset(sas_dev, 0, sizeof(*sas_dev));
++ }
+
+- hisi_hba->hw->clear_itct(hisi_hba, sas_dev);
+ if (hisi_hba->hw->free_device)
+ hisi_hba->hw->free_device(sas_dev);
+-
+- device->lldd_dev = NULL;
+- memset(sas_dev, 0, sizeof(*sas_dev));
+ sas_dev->dev_type = SAS_PHY_UNUSED;
+ }
+
+
diff --git a/patches.drivers/scsi-hisi_sas-modify-some-register-config-for-hip08.patch b/patches.drivers/scsi-hisi_sas-modify-some-register-config-for-hip08.patch
new file mode 100644
index 0000000000..cf29b4ecd9
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-modify-some-register-config-for-hip08.patch
@@ -0,0 +1,81 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Wed, 7 Mar 2018 20:25:13 +0800
+Subject: scsi: hisi_sas: modify some register config for hip08
+Git-commit: 15c38e31c47c0f2cd7e959054258714991a6a2d6
+Patch-mainline: v4.17-rc1
+References: FATE#326253
+
+Do some modifications for register configuring for hip08.
+
+In future, to reduce kernel churn with patches to modify registers, any
+registers which may change between board models (mostly PHY/SERDES related)
+should be set in ACPI reset handler.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 23 +++++++++++------------
+ 1 file changed, 11 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+index 4023fcbc3f04..5ce5ef2caabe 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -172,6 +172,7 @@
+ #define CHL_INT1_MSK (PORT_BASE + 0x1c4)
+ #define CHL_INT2_MSK (PORT_BASE + 0x1c8)
+ #define CHL_INT_COAL_EN (PORT_BASE + 0x1d0)
++#define SAS_RX_TRAIN_TIMER (PORT_BASE + 0x2a4)
+ #define PHY_CTRL_RDY_MSK (PORT_BASE + 0x2b0)
+ #define PHYCTRL_NOT_RDY_MSK (PORT_BASE + 0x2b4)
+ #define PHYCTRL_DWS_RESET_MSK (PORT_BASE + 0x2b8)
+@@ -184,6 +185,8 @@
+ #define DMA_RX_STATUS (PORT_BASE + 0x2e8)
+ #define DMA_RX_STATUS_BUSY_OFF 0
+ #define DMA_RX_STATUS_BUSY_MSK (0x1 << DMA_RX_STATUS_BUSY_OFF)
++
++#define COARSETUNE_TIME (PORT_BASE + 0x304)
+ #define ERR_CNT_DWS_LOST (PORT_BASE + 0x380)
+ #define ERR_CNT_RESET_PROB (PORT_BASE + 0x384)
+ #define ERR_CNT_INVLD_DW (PORT_BASE + 0x390)
+@@ -417,10 +420,10 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
+ hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK+0x4*i, 0);
+
+ hisi_sas_write32(hisi_hba, HYPER_STREAM_ID_EN_CFG, 1);
+- hisi_sas_write32(hisi_hba, AXI_MASTER_CFG_BASE, 0x30000);
+
+ for (i = 0; i < hisi_hba->n_phy; i++) {
+- hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE, 0x801);
++ hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE, 0x855);
++ hisi_sas_phy_write32(hisi_hba, i, SAS_RX_TRAIN_TIMER, 0x13e80);
+ 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);
+@@ -432,17 +435,13 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
+ 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);
+- hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_OOB_RESTART_MSK, 0x0);
+- hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL, 0x199b4fa);
+- hisi_sas_phy_write32(hisi_hba, i, SAS_SSP_CON_TIMER_CFG,
+- 0xa03e8);
+- hisi_sas_phy_write32(hisi_hba, i, SAS_STP_CON_TIMER_CFG,
+- 0xa03e8);
+- hisi_sas_phy_write32(hisi_hba, i, STP_LINK_TIMER,
+- 0x7f7a120);
+- hisi_sas_phy_write32(hisi_hba, i, CON_CFG_DRIVER,
+- 0x2a0a80);
++ hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_OOB_RESTART_MSK, 0x1);
++ hisi_sas_phy_write32(hisi_hba, i, STP_LINK_TIMER, 0x7f7a120);
++
++ /* used for 12G negotiate */
++ hisi_sas_phy_write32(hisi_hba, i, COARSETUNE_TIME, 0x1e);
+ }
++
+ for (i = 0; i < hisi_hba->queue_count; i++) {
+ /* Delivery queue */
+ hisi_sas_write32(hisi_hba,
+
diff --git a/patches.drivers/scsi-hisi_sas-optimise-port-id-refresh-function.patch b/patches.drivers/scsi-hisi_sas-optimise-port-id-refresh-function.patch
new file mode 100644
index 0000000000..d9bf86b49b
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-optimise-port-id-refresh-function.patch
@@ -0,0 +1,115 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Sat, 9 Dec 2017 01:16:35 +0800
+Subject: scsi: hisi_sas: optimise port id refresh function
+Git-commit: a669bdbf4939ac72eff6b3ae33f771a1ef28448c
+Patch-mainline: v4.16-rc1
+References: FATE#326253
+
+Currently refreshing the PHY port id after reset is done in the rescan
+topology function, which is quite late in the reset process. It could be moved
+earlier in the process, as the port id can be refreshed once the PHYs become
+ready.
+
+In addition to this, we should set the hisi_sas_dev port id to 0xff (invalid
+port id) if all PHYs of this port remain down for the same device.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 48 ++++++++++++++++++++++-------------
+ 1 file changed, 30 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 6446ce23465a..326ecb24bb20 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -990,27 +990,42 @@ static int hisi_sas_debug_issue_ssp_tmf(struct domain_device *device,
+ sizeof(ssp_task), tmf);
+ }
+
+-static void hisi_sas_refresh_port_id(struct hisi_hba *hisi_hba,
+- struct asd_sas_port *sas_port, enum sas_linkrate linkrate)
++static void hisi_sas_refresh_port_id(struct hisi_hba *hisi_hba)
+ {
+- struct hisi_sas_device *sas_dev;
+- struct domain_device *device;
++ u32 state = hisi_hba->hw->get_phys_state(hisi_hba);
+ int i;
+
+ for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
+- sas_dev = &hisi_hba->devices[i];
+- device = sas_dev->sas_device;
++ struct hisi_sas_device *sas_dev = &hisi_hba->devices[i];
++ struct domain_device *device = sas_dev->sas_device;
++ struct asd_sas_port *sas_port;
++ struct hisi_sas_port *port;
++ struct hisi_sas_phy *phy = NULL;
++ struct asd_sas_phy *sas_phy;
++
+ if ((sas_dev->dev_type == SAS_PHY_UNUSED)
+- || !device || (device->port != sas_port))
++ || !device || !device->port)
+ continue;
+
+- hisi_hba->hw->clear_itct(hisi_hba, sas_dev);
++ sas_port = device->port;
++ port = to_hisi_sas_port(sas_port);
++
++ 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;
++ }
++
++ if (phy) {
++ port->id = phy->port_id;
+
+- /* Update linkrate of directly attached device. */
+- if (!device->parent)
+- device->linkrate = linkrate;
++ /* Update linkrate of directly attached device. */
++ if (!device->parent)
++ device->linkrate = phy->sas_phy.linkrate;
+
+- hisi_hba->hw->setup_itct(hisi_hba, sas_dev);
++ hisi_hba->hw->setup_itct(hisi_hba, sas_dev);
++ } else
++ port->id = 0xff;
+ }
+ }
+
+@@ -1025,21 +1040,17 @@ static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 old_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;
+- struct hisi_sas_port *port = to_hisi_sas_port(sas_port);
+ bool do_port_check = !!(_sas_port != sas_port);
+
+ if (!sas_phy->phy->enabled)
+ continue;
+
+ /* Report PHY state change to libsas */
+- if (state & (1 << phy_no)) {
+- if (do_port_check && sas_port) {
++ if (state & BIT(phy_no)) {
++ if (do_port_check && sas_port && sas_port->port_dev) {
+ struct domain_device *dev = sas_port->port_dev;
+
+ _sas_port = sas_port;
+- port->id = phy->port_id;
+- hisi_sas_refresh_port_id(hisi_hba,
+- sas_port, sas_phy->linkrate);
+
+ if (DEV_IS_EXPANDER(dev->dev_type))
+ sas_ha->notify_port_event(sas_phy,
+@@ -1088,6 +1099,7 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
+ /* Init and wait for PHYs to come up and all libsas event finished. */
+ hisi_hba->hw->phys_init(hisi_hba);
+ msleep(1000);
++ hisi_sas_refresh_port_id(hisi_hba);
+ drain_workqueue(hisi_hba->wq);
+ drain_workqueue(shost->work_q);
+
+
diff --git a/patches.drivers/scsi-hisi_sas-optimise-the-usage-of-dq-locking.patch b/patches.drivers/scsi-hisi_sas-optimise-the-usage-of-dq-locking.patch
new file mode 100644
index 0000000000..b73a8c21c6
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-optimise-the-usage-of-dq-locking.patch
@@ -0,0 +1,78 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Wed, 2 May 2018 23:56:24 +0800
+Subject: scsi: hisi_sas: optimise the usage of DQ locking
+Git-commit: 24cf43612d4d851e660ac85f36cf389650c5a3ba
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+In the DQ tasklet processing it is not necessary to take the DQ lock, as
+there is no contention between adding slots to the CQ and removing slots
+from the matching DQ.
+
+In addition, since we run each DQ in a separate tasklet context, there
+would be no possible contention between DQ processing running for the
+same queue in parallel.
+
+It is still necessary to take hisi_hba lock when free'ing slots.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 3 ---
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 3 ---
+ 2 files changed, 6 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+index a5abde855cb2..384e4ef50b24 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -3151,14 +3151,12 @@ static void cq_tasklet_v2_hw(unsigned long val)
+ struct hisi_sas_complete_v2_hdr *complete_queue;
+ u32 rd_point = cq->rd_point, wr_point, dev_id;
+ int queue = cq->id;
+- struct hisi_sas_dq *dq = &hisi_hba->dq[queue];
+
+ if (unlikely(hisi_hba->reject_stp_links_msk))
+ phys_try_accept_stp_links_v2_hw(hisi_hba);
+
+ complete_queue = hisi_hba->complete_hdr[queue];
+
+- spin_lock(&dq->lock);
+ wr_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_WR_PTR +
+ (0x14 * queue));
+
+@@ -3208,7 +3206,6 @@ 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);
+- spin_unlock(&dq->lock);
+ }
+
+ static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p)
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+index 33735a7082b6..afc1242abdcf 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -1721,11 +1721,9 @@ static void cq_tasklet_v3_hw(unsigned long val)
+ struct hisi_sas_complete_v3_hdr *complete_queue;
+ u32 rd_point = cq->rd_point, wr_point;
+ int queue = cq->id;
+- struct hisi_sas_dq *dq = &hisi_hba->dq[queue];
+
+ complete_queue = hisi_hba->complete_hdr[queue];
+
+- spin_lock(&dq->lock);
+ wr_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_WR_PTR +
+ (0x14 * queue));
+
+@@ -1752,7 +1750,6 @@ static void cq_tasklet_v3_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);
+- spin_unlock(&dq->lock);
+ }
+
+ static irqreturn_t cq_interrupt_v3_hw(int irq_no, void *p)
+
diff --git a/patches.drivers/scsi-hisi_sas-print-device-id-for-errors.patch b/patches.drivers/scsi-hisi_sas-print-device-id-for-errors.patch
new file mode 100644
index 0000000000..495b1e371d
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-print-device-id-for-errors.patch
@@ -0,0 +1,54 @@
+From: John Garry <john.garry@huawei.com>
+Date: Sat, 24 Mar 2018 00:05:14 +0800
+Subject: scsi: hisi_sas: print device id for errors
+Git-commit: 381ed6c081ae423b03d82ce1a0bb79bbec2b033e
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+When we find an erroneous slot completion, to help aid debugging add the
+device index to the current debug log.
+
+Signed-off-by: John Garry <john.garry@huawei.com>
+Reviewed-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 4 ++--
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+index bed6afb324a1..a5abde855cb2 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -2459,10 +2459,10 @@ 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=%p "
++ dev_info(dev, "erroneous completion iptt=%d task=%p 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,
++ slot->idx, task, sas_dev->device_id,
+ complete_hdr->dw0, complete_hdr->dw1,
+ complete_hdr->act, complete_hdr->dw3,
+ error_info[0], error_info[1],
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+index aa52d5e424f7..760724ae4d6f 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -1641,10 +1641,10 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
+
+ slot_err_v3_hw(hisi_hba, task, slot);
+ if (ts->stat != SAS_DATA_UNDERRUN)
+- dev_info(dev, "erroneous completion iptt=%d task=%p "
++ dev_info(dev, "erroneous completion iptt=%d task=%p 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,
++ slot->idx, task, sas_dev->device_id,
+ complete_hdr->dw0, complete_hdr->dw1,
+ complete_hdr->act, complete_hdr->dw3,
+ error_info[0], error_info[1],
+
diff --git a/patches.drivers/scsi-hisi_sas-re-add-the-lldd_port_deformed.patch b/patches.drivers/scsi-hisi_sas-re-add-the-lldd_port_deformed.patch
new file mode 100644
index 0000000000..278b616826
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-re-add-the-lldd_port_deformed.patch
@@ -0,0 +1,47 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Sat, 9 Dec 2017 01:16:49 +0800
+Subject: scsi: hisi_sas: re-add the lldd_port_deformed()
+Git-commit: 336bd78bdabf39dbcee6b41f9628c6e51d1c25b0
+Patch-mainline: v4.16-rc1
+References: FATE#326253
+
+In function sas_suspend_devices(), it requires callback lldd_port_deformed
+callback to be implemented if lldd_port_deformed is implemented.
+
+So add a stub for lldd_port_deformed.
+
+Callback lldd_port_deformed was not required as the port deformation is done
+elsewhere in the LLDD.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 9bd98e5be78e..ad122378b84a 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -1613,6 +1613,10 @@ static void hisi_sas_port_formed(struct asd_sas_phy *sas_phy)
+ hisi_sas_port_notify_formed(sas_phy);
+ }
+
++static void hisi_sas_port_deformed(struct asd_sas_phy *sas_phy)
++{
++}
++
+ static void hisi_sas_phy_disconnected(struct hisi_sas_phy *phy)
+ {
+ phy->phy_attached = 0;
+@@ -1703,6 +1707,7 @@ static struct sas_domain_function_template hisi_sas_transport_ops = {
+ .lldd_query_task = hisi_sas_query_task,
+ .lldd_clear_nexus_ha = hisi_sas_clear_nexus_ha,
+ .lldd_port_formed = hisi_sas_port_formed,
++ .lldd_port_deformed = hisi_sas_port_deformed,
+ };
+
+ void hisi_sas_init_mem(struct hisi_hba *hisi_hba)
+
diff --git a/patches.drivers/scsi-hisi_sas-relocate-clearing-itct-and-freeing-device.patch b/patches.drivers/scsi-hisi_sas-relocate-clearing-itct-and-freeing-device.patch
new file mode 100644
index 0000000000..55af7f9f1a
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-relocate-clearing-itct-and-freeing-device.patch
@@ -0,0 +1,161 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Sat, 9 Dec 2017 01:16:34 +0800
+Subject: scsi: hisi_sas: relocate clearing ITCT and freeing device
+Git-commit: 0258141aaab3007949ba0e67c3d28436354429bb
+Patch-mainline: v4.16-rc1
+References: FATE#326253
+
+In certain scenarios we may just want to clear the ITCT for a device, and not
+free other resources like the SATA bitmap using in v2 hw.
+
+To facilitate this, this patch relocates the code of clearing ITCT from
+free_device() to a new hw interface clear_itct(). Then for some hw, we should
+not realise free_device() if there's nothing left to do for it.
+
+[mkp: typo]
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas.h | 3 ++-
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 7 +++++--
+ drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 4 ++--
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 16 +++++++++++-----
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 4 ++--
+ 5 files changed, 22 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
+index 83357b0367d8..b2534caed45a 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas.h
++++ b/drivers/scsi/hisi_sas/hisi_sas.h
+@@ -205,8 +205,9 @@ struct hisi_sas_hw {
+ void (*phy_set_linkrate)(struct hisi_hba *hisi_hba, int phy_no,
+ struct sas_phy_linkrates *linkrates);
+ enum sas_linkrate (*phy_get_max_linkrate)(void);
+- void (*free_device)(struct hisi_hba *hisi_hba,
++ void (*clear_itct)(struct hisi_hba *hisi_hba,
+ struct hisi_sas_device *dev);
++ void (*free_device)(struct hisi_sas_device *sas_dev);
+ int (*get_wideport_bitmap)(struct hisi_hba *hisi_hba, int port_id);
+ void (*dereg_device)(struct hisi_hba *hisi_hba,
+ struct domain_device *device);
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index d8425303eadd..6446ce23465a 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -743,7 +743,10 @@ static void hisi_sas_dev_gone(struct domain_device *device)
+
+ hisi_sas_dereg_device(hisi_hba, device);
+
+- hisi_hba->hw->free_device(hisi_hba, sas_dev);
++ hisi_hba->hw->clear_itct(hisi_hba, sas_dev);
++ if (hisi_hba->hw->free_device)
++ hisi_hba->hw->free_device(sas_dev);
++
+ device->lldd_dev = NULL;
+ memset(sas_dev, 0, sizeof(*sas_dev));
+ sas_dev->dev_type = SAS_PHY_UNUSED;
+@@ -1001,7 +1004,7 @@ static void hisi_sas_refresh_port_id(struct hisi_hba *hisi_hba,
+ || !device || (device->port != sas_port))
+ continue;
+
+- hisi_hba->hw->free_device(hisi_hba, sas_dev);
++ hisi_hba->hw->clear_itct(hisi_hba, sas_dev);
+
+ /* Update linkrate of directly attached device. */
+ if (!device->parent)
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+index dc6eca8d6afd..8cb9061e616f 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+@@ -544,7 +544,7 @@ static void setup_itct_v1_hw(struct hisi_hba *hisi_hba,
+ (0xff00ULL << ITCT_HDR_REJ_OPEN_TL_OFF));
+ }
+
+-static void free_device_v1_hw(struct hisi_hba *hisi_hba,
++static void clear_itct_v1_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_device *sas_dev)
+ {
+ u64 dev_id = sas_dev->device_id;
+@@ -1850,7 +1850,7 @@ static const struct hisi_sas_hw hisi_sas_v1_hw = {
+ .hw_init = hisi_sas_v1_init,
+ .setup_itct = setup_itct_v1_hw,
+ .sl_notify = sl_notify_v1_hw,
+- .free_device = free_device_v1_hw,
++ .clear_itct = clear_itct_v1_hw,
+ .prep_smp = prep_smp_v1_hw,
+ .prep_ssp = prep_ssp_v1_hw,
+ .get_free_slot = get_free_slot_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 5d3467fd728d..cd9cd8468829 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -952,7 +952,7 @@ static void setup_itct_v2_hw(struct hisi_hba *hisi_hba,
+ (0x1ULL << ITCT_HDR_RTOLT_OFF));
+ }
+
+-static void free_device_v2_hw(struct hisi_hba *hisi_hba,
++static void clear_itct_v2_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_device *sas_dev)
+ {
+ DECLARE_COMPLETION_ONSTACK(completion);
+@@ -963,10 +963,6 @@ static void free_device_v2_hw(struct hisi_hba *hisi_hba,
+
+ sas_dev->completion = &completion;
+
+- /* SoC bug workaround */
+- if (dev_is_sata(sas_dev->sas_device))
+- clear_bit(sas_dev->sata_idx, hisi_hba->sata_dev_bitmap);
+-
+ /* clear the itct interrupt state */
+ if (ENT_INT_SRC3_ITC_INT_MSK & reg_val)
+ hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
+@@ -981,6 +977,15 @@ static void free_device_v2_hw(struct hisi_hba *hisi_hba,
+ }
+ }
+
++static void free_device_v2_hw(struct hisi_sas_device *sas_dev)
++{
++ struct hisi_hba *hisi_hba = sas_dev->hisi_hba;
++
++ /* SoC bug workaround */
++ if (dev_is_sata(sas_dev->sas_device))
++ clear_bit(sas_dev->sata_idx, hisi_hba->sata_dev_bitmap);
++}
++
+ static int reset_hw_v2_hw(struct hisi_hba *hisi_hba)
+ {
+ int i, reset_val;
+@@ -3415,6 +3420,7 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = {
+ .alloc_dev = alloc_dev_quirk_v2_hw,
+ .sl_notify = sl_notify_v2_hw,
+ .get_wideport_bitmap = get_wideport_bitmap_v2_hw,
++ .clear_itct = clear_itct_v2_hw,
+ .free_device = free_device_v2_hw,
+ .prep_smp = prep_smp_v2_hw,
+ .prep_ssp = prep_ssp_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 19b1f2ffec17..44f07bc37177 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -588,7 +588,7 @@ static void setup_itct_v3_hw(struct hisi_hba *hisi_hba,
+ (0x1ULL << ITCT_HDR_RTOLT_OFF));
+ }
+
+-static void free_device_v3_hw(struct hisi_hba *hisi_hba,
++static void clear_itct_v3_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_device *sas_dev)
+ {
+ DECLARE_COMPLETION_ONSTACK(completion);
+@@ -1951,7 +1951,7 @@ static const struct hisi_sas_hw hisi_sas_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),
+- .free_device = free_device_v3_hw,
++ .clear_itct = clear_itct_v3_hw,
+ .sl_notify = sl_notify_v3_hw,
+ .prep_ssp = prep_ssp_v3_hw,
+ .prep_smp = prep_smp_v3_hw,
+
diff --git a/patches.drivers/scsi-hisi_sas-relocate-smp-sg-map.patch b/patches.drivers/scsi-hisi_sas-relocate-smp-sg-map.patch
new file mode 100644
index 0000000000..c36ba0a924
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-relocate-smp-sg-map.patch
@@ -0,0 +1,309 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Wed, 9 May 2018 23:10:45 +0800
+Subject: scsi: hisi_sas: relocate smp sg map
+Git-commit: 7eee4b921822addfb67c2ced5772f003bb083520
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+Currently we use DQ lock to protect delivery of DQ entry one by one.
+
+To optimise to allow more than one slot to be built for a single DQ in
+parallel, we need to remove the DQ lock when preparing slots, prior to
+delivery.
+
+To achieve this, we rearrange the slot build order to ensure that once
+we allocate a slot for a task, we do cannot fail to deliver the task.
+
+In this patch, we rearrange the slot building for SMP tasks to ensure
+that sg mapping part (which can fail) happens before we allocate the
+slot in the DQ.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 56 ++++++++++++++++++++++++++--------
+ drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 33 ++------------------
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 35 ++-------------------
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 33 ++------------------
+ 4 files changed, 51 insertions(+), 106 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index ff5b8d7de1d1..0ce7c717b201 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -319,7 +319,8 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
+ struct hisi_sas_cmd_hdr *cmd_hdr_base;
+ struct asd_sas_port *sas_port = device->port;
+ struct device *dev = hisi_hba->dev;
+- int dlvry_queue_slot, dlvry_queue, n_elem = 0, rc, slot_idx;
++ int dlvry_queue_slot, dlvry_queue, rc, slot_idx;
++ int n_elem = 0, n_elem_req = 0, n_elem_resp = 0;
+ unsigned long flags;
+
+ if (!sas_port) {
+@@ -358,6 +359,8 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
+ }
+
+ if (!sas_protocol_ata(task->task_proto)) {
++ unsigned int req_len, resp_len;
++
+ if (task->num_scatter) {
+ n_elem = dma_map_sg(dev, task->scatter,
+ task->num_scatter, task->data_dir);
+@@ -365,6 +368,29 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
+ rc = -ENOMEM;
+ goto prep_out;
+ }
++ } else if (task->task_proto & SAS_PROTOCOL_SMP) {
++ n_elem_req = dma_map_sg(dev, &task->smp_task.smp_req,
++ 1, DMA_TO_DEVICE);
++ if (!n_elem_req) {
++ rc = -ENOMEM;
++ goto prep_out;
++ }
++ req_len = sg_dma_len(&task->smp_task.smp_req);
++ if (req_len & 0x3) {
++ 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_req) {
++ 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;
+@@ -375,11 +401,9 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
+ device);
+ else
+ rc = hisi_sas_slot_index_alloc(hisi_hba, &slot_idx);
+- if (rc) {
+- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+- goto err_out;
+- }
+ spin_unlock_irqrestore(&hisi_hba->lock, flags);
++ if (rc)
++ goto err_out_dma_unmap;
+
+ rc = hisi_hba->hw->get_free_slot(hisi_hba, dq);
+ if (rc)
+@@ -458,14 +482,22 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
+ spin_lock_irqsave(&hisi_hba->lock, flags);
+ hisi_sas_slot_index_free(hisi_hba, slot_idx);
+ spin_unlock_irqrestore(&hisi_hba->lock, flags);
+-err_out:
+- dev_err(dev, "task prep: failed[%d]!\n", rc);
+- if (!sas_protocol_ata(task->task_proto))
+- if (n_elem)
+- dma_unmap_sg(dev, task->scatter,
+- task->num_scatter,
+- task->data_dir);
++err_out_dma_unmap:
++ if (!sas_protocol_ata(task->task_proto)) {
++ if (task->num_scatter) {
++ dma_unmap_sg(dev, task->scatter, task->num_scatter,
++ task->data_dir);
++ } else if (task->task_proto & SAS_PROTOCOL_SMP) {
++ 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);
++ }
++ }
+ 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 84a0ccc4daf5..3769d70c9861 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+@@ -974,38 +974,17 @@ static int prep_smp_v1_hw(struct hisi_hba *hisi_hba,
+ struct sas_task *task = slot->task;
+ struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
+ struct domain_device *device = task->dev;
+- struct device *dev = hisi_hba->dev;
+ struct hisi_sas_port *port = slot->port;
+- struct scatterlist *sg_req, *sg_resp;
++ struct scatterlist *sg_req;
+ struct hisi_sas_device *sas_dev = device->lldd_dev;
+ dma_addr_t req_dma_addr;
+- unsigned int req_len, resp_len;
+- int elem, rc;
++ unsigned int req_len;
+
+- /*
+- * DMA-map SMP request, response buffers
+- */
+ /* req */
+ sg_req = &task->smp_task.smp_req;
+- elem = dma_map_sg(dev, sg_req, 1, DMA_TO_DEVICE);
+- if (!elem)
+- return -ENOMEM;
+ req_len = sg_dma_len(sg_req);
+ req_dma_addr = sg_dma_address(sg_req);
+
+- /* resp */
+- sg_resp = &task->smp_task.smp_resp;
+- elem = dma_map_sg(dev, sg_resp, 1, DMA_FROM_DEVICE);
+- if (!elem) {
+- rc = -ENOMEM;
+- goto err_out_req;
+- }
+- resp_len = sg_dma_len(sg_resp);
+- if ((req_len & 0x3) || (resp_len & 0x3)) {
+- rc = -EINVAL;
+- goto err_out_resp;
+- }
+-
+ /* create header */
+ /* dw0 */
+ hdr->dw0 = cpu_to_le32((port->id << CMD_HDR_PORT_OFF) |
+@@ -1027,14 +1006,6 @@ static int prep_smp_v1_hw(struct hisi_hba *hisi_hba,
+ hdr->sts_buffer_addr = cpu_to_le64(hisi_sas_status_buf_addr_dma(slot));
+
+ return 0;
+-
+-err_out_resp:
+- dma_unmap_sg(dev, &slot->task->smp_task.smp_resp, 1,
+- DMA_FROM_DEVICE);
+-err_out_req:
+- dma_unmap_sg(dev, &slot->task->smp_task.smp_req, 1,
+- DMA_TO_DEVICE);
+- return rc;
+ }
+
+ static int prep_ssp_v1_hw(struct hisi_hba *hisi_hba,
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+index 9e687319b8bc..ac0a0b2c72c5 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -1721,37 +1721,16 @@ static int prep_smp_v2_hw(struct hisi_hba *hisi_hba,
+ struct sas_task *task = slot->task;
+ struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
+ struct domain_device *device = task->dev;
+- struct device *dev = hisi_hba->dev;
+ struct hisi_sas_port *port = slot->port;
+- struct scatterlist *sg_req, *sg_resp;
++ struct scatterlist *sg_req;
+ struct hisi_sas_device *sas_dev = device->lldd_dev;
+ dma_addr_t req_dma_addr;
+- unsigned int req_len, resp_len;
+- int elem, rc;
++ unsigned int req_len;
+
+- /*
+- * DMA-map SMP request, response buffers
+- */
+ /* req */
+ sg_req = &task->smp_task.smp_req;
+- elem = dma_map_sg(dev, sg_req, 1, DMA_TO_DEVICE);
+- if (!elem)
+- return -ENOMEM;
+- req_len = sg_dma_len(sg_req);
+ req_dma_addr = sg_dma_address(sg_req);
+-
+- /* resp */
+- sg_resp = &task->smp_task.smp_resp;
+- elem = dma_map_sg(dev, sg_resp, 1, DMA_FROM_DEVICE);
+- if (!elem) {
+- rc = -ENOMEM;
+- goto err_out_req;
+- }
+- resp_len = sg_dma_len(sg_resp);
+- if ((req_len & 0x3) || (resp_len & 0x3)) {
+- rc = -EINVAL;
+- goto err_out_resp;
+- }
++ req_len = sg_dma_len(&task->smp_task.smp_req);
+
+ /* create header */
+ /* dw0 */
+@@ -1775,14 +1754,6 @@ static int prep_smp_v2_hw(struct hisi_hba *hisi_hba,
+ hdr->sts_buffer_addr = cpu_to_le64(hisi_sas_status_buf_addr_dma(slot));
+
+ return 0;
+-
+-err_out_resp:
+- dma_unmap_sg(dev, &slot->task->smp_task.smp_resp, 1,
+- DMA_FROM_DEVICE);
+-err_out_req:
+- dma_unmap_sg(dev, &slot->task->smp_task.smp_req, 1,
+- DMA_TO_DEVICE);
+- return rc;
+ }
+
+ static int prep_ssp_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 492c3beea3d5..cea5354c184f 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -986,38 +986,17 @@ static int prep_smp_v3_hw(struct hisi_hba *hisi_hba,
+ struct sas_task *task = slot->task;
+ struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
+ struct domain_device *device = task->dev;
+- struct device *dev = hisi_hba->dev;
+ struct hisi_sas_port *port = slot->port;
+- struct scatterlist *sg_req, *sg_resp;
++ struct scatterlist *sg_req;
+ struct hisi_sas_device *sas_dev = device->lldd_dev;
+ dma_addr_t req_dma_addr;
+- unsigned int req_len, resp_len;
+- int elem, rc;
++ unsigned int req_len;
+
+- /*
+- * DMA-map SMP request, response buffers
+- */
+ /* req */
+ sg_req = &task->smp_task.smp_req;
+- elem = dma_map_sg(dev, sg_req, 1, DMA_TO_DEVICE);
+- if (!elem)
+- return -ENOMEM;
+ req_len = sg_dma_len(sg_req);
+ req_dma_addr = sg_dma_address(sg_req);
+
+- /* resp */
+- sg_resp = &task->smp_task.smp_resp;
+- elem = dma_map_sg(dev, sg_resp, 1, DMA_FROM_DEVICE);
+- if (!elem) {
+- rc = -ENOMEM;
+- goto err_out_req;
+- }
+- resp_len = sg_dma_len(sg_resp);
+- if ((req_len & 0x3) || (resp_len & 0x3)) {
+- rc = -EINVAL;
+- goto err_out_resp;
+- }
+-
+ /* create header */
+ /* dw0 */
+ hdr->dw0 = cpu_to_le32((port->id << CMD_HDR_PORT_OFF) |
+@@ -1040,14 +1019,6 @@ static int prep_smp_v3_hw(struct hisi_hba *hisi_hba,
+ hdr->sts_buffer_addr = cpu_to_le64(hisi_sas_status_buf_addr_dma(slot));
+
+ return 0;
+-
+-err_out_resp:
+- dma_unmap_sg(dev, &slot->task->smp_task.smp_resp, 1,
+- DMA_FROM_DEVICE);
+-err_out_req:
+- dma_unmap_sg(dev, &slot->task->smp_task.smp_req, 1,
+- DMA_TO_DEVICE);
+- return rc;
+ }
+
+ static int prep_ata_v3_hw(struct hisi_hba *hisi_hba,
+
diff --git a/patches.drivers/scsi-hisi_sas-remove-depends-on-has_dma-in-case-of-platform-dependency.patch b/patches.drivers/scsi-hisi_sas-remove-depends-on-has_dma-in-case-of-platform-dependency.patch
new file mode 100644
index 0000000000..28d4992b75
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-remove-depends-on-has_dma-in-case-of-platform-dependency.patch
@@ -0,0 +1,42 @@
+From: Geert Uytterhoeven <geert@linux-m68k.org>
+Date: Fri, 16 Mar 2018 14:51:50 +0100
+Subject: scsi: hisi_sas: Remove depends on HAS_DMA in case of platform
+ dependency
+Git-commit: 3565a3d01e14c33d29512ca8129365cbe38df809
+Patch-mainline: v4.17-rc1
+References: FATE#326253
+
+Remove dependencies on HAS_DMA where a Kconfig symbol depends on another
+symbol that implies HAS_DMA, and, optionally, on "|| COMPILE_TEST". In
+most cases this other symbol is an architecture or platform specific
+symbol, or PCI.
+
+Generic symbols and drivers without platform dependencies keep their
+dependencies on HAS_DMA, to prevent compiling subsystems or drivers that
+cannot work anyway.
+
+This simplifies the dependencies, and allows to improve compile-testing.
+
+Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
+Reviewed-by: Mark Brown <broonie@kernel.org>
+Acked-by: Robin Murphy <robin.murphy@arm.com>
+Acked-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/hisi_sas/Kconfig b/drivers/scsi/hisi_sas/Kconfig
+index d42f29a5eb65..57183fce70fb 100644
+--- a/drivers/scsi/hisi_sas/Kconfig
++++ b/drivers/scsi/hisi_sas/Kconfig
+@@ -1,6 +1,6 @@
+ config SCSI_HISI_SAS
+ tristate "HiSilicon SAS"
+- depends on HAS_DMA && HAS_IOMEM
++ depends on HAS_IOMEM
+ depends on ARM64 || COMPILE_TEST
+ select SCSI_SAS_LIBSAS
+ select BLK_DEV_INTEGRITY
+
diff --git a/patches.drivers/scsi-hisi_sas-remove-redundant-handling-to-event95-for-v3.patch b/patches.drivers/scsi-hisi_sas-remove-redundant-handling-to-event95-for-v3.patch
new file mode 100644
index 0000000000..a2c3d42b0a
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-remove-redundant-handling-to-event95-for-v3.patch
@@ -0,0 +1,49 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Wed, 2 May 2018 23:56:32 +0800
+Subject: scsi: hisi_sas: remove redundant handling to event95 for v3
+Git-commit: bf081d5da4fa3a0d0ef640868de1b9f644f633e0
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+Event95 is used for DFX purpose. The relevant bit for this interrupt in
+the ENT_INT_SRC_MSK3 register has been disabled, so remove the
+processing.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 9 +--------
+ 1 file changed, 1 insertion(+), 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 026faeee5ead..d6e705ff9dad 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -1331,14 +1331,9 @@ static irqreturn_t int_chnl_int_v3_hw(int irq_no, void *p)
+ {
+ struct hisi_hba *hisi_hba = p;
+ struct device *dev = hisi_hba->dev;
+- u32 ent_msk, ent_tmp, irq_msk;
++ u32 irq_msk;
+ int phy_no = 0;
+
+- ent_msk = hisi_sas_read32(hisi_hba, ENT_INT_SRC_MSK3);
+- ent_tmp = ent_msk;
+- ent_msk |= ENT_INT_SRC_MSK3_ENT95_MSK_MSK;
+- hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, ent_msk);
+-
+ irq_msk = hisi_sas_read32(hisi_hba, CHNL_INT_STATUS)
+ & 0xeeeeeeee;
+
+@@ -1415,8 +1410,6 @@ static irqreturn_t int_chnl_int_v3_hw(int irq_no, void *p)
+ phy_no++;
+ }
+
+- hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, ent_tmp);
+-
+ return IRQ_HANDLED;
+ }
+
+
diff --git a/patches.drivers/scsi-hisi_sas-remove-some-unneeded-structure-members.patch b/patches.drivers/scsi-hisi_sas-remove-some-unneeded-structure-members.patch
new file mode 100644
index 0000000000..d5e7fa2874
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-remove-some-unneeded-structure-members.patch
@@ -0,0 +1,104 @@
+From: John Garry <john.garry@huawei.com>
+Date: Sat, 24 Mar 2018 00:05:15 +0800
+Subject: scsi: hisi_sas: remove some unneeded structure members
+Git-commit: c90a0bea4f645d561b87becd2bd99f7934402510
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+This patch removes unneeded structure elements:
+
+- hisi_sas_phy.dev_sas_addr: only ever written
+ - Also remove associated function which writes it,
+ hisi_sas_init_add().
+
+- hisi_sas_device.attached_phy: only ever written
+ - Also remove code to set it in hisi_sas_dev_found()
+
+Signed-off-by: John Garry <john.garry@huawei.com>
+Reviewed-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas.h | 3 ---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 17 +----------------
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 2 --
+ 3 files changed, 1 insertion(+), 21 deletions(-)
+
+--- a/drivers/scsi/hisi_sas/hisi_sas.h
++++ b/drivers/scsi/hisi_sas/hisi_sas.h
+@@ -138,7 +138,6 @@ struct hisi_sas_phy {
+ struct sas_identify identify;
+ struct timer_list timer;
+ u64 port_id; /* from hw */
+- u64 dev_sas_addr;
+ u64 frame_rcvd_size;
+ u8 frame_rcvd[32];
+ u8 phy_attached;
+@@ -175,7 +174,6 @@ struct hisi_sas_device {
+ struct completion *completion;
+ struct hisi_sas_dq *dq;
+ struct list_head list;
+- u64 attached_phy;
+ enum sas_device_type dev_type;
+ int device_id;
+ int sata_idx;
+@@ -441,7 +439,6 @@ extern struct scsi_transport_template *h
+ extern struct scsi_host_template *hisi_sas_sht;
+
+ extern void hisi_sas_stop_phys(struct hisi_hba *hisi_hba);
+-extern void hisi_sas_init_add(struct hisi_hba *hisi_hba);
+ extern int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost);
+ extern void hisi_sas_free(struct hisi_hba *hisi_hba);
+ extern u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis,
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -577,10 +577,8 @@ static int hisi_sas_dev_found(struct dom
+ for (phy_no = 0; phy_no < phy_num; phy_no++) {
+ phy = &parent_dev->ex_dev.ex_phy[phy_no];
+ if (SAS_ADDR(phy->attached_sas_addr) ==
+- SAS_ADDR(device->sas_addr)) {
+- sas_dev->attached_phy = phy_no;
++ SAS_ADDR(device->sas_addr))
+ break;
+- }
+ }
+
+ if (phy_no == phy_num) {
+@@ -2081,17 +2079,6 @@ err_out:
+ return NULL;
+ }
+
+-void hisi_sas_init_add(struct hisi_hba *hisi_hba)
+-{
+- int i;
+-
+- for (i = 0; i < hisi_hba->n_phy; i++)
+- memcpy(&hisi_hba->phy[i].dev_sas_addr,
+- hisi_hba->sas_addr,
+- SAS_ADDR_SIZE);
+-}
+-EXPORT_SYMBOL_GPL(hisi_sas_init_add);
+-
+ int hisi_sas_probe(struct platform_device *pdev,
+ const struct hisi_sas_hw *hw)
+ {
+@@ -2145,8 +2132,6 @@ int hisi_sas_probe(struct platform_devic
+ sha->sas_port[i] = &hisi_hba->port[i].sas_port;
+ }
+
+- hisi_sas_init_add(hisi_hba);
+-
+ rc = scsi_add_host(shost, &pdev->dev);
+ if (rc)
+ goto err_out_ha;
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -2134,8 +2134,6 @@ hisi_sas_v3_probe(struct pci_dev *pdev,
+ sha->sas_port[i] = &hisi_hba->port[i].sas_port;
+ }
+
+- hisi_sas_init_add(hisi_hba);
+-
+ rc = scsi_add_host(shost, dev);
+ if (rc)
+ goto err_out_ha;
diff --git a/patches.drivers/scsi-hisi_sas-remove-unused-variable-hisi_sas_devices-running_req.patch b/patches.drivers/scsi-hisi_sas-remove-unused-variable-hisi_sas_devices-running_req.patch
new file mode 100644
index 0000000000..bbc087c246
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-remove-unused-variable-hisi_sas_devices-running_req.patch
@@ -0,0 +1,89 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Wed, 7 Mar 2018 20:25:10 +0800
+Subject: scsi: hisi_sas: remove unused variable hisi_sas_devices.running_req
+Git-commit: 36996a1e6dff4e5835faeb00ba920ccb9a07aa52
+Patch-mainline: v4.17-rc1
+References: FATE#326253
+
+The structure element hisi_sas_devices.running_req to count how many
+commands are active is in effect only ever written in the code, so remove
+it.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas.h | 1 -
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 9 ---------
+ drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 3 ---
+ 3 files changed, 13 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
+index e7fd2877c19c..d1153e8e846b 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas.h
++++ b/drivers/scsi/hisi_sas/hisi_sas.h
+@@ -175,7 +175,6 @@ struct hisi_sas_device {
+ struct hisi_sas_dq *dq;
+ struct list_head list;
+ u64 attached_phy;
+- atomic64_t running_req;
+ enum sas_device_type dev_type;
+ int device_id;
+ int sata_idx;
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 9ff87902d67a..88ad8d42ef6f 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -200,8 +200,6 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
+
+ if (task) {
+ struct device *dev = hisi_hba->dev;
+- struct domain_device *device = task->dev;
+- struct hisi_sas_device *sas_dev = device->lldd_dev;
+
+ if (!task->lldd_task)
+ return;
+@@ -213,9 +211,6 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
+ dma_unmap_sg(dev, task->scatter,
+ task->num_scatter,
+ task->data_dir);
+-
+- if (sas_dev)
+- atomic64_dec(&sas_dev->running_req);
+ }
+
+ if (slot->buf)
+@@ -431,8 +426,6 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
+
+ dq->slot_prep = slot;
+-
+- atomic64_inc(&sas_dev->running_req);
+ ++(*pass);
+
+ return 0;
+@@ -1517,8 +1510,6 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id,
+
+ dq->slot_prep = slot;
+
+- atomic64_inc(&sas_dev->running_req);
+-
+ /* send abort command to the chip */
+ hisi_hba->hw->start_delivery(dq);
+ spin_unlock_irqrestore(&dq->lock, flags_dq);
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+index 2eb89806c512..8dd0e6a6ff8a 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+@@ -1407,9 +1407,6 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba,
+ }
+
+ out:
+- if (sas_dev)
+- atomic64_dec(&sas_dev->running_req);
+-
+ hisi_sas_slot_task_free(hisi_hba, task, slot);
+ sts = ts->stat;
+
+
diff --git a/patches.drivers/scsi-hisi_sas-reset-disks-when-discovered.patch b/patches.drivers/scsi-hisi_sas-reset-disks-when-discovered.patch
new file mode 100644
index 0000000000..0a32230b1d
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-reset-disks-when-discovered.patch
@@ -0,0 +1,111 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Mon, 21 May 2018 18:09:17 +0800
+Subject: scsi: hisi_sas: Reset disks when discovered
+Git-commit: d5a60dfdb364bd1fa59c2c11be54be80f6990a3d
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+When a disk is discovered, it may be in an error state, or there may be
+residual commands remaining in the disk.
+
+To ensure any disk is in good state after discovery, reset via TMF (for SAS
+disk) or softreset (for a SATA disk).
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 50 ++++++++++++++++++++++++++++++++++-
+ 1 file changed, 49 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index a7e4c6e77068..c8e647a65b30 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -24,6 +24,9 @@ hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
+ 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);
++static void hisi_sas_release_task(struct hisi_hba *hisi_hba,
++ struct domain_device *device);
++static void hisi_sas_dev_gone(struct domain_device *device);
+
+ u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction)
+ {
+@@ -624,12 +627,49 @@ static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device)
+ return sas_dev;
+ }
+
++#define HISI_SAS_SRST_ATA_DISK_CNT 3
++static int hisi_sas_init_device(struct domain_device *device)
++{
++ int rc = TMF_RESP_FUNC_COMPLETE;
++ struct scsi_lun lun;
++ struct hisi_sas_tmf_task tmf_task;
++ int retry = HISI_SAS_SRST_ATA_DISK_CNT;
++ struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
++
++ switch (device->dev_type) {
++ case SAS_END_DEVICE:
++ int_to_scsilun(0, &lun);
++
++ tmf_task.tmf = TMF_CLEAR_TASK_SET;
++ rc = hisi_sas_debug_issue_ssp_tmf(device, lun.scsi_lun,
++ &tmf_task);
++ if (rc == TMF_RESP_FUNC_COMPLETE)
++ hisi_sas_release_task(hisi_hba, device);
++ break;
++ case SAS_SATA_DEV:
++ case SAS_SATA_PM:
++ case SAS_SATA_PM_PORT:
++ case SAS_SATA_PENDING:
++ while (retry-- > 0) {
++ rc = hisi_sas_softreset_ata_disk(device);
++ if (!rc)
++ break;
++ }
++ break;
++ default:
++ break;
++ }
++
++ return rc;
++}
++
+ static int hisi_sas_dev_found(struct domain_device *device)
+ {
+ struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
+ struct domain_device *parent_dev = device->parent;
+ struct hisi_sas_device *sas_dev;
+ struct device *dev = hisi_hba->dev;
++ int rc;
+
+ if (hisi_hba->hw->alloc_dev)
+ sas_dev = hisi_hba->hw->alloc_dev(device);
+@@ -661,14 +701,22 @@ static int hisi_sas_dev_found(struct domain_device *device)
+ "dev:%016llx at ex:%016llx\n",
+ SAS_ADDR(device->sas_addr),
+ SAS_ADDR(parent_dev->sas_addr));
+- return -EINVAL;
++ rc = -EINVAL;
++ goto err_out;
+ }
+ }
+
+ 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;
+ return 0;
++
++err_out:
++ hisi_sas_dev_gone(device);
++ return rc;
+ }
+
+ static int hisi_sas_slave_configure(struct scsi_device *sdev)
+
diff --git a/patches.drivers/scsi-hisi_sas-some-optimizations-of-host-controller-reset.patch b/patches.drivers/scsi-hisi_sas-some-optimizations-of-host-controller-reset.patch
new file mode 100644
index 0000000000..43e2bba786
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-some-optimizations-of-host-controller-reset.patch
@@ -0,0 +1,77 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Sat, 9 Dec 2017 01:16:36 +0800
+Subject: scsi: hisi_sas: some optimizations of host controller reset
+Git-commit: fb51e7a8d38484687337f16636c5be9528e00fed
+Patch-mainline: v4.16-rc1
+References: FATE#326253
+
+This patch do following optimizations to host controller reset:
+
+1. Unblock scsi requests before rescanning topology, as SCSI command need be
+ used if new device is found during rescanning topology.
+
+2. Remove drain_workqueue(hisi_hba->wq) and drain_workqueue(shost->work_q), as
+ there is no need to ensure that all PHYs event are done before exiting host
+ reset.
+
+3. Improve message print level of host reset. Host reset is an important and
+ very few occurrence event. We should know its progress even when not
+ debugging.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 11 ++++-------
+ 1 file changed, 4 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 326ecb24bb20..64d51a839187 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -1061,8 +1061,6 @@ static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 old_state,
+ hisi_sas_phy_down(hisi_hba, phy_no, 0);
+
+ }
+-
+- drain_workqueue(hisi_hba->shost->work_q);
+ }
+
+ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
+@@ -1079,7 +1077,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 -1;
+
+- dev_dbg(dev, "controller resetting...\n");
++ dev_info(dev, "controller resetting...\n");
+ old_state = hisi_hba->hw->get_phys_state(hisi_hba);
+
+ scsi_block_requests(shost);
+@@ -1088,6 +1086,7 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
+ if (rc) {
+ dev_warn(dev, "controller reset failed (%d)\n", rc);
+ clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
++ scsi_unblock_requests(shost);
+ goto out;
+ }
+ spin_lock_irqsave(&hisi_hba->lock, flags);
+@@ -1100,15 +1099,13 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
+ hisi_hba->hw->phys_init(hisi_hba);
+ msleep(1000);
+ hisi_sas_refresh_port_id(hisi_hba);
+- drain_workqueue(hisi_hba->wq);
+- drain_workqueue(shost->work_q);
++ scsi_unblock_requests(shost);
+
+ state = hisi_hba->hw->get_phys_state(hisi_hba);
+ hisi_sas_rescan_topology(hisi_hba, old_state, state);
+- dev_dbg(dev, "controller reset complete\n");
++ dev_info(dev, "controller reset complete\n");
+
+ out:
+- scsi_unblock_requests(shost);
+ clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags);
+
+ return rc;
+
diff --git a/patches.drivers/scsi-hisi_sas-stop-controller-timer-for-reset.patch b/patches.drivers/scsi-hisi_sas-stop-controller-timer-for-reset.patch
new file mode 100644
index 0000000000..3d64529e3c
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-stop-controller-timer-for-reset.patch
@@ -0,0 +1,33 @@
+From: John Garry <john.garry@huawei.com>
+Date: Wed, 2 May 2018 23:56:29 +0800
+Subject: scsi: hisi_sas: stop controller timer for reset
+Git-commit: 6f7c32d6057cad05cf057b14c910659a8d06c975
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+We should only have the timer enabled after PHY up after controller
+reset, so disable prior to reset.
+
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ 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 24416bb66027..1f27f847b8b4 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -1130,6 +1130,9 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
+ old_state = hisi_hba->hw->get_phys_state(hisi_hba);
+
+ scsi_block_requests(shost);
++ if (timer_pending(&hisi_hba->timer))
++ del_timer_sync(&hisi_hba->timer);
++
+ set_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
+ rc = hisi_hba->hw->soft_reset(hisi_hba);
+ if (rc) {
+
diff --git a/patches.drivers/scsi-hisi_sas-support-the-property-of-signal-attenuation-for-v2-hw.patch b/patches.drivers/scsi-hisi_sas-support-the-property-of-signal-attenuation-for-v2-hw.patch
new file mode 100644
index 0000000000..d74732833d
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-support-the-property-of-signal-attenuation-for-v2-hw.patch
@@ -0,0 +1,93 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Wed, 7 Mar 2018 20:25:06 +0800
+Subject: scsi: hisi_sas: support the property of signal attenuation for v2 hw
+Git-commit: 67c2bf23314170a17f2aefec4f0aaa4881b72181
+Patch-mainline: v4.17-rc1
+References: FATE#326253
+
+The register SAS_PHY_CTRL is configured according to signal quality. The
+signal quality is calculated by signal attenuation of hardware physical
+link. It may be different for different PCB layout.
+
+So, in order to give better support to new board, this patch add support to
+reading the devicetree property, "hisilicon,signal-attenuation". Of course,
+we still keep an default value in driver to adapt old board.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 39 +++++++++++++++++++++++++++++++++-
+ 1 file changed, 38 insertions(+), 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 4ccb61e2ae5c..42b3fd6a9936 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -406,6 +406,17 @@ struct hisi_sas_err_record_v2 {
+ __le32 dma_rx_err_type;
+ };
+
++struct signal_attenuation_s {
++ u32 de_emphasis;
++ u32 preshoot;
++ u32 boost;
++};
++
++struct sig_atten_lu_s {
++ const struct signal_attenuation_s *att;
++ u32 sas_phy_ctrl;
++};
++
+ static const struct hisi_sas_hw_error one_bit_ecc_errors[] = {
+ {
+ .irq_msk = BIT(SAS_ECC_INTR_DQE_ECC_1B_OFF),
+@@ -1130,9 +1141,16 @@ static void phys_try_accept_stp_links_v2_hw(struct hisi_hba *hisi_hba)
+ }
+ }
+
++static const struct signal_attenuation_s x6000 = {9200, 0, 10476};
++static const struct sig_atten_lu_s sig_atten_lu[] = {
++ { &x6000, 0x3016a68 },
++};
++
+ static void init_reg_v2_hw(struct hisi_hba *hisi_hba)
+ {
+ struct device *dev = hisi_hba->dev;
++ u32 sas_phy_ctrl = 0x30b9908;
++ u32 signal[3];
+ int i;
+
+ /* Global registers init */
+@@ -1176,9 +1194,28 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba)
+ hisi_sas_write32(hisi_hba, AXI_AHB_CLK_CFG, 1);
+ hisi_sas_write32(hisi_hba, HYPER_STREAM_ID_EN_CFG, 1);
+
++ /* Get sas_phy_ctrl value to deal with TX FFE issue. */
++ if (!device_property_read_u32_array(dev, "hisilicon,signal-attenuation",
++ signal, ARRAY_SIZE(signal))) {
++ for (i = 0; i < ARRAY_SIZE(sig_atten_lu); i++) {
++ const struct sig_atten_lu_s *lookup = &sig_atten_lu[i];
++ const struct signal_attenuation_s *att = lookup->att;
++
++ if ((signal[0] == att->de_emphasis) &&
++ (signal[1] == att->preshoot) &&
++ (signal[2] == att->boost)) {
++ sas_phy_ctrl = lookup->sas_phy_ctrl;
++ break;
++ }
++ }
++
++ if (i == ARRAY_SIZE(sig_atten_lu))
++ dev_warn(dev, "unknown signal attenuation values, using default PHY ctrl config\n");
++ }
++
+ for (i = 0; i < hisi_hba->n_phy; i++) {
+ hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE, 0x855);
+- hisi_sas_phy_write32(hisi_hba, i, SAS_PHY_CTRL, 0x30b9908);
++ hisi_sas_phy_write32(hisi_hba, i, SAS_PHY_CTRL, sas_phy_ctrl);
+ hisi_sas_phy_write32(hisi_hba, i, SL_TOUT_CFG, 0x7d7d7d7d);
+ hisi_sas_phy_write32(hisi_hba, i, SL_CONTROL, 0x0);
+ hisi_sas_phy_write32(hisi_hba, i, TXID_AUTO, 0x2);
+
diff --git a/patches.drivers/scsi-hisi_sas-terminate-stp-reject-quickly-for-v2-hw.patch b/patches.drivers/scsi-hisi_sas-terminate-stp-reject-quickly-for-v2-hw.patch
new file mode 100644
index 0000000000..90337c5882
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-terminate-stp-reject-quickly-for-v2-hw.patch
@@ -0,0 +1,127 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Mon, 21 May 2018 18:09:23 +0800
+Subject: scsi: hisi_sas: Terminate STP reject quickly for v2 hw
+Git-commit: 31709548d2aca9861a72e2890d62fc87c52199de
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+For v2 hw, STP link from target is rejected after host reset because of a
+SoC bug. The STP reject will be terminated after we have sent IO from each
+PHY of a port.
+
+This is not an problem before, as we don't need to setup STP link from
+target immediately after host reset. But now, it is. Because we want to
+send soft-reset immediately after host reset.
+
+In order to terminate STP reject quickly, this patch send ATA reset command
+through each PHY of a port. Notes: ATA reset command don't need target's
+response.
+
+Besides, we do abort dev for each device before terminating STP reject.
+This is a quirk of v2 hw.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 78 +++++++++++++++++++++++++++++++++++
+ 1 file changed, 78 insertions(+)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 4e8046ecf477..cd55849bcd07 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -1275,6 +1275,81 @@ static void hisi_sas_reset_init_all_devices(struct hisi_hba *hisi_hba)
+ }
+ }
+
++static void hisi_sas_send_ata_reset_each_phy(struct hisi_hba *hisi_hba,
++ struct asd_sas_port *sas_port,
++ struct domain_device *device)
++{
++ struct hisi_sas_tmf_task tmf_task = { .force_phy = 1 };
++ struct ata_port *ap = device->sata_dev.ap;
++ struct device *dev = hisi_hba->dev;
++ int s = sizeof(struct host_to_dev_fis);
++ int rc = TMF_RESP_FUNC_FAILED;
++ struct asd_sas_phy *sas_phy;
++ struct ata_link *link;
++ u8 fis[20] = {0};
++ u32 state;
++
++ state = hisi_hba->hw->get_phys_state(hisi_hba);
++ list_for_each_entry(sas_phy, &sas_port->phy_list, port_phy_el) {
++ if (!(state & BIT(sas_phy->id)))
++ continue;
++
++ ata_for_each_link(link, ap, EDGE) {
++ int pmp = sata_srst_pmp(link);
++
++ tmf_task.phy_id = sas_phy->id;
++ hisi_sas_fill_ata_reset_cmd(link->device, 1, pmp, 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);
++ break;
++ }
++ }
++ }
++}
++
++static void hisi_sas_terminate_stp_reject(struct hisi_hba *hisi_hba)
++{
++ struct device *dev = hisi_hba->dev;
++ int port_no, rc, i;
++
++ for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
++ struct hisi_sas_device *sas_dev = &hisi_hba->devices[i];
++ struct domain_device *device = sas_dev->sas_device;
++
++ if ((sas_dev->dev_type == SAS_PHY_UNUSED) || !device)
++ continue;
++
++ rc = hisi_sas_internal_task_abort(hisi_hba, device,
++ HISI_SAS_INT_ABT_DEV, 0);
++ if (rc < 0)
++ dev_err(dev, "STP reject: abort dev failed %d\n", rc);
++ }
++
++ for (port_no = 0; port_no < hisi_hba->n_phy; port_no++) {
++ struct hisi_sas_port *port = &hisi_hba->port[port_no];
++ struct asd_sas_port *sas_port = &port->sas_port;
++ struct domain_device *port_dev = sas_port->port_dev;
++ struct domain_device *device;
++
++ if (!port_dev || !DEV_IS_EXPANDER(port_dev->dev_type))
++ continue;
++
++ /* Try to find a SATA device */
++ list_for_each_entry(device, &sas_port->dev_list,
++ dev_list_node) {
++ if (dev_is_sata(device)) {
++ hisi_sas_send_ata_reset_each_phy(hisi_hba,
++ sas_port,
++ device);
++ break;
++ }
++ }
++ }
++}
++
+ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
+ {
+ struct device *dev = hisi_hba->dev;
+@@ -1312,6 +1387,9 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
+ hisi_hba->hw->phys_init(hisi_hba);
+ msleep(1000);
+ hisi_sas_refresh_port_id(hisi_hba);
++
++ if (hisi_hba->reject_stp_links_msk)
++ hisi_sas_terminate_stp_reject(hisi_hba);
+ hisi_sas_reset_init_all_devices(hisi_hba);
+ scsi_unblock_requests(shost);
+
+
diff --git a/patches.drivers/scsi-hisi_sas-try-wait-commands-before-before-controller-reset.patch b/patches.drivers/scsi-hisi_sas-try-wait-commands-before-before-controller-reset.patch
new file mode 100644
index 0000000000..61c72b701e
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-try-wait-commands-before-before-controller-reset.patch
@@ -0,0 +1,148 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Mon, 21 May 2018 18:09:20 +0800
+Subject: scsi: hisi_sas: Try wait commands before before controller reset
+Git-commit: a865ae14ff62797f14b760b2063b90c81d27d178
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+We may reset the controller in many scenarios, such as SCSI EH and HW
+errors. There should be no IO which returns from target when SCSI EH is
+active. But for other scenarios, there may be. It is not necessary to make
+such IOs fail.
+
+This patch adds an function of trying to wait for any commands, or IO, to
+complete before host reset. If no more CQ returned from host controller in
+100ms, we assume no more IO can return, and then stop waiting. We wait 5s
+at most.
+
+The HW has a register CQE_SEND_CNT to indicate the total number of CQs that
+has been reported to driver. We can use this register and it is reliable to
+resd this register in such scenarios that require host reset.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas.h | 2 ++
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 2 ++
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 19 +++++++++++++++++++
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 20 ++++++++++++++++++++
+ 4 files changed, 43 insertions(+)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
+index 37c9a6246dc8..8ce6abb48867 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas.h
++++ b/drivers/scsi/hisi_sas/hisi_sas.h
+@@ -246,6 +246,8 @@ 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);
++ void (*wait_cmds_complete_timeout)(struct hisi_hba *hisi_hba,
++ int delay_ms, int timeout_ms);
+ 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 dc67bd7c7ab0..5bc522c35690 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -1293,6 +1293,8 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
+ old_state = hisi_hba->hw->get_phys_state(hisi_hba);
+
+ scsi_block_requests(shost);
++ hisi_hba->hw->wait_cmds_complete_timeout(hisi_hba, 100, 5000);
++
+ if (timer_pending(&hisi_hba->timer))
+ del_timer_sync(&hisi_hba->timer);
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+index 8def327c4f46..18dbaffc9988 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -144,6 +144,7 @@
+ #define SAS_ECC_INTR_NCQ_MEM3_ECC_1B_OFF 19
+ #define SAS_ECC_INTR_MSK 0x1ec
+ #define HGC_ERR_STAT_EN 0x238
++#define CQE_SEND_CNT 0x248
+ #define DLVRY_Q_0_BASE_ADDR_LO 0x260
+ #define DLVRY_Q_0_BASE_ADDR_HI 0x264
+ #define DLVRY_Q_0_DEPTH 0x268
+@@ -3501,6 +3502,23 @@ static int write_gpio_v2_hw(struct hisi_hba *hisi_hba, u8 reg_type,
+ return 0;
+ }
+
++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;
++ int entries, entries_old = 0, time;
++
++ for (time = 0; time < timeout_ms; time += delay_ms) {
++ entries = hisi_sas_read32(hisi_hba, CQE_SEND_CNT);
++ if (entries == entries_old)
++ break;
++
++ entries_old = entries;
++ msleep(delay_ms);
++ }
++
++ dev_dbg(dev, "wait commands complete %dms\n", time);
++}
+
+ static struct scsi_host_template sht_v2_hw = {
+ .name = DRV_NAME,
+@@ -3552,6 +3570,7 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = {
+ .soft_reset = soft_reset_v2_hw,
+ .get_phys_state = get_phys_state_v2_hw,
+ .write_gpio = write_gpio_v2_hw,
++ .wait_cmds_complete_timeout = wait_cmds_complete_timeout_v2_hw,
+ .sht = &sht_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 13d21349d1ba..dd5f542bbc45 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -92,6 +92,7 @@
+ #define SAS_ECC_INTR 0x1e8
+ #define SAS_ECC_INTR_MSK 0x1ec
+ #define HGC_ERR_STAT_EN 0x238
++#define CQE_SEND_CNT 0x248
+ #define DLVRY_Q_0_BASE_ADDR_LO 0x260
+ #define DLVRY_Q_0_BASE_ADDR_HI 0x264
+ #define DLVRY_Q_0_DEPTH 0x268
+@@ -2015,6 +2016,24 @@ static int write_gpio_v3_hw(struct hisi_hba *hisi_hba, u8 reg_type,
+ return 0;
+ }
+
++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;
++ int entries, entries_old = 0, time;
++
++ for (time = 0; time < timeout_ms; time += delay_ms) {
++ entries = hisi_sas_read32(hisi_hba, CQE_SEND_CNT);
++ if (entries == entries_old)
++ break;
++
++ entries_old = entries;
++ msleep(delay_ms);
++ }
++
++ dev_dbg(dev, "wait commands complete %dms\n", time);
++}
++
+ static struct scsi_host_template sht_v3_hw = {
+ .name = DRV_NAME,
+ .module = THIS_MODULE,
+@@ -2063,6 +2082,7 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = {
+ .get_phys_state = get_phys_state_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,
+ };
+
+ static struct Scsi_Host *
+
diff --git a/patches.drivers/scsi-hisi_sas-update-phy-linkrate-after-a-controller-reset.patch b/patches.drivers/scsi-hisi_sas-update-phy-linkrate-after-a-controller-reset.patch
new file mode 100644
index 0000000000..04f2a1efaa
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-update-phy-linkrate-after-a-controller-reset.patch
@@ -0,0 +1,181 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Wed, 2 May 2018 23:56:30 +0800
+Subject: scsi: hisi_sas: update PHY linkrate after a controller reset
+Git-commit: c2c1d9ded0a2c06df300e244220708f5c1f1db77
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+After the controller is reset, we currently may not honour the PHY max
+linkrate set via sysfs, in that after a reset we always revert to max
+linkrate of 12Gbps, ignoring the value set via sysfs.
+
+This patch modifies to policy to set the programmed PHY linkrate,
+honouring the max linkrate programmed via sysfs.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas.h | 1 +
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 16 ++++++++++++++++
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 31 ++++++++++++++++++-------------
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 31 ++++++++++++++++++-------------
+ 4 files changed, 53 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
+index 04a40c427a20..44105389f2df 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas.h
++++ b/drivers/scsi/hisi_sas/hisi_sas.h
+@@ -463,4 +463,5 @@ extern void hisi_sas_kill_tasklets(struct hisi_hba *hisi_hba);
+ 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);
++extern u8 hisi_sas_get_prog_phy_linkrate_mask(enum sas_linkrate max);
+ #endif
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 1f27f847b8b4..ff5b8d7de1d1 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -135,6 +135,22 @@ int hisi_sas_get_ncq_tag(struct sas_task *task, u32 *tag)
+ }
+ EXPORT_SYMBOL_GPL(hisi_sas_get_ncq_tag);
+
++/*
++ * This function assumes linkrate mask fits in 8 bits, which it
++ * does for all HW versions supported.
++ */
++u8 hisi_sas_get_prog_phy_linkrate_mask(enum sas_linkrate max)
++{
++ u16 rate = 0;
++ int i;
++
++ max -= SAS_LINK_RATE_1_5_GBPS;
++ for (i = 0; i <= max; i++)
++ rate |= 1 << (i * 2);
++ return rate;
++}
++EXPORT_SYMBOL_GPL(hisi_sas_get_prog_phy_linkrate_mask);
++
+ static struct hisi_hba *dev_to_hisi_hba(struct domain_device *device)
+ {
+ return device->port->ha->lldd_ha;
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+index 6dda6eb50918..9e687319b8bc 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -1216,7 +1216,22 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba)
+ }
+
+ for (i = 0; i < hisi_hba->n_phy; i++) {
+- hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE, 0x855);
++ struct hisi_sas_phy *phy = &hisi_hba->phy[i];
++ struct asd_sas_phy *sas_phy = &phy->sas_phy;
++ u32 prog_phy_link_rate = 0x800;
++
++ if (!sas_phy->phy || (sas_phy->phy->maximum_linkrate <
++ SAS_LINK_RATE_1_5_GBPS)) {
++ prog_phy_link_rate = 0x855;
++ } else {
++ enum sas_linkrate max = sas_phy->phy->maximum_linkrate;
++
++ prog_phy_link_rate =
++ hisi_sas_get_prog_phy_linkrate_mask(max) |
++ 0x800;
++ }
++ hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE,
++ prog_phy_link_rate);
+ hisi_sas_phy_write32(hisi_hba, i, SAS_PHY_CTRL, sas_phy_ctrl);
+ hisi_sas_phy_write32(hisi_hba, i, SL_TOUT_CFG, 0x7d7d7d7d);
+ hisi_sas_phy_write32(hisi_hba, i, SL_CONTROL, 0x0);
+@@ -1585,13 +1600,10 @@ static enum sas_linkrate phy_get_max_linkrate_v2_hw(void)
+ static void phy_set_linkrate_v2_hw(struct hisi_hba *hisi_hba, int phy_no,
+ struct sas_phy_linkrates *r)
+ {
+- u32 prog_phy_link_rate =
+- hisi_sas_phy_read32(hisi_hba, phy_no, PROG_PHY_LINK_RATE);
+ struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
+ struct asd_sas_phy *sas_phy = &phy->sas_phy;
+- int i;
+ enum sas_linkrate min, max;
+- u32 rate_mask = 0;
++ u32 prog_phy_link_rate = 0x800;
+
+ if (r->maximum_linkrate == SAS_LINK_RATE_UNKNOWN) {
+ max = sas_phy->phy->maximum_linkrate;
+@@ -1604,14 +1616,7 @@ static void phy_set_linkrate_v2_hw(struct hisi_hba *hisi_hba, int phy_no,
+
+ sas_phy->phy->maximum_linkrate = max;
+ sas_phy->phy->minimum_linkrate = min;
+-
+- max -= SAS_LINK_RATE_1_5_GBPS;
+-
+- for (i = 0; i <= max; i++)
+- rate_mask |= 1 << (i * 2);
+-
+- prog_phy_link_rate &= ~0xff;
+- prog_phy_link_rate |= rate_mask;
++ prog_phy_link_rate |= hisi_sas_get_prog_phy_linkrate_mask(max);
+
+ disable_phy_v2_hw(hisi_hba, phy_no);
+ msleep(100);
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+index 5c0d9683630b..ffa3cea5ca8f 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -429,7 +429,22 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
+ hisi_sas_write32(hisi_hba, HYPER_STREAM_ID_EN_CFG, 1);
+
+ for (i = 0; i < hisi_hba->n_phy; i++) {
+- hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE, 0x855);
++ struct hisi_sas_phy *phy = &hisi_hba->phy[i];
++ struct asd_sas_phy *sas_phy = &phy->sas_phy;
++ u32 prog_phy_link_rate = 0x800;
++
++ if (!sas_phy->phy || (sas_phy->phy->maximum_linkrate <
++ SAS_LINK_RATE_1_5_GBPS)) {
++ prog_phy_link_rate = 0x855;
++ } else {
++ enum sas_linkrate max = sas_phy->phy->maximum_linkrate;
++
++ prog_phy_link_rate =
++ hisi_sas_get_prog_phy_linkrate_mask(max) |
++ 0x800;
++ }
++ hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE,
++ prog_phy_link_rate);
+ hisi_sas_phy_write32(hisi_hba, i, SAS_RX_TRAIN_TIMER, 0x13e80);
+ hisi_sas_phy_write32(hisi_hba, i, CHL_INT0, 0xffffffff);
+ hisi_sas_phy_write32(hisi_hba, i, CHL_INT1, 0xffffffff);
+@@ -1869,13 +1884,10 @@ static int hisi_sas_v3_init(struct hisi_hba *hisi_hba)
+ static void phy_set_linkrate_v3_hw(struct hisi_hba *hisi_hba, int phy_no,
+ struct sas_phy_linkrates *r)
+ {
+- u32 prog_phy_link_rate =
+- hisi_sas_phy_read32(hisi_hba, phy_no, PROG_PHY_LINK_RATE);
+ struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
+ struct asd_sas_phy *sas_phy = &phy->sas_phy;
+- int i;
+ enum sas_linkrate min, max;
+- u32 rate_mask = 0;
++ u32 prog_phy_link_rate = 0x800;
+
+ if (r->maximum_linkrate == SAS_LINK_RATE_UNKNOWN) {
+ max = sas_phy->phy->maximum_linkrate;
+@@ -1888,14 +1900,7 @@ static void phy_set_linkrate_v3_hw(struct hisi_hba *hisi_hba, int phy_no,
+
+ sas_phy->phy->maximum_linkrate = max;
+ sas_phy->phy->minimum_linkrate = min;
+-
+- max -= SAS_LINK_RATE_1_5_GBPS;
+-
+- for (i = 0; i <= max; i++)
+- rate_mask |= 1 << (i * 2);
+-
+- prog_phy_link_rate &= ~0xff;
+- prog_phy_link_rate |= rate_mask;
++ prog_phy_link_rate |= hisi_sas_get_prog_phy_linkrate_mask(max);
+
+ disable_phy_v3_hw(hisi_hba, phy_no);
+ msleep(100);
+
diff --git a/patches.drivers/scsi-hisi_sas-update-ras-feature-for-later-revision-of-v3-hw.patch b/patches.drivers/scsi-hisi_sas-update-ras-feature-for-later-revision-of-v3-hw.patch
new file mode 100644
index 0000000000..ef34ab6448
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-update-ras-feature-for-later-revision-of-v3-hw.patch
@@ -0,0 +1,158 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Sat, 24 Mar 2018 00:05:09 +0800
+Subject: scsi: hisi_sas: update RAS feature for later revision of v3 HW
+Git-commit: 61573630918bf29a1974e08ef5d4b8889fb9dd7f
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+There is an modification for later revision of v3 hw. More HW errors are
+reported through RAS interrupt. These errors were originally reported
+only through MSI.
+
+When report to RAS, some combinations are done to port AXI errors and
+FIFO OMIT errors. For example, each port has 4 AXI errors, and they are
+combined to one when report to RAS.
+
+This patch does two things:
+
+1. Enable RAS interrupt of these errors and handle them in PCI
+ error handlers.
+
+2. Disable MSI interrupts of these errors for this later revision hw.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 60 ++++++++++++++++++++++++++++++++--
+ 1 file changed, 58 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 6f3e5ba6b472..df5414a0bdd9 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -216,6 +216,9 @@
+ #define SAS_RAS_INTR1 (RAS_BASE + 0x04)
+ #define SAS_RAS_INTR0_MASK (RAS_BASE + 0x08)
+ #define SAS_RAS_INTR1_MASK (RAS_BASE + 0x0c)
++#define CFG_SAS_RAS_INTR_MASK (RAS_BASE + 0x1c)
++#define SAS_RAS_INTR2 (RAS_BASE + 0x20)
++#define SAS_RAS_INTR2_MASK (RAS_BASE + 0x24)
+
+ /* HW dma structures */
+ /* Delivery queue header */
+@@ -392,6 +395,7 @@ static u32 hisi_sas_phy_read32(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;
+
+ /* Global registers init */
+@@ -409,7 +413,10 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
+ 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, 0xfffe20ff);
++ if (pdev->revision >= 0x21)
++ hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0xffff7fff);
++ else
++ hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0xfffe20ff);
+ 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);
+@@ -428,7 +435,12 @@ 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, 0xff87ffff);
++ if (pdev->revision >= 0x21)
++ hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK,
++ 0xffffffff);
++ else
++ hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK,
++ 0xff87ffff);
+ 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);
+@@ -503,6 +515,8 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
+ /* RAS registers init */
+ hisi_sas_write32(hisi_hba, SAS_RAS_INTR0_MASK, 0x0);
+ hisi_sas_write32(hisi_hba, SAS_RAS_INTR1_MASK, 0x0);
++ hisi_sas_write32(hisi_hba, SAS_RAS_INTR2_MASK, 0x0);
++ hisi_sas_write32(hisi_hba, CFG_SAS_RAS_INTR_MASK, 0x0);
+ }
+
+ static void config_phy_opt_mode_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
+@@ -1319,6 +1333,13 @@ static irqreturn_t int_chnl_int_v3_hw(int irq_no, void *p)
+ CHL_INT1);
+ u32 irq_value2 = hisi_sas_phy_read32(hisi_hba, phy_no,
+ CHL_INT2);
++ u32 irq_msk1 = hisi_sas_phy_read32(hisi_hba, phy_no,
++ CHL_INT1_MSK);
++ u32 irq_msk2 = hisi_sas_phy_read32(hisi_hba, phy_no,
++ CHL_INT2_MSK);
++
++ irq_value1 &= ~irq_msk1;
++ irq_value2 &= ~irq_msk2;
+
+ if ((irq_msk & (4 << (phy_no * 4))) &&
+ irq_value1) {
+@@ -1448,6 +1469,7 @@ static irqreturn_t fatal_axi_int_v3_hw(int irq_no, void *p)
+ hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, irq_msk | 0x1df00);
+
+ irq_value = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
++ irq_value &= ~irq_msk;
+
+ for (i = 0; i < ARRAY_SIZE(fatal_axi_error); i++) {
+ const struct hisi_sas_hw_error *error = &fatal_axi_error[i];
+@@ -2222,6 +2244,29 @@ static const struct hisi_sas_hw_error sas_ras_intr1_nfe[] = {
+ { .irq_msk = BIT(31), .msg = "DMAC7_RX_POISON" },
+ };
+
++static const struct hisi_sas_hw_error sas_ras_intr2_nfe[] = {
++ { .irq_msk = BIT(0), .msg = "DMAC0_AXI_BUS_ERR" },
++ { .irq_msk = BIT(1), .msg = "DMAC1_AXI_BUS_ERR" },
++ { .irq_msk = BIT(2), .msg = "DMAC2_AXI_BUS_ERR" },
++ { .irq_msk = BIT(3), .msg = "DMAC3_AXI_BUS_ERR" },
++ { .irq_msk = BIT(4), .msg = "DMAC4_AXI_BUS_ERR" },
++ { .irq_msk = BIT(5), .msg = "DMAC5_AXI_BUS_ERR" },
++ { .irq_msk = BIT(6), .msg = "DMAC6_AXI_BUS_ERR" },
++ { .irq_msk = BIT(7), .msg = "DMAC7_AXI_BUS_ERR" },
++ { .irq_msk = BIT(8), .msg = "DMAC0_FIFO_OMIT_ERR" },
++ { .irq_msk = BIT(9), .msg = "DMAC1_FIFO_OMIT_ERR" },
++ { .irq_msk = BIT(10), .msg = "DMAC2_FIFO_OMIT_ERR" },
++ { .irq_msk = BIT(11), .msg = "DMAC3_FIFO_OMIT_ERR" },
++ { .irq_msk = BIT(12), .msg = "DMAC4_FIFO_OMIT_ERR" },
++ { .irq_msk = BIT(13), .msg = "DMAC5_FIFO_OMIT_ERR" },
++ { .irq_msk = BIT(14), .msg = "DMAC6_FIFO_OMIT_ERR" },
++ { .irq_msk = BIT(15), .msg = "DMAC7_FIFO_OMIT_ERR" },
++ { .irq_msk = BIT(16), .msg = "HGC_RLSE_SLOT_UNMATCH" },
++ { .irq_msk = BIT(17), .msg = "HGC_LM_ADD_FCH_LIST_ERR" },
++ { .irq_msk = BIT(18), .msg = "HGC_AXI_BUS_ERR" },
++ { .irq_msk = BIT(19), .msg = "HGC_FIFO_OMIT_ERR" },
++};
++
+ static bool process_non_fatal_error_v3_hw(struct hisi_hba *hisi_hba)
+ {
+ struct device *dev = hisi_hba->dev;
+@@ -2252,6 +2297,17 @@ static bool process_non_fatal_error_v3_hw(struct hisi_hba *hisi_hba)
+ }
+ hisi_sas_write32(hisi_hba, SAS_RAS_INTR1, irq_value);
+
++ irq_value = hisi_sas_read32(hisi_hba, SAS_RAS_INTR2);
++ for (i = 0; i < ARRAY_SIZE(sas_ras_intr2_nfe); i++) {
++ ras_error = &sas_ras_intr2_nfe[i];
++ if (ras_error->irq_msk & irq_value) {
++ dev_warn(dev, "SAS_RAS_INTR2: %s(irq_value=0x%x) found.\n",
++ ras_error->msg, irq_value);
++ need_reset = true;
++ }
++ }
++ hisi_sas_write32(hisi_hba, SAS_RAS_INTR2, irq_value);
++
+ return need_reset;
+ }
+
+
diff --git a/patches.drivers/scsi-hisi_sas-use-an-general-way-to-delay-phy-work.patch b/patches.drivers/scsi-hisi_sas-use-an-general-way-to-delay-phy-work.patch
new file mode 100644
index 0000000000..01a66f7c85
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-use-an-general-way-to-delay-phy-work.patch
@@ -0,0 +1,142 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Sat, 9 Dec 2017 01:16:44 +0800
+Subject: scsi: hisi_sas: use an general way to delay PHY work
+Git-commit: e537b62b0796042e1ab66657c4dab662d19e9f0b
+Patch-mainline: v4.16-rc1
+References: FATE#326253
+
+Use an general way to do delay work for a PHY. Then it will be easier to add
+new delayed work for a PHY in future.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas.h | 9 ++++++++-
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 22 ++++++++++++++++++++--
+ drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 2 +-
+ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 4 ++--
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 2 +-
+ 5 files changed, 32 insertions(+), 7 deletions(-)
+
+--- a/drivers/scsi/hisi_sas/hisi_sas.h
++++ b/drivers/scsi/hisi_sas/hisi_sas.h
+@@ -124,13 +124,18 @@ enum hisi_sas_bit_err_type {
+ HISI_SAS_ERR_MULTI_BIT_ECC = 0x1,
+ };
+
++enum hisi_sas_phy_event {
++ HISI_PHYE_PHY_UP = 0U,
++ HISI_PHYES_NUM,
++};
++
+ struct hisi_sas_phy {
++ struct work_struct works[HISI_PHYES_NUM];
+ struct hisi_hba *hisi_hba;
+ struct hisi_sas_port *port;
+ struct asd_sas_phy sas_phy;
+ struct sas_identify identify;
+ struct timer_list timer;
+- struct work_struct phyup_ws;
+ u64 port_id; /* from hw */
+ u64 dev_sas_addr;
+ u64 frame_rcvd_size;
+@@ -454,4 +459,6 @@ extern void hisi_sas_init_mem(struct his
+ 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 bool hisi_sas_notify_phy_event(struct hisi_sas_phy *phy,
++ enum hisi_sas_phy_event event);
+ #endif
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -622,7 +622,7 @@ static int hisi_sas_scan_finished(struct
+ static void hisi_sas_phyup_work(struct work_struct *work)
+ {
+ struct hisi_sas_phy *phy =
+- container_of(work, struct hisi_sas_phy, phyup_ws);
++ container_of(work, typeof(*phy), works[HISI_PHYE_PHY_UP]);
+ struct hisi_hba *hisi_hba = phy->hisi_hba;
+ struct asd_sas_phy *sas_phy = &phy->sas_phy;
+ int phy_no = sas_phy->id;
+@@ -631,10 +631,27 @@ static void hisi_sas_phyup_work(struct w
+ hisi_sas_bytes_dmaed(hisi_hba, phy_no);
+ }
+
++static const work_func_t hisi_sas_phye_fns[HISI_PHYES_NUM] = {
++ [HISI_PHYE_PHY_UP] = hisi_sas_phyup_work,
++};
++
++bool hisi_sas_notify_phy_event(struct hisi_sas_phy *phy,
++ enum hisi_sas_phy_event event)
++{
++ struct hisi_hba *hisi_hba = phy->hisi_hba;
++
++ if (WARN_ON(event >= HISI_PHYES_NUM))
++ return false;
++
++ return queue_work(hisi_hba->wq, &phy->works[event]);
++}
++EXPORT_SYMBOL_GPL(hisi_sas_notify_phy_event);
++
+ static void hisi_sas_phy_init(struct hisi_hba *hisi_hba, int phy_no)
+ {
+ struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
+ struct asd_sas_phy *sas_phy = &phy->sas_phy;
++ int i;
+
+ phy->hisi_hba = hisi_hba;
+ phy->port = NULL;
+@@ -653,7 +670,8 @@ static void hisi_sas_phy_init(struct his
+ sas_phy->ha = (struct sas_ha_struct *)hisi_hba->shost->hostdata;
+ sas_phy->lldd_phy = phy;
+
+- INIT_WORK(&phy->phyup_ws, hisi_sas_phyup_work);
++ for (i = 0; i < HISI_PHYES_NUM; i++)
++ INIT_WORK(&phy->works[i], hisi_sas_phye_fns[i]);
+ }
+
+ static void hisi_sas_port_notify_formed(struct asd_sas_phy *sas_phy)
+--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+@@ -1482,7 +1482,7 @@ static irqreturn_t int_phyup_v1_hw(int i
+ else if (phy->identify.device_type != SAS_PHY_UNUSED)
+ phy->identify.target_port_protocols =
+ SAS_PROTOCOL_SMP;
+- queue_work(hisi_hba->wq, &phy->phyup_ws);
++ hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP);
+
+ end:
+ hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2,
+--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+@@ -2710,7 +2710,7 @@ static int phy_up_v2_hw(int phy_no, stru
+ if (!timer_pending(&hisi_hba->timer))
+ set_link_timer_quirk(hisi_hba);
+ }
+- queue_work(hisi_hba->wq, &phy->phyup_ws);
++ hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP);
+
+ end:
+ hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
+@@ -3264,7 +3264,7 @@ static irqreturn_t sata_int_v2_hw(int ir
+ phy->identify.device_type = SAS_SATA_DEV;
+ phy->frame_rcvd_size = sizeof(struct dev_to_host_fis);
+ phy->identify.target_port_protocols = SAS_PROTOCOL_SATA;
+- queue_work(hisi_hba->wq, &phy->phyup_ws);
++ hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP);
+
+ end:
+ hisi_sas_write32(hisi_hba, ENT_INT_SRC1 + offset, ent_tmp);
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -1192,7 +1192,7 @@ static int phy_up_v3_hw(int phy_no, stru
+
+ phy->port_id = port_id;
+ phy->phy_attached = 1;
+- queue_work(hisi_hba->wq, &phy->phyup_ws);
++ hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP);
+
+ end:
+ hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
diff --git a/patches.drivers/scsi-hisi_sas-use-device-lock-to-protect-slot-alloc-free.patch b/patches.drivers/scsi-hisi_sas-use-device-lock-to-protect-slot-alloc-free.patch
new file mode 100644
index 0000000000..151f162f55
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-use-device-lock-to-protect-slot-alloc-free.patch
@@ -0,0 +1,246 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Wed, 9 May 2018 23:10:49 +0800
+Subject: scsi: hisi_sas: Use device lock to protect slot alloc/free
+Git-commit: e85d93b21267fff56110e3a258b9fad8adbfbce3
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+The IPTT of a slot is unique, and we currently use hisi_hba lock to
+protect it.
+
+Now slot is managed on hisi_sas_device.list, so use DQ lock to protect
+for allocating and freeing the slot.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 56 ++++++++++------------------------
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 3 --
+ 2 files changed, 16 insertions(+), 43 deletions(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index bf374a795962..a451625b8253 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -214,6 +214,8 @@ static void hisi_sas_slot_index_init(struct hisi_hba *hisi_hba)
+ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
+ struct hisi_sas_slot *slot)
+ {
++ struct hisi_sas_dq *dq = &hisi_hba->dq[slot->dlvry_queue];
++ unsigned long flags;
+
+ if (task) {
+ struct device *dev = hisi_hba->dev;
+@@ -233,11 +235,15 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
+ if (slot->buf)
+ dma_pool_free(hisi_hba->buffer_pool, slot->buf, slot->buf_dma);
+
++ spin_lock_irqsave(&dq->lock, flags);
+ list_del_init(&slot->entry);
++ spin_unlock_irqrestore(&dq->lock, flags);
+ slot->buf = NULL;
+ slot->task = NULL;
+ slot->port = NULL;
++ spin_lock_irqsave(&hisi_hba->lock, flags);
+ hisi_sas_slot_index_free(hisi_hba, slot->idx);
++ spin_unlock_irqrestore(&hisi_hba->lock, flags);
+
+ /* slot memory is fully zeroed when it is reused */
+ }
+@@ -286,7 +292,6 @@ static void hisi_sas_slot_abort(struct work_struct *work)
+ struct scsi_lun lun;
+ struct device *dev = hisi_hba->dev;
+ int tag = abort_slot->idx;
+- unsigned long flags;
+
+ if (!(task->task_proto & SAS_PROTOCOL_SSP)) {
+ dev_err(dev, "cannot abort slot for non-ssp task\n");
+@@ -300,9 +305,7 @@ static void hisi_sas_slot_abort(struct work_struct *work)
+ hisi_sas_debug_issue_ssp_tmf(task->dev, lun.scsi_lun, &tmf_task);
+ out:
+ /* Do cleanup for this task */
+- spin_lock_irqsave(&hisi_hba->lock, flags);
+ hisi_sas_slot_task_free(hisi_hba, task, abort_slot);
+- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+ if (task->task_done)
+ task->task_done(task);
+ }
+@@ -471,9 +474,9 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq *dq,
+ break;
+ }
+
+- spin_lock_irqsave(&hisi_hba->lock, flags);
++ spin_lock_irqsave(&dq->lock, flags);
+ list_add_tail(&slot->entry, &sas_dev->list);
+- spin_unlock_irqrestore(&hisi_hba->lock, flags);
++ spin_unlock_irqrestore(&dq->lock, flags);
+ spin_lock_irqsave(&task->task_state_lock, flags);
+ task->task_state_flags |= SAS_TASK_AT_INITIATOR;
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
+@@ -1047,7 +1050,6 @@ static int hisi_sas_softreset_ata_disk(struct domain_device *device)
+ struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
+ struct device *dev = hisi_hba->dev;
+ int s = sizeof(struct host_to_dev_fis);
+- unsigned long flags;
+
+ ata_for_each_link(link, ap, EDGE) {
+ int pmp = sata_srst_pmp(link);
+@@ -1072,11 +1074,8 @@ static int hisi_sas_softreset_ata_disk(struct domain_device *device)
+ dev_err(dev, "ata disk reset failed\n");
+ }
+
+- if (rc == TMF_RESP_FUNC_COMPLETE) {
+- spin_lock_irqsave(&hisi_hba->lock, flags);
++ if (rc == TMF_RESP_FUNC_COMPLETE)
+ hisi_sas_release_task(hisi_hba, device);
+- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+- }
+
+ return rc;
+ }
+@@ -1173,7 +1172,6 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
+ struct device *dev = hisi_hba->dev;
+ struct Scsi_Host *shost = hisi_hba->shost;
+ u32 old_state, state;
+- unsigned long flags;
+ int rc;
+
+ if (!hisi_hba->hw->soft_reset)
+@@ -1197,9 +1195,7 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
+ scsi_unblock_requests(shost);
+ goto out;
+ }
+- spin_lock_irqsave(&hisi_hba->lock, flags);
+ hisi_sas_release_tasks(hisi_hba);
+- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+
+ clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
+
+@@ -1274,11 +1270,8 @@ static int hisi_sas_abort_task(struct sas_task *task)
+ * will have already been completed
+ */
+ if (rc == TMF_RESP_FUNC_COMPLETE && rc2 != TMF_RESP_FUNC_SUCC) {
+- if (task->lldd_task) {
+- spin_lock_irqsave(&hisi_hba->lock, flags);
++ if (task->lldd_task)
+ hisi_sas_do_release_task(hisi_hba, task, slot);
+- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+- }
+ }
+ } else if (task->task_proto & SAS_PROTOCOL_SATA ||
+ task->task_proto & SAS_PROTOCOL_STP) {
+@@ -1300,11 +1293,8 @@ static int hisi_sas_abort_task(struct sas_task *task)
+ rc = hisi_sas_internal_task_abort(hisi_hba, device,
+ HISI_SAS_INT_ABT_CMD, tag);
+ if (((rc < 0) || (rc == TMF_RESP_FUNC_FAILED)) &&
+- task->lldd_task) {
+- spin_lock_irqsave(&hisi_hba->lock, flags);
++ task->lldd_task)
+ hisi_sas_do_release_task(hisi_hba, task, slot);
+- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+- }
+ }
+
+ out:
+@@ -1319,7 +1309,6 @@ static int hisi_sas_abort_task_set(struct domain_device *device, u8 *lun)
+ struct device *dev = hisi_hba->dev;
+ struct hisi_sas_tmf_task tmf_task;
+ int rc = TMF_RESP_FUNC_FAILED;
+- unsigned long flags;
+
+ rc = hisi_sas_internal_task_abort(hisi_hba, device,
+ HISI_SAS_INT_ABT_DEV, 0);
+@@ -1332,11 +1321,8 @@ static int hisi_sas_abort_task_set(struct domain_device *device, u8 *lun)
+ tmf_task.tmf = TMF_ABORT_TASK_SET;
+ rc = hisi_sas_debug_issue_ssp_tmf(device, lun, &tmf_task);
+
+- if (rc == TMF_RESP_FUNC_COMPLETE) {
+- spin_lock_irqsave(&hisi_hba->lock, flags);
++ if (rc == TMF_RESP_FUNC_COMPLETE)
+ hisi_sas_release_task(hisi_hba, device);
+- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+- }
+
+ return rc;
+ }
+@@ -1369,7 +1355,6 @@ static int hisi_sas_I_T_nexus_reset(struct domain_device *device)
+ struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
+ struct device *dev = hisi_hba->dev;
+ int rc = TMF_RESP_FUNC_FAILED;
+- unsigned long flags;
+
+ if (sas_dev->dev_status != HISI_SAS_DEV_EH)
+ return TMF_RESP_FUNC_FAILED;
+@@ -1385,11 +1370,9 @@ static int hisi_sas_I_T_nexus_reset(struct domain_device *device)
+
+ rc = hisi_sas_debug_I_T_nexus_reset(device);
+
+- if ((rc == TMF_RESP_FUNC_COMPLETE) || (rc == -ENODEV)) {
+- spin_lock_irqsave(&hisi_hba->lock, flags);
++ if ((rc == TMF_RESP_FUNC_COMPLETE) || (rc == -ENODEV))
+ hisi_sas_release_task(hisi_hba, device);
+- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+- }
++
+ return rc;
+ }
+
+@@ -1398,7 +1381,6 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun)
+ struct hisi_sas_device *sas_dev = device->lldd_dev;
+ struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
+ struct device *dev = hisi_hba->dev;
+- unsigned long flags;
+ int rc = TMF_RESP_FUNC_FAILED;
+
+ sas_dev->dev_status = HISI_SAS_DEV_EH;
+@@ -1418,11 +1400,8 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun)
+
+ rc = sas_phy_reset(phy, 1);
+
+- if (rc == 0) {
+- spin_lock_irqsave(&hisi_hba->lock, flags);
++ if (rc == 0)
+ hisi_sas_release_task(hisi_hba, device);
+- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+- }
+ sas_put_local_phy(phy);
+ } else {
+ struct hisi_sas_tmf_task tmf_task = { .tmf = TMF_LU_RESET };
+@@ -1436,11 +1415,8 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun)
+ hisi_sas_dereg_device(hisi_hba, device);
+
+ rc = hisi_sas_debug_issue_ssp_tmf(device, lun, &tmf_task);
+- if (rc == TMF_RESP_FUNC_COMPLETE) {
+- spin_lock_irqsave(&hisi_hba->lock, flags);
++ if (rc == TMF_RESP_FUNC_COMPLETE)
+ hisi_sas_release_task(hisi_hba, device);
+- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+- }
+ }
+ out:
+ if (rc != TMF_RESP_FUNC_COMPLETE)
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+index 56f1046b244c..c013673ee8ac 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -2373,7 +2373,6 @@ static int hisi_sas_v3_suspend(struct pci_dev *pdev, pm_message_t state)
+ u32 device_state, status;
+ int rc;
+ u32 reg_val;
+- unsigned long flags;
+
+ if (!pdev->pm_cap) {
+ dev_err(dev, "PCI PM not supported\n");
+@@ -2418,9 +2417,7 @@ static int hisi_sas_v3_suspend(struct pci_dev *pdev, pm_message_t state)
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, device_state);
+
+- spin_lock_irqsave(&hisi_hba->lock, flags);
+ hisi_sas_release_tasks(hisi_hba);
+- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+
+ sas_suspend_ha(sha);
+ return 0;
+
diff --git a/patches.drivers/scsi-hisi_sas-use-dma_zalloc_coherent.patch b/patches.drivers/scsi-hisi_sas-use-dma_zalloc_coherent.patch
new file mode 100644
index 0000000000..c715c9b760
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-use-dma_zalloc_coherent.patch
@@ -0,0 +1,38 @@
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Sat, 24 Mar 2018 00:05:11 +0800
+Subject: scsi: hisi_sas: use dma_zalloc_coherent()
+Git-commit: 4f4e21b8ff3e706f79e1adb2a475c3f5ee6b57f9
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+This is a warning coming from Coccinelle, and need to use new interface
+dma_zalloc_coherent() instead of dma_alloc_coherent()/memset().
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ 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 a21679574142..9563dfa72181 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -1822,13 +1822,11 @@ int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost)
+ goto err_out;
+
+ s = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct);
+- hisi_hba->itct = dma_alloc_coherent(dev, s, &hisi_hba->itct_dma,
++ hisi_hba->itct = dma_zalloc_coherent(dev, s, &hisi_hba->itct_dma,
+ GFP_KERNEL);
+ if (!hisi_hba->itct)
+ goto err_out;
+
+- memset(hisi_hba->itct, 0, s);
+-
+ hisi_hba->slot_info = devm_kcalloc(dev, max_command_entries,
+ sizeof(struct hisi_sas_slot),
+ GFP_KERNEL);
+
diff --git a/patches.drivers/scsi-hisi_sas-workaround-a-v3-hw-hilink-bug.patch b/patches.drivers/scsi-hisi_sas-workaround-a-v3-hw-hilink-bug.patch
new file mode 100644
index 0000000000..ad547e9e34
--- /dev/null
+++ b/patches.drivers/scsi-hisi_sas-workaround-a-v3-hw-hilink-bug.patch
@@ -0,0 +1,91 @@
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+Date: Wed, 2 May 2018 23:56:34 +0800
+Subject: scsi: hisi_sas: workaround a v3 hw hilink bug
+Git-commit: f70c1251deb5ab17dec70119c03f2428288ebada
+Patch-mainline: v4.18-rc1
+References: FATE#326253
+
+There is an SoC bug of v3 hw development version. When hot- unplugging a
+directly attached disk, the PHY down interrupt may not happen. It is
+very easy to appear on some boards.
+
+When this issue occurs, the controller will receive many invalid dword
+frames, and the "alos" fields of register HILINK_ERR_DFX can indicate
+that disk was unplugged.
+
+As an workaround solution, this patch detects this issue in the channel
+interrupt, and workaround it by following steps:
+
+ - Disable the PHY
+ - Clear error code and interrupt
+ - Enable the PHY
+
+Then the HW will reissue PHY down interrupt.
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 25 ++++++++++++++++++++++++-
+ 1 file changed, 24 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 28bb71e3b093..492c3beea3d5 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -106,6 +106,7 @@
+ #define COMPL_Q_0_RD_PTR 0x4f0
+ #define AWQOS_AWCACHE_CFG 0xc84
+ #define ARQOS_ARCACHE_CFG 0xc88
++#define HILINK_ERR_DFX 0xe04
+
+ /* phy registers requiring init */
+ #define PORT_BASE (0x2000)
+@@ -167,6 +168,7 @@
+ #define CHL_INT1_DMAC_RX_AXI_RD_ERR_OFF 22
+ #define CHL_INT2 (PORT_BASE + 0x1bc)
+ #define CHL_INT2_SL_IDAF_TOUT_CONF_OFF 0
++#define CHL_INT2_RX_INVLD_DW_OFF 30
+ #define CHL_INT2_STP_LINK_TIMEOUT_OFF 31
+ #define CHL_INT0_MSK (PORT_BASE + 0x1c0)
+ #define CHL_INT1_MSK (PORT_BASE + 0x1c4)
+@@ -1345,6 +1347,7 @@ static irqreturn_t int_chnl_int_v3_hw(int irq_no, void *p)
+ {
+ struct hisi_hba *hisi_hba = p;
+ struct device *dev = hisi_hba->dev;
++ struct pci_dev *pci_dev = hisi_hba->pci_dev;
+ u32 irq_msk;
+ int phy_no = 0;
+
+@@ -1410,8 +1413,28 @@ static irqreturn_t int_chnl_int_v3_hw(int irq_no, void *p)
+
+ hisi_sas_phy_write32(hisi_hba, phy_no,
+ CHL_INT2, irq_value2);
+- }
+
++ if ((irq_value2 & BIT(CHL_INT2_RX_INVLD_DW_OFF)) &&
++ (pci_dev->revision == 0x20)) {
++ u32 reg_value;
++ int rc;
++
++ rc = hisi_sas_read32_poll_timeout_atomic(
++ HILINK_ERR_DFX, reg_value,
++ !((reg_value >> 8) & BIT(phy_no)),
++ 1000, 10000);
++ if (rc) {
++ disable_phy_v3_hw(hisi_hba, phy_no);
++ hisi_sas_phy_write32(hisi_hba, phy_no,
++ CHL_INT2,
++ BIT(CHL_INT2_RX_INVLD_DW_OFF));
++ hisi_sas_phy_read32(hisi_hba, phy_no,
++ ERR_CNT_INVLD_DW);
++ mdelay(1);
++ enable_phy_v3_hw(hisi_hba, phy_no);
++ }
++ }
++ }
+
+ if (irq_msk & (2 << (phy_no * 4)) && irq_value0) {
+ hisi_sas_phy_write32(hisi_hba, phy_no,
+
diff --git a/patches.drivers/scsi-lpfc-Add-Buffer-overflow-check-when-nvme_info-l.patch b/patches.drivers/scsi-lpfc-Add-Buffer-overflow-check-when-nvme_info-l.patch
new file mode 100644
index 0000000000..8948bcc500
--- /dev/null
+++ b/patches.drivers/scsi-lpfc-Add-Buffer-overflow-check-when-nvme_info-l.patch
@@ -0,0 +1,550 @@
+From: James Smart <jsmart2021@gmail.com>
+Date: Tue, 26 Jun 2018 08:24:22 -0700
+Subject: [PATCH] scsi: lpfc: Add Buffer overflow check, when nvme_info larger
+ than PAGE_SIZE
+References: bsc#1102658
+Git-commit: afff0d2321ea2beb6f4dcd029d4667acf73dec25
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
+Patch-mainline: Queued in subsystem maintainer repository
+
+Kernel crashes during fill_read_buffer when nvme_info sysfs file read.
+
+With multiple NVME targets, approx 40, nvme_info may grow larger than
+PAGE_SIZE bytes. snprintf(buf + len, PAGE_SIZE - len, ...) logic is flawed
+as PAGE_SIZE - len can be < 0 and is accepted by snprintf. This results in
+buffer overflow, and is detected with check from dev_attr_show and
+fill_read_buffer.
+
+Change to use scnprintf to a tmp array, before calling strlcat to ensure no
+buffer overflow over PAGE_SIZE bytes.
+
+Message "6314" created as a new message indicating when there is more nvme
+info, but is truncated to fit within PAGE_SIZE bytes.
+
+Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
+Signed-off-by: James Smart <james.smart@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/lpfc/lpfc_attr.c | 432 +++++++++++++++++++++++++-----------------
+ 1 file changed, 257 insertions(+), 175 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
+index fdabba7b0282..0f8ab3ffb010 100644
+--- a/drivers/scsi/lpfc/lpfc_attr.c
++++ b/drivers/scsi/lpfc/lpfc_attr.c
+@@ -64,6 +64,9 @@
+ #define LPFC_MIN_MRQ_POST 512
+ #define LPFC_MAX_MRQ_POST 2048
+
++#define LPFC_MAX_NVME_INFO_TMP_LEN 100
++#define LPFC_NVME_INFO_MORE_STR "\nCould be more info...\n"
++
+ /*
+ * Write key size should be multiple of 4. If write key is changed
+ * make sure that library write key is also changed.
+@@ -158,14 +161,15 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
+ char *statep;
+ int i;
+ int len = 0;
++ char tmp[LPFC_MAX_NVME_INFO_TMP_LEN] = {0};
+
+ if (!(phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME)) {
+- len += snprintf(buf, PAGE_SIZE, "NVME Disabled\n");
++ len = scnprintf(buf, PAGE_SIZE, "NVME Disabled\n");
+ return len;
+ }
+ if (phba->nvmet_support) {
+ if (!phba->targetport) {
+- len = snprintf(buf, PAGE_SIZE,
++ len = scnprintf(buf, PAGE_SIZE,
+ "NVME Target: x%llx is not allocated\n",
+ wwn_to_u64(vport->fc_portname.u.wwn));
+ return len;
+@@ -175,135 +179,169 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
+ statep = "REGISTERED";
+ else
+ statep = "INIT";
+- len += snprintf(buf + len, PAGE_SIZE - len,
+- "NVME Target Enabled State %s\n",
+- statep);
+- len += snprintf(buf + len, PAGE_SIZE - len,
+- "%s%d WWPN x%llx WWNN x%llx DID x%06x\n",
+- "NVME Target: lpfc",
+- phba->brd_no,
+- wwn_to_u64(vport->fc_portname.u.wwn),
+- wwn_to_u64(vport->fc_nodename.u.wwn),
+- phba->targetport->port_id);
+-
+- len += snprintf(buf + len, PAGE_SIZE - len,
+- "\nNVME Target: Statistics\n");
++ scnprintf(tmp, sizeof(tmp),
++ "NVME Target Enabled State %s\n",
++ statep);
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
++
++ scnprintf(tmp, sizeof(tmp),
++ "%s%d WWPN x%llx WWNN x%llx DID x%06x\n",
++ "NVME Target: lpfc",
++ phba->brd_no,
++ wwn_to_u64(vport->fc_portname.u.wwn),
++ wwn_to_u64(vport->fc_nodename.u.wwn),
++ phba->targetport->port_id);
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
++
++ if (strlcat(buf, "\nNVME Target: Statistics\n", PAGE_SIZE)
++ >= PAGE_SIZE)
++ goto buffer_done;
++
+ tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
+- len += snprintf(buf+len, PAGE_SIZE-len,
+- "LS: Rcv %08x Drop %08x Abort %08x\n",
+- atomic_read(&tgtp->rcv_ls_req_in),
+- atomic_read(&tgtp->rcv_ls_req_drop),
+- atomic_read(&tgtp->xmt_ls_abort));
++ scnprintf(tmp, sizeof(tmp),
++ "LS: Rcv %08x Drop %08x Abort %08x\n",
++ atomic_read(&tgtp->rcv_ls_req_in),
++ atomic_read(&tgtp->rcv_ls_req_drop),
++ atomic_read(&tgtp->xmt_ls_abort));
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
++
+ if (atomic_read(&tgtp->rcv_ls_req_in) !=
+ atomic_read(&tgtp->rcv_ls_req_out)) {
+- len += snprintf(buf+len, PAGE_SIZE-len,
+- "Rcv LS: in %08x != out %08x\n",
+- atomic_read(&tgtp->rcv_ls_req_in),
+- atomic_read(&tgtp->rcv_ls_req_out));
++ scnprintf(tmp, sizeof(tmp),
++ "Rcv LS: in %08x != out %08x\n",
++ atomic_read(&tgtp->rcv_ls_req_in),
++ atomic_read(&tgtp->rcv_ls_req_out));
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
+ }
+
+- len += snprintf(buf+len, PAGE_SIZE-len,
+- "LS: Xmt %08x Drop %08x Cmpl %08x\n",
+- atomic_read(&tgtp->xmt_ls_rsp),
+- atomic_read(&tgtp->xmt_ls_drop),
+- atomic_read(&tgtp->xmt_ls_rsp_cmpl));
+-
+- len += snprintf(buf + len, PAGE_SIZE - len,
+- "LS: RSP Abort %08x xb %08x Err %08x\n",
+- atomic_read(&tgtp->xmt_ls_rsp_aborted),
+- atomic_read(&tgtp->xmt_ls_rsp_xb_set),
+- atomic_read(&tgtp->xmt_ls_rsp_error));
+-
+- len += snprintf(buf+len, PAGE_SIZE-len,
+- "FCP: Rcv %08x Defer %08x Release %08x "
+- "Drop %08x\n",
+- atomic_read(&tgtp->rcv_fcp_cmd_in),
+- atomic_read(&tgtp->rcv_fcp_cmd_defer),
+- atomic_read(&tgtp->xmt_fcp_release),
+- atomic_read(&tgtp->rcv_fcp_cmd_drop));
++ scnprintf(tmp, sizeof(tmp),
++ "LS: Xmt %08x Drop %08x Cmpl %08x\n",
++ atomic_read(&tgtp->xmt_ls_rsp),
++ atomic_read(&tgtp->xmt_ls_drop),
++ atomic_read(&tgtp->xmt_ls_rsp_cmpl));
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
++
++ scnprintf(tmp, sizeof(tmp),
++ "LS: RSP Abort %08x xb %08x Err %08x\n",
++ atomic_read(&tgtp->xmt_ls_rsp_aborted),
++ atomic_read(&tgtp->xmt_ls_rsp_xb_set),
++ atomic_read(&tgtp->xmt_ls_rsp_error));
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
++
++ scnprintf(tmp, sizeof(tmp),
++ "FCP: Rcv %08x Defer %08x Release %08x "
++ "Drop %08x\n",
++ atomic_read(&tgtp->rcv_fcp_cmd_in),
++ atomic_read(&tgtp->rcv_fcp_cmd_defer),
++ atomic_read(&tgtp->xmt_fcp_release),
++ atomic_read(&tgtp->rcv_fcp_cmd_drop));
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
+
+ if (atomic_read(&tgtp->rcv_fcp_cmd_in) !=
+ atomic_read(&tgtp->rcv_fcp_cmd_out)) {
+- len += snprintf(buf+len, PAGE_SIZE-len,
+- "Rcv FCP: in %08x != out %08x\n",
+- atomic_read(&tgtp->rcv_fcp_cmd_in),
+- atomic_read(&tgtp->rcv_fcp_cmd_out));
++ scnprintf(tmp, sizeof(tmp),
++ "Rcv FCP: in %08x != out %08x\n",
++ atomic_read(&tgtp->rcv_fcp_cmd_in),
++ atomic_read(&tgtp->rcv_fcp_cmd_out));
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
+ }
+
+- len += snprintf(buf+len, PAGE_SIZE-len,
+- "FCP Rsp: RD %08x rsp %08x WR %08x rsp %08x "
+- "drop %08x\n",
+- atomic_read(&tgtp->xmt_fcp_read),
+- atomic_read(&tgtp->xmt_fcp_read_rsp),
+- atomic_read(&tgtp->xmt_fcp_write),
+- atomic_read(&tgtp->xmt_fcp_rsp),
+- atomic_read(&tgtp->xmt_fcp_drop));
+-
+- len += snprintf(buf+len, PAGE_SIZE-len,
+- "FCP Rsp Cmpl: %08x err %08x drop %08x\n",
+- atomic_read(&tgtp->xmt_fcp_rsp_cmpl),
+- atomic_read(&tgtp->xmt_fcp_rsp_error),
+- atomic_read(&tgtp->xmt_fcp_rsp_drop));
+-
+- len += snprintf(buf+len, PAGE_SIZE-len,
+- "FCP Rsp Abort: %08x xb %08x xricqe %08x\n",
+- atomic_read(&tgtp->xmt_fcp_rsp_aborted),
+- atomic_read(&tgtp->xmt_fcp_rsp_xb_set),
+- atomic_read(&tgtp->xmt_fcp_xri_abort_cqe));
+-
+- len += snprintf(buf + len, PAGE_SIZE - len,
+- "ABORT: Xmt %08x Cmpl %08x\n",
+- atomic_read(&tgtp->xmt_fcp_abort),
+- atomic_read(&tgtp->xmt_fcp_abort_cmpl));
+-
+- len += snprintf(buf + len, PAGE_SIZE - len,
+- "ABORT: Sol %08x Usol %08x Err %08x Cmpl %08x",
+- atomic_read(&tgtp->xmt_abort_sol),
+- atomic_read(&tgtp->xmt_abort_unsol),
+- atomic_read(&tgtp->xmt_abort_rsp),
+- atomic_read(&tgtp->xmt_abort_rsp_error));
+-
+- len += snprintf(buf + len, PAGE_SIZE - len,
+- "DELAY: ctx %08x fod %08x wqfull %08x\n",
+- atomic_read(&tgtp->defer_ctx),
+- atomic_read(&tgtp->defer_fod),
+- atomic_read(&tgtp->defer_wqfull));
++ scnprintf(tmp, sizeof(tmp),
++ "FCP Rsp: RD %08x rsp %08x WR %08x rsp %08x "
++ "drop %08x\n",
++ atomic_read(&tgtp->xmt_fcp_read),
++ atomic_read(&tgtp->xmt_fcp_read_rsp),
++ atomic_read(&tgtp->xmt_fcp_write),
++ atomic_read(&tgtp->xmt_fcp_rsp),
++ atomic_read(&tgtp->xmt_fcp_drop));
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
++
++ scnprintf(tmp, sizeof(tmp),
++ "FCP Rsp Cmpl: %08x err %08x drop %08x\n",
++ atomic_read(&tgtp->xmt_fcp_rsp_cmpl),
++ atomic_read(&tgtp->xmt_fcp_rsp_error),
++ atomic_read(&tgtp->xmt_fcp_rsp_drop));
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
++
++ scnprintf(tmp, sizeof(tmp),
++ "FCP Rsp Abort: %08x xb %08x xricqe %08x\n",
++ atomic_read(&tgtp->xmt_fcp_rsp_aborted),
++ atomic_read(&tgtp->xmt_fcp_rsp_xb_set),
++ atomic_read(&tgtp->xmt_fcp_xri_abort_cqe));
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
++
++ scnprintf(tmp, sizeof(tmp),
++ "ABORT: Xmt %08x Cmpl %08x\n",
++ atomic_read(&tgtp->xmt_fcp_abort),
++ atomic_read(&tgtp->xmt_fcp_abort_cmpl));
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
++
++ scnprintf(tmp, sizeof(tmp),
++ "ABORT: Sol %08x Usol %08x Err %08x Cmpl %08x\n",
++ atomic_read(&tgtp->xmt_abort_sol),
++ atomic_read(&tgtp->xmt_abort_unsol),
++ atomic_read(&tgtp->xmt_abort_rsp),
++ atomic_read(&tgtp->xmt_abort_rsp_error));
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
++
++ scnprintf(tmp, sizeof(tmp),
++ "DELAY: ctx %08x fod %08x wqfull %08x\n",
++ atomic_read(&tgtp->defer_ctx),
++ atomic_read(&tgtp->defer_fod),
++ atomic_read(&tgtp->defer_wqfull));
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
+
+ /* Calculate outstanding IOs */
+ tot = atomic_read(&tgtp->rcv_fcp_cmd_drop);
+ tot += atomic_read(&tgtp->xmt_fcp_release);
+ tot = atomic_read(&tgtp->rcv_fcp_cmd_in) - tot;
+
+- len += snprintf(buf + len, PAGE_SIZE - len,
+- "IO_CTX: %08x WAIT: cur %08x tot %08x\n"
+- "CTX Outstanding %08llx\n",
+- phba->sli4_hba.nvmet_xri_cnt,
+- phba->sli4_hba.nvmet_io_wait_cnt,
+- phba->sli4_hba.nvmet_io_wait_total,
+- tot);
+-
+- len += snprintf(buf+len, PAGE_SIZE-len, "\n");
+- return len;
++ scnprintf(tmp, sizeof(tmp),
++ "IO_CTX: %08x WAIT: cur %08x tot %08x\n"
++ "CTX Outstanding %08llx\n\n",
++ phba->sli4_hba.nvmet_xri_cnt,
++ phba->sli4_hba.nvmet_io_wait_cnt,
++ phba->sli4_hba.nvmet_io_wait_total,
++ tot);
++ strlcat(buf, tmp, PAGE_SIZE);
++ goto buffer_done;
+ }
+
+ localport = vport->localport;
+ if (!localport) {
+- len = snprintf(buf, PAGE_SIZE,
++ len = scnprintf(buf, PAGE_SIZE,
+ "NVME Initiator x%llx is not allocated\n",
+ wwn_to_u64(vport->fc_portname.u.wwn));
+ return len;
+ }
+ lport = (struct lpfc_nvme_lport *)localport->private;
+- len = snprintf(buf, PAGE_SIZE, "NVME Initiator Enabled\n");
+-
+- spin_lock_irq(shost->host_lock);
+- len += snprintf(buf + len, PAGE_SIZE - len,
+- "XRI Dist lpfc%d Total %d NVME %d SCSI %d ELS %d\n",
+- phba->brd_no,
+- phba->sli4_hba.max_cfg_param.max_xri,
+- phba->sli4_hba.nvme_xri_max,
+- phba->sli4_hba.scsi_xri_max,
+- lpfc_sli4_get_els_iocb_cnt(phba));
++ if (strlcat(buf, "\nNVME Initiator Enabled\n", PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
++
++ rcu_read_lock();
++ scnprintf(tmp, sizeof(tmp),
++ "XRI Dist lpfc%d Total %d NVME %d SCSI %d ELS %d\n",
++ phba->brd_no,
++ phba->sli4_hba.max_cfg_param.max_xri,
++ phba->sli4_hba.nvme_xri_max,
++ phba->sli4_hba.scsi_xri_max,
++ lpfc_sli4_get_els_iocb_cnt(phba));
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
+
+ /* Port state is only one of two values for now. */
+ if (localport->port_id)
+@@ -311,13 +349,15 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
+ else
+ statep = "UNKNOWN ";
+
+- len += snprintf(buf + len, PAGE_SIZE - len,
+- "%s%d WWPN x%llx WWNN x%llx DID x%06x %s\n",
+- "NVME LPORT lpfc",
+- phba->brd_no,
+- wwn_to_u64(vport->fc_portname.u.wwn),
+- wwn_to_u64(vport->fc_nodename.u.wwn),
+- localport->port_id, statep);
++ scnprintf(tmp, sizeof(tmp),
++ "%s%d WWPN x%llx WWNN x%llx DID x%06x %s\n",
++ "NVME LPORT lpfc",
++ phba->brd_no,
++ wwn_to_u64(vport->fc_portname.u.wwn),
++ wwn_to_u64(vport->fc_nodename.u.wwn),
++ localport->port_id, statep);
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
+
+ list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
+ rport = lpfc_ndlp_get_nrport(ndlp);
+@@ -343,56 +383,77 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
+ }
+
+ /* Tab in to show lport ownership. */
+- len += snprintf(buf + len, PAGE_SIZE - len,
+- "NVME RPORT ");
+- if (phba->brd_no >= 10)
+- len += snprintf(buf + len, PAGE_SIZE - len, " ");
+-
+- len += snprintf(buf + len, PAGE_SIZE - len, "WWPN x%llx ",
+- nrport->port_name);
+- len += snprintf(buf + len, PAGE_SIZE - len, "WWNN x%llx ",
+- nrport->node_name);
+- len += snprintf(buf + len, PAGE_SIZE - len, "DID x%06x ",
+- nrport->port_id);
++ if (strlcat(buf, "NVME RPORT ", PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
++ if (phba->brd_no >= 10) {
++ if (strlcat(buf, " ", PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
++ }
++
++ scnprintf(tmp, sizeof(tmp), "WWPN x%llx ",
++ nrport->port_name);
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
++
++ scnprintf(tmp, sizeof(tmp), "WWNN x%llx ",
++ nrport->node_name);
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
++
++ scnprintf(tmp, sizeof(tmp), "DID x%06x ",
++ nrport->port_id);
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
+
+ /* An NVME rport can have multiple roles. */
+- if (nrport->port_role & FC_PORT_ROLE_NVME_INITIATOR)
+- len += snprintf(buf + len, PAGE_SIZE - len,
+- "INITIATOR ");
+- if (nrport->port_role & FC_PORT_ROLE_NVME_TARGET)
+- len += snprintf(buf + len, PAGE_SIZE - len,
+- "TARGET ");
+- if (nrport->port_role & FC_PORT_ROLE_NVME_DISCOVERY)
+- len += snprintf(buf + len, PAGE_SIZE - len,
+- "DISCSRVC ");
++ if (nrport->port_role & FC_PORT_ROLE_NVME_INITIATOR) {
++ if (strlcat(buf, "INITIATOR ", PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
++ }
++ if (nrport->port_role & FC_PORT_ROLE_NVME_TARGET) {
++ if (strlcat(buf, "TARGET ", PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
++ }
++ if (nrport->port_role & FC_PORT_ROLE_NVME_DISCOVERY) {
++ if (strlcat(buf, "DISCSRVC ", PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
++ }
+ if (nrport->port_role & ~(FC_PORT_ROLE_NVME_INITIATOR |
+ FC_PORT_ROLE_NVME_TARGET |
+- FC_PORT_ROLE_NVME_DISCOVERY))
+- len += snprintf(buf + len, PAGE_SIZE - len,
+- "UNKNOWN ROLE x%x",
+- nrport->port_role);
+-
+- len += snprintf(buf + len, PAGE_SIZE - len, "%s ", statep);
+- /* Terminate the string. */
+- len += snprintf(buf + len, PAGE_SIZE - len, "\n");
++ FC_PORT_ROLE_NVME_DISCOVERY)) {
++ scnprintf(tmp, sizeof(tmp), "UNKNOWN ROLE x%x",
++ nrport->port_role);
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
++ }
++
++ scnprintf(tmp, sizeof(tmp), "%s\n", statep);
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
+ }
+- spin_unlock_irq(shost->host_lock);
++ rcu_read_unlock();
+
+ if (!lport)
+- return len;
+-
+- len += snprintf(buf + len, PAGE_SIZE - len, "\nNVME Statistics\n");
+- len += snprintf(buf+len, PAGE_SIZE-len,
+- "LS: Xmt %010x Cmpl %010x Abort %08x\n",
+- atomic_read(&lport->fc4NvmeLsRequests),
+- atomic_read(&lport->fc4NvmeLsCmpls),
+- atomic_read(&lport->xmt_ls_abort));
+-
+- len += snprintf(buf + len, PAGE_SIZE - len,
+- "LS XMIT: Err %08x CMPL: xb %08x Err %08x\n",
+- atomic_read(&lport->xmt_ls_err),
+- atomic_read(&lport->cmpl_ls_xb),
+- atomic_read(&lport->cmpl_ls_err));
++ goto buffer_done;
++
++ if (strlcat(buf, "\nNVME Statistics\n", PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
++
++ scnprintf(tmp, sizeof(tmp),
++ "LS: Xmt %010x Cmpl %010x Abort %08x\n",
++ atomic_read(&lport->fc4NvmeLsRequests),
++ atomic_read(&lport->fc4NvmeLsCmpls),
++ atomic_read(&lport->xmt_ls_abort));
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
++
++ scnprintf(tmp, sizeof(tmp),
++ "LS XMIT: Err %08x CMPL: xb %08x Err %08x\n",
++ atomic_read(&lport->xmt_ls_err),
++ atomic_read(&lport->cmpl_ls_xb),
++ atomic_read(&lport->cmpl_ls_err));
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
+
+ totin = 0;
+ totout = 0;
+@@ -405,25 +466,46 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
+ data3 = atomic_read(&cstat->fc4NvmeControlRequests);
+ totout += (data1 + data2 + data3);
+ }
+- len += snprintf(buf+len, PAGE_SIZE-len,
+- "Total FCP Cmpl %016llx Issue %016llx "
+- "OutIO %016llx\n",
+- totin, totout, totout - totin);
+-
+- len += snprintf(buf+len, PAGE_SIZE-len,
+- " abort %08x noxri %08x nondlp %08x qdepth %08x "
+- "wqerr %08x err %08x\n",
+- atomic_read(&lport->xmt_fcp_abort),
+- atomic_read(&lport->xmt_fcp_noxri),
+- atomic_read(&lport->xmt_fcp_bad_ndlp),
+- atomic_read(&lport->xmt_fcp_qdepth),
+- atomic_read(&lport->xmt_fcp_err),
+- atomic_read(&lport->xmt_fcp_wqerr));
+-
+- len += snprintf(buf + len, PAGE_SIZE - len,
+- "FCP CMPL: xb %08x Err %08x\n",
+- atomic_read(&lport->cmpl_fcp_xb),
+- atomic_read(&lport->cmpl_fcp_err));
++ scnprintf(tmp, sizeof(tmp),
++ "Total FCP Cmpl %016llx Issue %016llx "
++ "OutIO %016llx\n",
++ totin, totout, totout - totin);
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
++
++ scnprintf(tmp, sizeof(tmp),
++ "\tabort %08x noxri %08x nondlp %08x qdepth %08x "
++ "wqerr %08x err %08x\n",
++ atomic_read(&lport->xmt_fcp_abort),
++ atomic_read(&lport->xmt_fcp_noxri),
++ atomic_read(&lport->xmt_fcp_bad_ndlp),
++ atomic_read(&lport->xmt_fcp_qdepth),
++ atomic_read(&lport->xmt_fcp_err),
++ atomic_read(&lport->xmt_fcp_wqerr));
++ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
++ goto buffer_done;
++
++ scnprintf(tmp, sizeof(tmp),
++ "FCP CMPL: xb %08x Err %08x\n",
++ atomic_read(&lport->cmpl_fcp_xb),
++ atomic_read(&lport->cmpl_fcp_err));
++ strlcat(buf, tmp, PAGE_SIZE);
++
++buffer_done:
++ len = strnlen(buf, PAGE_SIZE);
++
++ if (unlikely(len >= (PAGE_SIZE - 1))) {
++ lpfc_printf_log(phba, KERN_INFO, LOG_NVME,
++ "6314 Catching potential buffer "
++ "overflow > PAGE_SIZE = %lu bytes\n",
++ PAGE_SIZE);
++ strlcpy(buf + PAGE_SIZE - 1 -
++ strnlen(LPFC_NVME_INFO_MORE_STR, PAGE_SIZE - 1),
++ LPFC_NVME_INFO_MORE_STR,
++ strnlen(LPFC_NVME_INFO_MORE_STR, PAGE_SIZE - 1)
++ + 1);
++ }
++
+ return len;
+ }
+
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-lpfc-Correct-LCB-ACCept-payload.patch b/patches.drivers/scsi-lpfc-Correct-LCB-ACCept-payload.patch
new file mode 100644
index 0000000000..4ed094e4dc
--- /dev/null
+++ b/patches.drivers/scsi-lpfc-Correct-LCB-ACCept-payload.patch
@@ -0,0 +1,46 @@
+From: James Smart <jsmart2021@gmail.com>
+Date: Tue, 31 Jul 2018 17:23:23 -0700
+Subject: [PATCH] scsi: lpfc: Correct LCB ACCept payload
+References: bsc#1102658
+Git-commit: 24bc3119424ac163c2f67e072c956f50e153d034
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git
+
+After memory allocation for the LCB response frame, the memory wasn't zero
+initialized, and not all fields are set. Thus garbage shows up in the
+payload.
+
+Fix by zeroing the memory at allocation. Also properly set the Capability
+field based on duration support.
+
+Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
+Signed-off-by: James Smart <james.smart@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/lpfc/lpfc_els.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
+index df655f1284d0..4dda969e947c 100644
+--- a/drivers/scsi/lpfc/lpfc_els.c
++++ b/drivers/scsi/lpfc/lpfc_els.c
+@@ -5662,6 +5662,7 @@ lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+ lcb_res = (struct fc_lcb_res_frame *)
+ (((struct lpfc_dmabuf *)elsiocb->context2)->virt);
+
++ memset(lcb_res, 0, sizeof(struct fc_lcb_res_frame));
+ icmd = &elsiocb->iocb;
+ icmd->ulpContext = lcb_context->rx_id;
+ icmd->unsli3.rcvsli3.ox_id = lcb_context->ox_id;
+@@ -5670,6 +5671,7 @@ lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+ *((uint32_t *)(pcmd)) = ELS_CMD_ACC;
+ lcb_res->lcb_sub_command = lcb_context->sub_command;
+ lcb_res->lcb_type = lcb_context->type;
++ lcb_res->capability = lcb_context->capability;
+ lcb_res->lcb_frequency = lcb_context->frequency;
+ lcb_res->lcb_duration = lcb_context->duration;
+ elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-lpfc-Fix-ELS-abort-on-SLI-3-adapters.patch b/patches.drivers/scsi-lpfc-Fix-ELS-abort-on-SLI-3-adapters.patch
new file mode 100644
index 0000000000..870536575d
--- /dev/null
+++ b/patches.drivers/scsi-lpfc-Fix-ELS-abort-on-SLI-3-adapters.patch
@@ -0,0 +1,89 @@
+From: James Smart <jsmart2021@gmail.com>
+Date: Tue, 31 Jul 2018 17:23:18 -0700
+Subject: [PATCH] scsi: lpfc: Fix ELS abort on SLI-3 adapters
+References: bsc#1102658
+Git-commit: faa832e97a0c0d79838c3a6521a473d870217053
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git
+
+For ABORT_XRI_CN command, firmware identifies XRI to abort by IOTAG and RPI
+combination. For ELS aborts, driver specifies IOTAG correctly but RPI is
+not specified.
+
+Fix by setting RPI in WQE.
+
+Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
+Signed-off-by: James Smart <james.smart@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/lpfc/lpfc_nportdisc.c | 3 +++
+ drivers/scsi/lpfc/lpfc_sli.c | 16 ++++++++++++++--
+ 2 files changed, 17 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
+index 1f0a7d7dbc54..843e765db86d 100644
+--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
++++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
+@@ -1062,6 +1062,9 @@ lpfc_rcv_logo_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ {
+ struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
+
++ /* Retrieve RPI from LOGO IOCB. RPI is used for CMD_ABORT_XRI_CN */
++ if (vport->phba->sli_rev == LPFC_SLI_REV3)
++ ndlp->nlp_rpi = cmdiocb->iocb.ulpIoTag;
+ /* software abort outstanding PLOGI */
+ lpfc_els_abort(vport->phba, ndlp);
+
+diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
+index 72500dcb13a9..9830bdb6e072 100644
+--- a/drivers/scsi/lpfc/lpfc_sli.c
++++ b/drivers/scsi/lpfc/lpfc_sli.c
+@@ -10703,6 +10703,12 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+
+ spin_lock_irq(&phba->hbalock);
+ if (phba->sli_rev < LPFC_SLI_REV4) {
++ if (irsp->ulpCommand == CMD_ABORT_XRI_CX &&
++ irsp->ulpStatus == IOSTAT_LOCAL_REJECT &&
++ irsp->un.ulpWord[4] == IOERR_ABORT_REQUESTED) {
++ spin_unlock_irq(&phba->hbalock);
++ goto release_iocb;
++ }
+ if (abort_iotag != 0 &&
+ abort_iotag <= phba->sli.last_iotag)
+ abort_iocb =
+@@ -10724,6 +10730,7 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+
+ spin_unlock_irq(&phba->hbalock);
+ }
++release_iocb:
+ lpfc_sli_release_iocbq(phba, cmdiocb);
+ return;
+ }
+@@ -10780,6 +10787,7 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ IOCB_t *iabt = NULL;
+ int retval;
+ unsigned long iflags;
++ struct lpfc_nodelist *ndlp;
+
+ lockdep_assert_held(&phba->hbalock);
+
+@@ -10810,9 +10818,13 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ if (phba->sli_rev == LPFC_SLI_REV4) {
+ iabt->un.acxri.abortIoTag = cmdiocb->sli4_xritag;
+ iabt->un.acxri.abortContextTag = cmdiocb->iotag;
+- }
+- else
++ } else {
+ iabt->un.acxri.abortIoTag = icmd->ulpIoTag;
++ if (pring->ringno == LPFC_ELS_RING) {
++ ndlp = (struct lpfc_nodelist *)(cmdiocb->context1);
++ iabt->un.acxri.abortContextTag = ndlp->nlp_rpi;
++ }
++ }
+ iabt->ulpLe = 1;
+ iabt->ulpClass = icmd->ulpClass;
+
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-lpfc-Fix-NVME-Target-crash-in-defer-rcv-logic.patch b/patches.drivers/scsi-lpfc-Fix-NVME-Target-crash-in-defer-rcv-logic.patch
new file mode 100644
index 0000000000..184bb0f43e
--- /dev/null
+++ b/patches.drivers/scsi-lpfc-Fix-NVME-Target-crash-in-defer-rcv-logic.patch
@@ -0,0 +1,61 @@
+From: James Smart <jsmart2021@gmail.com>
+Date: Tue, 26 Jun 2018 08:24:28 -0700
+Subject: [PATCH] scsi: lpfc: Fix NVME Target crash in defer rcv logic
+References: bsc#1102658
+Git-commit: 6871e8144f935a1f08e7fc6269c894861ce494aa
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
+Patch-mainline: Queued in subsystem maintainer repository
+
+Kernel occasionally crashed with the following
+ops on NVME Target:
+ BUG: unable to handle kernel NULL pointer dereference at 0000000000000058
+ IP: [<ffffffffa042ee50>] lpfc_nvmet_defer_rcv+0x50/0x70 [lpfc]
+
+Callback routine was called for deferred rcv when it should be treated as a
+normal rcv.
+
+Added code in callback routine to detect this condition and log a message,
+then bail.
+
+Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
+Signed-off-by: James Smart <james.smart@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/lpfc/lpfc_nvmet.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c
+index ccb35efef1e1..ff994712f58a 100644
+--- a/drivers/scsi/lpfc/lpfc_nvmet.c
++++ b/drivers/scsi/lpfc/lpfc_nvmet.c
+@@ -402,6 +402,7 @@ lpfc_nvmet_ctxbuf_post(struct lpfc_hba *phba, struct lpfc_nvmet_ctxbuf *ctx_buf)
+
+ /* Process FCP command */
+ if (rc == 0) {
++ ctxp->rqb_buffer = NULL;
+ atomic_inc(&tgtp->rcv_fcp_cmd_out);
+ nvmebuf->hrq->rqbp->rqb_free_buffer(phba, nvmebuf);
+ return;
+@@ -1116,8 +1117,17 @@ lpfc_nvmet_defer_rcv(struct nvmet_fc_target_port *tgtport,
+ lpfc_nvmeio_data(phba, "NVMET DEFERRCV: xri x%x sz %d CPU %02x\n",
+ ctxp->oxid, ctxp->size, smp_processor_id());
+
++ if (!nvmebuf) {
++ lpfc_printf_log(phba, KERN_INFO, LOG_NVME_IOERR,
++ "6425 Defer rcv: no buffer xri x%x: "
++ "flg %x ste %x\n",
++ ctxp->oxid, ctxp->flag, ctxp->state);
++ return;
++ }
++
+ tgtp = phba->targetport->private;
+- atomic_inc(&tgtp->rcv_fcp_cmd_defer);
++ if (tgtp)
++ atomic_inc(&tgtp->rcv_fcp_cmd_defer);
+
+ /* Free the nvmebuf since a new buffer already replaced it */
+ nvmebuf->hrq->rqbp->rqb_free_buffer(phba, nvmebuf);
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-lpfc-Fix-abort-error-path-for-NVMET.patch b/patches.drivers/scsi-lpfc-Fix-abort-error-path-for-NVMET.patch
new file mode 100644
index 0000000000..5376f7645c
--- /dev/null
+++ b/patches.drivers/scsi-lpfc-Fix-abort-error-path-for-NVMET.patch
@@ -0,0 +1,94 @@
+From: James Smart <jsmart2021@gmail.com>
+Date: Tue, 26 Jun 2018 08:24:25 -0700
+Subject: [PATCH] scsi: lpfc: Fix abort error path for NVMET
+References: bsc#1102658
+Git-commit: 68c9b55deea51151d9da3d45ecc9a5ef72f9dfb1
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
+Patch-mainline: Queued in subsystem maintainer repository
+
+rmmod of driver hangs
+
+As driver instances were being unloaded, the NVME target port was unloaded
+first. During the unload, the NVME initiator port sent a heartbeat
+IO. Because of the target port state, that IO was scheduled for an Abort;
+however, that abort subsequently failed. The failure was not cleaned up
+properly and lpfc_sli4_xri_exchange_busy_wait silently hung forever.
+
+Clean failed abort properly and make lpfc_sli4_xri_exchange_busy_wait not
+hangs silently while waiting for aborts to complete.
+
+Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
+Signed-off-by: James Smart <james.smart@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/lpfc/lpfc_init.c | 5 +++++
+ drivers/scsi/lpfc/lpfc_nvmet.c | 15 +++++++++++----
+ 2 files changed, 16 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
+index 1f2d8a29b075..64ccfe735252 100644
+--- a/drivers/scsi/lpfc/lpfc_init.c
++++ b/drivers/scsi/lpfc/lpfc_init.c
+@@ -10393,6 +10393,11 @@ lpfc_sli4_xri_exchange_busy_wait(struct lpfc_hba *phba)
+ while (!fcp_xri_cmpl || !els_xri_cmpl || !nvme_xri_cmpl ||
+ !nvmet_xri_cmpl) {
+ if (wait_time > LPFC_XRI_EXCH_BUSY_WAIT_TMO) {
++ if (!nvmet_xri_cmpl)
++ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
++ "6424 NVMET XRI exchange busy "
++ "wait time: %d seconds.\n",
++ wait_time/1000);
+ if (!nvme_xri_cmpl)
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "6100 NVME XRI exchange busy "
+diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c
+index 7271c9d885dd..102c970a00e6 100644
+--- a/drivers/scsi/lpfc/lpfc_nvmet.c
++++ b/drivers/scsi/lpfc/lpfc_nvmet.c
+@@ -1732,9 +1732,12 @@ lpfc_nvmet_unsol_ls_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ uint32_t *payload;
+ uint32_t size, oxid, sid, rc;
+
++ fc_hdr = (struct fc_frame_header *)(nvmebuf->hbuf.virt);
++ oxid = be16_to_cpu(fc_hdr->fh_ox_id);
++
+ if (!nvmebuf || !phba->targetport) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+- "6154 LS Drop IO\n");
++ "6154 LS Drop IO x%x\n", oxid);
+ oxid = 0;
+ size = 0;
+ sid = 0;
+@@ -1744,9 +1747,7 @@ lpfc_nvmet_unsol_ls_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+
+ tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
+ payload = (uint32_t *)(nvmebuf->dbuf.virt);
+- fc_hdr = (struct fc_frame_header *)(nvmebuf->hbuf.virt);
+ size = bf_get(lpfc_rcqe_length, &nvmebuf->cq_event.cqe.rcqe_cmpl);
+- oxid = be16_to_cpu(fc_hdr->fh_ox_id);
+ sid = sli4_sid_from_fc_hdr(fc_hdr);
+
+ ctxp = kzalloc(sizeof(struct lpfc_nvmet_rcv_ctx), GFP_ATOMIC);
+@@ -3105,11 +3106,17 @@ lpfc_nvmet_unsol_fcp_issue_abort(struct lpfc_hba *phba,
+ }
+
+ aerr:
+- ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
++ spin_lock_irqsave(&ctxp->ctxlock, flags);
++ if (ctxp->flag & LPFC_NVMET_CTX_RLS)
++ list_del(&ctxp->list);
++ ctxp->flag &= ~(LPFC_NVMET_ABORT_OP | LPFC_NVMET_CTX_RLS);
++ spin_unlock_irqrestore(&ctxp->ctxlock, flags);
++
+ atomic_inc(&tgtp->xmt_abort_rsp_error);
+ lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
+ "6135 Failed to Issue ABTS for oxid x%x. Status x%x\n",
+ ctxp->oxid, rc);
++ lpfc_nvmet_ctxbuf_post(phba, ctxp->ctxbuf);
+ return 1;
+ }
+
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-lpfc-Fix-driver-crash-when-re-registering-NVME-.patch b/patches.drivers/scsi-lpfc-Fix-driver-crash-when-re-registering-NVME-.patch
new file mode 100644
index 0000000000..4ab4989fae
--- /dev/null
+++ b/patches.drivers/scsi-lpfc-Fix-driver-crash-when-re-registering-NVME-.patch
@@ -0,0 +1,109 @@
+From: James Smart <jsmart2021@gmail.com>
+Date: Tue, 31 Jul 2018 17:23:21 -0700
+Subject: [PATCH] scsi: lpfc: Fix driver crash when re-registering NVME rports.
+References: bsc#1102658
+Git-commit: 93a3922da428ec0752e8b2ab00c42dadbbf805a9
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git
+
+During remote port loss fault testing, the driver crashed with the
+following trace:
+
+general protection fault: 0000 [#1] SMP
+RIP: ... lpfc_nvme_register_port+0x250/0x480 [lpfc]
+Call Trace:
+ lpfc_nlp_state_cleanup+0x1b3/0x7a0 [lpfc]
+ lpfc_nlp_set_state+0xa6/0x1d0 [lpfc]
+ lpfc_cmpl_prli_prli_issue+0x213/0x440
+ lpfc_disc_state_machine+0x7e/0x1e0 [lpfc]
+ lpfc_cmpl_els_prli+0x18a/0x200 [lpfc]
+ lpfc_sli_sp_handle_rspiocb+0x3b5/0x6f0 [lpfc]
+ lpfc_sli_handle_slow_ring_event_s4+0x161/0x240 [lpfc]
+ lpfc_work_done+0x948/0x14c0 [lpfc]
+ lpfc_do_work+0x16f/0x180 [lpfc]
+ kthread+0xc9/0xe0
+ ret_from_fork+0x55/0x80
+
+After registering a new remoteport, the driver is pulling an ndlp pointer
+from the lpfc rport associated with the private area of a newly registered
+remoteport. The private area is uninitialized, so it's garbage.
+
+Correct by pulling the the lpfc rport pointer from the entering ndlp point,
+then ndlp value from at rport. Note the entering ndlp may be replacing by
+the rport->ndlp due to an address change swap.
+
+Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
+Signed-off-by: James Smart <james.smart@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/lpfc/lpfc_nvme.c | 22 ++++++++++++++--------
+ 1 file changed, 14 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
+index 4cc6783b6a9f..32053424d546 100644
+--- a/drivers/scsi/lpfc/lpfc_nvme.c
++++ b/drivers/scsi/lpfc/lpfc_nvme.c
+@@ -2687,7 +2687,7 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
+ struct lpfc_nvme_rport *oldrport;
+ struct nvme_fc_remote_port *remote_port;
+ struct nvme_fc_port_info rpinfo;
+- struct lpfc_nodelist *prev_ndlp;
++ struct lpfc_nodelist *prev_ndlp = NULL;
+
+ lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NVME_DISC,
+ "6006 Register NVME PORT. DID x%06x nlptype x%x\n",
+@@ -2736,23 +2736,29 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
+ spin_unlock_irq(&vport->phba->hbalock);
+ rport = remote_port->private;
+ if (oldrport) {
++ /* New remoteport record does not guarantee valid
++ * host private memory area.
++ */
++ prev_ndlp = oldrport->ndlp;
+ if (oldrport == remote_port->private) {
+- /* Same remoteport. Just reuse. */
++ /* Same remoteport - ndlp should match.
++ * Just reuse.
++ */
+ lpfc_printf_vlog(ndlp->vport, KERN_INFO,
+ LOG_NVME_DISC,
+ "6014 Rebinding lport to "
+ "remoteport %p wwpn 0x%llx, "
+- "Data: x%x x%x %p x%x x%06x\n",
++ "Data: x%x x%x %p %p x%x x%06x\n",
+ remote_port,
+ remote_port->port_name,
+ remote_port->port_id,
+ remote_port->port_role,
++ prev_ndlp,
+ ndlp,
+ ndlp->nlp_type,
+ ndlp->nlp_DID);
+ return 0;
+ }
+- prev_ndlp = rport->ndlp;
+
+ /* Sever the ndlp<->rport association
+ * before dropping the ndlp ref from
+@@ -2786,13 +2792,13 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
+ lpfc_printf_vlog(vport, KERN_INFO,
+ LOG_NVME_DISC | LOG_NODE,
+ "6022 Binding new rport to "
+- "lport %p Remoteport %p WWNN 0x%llx, "
++ "lport %p Remoteport %p rport %p WWNN 0x%llx, "
+ "Rport WWPN 0x%llx DID "
+- "x%06x Role x%x, ndlp %p\n",
+- lport, remote_port,
++ "x%06x Role x%x, ndlp %p prev_ndlp %p\n",
++ lport, remote_port, rport,
+ rpinfo.node_name, rpinfo.port_name,
+ rpinfo.port_id, rpinfo.port_role,
+- ndlp);
++ ndlp, prev_ndlp);
+ } else {
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_NVME_DISC | LOG_NODE,
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-lpfc-Fix-driver-not-setting-dpp-bits-correctly-.patch b/patches.drivers/scsi-lpfc-Fix-driver-not-setting-dpp-bits-correctly-.patch
new file mode 100644
index 0000000000..2f0895c61d
--- /dev/null
+++ b/patches.drivers/scsi-lpfc-Fix-driver-not-setting-dpp-bits-correctly-.patch
@@ -0,0 +1,54 @@
+From: James Smart <jsmart2021@gmail.com>
+Date: Tue, 26 Jun 2018 08:24:23 -0700
+Subject: [PATCH] scsi: lpfc: Fix driver not setting dpp bits correctly in
+ doorbell word
+References: bsc#1102658
+Git-commit: 5cc167ddb7441013e2b5a5f47bf11af0264bb3e8
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
+Patch-mainline: Queued in subsystem maintainer repository
+
+Driver is incorrectly formatting a register on new hardware, using a format
+for an older chip. This can result in non-deterministic behavior.
+
+Ensure driver is not setting "workqueue index" in the WQ doorbell when
+making a non-dpp doorbell write. The field must be zero when non-dpp.
+
+Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
+Signed-off-by: James Smart <james.smart@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/lpfc/lpfc_sli.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
+index d4510e64856a..a25e38ac64e3 100644
+--- a/drivers/scsi/lpfc/lpfc_sli.c
++++ b/drivers/scsi/lpfc/lpfc_sli.c
+@@ -145,6 +145,7 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe128 *wqe)
+ uint32_t idx;
+ uint32_t i = 0;
+ uint8_t *tmp;
++ u32 if_type;
+
+ /* sanity check on queue memory */
+ if (unlikely(!q))
+@@ -199,8 +200,14 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe128 *wqe)
+ q->queue_id);
+ } else {
+ bf_set(lpfc_wq_db_list_fm_num_posted, &doorbell, 1);
+- bf_set(lpfc_wq_db_list_fm_index, &doorbell, host_index);
+ bf_set(lpfc_wq_db_list_fm_id, &doorbell, q->queue_id);
++
++ /* Leave bits <23:16> clear for if_type 6 dpp */
++ if_type = bf_get(lpfc_sli_intf_if_type,
++ &q->phba->sli4_hba.sli_intf);
++ if (if_type != LPFC_SLI_INTF_IF_TYPE_6)
++ bf_set(lpfc_wq_db_list_fm_index, &doorbell,
++ host_index);
+ }
+ } else if (q->db_format == LPFC_DB_RING_FORMAT) {
+ bf_set(lpfc_wq_db_ring_fm_num_posted, &doorbell, 1);
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-lpfc-Fix-list-corruption-on-the-completion-queu.patch b/patches.drivers/scsi-lpfc-Fix-list-corruption-on-the-completion-queu.patch
new file mode 100644
index 0000000000..bd245e8e33
--- /dev/null
+++ b/patches.drivers/scsi-lpfc-Fix-list-corruption-on-the-completion-queu.patch
@@ -0,0 +1,143 @@
+From: James Smart <jsmart2021@gmail.com>
+Date: Tue, 31 Jul 2018 17:23:20 -0700
+Subject: [PATCH] scsi: lpfc: Fix list corruption on the completion queue.
+References: bsc#1102658
+Git-commit: 8931c73bee077f5bc5710afebc0136363970cb2b
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git
+
+Enabling list_debug showed the drivers txcmplq was suffering list
+corruption. The systems will eventually crash because the iocb free list
+gets crossed linked with the prings txcmplq. Most systems will run for a
+while after the corruption, but will eventually crash when a scsi eh reset
+occurs and the txcmplq is attempted to be flushed. The flush gets stuck in
+an endless loop.
+
+The problem is the abort handler does not hold the sli4 ring lock while
+validating the IO so the IO could complete while the driver is still
+preping the abort. The erroneously generated abort, when it completes, has
+pointers to the original IO that has already completed, and the IO
+manipulation (for the second time) corrupts the list.
+
+Correct by taking the ring lock early in the abort handler so the erroneous
+abort won't be sent if the io has/is completing.
+
+Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
+Signed-off-by: James Smart <james.smart@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/lpfc/lpfc_scsi.c | 44 +++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 36 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
+index 25ef2b6ccc34..51ce244cf10a 100644
+--- a/drivers/scsi/lpfc/lpfc_scsi.c
++++ b/drivers/scsi/lpfc/lpfc_scsi.c
+@@ -4727,7 +4727,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
+ struct lpfc_scsi_buf *lpfc_cmd;
+ IOCB_t *cmd, *icmd;
+ int ret = SUCCESS, status = 0;
+- struct lpfc_sli_ring *pring_s4;
++ struct lpfc_sli_ring *pring_s4 = NULL;
+ int ret_val;
+ unsigned long flags;
+ DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq);
+@@ -4757,8 +4757,25 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
+ }
+
+ iocb = &lpfc_cmd->cur_iocbq;
++ if (phba->sli_rev == LPFC_SLI_REV4) {
++ if (!(phba->cfg_fof) ||
++ (!(iocb->iocb_flag & LPFC_IO_FOF))) {
++ pring_s4 =
++ phba->sli4_hba.fcp_wq[iocb->hba_wqidx]->pring;
++ } else {
++ iocb->hba_wqidx = 0;
++ pring_s4 = phba->sli4_hba.oas_wq->pring;
++ }
++ if (!pring_s4) {
++ ret = FAILED;
++ goto out_unlock;
++ }
++ spin_lock(&pring_s4->ring_lock);
++ }
+ /* the command is in process of being cancelled */
+ if (!(iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ)) {
++ if (phba->sli_rev == LPFC_SLI_REV4)
++ spin_unlock(&pring_s4->ring_lock);
+ spin_unlock_irqrestore(&phba->hbalock, flags);
+ lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
+ "3169 SCSI Layer abort requested I/O has been "
+@@ -4772,6 +4789,8 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
+ * see the completion before the eh fired. Just return SUCCESS.
+ */
+ if (lpfc_cmd->pCmd != cmnd) {
++ if (phba->sli_rev == LPFC_SLI_REV4)
++ spin_unlock(&pring_s4->ring_lock);
+ lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
+ "3170 SCSI Layer abort requested I/O has been "
+ "completed by LLD.\n");
+@@ -4784,6 +4803,8 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
+ if (iocb->iocb_flag & LPFC_DRIVER_ABORTED) {
+ lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
+ "3389 SCSI Layer I/O Abort Request is pending\n");
++ if (phba->sli_rev == LPFC_SLI_REV4)
++ spin_unlock(&pring_s4->ring_lock);
+ spin_unlock_irqrestore(&phba->hbalock, flags);
+ goto wait_for_cmpl;
+ }
+@@ -4791,6 +4812,8 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
+ abtsiocb = __lpfc_sli_get_iocbq(phba);
+ if (abtsiocb == NULL) {
+ ret = FAILED;
++ if (phba->sli_rev == LPFC_SLI_REV4)
++ spin_unlock(&pring_s4->ring_lock);
+ goto out_unlock;
+ }
+
+@@ -4828,14 +4851,9 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
+
+ abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl;
+ abtsiocb->vport = vport;
++ lpfc_cmd->waitq = &waitq;
+ if (phba->sli_rev == LPFC_SLI_REV4) {
+- pring_s4 = lpfc_sli4_calc_ring(phba, abtsiocb);
+- if (pring_s4 == NULL) {
+- ret = FAILED;
+- goto out_unlock;
+- }
+ /* Note: both hbalock and ring_lock must be set here */
+- spin_lock(&pring_s4->ring_lock);
+ ret_val = __lpfc_sli_issue_iocb(phba, pring_s4->ringno,
+ abtsiocb, 0);
+ spin_unlock(&pring_s4->ring_lock);
+@@ -4848,6 +4866,17 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
+
+
+ if (ret_val == IOCB_ERROR) {
++ if (phba->sli_rev == LPFC_SLI_REV4)
++ spin_lock_irqsave(&pring_s4->ring_lock, flags);
++ else
++ spin_lock_irqsave(&phba->hbalock, flags);
++ /* Indicate the IO is not being aborted by the driver. */
++ iocb->iocb_flag &= ~LPFC_DRIVER_ABORTED;
++ lpfc_cmd->waitq = NULL;
++ if (phba->sli_rev == LPFC_SLI_REV4)
++ spin_unlock_irqrestore(&pring_s4->ring_lock, flags);
++ else
++ spin_unlock_irqrestore(&phba->hbalock, flags);
+ lpfc_sli_release_iocbq(phba, abtsiocb);
+ ret = FAILED;
+ goto out;
+@@ -4858,7 +4887,6 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
+ &phba->sli.sli3_ring[LPFC_FCP_RING], HA_R0RE_REQ);
+
+ wait_for_cmpl:
+- lpfc_cmd->waitq = &waitq;
+ /* Wait for abort to complete */
+ wait_event_timeout(waitq,
+ (lpfc_cmd->pCmd != cmnd),
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-lpfc-Fix-panic-if-driver-unloaded-when-port-is-.patch b/patches.drivers/scsi-lpfc-Fix-panic-if-driver-unloaded-when-port-is-.patch
new file mode 100644
index 0000000000..eee87b09bd
--- /dev/null
+++ b/patches.drivers/scsi-lpfc-Fix-panic-if-driver-unloaded-when-port-is-.patch
@@ -0,0 +1,50 @@
+From: James Smart <jsmart2021@gmail.com>
+Date: Tue, 26 Jun 2018 08:24:24 -0700
+Subject: [PATCH] scsi: lpfc: Fix panic if driver unloaded when port is offline
+References: bsc#1102658
+Git-commit: d580c6137476ab307a66e278cf7dbc666230f714
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
+Patch-mainline: Queued in subsystem maintainer repository
+
+System crashes when the lpfc module is unloaded after making the port
+offline
+
+The nvme queue pointers were freed during port offline, but were later
+accessed in pci remove path.
+
+Validate the pointers in pci remove path before accessing them.
+
+Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
+Signed-off-by: James Smart <james.smart@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/lpfc/lpfc_nvme.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
+index 76a5a99605aa..ada5a2aaee82 100644
+--- a/drivers/scsi/lpfc/lpfc_nvme.c
++++ b/drivers/scsi/lpfc/lpfc_nvme.c
+@@ -2970,7 +2970,7 @@ lpfc_nvme_wait_for_io_drain(struct lpfc_hba *phba)
+ struct lpfc_sli_ring *pring;
+ u32 i, wait_cnt = 0;
+
+- if (phba->sli_rev < LPFC_SLI_REV4)
++ if (phba->sli_rev < LPFC_SLI_REV4 || !phba->sli4_hba.nvme_wq)
+ return;
+
+ /* Cycle through all NVME rings and make sure all outstanding
+@@ -2979,6 +2979,9 @@ lpfc_nvme_wait_for_io_drain(struct lpfc_hba *phba)
+ for (i = 0; i < phba->cfg_nvme_io_channel; i++) {
+ pring = phba->sli4_hba.nvme_wq[i]->pring;
+
++ if (!pring)
++ continue;
++
+ /* Retrieve everything on the txcmplq */
+ while (!list_empty(&pring->txcmplq)) {
+ msleep(LPFC_XRI_EXCH_BUSY_WAIT_T1);
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-lpfc-Fix-sysfs-Speed-value-on-CNA-ports.patch b/patches.drivers/scsi-lpfc-Fix-sysfs-Speed-value-on-CNA-ports.patch
new file mode 100644
index 0000000000..7145de9f4d
--- /dev/null
+++ b/patches.drivers/scsi-lpfc-Fix-sysfs-Speed-value-on-CNA-ports.patch
@@ -0,0 +1,52 @@
+From: James Smart <jsmart2021@gmail.com>
+Date: Tue, 31 Jul 2018 17:23:19 -0700
+Subject: [PATCH] scsi: lpfc: Fix sysfs Speed value on CNA ports
+References: bsc#1102658
+Git-commit: b615a20adf04cf3c8e9293851da3aac54792fb07
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git
+
+CNA ports were showing speed as "unknown" even if the link is up.
+
+Add speed decoding for FCOE-based adapters.
+
+Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
+Signed-off-by: James Smart <james.smart@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/lpfc/lpfc_attr.c | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
+index 23a5a298d60e..514513f837a8 100644
+--- a/drivers/scsi/lpfc/lpfc_attr.c
++++ b/drivers/scsi/lpfc/lpfc_attr.c
+@@ -5927,6 +5927,24 @@ lpfc_get_host_speed(struct Scsi_Host *shost)
+ fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
+ break;
+ }
++ } else if (lpfc_is_link_up(phba) && (phba->hba_flag & HBA_FCOE_MODE)) {
++ switch (phba->fc_linkspeed) {
++ case LPFC_ASYNC_LINK_SPEED_10GBPS:
++ fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
++ break;
++ case LPFC_ASYNC_LINK_SPEED_25GBPS:
++ fc_host_speed(shost) = FC_PORTSPEED_25GBIT;
++ break;
++ case LPFC_ASYNC_LINK_SPEED_40GBPS:
++ fc_host_speed(shost) = FC_PORTSPEED_40GBIT;
++ break;
++ case LPFC_ASYNC_LINK_SPEED_100GBPS:
++ fc_host_speed(shost) = FC_PORTSPEED_100GBIT;
++ break;
++ default:
++ fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
++ break;
++ }
+ } else
+ fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
+
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-lpfc-Limit-tracking-of-tgt-queue-depth-in-fast-.patch b/patches.drivers/scsi-lpfc-Limit-tracking-of-tgt-queue-depth-in-fast-.patch
new file mode 100644
index 0000000000..fe1bd6c96e
--- /dev/null
+++ b/patches.drivers/scsi-lpfc-Limit-tracking-of-tgt-queue-depth-in-fast-.patch
@@ -0,0 +1,325 @@
+From: James Smart <jsmart2021@gmail.com>
+Date: Tue, 31 Jul 2018 17:23:22 -0700
+Subject: [PATCH] scsi: lpfc: Limit tracking of tgt queue depth in fast path
+References: bsc#1102658
+Git-commit: 2a5b7d626ed2256fd0ef0e799ebc6ef47b7bd283
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git
+
+Performance is affected when target queue depth is tracked. An atomic
+counter is incremented on the submission path which competes with it being
+decremented on the completion path. In addition, multiple CPUs can
+simultaniously be manipulating this counter for the same ndlp.
+
+Reduce the overhead by only performing the target increment/decrement when
+the target queue depth is less than the overall adapter depth, thus is
+actually meaningful.
+
+Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
+Signed-off-by: James Smart <james.smart@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/lpfc/lpfc_disc.h | 3 ++
+ drivers/scsi/lpfc/lpfc_nportdisc.c | 6 ----
+ drivers/scsi/lpfc/lpfc_nvme.c | 41 ++++++++++++---------
+ drivers/scsi/lpfc/lpfc_nvme.h | 1 +
+ drivers/scsi/lpfc/lpfc_scsi.c | 74 ++++++++++++++++++++++----------------
+ drivers/scsi/lpfc/lpfc_scsi.h | 2 ++
+ 6 files changed, 74 insertions(+), 53 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
+index 376f02819f20..28e2b60fc5c0 100644
+--- a/drivers/scsi/lpfc/lpfc_disc.h
++++ b/drivers/scsi/lpfc/lpfc_disc.h
+@@ -150,6 +150,9 @@ struct lpfc_node_rrq {
+ unsigned long rrq_stop_time;
+ };
+
++#define lpfc_ndlp_check_qdepth(phba, ndlp) \
++ (ndlp->cmd_qdepth < phba->sli4_hba.max_cfg_param.max_xri)
++
+ /* Defines for nlp_flag (uint32) */
+ #define NLP_IGNR_REG_CMPL 0x00000001 /* Rcvd rscn before we cmpl reg login */
+ #define NLP_REG_LOGIN_SEND 0x00000002 /* sent reglogin to adapter */
+diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
+index 843e765db86d..bd9bce9d9974 100644
+--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
++++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
+@@ -1985,12 +1985,6 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ if (bf_get_be32(prli_disc, nvpr))
+ ndlp->nlp_type |= NLP_NVME_DISCOVERY;
+
+- /* This node is an NVME target. Adjust the command
+- * queue depth on this node to not exceed the available
+- * xris.
+- */
+- ndlp->cmd_qdepth = phba->sli4_hba.nvme_xri_max;
+-
+ /*
+ * If prli_fba is set, the Target supports FirstBurst.
+ * If prli_fb_sz is 0, the FirstBurst size is unlimited,
+diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
+index 32053424d546..028462e5994d 100644
+--- a/drivers/scsi/lpfc/lpfc_nvme.c
++++ b/drivers/scsi/lpfc/lpfc_nvme.c
+@@ -1135,9 +1135,6 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
+ else
+ lpfc_ncmd->flags &= ~LPFC_SBUF_XBUSY;
+
+- if (ndlp && NLP_CHK_NODE_ACT(ndlp))
+- atomic_dec(&ndlp->cmd_pending);
+-
+ /* Update stats and complete the IO. There is
+ * no need for dma unprep because the nvme_transport
+ * owns the dma address.
+@@ -1546,17 +1543,19 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
+ /* The node is shared with FCP IO, make sure the IO pending count does
+ * not exceed the programmed depth.
+ */
+- if ((atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth) &&
+- !expedite) {
+- lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR,
+- "6174 Fail IO, ndlp qdepth exceeded: "
+- "idx %d DID %x pend %d qdepth %d\n",
+- lpfc_queue_info->index, ndlp->nlp_DID,
+- atomic_read(&ndlp->cmd_pending),
+- ndlp->cmd_qdepth);
+- atomic_inc(&lport->xmt_fcp_qdepth);
+- ret = -EBUSY;
+- goto out_fail;
++ if (lpfc_ndlp_check_qdepth(phba, ndlp)) {
++ if ((atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth) &&
++ !expedite) {
++ lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR,
++ "6174 Fail IO, ndlp qdepth exceeded: "
++ "idx %d DID %x pend %d qdepth %d\n",
++ lpfc_queue_info->index, ndlp->nlp_DID,
++ atomic_read(&ndlp->cmd_pending),
++ ndlp->cmd_qdepth);
++ atomic_inc(&lport->xmt_fcp_qdepth);
++ ret = -EBUSY;
++ goto out_fail;
++ }
+ }
+
+ lpfc_ncmd = lpfc_get_nvme_buf(phba, ndlp, expedite);
+@@ -1614,8 +1613,6 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
+ goto out_free_nvme_buf;
+ }
+
+- atomic_inc(&ndlp->cmd_pending);
+-
+ lpfc_nvmeio_data(phba, "NVME FCP XMIT: xri x%x idx %d to %06x\n",
+ lpfc_ncmd->cur_iocbq.sli4_xritag,
+ lpfc_queue_info->index, ndlp->nlp_DID);
+@@ -1623,7 +1620,6 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
+ ret = lpfc_sli4_issue_wqe(phba, LPFC_FCP_RING, &lpfc_ncmd->cur_iocbq);
+ if (ret) {
+ atomic_inc(&lport->xmt_fcp_wqerr);
+- atomic_dec(&ndlp->cmd_pending);
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR,
+ "6113 Fail IO, Could not issue WQE err %x "
+ "sid: x%x did: x%x oxid: x%x\n",
+@@ -2378,6 +2374,11 @@ lpfc_get_nvme_buf(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+ lpfc_ncmd = lpfc_nvme_buf(phba);
+ }
+ spin_unlock_irqrestore(&phba->nvme_buf_list_get_lock, iflag);
++
++ if (lpfc_ndlp_check_qdepth(phba, ndlp) && lpfc_ncmd) {
++ atomic_inc(&ndlp->cmd_pending);
++ lpfc_ncmd->flags |= LPFC_BUMP_QDEPTH;
++ }
+ return lpfc_ncmd;
+ }
+
+@@ -2396,7 +2397,13 @@ lpfc_release_nvme_buf(struct lpfc_hba *phba, struct lpfc_nvme_buf *lpfc_ncmd)
+ {
+ unsigned long iflag = 0;
+
++ if ((lpfc_ncmd->flags & LPFC_BUMP_QDEPTH) && lpfc_ncmd->ndlp)
++ atomic_dec(&lpfc_ncmd->ndlp->cmd_pending);
++
+ lpfc_ncmd->nonsg_phys = 0;
++ lpfc_ncmd->ndlp = NULL;
++ lpfc_ncmd->flags &= ~LPFC_BUMP_QDEPTH;
++
+ if (lpfc_ncmd->flags & LPFC_SBUF_XBUSY) {
+ lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
+ "6310 XB release deferred for "
+diff --git a/drivers/scsi/lpfc/lpfc_nvme.h b/drivers/scsi/lpfc/lpfc_nvme.h
+index 04bd463dd043..cfd4719be25c 100644
+--- a/drivers/scsi/lpfc/lpfc_nvme.h
++++ b/drivers/scsi/lpfc/lpfc_nvme.h
+@@ -86,6 +86,7 @@ struct lpfc_nvme_buf {
+
+ uint16_t flags; /* TBD convert exch_busy to flags */
+ #define LPFC_SBUF_XBUSY 0x1 /* SLI4 hba reported XB on WCQE cmpl */
++#define LPFC_BUMP_QDEPTH 0x2 /* bumped queue depth counter */
+ uint16_t exch_busy; /* SLI4 hba reported XB on complete WCQE */
+ uint16_t status; /* From IOCB Word 7- ulpStatus */
+ uint16_t cpu;
+diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
+index 51ce244cf10a..5c7858e735c9 100644
+--- a/drivers/scsi/lpfc/lpfc_scsi.c
++++ b/drivers/scsi/lpfc/lpfc_scsi.c
+@@ -995,6 +995,11 @@ lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
+ spin_unlock(&phba->scsi_buf_list_put_lock);
+ }
+ spin_unlock_irqrestore(&phba->scsi_buf_list_get_lock, iflag);
++
++ if (lpfc_ndlp_check_qdepth(phba, ndlp) && lpfc_cmd) {
++ atomic_inc(&ndlp->cmd_pending);
++ lpfc_cmd->flags |= LPFC_SBUF_BUMP_QDEPTH;
++ }
+ return lpfc_cmd;
+ }
+ /**
+@@ -1044,6 +1049,11 @@ lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
+ spin_unlock_irqrestore(&phba->scsi_buf_list_get_lock, iflag);
+ if (!found)
+ return NULL;
++
++ if (lpfc_ndlp_check_qdepth(phba, ndlp) && lpfc_cmd) {
++ atomic_inc(&ndlp->cmd_pending);
++ lpfc_cmd->flags |= LPFC_SBUF_BUMP_QDEPTH;
++ }
+ return lpfc_cmd;
+ }
+ /**
+@@ -1134,7 +1144,10 @@ lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
+ static void
+ lpfc_release_scsi_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
+ {
++ if ((psb->flags & LPFC_SBUF_BUMP_QDEPTH) && psb->ndlp)
++ atomic_dec(&psb->ndlp->cmd_pending);
+
++ psb->flags &= ~LPFC_SBUF_BUMP_QDEPTH;
+ phba->lpfc_release_scsi_buf(phba, psb);
+ }
+
+@@ -4130,7 +4143,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
+ msecs_to_jiffies(vport->cfg_max_scsicmpl_time))) {
+ spin_lock_irqsave(shost->host_lock, flags);
+ if (pnode && NLP_CHK_NODE_ACT(pnode)) {
+- atomic_dec(&pnode->cmd_pending);
+ if (pnode->cmd_qdepth >
+ atomic_read(&pnode->cmd_pending) &&
+ (atomic_read(&pnode->cmd_pending) >
+@@ -4143,8 +4155,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
+ pnode->last_change_time = jiffies;
+ }
+ spin_unlock_irqrestore(shost->host_lock, flags);
+- } else if (pnode && NLP_CHK_NODE_ACT(pnode)) {
+- atomic_dec(&pnode->cmd_pending);
+ }
+ lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
+
+@@ -4568,33 +4578,36 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
+ */
+ if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
+ goto out_tgt_busy;
+- if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth) {
+- lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP_ERROR,
+- "3377 Target Queue Full, scsi Id:%d Qdepth:%d"
+- " Pending command:%d"
+- " WWNN:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, "
+- " WWPN:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+- ndlp->nlp_sid, ndlp->cmd_qdepth,
+- atomic_read(&ndlp->cmd_pending),
+- ndlp->nlp_nodename.u.wwn[0],
+- ndlp->nlp_nodename.u.wwn[1],
+- ndlp->nlp_nodename.u.wwn[2],
+- ndlp->nlp_nodename.u.wwn[3],
+- ndlp->nlp_nodename.u.wwn[4],
+- ndlp->nlp_nodename.u.wwn[5],
+- ndlp->nlp_nodename.u.wwn[6],
+- ndlp->nlp_nodename.u.wwn[7],
+- ndlp->nlp_portname.u.wwn[0],
+- ndlp->nlp_portname.u.wwn[1],
+- ndlp->nlp_portname.u.wwn[2],
+- ndlp->nlp_portname.u.wwn[3],
+- ndlp->nlp_portname.u.wwn[4],
+- ndlp->nlp_portname.u.wwn[5],
+- ndlp->nlp_portname.u.wwn[6],
+- ndlp->nlp_portname.u.wwn[7]);
+- goto out_tgt_busy;
++ if (lpfc_ndlp_check_qdepth(phba, ndlp)) {
++ if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth) {
++ lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP_ERROR,
++ "3377 Target Queue Full, scsi Id:%d "
++ "Qdepth:%d Pending command:%d"
++ " WWNN:%02x:%02x:%02x:%02x:"
++ "%02x:%02x:%02x:%02x, "
++ " WWPN:%02x:%02x:%02x:%02x:"
++ "%02x:%02x:%02x:%02x",
++ ndlp->nlp_sid, ndlp->cmd_qdepth,
++ atomic_read(&ndlp->cmd_pending),
++ ndlp->nlp_nodename.u.wwn[0],
++ ndlp->nlp_nodename.u.wwn[1],
++ ndlp->nlp_nodename.u.wwn[2],
++ ndlp->nlp_nodename.u.wwn[3],
++ ndlp->nlp_nodename.u.wwn[4],
++ ndlp->nlp_nodename.u.wwn[5],
++ ndlp->nlp_nodename.u.wwn[6],
++ ndlp->nlp_nodename.u.wwn[7],
++ ndlp->nlp_portname.u.wwn[0],
++ ndlp->nlp_portname.u.wwn[1],
++ ndlp->nlp_portname.u.wwn[2],
++ ndlp->nlp_portname.u.wwn[3],
++ ndlp->nlp_portname.u.wwn[4],
++ ndlp->nlp_portname.u.wwn[5],
++ ndlp->nlp_portname.u.wwn[6],
++ ndlp->nlp_portname.u.wwn[7]);
++ goto out_tgt_busy;
++ }
+ }
+- atomic_inc(&ndlp->cmd_pending);
+
+ lpfc_cmd = lpfc_get_scsi_buf(phba, ndlp);
+ if (lpfc_cmd == NULL) {
+@@ -4612,6 +4625,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
+ */
+ lpfc_cmd->pCmd = cmnd;
+ lpfc_cmd->rdata = rdata;
++ lpfc_cmd->ndlp = ndlp;
+ lpfc_cmd->timeout = 0;
+ lpfc_cmd->start_time = jiffies;
+ cmnd->host_scribble = (unsigned char *)lpfc_cmd;
+@@ -4694,7 +4708,6 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
+ lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
+ lpfc_release_scsi_buf(phba, lpfc_cmd);
+ out_host_busy:
+- atomic_dec(&ndlp->cmd_pending);
+ return SCSI_MLQUEUE_HOST_BUSY;
+
+ out_tgt_busy:
+@@ -5047,6 +5060,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd,
+ lpfc_cmd->timeout = phba->cfg_task_mgmt_tmo;
+ lpfc_cmd->rdata = rdata;
+ lpfc_cmd->pCmd = cmnd;
++ lpfc_cmd->ndlp = pnode;
+
+ status = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun_id,
+ task_mgmt_cmd);
+diff --git a/drivers/scsi/lpfc/lpfc_scsi.h b/drivers/scsi/lpfc/lpfc_scsi.h
+index c38e4da71f5f..cc99859774ff 100644
+--- a/drivers/scsi/lpfc/lpfc_scsi.h
++++ b/drivers/scsi/lpfc/lpfc_scsi.h
+@@ -134,11 +134,13 @@ struct lpfc_scsi_buf {
+ struct list_head list;
+ struct scsi_cmnd *pCmd;
+ struct lpfc_rport_data *rdata;
++ struct lpfc_nodelist *ndlp;
+
+ uint32_t timeout;
+
+ uint16_t flags; /* TBD convert exch_busy to flags */
+ #define LPFC_SBUF_XBUSY 0x1 /* SLI4 hba reported XB on WCQE cmpl */
++#define LPFC_SBUF_BUMP_QDEPTH 0x8 /* bumped queue depth counter */
+ uint16_t exch_busy; /* SLI4 hba reported XB on complete WCQE */
+ uint16_t status; /* From IOCB Word 7- ulpStatus */
+ uint32_t result; /* From IOCB Word 4. */
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-lpfc-Make-PBDE-optimizations-configurable.patch b/patches.drivers/scsi-lpfc-Make-PBDE-optimizations-configurable.patch
new file mode 100644
index 0000000000..159e6d8d64
--- /dev/null
+++ b/patches.drivers/scsi-lpfc-Make-PBDE-optimizations-configurable.patch
@@ -0,0 +1,257 @@
+From: James Smart <jsmart2021@gmail.com>
+Date: Tue, 26 Jun 2018 08:24:26 -0700
+Subject: [PATCH] scsi: lpfc: Make PBDE optimizations configurable
+References: bsc#1102658
+Git-commit: 414abe0ab66f951efe743a3293cb36ac3255214a
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
+Patch-mainline: Queued in subsystem maintainer repository
+
+The PBDE optimizations aren't supported in all firmware revs.
+
+Make optimizations configurable in case there's a side effect on old
+firmware.
+
+Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
+Signed-off-by: James Smart <james.smart@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/lpfc/lpfc.h | 3 +--
+ drivers/scsi/lpfc/lpfc_attr.c | 10 ++++++++++
+ drivers/scsi/lpfc/lpfc_init.c | 22 +++++++---------------
+ drivers/scsi/lpfc/lpfc_nvme.c | 8 ++++----
+ drivers/scsi/lpfc/lpfc_nvmet.c | 23 +++++++++++++----------
+ drivers/scsi/lpfc/lpfc_scsi.c | 14 +++++++++++---
+ drivers/scsi/lpfc/lpfc_sli.c | 8 ++++----
+ 7 files changed, 50 insertions(+), 38 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
+index 20b249a649dd..fc580a9b2bae 100644
+--- a/drivers/scsi/lpfc/lpfc.h
++++ b/drivers/scsi/lpfc/lpfc.h
+@@ -840,8 +840,7 @@ struct lpfc_hba {
+ #define LPFC_ENABLE_FCP 1
+ #define LPFC_ENABLE_NVME 2
+ #define LPFC_ENABLE_BOTH 3
+- uint32_t nvme_embed_pbde;
+- uint32_t fcp_embed_pbde;
++ uint32_t cfg_enable_pbde;
+ uint32_t io_channel_irqs; /* number of irqs for io channels */
+ struct nvmet_fc_target_port *targetport;
+ lpfc_vpd_t vpd; /* vital product data */
+diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
+index 0f8ab3ffb010..ae163713d3b9 100644
+--- a/drivers/scsi/lpfc/lpfc_attr.c
++++ b/drivers/scsi/lpfc/lpfc_attr.c
+@@ -5405,6 +5405,14 @@ LPFC_BBCR_ATTR_RW(enable_bbcr, 1, 0, 1, "Enable BBC Recovery");
+ */
+ LPFC_ATTR_RW(enable_dpp, 1, 0, 1, "Enable Direct Packet Push");
+
++/*
++ * lpfc_enable_pbde: Enable PBDE on PRISM - G7
++ * 0 = PBDE on G7 disabled
++ * 1 = PBDE on G7 enabled (default)
++ * Value range is [0,1]. Default value is 1
++ */
++LPFC_ATTR_R(enable_pbde, 1, 0, 1, "Enable PBDE support on PRISM");
++
+ struct device_attribute *lpfc_hba_attrs[] = {
+ &dev_attr_nvme_info,
+ &dev_attr_bg_info,
+@@ -5516,6 +5524,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
+ &dev_attr_lpfc_enable_mds_diags,
+ &dev_attr_lpfc_enable_bbcr,
+ &dev_attr_lpfc_enable_dpp,
++ &dev_attr_lpfc_enable_pbde,
+ NULL,
+ };
+
+@@ -6538,6 +6547,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
+ lpfc_nvme_io_channel_init(phba, lpfc_nvme_io_channel);
+ lpfc_enable_bbcr_init(phba, lpfc_enable_bbcr);
+ lpfc_enable_dpp_init(phba, lpfc_enable_dpp);
++ lpfc_enable_pbde_init(phba, lpfc_enable_pbde);
+
+ if (phba->sli_rev != LPFC_SLI_REV4) {
+ /* NVME only supported on SLI4 */
+diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
+index 64ccfe735252..cca06206f003 100644
+--- a/drivers/scsi/lpfc/lpfc_init.c
++++ b/drivers/scsi/lpfc/lpfc_init.c
+@@ -10679,18 +10679,10 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
+ phba->cfg_enable_fc4_type = LPFC_ENABLE_FCP;
+ }
+
+- /* Only embed PBDE for if_type 6 */
+- if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
+- LPFC_SLI_INTF_IF_TYPE_6) {
+- phba->fcp_embed_pbde = 1;
+- phba->nvme_embed_pbde = 1;
+- }
+-
+- /* PBDE support requires xib be set */
+- if (!bf_get(cfg_xib, mbx_sli4_parameters)) {
+- phba->fcp_embed_pbde = 0;
+- phba->nvme_embed_pbde = 0;
+- }
++ /* Only embed PBDE for if_type 6, PBDE support requires xib be set */
++ if ((bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
++ LPFC_SLI_INTF_IF_TYPE_6) || (!bf_get(cfg_xib, mbx_sli4_parameters)))
++ phba->cfg_enable_pbde = 0;
+
+ /*
+ * To support Suppress Response feature we must satisfy 3 conditions.
+@@ -10724,10 +10716,10 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
+ phba->fcp_embed_io = 0;
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_NVME,
+- "6422 XIB %d: FCP %d %d NVME %d %d %d %d\n",
++ "6422 XIB %d PBDE %d: FCP %d NVME %d %d %d\n",
+ bf_get(cfg_xib, mbx_sli4_parameters),
+- phba->fcp_embed_pbde, phba->fcp_embed_io,
+- phba->nvme_support, phba->nvme_embed_pbde,
++ phba->cfg_enable_pbde,
++ phba->fcp_embed_io, phba->nvme_support,
+ phba->cfg_nvme_embed_cmd, phba->cfg_suppress_rsp);
+
+ if ((bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
+diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
+index ada5a2aaee82..4cc6783b6a9f 100644
+--- a/drivers/scsi/lpfc/lpfc_nvme.c
++++ b/drivers/scsi/lpfc/lpfc_nvme.c
+@@ -1279,6 +1279,8 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport,
+ /* Word 9 */
+ bf_set(wqe_reqtag, &wqe->generic.wqe_com, pwqeq->iotag);
+
++ /* Words 13 14 15 are for PBDE support */
++
+ pwqeq->vport = vport;
+ return 0;
+ }
+@@ -1378,7 +1380,7 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport,
+ data_sg = sg_next(data_sg);
+ sgl++;
+ }
+- if (phba->nvme_embed_pbde) {
++ if (phba->cfg_enable_pbde) {
+ /* Use PBDE support for first SGL only, offset == 0 */
+ /* Words 13-15 */
+ bde = (struct ulp_bde64 *)
+@@ -1394,10 +1396,8 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport,
+ memset(&wqe->words[13], 0, (sizeof(uint32_t) * 3));
+ bf_set(wqe_pbde, &wqe->generic.wqe_com, 0);
+ }
+- } else {
+- bf_set(wqe_pbde, &wqe->generic.wqe_com, 0);
+- memset(&wqe->words[13], 0, (sizeof(uint32_t) * 3));
+
++ } else {
+ /* For this clause to be valid, the payload_length
+ * and sg_cnt must zero.
+ */
+diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c
+index 102c970a00e6..ccb35efef1e1 100644
+--- a/drivers/scsi/lpfc/lpfc_nvmet.c
++++ b/drivers/scsi/lpfc/lpfc_nvmet.c
+@@ -2493,7 +2493,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
+ bf_set(wqe_xc, &wqe->fcp_treceive.wqe_com, 0);
+
+ /* Word 11 - set pbde later */
+- if (phba->nvme_embed_pbde) {
++ if (phba->cfg_enable_pbde) {
+ do_pbde = 1;
+ } else {
+ bf_set(wqe_pbde, &wqe->fcp_treceive.wqe_com, 0);
+@@ -2608,16 +2608,19 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
+ bf_set(lpfc_sli4_sge_last, sgl, 1);
+ sgl->word2 = cpu_to_le32(sgl->word2);
+ sgl->sge_len = cpu_to_le32(cnt);
+- if (do_pbde && i == 0) {
++ if (i == 0) {
+ bde = (struct ulp_bde64 *)&wqe->words[13];
+- memset(bde, 0, sizeof(struct ulp_bde64));
+- /* Words 13-15 (PBDE)*/
+- bde->addrLow = sgl->addr_lo;
+- bde->addrHigh = sgl->addr_hi;
+- bde->tus.f.bdeSize =
+- le32_to_cpu(sgl->sge_len);
+- bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
+- bde->tus.w = cpu_to_le32(bde->tus.w);
++ if (do_pbde) {
++ /* Words 13-15 (PBDE) */
++ bde->addrLow = sgl->addr_lo;
++ bde->addrHigh = sgl->addr_hi;
++ bde->tus.f.bdeSize =
++ le32_to_cpu(sgl->sge_len);
++ bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
++ bde->tus.w = cpu_to_le32(bde->tus.w);
++ } else {
++ memset(bde, 0, sizeof(struct ulp_bde64));
++ }
+ }
+ sgl++;
+ ctxp->offset += cnt;
+diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
+index 00045daefb17..72abd5c133cf 100644
+--- a/drivers/scsi/lpfc/lpfc_scsi.c
++++ b/drivers/scsi/lpfc/lpfc_scsi.c
+@@ -3311,12 +3311,13 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
+ }
+ /*
+ * Setup the first Payload BDE. For FCoE we just key off
+- * Performance Hints, for FC we utilize fcp_embed_pbde.
++ * Performance Hints, for FC we use lpfc_enable_pbde.
++ * We populate words 13-15 of IOCB/WQE.
+ */
+ if ((phba->sli3_options & LPFC_SLI4_PERFH_ENABLED) ||
+- phba->fcp_embed_pbde) {
++ phba->cfg_enable_pbde) {
+ bde = (struct ulp_bde64 *)
+- &(iocb_cmd->unsli3.sli3Words[5]);
++ &(iocb_cmd->unsli3.sli3Words[5]);
+ bde->addrLow = first_data_sgl->addr_lo;
+ bde->addrHigh = first_data_sgl->addr_hi;
+ bde->tus.f.bdeSize =
+@@ -3330,6 +3331,13 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
+ sgl->word2 = le32_to_cpu(sgl->word2);
+ bf_set(lpfc_sli4_sge_last, sgl, 1);
+ sgl->word2 = cpu_to_le32(sgl->word2);
++
++ if ((phba->sli3_options & LPFC_SLI4_PERFH_ENABLED) ||
++ phba->cfg_enable_pbde) {
++ bde = (struct ulp_bde64 *)
++ &(iocb_cmd->unsli3.sli3Words[5]);
++ memset(bde, 0, (sizeof(uint32_t) * 3));
++ }
+ }
+
+ /*
+diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
+index a25e38ac64e3..2ad16d89d67e 100644
+--- a/drivers/scsi/lpfc/lpfc_sli.c
++++ b/drivers/scsi/lpfc/lpfc_sli.c
+@@ -9123,8 +9123,8 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
+ }
+ /* Note, word 10 is already initialized to 0 */
+
+- /* Don't set PBDE for Perf hints, just fcp_embed_pbde */
+- if (phba->fcp_embed_pbde)
++ /* Don't set PBDE for Perf hints, just lpfc_enable_pbde */
++ if (phba->cfg_enable_pbde)
+ bf_set(wqe_pbde, &wqe->fcp_iwrite.wqe_com, 1);
+ else
+ bf_set(wqe_pbde, &wqe->fcp_iwrite.wqe_com, 0);
+@@ -9187,8 +9187,8 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
+ }
+ /* Note, word 10 is already initialized to 0 */
+
+- /* Don't set PBDE for Perf hints, just fcp_embed_pbde */
+- if (phba->fcp_embed_pbde)
++ /* Don't set PBDE for Perf hints, just lpfc_enable_pbde */
++ if (phba->cfg_enable_pbde)
+ bf_set(wqe_pbde, &wqe->fcp_iread.wqe_com, 1);
+ else
+ bf_set(wqe_pbde, &wqe->fcp_iread.wqe_com, 0);
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-lpfc-Remove-lpfc_enable_pbde-as-module-paramete.patch b/patches.drivers/scsi-lpfc-Remove-lpfc_enable_pbde-as-module-paramete.patch
new file mode 100644
index 0000000000..2ba0173a76
--- /dev/null
+++ b/patches.drivers/scsi-lpfc-Remove-lpfc_enable_pbde-as-module-paramete.patch
@@ -0,0 +1,68 @@
+From: James Smart <jsmart2021@gmail.com>
+Date: Tue, 31 Jul 2018 17:23:24 -0700
+Subject: [PATCH] scsi: lpfc: Remove lpfc_enable_pbde as module parameter
+References: bsc#1102658
+Git-commit: 06b6fa38155ea3709f4d612ae71c201c3f179164
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git
+
+Enablement of the PBDE optimization brought out some incompatible behaviors
+under error scenarios.
+
+Best to disable and remove the PBDE optimization.
+
+Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
+Signed-off-by: James Smart <james.smart@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/lpfc/lpfc_attr.c | 12 ++----------
+ 1 file changed, 2 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
+index 514513f837a8..5a25553415f8 100644
+--- a/drivers/scsi/lpfc/lpfc_attr.c
++++ b/drivers/scsi/lpfc/lpfc_attr.c
+@@ -5387,14 +5387,6 @@ LPFC_BBCR_ATTR_RW(enable_bbcr, 1, 0, 1, "Enable BBC Recovery");
+ */
+ LPFC_ATTR_RW(enable_dpp, 1, 0, 1, "Enable Direct Packet Push");
+
+-/*
+- * lpfc_enable_pbde: Enable PBDE on PRISM - G7
+- * 0 = PBDE on G7 disabled
+- * 1 = PBDE on G7 enabled (default)
+- * Value range is [0,1]. Default value is 1
+- */
+-LPFC_ATTR_R(enable_pbde, 1, 0, 1, "Enable PBDE support on PRISM");
+-
+ struct device_attribute *lpfc_hba_attrs[] = {
+ &dev_attr_nvme_info,
+ &dev_attr_bg_info,
+@@ -5506,7 +5498,6 @@ struct device_attribute *lpfc_hba_attrs[] = {
+ &dev_attr_lpfc_enable_mds_diags,
+ &dev_attr_lpfc_enable_bbcr,
+ &dev_attr_lpfc_enable_dpp,
+- &dev_attr_lpfc_enable_pbde,
+ NULL,
+ };
+
+@@ -6541,7 +6532,6 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
+ lpfc_nvme_io_channel_init(phba, lpfc_nvme_io_channel);
+ lpfc_enable_bbcr_init(phba, lpfc_enable_bbcr);
+ lpfc_enable_dpp_init(phba, lpfc_enable_dpp);
+- lpfc_enable_pbde_init(phba, lpfc_enable_pbde);
+
+ if (phba->sli_rev != LPFC_SLI_REV4) {
+ /* NVME only supported on SLI4 */
+@@ -6558,6 +6548,8 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
+ phba->cfg_auto_imax = 0;
+ phba->initial_imax = phba->cfg_fcp_imax;
+
++ phba->cfg_enable_pbde = 0;
++
+ /* A value of 0 means use the number of CPUs found in the system */
+ if (phba->cfg_fcp_io_channel == 0)
+ phba->cfg_fcp_io_channel = phba->sli4_hba.num_present_cpu;
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-lpfc-Revise-copyright-for-new-company-language.patch b/patches.drivers/scsi-lpfc-Revise-copyright-for-new-company-language.patch
new file mode 100644
index 0000000000..b4ecd4ca1f
--- /dev/null
+++ b/patches.drivers/scsi-lpfc-Revise-copyright-for-new-company-language.patch
@@ -0,0 +1,412 @@
+From: James Smart <jsmart2021@gmail.com>
+Date: Tue, 26 Jun 2018 08:24:31 -0700
+Subject: [PATCH] scsi: lpfc: Revise copyright for new company language
+References: bsc#1102658
+Git-commit: 4ae2ebde318fc120bc91c65a0127b6a225b2d6ed
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
+Patch-mainline: Queued in subsystem maintainer repository
+
+Change references from "Broadcom Limited" to "Broadcom Inc." in the
+copyright message. Update copyright duration if not yet updated for 2018.
+
+Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
+Signed-off-by: James Smart <james.smart@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/lpfc/Makefile | 4 ++--
+ drivers/scsi/lpfc/lpfc.h | 2 +-
+ drivers/scsi/lpfc/lpfc_attr.h | 4 ++--
+ drivers/scsi/lpfc/lpfc_bsg.c | 2 +-
+ drivers/scsi/lpfc/lpfc_bsg.h | 4 ++--
+ drivers/scsi/lpfc/lpfc_compat.h | 4 ++--
+ drivers/scsi/lpfc/lpfc_crtn.h | 2 +-
+ drivers/scsi/lpfc/lpfc_ct.c | 2 +-
+ drivers/scsi/lpfc/lpfc_debugfs.h | 2 +-
+ drivers/scsi/lpfc/lpfc_disc.h | 4 ++--
+ drivers/scsi/lpfc/lpfc_els.c | 2 +-
+ drivers/scsi/lpfc/lpfc_hbadisc.c | 2 +-
+ drivers/scsi/lpfc/lpfc_hw.h | 2 +-
+ drivers/scsi/lpfc/lpfc_ids.h | 2 +-
+ drivers/scsi/lpfc/lpfc_logmsg.h | 4 ++--
+ drivers/scsi/lpfc/lpfc_mbox.c | 2 +-
+ drivers/scsi/lpfc/lpfc_mem.c | 2 +-
+ drivers/scsi/lpfc/lpfc_nl.h | 4 ++--
+ drivers/scsi/lpfc/lpfc_nportdisc.c | 2 +-
+ drivers/scsi/lpfc/lpfc_nvmet.c | 2 +-
+ drivers/scsi/lpfc/lpfc_nvmet.h | 2 +-
+ drivers/scsi/lpfc/lpfc_sli.h | 4 ++--
+ drivers/scsi/lpfc/lpfc_sli4.h | 2 +-
+ drivers/scsi/lpfc/lpfc_version.h | 4 ++--
+ drivers/scsi/lpfc/lpfc_vport.c | 4 ++--
+ drivers/scsi/lpfc/lpfc_vport.h | 4 ++--
+ 26 files changed, 37 insertions(+), 37 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/Makefile b/drivers/scsi/lpfc/Makefile
+index cb6aa802c48e..092a971d066b 100644
+--- a/drivers/scsi/lpfc/Makefile
++++ b/drivers/scsi/lpfc/Makefile
+@@ -1,8 +1,8 @@
+ #/*******************************************************************
+ # * This file is part of the Emulex Linux Device Driver for *
+ # * Fibre Channel Host Bus Adapters. *
+-# * Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
+-# * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++# * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
++# * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ # * Copyright (C) 2004-2012 Emulex. All rights reserved. *
+ # * EMULEX and SLI are trademarks of Emulex. *
+ # * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
+index fc580a9b2bae..e0d0da5f43d6 100644
+--- a/drivers/scsi/lpfc/lpfc.h
++++ b/drivers/scsi/lpfc/lpfc.h
+@@ -2,7 +2,7 @@
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2004-2016 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc_attr.h b/drivers/scsi/lpfc/lpfc_attr.h
+index 931db52692f5..9659a8fff971 100644
+--- a/drivers/scsi/lpfc/lpfc_attr.h
++++ b/drivers/scsi/lpfc/lpfc_attr.h
+@@ -1,8 +1,8 @@
+ /*******************************************************************
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+- * Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2004-2016 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
+index edb1a18a6414..90745feca808 100644
+--- a/drivers/scsi/lpfc/lpfc_bsg.c
++++ b/drivers/scsi/lpfc/lpfc_bsg.c
+@@ -2,7 +2,7 @@
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2009-2015 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc_bsg.h b/drivers/scsi/lpfc/lpfc_bsg.h
+index e7d95a4e8042..32347c87e3b4 100644
+--- a/drivers/scsi/lpfc/lpfc_bsg.h
++++ b/drivers/scsi/lpfc/lpfc_bsg.h
+@@ -1,8 +1,8 @@
+ /*******************************************************************
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+- * Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2010-2015 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc_compat.h b/drivers/scsi/lpfc/lpfc_compat.h
+index 6b32b0ae7506..43cf46a3a71f 100644
+--- a/drivers/scsi/lpfc/lpfc_compat.h
++++ b/drivers/scsi/lpfc/lpfc_compat.h
+@@ -1,8 +1,8 @@
+ /*******************************************************************
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+- * Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2004-2011 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
+index 437476df1130..fe987b26fcd9 100644
+--- a/drivers/scsi/lpfc/lpfc_crtn.h
++++ b/drivers/scsi/lpfc/lpfc_crtn.h
+@@ -2,7 +2,7 @@
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2004-2016 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
+index cbd1372a134a..41b32f48c705 100644
+--- a/drivers/scsi/lpfc/lpfc_ct.c
++++ b/drivers/scsi/lpfc/lpfc_ct.c
+@@ -2,7 +2,7 @@
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2004-2016 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h
+index f32eaeb2225a..30efc7bf91bd 100644
+--- a/drivers/scsi/lpfc/lpfc_debugfs.h
++++ b/drivers/scsi/lpfc/lpfc_debugfs.h
+@@ -2,7 +2,7 @@
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2007-2011 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
+index 5a7547f9d8d8..376f02819f20 100644
+--- a/drivers/scsi/lpfc/lpfc_disc.h
++++ b/drivers/scsi/lpfc/lpfc_disc.h
+@@ -1,8 +1,8 @@
+ /*******************************************************************
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+- * Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2004-2013 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
+index 623d2127c9ad..09159437079d 100644
+--- a/drivers/scsi/lpfc/lpfc_els.c
++++ b/drivers/scsi/lpfc/lpfc_els.c
+@@ -2,7 +2,7 @@
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2004-2016 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
+index 66a3aa0f1255..f430d3dddfa1 100644
+--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
+@@ -2,7 +2,7 @@
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2004-2016 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
+index f6dcabe27ca1..009aa0eee040 100644
+--- a/drivers/scsi/lpfc/lpfc_hw.h
++++ b/drivers/scsi/lpfc/lpfc_hw.h
+@@ -2,7 +2,7 @@
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2004-2016 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc_ids.h b/drivers/scsi/lpfc/lpfc_ids.h
+index 07ee34017d88..d48414e295a0 100644
+--- a/drivers/scsi/lpfc/lpfc_ids.h
++++ b/drivers/scsi/lpfc/lpfc_ids.h
+@@ -2,7 +2,7 @@
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2004-2016 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h
+index 3b654ad08d1f..ea10f03437f5 100644
+--- a/drivers/scsi/lpfc/lpfc_logmsg.h
++++ b/drivers/scsi/lpfc/lpfc_logmsg.h
+@@ -1,8 +1,8 @@
+ /*******************************************************************
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+- * Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2004-2009 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
+index 47c02da11f01..deb094fdbb79 100644
+--- a/drivers/scsi/lpfc/lpfc_mbox.c
++++ b/drivers/scsi/lpfc/lpfc_mbox.c
+@@ -2,7 +2,7 @@
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2004-2016 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
+index f69054afb986..dc272a936d7c 100644
+--- a/drivers/scsi/lpfc/lpfc_mem.c
++++ b/drivers/scsi/lpfc/lpfc_mem.c
+@@ -2,7 +2,7 @@
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2004-2014 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc_nl.h b/drivers/scsi/lpfc/lpfc_nl.h
+index b93e78f671fb..95d60ab5ebf9 100644
+--- a/drivers/scsi/lpfc/lpfc_nl.h
++++ b/drivers/scsi/lpfc/lpfc_nl.h
+@@ -1,8 +1,8 @@
+ /*******************************************************************
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+- * Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2010 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
+index 31089721990b..68f07b7e88da 100644
+--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
++++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
+@@ -2,7 +2,7 @@
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2004-2016 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c
+index ff994712f58a..22f8a204b69f 100644
+--- a/drivers/scsi/lpfc/lpfc_nvmet.c
++++ b/drivers/scsi/lpfc/lpfc_nvmet.c
+@@ -2,7 +2,7 @@
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channsel Host Bus Adapters. *
+ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2004-2016 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc_nvmet.h b/drivers/scsi/lpfc/lpfc_nvmet.h
+index 81f520abfd64..1aaff63f1f41 100644
+--- a/drivers/scsi/lpfc/lpfc_nvmet.h
++++ b/drivers/scsi/lpfc/lpfc_nvmet.h
+@@ -2,7 +2,7 @@
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2004-2016 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h
+index 431754195505..f37f0f33ef2a 100644
+--- a/drivers/scsi/lpfc/lpfc_sli.h
++++ b/drivers/scsi/lpfc/lpfc_sli.h
+@@ -1,8 +1,8 @@
+ /*******************************************************************
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+- * Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2004-2016 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
+index ada68de970b3..399c0015c546 100644
+--- a/drivers/scsi/lpfc/lpfc_sli4.h
++++ b/drivers/scsi/lpfc/lpfc_sli4.h
+@@ -2,7 +2,7 @@
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2009-2016 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
+index 30591e6364ec..a669af45fce7 100644
+--- a/drivers/scsi/lpfc/lpfc_version.h
++++ b/drivers/scsi/lpfc/lpfc_version.h
+@@ -2,7 +2,7 @@
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2004-2016 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+@@ -33,5 +33,5 @@
+ #define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \
+ LPFC_DRIVER_VERSION
+ #define LPFC_COPYRIGHT "Copyright (C) 2017-2018 Broadcom. All Rights " \
+- "Reserved. The term \"Broadcom\" refers to Broadcom Limited " \
++ "Reserved. The term \"Broadcom\" refers to Broadcom Inc. " \
+ "and/or its subsidiaries."
+diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c
+index c9d33b1268cb..48d19d9fbcbb 100644
+--- a/drivers/scsi/lpfc/lpfc_vport.c
++++ b/drivers/scsi/lpfc/lpfc_vport.c
+@@ -1,8 +1,8 @@
+ /*******************************************************************
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+- * Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2004-2016 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+diff --git a/drivers/scsi/lpfc/lpfc_vport.h b/drivers/scsi/lpfc/lpfc_vport.h
+index 62295971f66c..f4b8528dd2e7 100644
+--- a/drivers/scsi/lpfc/lpfc_vport.h
++++ b/drivers/scsi/lpfc/lpfc_vport.h
+@@ -1,8 +1,8 @@
+ /*******************************************************************
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+- * Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
+- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
++ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
++ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
+ * Copyright (C) 2004-2006 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.broadcom.com *
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-lpfc-Support-duration-field-in-Link-Cable-Beaco.patch b/patches.drivers/scsi-lpfc-Support-duration-field-in-Link-Cable-Beaco.patch
new file mode 100644
index 0000000000..6c0a1c9f5d
--- /dev/null
+++ b/patches.drivers/scsi-lpfc-Support-duration-field-in-Link-Cable-Beaco.patch
@@ -0,0 +1,294 @@
+From: James Smart <jsmart2021@gmail.com>
+Date: Tue, 26 Jun 2018 08:24:27 -0700
+Subject: [PATCH] scsi: lpfc: Support duration field in Link Cable Beacon V1
+ command
+References: bsc#1102658
+Git-commit: 66e9e6bf07cb0a2d4bbccebf6a6f1f27e6768e38
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
+Patch-mainline: Queued in subsystem maintainer repository
+
+Current implementation missed setting the duration field. Correct the code
+to set the field.
+
+Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
+Signed-off-by: James Smart <james.smart@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/lpfc/lpfc_els.c | 64 +++++++++++++++++++++++++++++++------------
+ drivers/scsi/lpfc/lpfc_hw.h | 18 +++++++-----
+ drivers/scsi/lpfc/lpfc_hw4.h | 46 ++++++++++++++++++++++++++++---
+ drivers/scsi/lpfc/lpfc_init.c | 1 +
+ drivers/scsi/lpfc/lpfc_sli4.h | 3 ++
+ 5 files changed, 104 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
+index 3d34c8bf285a..623d2127c9ad 100644
+--- a/drivers/scsi/lpfc/lpfc_els.c
++++ b/drivers/scsi/lpfc/lpfc_els.c
+@@ -5640,8 +5640,9 @@ lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+ " mbx status x%x\n",
+ shdr_status, shdr_add_status, mb->mbxStatus);
+
+- if (mb->mbxStatus && !(shdr_status &&
+- shdr_add_status == ADD_STATUS_OPERATION_ALREADY_ACTIVE)) {
++ if ((mb->mbxStatus != MBX_SUCCESS) || shdr_status ||
++ (shdr_add_status == ADD_STATUS_OPERATION_ALREADY_ACTIVE) ||
++ (shdr_add_status == ADD_STATUS_INVALID_REQUEST)) {
+ mempool_free(pmb, phba->mbox_mem_pool);
+ goto error;
+ }
+@@ -5670,6 +5671,7 @@ lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+ lcb_res->lcb_sub_command = lcb_context->sub_command;
+ lcb_res->lcb_type = lcb_context->type;
+ lcb_res->lcb_frequency = lcb_context->frequency;
++ lcb_res->lcb_duration = lcb_context->duration;
+ elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
+ phba->fc_stat.elsXmitACC++;
+ rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
+@@ -5712,6 +5714,7 @@ lpfc_sli4_set_beacon(struct lpfc_vport *vport,
+ uint32_t beacon_state)
+ {
+ struct lpfc_hba *phba = vport->phba;
++ union lpfc_sli4_cfg_shdr *cfg_shdr;
+ LPFC_MBOXQ_t *mbox = NULL;
+ uint32_t len;
+ int rc;
+@@ -5720,6 +5723,7 @@ lpfc_sli4_set_beacon(struct lpfc_vport *vport,
+ if (!mbox)
+ return 1;
+
++ cfg_shdr = &mbox->u.mqe.un.sli4_config.header.cfg_shdr;
+ len = sizeof(struct lpfc_mbx_set_beacon_config) -
+ sizeof(struct lpfc_sli4_cfg_mhdr);
+ lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON,
+@@ -5732,8 +5736,40 @@ lpfc_sli4_set_beacon(struct lpfc_vport *vport,
+ phba->sli4_hba.physical_port);
+ bf_set(lpfc_mbx_set_beacon_state, &mbox->u.mqe.un.beacon_config,
+ beacon_state);
+- bf_set(lpfc_mbx_set_beacon_port_type, &mbox->u.mqe.un.beacon_config, 1);
+- bf_set(lpfc_mbx_set_beacon_duration, &mbox->u.mqe.un.beacon_config, 0);
++ mbox->u.mqe.un.beacon_config.word5 = 0; /* Reserved */
++
++ /*
++ * Check bv1s bit before issuing the mailbox
++ * if bv1s == 1, LCB V1 supported
++ * else, LCB V0 supported
++ */
++
++ if (phba->sli4_hba.pc_sli4_params.bv1s) {
++ /* COMMON_SET_BEACON_CONFIG_V1 */
++ cfg_shdr->request.word9 = BEACON_VERSION_V1;
++ lcb_context->capability |= LCB_CAPABILITY_DURATION;
++ bf_set(lpfc_mbx_set_beacon_port_type,
++ &mbox->u.mqe.un.beacon_config, 0);
++ bf_set(lpfc_mbx_set_beacon_duration_v1,
++ &mbox->u.mqe.un.beacon_config,
++ be16_to_cpu(lcb_context->duration));
++ } else {
++ /* COMMON_SET_BEACON_CONFIG_V0 */
++ if (be16_to_cpu(lcb_context->duration) != 0) {
++ mempool_free(mbox, phba->mbox_mem_pool);
++ return 1;
++ }
++ cfg_shdr->request.word9 = BEACON_VERSION_V0;
++ lcb_context->capability &= ~(LCB_CAPABILITY_DURATION);
++ bf_set(lpfc_mbx_set_beacon_state,
++ &mbox->u.mqe.un.beacon_config, beacon_state);
++ bf_set(lpfc_mbx_set_beacon_port_type,
++ &mbox->u.mqe.un.beacon_config, 1);
++ bf_set(lpfc_mbx_set_beacon_duration,
++ &mbox->u.mqe.un.beacon_config,
++ be16_to_cpu(lcb_context->duration));
++ }
++
+ rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
+ if (rc == MBX_NOT_FINISHED) {
+ mempool_free(mbox, phba->mbox_mem_pool);
+@@ -5784,24 +5820,16 @@ lpfc_els_rcv_lcb(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+ beacon->lcb_frequency,
+ be16_to_cpu(beacon->lcb_duration));
+
+- if (phba->sli_rev < LPFC_SLI_REV4 ||
+- (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
+- LPFC_SLI_INTF_IF_TYPE_2)) {
+- rjt_err = LSRJT_CMD_UNSUPPORTED;
+- goto rjt;
+- }
+-
+- if (phba->hba_flag & HBA_FCOE_MODE) {
+- rjt_err = LSRJT_CMD_UNSUPPORTED;
+- goto rjt;
+- }
+ if (beacon->lcb_sub_command != LPFC_LCB_ON &&
+ beacon->lcb_sub_command != LPFC_LCB_OFF) {
+ rjt_err = LSRJT_CMD_UNSUPPORTED;
+ goto rjt;
+ }
+- if (beacon->lcb_sub_command == LPFC_LCB_ON &&
+- be16_to_cpu(beacon->lcb_duration) != 0) {
++
++ if (phba->sli_rev < LPFC_SLI_REV4 ||
++ phba->hba_flag & HBA_FCOE_MODE ||
++ (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) <
++ LPFC_SLI_INTF_IF_TYPE_2)) {
+ rjt_err = LSRJT_CMD_UNSUPPORTED;
+ goto rjt;
+ }
+@@ -5814,8 +5842,10 @@ lpfc_els_rcv_lcb(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+
+ state = (beacon->lcb_sub_command == LPFC_LCB_ON) ? 1 : 0;
+ lcb_context->sub_command = beacon->lcb_sub_command;
++ lcb_context->capability = 0;
+ lcb_context->type = beacon->lcb_type;
+ lcb_context->frequency = beacon->lcb_frequency;
++ lcb_context->duration = beacon->lcb_duration;
+ lcb_context->ox_id = cmdiocb->iocb.unsli3.rcvsli3.ox_id;
+ lcb_context->rx_id = cmdiocb->iocb.ulpContext;
+ lcb_context->ndlp = lpfc_nlp_get(ndlp);
+diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
+index 08a3f1520159..f6dcabe27ca1 100644
+--- a/drivers/scsi/lpfc/lpfc_hw.h
++++ b/drivers/scsi/lpfc/lpfc_hw.h
+@@ -1065,14 +1065,17 @@ typedef struct _ELS_PKT { /* Structure is in Big Endian format */
+ struct fc_lcb_request_frame {
+ uint32_t lcb_command; /* ELS command opcode (0x81) */
+ uint8_t lcb_sub_command;/* LCB Payload Word 1, bit 24:31 */
+-#define LPFC_LCB_ON 0x1
+-#define LPFC_LCB_OFF 0x2
+- uint8_t reserved[3];
+-
++#define LPFC_LCB_ON 0x1
++#define LPFC_LCB_OFF 0x2
++ uint8_t reserved[2];
++ uint8_t capability; /* LCB Payload Word 1, bit 0:7 */
+ uint8_t lcb_type; /* LCB Payload Word 2, bit 24:31 */
+-#define LPFC_LCB_GREEN 0x1
+-#define LPFC_LCB_AMBER 0x2
++#define LPFC_LCB_GREEN 0x1
++#define LPFC_LCB_AMBER 0x2
+ uint8_t lcb_frequency; /* LCB Payload Word 2, bit 16:23 */
++#define LCB_CAPABILITY_DURATION 1
++#define BEACON_VERSION_V1 1
++#define BEACON_VERSION_V0 0
+ uint16_t lcb_duration; /* LCB Payload Word 2, bit 15:0 */
+ };
+
+@@ -1082,7 +1085,8 @@ struct fc_lcb_request_frame {
+ struct fc_lcb_res_frame {
+ uint32_t lcb_ls_acc; /* Acceptance of LCB request (0x02) */
+ uint8_t lcb_sub_command;/* LCB Payload Word 1, bit 24:31 */
+- uint8_t reserved[3];
++ uint8_t reserved[2];
++ uint8_t capability; /* LCB Payload Word 1, bit 0:7 */
+ uint8_t lcb_type; /* LCB Payload Word 2, bit 24:31 */
+ uint8_t lcb_frequency; /* LCB Payload Word 2, bit 16:23 */
+ uint16_t lcb_duration; /* LCB Payload Word 2, bit 15:0 */
+diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
+index f43f0bacb77a..083f8c8706e5 100644
+--- a/drivers/scsi/lpfc/lpfc_hw4.h
++++ b/drivers/scsi/lpfc/lpfc_hw4.h
+@@ -1790,9 +1790,12 @@ struct lpfc_mbx_set_beacon_config {
+ #define lpfc_mbx_set_beacon_duration_SHIFT 16
+ #define lpfc_mbx_set_beacon_duration_MASK 0x000000FF
+ #define lpfc_mbx_set_beacon_duration_WORD word4
+-#define lpfc_mbx_set_beacon_status_duration_SHIFT 24
+-#define lpfc_mbx_set_beacon_status_duration_MASK 0x000000FF
+-#define lpfc_mbx_set_beacon_status_duration_WORD word4
++
++/* COMMON_SET_BEACON_CONFIG_V1 */
++#define lpfc_mbx_set_beacon_duration_v1_SHIFT 16
++#define lpfc_mbx_set_beacon_duration_v1_MASK 0x0000FFFF
++#define lpfc_mbx_set_beacon_duration_v1_WORD word4
++ uint32_t word5; /* RESERVED */
+ };
+
+ struct lpfc_id_range {
+@@ -2243,6 +2246,7 @@ struct lpfc_mbx_redisc_fcf_tbl {
+ */
+ #define ADD_STATUS_OPERATION_ALREADY_ACTIVE 0x67
+ #define ADD_STATUS_FW_NOT_SUPPORTED 0xEB
++#define ADD_STATUS_INVALID_REQUEST 0x4B
+
+ struct lpfc_mbx_sli4_config {
+ struct mbox_header header;
+@@ -3392,7 +3396,41 @@ struct lpfc_sli4_parameters {
+ #define cfg_nosr_SHIFT 9
+ #define cfg_nosr_MASK 0x00000001
+ #define cfg_nosr_WORD word19
+-#define LPFC_NODELAY_MAX_IO 32
++
++#define cfg_bv1s_SHIFT 10
++#define cfg_bv1s_MASK 0x00000001
++#define cfg_bv1s_WORD word19
++
++ uint32_t word20;
++#define cfg_max_tow_xri_SHIFT 0
++#define cfg_max_tow_xri_MASK 0x0000ffff
++#define cfg_max_tow_xri_WORD word20
++
++ uint32_t word21; /* RESERVED */
++ uint32_t word22; /* RESERVED */
++ uint32_t word23; /* RESERVED */
++
++ uint32_t word24;
++#define cfg_frag_field_offset_SHIFT 0
++#define cfg_frag_field_offset_MASK 0x0000ffff
++#define cfg_frag_field_offset_WORD word24
++
++#define cfg_frag_field_size_SHIFT 16
++#define cfg_frag_field_size_MASK 0x0000ffff
++#define cfg_frag_field_size_WORD word24
++
++ uint32_t word25;
++#define cfg_sgl_field_offset_SHIFT 0
++#define cfg_sgl_field_offset_MASK 0x0000ffff
++#define cfg_sgl_field_offset_WORD word25
++
++#define cfg_sgl_field_size_SHIFT 16
++#define cfg_sgl_field_size_MASK 0x0000ffff
++#define cfg_sgl_field_size_WORD word25
++
++ uint32_t word26; /* Chain SGE initial value LOW */
++ uint32_t word27; /* Chain SGE initial value HIGH */
++#define LPFC_NODELAY_MAX_IO 32
+ };
+
+ #define LPFC_SET_UE_RECOVERY 0x10
+diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
+index cca06206f003..3b1d83feb98f 100644
+--- a/drivers/scsi/lpfc/lpfc_init.c
++++ b/drivers/scsi/lpfc/lpfc_init.c
+@@ -10650,6 +10650,7 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
+ sli4_params->eqav = bf_get(cfg_eqav, mbx_sli4_parameters);
+ sli4_params->cqav = bf_get(cfg_cqav, mbx_sli4_parameters);
+ sli4_params->wqsize = bf_get(cfg_wqsize, mbx_sli4_parameters);
++ sli4_params->bv1s = bf_get(cfg_bv1s, mbx_sli4_parameters);
+ sli4_params->sgl_pages_max = bf_get(cfg_sgl_page_cnt,
+ mbx_sli4_parameters);
+ sli4_params->wqpcnt = bf_get(cfg_wqpcnt, mbx_sli4_parameters);
+diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
+index cf64aca82bd0..ada68de970b3 100644
+--- a/drivers/scsi/lpfc/lpfc_sli4.h
++++ b/drivers/scsi/lpfc/lpfc_sli4.h
+@@ -490,6 +490,7 @@ struct lpfc_pc_sli4_params {
+ uint8_t eqav;
+ uint8_t cqav;
+ uint8_t wqsize;
++ uint8_t bv1s;
+ #define LPFC_WQ_SZ64_SUPPORT 1
+ #define LPFC_WQ_SZ128_SUPPORT 2
+ uint8_t wqpcnt;
+@@ -774,7 +775,9 @@ struct lpfc_rdp_context {
+ struct lpfc_lcb_context {
+ uint8_t sub_command;
+ uint8_t type;
++ uint8_t capability;
+ uint8_t frequency;
++ uint16_t duration;
+ uint16_t ox_id;
+ uint16_t rx_id;
+ struct lpfc_nodelist *ndlp;
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-lpfc-devloss-timeout-race-condition-caused-null.patch b/patches.drivers/scsi-lpfc-devloss-timeout-race-condition-caused-null.patch
new file mode 100644
index 0000000000..fb254aae1b
--- /dev/null
+++ b/patches.drivers/scsi-lpfc-devloss-timeout-race-condition-caused-null.patch
@@ -0,0 +1,94 @@
+From: James Smart <jsmart2021@gmail.com>
+Date: Tue, 26 Jun 2018 08:24:29 -0700
+Subject: [PATCH] scsi: lpfc: devloss timeout race condition caused null
+ pointer reference
+References: bsc#1102658
+Git-commit: b0e830125b669570d8096b8ba22eb00f659fc05e
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
+Patch-mainline: Queued in subsystem maintainer repository
+
+A race condition between the context of devloss timeout handler and I/O
+completion caused devloss timeout handler de-referencing pointer that had
+been released.
+
+Added the check in lpfc_sli_validate_fcp_iocb() on LPFC_IO_ON_TXCMPLQ to
+capture the race condition of I/O completion and devloss timeout handler
+attemption for aborting the I/O. Also, added check on lpfc_cmd->rdata
+pointer before de-referenceing lpfc_cmd->rdata->pnode.
+
+Also, added protection in lpfc_sli_abort_iocb() routine on driver performed
+FCP I/O FLUSHING already under way before proceeding to aborting I/Os.
+
+Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
+Signed-off-by: James Smart <james.smart@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/lpfc/lpfc_scsi.c | 5 +++++
+ drivers/scsi/lpfc/lpfc_sli.c | 13 +++++++++----
+ 2 files changed, 14 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
+index 72abd5c133cf..8f5ef50dbb4e 100644
+--- a/drivers/scsi/lpfc/lpfc_scsi.c
++++ b/drivers/scsi/lpfc/lpfc_scsi.c
+@@ -4538,6 +4538,11 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
+ int err;
+
+ rdata = lpfc_rport_data_from_scsi_device(cmnd->device);
++
++ /* sanity check on references */
++ if (unlikely(!rdata) || unlikely(!rport))
++ goto out_fail_command;
++
+ err = fc_remote_port_chkready(rport);
+ if (err) {
+ cmnd->result = err;
+diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
+index 2ad16d89d67e..bbb286c6c94e 100644
+--- a/drivers/scsi/lpfc/lpfc_sli.c
++++ b/drivers/scsi/lpfc/lpfc_sli.c
+@@ -11097,10 +11097,11 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport,
+ struct lpfc_scsi_buf *lpfc_cmd;
+ int rc = 1;
+
+- if (!(iocbq->iocb_flag & LPFC_IO_FCP))
++ if (iocbq->vport != vport)
+ return rc;
+
+- if (iocbq->vport != vport)
++ if (!(iocbq->iocb_flag & LPFC_IO_FCP) ||
++ !(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ))
+ return rc;
+
+ lpfc_cmd = container_of(iocbq, struct lpfc_scsi_buf, cur_iocbq);
+@@ -11110,13 +11111,13 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport,
+
+ switch (ctx_cmd) {
+ case LPFC_CTX_LUN:
+- if ((lpfc_cmd->rdata->pnode) &&
++ if ((lpfc_cmd->rdata) && (lpfc_cmd->rdata->pnode) &&
+ (lpfc_cmd->rdata->pnode->nlp_sid == tgt_id) &&
+ (scsilun_to_int(&lpfc_cmd->fcp_cmnd->fcp_lun) == lun_id))
+ rc = 0;
+ break;
+ case LPFC_CTX_TGT:
+- if ((lpfc_cmd->rdata->pnode) &&
++ if ((lpfc_cmd->rdata) && (lpfc_cmd->rdata->pnode) &&
+ (lpfc_cmd->rdata->pnode->nlp_sid == tgt_id))
+ rc = 0;
+ break;
+@@ -11231,6 +11232,10 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
+ int errcnt = 0, ret_val = 0;
+ int i;
+
++ /* all I/Os are in process of being flushed */
++ if (phba->hba_flag & HBA_FCP_IOQ_FLUSH)
++ return errcnt;
++
+ for (i = 1; i <= phba->sli.last_iotag; i++) {
+ iocbq = phba->sli.iocbq_lookup[i];
+
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-lpfc-update-driver-version-to-12.0.0.5.patch b/patches.drivers/scsi-lpfc-update-driver-version-to-12.0.0.5.patch
new file mode 100644
index 0000000000..a9242c89ea
--- /dev/null
+++ b/patches.drivers/scsi-lpfc-update-driver-version-to-12.0.0.5.patch
@@ -0,0 +1,34 @@
+From: James Smart <jsmart2021@gmail.com>
+Date: Tue, 26 Jun 2018 08:24:30 -0700
+Subject: [PATCH] scsi: lpfc: update driver version to 12.0.0.5
+References: bsc#1102658
+Git-commit: 3e1ebadd889f2670ecef77157d84261d09a5ca41
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
+Patch-mainline: Queued in subsystem maintainer repository
+
+Update the driver version to 12.0.0.5
+
+Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
+Signed-off-by: James Smart <james.smart@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/lpfc/lpfc_version.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
+index 18c23afcf46b..30591e6364ec 100644
+--- a/drivers/scsi/lpfc/lpfc_version.h
++++ b/drivers/scsi/lpfc/lpfc_version.h
+@@ -20,7 +20,7 @@
+ * included with this package. *
+ *******************************************************************/
+
+-#define LPFC_DRIVER_VERSION "12.0.0.4"
++#define LPFC_DRIVER_VERSION "12.0.0.5"
+ #define LPFC_DRIVER_NAME "lpfc"
+
+ /* Used for SLI 2/3 */
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-lpfc-update-driver-version-to-12.0.0.6.patch b/patches.drivers/scsi-lpfc-update-driver-version-to-12.0.0.6.patch
new file mode 100644
index 0000000000..14d0455ea4
--- /dev/null
+++ b/patches.drivers/scsi-lpfc-update-driver-version-to-12.0.0.6.patch
@@ -0,0 +1,34 @@
+From: James Smart <jsmart2021@gmail.com>
+Date: Tue, 31 Jul 2018 17:23:25 -0700
+Subject: [PATCH] scsi: lpfc: update driver version to 12.0.0.6
+References: bsc#1102658
+Git-commit: 7fa8512330ab7cbb394b3e42ee092f4ad2e8f906
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git
+
+Update the driver version to 12.0.0.6
+
+Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
+Signed-off-by: James Smart <james.smart@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/lpfc/lpfc_version.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
+index a669af45fce7..501249509af4 100644
+--- a/drivers/scsi/lpfc/lpfc_version.h
++++ b/drivers/scsi/lpfc/lpfc_version.h
+@@ -20,7 +20,7 @@
+ * included with this package. *
+ *******************************************************************/
+
+-#define LPFC_DRIVER_VERSION "12.0.0.5"
++#define LPFC_DRIVER_VERSION "12.0.0.6"
+ #define LPFC_DRIVER_NAME "lpfc"
+
+ /* Used for SLI 2/3 */
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-smartpqi-add-in-new-supported-controllers.patch b/patches.drivers/scsi-smartpqi-add-in-new-supported-controllers.patch
new file mode 100644
index 0000000000..143d53fae6
--- /dev/null
+++ b/patches.drivers/scsi-smartpqi-add-in-new-supported-controllers.patch
@@ -0,0 +1,88 @@
+From: Kevin Barnett <kevin.barnett@microsemi.com>
+Date: Mon, 5 Mar 2018 09:01:00 -0600
+Subject: [PATCH] scsi: smartpqi: add in new supported controllers
+References: bsc#1086274
+Git-commit: b0f9408b14838566b2a9b26434fab667c2afb0ea
+Patch-mainline: v4.17-rc1
+
+Reviewed-by: Scott Benesh <scott.benesh@microsemi.com>
+Signed-off-by: Kevin Barnett <kevin.barnett@microsemi.com>
+Signed-off-by: Don Brace <don.brace@microsemi.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/smartpqi/smartpqi_init.c | 44 +++++++++++++++++++++++++++++++++++
+ 1 file changed, 44 insertions(+)
+
+diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
+index 8fe918398336..68f82cee0720 100644
+--- a/drivers/scsi/smartpqi/smartpqi_init.c
++++ b/drivers/scsi/smartpqi/smartpqi_init.c
+@@ -6798,6 +6798,14 @@ static __maybe_unused int pqi_resume(struct pci_dev *pci_dev)
+ static const struct pci_device_id pqi_pci_id_table[] = {
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++ 0x105b, 0x1211)
++ },
++ {
++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++ 0x105b, 0x1321)
++ },
++ {
++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x152d, 0x8a22)
+ },
+ {
+@@ -6818,6 +6826,38 @@ static const struct pci_device_id pqi_pci_id_table[] = {
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++ 0x193d, 0x8460)
++ },
++ {
++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++ 0x193d, 0x8461)
++ },
++ {
++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++ 0x193d, 0xf460)
++ },
++ {
++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++ 0x193d, 0xf461)
++ },
++ {
++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++ 0x1bd4, 0x0045)
++ },
++ {
++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++ 0x1bd4, 0x0046)
++ },
++ {
++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++ 0x1bd4, 0x0047)
++ },
++ {
++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++ 0x1bd4, 0x0048)
++ },
++ {
++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ PCI_VENDOR_ID_ADAPTEC2, 0x0110)
+ },
+ {
+@@ -6918,6 +6958,10 @@ static const struct pci_device_id pqi_pci_id_table[] = {
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++ PCI_VENDOR_ID_ADAPTEC2, 0x1282)
++ },
++ {
++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ PCI_VENDOR_ID_ADAPTEC2, 0x1300)
+ },
+ {
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-smartpqi-add-inspur-advantech-ids.patch b/patches.drivers/scsi-smartpqi-add-inspur-advantech-ids.patch
new file mode 100644
index 0000000000..0b1c600f3d
--- /dev/null
+++ b/patches.drivers/scsi-smartpqi-add-inspur-advantech-ids.patch
@@ -0,0 +1,61 @@
+From: Kevin Barnett <kevin.barnett@microsemi.com>
+Date: Mon, 18 Jun 2018 13:22:54 -0500
+Subject: [PATCH] scsi: smartpqi: add inspur advantech ids
+References: bsc#1086274
+Git-commit: 9f8d05fa98442de78d1ab30235b0cc656ed7aff0
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
+Patch-mainline: Queued in subsystem maintainer repository
+
+Add support for these new device IDs:
+
+ Advantech MIC-8312BridgeB
+ INSPUR PM8204-2GB
+ INSPUR PM8204-4GB
+ INSPUR PM8222-SHBA
+
+Reviewed-by: Scott Benesh <scott.benesh@microsemi.com>
+Signed-off-by: Kevin Barnett <kevin.barnett@microsemi.com>
+Signed-off-by: Don Brace <don.brace@microsemi.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/smartpqi/smartpqi_init.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
+index d3f1450e11a1..ee30d9b8995f 100644
+--- a/drivers/scsi/smartpqi/smartpqi_init.c
++++ b/drivers/scsi/smartpqi/smartpqi_init.c
+@@ -6838,6 +6838,18 @@ static const struct pci_device_id pqi_pci_id_table[] = {
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++ 0x1bd4, 0x004a)
++ },
++ {
++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++ 0x1bd4, 0x004b)
++ },
++ {
++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++ 0x1bd4, 0x004c)
++ },
++ {
++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ PCI_VENDOR_ID_ADAPTEC2, 0x0110)
+ },
+ {
+@@ -6962,6 +6974,10 @@ static const struct pci_device_id pqi_pci_id_table[] = {
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++ PCI_VENDOR_ID_ADVANTECH, 0x8312)
++ },
++ {
++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ PCI_VENDOR_ID_DELL, 0x1fe0)
+ },
+ {
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-smartpqi-bump-driver-version-to-1.1.4-130.patch b/patches.drivers/scsi-smartpqi-bump-driver-version-to-1.1.4-130.patch
new file mode 100644
index 0000000000..ccec2f4d06
--- /dev/null
+++ b/patches.drivers/scsi-smartpqi-bump-driver-version-to-1.1.4-130.patch
@@ -0,0 +1,38 @@
+From: Don Brace <don.brace@microsemi.com>
+Date: Mon, 18 Jun 2018 13:23:06 -0500
+Subject: [PATCH] scsi: smartpqi: bump driver version to 1.1.4-130
+References: bsc#1086274
+Git-commit: 4ae5e9d159f83392c98c4ed88dfc63f19745be38
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
+Patch-mainline: Queued in subsystem maintainer repository
+
+Reviewed-by: Scott Benesh <scott.benesh@microsemi.com>
+Signed-off-by: Kevin Barnett <kevin.barnett@microsemi.com>
+Signed-off-by: Don Brace <don.brace@microsemi.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/smartpqi/smartpqi_init.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
+index 102f0757a8d2..9295f4842c7b 100644
+--- a/drivers/scsi/smartpqi/smartpqi_init.c
++++ b/drivers/scsi/smartpqi/smartpqi_init.c
+@@ -40,11 +40,11 @@
+ #define BUILD_TIMESTAMP
+ #endif
+
+-#define DRIVER_VERSION "1.1.4-115"
++#define DRIVER_VERSION "1.1.4-130"
+ #define DRIVER_MAJOR 1
+ #define DRIVER_MINOR 1
+ #define DRIVER_RELEASE 4
+-#define DRIVER_REVISION 115
++#define DRIVER_REVISION 130
+
+ #define DRIVER_NAME "Microsemi PQI Driver (v" \
+ DRIVER_VERSION BUILD_TIMESTAMP ")"
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-smartpqi-fix-critical-ARM-issue-reading-PQI-ind.patch b/patches.drivers/scsi-smartpqi-fix-critical-ARM-issue-reading-PQI-ind.patch
new file mode 100644
index 0000000000..1654a39aea
--- /dev/null
+++ b/patches.drivers/scsi-smartpqi-fix-critical-ARM-issue-reading-PQI-ind.patch
@@ -0,0 +1,224 @@
+From: Kevin Barnett <kevin.barnett@microsemi.com>
+Date: Mon, 18 Jun 2018 13:23:00 -0500
+Subject: [PATCH] scsi: smartpqi: fix critical ARM issue reading PQI index
+ registers
+References: bsc#1086274
+Git-commit: dac12fbc7b0a433a160b89212a56e155c94f3a80
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
+Patch-mainline: Queued in subsystem maintainer repository
+
+Use the readl() kernel function to read all index registers. For ARM
+systems, this function includes a read memory barrier that eliminates ci/pi
+corruption.
+
+Reviewed-by: Scott Benesh <scott.benesh@microsemi.com>
+Reviewed-by: Scott Teel <scott.teel@microsemi.com>
+Tested-by: Shunyong Yang <shunyong.yang@hxt-semitech.com>
+Signed-off-by: Kevin Barnett <kevin.barnett@microsemi.com>
+Signed-off-by: Don Brace <don.brace@microsemi.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/smartpqi/smartpqi.h | 10 ++++----
+ drivers/scsi/smartpqi/smartpqi_init.c | 45 +++++++++++++++++++----------------
+ 2 files changed, 30 insertions(+), 25 deletions(-)
+
+diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
+index a8e7c4d48061..e97bf2670315 100644
+--- a/drivers/scsi/smartpqi/smartpqi.h
++++ b/drivers/scsi/smartpqi/smartpqi.h
+@@ -583,8 +583,8 @@ struct pqi_admin_queues_aligned {
+ struct pqi_admin_queues {
+ void *iq_element_array;
+ void *oq_element_array;
+- volatile pqi_index_t *iq_ci;
+- volatile pqi_index_t *oq_pi;
++ pqi_index_t *iq_ci;
++ pqi_index_t __iomem *oq_pi;
+ dma_addr_t iq_element_array_bus_addr;
+ dma_addr_t oq_element_array_bus_addr;
+ dma_addr_t iq_ci_bus_addr;
+@@ -608,8 +608,8 @@ struct pqi_queue_group {
+ dma_addr_t oq_element_array_bus_addr;
+ __le32 __iomem *iq_pi[2];
+ pqi_index_t iq_pi_copy[2];
+- volatile pqi_index_t *iq_ci[2];
+- volatile pqi_index_t *oq_pi;
++ pqi_index_t __iomem *iq_ci[2];
++ pqi_index_t __iomem *oq_pi;
+ dma_addr_t iq_ci_bus_addr[2];
+ dma_addr_t oq_pi_bus_addr;
+ __le32 __iomem *oq_ci;
+@@ -622,7 +622,7 @@ struct pqi_event_queue {
+ u16 oq_id;
+ u16 int_msg_num;
+ void *oq_element_array;
+- volatile pqi_index_t *oq_pi;
++ pqi_index_t __iomem *oq_pi;
+ dma_addr_t oq_element_array_bus_addr;
+ dma_addr_t oq_pi_bus_addr;
+ __le32 __iomem *oq_ci;
+diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
+index ee30d9b8995f..102f0757a8d2 100644
+--- a/drivers/scsi/smartpqi/smartpqi_init.c
++++ b/drivers/scsi/smartpqi/smartpqi_init.c
+@@ -2702,7 +2702,7 @@ static unsigned int pqi_process_io_intr(struct pqi_ctrl_info *ctrl_info,
+ oq_ci = queue_group->oq_ci_copy;
+
+ while (1) {
+- oq_pi = *queue_group->oq_pi;
++ oq_pi = readl(queue_group->oq_pi);
+ if (oq_pi == oq_ci)
+ break;
+
+@@ -2793,7 +2793,7 @@ static void pqi_send_event_ack(struct pqi_ctrl_info *ctrl_info,
+ spin_lock_irqsave(&queue_group->submit_lock[RAID_PATH], flags);
+
+ iq_pi = queue_group->iq_pi_copy[RAID_PATH];
+- iq_ci = *queue_group->iq_ci[RAID_PATH];
++ iq_ci = readl(queue_group->iq_ci[RAID_PATH]);
+
+ if (pqi_num_elements_free(iq_pi, iq_ci,
+ ctrl_info->num_elements_per_iq))
+@@ -2953,7 +2953,7 @@ static unsigned int pqi_process_event_intr(struct pqi_ctrl_info *ctrl_info)
+ oq_ci = event_queue->oq_ci_copy;
+
+ while (1) {
+- oq_pi = *event_queue->oq_pi;
++ oq_pi = readl(event_queue->oq_pi);
+ if (oq_pi == oq_ci)
+ break;
+
+@@ -3177,7 +3177,7 @@ static int pqi_alloc_operational_queues(struct pqi_ctrl_info *ctrl_info)
+ size_t element_array_length_per_iq;
+ size_t element_array_length_per_oq;
+ void *element_array;
+- void *next_queue_index;
++ void __iomem *next_queue_index;
+ void *aligned_pointer;
+ unsigned int num_inbound_queues;
+ unsigned int num_outbound_queues;
+@@ -3273,7 +3273,7 @@ static int pqi_alloc_operational_queues(struct pqi_ctrl_info *ctrl_info)
+ element_array += PQI_NUM_EVENT_QUEUE_ELEMENTS *
+ PQI_EVENT_OQ_ELEMENT_LENGTH;
+
+- next_queue_index = PTR_ALIGN(element_array,
++ next_queue_index = (void __iomem *)PTR_ALIGN(element_array,
+ PQI_OPERATIONAL_INDEX_ALIGNMENT);
+
+ for (i = 0; i < ctrl_info->num_queue_groups; i++) {
+@@ -3281,21 +3281,24 @@ static int pqi_alloc_operational_queues(struct pqi_ctrl_info *ctrl_info)
+ queue_group->iq_ci[RAID_PATH] = next_queue_index;
+ queue_group->iq_ci_bus_addr[RAID_PATH] =
+ ctrl_info->queue_memory_base_dma_handle +
+- (next_queue_index - ctrl_info->queue_memory_base);
++ (next_queue_index -
++ (void __iomem *)ctrl_info->queue_memory_base);
+ next_queue_index += sizeof(pqi_index_t);
+ next_queue_index = PTR_ALIGN(next_queue_index,
+ PQI_OPERATIONAL_INDEX_ALIGNMENT);
+ queue_group->iq_ci[AIO_PATH] = next_queue_index;
+ queue_group->iq_ci_bus_addr[AIO_PATH] =
+ ctrl_info->queue_memory_base_dma_handle +
+- (next_queue_index - ctrl_info->queue_memory_base);
++ (next_queue_index -
++ (void __iomem *)ctrl_info->queue_memory_base);
+ next_queue_index += sizeof(pqi_index_t);
+ next_queue_index = PTR_ALIGN(next_queue_index,
+ PQI_OPERATIONAL_INDEX_ALIGNMENT);
+ queue_group->oq_pi = next_queue_index;
+ queue_group->oq_pi_bus_addr =
+ ctrl_info->queue_memory_base_dma_handle +
+- (next_queue_index - ctrl_info->queue_memory_base);
++ (next_queue_index -
++ (void __iomem *)ctrl_info->queue_memory_base);
+ next_queue_index += sizeof(pqi_index_t);
+ next_queue_index = PTR_ALIGN(next_queue_index,
+ PQI_OPERATIONAL_INDEX_ALIGNMENT);
+@@ -3304,7 +3307,8 @@ static int pqi_alloc_operational_queues(struct pqi_ctrl_info *ctrl_info)
+ ctrl_info->event_queue.oq_pi = next_queue_index;
+ ctrl_info->event_queue.oq_pi_bus_addr =
+ ctrl_info->queue_memory_base_dma_handle +
+- (next_queue_index - ctrl_info->queue_memory_base);
++ (next_queue_index -
++ (void __iomem *)ctrl_info->queue_memory_base);
+
+ return 0;
+ }
+@@ -3378,7 +3382,8 @@ static int pqi_alloc_admin_queues(struct pqi_ctrl_info *ctrl_info)
+ admin_queues->oq_element_array =
+ &admin_queues_aligned->oq_element_array;
+ admin_queues->iq_ci = &admin_queues_aligned->iq_ci;
+- admin_queues->oq_pi = &admin_queues_aligned->oq_pi;
++ admin_queues->oq_pi =
++ (pqi_index_t __iomem *)&admin_queues_aligned->oq_pi;
+
+ admin_queues->iq_element_array_bus_addr =
+ ctrl_info->admin_queue_memory_base_dma_handle +
+@@ -3394,8 +3399,8 @@ static int pqi_alloc_admin_queues(struct pqi_ctrl_info *ctrl_info)
+ ctrl_info->admin_queue_memory_base);
+ admin_queues->oq_pi_bus_addr =
+ ctrl_info->admin_queue_memory_base_dma_handle +
+- ((void *)admin_queues->oq_pi -
+- ctrl_info->admin_queue_memory_base);
++ ((void __iomem *)admin_queues->oq_pi -
++ (void __iomem *)ctrl_info->admin_queue_memory_base);
+
+ return 0;
+ }
+@@ -3496,7 +3501,7 @@ static int pqi_poll_for_admin_response(struct pqi_ctrl_info *ctrl_info,
+ timeout = (PQI_ADMIN_REQUEST_TIMEOUT_SECS * HZ) + jiffies;
+
+ while (1) {
+- oq_pi = *admin_queues->oq_pi;
++ oq_pi = readl(admin_queues->oq_pi);
+ if (oq_pi != oq_ci)
+ break;
+ if (time_after(jiffies, timeout)) {
+@@ -3555,7 +3560,7 @@ static void pqi_start_io(struct pqi_ctrl_info *ctrl_info,
+ DIV_ROUND_UP(iu_length,
+ PQI_OPERATIONAL_IQ_ELEMENT_LENGTH);
+
+- iq_ci = *queue_group->iq_ci[path];
++ iq_ci = readl(queue_group->iq_ci[path]);
+
+ if (num_elements_needed > pqi_num_elements_free(iq_pi, iq_ci,
+ ctrl_info->num_elements_per_iq))
+@@ -5053,7 +5058,7 @@ static int pqi_wait_until_inbound_queues_empty(struct pqi_ctrl_info *ctrl_info)
+ iq_pi = queue_group->iq_pi_copy[path];
+
+ while (1) {
+- iq_ci = *queue_group->iq_ci[path];
++ iq_ci = readl(queue_group->iq_ci[path]);
+ if (iq_ci == iq_pi)
+ break;
+ pqi_check_ctrl_health(ctrl_info);
+@@ -6242,20 +6247,20 @@ static void pqi_reinit_queues(struct pqi_ctrl_info *ctrl_info)
+ admin_queues = &ctrl_info->admin_queues;
+ admin_queues->iq_pi_copy = 0;
+ admin_queues->oq_ci_copy = 0;
+- *admin_queues->oq_pi = 0;
++ writel(0, admin_queues->oq_pi);
+
+ for (i = 0; i < ctrl_info->num_queue_groups; i++) {
+ ctrl_info->queue_groups[i].iq_pi_copy[RAID_PATH] = 0;
+ ctrl_info->queue_groups[i].iq_pi_copy[AIO_PATH] = 0;
+ ctrl_info->queue_groups[i].oq_ci_copy = 0;
+
+- *ctrl_info->queue_groups[i].iq_ci[RAID_PATH] = 0;
+- *ctrl_info->queue_groups[i].iq_ci[AIO_PATH] = 0;
+- *ctrl_info->queue_groups[i].oq_pi = 0;
++ writel(0, ctrl_info->queue_groups[i].iq_ci[RAID_PATH]);
++ writel(0, ctrl_info->queue_groups[i].iq_ci[AIO_PATH]);
++ writel(0, ctrl_info->queue_groups[i].oq_pi);
+ }
+
+ event_queue = &ctrl_info->event_queue;
+- *event_queue->oq_pi = 0;
++ writel(0, event_queue->oq_pi);
+ event_queue->oq_ci_copy = 0;
+ }
+
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-smartpqi-improve-error-checking-for-sync-reques.patch b/patches.drivers/scsi-smartpqi-improve-error-checking-for-sync-reques.patch
new file mode 100644
index 0000000000..cece2515d5
--- /dev/null
+++ b/patches.drivers/scsi-smartpqi-improve-error-checking-for-sync-reques.patch
@@ -0,0 +1,130 @@
+From: Kevin Barnett <kevin.barnett@microsemi.com>
+Date: Mon, 18 Jun 2018 13:22:48 -0500
+Subject: [PATCH] scsi: smartpqi: improve error checking for sync requests
+References: bsc#1086274
+Git-commit: 26b390aba2a8f7b9dd5ce4e3ada9431de327da6d
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
+Patch-mainline: Queued in subsystem maintainer repository
+
+Detect rare error cases for synchronous requests down the RAID path.
+
+Also retry INQUIRY of VPD page 0 sent to an HBA drive if the command failed
+due to an abort.
+
+Reviewed-by: Scott Benesh <scott.benesh@microsemi.com>
+Reviewed-by: Scott Teel <scott.teel@microsemi.com>
+Signed-off-by: Kevin Barnett <kevin.barnett@microsemi.com>
+Signed-off-by: Don Brace <don.brace@microsemi.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/smartpqi/smartpqi.h | 2 ++
+ drivers/scsi/smartpqi/smartpqi_init.c | 54 ++++++++++++++++++++++++-----------
+ 2 files changed, 40 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
+index dc3a0542a2e8..a8e7c4d48061 100644
+--- a/drivers/scsi/smartpqi/smartpqi.h
++++ b/drivers/scsi/smartpqi/smartpqi.h
+@@ -483,6 +483,8 @@ struct pqi_raid_error_info {
+ #define CISS_CMD_STATUS_TMF 0xd
+ #define CISS_CMD_STATUS_AIO_DISABLED 0xe
+
++#define PQI_CMD_STATUS_ABORTED CISS_CMD_STATUS_ABORTED
++
+ #define PQI_NUM_EVENT_QUEUE_ELEMENTS 32
+ #define PQI_EVENT_OQ_ELEMENT_LENGTH sizeof(struct pqi_event_response)
+
+diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
+index d309438697a2..d3f1450e11a1 100644
+--- a/drivers/scsi/smartpqi/smartpqi_init.c
++++ b/drivers/scsi/smartpqi/smartpqi_init.c
+@@ -1197,20 +1197,30 @@ static void pqi_get_volume_status(struct pqi_ctrl_info *ctrl_info,
+ device->volume_offline = volume_offline;
+ }
+
++#define PQI_INQUIRY_PAGE0_RETRIES 3
++
+ static int pqi_get_device_info(struct pqi_ctrl_info *ctrl_info,
+ struct pqi_scsi_dev *device)
+ {
+ int rc;
+ u8 *buffer;
++ unsigned int retries;
+
+ buffer = kmalloc(64, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ /* Send an inquiry to the device to see what it is. */
+- rc = pqi_scsi_inquiry(ctrl_info, device->scsi3addr, 0, buffer, 64);
+- if (rc)
+- goto out;
++ for (retries = 0;;) {
++ rc = pqi_scsi_inquiry(ctrl_info, device->scsi3addr, 0,
++ buffer, 64);
++ if (rc == 0)
++ break;
++ if (pqi_is_logical_device(device) ||
++ rc != PQI_CMD_STATUS_ABORTED ||
++ ++retries > PQI_INQUIRY_PAGE0_RETRIES)
++ goto out;
++ }
+
+ scsi_sanitize_inquiry_string(&buffer[8], 8);
+ scsi_sanitize_inquiry_string(&buffer[16], 16);
+@@ -3621,6 +3631,29 @@ static void pqi_raid_synchronous_complete(struct pqi_io_request *io_request,
+ complete(waiting);
+ }
+
++static int pqi_process_raid_io_error_synchronous(struct pqi_raid_error_info
++ *error_info)
++{
++ int rc = -EIO;
++
++ switch (error_info->data_out_result) {
++ case PQI_DATA_IN_OUT_GOOD:
++ if (error_info->status == SAM_STAT_GOOD)
++ rc = 0;
++ break;
++ case PQI_DATA_IN_OUT_UNDERFLOW:
++ if (error_info->status == SAM_STAT_GOOD ||
++ error_info->status == SAM_STAT_CHECK_CONDITION)
++ rc = 0;
++ break;
++ case PQI_DATA_IN_OUT_ABORTED:
++ rc = PQI_CMD_STATUS_ABORTED;
++ break;
++ }
++
++ return rc;
++}
++
+ static int pqi_submit_raid_request_synchronous(struct pqi_ctrl_info *ctrl_info,
+ struct pqi_iu_header *request, unsigned int flags,
+ struct pqi_raid_error_info *error_info, unsigned long timeout_msecs)
+@@ -3710,19 +3743,8 @@ static int pqi_submit_raid_request_synchronous(struct pqi_ctrl_info *ctrl_info,
+ else
+ memset(error_info, 0, sizeof(*error_info));
+ } else if (rc == 0 && io_request->error_info) {
+- u8 scsi_status;
+- struct pqi_raid_error_info *raid_error_info;
+-
+- raid_error_info = io_request->error_info;
+- scsi_status = raid_error_info->status;
+-
+- if (scsi_status == SAM_STAT_CHECK_CONDITION &&
+- raid_error_info->data_out_result ==
+- PQI_DATA_IN_OUT_UNDERFLOW)
+- scsi_status = SAM_STAT_GOOD;
+-
+- if (scsi_status != SAM_STAT_GOOD)
+- rc = -EIO;
++ rc = pqi_process_raid_io_error_synchronous(
++ io_request->error_info);
+ }
+
+ pqi_free_io_request(io_request);
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-smartpqi-improve-handling-for-sync-requests.patch b/patches.drivers/scsi-smartpqi-improve-handling-for-sync-requests.patch
new file mode 100644
index 0000000000..24d353ae3c
--- /dev/null
+++ b/patches.drivers/scsi-smartpqi-improve-handling-for-sync-requests.patch
@@ -0,0 +1,125 @@
+From: Kevin Barnett <kevin.barnett@microsemi.com>
+Date: Mon, 18 Jun 2018 13:22:42 -0500
+Subject: [PATCH] scsi: smartpqi: improve handling for sync requests
+References: bsc#1086274
+Git-commit: 957c5ab108c7d98369b7524daea532c0ebbcf845
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
+Patch-mainline: Queued in subsystem maintainer repository
+
+Decrement the active thread count after the synchronous request was
+submitted to the controller but before the driver blocks to wait for the
+request to complete.
+
+Reviewed-by: Scott Benesh <scott.benesh@microsemi.com>
+Reviewed-by: Scott Teel <scott.teel@microsemi.com>
+Signed-off-by: Kevin Barnett <kevin.barnett@microsemi.com>
+Signed-off-by: Don Brace <don.brace@microsemi.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/smartpqi/smartpqi_init.c | 55 +++++++++++++++--------------------
+ 1 file changed, 23 insertions(+), 32 deletions(-)
+
+diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
+index 5d2bb0cfa92d..d309438697a2 100644
+--- a/drivers/scsi/smartpqi/smartpqi_init.c
++++ b/drivers/scsi/smartpqi/smartpqi_init.c
+@@ -3621,43 +3621,16 @@ static void pqi_raid_synchronous_complete(struct pqi_io_request *io_request,
+ complete(waiting);
+ }
+
+-static int pqi_submit_raid_request_synchronous_with_io_request(
+- struct pqi_ctrl_info *ctrl_info, struct pqi_io_request *io_request,
+- unsigned long timeout_msecs)
+-{
+- int rc = 0;
+- DECLARE_COMPLETION_ONSTACK(wait);
+-
+- io_request->io_complete_callback = pqi_raid_synchronous_complete;
+- io_request->context = &wait;
+-
+- pqi_start_io(ctrl_info,
+- &ctrl_info->queue_groups[PQI_DEFAULT_QUEUE_GROUP], RAID_PATH,
+- io_request);
+-
+- if (timeout_msecs == NO_TIMEOUT) {
+- pqi_wait_for_completion_io(ctrl_info, &wait);
+- } else {
+- if (!wait_for_completion_io_timeout(&wait,
+- msecs_to_jiffies(timeout_msecs))) {
+- dev_warn(&ctrl_info->pci_dev->dev,
+- "command timed out\n");
+- rc = -ETIMEDOUT;
+- }
+- }
+-
+- return rc;
+-}
+-
+ static int pqi_submit_raid_request_synchronous(struct pqi_ctrl_info *ctrl_info,
+ struct pqi_iu_header *request, unsigned int flags,
+ struct pqi_raid_error_info *error_info, unsigned long timeout_msecs)
+ {
+- int rc;
++ int rc = 0;
+ struct pqi_io_request *io_request;
+ unsigned long start_jiffies;
+ unsigned long msecs_blocked;
+ size_t iu_length;
++ DECLARE_COMPLETION_ONSTACK(wait);
+
+ /*
+ * Note that specifying PQI_SYNC_FLAGS_INTERRUPTABLE and a timeout value
+@@ -3686,11 +3659,13 @@ static int pqi_submit_raid_request_synchronous(struct pqi_ctrl_info *ctrl_info,
+ pqi_ctrl_busy(ctrl_info);
+ timeout_msecs = pqi_wait_if_ctrl_blocked(ctrl_info, timeout_msecs);
+ if (timeout_msecs == 0) {
++ pqi_ctrl_unbusy(ctrl_info);
+ rc = -ETIMEDOUT;
+ goto out;
+ }
+
+ if (pqi_ctrl_offline(ctrl_info)) {
++ pqi_ctrl_unbusy(ctrl_info);
+ rc = -ENXIO;
+ goto out;
+ }
+@@ -3708,8 +3683,25 @@ static int pqi_submit_raid_request_synchronous(struct pqi_ctrl_info *ctrl_info,
+ PQI_REQUEST_HEADER_LENGTH;
+ memcpy(io_request->iu, request, iu_length);
+
+- rc = pqi_submit_raid_request_synchronous_with_io_request(ctrl_info,
+- io_request, timeout_msecs);
++ io_request->io_complete_callback = pqi_raid_synchronous_complete;
++ io_request->context = &wait;
++
++ pqi_start_io(ctrl_info,
++ &ctrl_info->queue_groups[PQI_DEFAULT_QUEUE_GROUP], RAID_PATH,
++ io_request);
++
++ pqi_ctrl_unbusy(ctrl_info);
++
++ if (timeout_msecs == NO_TIMEOUT) {
++ pqi_wait_for_completion_io(ctrl_info, &wait);
++ } else {
++ if (!wait_for_completion_io_timeout(&wait,
++ msecs_to_jiffies(timeout_msecs))) {
++ dev_warn(&ctrl_info->pci_dev->dev,
++ "command timed out\n");
++ rc = -ETIMEDOUT;
++ }
++ }
+
+ if (error_info) {
+ if (io_request->error_info)
+@@ -3736,7 +3728,6 @@ static int pqi_submit_raid_request_synchronous(struct pqi_ctrl_info *ctrl_info,
+ pqi_free_io_request(io_request);
+
+ out:
+- pqi_ctrl_unbusy(ctrl_info);
+ up(&ctrl_info->sync_request_sem);
+
+ return rc;
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-smartpqi-update-driver-version.patch b/patches.drivers/scsi-smartpqi-update-driver-version.patch
new file mode 100644
index 0000000000..7570f9ad0e
--- /dev/null
+++ b/patches.drivers/scsi-smartpqi-update-driver-version.patch
@@ -0,0 +1,40 @@
+From: Don Brace <don.brace@microsemi.com>
+Date: Wed, 21 Mar 2018 13:32:37 -0500
+Subject: [PATCH] scsi: smartpqi: update driver version
+References: bsc#1086274
+Git-commit: 61c187e46ebb27f51b52bd0eb68b7f534a300184
+Patch-mainline: v4.17-rc1
+
+Reviewed-by: Scott Teel <scott.teel@microsemi.com>
+Reviewed-by: Gerry Morong <gerry.morong@microsemi.com>
+Reviewed-by: Scott Benesh <scott.benesh@microsemi.com>
+Signed-off-by: Kevin Barnett <kevin.barnett@microsemi.com>
+Signed-off-by: Don Brace <don.brace@microsemi.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/smartpqi/smartpqi_init.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
+index 7fa2583ada8f..5d2bb0cfa92d 100644
+--- a/drivers/scsi/smartpqi/smartpqi_init.c
++++ b/drivers/scsi/smartpqi/smartpqi_init.c
+@@ -40,11 +40,11 @@
+ #define BUILD_TIMESTAMP
+ #endif
+
+-#define DRIVER_VERSION "1.1.2-126"
++#define DRIVER_VERSION "1.1.4-115"
+ #define DRIVER_MAJOR 1
+ #define DRIVER_MINOR 1
+-#define DRIVER_RELEASE 2
+-#define DRIVER_REVISION 126
++#define DRIVER_RELEASE 4
++#define DRIVER_REVISION 115
+
+ #define DRIVER_NAME "Microsemi PQI Driver (v" \
+ DRIVER_VERSION BUILD_TIMESTAMP ")"
+--
+2.12.3
+
diff --git a/patches.drivers/scsi-smartpqi-workaround-fw-bug-for-oq-deletion.patch b/patches.drivers/scsi-smartpqi-workaround-fw-bug-for-oq-deletion.patch
new file mode 100644
index 0000000000..a3e71e6c23
--- /dev/null
+++ b/patches.drivers/scsi-smartpqi-workaround-fw-bug-for-oq-deletion.patch
@@ -0,0 +1,100 @@
+From: Kevin Barnett <kevin.barnett@microsemi.com>
+Date: Wed, 21 Mar 2018 13:32:31 -0500
+Subject: [PATCH] scsi: smartpqi: workaround fw bug for oq deletion
+References: bsc#1086274
+Git-commit: 339faa8150fd56891105bc69fc18f5d51b8a63dd
+Patch-mainline: v4.17-rc1
+
+Skip deleting PQI operational queues when there is an error creating a
+new queue group. It's not really necessary to delete the queues anyway
+because they get deleted during the PQI reset that is part of the error
+recovery path.
+
+Signed-off-by: Don Brace <don.brace@microsemi.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/scsi/smartpqi/smartpqi_init.c | 39 +++--------------------------------
+ 1 file changed, 3 insertions(+), 36 deletions(-)
+
+diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
+index 68f82cee0720..7fa2583ada8f 100644
+--- a/drivers/scsi/smartpqi/smartpqi_init.c
++++ b/drivers/scsi/smartpqi/smartpqi_init.c
+@@ -3899,29 +3899,6 @@ static int pqi_validate_device_capability(struct pqi_ctrl_info *ctrl_info)
+ return 0;
+ }
+
+-static int pqi_delete_operational_queue(struct pqi_ctrl_info *ctrl_info,
+- bool inbound_queue, u16 queue_id)
+-{
+- struct pqi_general_admin_request request;
+- struct pqi_general_admin_response response;
+-
+- memset(&request, 0, sizeof(request));
+- request.header.iu_type = PQI_REQUEST_IU_GENERAL_ADMIN;
+- put_unaligned_le16(PQI_GENERAL_ADMIN_IU_LENGTH,
+- &request.header.iu_length);
+- if (inbound_queue)
+- request.function_code =
+- PQI_GENERAL_ADMIN_FUNCTION_DELETE_IQ;
+- else
+- request.function_code =
+- PQI_GENERAL_ADMIN_FUNCTION_DELETE_OQ;
+- put_unaligned_le16(queue_id,
+- &request.data.delete_operational_queue.queue_id);
+-
+- return pqi_submit_admin_request_synchronous(ctrl_info, &request,
+- &response);
+-}
+-
+ static int pqi_create_event_queue(struct pqi_ctrl_info *ctrl_info)
+ {
+ int rc;
+@@ -4039,7 +4016,7 @@ static int pqi_create_queue_group(struct pqi_ctrl_info *ctrl_info,
+ if (rc) {
+ dev_err(&ctrl_info->pci_dev->dev,
+ "error creating inbound AIO queue\n");
+- goto delete_inbound_queue_raid;
++ return rc;
+ }
+
+ queue_group->iq_pi[AIO_PATH] = ctrl_info->iomem_base +
+@@ -4067,7 +4044,7 @@ static int pqi_create_queue_group(struct pqi_ctrl_info *ctrl_info,
+ if (rc) {
+ dev_err(&ctrl_info->pci_dev->dev,
+ "error changing queue property\n");
+- goto delete_inbound_queue_aio;
++ return rc;
+ }
+
+ /*
+@@ -4097,7 +4074,7 @@ static int pqi_create_queue_group(struct pqi_ctrl_info *ctrl_info,
+ if (rc) {
+ dev_err(&ctrl_info->pci_dev->dev,
+ "error creating outbound queue\n");
+- goto delete_inbound_queue_aio;
++ return rc;
+ }
+
+ queue_group->oq_ci = ctrl_info->iomem_base +
+@@ -4106,16 +4083,6 @@ static int pqi_create_queue_group(struct pqi_ctrl_info *ctrl_info,
+ &response.data.create_operational_oq.oq_ci_offset);
+
+ return 0;
+-
+-delete_inbound_queue_aio:
+- pqi_delete_operational_queue(ctrl_info, true,
+- queue_group->iq_id[AIO_PATH]);
+-
+-delete_inbound_queue_raid:
+- pqi_delete_operational_queue(ctrl_info, true,
+- queue_group->iq_id[RAID_PATH]);
+-
+- return rc;
+ }
+
+ static int pqi_create_queues(struct pqi_ctrl_info *ctrl_info)
+--
+2.12.3
+
diff --git a/patches.fixes/dax-check-for-queue_flag_dax-in-bdev_dax_supported.patch b/patches.fixes/dax-check-for-queue_flag_dax-in-bdev_dax_supported.patch
index 54f1f5325f..df2f36209b 100644
--- a/patches.fixes/dax-check-for-queue_flag_dax-in-bdev_dax_supported.patch
+++ b/patches.fixes/dax-check-for-queue_flag_dax-in-bdev_dax_supported.patch
@@ -20,25 +20,20 @@ Reviewed-by: Toshi Kani <toshi.kani@hpe.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
---
- drivers/dax/super.c | 9 +++++++++
- 1 file changed, 9 insertions(+)
+ drivers/dax/super.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
--- a/drivers/dax/super.c
+++ b/drivers/dax/super.c
-@@ -86,10 +86,12 @@ int __bdev_dax_supported(struct super_bl
- struct block_device *bdev = sb->s_bdev;
+@@ -85,6 +85,7 @@ int __bdev_dax_supported(struct block_de
+ {
struct dax_device *dax_dev;
pgoff_t pgoff;
+ struct request_queue *q;
int err, id;
void *kaddr;
pfn_t pfn;
- long len;
-+ char buf[BDEVNAME_SIZE];
-
- if (blocksize != PAGE_SIZE) {
- pr_err("VFS (%s): error: unsupported blocksize for dax\n",
-@@ -97,6 +99,13 @@ int __bdev_dax_supported(struct super_bl
+@@ -97,6 +98,13 @@ int __bdev_dax_supported(struct block_de
return -EINVAL;
}
@@ -51,4 +46,4 @@ Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+
err = bdev_dax_pgoff(bdev, 0, PAGE_SIZE, &pgoff);
if (err) {
- pr_err("VFS (%s): error: unaligned partition for dax\n",
+ pr_debug("%s: error: unaligned partition for dax\n",
diff --git a/patches.fixes/dm-prevent-dax-mounts-if-not-supported.patch b/patches.fixes/dm-prevent-dax-mounts-if-not-supported.patch
new file mode 100644
index 0000000000..9c208111a7
--- /dev/null
+++ b/patches.fixes/dm-prevent-dax-mounts-if-not-supported.patch
@@ -0,0 +1,69 @@
+From: Ross Zwisler <ross.zwisler@linux.intel.com>
+Date: Tue, 26 Jun 2018 16:30:41 -0600
+Subject: dm: prevent DAX mounts if not supported
+Git-commit: dbc626597c39b24cefce09fbd8e9dea85869a801
+Patch-mainline: v4.18-rc3
+References: bsc#1103917
+
+Currently device_supports_dax() just checks to see if the QUEUE_FLAG_DAX
+flag is set on the device's request queue to decide whether or not the
+device supports filesystem DAX. Really we should be using
+bdev_dax_supported() like filesystems do at mount time. This performs
+other tests like checking to make sure the dax_direct_access() path works.
+
+We also explicitly clear QUEUE_FLAG_DAX on the DM device's request queue if
+any of the underlying devices do not support DAX. This makes the handling
+of QUEUE_FLAG_DAX consistent with the setting/clearing of most other flags
+in dm_table_set_restrictions().
+
+Now that bdev_dax_supported() explicitly checks for QUEUE_FLAG_DAX, this
+will ensure that filesystems built upon DM devices will only be able to
+mount with DAX if all underlying devices also support DAX.
+
+Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
+Fixes: commit 545ed20e6df6 ("dm: add infrastructure for DAX support")
+Cc: stable@vger.kernel.org
+Acked-by: Dan Williams <dan.j.williams@intel.com>
+Reviewed-by: Toshi Kani <toshi.kani@hpe.com>
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/md/dm-table.c | 7 ++++---
+ drivers/md/dm.c | 3 +--
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+--- a/drivers/md/dm-table.c
++++ b/drivers/md/dm-table.c
+@@ -883,9 +883,7 @@ EXPORT_SYMBOL_GPL(dm_table_set_type);
+ static int device_supports_dax(struct dm_target *ti, struct dm_dev *dev,
+ sector_t start, sector_t len, void *data)
+ {
+- struct request_queue *q = bdev_get_queue(dev->bdev);
+-
+- return q && blk_queue_dax(q);
++ return bdev_dax_supported(dev->bdev, PAGE_SIZE);
+ }
+
+ static bool dm_table_supports_dax(struct dm_table *t)
+@@ -1824,6 +1822,9 @@ void dm_table_set_restrictions(struct dm
+
+ if (dm_table_supports_dax(t))
+ queue_flag_set_unlocked(QUEUE_FLAG_DAX, q);
++ else
++ queue_flag_clear_unlocked(QUEUE_FLAG_DAX, q);
++
+ if (dm_table_supports_dax_write_cache(t))
+ dax_write_cache(t->md->dax_dev, true);
+
+--- a/drivers/md/dm.c
++++ b/drivers/md/dm.c
+@@ -970,8 +970,7 @@ static long dm_dax_direct_access(struct
+ if (len < 1)
+ goto out;
+ nr_pages = min(len, nr_pages);
+- if (ti->type->direct_access)
+- ret = ti->type->direct_access(ti, pgoff, nr_pages, kaddr, pfn);
++ ret = ti->type->direct_access(ti, pgoff, nr_pages, kaddr, pfn);
+
+ out:
+ dm_put_live_table(md, srcu_idx);
diff --git a/patches.fixes/fs-allow-per-device-dax-status-checking-for-filesystems.patch b/patches.fixes/fs-allow-per-device-dax-status-checking-for-filesystems.patch
new file mode 100644
index 0000000000..5a80cba37c
--- /dev/null
+++ b/patches.fixes/fs-allow-per-device-dax-status-checking-for-filesystems.patch
@@ -0,0 +1,223 @@
+From: "Darrick J. Wong" <darrick.wong@oracle.com>
+Date: Wed, 30 May 2018 13:03:45 -0700
+Subject: fs: allow per-device dax status checking for filesystems
+Git-commit: ba23cba9b3bdc967aabdc6ff1e3e9b11ce05bb4f
+Patch-mainline: v4.18-rc1
+References: bsc#1103917
+
+Change bdev_dax_supported so it takes a bdev parameter. This enables
+multi-device filesystems like xfs to check that a dax device can work for
+the particular filesystem. Once that's in place, actually fix all the
+parts of XFS where we need to be able to distinguish between datadev and
+rtdev.
+
+This patch fixes the problem where we screw up the dax support checking
+in xfs if the datadev and rtdev have different dax capabilities.
+
+Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
+[rez: Re-added __bdev_dax_supported() for !CONFIG_FS_DAX cases]
+Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
+Reviewed-by: Eric Sandeen <sandeen@redhat.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/dax/super.c | 22 +++++++++++-----------
+ fs/ext2/super.c | 2 +-
+ fs/ext4/super.c | 2 +-
+ fs/xfs/xfs_ioctl.c | 3 ++-
+ fs/xfs/xfs_iops.c | 30 +++++++++++++++++++++++++-----
+ fs/xfs/xfs_super.c | 10 ++++++++--
+ include/linux/dax.h | 9 +++++----
+ 7 files changed, 53 insertions(+), 25 deletions(-)
+
+--- a/drivers/dax/super.c
++++ b/drivers/dax/super.c
+@@ -73,7 +73,7 @@ EXPORT_SYMBOL_GPL(fs_dax_get_by_bdev);
+
+ /**
+ * __bdev_dax_supported() - Check if the device supports dax for filesystem
+- * @sb: The superblock of the device
++ * @bdev: block device to check
+ * @blocksize: The block size of the device
+ *
+ * This is a library function for filesystems to check if the block device
+@@ -81,33 +81,33 @@ EXPORT_SYMBOL_GPL(fs_dax_get_by_bdev);
+ *
+ * Return: negative errno if unsupported, 0 if supported.
+ */
+-int __bdev_dax_supported(struct super_block *sb, int blocksize)
++int __bdev_dax_supported(struct block_device *bdev, int blocksize)
+ {
+- struct block_device *bdev = sb->s_bdev;
+ struct dax_device *dax_dev;
+ pgoff_t pgoff;
+ int err, id;
+ void *kaddr;
+ pfn_t pfn;
+ long len;
++ char buf[BDEVNAME_SIZE];
+
+ if (blocksize != PAGE_SIZE) {
+- pr_err("VFS (%s): error: unsupported blocksize for dax\n",
+- sb->s_id);
++ pr_debug("%s: error: unsupported blocksize for dax\n",
++ bdevname(bdev, buf));
+ return -EINVAL;
+ }
+
+ err = bdev_dax_pgoff(bdev, 0, PAGE_SIZE, &pgoff);
+ if (err) {
+- pr_err("VFS (%s): error: unaligned partition for dax\n",
+- sb->s_id);
++ pr_debug("%s: error: unaligned partition for dax\n",
++ bdevname(bdev, buf));
+ return err;
+ }
+
+ dax_dev = dax_get_by_host(bdev->bd_disk->disk_name);
+ if (!dax_dev) {
+- pr_err("VFS (%s): error: device does not support dax\n",
+- sb->s_id);
++ pr_err("%s: error: device does not support dax\n",
++ bdevname(bdev, buf));
+ return -EOPNOTSUPP;
+ }
+
+@@ -118,8 +118,8 @@ int __bdev_dax_supported(struct super_bl
+ put_dax(dax_dev);
+
+ if (len < 1) {
+- pr_err("VFS (%s): error: dax access failed (%ld)",
+- sb->s_id, len);
++ pr_debug("%s: error: dax access failed (%ld)\n",
++ bdevname(bdev, buf), len);
+ return len < 0 ? len : -EIO;
+ }
+
+--- a/fs/ext2/super.c
++++ b/fs/ext2/super.c
+@@ -955,7 +955,7 @@ static int ext2_fill_super(struct super_
+ blocksize = BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size);
+
+ if (sbi->s_mount_opt & EXT2_MOUNT_DAX) {
+- err = bdev_dax_supported(sb, blocksize);
++ err = bdev_dax_supported(sb->s_bdev, blocksize);
+ if (err)
+ goto failed_mount;
+ }
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3690,7 +3690,7 @@ static int ext4_fill_super(struct super_
+ " that may contain inline data");
+ goto failed_mount;
+ }
+- err = bdev_dax_supported(sb, blocksize);
++ err = bdev_dax_supported(sb->s_bdev, blocksize);
+ if (err)
+ goto failed_mount;
+ }
+--- a/fs/xfs/xfs_ioctl.c
++++ b/fs/xfs/xfs_ioctl.c
+@@ -1102,7 +1102,8 @@ xfs_ioctl_setattr_dax_invalidate(
+ if (fa->fsx_xflags & FS_XFLAG_DAX) {
+ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
+ return -EINVAL;
+- if (bdev_dax_supported(sb, sb->s_blocksize) < 0)
++ if (bdev_dax_supported(xfs_find_bdev_for_inode(VFS_I(ip)),
++ sb->s_blocksize) < 0)
+ return -EINVAL;
+ }
+
+--- a/fs/xfs/xfs_iops.c
++++ b/fs/xfs/xfs_iops.c
+@@ -1184,6 +1184,30 @@ static const struct inode_operations xfs
+ .update_time = xfs_vn_update_time,
+ };
+
++/* Figure out if this file actually supports DAX. */
++static bool
++xfs_inode_supports_dax(
++ struct xfs_inode *ip)
++{
++ struct xfs_mount *mp = ip->i_mount;
++
++ /* Only supported on non-reflinked files. */
++ if (!S_ISREG(VFS_I(ip)->i_mode) || xfs_is_reflink_inode(ip))
++ return false;
++
++ /* DAX mount option or DAX iflag must be set. */
++ if (!(mp->m_flags & XFS_MOUNT_DAX) &&
++ !(ip->i_d.di_flags2 & XFS_DIFLAG2_DAX))
++ return false;
++
++ /* Block size must match page size */
++ if (mp->m_sb.sb_blocksize != PAGE_SIZE)
++ return false;
++
++ /* Device has to support DAX too. */
++ return xfs_find_daxdev_for_inode(VFS_I(ip)) != NULL;
++}
++
+ STATIC void
+ xfs_diflags_to_iflags(
+ struct inode *inode,
+@@ -1202,11 +1226,7 @@ xfs_diflags_to_iflags(
+ inode->i_flags |= S_SYNC;
+ if (flags & XFS_DIFLAG_NOATIME)
+ inode->i_flags |= S_NOATIME;
+- if (S_ISREG(inode->i_mode) &&
+- ip->i_mount->m_sb.sb_blocksize == PAGE_SIZE &&
+- !xfs_is_reflink_inode(ip) &&
+- (ip->i_mount->m_flags & XFS_MOUNT_DAX ||
+- ip->i_d.di_flags2 & XFS_DIFLAG2_DAX))
++ if (xfs_inode_supports_dax(ip))
+ inode->i_flags |= S_DAX;
+ }
+
+--- a/fs/xfs/xfs_super.c
++++ b/fs/xfs/xfs_super.c
+@@ -1640,11 +1640,17 @@ xfs_fs_fill_super(
+ sb->s_flags |= MS_I_VERSION;
+
+ if (mp->m_flags & XFS_MOUNT_DAX) {
++ int error2 = 0;
++
+ xfs_warn(mp,
+ "DAX enabled. Warning: EXPERIMENTAL, use at your own risk");
+
+- error = bdev_dax_supported(sb, sb->s_blocksize);
+- if (error) {
++ error = bdev_dax_supported(mp->m_ddev_targp->bt_bdev,
++ sb->s_blocksize);
++ if (mp->m_rtdev_targp)
++ error2 = bdev_dax_supported(mp->m_rtdev_targp->bt_bdev,
++ sb->s_blocksize);
++ if (error && error2) {
+ xfs_alert(mp,
+ "DAX unsupported by block device. Turning off DAX.");
+ mp->m_flags &= ~XFS_MOUNT_DAX;
+--- a/include/linux/dax.h
++++ b/include/linux/dax.h
+@@ -62,10 +62,10 @@ static inline bool dax_write_cache_enabl
+
+ int bdev_dax_pgoff(struct block_device *, sector_t, size_t, pgoff_t *pgoff);
+ #if IS_ENABLED(CONFIG_FS_DAX)
+-int __bdev_dax_supported(struct super_block *sb, int blocksize);
+-static inline int bdev_dax_supported(struct super_block *sb, int blocksize)
++int __bdev_dax_supported(struct block_device *bdev, int blocksize);
++static inline int bdev_dax_supported(struct block_device *bdev, int blocksize)
+ {
+- return __bdev_dax_supported(sb, blocksize);
++ return __bdev_dax_supported(bdev, blocksize);
+ }
+
+ static inline struct dax_device *fs_dax_get_by_host(const char *host)
+@@ -80,7 +80,8 @@ static inline void fs_put_dax(struct dax
+
+ struct dax_device *fs_dax_get_by_bdev(struct block_device *bdev);
+ #else
+-static inline int bdev_dax_supported(struct super_block *sb, int blocksize)
++static inline int bdev_dax_supported(struct block_device *bdev,
++ int blocksize)
+ {
+ return -EOPNOTSUPP;
+ }
diff --git a/patches.fixes/libnvdimm-dimm-fix-dpa-reservation-vs-uninitialized-.patch b/patches.fixes/libnvdimm-dimm-fix-dpa-reservation-vs-uninitialized-.patch
new file mode 100644
index 0000000000..da8e5851b0
--- /dev/null
+++ b/patches.fixes/libnvdimm-dimm-fix-dpa-reservation-vs-uninitialized-.patch
@@ -0,0 +1,53 @@
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Fri, 6 Apr 2018 11:25:38 -0700
+Subject: libnvdimm, dimm: fix dpa reservation vs uninitialized label area
+Patch-mainline: v4.17-rc1
+Git-commit: c31898c8c711f2bbbcaebe802a55827e288d875a
+References: git-fixes
+
+At initialization time the 'dimm' driver caches a copy of the memory
+device's label area and reserves address space for each of the
+namespaces defined.
+
+However, as can be seen below, the reservation occurs even when the
+index blocks are invalid:
+
+ nvdimm nmem0: nvdimm_init_config_data: len: 131072 rc: 0
+ nvdimm nmem0: config data size: 131072
+ nvdimm nmem0: __nd_label_validate: nsindex0 labelsize 1 invalid
+ nvdimm nmem0: __nd_label_validate: nsindex1 labelsize 1 invalid
+ nvdimm nmem0: : pmem-6025e505: 0x1000000000 @ 0xf50000000 reserve <-- bad
+
+Gate dpa reservation on the presence of valid index blocks.
+
+Cc: <stable@vger.kernel.org>
+Fixes: 4a826c83db4e ("libnvdimm: namespace indices: read and validate")
+Reported-by: Krzysztof Rusocki <krzysztof.rusocki@intel.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/nvdimm/dimm.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/nvdimm/dimm.c b/drivers/nvdimm/dimm.c
+index f8913b8124b6..233907889f96 100644
+--- a/drivers/nvdimm/dimm.c
++++ b/drivers/nvdimm/dimm.c
+@@ -67,9 +67,11 @@ static int nvdimm_probe(struct device *dev)
+ ndd->ns_next = nd_label_next_nsindex(ndd->ns_current);
+ nd_label_copy(ndd, to_next_namespace_index(ndd),
+ to_current_namespace_index(ndd));
+- rc = nd_label_reserve_dpa(ndd);
+- if (ndd->ns_current >= 0)
+- nvdimm_set_aliasing(dev);
++ if (ndd->ns_current >= 0) {
++ rc = nd_label_reserve_dpa(ndd);
++ if (rc == 0)
++ nvdimm_set_aliasing(dev);
++ }
+ nvdimm_clear_locked(dev);
+ nvdimm_bus_unlock(dev);
+
+--
+2.12.3
+
diff --git a/patches.fixes/linvdimm-pmem-Preserve-read-only-setting-for-pmem-de.patch b/patches.fixes/linvdimm-pmem-Preserve-read-only-setting-for-pmem-de.patch
new file mode 100644
index 0000000000..0a86a1a0b6
--- /dev/null
+++ b/patches.fixes/linvdimm-pmem-Preserve-read-only-setting-for-pmem-de.patch
@@ -0,0 +1,77 @@
+From: Robert Elliott <elliott@hpe.com>
+Date: Thu, 31 May 2018 18:36:36 -0500
+Subject: linvdimm, pmem: Preserve read-only setting for pmem devices
+Patch-mainline: v4.18-rc1
+Git-commit: 254a4cd50b9fe2291a12b8902e08e56dcc4e9b10
+References: git-fixes
+
+The pmem driver does not honor a forced read-only setting for very long:
+ $ blockdev --setro /dev/pmem0
+ $ blockdev --getro /dev/pmem0
+ 1
+
+followed by various commands like these:
+ $ blockdev --rereadpt /dev/pmem0
+ or
+ $ mkfs.ext4 /dev/pmem0
+
+results in this in the kernel serial log:
+ nd_pmem namespace0.0: region0 read-write, marking pmem0 read-write
+
+with the read-only setting lost:
+ $ blockdev --getro /dev/pmem0
+ 0
+
+That's from bus.c nvdimm_revalidate_disk(), which always applies the
+setting from nd_region (which is initially based on the ACPI NFIT
+NVDIMM state flags not_armed bit).
+
+In contrast, commit 20bd1d026aac ("scsi: sd: Keep disk read-only when
+re-reading partition") fixed this issue for SCSI devices to preserve
+the previous setting if it was set to read-only.
+
+This patch modifies bus.c to preserve any previous read-only setting.
+It also eliminates the kernel serial log print except for cases where
+read-write is changed to read-only, so it doesn't print read-only to
+read-only non-changes.
+
+Cc: <stable@vger.kernel.org>
+Fixes: 581388209405 ("libnvdimm, nfit: handle unarmed dimms, mark namespaces read-only")
+Signed-off-by: Robert Elliott <elliott@hpe.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/nvdimm/bus.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
+index a64023690cad..b9e0d30e317a 100644
+--- a/drivers/nvdimm/bus.c
++++ b/drivers/nvdimm/bus.c
+@@ -566,14 +566,18 @@ int nvdimm_revalidate_disk(struct gendisk *disk)
+ {
+ struct device *dev = disk_to_dev(disk)->parent;
+ struct nd_region *nd_region = to_nd_region(dev->parent);
+- const char *pol = nd_region->ro ? "only" : "write";
++ int disk_ro = get_disk_ro(disk);
+
+- if (nd_region->ro == get_disk_ro(disk))
++ /*
++ * Upgrade to read-only if the region is read-only preserve as
++ * read-only if the disk is already read-only.
++ */
++ if (disk_ro || nd_region->ro == disk_ro)
+ return 0;
+
+- dev_info(dev, "%s read-%s, marking %s read-%s\n",
+- dev_name(&nd_region->dev), pol, disk->disk_name, pol);
+- set_disk_ro(disk, nd_region->ro);
++ dev_info(dev, "%s read-only, marking %s read-only\n",
++ dev_name(&nd_region->dev), disk->disk_name);
++ set_disk_ro(disk, 1);
+
+ return 0;
+
+--
+2.12.3
+
diff --git a/patches.fixes/nvme-fabrics-Ignore-nr_io_queues-option-for-discover.patch b/patches.fixes/nvme-fabrics-Ignore-nr_io_queues-option-for-discover.patch
new file mode 100644
index 0000000000..e671622804
--- /dev/null
+++ b/patches.fixes/nvme-fabrics-Ignore-nr_io_queues-option-for-discover.patch
@@ -0,0 +1,47 @@
+From: Roland Dreier <roland@purestorage.com>
+Date: Mon, 5 Mar 2018 11:59:53 -0800
+Subject: [PATCH] nvme-fabrics: Ignore nr_io_queues option for discovery
+ controllers
+References: bsc#1102633
+Git-commit: 0475821e229cfd9954b7501113d1acbc57b68689
+Patch-mainline: v4.16-rc5
+
+This removes a dependency on the order options are passed when creating
+a fabrics controller. With the old code, if "nr_io_queues" appears before
+an "nqn" option specifying the discovery controller, then nr_io_queues
+is overridden with zero. If "nr_io_queues" appears after specifying the
+discovery controller, then the nr_io_queues option is used to set the
+number of queues, and the driver attempts to establish IO connections
+to the discovery controller (which doesn't work).
+
+It seems better to ignore (and warn about) the "nr_io_queues" option
+if userspace has already asked to connect to the discovery controller.
+
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+Reviewed-by: James Smart <james.smart@broadcom.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Keith Busch <keith.busch@intel.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/nvme/host/fabrics.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c
+index 3dc0980d7435..34f363dc7de8 100644
+--- a/drivers/nvme/host/fabrics.c
++++ b/drivers/nvme/host/fabrics.c
+@@ -715,6 +715,11 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
+ ret = -EINVAL;
+ goto out;
+ }
++ if (opts->discovery_nqn) {
++ pr_debug("Ignoring nr_io_queues value for discovery controller\n");
++ break;
++ }
++
+ opts->nr_io_queues = min_t(unsigned int,
+ num_online_cpus(), token);
+ break;
+--
+2.12.3
+
diff --git a/patches.fixes/nvme-fixup-crash-on-failed-discovery.patch b/patches.fixes/nvme-fixup-crash-on-failed-discovery.patch
new file mode 100644
index 0000000000..b3b0682de7
--- /dev/null
+++ b/patches.fixes/nvme-fixup-crash-on-failed-discovery.patch
@@ -0,0 +1,34 @@
+From: Hannes Reinecke <hare@suse.de>
+Date: Tue, 7 Aug 2018 12:43:42 +0200
+Subject: [PATCH] nvme: fixup crash on failed discovery
+Git-commit: 8f220c418d070a097f7d292cf6b37f88d67845ad
+References: bsc#1103920
+Patch-Mainline: queued in subsystem maintainer repository
+Git-repo: git://git.infradead.org/nvme.git
+
+When the initial discovery fails the subsystem hasn't been setup yet
+in nvme_mpath_stop, and we can't dereference ctrl->subsys.
+
+Fixes: 0d0b660f ("nvme: add ANA support")
+Signed-off-by: Hannes Reinecke <hare@suse.com>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+---
+ drivers/nvme/host/multipath.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
+index c643872f8dac..5a9562881d4e 100644
+--- a/drivers/nvme/host/multipath.c
++++ b/drivers/nvme/host/multipath.c
+@@ -22,7 +22,7 @@ MODULE_PARM_DESC(multipath,
+
+ inline bool nvme_ctrl_use_ana(struct nvme_ctrl *ctrl)
+ {
+- return multipath && (ctrl->subsys->cmic & (1 << 3));
++ return multipath && ctrl->subsys && (ctrl->subsys->cmic & (1 << 3));
+ }
+
+ /*
+--
+2.12.3
+
diff --git a/patches.fixes/nvme-use-hw-qid-in-trace-events.patch b/patches.fixes/nvme-use-hw-qid-in-trace-events.patch
new file mode 100644
index 0000000000..dc09204f91
--- /dev/null
+++ b/patches.fixes/nvme-use-hw-qid-in-trace-events.patch
@@ -0,0 +1,214 @@
+From: Keith Busch <keith.busch@intel.com>
+Date: Fri, 29 Jun 2018 16:50:01 -0600
+Subject: [PATCH] nvme: use hw qid in trace events
+References: bsc#1102633
+Git-commit: 5d87eb94d9ba13e5e2d5ceb56ac6fe0948259ffa
+Git-repo: git://git.infradead.org/nvme.git
+Patch-mainline: Queued in subsystem maintainer repository
+
+We can not match a command to its completion based on the command
+id alone. We need the submitting queue identifier to pair with the
+completion, so this patch adds that to the trace buffer.
+
+This patch is also collapsing the admin and IO submission traces into a
+single one so we don't need to duplicate this and creating unnecessary
+code branches: we know if the command is an admin vs IO based on the qid.
+
+And since we're here, the patch fixes code formatting in the area.
+
+Signed-off-by: Keith Busch <keith.busch@intel.com>
+Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
+Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
+[hch: move the qid helper to nvme.h and made it an inline function]
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ drivers/nvme/host/core.c | 5 +--
+ drivers/nvme/host/nvme.h | 7 +++
+ drivers/nvme/host/trace.h | 112 +++++++++++++++++++---------------------------
+ 3 files changed, 53 insertions(+), 71 deletions(-)
+
+diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
+index 21a8a61684d3..aea49b5fd9d1 100644
+--- a/drivers/nvme/host/core.c
++++ b/drivers/nvme/host/core.c
+@@ -673,10 +673,7 @@ blk_status_t nvme_setup_cmd(struct nvme_ns *ns, struct request *req,
+ }
+
+ cmd->common.command_id = req->tag;
+- if (ns)
+- trace_nvme_setup_nvm_cmd(req->q->id, cmd);
+- else
+- trace_nvme_setup_admin_cmd(cmd);
++ trace_nvme_setup_cmd(req, cmd);
+ return ret;
+ }
+ EXPORT_SYMBOL_GPL(nvme_setup_cmd);
+diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
+index 5856616a5abc..408cb8bd7de7 100644
+--- a/drivers/nvme/host/nvme.h
++++ b/drivers/nvme/host/nvme.h
+@@ -118,6 +118,13 @@ static inline struct nvme_request *nvme_req(struct request *req)
+ return blk_mq_rq_to_pdu(req);
+ }
+
++static inline u16 nvme_req_qid(struct request *req)
++{
++ if (!req->rq_disk)
++ return 0;
++ return blk_mq_unique_tag_to_hwq(blk_mq_unique_tag(req)) + 1;
++}
++
+ /* The below value is the specific amount of delay needed before checking
+ * readiness in case of the PCI_DEVICE(0x1c58, 0x0003), which needs the
+ * NVME_QUIRK_DELAY_BEFORE_CHK_RDY quirk enabled. The value (in ms) was
+diff --git a/drivers/nvme/host/trace.h b/drivers/nvme/host/trace.h
+index ea91fccd1bc0..09844495a86a 100644
+--- a/drivers/nvme/host/trace.h
++++ b/drivers/nvme/host/trace.h
+@@ -50,13 +50,8 @@
+ nvme_admin_opcode_name(nvme_admin_security_recv), \
+ nvme_admin_opcode_name(nvme_admin_sanitize_nvm))
+
+-const char *nvme_trace_parse_admin_cmd(struct trace_seq *p, u8 opcode,
+- u8 *cdw10);
+-#define __parse_nvme_admin_cmd(opcode, cdw10) \
+- nvme_trace_parse_admin_cmd(p, opcode, cdw10)
+-
+ #define nvme_opcode_name(opcode) { opcode, #opcode }
+-#define show_opcode_name(val) \
++#define show_nvm_opcode_name(val) \
+ __print_symbolic(val, \
+ nvme_opcode_name(nvme_cmd_flush), \
+ nvme_opcode_name(nvme_cmd_write), \
+@@ -70,83 +65,66 @@ const char *nvme_trace_parse_admin_cmd(struct trace_seq *p, u8 opcode,
+ nvme_opcode_name(nvme_cmd_resv_acquire), \
+ nvme_opcode_name(nvme_cmd_resv_release))
+
+-const char *nvme_trace_parse_nvm_cmd(struct trace_seq *p, u8 opcode,
+- u8 *cdw10);
+-#define __parse_nvme_cmd(opcode, cdw10) \
+- nvme_trace_parse_nvm_cmd(p, opcode, cdw10)
++#define show_opcode_name(qid, opcode) \
++ (qid ? show_nvm_opcode_name(opcode) : show_admin_opcode_name(opcode))
+
+-TRACE_EVENT(nvme_setup_admin_cmd,
+- TP_PROTO(struct nvme_command *cmd),
+- TP_ARGS(cmd),
+- TP_STRUCT__entry(
+- __field(u8, opcode)
+- __field(u8, flags)
+- __field(u16, cid)
+- __field(u64, metadata)
+- __array(u8, cdw10, 24)
+- ),
+- TP_fast_assign(
+- __entry->opcode = cmd->common.opcode;
+- __entry->flags = cmd->common.flags;
+- __entry->cid = cmd->common.command_id;
+- __entry->metadata = le64_to_cpu(cmd->common.metadata);
+- memcpy(__entry->cdw10, cmd->common.cdw10,
+- sizeof(__entry->cdw10));
+- ),
+- TP_printk(" cmdid=%u, flags=0x%x, meta=0x%llx, cmd=(%s %s)",
+- __entry->cid, __entry->flags, __entry->metadata,
+- show_admin_opcode_name(__entry->opcode),
+- __parse_nvme_admin_cmd(__entry->opcode, __entry->cdw10))
+-);
++const char *nvme_trace_parse_admin_cmd(struct trace_seq *p, u8 opcode,
++ u8 *cdw10);
++const char *nvme_trace_parse_nvm_cmd(struct trace_seq *p, u8 opcode,
++ u8 *cdw10);
+
++#define parse_nvme_cmd(qid, opcode, cdw10) \
++ (qid ? \
++ nvme_trace_parse_nvm_cmd(p, opcode, cdw10) : \
++ nvme_trace_parse_admin_cmd(p, opcode, cdw10))
+
+-TRACE_EVENT(nvme_setup_nvm_cmd,
+- TP_PROTO(int qid, struct nvme_command *cmd),
+- TP_ARGS(qid, cmd),
++TRACE_EVENT(nvme_setup_cmd,
++ TP_PROTO(struct request *req, struct nvme_command *cmd),
++ TP_ARGS(req, cmd),
+ TP_STRUCT__entry(
+- __field(int, qid)
+- __field(u8, opcode)
+- __field(u8, flags)
+- __field(u16, cid)
+- __field(u32, nsid)
+- __field(u64, metadata)
+- __array(u8, cdw10, 24)
++ __field(int, qid)
++ __field(u8, opcode)
++ __field(u8, flags)
++ __field(u16, cid)
++ __field(u32, nsid)
++ __field(u64, metadata)
++ __array(u8, cdw10, 24)
+ ),
+ TP_fast_assign(
+- __entry->qid = qid;
+- __entry->opcode = cmd->common.opcode;
+- __entry->flags = cmd->common.flags;
+- __entry->cid = cmd->common.command_id;
+- __entry->nsid = le32_to_cpu(cmd->common.nsid);
+- __entry->metadata = le64_to_cpu(cmd->common.metadata);
+- memcpy(__entry->cdw10, cmd->common.cdw10,
+- sizeof(__entry->cdw10));
++ __entry->qid = nvme_req_qid(req);
++ __entry->opcode = cmd->common.opcode;
++ __entry->flags = cmd->common.flags;
++ __entry->cid = cmd->common.command_id;
++ __entry->nsid = le32_to_cpu(cmd->common.nsid);
++ __entry->metadata = le64_to_cpu(cmd->common.metadata);
++ memcpy(__entry->cdw10, cmd->common.cdw10,
++ sizeof(__entry->cdw10));
+ ),
+- TP_printk("qid=%d, nsid=%u, cmdid=%u, flags=0x%x, meta=0x%llx, cmd=(%s %s)",
+- __entry->qid, __entry->nsid, __entry->cid,
++ TP_printk("qid=%d, cmdid=%u, nsid=%u, flags=0x%x, meta=0x%llx, cmd=(%s %s)",
++ __entry->qid, __entry->cid, __entry->nsid,
+ __entry->flags, __entry->metadata,
+- show_opcode_name(__entry->opcode),
+- __parse_nvme_cmd(__entry->opcode, __entry->cdw10))
++ show_opcode_name(__entry->qid, __entry->opcode),
++ parse_nvme_cmd(__entry->qid, __entry->opcode, __entry->cdw10))
+ );
+
+ TRACE_EVENT(nvme_complete_rq,
+ TP_PROTO(struct request *req),
+ TP_ARGS(req),
+ TP_STRUCT__entry(
+- __field(int, qid)
+- __field(int, cid)
+- __field(u64, result)
+- __field(u8, retries)
+- __field(u8, flags)
+- __field(u16, status)
++ __field(int, qid)
++ __field(int, cid)
++ __field(u64, result)
++ __field(u8, retries)
++ __field(u8, flags)
++ __field(u16, status)
+ ),
+ TP_fast_assign(
+- __entry->qid = req->q->id;
+- __entry->cid = req->tag;
+- __entry->result = le64_to_cpu(nvme_req(req)->result.u64);
+- __entry->retries = nvme_req(req)->retries;
+- __entry->flags = nvme_req(req)->flags;
+- __entry->status = nvme_req(req)->status;
++ __entry->qid = nvme_req_qid(req);
++ __entry->cid = req->tag;
++ __entry->result = le64_to_cpu(nvme_req(req)->result.u64);
++ __entry->retries = nvme_req(req)->retries;
++ __entry->flags = nvme_req(req)->flags;
++ __entry->status = nvme_req(req)->status;
+ ),
+ TP_printk("cmdid=%u, qid=%d, res=%llu, retries=%u, flags=0x%x, status=%u",
+ __entry->cid, __entry->qid, __entry->result,
+--
+2.12.3
+
diff --git a/patches.fixes/nvme.h-fixup-ANA-group-descriptor-format.patch b/patches.fixes/nvme.h-fixup-ANA-group-descriptor-format.patch
new file mode 100644
index 0000000000..12f0e87c31
--- /dev/null
+++ b/patches.fixes/nvme.h-fixup-ANA-group-descriptor-format.patch
@@ -0,0 +1,35 @@
+From: Hannes Reinecke <hare@suse.com>
+Date: Wed, 8 Aug 2018 08:35:29 +0200
+Subject: [PATCH] nvme.h: fixup ANA group descriptor format
+Git-commit: 8b92d0e3d400390660a26ef7f475524700fb86cf
+Git-repo: git://git.infradead.org/nvme.git
+Patch-mainline: queued in subsystem maintainers repository
+References: bsc#1104111
+
+ANA Phase 3 draft had the 'reserved' field in the group descriptor
+format set to '23:17' (so that the first namespace identifier started
+at byte 24), but that got move with the approved TP to '31:17'
+(so that the first namespace identifier started at byte 32).
+
+Signed-off-by: Hannes Reinecke <hare@suse.com>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+---
+ include/linux/nvme.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/linux/nvme.h b/include/linux/nvme.h
+index 64c9175723de..a661861e9d56 100644
+--- a/include/linux/nvme.h
++++ b/include/linux/nvme.h
+@@ -446,7 +446,7 @@ struct nvme_ana_group_desc {
+ __le32 nnsids;
+ __le64 chgcnt;
+ __u8 state;
+- __u8 rsvd17[7];
++ __u8 rsvd17[15];
+ __le32 nsids[];
+ };
+
+--
+2.12.3
+
diff --git a/patches.fixes/pmem-only-set-queue_flag_dax-for-fsdax-mode.patch b/patches.fixes/pmem-only-set-queue_flag_dax-for-fsdax-mode.patch
new file mode 100644
index 0000000000..723a894054
--- /dev/null
+++ b/patches.fixes/pmem-only-set-queue_flag_dax-for-fsdax-mode.patch
@@ -0,0 +1,37 @@
+From: Ross Zwisler <ross.zwisler@linux.intel.com>
+Date: Tue, 26 Jun 2018 16:30:39 -0600
+Subject: pmem: only set QUEUE_FLAG_DAX for fsdax mode
+Git-commit: 4557641b4c7046625c026fb809c47ef0d43ae595
+Patch-mainline: v4.18-rc3
+References: bsc#1103917
+
+QUEUE_FLAG_DAX is an indication that a given block device supports
+filesystem DAX and should not be set for PMEM namespaces which are in "raw"
+mode. These namespaces lack struct page and are prevented from
+participating in filesystem DAX as of commit 569d0365f571 ("dax: require
+'struct page' by default for filesystem dax").
+
+Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
+Suggested-by: Mike Snitzer <snitzer@redhat.com>
+Fixes: 569d0365f571 ("dax: require 'struct page' by default for filesystem dax")
+Cc: stable@vger.kernel.org
+Acked-by: Dan Williams <dan.j.williams@intel.com>
+Reviewed-by: Toshi Kani <toshi.kani@hpe.com>
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/nvdimm/pmem.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/nvdimm/pmem.c
++++ b/drivers/nvdimm/pmem.c
+@@ -365,7 +365,8 @@ static int pmem_attach_disk(struct devic
+ blk_queue_logical_block_size(q, pmem_sector_size(ndns));
+ blk_queue_max_hw_sectors(q, UINT_MAX);
+ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q);
+- queue_flag_set_unlocked(QUEUE_FLAG_DAX, q);
++ if (pmem->pfn_flags & PFN_MAP)
++ queue_flag_set_unlocked(QUEUE_FLAG_DAX, q);
+ q->queuedata = pmem;
+
+ disk = alloc_disk_node(0, nid);
diff --git a/patches.kabi/kabi-fixup-bdev_dax_supported.patch b/patches.kabi/kabi-fixup-bdev_dax_supported.patch
new file mode 100644
index 0000000000..271b19a0e2
--- /dev/null
+++ b/patches.kabi/kabi-fixup-bdev_dax_supported.patch
@@ -0,0 +1,141 @@
+From: Johannes Thumshirn <jthumshirn@suse.de>
+Subject: kabi protect bdev_dax_supported
+Date: Tue Aug 7 15:11:48 CEST 2018
+Patch-mainline: Never, KABI fixup
+References: bsc#1103917
+
+Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ drivers/dax/super.c | 14 ++++++++++++--
+ drivers/md/dm-table.c | 2 +-
+ fs/ext2/super.c | 2 +-
+ fs/ext4/super.c | 2 +-
+ fs/xfs/xfs_ioctl.c | 2 +-
+ fs/xfs/xfs_super.c | 4 ++--
+ include/linux/dax.h | 10 ++++++----
+ 7 files changed, 24 insertions(+), 12 deletions(-)
+
+--- a/drivers/dax/super.c
++++ b/drivers/dax/super.c
+@@ -72,7 +72,7 @@ EXPORT_SYMBOL_GPL(fs_dax_get_by_bdev);
+ #endif
+
+ /**
+- * __bdev_dax_supported() - Check if the device supports dax for filesystem
++ * ____bdev_dax_supported() - Check if the device supports dax for filesystem
+ * @bdev: block device to check
+ * @blocksize: The block size of the device
+ *
+@@ -81,8 +81,9 @@ EXPORT_SYMBOL_GPL(fs_dax_get_by_bdev);
+ *
+ * Return: negative errno if unsupported, 0 if supported.
+ */
+-int __bdev_dax_supported(struct block_device *bdev, int blocksize)
++int ____bdev_dax_supported(struct block_device *bdev, int blocksize)
+ {
++#if IS_ENABLED(CONFIG_FS_DAX)
+ struct dax_device *dax_dev;
+ pgoff_t pgoff;
+ struct request_queue *q;
+@@ -132,6 +133,15 @@ int __bdev_dax_supported(struct block_de
+ }
+
+ return 0;
++#else
++ return -EOPNOTSUPP;
++#endif
++}
++EXPORT_SYMBOL_GPL(____bdev_dax_supported);
++
++int __bdev_dax_supported(struct super_block *sb, int blocksize)
++{
++ return ____bdev_dax_supported(sb->s_bdev, blocksize);
+ }
+ EXPORT_SYMBOL_GPL(__bdev_dax_supported);
+ #endif
+--- a/drivers/md/dm-table.c
++++ b/drivers/md/dm-table.c
+@@ -889,7 +889,7 @@ EXPORT_SYMBOL_GPL(dm_table_set_type);
+ static int device_supports_dax(struct dm_target *ti, struct dm_dev *dev,
+ sector_t start, sector_t len, void *data)
+ {
+- return bdev_dax_supported(dev->bdev, PAGE_SIZE);
++ return ____bdev_dax_supported(dev->bdev, PAGE_SIZE);
+ }
+
+ static bool dm_table_supports_dax(struct dm_table *t)
+--- a/fs/ext2/super.c
++++ b/fs/ext2/super.c
+@@ -955,7 +955,7 @@ static int ext2_fill_super(struct super_
+ blocksize = BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size);
+
+ if (sbi->s_mount_opt & EXT2_MOUNT_DAX) {
+- err = bdev_dax_supported(sb->s_bdev, blocksize);
++ err = ____bdev_dax_supported(sb->s_bdev, blocksize);
+ if (err)
+ goto failed_mount;
+ }
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3724,7 +3724,7 @@ static int ext4_fill_super(struct super_
+ " that may contain inline data");
+ goto failed_mount;
+ }
+- err = bdev_dax_supported(sb->s_bdev, blocksize);
++ err = ____bdev_dax_supported(sb->s_bdev, blocksize);
+ if (err)
+ goto failed_mount;
+ }
+--- a/fs/xfs/xfs_ioctl.c
++++ b/fs/xfs/xfs_ioctl.c
+@@ -1102,7 +1102,7 @@ xfs_ioctl_setattr_dax_invalidate(
+ if (fa->fsx_xflags & FS_XFLAG_DAX) {
+ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
+ return -EINVAL;
+- if (bdev_dax_supported(xfs_find_bdev_for_inode(VFS_I(ip)),
++ if (____bdev_dax_supported(xfs_find_bdev_for_inode(VFS_I(ip)),
+ sb->s_blocksize) < 0)
+ return -EINVAL;
+ }
+--- a/fs/xfs/xfs_super.c
++++ b/fs/xfs/xfs_super.c
+@@ -1661,10 +1661,10 @@ xfs_fs_fill_super(
+ int error2 = 0;
+
+
+- error = bdev_dax_supported(mp->m_ddev_targp->bt_bdev,
++ error = ____bdev_dax_supported(mp->m_ddev_targp->bt_bdev,
+ sb->s_blocksize);
+ if (mp->m_rtdev_targp)
+- error2 = bdev_dax_supported(mp->m_rtdev_targp->bt_bdev,
++ error2 = ____bdev_dax_supported(mp->m_rtdev_targp->bt_bdev,
+ sb->s_blocksize);
+ if (error && error2) {
+ xfs_alert(mp,
+--- a/include/linux/dax.h
++++ b/include/linux/dax.h
+@@ -62,10 +62,11 @@ static inline bool dax_write_cache_enabl
+
+ int bdev_dax_pgoff(struct block_device *, sector_t, size_t, pgoff_t *pgoff);
+ #if IS_ENABLED(CONFIG_FS_DAX)
+-int __bdev_dax_supported(struct block_device *bdev, int blocksize);
+-static inline int bdev_dax_supported(struct block_device *bdev, int blocksize)
++int ____bdev_dax_supported(struct block_device *bdev, int blocksize);
++int __bdev_dax_supported(struct super_block *sb, int blocksize);
++static inline int bdev_dax_supported(struct super_block *sb, int blocksize)
+ {
+- return __bdev_dax_supported(bdev, blocksize);
++ return __bdev_dax_supported(sb, blocksize);
+ }
+
+ static inline struct dax_device *fs_dax_get_by_host(const char *host)
+@@ -80,7 +81,8 @@ static inline void fs_put_dax(struct dax
+
+ struct dax_device *fs_dax_get_by_bdev(struct block_device *bdev);
+ #else
+-static inline int bdev_dax_supported(struct block_device *bdev,
++int ____bdev_dax_supported(struct block_device *bdev, int blocksize);
++static inline int bdev_dax_supported(struct super_block *sb,
+ int blocksize)
+ {
+ return -EOPNOTSUPP;
diff --git a/patches.suse/0201-dax-dm-allow-device-mapper-to-operate-without-dax-su.patch b/patches.suse/0201-dax-dm-allow-device-mapper-to-operate-without-dax-su.patch
deleted file mode 100644
index d2d1a36166..0000000000
--- a/patches.suse/0201-dax-dm-allow-device-mapper-to-operate-without-dax-su.patch
+++ /dev/null
@@ -1,291 +0,0 @@
-From 976431b02c2ef92ae3f8b6a7d699fc554025e118 Mon Sep 17 00:00:00 2001
-From: Dan Williams <dan.j.williams@intel.com>
-Date: Thu, 29 Mar 2018 17:22:13 -0700
-Subject: [PATCH] dax, dm: allow device-mapper to operate without dax support
-Git-commit: 976431b02c2ef92ae3f8b6a7d699fc554025e118
-Patch-mainline: v4.17-rc1
-References: bsc#1093023
-
-Change device-mapper's DAX dependency to require the presence of at
-least one DAX_DRIVER. This allows device-mapper to be built without
-bringing the DAX core along which is especially wasteful when there are
-no DAX drivers, like BLK_DEV_PMEM, configured.
-
-Cc: Alasdair Kergon <agk@redhat.com>
-Reported-by: Bart Van Assche <Bart.VanAssche@wdc.com>
-Reported-by: kbuild test robot <lkp@intel.com>
-Reported-by: Arnd Bergmann <arnd@arndb.de>
-Reviewed-by: Mike Snitzer <snitzer@redhat.com>
-Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-Signed-off-by: Coly Li <colyli@suse.de>
-
----
- drivers/md/Kconfig | 2
- drivers/md/dm-linear.c | 6 ++
- drivers/md/dm-log-writes.c | 95 +++++++++++++++++++++++----------------------
- drivers/md/dm-stripe.c | 6 ++
- drivers/md/dm.c | 10 ++--
- include/linux/dax.h | 30 +++++++++++---
- 6 files changed, 93 insertions(+), 56 deletions(-)
-
---- a/drivers/md/Kconfig
-+++ b/drivers/md/Kconfig
-@@ -201,7 +201,7 @@ config BLK_DEV_DM_BUILTIN
- config BLK_DEV_DM
- tristate "Device mapper support"
- select BLK_DEV_DM_BUILTIN
-- select DAX
-+ depends on DAX || DAX=n
- ---help---
- Device-mapper is a low level volume manager. It works by allowing
- people to specify mappings for ranges of logical sectors. Various
---- a/drivers/md/dm-linear.c
-+++ b/drivers/md/dm-linear.c
-@@ -154,6 +154,7 @@ static int linear_iterate_devices(struct
- return fn(ti, lc->dev, lc->start, ti->len, data);
- }
-
-+#if IS_ENABLED(CONFIG_DAX_DRIVER)
- static long linear_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
- long nr_pages, void **kaddr, pfn_t *pfn)
- {
-@@ -184,6 +185,11 @@ static size_t linear_dax_copy_from_iter(
- return dax_copy_from_iter(dax_dev, pgoff, addr, bytes, i);
- }
-
-+#else
-+#define linear_dax_direct_access NULL
-+#define linear_dax_copy_from_iter NULL
-+#endif
-+
- static struct target_type linear_target = {
- .name = "linear",
- .version = {1, 4, 0},
---- a/drivers/md/dm-log-writes.c
-+++ b/drivers/md/dm-log-writes.c
-@@ -611,51 +611,6 @@ static int log_mark(struct log_writes_c
- return 0;
- }
-
--static int log_dax(struct log_writes_c *lc, sector_t sector, size_t bytes,
-- struct iov_iter *i)
--{
-- struct pending_block *block;
--
-- if (!bytes)
-- return 0;
--
-- block = kzalloc(sizeof(struct pending_block), GFP_KERNEL);
-- if (!block) {
-- DMERR("Error allocating dax pending block");
-- return -ENOMEM;
-- }
--
-- block->data = kzalloc(bytes, GFP_KERNEL);
-- if (!block->data) {
-- DMERR("Error allocating dax data space");
-- kfree(block);
-- return -ENOMEM;
-- }
--
-- /* write data provided via the iterator */
-- if (!copy_from_iter(block->data, bytes, i)) {
-- DMERR("Error copying dax data");
-- kfree(block->data);
-- kfree(block);
-- return -EIO;
-- }
--
-- /* rewind the iterator so that the block driver can use it */
-- iov_iter_revert(i, bytes);
--
-- block->datalen = bytes;
-- block->sector = bio_to_dev_sectors(lc, sector);
-- block->nr_sectors = ALIGN(bytes, lc->sectorsize) >> lc->sectorshift;
--
-- atomic_inc(&lc->pending_blocks);
-- spin_lock_irq(&lc->blocks_lock);
-- list_add_tail(&block->list, &lc->unflushed_blocks);
-- spin_unlock_irq(&lc->blocks_lock);
-- wake_up_process(lc->log_kthread);
--
-- return 0;
--}
--
- static void log_writes_dtr(struct dm_target *ti)
- {
- struct log_writes_c *lc = ti->private;
-@@ -925,6 +880,52 @@ static void log_writes_io_hints(struct d
- limits->io_min = limits->physical_block_size;
- }
-
-+#if IS_ENABLED(CONFIG_DAX_DRIVER)
-+static int log_dax(struct log_writes_c *lc, sector_t sector, size_t bytes,
-+ struct iov_iter *i)
-+{
-+ struct pending_block *block;
-+
-+ if (!bytes)
-+ return 0;
-+
-+ block = kzalloc(sizeof(struct pending_block), GFP_KERNEL);
-+ if (!block) {
-+ DMERR("Error allocating dax pending block");
-+ return -ENOMEM;
-+ }
-+
-+ block->data = kzalloc(bytes, GFP_KERNEL);
-+ if (!block->data) {
-+ DMERR("Error allocating dax data space");
-+ kfree(block);
-+ return -ENOMEM;
-+ }
-+
-+ /* write data provided via the iterator */
-+ if (!copy_from_iter(block->data, bytes, i)) {
-+ DMERR("Error copying dax data");
-+ kfree(block->data);
-+ kfree(block);
-+ return -EIO;
-+ }
-+
-+ /* rewind the iterator so that the block driver can use it */
-+ iov_iter_revert(i, bytes);
-+
-+ block->datalen = bytes;
-+ block->sector = bio_to_dev_sectors(lc, sector);
-+ block->nr_sectors = ALIGN(bytes, lc->sectorsize) >> lc->sectorshift;
-+
-+ atomic_inc(&lc->pending_blocks);
-+ spin_lock_irq(&lc->blocks_lock);
-+ list_add_tail(&block->list, &lc->unflushed_blocks);
-+ spin_unlock_irq(&lc->blocks_lock);
-+ wake_up_process(lc->log_kthread);
-+
-+ return 0;
-+}
-+
- static long log_writes_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
- long nr_pages, void **kaddr, pfn_t *pfn)
- {
-@@ -961,6 +962,10 @@ static size_t log_writes_dax_copy_from_i
- dax_copy:
- return dax_copy_from_iter(lc->dev->dax_dev, pgoff, addr, bytes, i);
- }
-+#else
-+#define log_writes_dax_direct_access NULL
-+#define log_writes_dax_copy_from_iter NULL
-+#endif
-
- static struct target_type log_writes_target = {
- .name = "log-writes",
---- a/drivers/md/dm-stripe.c
-+++ b/drivers/md/dm-stripe.c
-@@ -313,6 +313,7 @@ static int stripe_map(struct dm_target *
- return DM_MAPIO_REMAPPED;
- }
-
-+#if IS_ENABLED(CONFIG_DAX_DRIVER)
- static long stripe_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
- long nr_pages, void **kaddr, pfn_t *pfn)
- {
-@@ -353,6 +354,11 @@ static size_t stripe_dax_copy_from_iter(
- return dax_copy_from_iter(dax_dev, pgoff, addr, bytes, i);
- }
-
-+#else
-+#define stripe_dax_direct_access NULL
-+#define stripe_dax_copy_from_iter NULL
-+#endif
-+
- /*
- * Stripe status:
- *
---- a/drivers/md/dm.c
-+++ b/drivers/md/dm.c
-@@ -1826,7 +1826,7 @@ static void cleanup_mapped_device(struct
- static struct mapped_device *alloc_dev(int minor)
- {
- int r, numa_node_id = dm_get_numa_node();
-- struct dax_device *dax_dev;
-+ struct dax_device *dax_dev = NULL;
- struct mapped_device *md;
- void *old_md;
-
-@@ -1892,9 +1892,11 @@ static struct mapped_device *alloc_dev(i
- md->disk->private_data = md;
- sprintf(md->disk->disk_name, "dm-%d", minor);
-
-- dax_dev = alloc_dax(md, md->disk->disk_name, &dm_dax_ops);
-- if (!dax_dev)
-- goto bad;
-+ if (IS_ENABLED(CONFIG_DAX_DRIVER)) {
-+ dax_dev = alloc_dax(md, md->disk->disk_name, &dm_dax_ops);
-+ if (!dax_dev)
-+ goto bad;
-+ }
- md->dax_dev = dax_dev;
-
- add_disk(md->disk);
---- a/include/linux/dax.h
-+++ b/include/linux/dax.h
-@@ -25,16 +25,39 @@ extern struct attribute_group dax_attrib
-
- #if IS_ENABLED(CONFIG_DAX)
- struct dax_device *dax_get_by_host(const char *host);
-+struct dax_device *alloc_dax(void *private, const char *host,
-+ const struct dax_operations *ops);
- void put_dax(struct dax_device *dax_dev);
-+void kill_dax(struct dax_device *dax_dev);
-+void dax_write_cache(struct dax_device *dax_dev, bool wc);
-+bool dax_write_cache_enabled(struct dax_device *dax_dev);
- #else
- static inline struct dax_device *dax_get_by_host(const char *host)
- {
- return NULL;
- }
--
-+static inline struct dax_device *alloc_dax(void *private, const char *host,
-+ const struct dax_operations *ops)
-+{
-+ /*
-+ * Callers should check IS_ENABLED(CONFIG_DAX) to know if this
-+ * NULL is an error or expected.
-+ */
-+ return NULL;
-+}
- static inline void put_dax(struct dax_device *dax_dev)
- {
- }
-+static inline void kill_dax(struct dax_device *dax_dev)
-+{
-+}
-+static inline void dax_write_cache(struct dax_device *dax_dev, bool wc)
-+{
-+}
-+static inline bool dax_write_cache_enabled(struct dax_device *dax_dev)
-+{
-+ return false;
-+}
- #endif
-
- int bdev_dax_pgoff(struct block_device *, sector_t, size_t, pgoff_t *pgoff);
-@@ -79,18 +102,13 @@ static inline struct dax_device *fs_dax_
-
- int dax_read_lock(void);
- void dax_read_unlock(int id);
--struct dax_device *alloc_dax(void *private, const char *host,
-- const struct dax_operations *ops);
- bool dax_alive(struct dax_device *dax_dev);
--void kill_dax(struct dax_device *dax_dev);
- void *dax_get_private(struct dax_device *dax_dev);
- long dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages,
- void **kaddr, pfn_t *pfn);
- size_t dax_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr,
- size_t bytes, struct iov_iter *i);
- void dax_flush(struct dax_device *dax_dev, void *addr, size_t size);
--void dax_write_cache(struct dax_device *dax_dev, bool wc);
--bool dax_write_cache_enabled(struct dax_device *dax_dev);
-
- /*
- * We use lowest available bit in exceptional entry for locking, one bit for
diff --git a/patches.suse/sched-fair-Consider-RT-IRQ-pressure-in-capacity_spare_wake.patch b/patches.suse/sched-fair-Consider-RT-IRQ-pressure-in-capacity_spare_wake.patch
new file mode 100644
index 0000000000..325bdaf194
--- /dev/null
+++ b/patches.suse/sched-fair-Consider-RT-IRQ-pressure-in-capacity_spare_wake.patch
@@ -0,0 +1,126 @@
+From 5e0054eb52904d25b2ff80c785400176ca7a5c0b Mon Sep 17 00:00:00 2001
+From: Joel Fernandes <joelaf@google.com>
+Date: Thu, 14 Dec 2017 13:21:58 -0800
+Subject: [PATCH] sched/fair: Consider RT/IRQ pressure in capacity_spare_wake()
+
+References: bnc#1101669 optimise numa balancing for fast migrate
+Patch-mainline: v4.16
+Git-commit: f453ae2200b0d1b7abc0c3794ce088899ac7a2af
+
+capacity_spare_wake() in the slow path influences choice of idlest groups,
+as we search for groups with maximum spare capacity. In scenarios where
+RT pressure is high, a sub optimal group can be chosen and hurt
+performance of the task being woken up.
+
+Fix this by using capacity_of() instead of capacity_orig_of() in capacity_spare_wake().
+
+Tests results from improvements with this change are below. More tests
+were also done by myself and Matt Fleming to ensure no degradation in
+different benchmarks.
+
+1) Rohit ran barrier.c test (details below) with following improvements:
+------------------------------------------------------------------------
+This was Rohit's original use case for a patch he posted at [1] however
+from his recent tests he showed my patch can replace his slow path
+changes [1] and there's no need to selectively scan/skip CPUs in
+find_idlest_group_cpu in the slow path to get the improvement he sees.
+
+barrier.c (open_mp code) as a micro-benchmark. It does a number of
+iterations and barrier sync at the end of each for loop.
+
+Here barrier,c is running in along with ping on CPU 0 and 1 as:
+'ping -l 10000 -q -s 10 -f hostX'
+
+barrier.c can be found at:
+http://www.spinics.net/lists/kernel/msg2506955.html
+
+Following are the results for the iterations per second with this
+micro-benchmark (higher is better), on a 44 core, 2 socket 88 Threads
+Intel x86 machine:
++--------+------------------+---------------------------+
+|Threads | Without patch | With patch |
+| | | |
++--------+--------+---------+-----------------+---------+
+| | Mean | Std Dev | Mean | Std Dev |
++--------+--------+---------+-----------------+---------+
+|1 | 539.36 | 60.16 | 572.54 (+6.15%) | 40.95 |
+|2 | 481.01 | 19.32 | 530.64 (+10.32%)| 56.16 |
+|4 | 474.78 | 22.28 | 479.46 (+0.99%) | 18.89 |
+|8 | 450.06 | 24.91 | 447.82 (-0.50%) | 12.36 |
+|16 | 436.99 | 22.57 | 441.88 (+1.12%) | 7.39 |
+|32 | 388.28 | 55.59 | 429.4 (+10.59%)| 31.14 |
+|64 | 314.62 | 6.33 | 311.81 (-0.89%) | 11.99 |
++--------+--------+---------+-----------------+---------+
+
+2) ping+hackbench test on bare-metal sever (by Rohit)
+-----------------------------------------------------
+Here hackbench is running in threaded mode along
+with, running ping on CPU 0 and 1 as:
+'ping -l 10000 -q -s 10 -f hostX'
+
+This test is running on 2 socket, 20 core and 40 threads Intel x86
+machine:
+Number of loops is 10000 and runtime is in seconds (Lower is better).
+
++--------------+-----------------+--------------------------+
+|Task Groups | Without patch | With patch |
+| +-------+---------+----------------+---------+
+|(Groups of 40)| Mean | Std Dev | Mean | Std Dev |
++--------------+-------+---------+----------------+---------+
+|1 | 0.851 | 0.007 | 0.828 (+2.77%)| 0.032 |
+|2 | 1.083 | 0.203 | 1.087 (-0.37%)| 0.246 |
+|4 | 1.601 | 0.051 | 1.611 (-0.62%)| 0.055 |
+|8 | 2.837 | 0.060 | 2.827 (+0.35%)| 0.031 |
+|16 | 5.139 | 0.133 | 5.107 (+0.63%)| 0.085 |
+|25 | 7.569 | 0.142 | 7.503 (+0.88%)| 0.143 |
++--------------+-------+---------+----------------+---------+
+
+[1] https://patchwork.kernel.org/patch/9991635/
+
+Matt Fleming also ran several different hackbench tests and cyclic test
+to santiy-check that the patch doesn't harm other usecases.
+
+Tested-by: Matt Fleming <matt@codeblueprint.co.uk>
+Tested-by: Rohit Jain <rohit.k.jain@oracle.com>
+Signed-off-by: Joel Fernandes <joelaf@google.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Vincent Guittot <vincent.guittot@linaro.org>
+Reviewed-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
+Cc: Atish Patra <atish.patra@oracle.com>
+Cc: Brendan Jackman <brendan.jackman@arm.com>
+Cc: Chris Redpath <Chris.Redpath@arm.com>
+Cc: Frederic Weisbecker <fweisbec@gmail.com>
+Cc: Juri Lelli <juri.lelli@arm.com>
+Cc: Len Brown <lenb@kernel.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Morten Ramussen <morten.rasmussen@arm.com>
+Cc: Patrick Bellasi <patrick.bellasi@arm.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
+Cc: Saravana Kannan <skannan@quicinc.com>
+Cc: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+Cc: Steve Muckle <smuckle@google.com>
+Cc: Steven Rostedt <rostedt@goodmis.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Vikram Mulukutla <markivx@codeaurora.org>
+Cc: Viresh Kumar <viresh.kumar@linaro.org>
+Link: http://lkml.kernel.org/r/20171214212158.188190-1-joelaf@google.com
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Mel Gorman <mgorman@suse.de>
+---
+ kernel/sched/fair.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
+index 9edea7a9d26d..14718f1bfd60 100644
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -5844,7 +5844,7 @@ static unsigned long cpu_util_wake(int cpu, struct task_struct *p);
+
+ static unsigned long capacity_spare_wake(int cpu, struct task_struct *p)
+ {
+- return capacity_orig_of(cpu) - cpu_util_wake(cpu, p);
++ return max_t(long, capacity_of(cpu) - cpu_util_wake(cpu, p), 0);
+ }
+
+ /*
diff --git a/patches.suse/sched-fair-Fix-find_idlest_group-when-local-group-is-not-allowed.patch b/patches.suse/sched-fair-Fix-find_idlest_group-when-local-group-is-not-allowed.patch
new file mode 100644
index 0000000000..5de0bc58f3
--- /dev/null
+++ b/patches.suse/sched-fair-Fix-find_idlest_group-when-local-group-is-not-allowed.patch
@@ -0,0 +1,50 @@
+From 8d7b5f3ab3feb50fede38056606b881ab992f809 Mon Sep 17 00:00:00 2001
+From: Brendan Jackman <brendan.jackman@arm.com>
+Date: Thu, 5 Oct 2017 12:45:14 +0100
+Subject: [PATCH] sched/fair: Fix find_idlest_group() when local group is not
+ allowed
+
+References: bnc#1101669 optimise numa balancing for fast migrate
+Patch-mainline: v4.15
+Git-commit: 0d10ab952e99f3e9f374898e93f45452b81e5711
+
+When the local group is not allowed we do not modify this_*_load from
+their initial value of 0. That means that the load checks at the end
+of find_idlest_group cause us to incorrectly return NULL. Fixing the
+initial values to ULONG_MAX means we will instead return the idlest
+remote group in that case.
+
+Signed-off-by: Brendan Jackman <brendan.jackman@arm.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Vincent Guittot <vincent.guittot@linaro.org>
+Reviewed-by: Josef Bacik <jbacik@fb.com>
+Cc: Dietmar Eggemann <dietmar.eggemann@arm.com>
+Cc: Josef Bacik <josef@toxicpanda.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Mike Galbraith <efault@gmx.de>
+Cc: Morten Rasmussen <morten.rasmussen@arm.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Link: http://lkml.kernel.org/r/20171005114516.18617-4-brendan.jackman@arm.com
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Mel Gorman <mgorman@suse.de>
+---
+ kernel/sched/fair.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
+index 1afeee2cefbc..5e9fdbaaf44d 100644
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -5857,8 +5857,9 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
+ {
+ struct sched_group *idlest = NULL, *group = sd->groups;
+ struct sched_group *most_spare_sg = NULL;
+- unsigned long min_runnable_load = ULONG_MAX, this_runnable_load = 0;
+- unsigned long min_avg_load = ULONG_MAX, this_avg_load = 0;
++ unsigned long min_runnable_load = ULONG_MAX;
++ unsigned long this_runnable_load = ULONG_MAX;
++ unsigned long min_avg_load = ULONG_MAX, this_avg_load = ULONG_MAX;
+ unsigned long most_spare = 0, this_spare = 0;
+ int load_idx = sd->forkexec_idx;
+ int imbalance_scale = 100 + (sd->imbalance_pct-100)/2;
diff --git a/patches.suse/sched-fair-Fix-usage-of-find_idlest_group-when-no-groups-are-allowed.patch b/patches.suse/sched-fair-Fix-usage-of-find_idlest_group-when-no-groups-are-allowed.patch
new file mode 100644
index 0000000000..ff77823cfa
--- /dev/null
+++ b/patches.suse/sched-fair-Fix-usage-of-find_idlest_group-when-no-groups-are-allowed.patch
@@ -0,0 +1,61 @@
+From b6a71bfbb60deb5f825ce5af778d3126adac4d92 Mon Sep 17 00:00:00 2001
+From: Brendan Jackman <brendan.jackman@arm.com>
+Date: Thu, 5 Oct 2017 12:45:15 +0100
+Subject: [PATCH] sched/fair: Fix usage of find_idlest_group() when no groups
+ are allowed
+
+References: bnc#1101669 optimise numa balancing for fast migrate
+Patch-mainline: v4.15
+Git-commit: 6fee85ccbc76e8aeba43dc120c5fa3c5409a4e2c
+
+When 'p' is not allowed on any of the CPUs in the sched_domain, we
+currently return NULL from find_idlest_group(), and pointlessly
+continue the search on lower sched_domain levels (where 'p' is also not
+allowed) before returning prev_cpu regardless (as we have not updated
+new_cpu).
+
+Add an explicit check for this case, and add a comment to
+find_idlest_group(). Now when find_idlest_group() returns NULL, it always
+means that the local group is allowed and idlest.
+
+Signed-off-by: Brendan Jackman <brendan.jackman@arm.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Vincent Guittot <vincent.guittot@linaro.org>
+Reviewed-by: Josef Bacik <jbacik@fb.com>
+Cc: Dietmar Eggemann <dietmar.eggemann@arm.com>
+Cc: Josef Bacik <josef@toxicpanda.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Mike Galbraith <efault@gmx.de>
+Cc: Morten Rasmussen <morten.rasmussen@arm.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Link: http://lkml.kernel.org/r/20171005114516.18617-5-brendan.jackman@arm.com
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Mel Gorman <mgorman@suse.de>
+---
+ kernel/sched/fair.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
+index 5e9fdbaaf44d..58adc098f7b7 100644
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -5850,6 +5850,8 @@ static unsigned long capacity_spare_wake(int cpu, struct task_struct *p)
+ /*
+ * find_idlest_group finds and returns the least busy CPU group within the
+ * domain.
++ *
++ * Assumes p is allowed on at least one CPU in sd.
+ */
+ static struct sched_group *
+ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
+@@ -6049,6 +6051,9 @@ static inline int find_idlest_cpu(struct sched_domain *sd, struct task_struct *p
+ {
+ int new_cpu = prev_cpu;
+
++ if (!cpumask_intersects(sched_domain_span(sd), &p->cpus_allowed))
++ return prev_cpu;
++
+ while (sd) {
+ struct sched_group *group;
+ struct sched_domain *tmp;
diff --git a/patches.suse/sched-fair-Fix-usage-of-find_idlest_group-when-the-local-group-is-idlest.patch b/patches.suse/sched-fair-Fix-usage-of-find_idlest_group-when-the-local-group-is-idlest.patch
new file mode 100644
index 0000000000..f5a9272212
--- /dev/null
+++ b/patches.suse/sched-fair-Fix-usage-of-find_idlest_group-when-the-local-group-is-idlest.patch
@@ -0,0 +1,49 @@
+From 4a963c2c00c9e52cfe4b462c65b4f259aab69123 Mon Sep 17 00:00:00 2001
+From: Brendan Jackman <brendan.jackman@arm.com>
+Date: Thu, 5 Oct 2017 12:45:16 +0100
+Subject: [PATCH] sched/fair: Fix usage of find_idlest_group() when the local
+ group is idlest
+
+References: bnc#1101669 optimise numa balancing for fast migrate
+Patch-mainline: v4.15
+Git-commit: 93f50f90247e3e926bbe9830df089c64a5cec236
+
+find_idlest_group() returns NULL when the local group is idlest. The
+caller then continues the find_idlest_group() search at a lower level
+of the current CPU's sched_domain hierarchy. find_idlest_group_cpu() is
+not consulted and, crucially, @new_cpu is not updated. This means the
+search is pointless and we return @prev_cpu from select_task_rq_fair().
+
+This is fixed by initialising @new_cpu to @cpu instead of @prev_cpu.
+
+Signed-off-by: Brendan Jackman <brendan.jackman@arm.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Josef Bacik <jbacik@fb.com>
+Reviewed-by: Vincent Guittot <vincent.guittot@linaro.org>
+Cc: Dietmar Eggemann <dietmar.eggemann@arm.com>
+Cc: Josef Bacik <josef@toxicpanda.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Mike Galbraith <efault@gmx.de>
+Cc: Morten Rasmussen <morten.rasmussen@arm.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Link: http://lkml.kernel.org/r/20171005114516.18617-6-brendan.jackman@arm.com
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Mel Gorman <mgorman@suse.de>
+---
+ kernel/sched/fair.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
+index 58adc098f7b7..54db37cf9dcb 100644
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -6049,7 +6049,7 @@ find_idlest_group_cpu(struct sched_group *group, struct task_struct *p, int this
+ static inline int find_idlest_cpu(struct sched_domain *sd, struct task_struct *p,
+ int cpu, int prev_cpu, int sd_flag)
+ {
+- int new_cpu = prev_cpu;
++ int new_cpu = cpu;
+
+ if (!cpumask_intersects(sched_domain_span(sd), &p->cpus_allowed))
+ return prev_cpu;
diff --git a/patches.suse/sched-fair-Move-select_task_rq_fair-slow-path-into-its-own-function.patch b/patches.suse/sched-fair-Move-select_task_rq_fair-slow-path-into-its-own-function.patch
new file mode 100644
index 0000000000..c8297373a7
--- /dev/null
+++ b/patches.suse/sched-fair-Move-select_task_rq_fair-slow-path-into-its-own-function.patch
@@ -0,0 +1,147 @@
+From ff6e7003437449a10180da203fd2649d9f80eaad Mon Sep 17 00:00:00 2001
+From: Brendan Jackman <brendan.jackman@arm.com>
+Date: Thu, 5 Oct 2017 12:45:12 +0100
+Subject: [PATCH] sched/fair: Move select_task_rq_fair() slow-path into its own
+ function
+
+References: bnc#1101669 optimise numa balancing for fast migrate
+Patch-mainline: v4.15
+Git-commit: 18bd1b4bd53aba81d76d55e91a68310a227dc187
+
+In preparation for changes that would otherwise require adding a new
+level of indentation to the while(sd) loop, create a new function
+find_idlest_cpu() which contains this loop, and rename the existing
+find_idlest_cpu() to find_idlest_group_cpu().
+
+Code inside the while(sd) loop is unchanged. @new_cpu is added as a
+variable in the new function, with the same initial value as the
+@new_cpu in select_task_rq_fair().
+
+Suggested-by: Peter Zijlstra <peterz@infradead.org>
+Signed-off-by: Brendan Jackman <brendan.jackman@arm.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Josef Bacik <jbacik@fb.com>
+Reviewed-by: Vincent Guittot <vincent.guittot@linaro.org>
+Cc: Dietmar Eggemann <dietmar.eggemann@arm.com>
+Cc: Josef Bacik <josef@toxicpanda.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Mike Galbraith <efault@gmx.de>
+Cc: Morten Rasmussen <morten.rasmussen@arm.com>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Link: http://lkml.kernel.org/r/20171005114516.18617-2-brendan.jackman@arm.com
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Mel Gorman <mgorman@suse.de>
+---
+ kernel/sched/fair.c | 83 +++++++++++++++++++++++++++++++----------------------
+ 1 file changed, 48 insertions(+), 35 deletions(-)
+
+diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
+index bd006a60d161..41a0f9ec6bce 100644
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -5991,10 +5991,10 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
+ }
+
+ /*
+- * find_idlest_cpu - find the idlest cpu among the cpus in group.
++ * find_idlest_group_cpu - find the idlest cpu among the cpus in group.
+ */
+ static int
+-find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu)
++find_idlest_group_cpu(struct sched_group *group, struct task_struct *p, int this_cpu)
+ {
+ unsigned long load, min_load = ULONG_MAX;
+ unsigned int min_exit_latency = UINT_MAX;
+@@ -6043,6 +6043,50 @@ find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu)
+ return shallowest_idle_cpu != -1 ? shallowest_idle_cpu : least_loaded_cpu;
+ }
+
++static inline int find_idlest_cpu(struct sched_domain *sd, struct task_struct *p,
++ int cpu, int prev_cpu, int sd_flag)
++{
++ int new_cpu = prev_cpu;
++
++ while (sd) {
++ struct sched_group *group;
++ struct sched_domain *tmp;
++ int weight;
++
++ if (!(sd->flags & sd_flag)) {
++ sd = sd->child;
++ continue;
++ }
++
++ group = find_idlest_group(sd, p, cpu, sd_flag);
++ if (!group) {
++ sd = sd->child;
++ continue;
++ }
++
++ new_cpu = find_idlest_group_cpu(group, p, cpu);
++ if (new_cpu == -1 || new_cpu == cpu) {
++ /* Now try balancing at a lower domain level of cpu */
++ sd = sd->child;
++ continue;
++ }
++
++ /* Now try balancing at a lower domain level of new_cpu */
++ cpu = new_cpu;
++ weight = sd->span_weight;
++ sd = NULL;
++ for_each_domain(cpu, tmp) {
++ if (weight <= tmp->span_weight)
++ break;
++ if (tmp->flags & sd_flag)
++ sd = tmp;
++ }
++ /* while loop will break here if sd == NULL */
++ }
++
++ return new_cpu;
++}
++
+ #ifdef CONFIG_SCHED_SMT
+
+ static inline void set_idle_cores(int cpu, int val)
+@@ -6426,39 +6470,8 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f
+ if (sd_flag & SD_BALANCE_WAKE) /* XXX always ? */
+ new_cpu = select_idle_sibling(p, prev_cpu, new_cpu);
+
+- } else while (sd) {
+- struct sched_group *group;
+- int weight;
+-
+- if (!(sd->flags & sd_flag)) {
+- sd = sd->child;
+- continue;
+- }
+-
+- group = find_idlest_group(sd, p, cpu, sd_flag);
+- if (!group) {
+- sd = sd->child;
+- continue;
+- }
+-
+- new_cpu = find_idlest_cpu(group, p, cpu);
+- if (new_cpu == -1 || new_cpu == cpu) {
+- /* Now try balancing at a lower domain level of cpu */
+- sd = sd->child;
+- continue;
+- }
+-
+- /* Now try balancing at a lower domain level of new_cpu */
+- cpu = new_cpu;
+- weight = sd->span_weight;
+- sd = NULL;
+- for_each_domain(cpu, tmp) {
+- if (weight <= tmp->span_weight)
+- break;
+- if (tmp->flags & sd_flag)
+- sd = tmp;
+- }
+- /* while loop will break here if sd == NULL */
++ } else {
++ new_cpu = find_idlest_cpu(sd, p, cpu, prev_cpu, sd_flag);
+ }
+ rcu_read_unlock();
+
diff --git a/patches.suse/sched-fair-Remove-impossible-condition-from-find_idlest_group_cpu.patch b/patches.suse/sched-fair-Remove-impossible-condition-from-find_idlest_group_cpu.patch
new file mode 100644
index 0000000000..a6a0a135df
--- /dev/null
+++ b/patches.suse/sched-fair-Remove-impossible-condition-from-find_idlest_group_cpu.patch
@@ -0,0 +1,65 @@
+From ecd598f23519728cb767cf94d186457d5b041702 Mon Sep 17 00:00:00 2001
+From: Joel Fernandes <joelaf@google.com>
+Date: Fri, 15 Dec 2017 07:39:44 -0800
+Subject: [PATCH] sched/fair: Remove impossible condition from
+ find_idlest_group_cpu()
+
+References: bnc#1101669 optimise numa balancing for fast migrate
+Patch-mainline: v4.16
+Git-commit: 18cec7e0ddd5e28b7722f7049d715873373be3e9
+
+find_idlest_group_cpu() goes through CPUs of a group previous selected by
+find_idlest_group(). find_idlest_group() returns NULL if the local group is the
+selected one and doesn't execute find_idlest_group_cpu if the group to which
+'cpu' belongs to is chosen. So we're always guaranteed to call
+find_idlest_group_cpu() with a group to which 'cpu' is non-local.
+
+This makes one of the conditions in find_idlest_group_cpu() an impossible one,
+which we can get rid off.
+
+Signed-off-by: Joel Fernandes <joelaf@google.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Brendan Jackman <brendan.jackman@arm.com>
+Reviewed-by: Vincent Guittot <vincent.guittot@linaro.org>
+Cc: Android Kernel <kernel-team@android.com>
+Cc: Atish Patra <atish.patra@oracle.com>
+Cc: Chris Redpath <Chris.Redpath@arm.com>
+Cc: Dietmar Eggemann <dietmar.eggemann@arm.com>
+Cc: EAS Dev <eas-dev@lists.linaro.org>
+Cc: Frederic Weisbecker <fweisbec@gmail.com>
+Cc: Josef Bacik <jbacik@fb.com>
+Cc: Juri Lelli <juri.lelli@arm.com>
+Cc: Len Brown <lenb@kernel.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Morten Ramussen <morten.rasmussen@arm.com>
+Cc: Patrick Bellasi <patrick.bellasi@arm.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
+Cc: Rohit Jain <rohit.k.jain@oracle.com>
+Cc: Saravana Kannan <skannan@quicinc.com>
+Cc: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+Cc: Steve Muckle <smuckle@google.com>
+Cc: Steven Rostedt <rostedt@goodmis.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Vikram Mulukutla <markivx@codeaurora.org>
+Cc: Viresh Kumar <viresh.kumar@linaro.org>
+Link: http://lkml.kernel.org/r/20171215153944.220146-3-joelaf@google.com
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Mel Gorman <mgorman@suse.de>
+---
+ kernel/sched/fair.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
+index 14718f1bfd60..406a5984b88c 100644
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -6036,7 +6036,7 @@ find_idlest_group_cpu(struct sched_group *group, struct task_struct *p, int this
+ }
+ } else if (shallowest_idle_cpu == -1) {
+ load = weighted_cpuload(cpu_rq(i));
+- if (load < min_load || (load == min_load && i == this_cpu)) {
++ if (load < min_load) {
+ min_load = load;
+ least_loaded_cpu = i;
+ }
diff --git a/patches.suse/sched-fair-Remove-unnecessary-comparison-with-1.patch b/patches.suse/sched-fair-Remove-unnecessary-comparison-with-1.patch
new file mode 100644
index 0000000000..847e162623
--- /dev/null
+++ b/patches.suse/sched-fair-Remove-unnecessary-comparison-with-1.patch
@@ -0,0 +1,47 @@
+From 9e4444529138743d40c4c9fc4000fd5618f748b9 Mon Sep 17 00:00:00 2001
+From: Brendan Jackman <brendan.jackman@arm.com>
+Date: Thu, 5 Oct 2017 12:45:13 +0100
+Subject: [PATCH] sched/fair: Remove unnecessary comparison with -1
+
+References: bnc#1101669 optimise numa balancing for fast migrate
+Patch-mainline: v4.15
+Git-commit: e90381eaecf6d59c60fe396838e0e99789531419
+
+Since commit:
+
+ 83a0a96a5f26 ("sched/fair: Leverage the idle state info when choosing the "idlest" cpu")
+
+find_idlest_group_cpu() (formerly find_idlest_cpu) no longer returns -1,
+so we can simplify the checking of the return value in find_idlest_cpu().
+
+Signed-off-by: Brendan Jackman <brendan.jackman@arm.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Josef Bacik <jbacik@fb.com>
+Reviewed-by: Vincent Guittot <vincent.guittot@linaro.org>
+Cc: Dietmar Eggemann <dietmar.eggemann@arm.com>
+Cc: Josef Bacik <josef@toxicpanda.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Mike Galbraith <efault@gmx.de>
+Cc: Morten Rasmussen <morten.rasmussen@arm.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Link: http://lkml.kernel.org/r/20171005114516.18617-3-brendan.jackman@arm.com
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Mel Gorman <mgorman@suse.de>
+---
+ kernel/sched/fair.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
+index 41a0f9ec6bce..1afeee2cefbc 100644
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -6065,7 +6065,7 @@ static inline int find_idlest_cpu(struct sched_domain *sd, struct task_struct *p