diff options
Diffstat (limited to 'debian/patches/bugfix/arm64')
32 files changed, 2732 insertions, 0 deletions
diff --git a/debian/patches/bugfix/arm64/arm64-PCI-Allow-resource-reallocation-if-necessary.patch b/debian/patches/bugfix/arm64/arm64-PCI-Allow-resource-reallocation-if-necessary.patch new file mode 100644 index 000000000..55fbe10b5 --- /dev/null +++ b/debian/patches/bugfix/arm64/arm64-PCI-Allow-resource-reallocation-if-necessary.patch @@ -0,0 +1,47 @@ +From: Benjamin Herrenschmidt <benh@kernel.crashing.org> +Date: Sat, 15 Jun 2019 10:23:56 +1000 +Subject: [PATCH 3/4] arm64: PCI: Allow resource reallocation if necessary +Origin: https://git.kernel.org/linus/3e8ba9686600e5f77e692126bf0293edf162989a + +Call pci_assign_unassigned_root_bus_resources() instead of the simpler: + + pci_bus_size_bridges(bus); + pci_bus_assign_resources(bus); + +pci_assign_unassigned_root_bus_resources() calls: + + __pci_bus_size_bridges(bus, add_list); + __pci_bus_assign_resources(bus, add_list, &fail_head); + +so this should be equivalent as long as we're able to assign everything. +If we were unable to assign something, previously we did nothing and left +it unassigned, but after this patch, we will attempt to do some +reallocation. + +Once we start honoring FW resource allocations, this will bring up the +"reallocation" feature which can help making room for SR-IOV when +necessary. + +Link: https://lore.kernel.org/r/20190615002359.29577-1-benh@kernel.crashing.org +Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> +[bhelgaas: commit log] +Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> +Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> +--- + arch/arm64/kernel/pci.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +Index: linux/arch/arm64/kernel/pci.c +=================================================================== +--- linux.orig/arch/arm64/kernel/pci.c ++++ linux/arch/arm64/kernel/pci.c +@@ -194,8 +194,7 @@ struct pci_bus *pci_acpi_scan_root(struc + if (!bus) + return NULL; + +- pci_bus_size_bridges(bus); +- pci_bus_assign_resources(bus); ++ pci_assign_unassigned_root_bus_resources(bus); + + list_for_each_entry(child, &bus->children, node) + pcie_bus_configure_settings(child); diff --git a/debian/patches/bugfix/arm64/arm64-PCI-Preserve-firmware-configuration-when-desir.patch b/debian/patches/bugfix/arm64/arm64-PCI-Preserve-firmware-configuration-when-desir.patch new file mode 100644 index 000000000..37bc6e0c8 --- /dev/null +++ b/debian/patches/bugfix/arm64/arm64-PCI-Preserve-firmware-configuration-when-desir.patch @@ -0,0 +1,46 @@ +From: Benjamin Herrenschmidt <benh@kernel.crashing.org> +Date: Sat, 15 Jun 2019 10:23:59 +1000 +Subject: [PATCH 4/4] arm64: PCI: Preserve firmware configuration when desired +Origin: https://git.kernel.org/linus/85dc04136e86680378546afb808357a58c06061c + +If we must preserve the firmware resource assignments, claim the existing +resources rather than reassigning everything. + +Link: https://lore.kernel.org/r/20190615002359.29577-4-benh@kernel.crashing.org +Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> +[bhelgaas: commit log] +Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> +Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> +Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> +--- + arch/arm64/kernel/pci.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +Index: linux/arch/arm64/kernel/pci.c +=================================================================== +--- linux.orig/arch/arm64/kernel/pci.c ++++ linux/arch/arm64/kernel/pci.c +@@ -169,6 +169,7 @@ struct pci_bus *pci_acpi_scan_root(struc + struct acpi_pci_generic_root_info *ri; + struct pci_bus *bus, *child; + struct acpi_pci_root_ops *root_ops; ++ struct pci_host_bridge *host; + + ri = kzalloc_node(sizeof(*ri), GFP_KERNEL, node); + if (!ri) +@@ -194,6 +195,15 @@ struct pci_bus *pci_acpi_scan_root(struc + if (!bus) + return NULL; + ++ /* If we must preserve the resource configuration, claim now */ ++ host = pci_find_host_bridge(bus); ++ if (host->preserve_config) ++ pci_bus_claim_resources(bus); ++ ++ /* ++ * Assign whatever was left unassigned. If we didn't claim above, ++ * this will reassign everything. ++ */ + pci_assign_unassigned_root_bus_resources(bus); + + list_for_each_entry(child, &bus->children, node) diff --git a/debian/patches/bugfix/arm64/arm64-acpi-Add-fixup-for-HPE-m400-quirks.patch b/debian/patches/bugfix/arm64/arm64-acpi-Add-fixup-for-HPE-m400-quirks.patch new file mode 100644 index 000000000..50098d001 --- /dev/null +++ b/debian/patches/bugfix/arm64/arm64-acpi-Add-fixup-for-HPE-m400-quirks.patch @@ -0,0 +1,92 @@ +From: Geoff Levand <geoff@infradead.org> +Date: Wed, 13 Jun 2018 10:56:08 -0700 +Subject: arm64/acpi: Add fixup for HPE m400 quirks +Forwarded: https://patchwork.codeaurora.org/patch/547277/ + +Adds a new ACPI init routine acpi_fixup_m400_quirks that adds +a work-around for HPE ProLiant m400 APEI firmware problems. + +The work-around disables APEI when CONFIG_ACPI_APEI is set and +m400 firmware is detected. Without this fixup m400 systems +experience errors like these on startup: + + [Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 2 + [Hardware Error]: event severity: fatal + [Hardware Error]: Error 0, type: fatal + [Hardware Error]: section_type: memory error + [Hardware Error]: error_status: 0x0000000000001300 + [Hardware Error]: error_type: 10, invalid address + Kernel panic - not syncing: Fatal hardware error! + +Signed-off-by: Geoff Levand <geoff@infradead.org> +[bwh: Adjust context to apply to Linux 4.19] +--- + arch/arm64/kernel/acpi.c | 40 ++++++++++++++++++++++++++++++++++++---- + 1 file changed, 36 insertions(+), 4 deletions(-) + +Index: linux/arch/arm64/kernel/acpi.c +=================================================================== +--- linux.orig/arch/arm64/kernel/acpi.c ++++ linux/arch/arm64/kernel/acpi.c +@@ -33,6 +33,8 @@ + #include <asm/pgtable.h> + #include <asm/smp_plat.h> + ++#include <acpi/apei.h> ++ + int acpi_noirq = 1; /* skip ACPI IRQ initialization */ + int acpi_disabled = 1; + EXPORT_SYMBOL(acpi_disabled); +@@ -179,6 +181,33 @@ out: + } + + /* ++ * acpi_fixup_m400_quirks - Work-around for HPE ProLiant m400 APEI firmware ++ * problems. ++ */ ++static void __init acpi_fixup_m400_quirks(void) ++{ ++ acpi_status status; ++ struct acpi_table_header *header; ++#if !defined(CONFIG_ACPI_APEI) ++ int hest_disable = HEST_DISABLED; ++#endif ++ ++ if (!IS_ENABLED(CONFIG_ACPI_APEI) || hest_disable != HEST_ENABLED) ++ return; ++ ++ status = acpi_get_table(ACPI_SIG_HEST, 0, &header); ++ ++ if (ACPI_SUCCESS(status) && !strncmp(header->oem_id, "HPE ", 6) && ++ !strncmp(header->oem_table_id, "ProLiant", 8) && ++ MIDR_IMPLEMENTOR(read_cpuid_id()) == ARM_CPU_IMP_APM) { ++ hest_disable = HEST_DISABLED; ++ pr_info("Disabled APEI for m400.\n"); ++ } ++ ++ acpi_put_table(header); ++} ++ ++/* + * acpi_boot_table_init() called from setup_arch(), always. + * 1. find RSDP and get its address, and then find XSDT + * 2. extract all tables and checksums them all +@@ -233,11 +262,14 @@ done: + if (acpi_disabled) { + if (earlycon_acpi_spcr_enable) + early_init_dt_scan_chosen_stdout(); +- } else { +- acpi_parse_spcr(earlycon_acpi_spcr_enable, true); +- if (IS_ENABLED(CONFIG_ACPI_BGRT)) +- acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt); ++ return; + } ++ ++ acpi_parse_spcr(earlycon_acpi_spcr_enable, true); ++ if (IS_ENABLED(CONFIG_ACPI_BGRT)) ++ acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt); ++ ++ acpi_fixup_m400_quirks(); + } + + pgprot_t __acpi_get_mem_attribute(phys_addr_t addr) diff --git a/debian/patches/bugfix/arm64/arm64-dts-allwinner-a64-Enable-A64-timer-workaround.patch b/debian/patches/bugfix/arm64/arm64-dts-allwinner-a64-Enable-A64-timer-workaround.patch new file mode 100644 index 000000000..543364416 --- /dev/null +++ b/debian/patches/bugfix/arm64/arm64-dts-allwinner-a64-Enable-A64-timer-workaround.patch @@ -0,0 +1,28 @@ +From: Samuel Holland <samuel@sholland.org> +Date: Sat, 12 Jan 2019 20:17:19 -0600 +Subject: arm64: dts: allwinner: a64: Enable A64 timer workaround +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git/commit?id=55ec26d6a4241363fa94f15377ebd8f1116fbfd7 + +As instability in the architectural timer has been observed on multiple +devices using this SoC, inluding the Pine64 and the Orange Pi Win, +enable the workaround in the SoC's device tree. + +Acked-by: Maxime Ripard <maxime.ripard@bootlin.com> +Signed-off-by: Samuel Holland <samuel@sholland.org> +Signed-off-by: Chen-Yu Tsai <wens@csie.org> +--- + arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 1 + + 1 file changed, 1 insertion(+) + +Index: linux/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +=================================================================== +--- linux.orig/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi ++++ linux/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +@@ -159,6 +159,7 @@ + + timer { + compatible = "arm,armv8-timer"; ++ allwinner,erratum-unknown1; + interrupts = <GIC_PPI 13 + (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>, + <GIC_PPI 14 diff --git a/debian/patches/bugfix/arm64/dts-rockchip-correct-voltage-selector-firefly-RK3399.patch b/debian/patches/bugfix/arm64/dts-rockchip-correct-voltage-selector-firefly-RK3399.patch new file mode 100644 index 000000000..4116ab598 --- /dev/null +++ b/debian/patches/bugfix/arm64/dts-rockchip-correct-voltage-selector-firefly-RK3399.patch @@ -0,0 +1,42 @@ +From: Heinrich Schuchardt <xypron.glpk@gmx.de> +Date: Mon, 4 Jun 2018 19:15:23 +0200 +Subject: arm64: dts: rockchip: correct voltage selector on Firefly-RK3399 +Bug-Debian: https://bugs.debian.org/900799 +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git/patch/?id=710e8c4a54be82ee8a97324e7b4330bf191e08bf + +Without this patch the Firefly-RK3399 board boot process hangs after these +lines: + + fan53555-regulator 0-0040: FAN53555 Option[8] Rev[1] Detected! + fan53555-reg: supplied by vcc_sys + vcc1v8_s3: supplied by vcc_1v8 + +Blacklisting driver fan53555 allows booting. + +The device tree uses a value of fcs,suspend-voltage-selector different to +any other board. + +Changing this setting to the usual value is sufficient to enable booting +and also matches the value used in the vendor kernel. + +Fixes: 171582e00db1 ("arm64: dts: rockchip: add support for firefly-rk3399 board") +Cc: stable@vger.kernel.org +Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de> +Signed-off-by: Heiko Stuebner <heiko@sntech.de> +--- + arch/arm64/boot/dts/rockchip/rk3399-firefly.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: linux/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts +=================================================================== +--- linux.orig/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts ++++ linux/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts +@@ -455,7 +455,7 @@ + vdd_cpu_b: regulator@40 { + compatible = "silergy,syr827"; + reg = <0x40>; +- fcs,suspend-voltage-selector = <0>; ++ fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_b"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0002-scsi-hisi_sas-Move-evaluation-of-hisi_hba-in-hisi_sa.patch b/debian/patches/bugfix/arm64/huawei-taishan/0002-scsi-hisi_sas-Move-evaluation-of-hisi_hba-in-hisi_sa.patch new file mode 100644 index 000000000..98b6e734e --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0002-scsi-hisi_sas-Move-evaluation-of-hisi_hba-in-hisi_sa.patch @@ -0,0 +1,47 @@ +From bbd24b8bdc501fb5dacb43e847b6eeb9a12829f5 Mon Sep 17 00:00:00 2001 +From: Luo Jiaxing <luojiaxing@huawei.com> +Date: Mon, 24 Sep 2018 23:06:29 +0800 +Subject: [PATCH 02/31] scsi: hisi_sas: Move evaluation of hisi_hba in + hisi_sas_task_prep() +Origin: https://git.kernel.org/linus/1668e3b6f8f8ed2ce685691c92b90dfadeaa3f2f + +In evaluating hisi_hba, the sas_port may be NULL, so for safety relocate +the the check to value possible NULL deference. + +Signed-off-by: Luo Jiaxing <luojiaxing@huawei.com> +Signed-off-by: John Garry <john.garry@huawei.com> +Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +Index: linux/drivers/scsi/hisi_sas/hisi_sas_main.c +=================================================================== +--- linux.orig/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ linux/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -288,13 +288,13 @@ static int hisi_sas_task_prep(struct sas + int *pass) + { + struct domain_device *device = task->dev; +- struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); ++ struct hisi_hba *hisi_hba; + struct hisi_sas_device *sas_dev = device->lldd_dev; + struct hisi_sas_port *port; + struct hisi_sas_slot *slot; + struct hisi_sas_cmd_hdr *cmd_hdr_base; + struct asd_sas_port *sas_port = device->port; +- struct device *dev = hisi_hba->dev; ++ struct device *dev; + int dlvry_queue_slot, dlvry_queue, rc, slot_idx; + int n_elem = 0, n_elem_req = 0, n_elem_resp = 0; + struct hisi_sas_dq *dq; +@@ -315,6 +315,9 @@ static int hisi_sas_task_prep(struct sas + return -ECOMM; + } + ++ hisi_hba = dev_to_hisi_hba(device); ++ dev = hisi_hba->dev; ++ + if (DEV_IS_GONE(sas_dev)) { + if (sas_dev) + dev_info(dev, "task prep: device %d not ready\n", diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0005-scsi-hisi_sas-unmask-interrupts-ent72-and-ent74.patch b/debian/patches/bugfix/arm64/huawei-taishan/0005-scsi-hisi_sas-unmask-interrupts-ent72-and-ent74.patch new file mode 100644 index 000000000..a25ca7885 --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0005-scsi-hisi_sas-unmask-interrupts-ent72-and-ent74.patch @@ -0,0 +1,29 @@ +From de1d5713a20562acdb3f94466232432c9dd1d95c Mon Sep 17 00:00:00 2001 +From: Xiang Chen <chenxiang66@hisilicon.com> +Date: Mon, 24 Sep 2018 23:06:32 +0800 +Subject: [PATCH 05/31] scsi: hisi_sas: unmask interrupts ent72 and ent74 +Origin: https://git.kernel.org/linus/6ecf5ba13cd5959eb75f617ff32c93bb67790e48 + +The interrupts of ent72 and ent74 are not processed by PCIe AER handling, +so we need to unmask the interrupts and process them first in the 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> +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: linux/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +=================================================================== +--- linux.orig/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ linux/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -441,7 +441,7 @@ static void init_reg_v3_hw(struct hisi_h + hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, 0xfefefefe); + hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK2, 0xfefefefe); + if (pdev->revision >= 0x21) +- hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0xffff7fff); ++ hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0xffff7aff); + else + hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0xfffe20ff); + hisi_sas_write32(hisi_hba, CHNL_PHYUPDOWN_INT_MSK, 0x0); diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0006-scsi-hisi_sas-Use-block-layer-tag-instead-for-IPTT.patch b/debian/patches/bugfix/arm64/huawei-taishan/0006-scsi-hisi_sas-Use-block-layer-tag-instead-for-IPTT.patch new file mode 100644 index 000000000..15a26a35a --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0006-scsi-hisi_sas-Use-block-layer-tag-instead-for-IPTT.patch @@ -0,0 +1,308 @@ +From d35bf6fccf7d4064065c078d3d369ffeaad6c731 Mon Sep 17 00:00:00 2001 +From: Xiang Chen <chenxiang66@hisilicon.com> +Date: Mon, 24 Sep 2018 23:06:33 +0800 +Subject: [PATCH 06/31] scsi: hisi_sas: Use block layer tag instead for IPTT +Origin: https://git.kernel.org/linus/784b46b7cba0ae914dd293f23848c5057c6ba017 + +Currently we use the IPTT defined in LLDD to identify IOs. Actually for +IOs which are from the block layer, they have tags to identify them. So +for those IOs, use tag of the block layer directly, and for IOs which is +not from the block layer (such as internal IOs from libsas/LLDD), reserve +96 IPTTs for them. + +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> +--- + drivers/scsi/hisi_sas/hisi_sas.h | 3 +- + drivers/scsi/hisi_sas/hisi_sas_main.c | 89 +++++++++++++++++--------- + drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 1 - + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 9 +-- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 8 ++- + 5 files changed, 70 insertions(+), 40 deletions(-) + +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -34,6 +34,7 @@ + #define HISI_SAS_MAX_DEVICES HISI_SAS_MAX_ITCT_ENTRIES + #define HISI_SAS_RESET_BIT 0 + #define HISI_SAS_REJECT_CMD_BIT 1 ++#define HISI_SAS_RESERVED_IPTT_CNT 96 + + #define HISI_SAS_STATUS_BUF_SZ (sizeof(struct hisi_sas_status_buffer)) + #define HISI_SAS_COMMAND_TABLE_SZ (sizeof(union hisi_sas_command_table)) +@@ -217,7 +218,7 @@ struct hisi_sas_hw { + int (*hw_init)(struct hisi_hba *hisi_hba); + void (*setup_itct)(struct hisi_hba *hisi_hba, + struct hisi_sas_device *device); +- int (*slot_index_alloc)(struct hisi_hba *hisi_hba, int *slot_idx, ++ int (*slot_index_alloc)(struct hisi_hba *hisi_hba, + struct domain_device *device); + struct hisi_sas_device *(*alloc_dev)(struct domain_device *device); + void (*sl_notify_ssp)(struct hisi_hba *hisi_hba, int phy_no); +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -184,7 +184,14 @@ static void hisi_sas_slot_index_clear(st + + static void hisi_sas_slot_index_free(struct hisi_hba *hisi_hba, int slot_idx) + { +- hisi_sas_slot_index_clear(hisi_hba, slot_idx); ++ unsigned long flags; ++ ++ if (hisi_hba->hw->slot_index_alloc || (slot_idx >= ++ hisi_hba->hw->max_command_entries - HISI_SAS_RESERVED_IPTT_CNT)) { ++ spin_lock_irqsave(&hisi_hba->lock, flags); ++ hisi_sas_slot_index_clear(hisi_hba, slot_idx); ++ spin_unlock_irqrestore(&hisi_hba->lock, flags); ++ } + } + + static void hisi_sas_slot_index_set(struct hisi_hba *hisi_hba, int slot_idx) +@@ -194,24 +201,34 @@ static void hisi_sas_slot_index_set(stru + set_bit(slot_idx, bitmap); + } + +-static int hisi_sas_slot_index_alloc(struct hisi_hba *hisi_hba, int *slot_idx) ++static int hisi_sas_slot_index_alloc(struct hisi_hba *hisi_hba, ++ struct scsi_cmnd *scsi_cmnd) + { +- unsigned int index; ++ int index; + void *bitmap = hisi_hba->slot_index_tags; ++ unsigned long flags; + ++ if (scsi_cmnd) ++ return scsi_cmnd->request->tag; ++ ++ spin_lock_irqsave(&hisi_hba->lock, flags); + index = find_next_zero_bit(bitmap, hisi_hba->slot_index_count, +- hisi_hba->last_slot_index + 1); ++ 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) ++ index = find_next_zero_bit(bitmap, ++ hisi_hba->slot_index_count, ++ hisi_hba->hw->max_command_entries - ++ HISI_SAS_RESERVED_IPTT_CNT); ++ if (index >= hisi_hba->slot_index_count) { ++ spin_unlock_irqrestore(&hisi_hba->lock, flags); + return -SAS_QUEUE_FULL; ++ } + } + hisi_sas_slot_index_set(hisi_hba, index); +- *slot_idx = index; + hisi_hba->last_slot_index = index; ++ spin_unlock_irqrestore(&hisi_hba->lock, flags); + +- return 0; ++ return index; + } + + static void hisi_sas_slot_index_init(struct hisi_hba *hisi_hba) +@@ -250,9 +267,7 @@ void hisi_sas_slot_task_free(struct hisi + + memset(slot, 0, offsetof(struct hisi_sas_slot, buf)); + +- spin_lock_irqsave(&hisi_hba->lock, flags); + hisi_sas_slot_index_free(hisi_hba, slot->idx); +- spin_unlock_irqrestore(&hisi_hba->lock, flags); + } + EXPORT_SYMBOL_GPL(hisi_sas_slot_task_free); + +@@ -385,16 +400,27 @@ static int hisi_sas_task_prep(struct sas + 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, +- device); +- else +- rc = hisi_sas_slot_index_alloc(hisi_hba, &slot_idx); +- spin_unlock_irqrestore(&hisi_hba->lock, flags); +- if (rc) ++ rc = hisi_hba->hw->slot_index_alloc(hisi_hba, device); ++ else { ++ struct scsi_cmnd *scsi_cmnd = NULL; ++ ++ if (task->uldd_task) { ++ struct ata_queued_cmd *qc; ++ ++ if (dev_is_sata(device)) { ++ qc = task->uldd_task; ++ scsi_cmnd = qc->scsicmd; ++ } else { ++ scsi_cmnd = task->uldd_task; ++ } ++ } ++ rc = hisi_sas_slot_index_alloc(hisi_hba, scsi_cmnd); ++ } ++ if (rc < 0) + goto err_out_dma_unmap; + ++ slot_idx = rc; + slot = &hisi_hba->slot_info[slot_idx]; + + spin_lock_irqsave(&dq->lock, flags); +@@ -455,9 +481,7 @@ static int hisi_sas_task_prep(struct sas + return 0; + + 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); + err_out_dma_unmap: + if (!sas_protocol_ata(task->task_proto)) { + if (task->num_scatter) { +@@ -1747,14 +1771,11 @@ hisi_sas_internal_abort_task_exec(struct + port = to_hisi_sas_port(sas_port); + + /* simply get a slot and send abort command */ +- spin_lock_irqsave(&hisi_hba->lock, flags); +- rc = hisi_sas_slot_index_alloc(hisi_hba, &slot_idx); +- if (rc) { +- spin_unlock_irqrestore(&hisi_hba->lock, flags); ++ rc = hisi_sas_slot_index_alloc(hisi_hba, NULL); ++ if (rc < 0) + goto err_out; +- } +- spin_unlock_irqrestore(&hisi_hba->lock, flags); + ++ slot_idx = rc; + slot = &hisi_hba->slot_info[slot_idx]; + + spin_lock_irqsave(&dq->lock, flags_dq); +@@ -1790,7 +1811,6 @@ hisi_sas_internal_abort_task_exec(struct + spin_lock_irqsave(&task->task_state_lock, flags); + task->task_state_flags |= SAS_TASK_AT_INITIATOR; + spin_unlock_irqrestore(&task->task_state_lock, flags); +- + WRITE_ONCE(slot->ready, 1); + /* send abort command to the chip */ + spin_lock_irqsave(&dq->lock, flags); +@@ -1801,9 +1821,7 @@ hisi_sas_internal_abort_task_exec(struct + return 0; + + 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); + err_out: + dev_err(dev, "internal abort task prep: failed[%d]!\n", rc); + +@@ -2179,6 +2197,8 @@ int hisi_sas_alloc(struct hisi_hba *hisi + hisi_sas_init_mem(hisi_hba); + + hisi_sas_slot_index_init(hisi_hba); ++ hisi_hba->last_slot_index = hisi_hba->hw->max_command_entries - ++ HISI_SAS_RESERVED_IPTT_CNT; + + hisi_hba->wq = create_singlethread_workqueue(dev_name(dev)); + if (!hisi_hba->wq) { +@@ -2382,8 +2402,15 @@ int hisi_sas_probe(struct platform_devic + shost->max_channel = 1; + shost->max_cmd_len = 16; + shost->sg_tablesize = min_t(u16, SG_ALL, HISI_SAS_SGE_PAGE_CNT); +- shost->can_queue = hisi_hba->hw->max_command_entries; +- shost->cmd_per_lun = hisi_hba->hw->max_command_entries; ++ if (hisi_hba->hw->slot_index_alloc) { ++ shost->can_queue = hisi_hba->hw->max_command_entries; ++ shost->cmd_per_lun = hisi_hba->hw->max_command_entries; ++ } else { ++ shost->can_queue = hisi_hba->hw->max_command_entries - ++ HISI_SAS_RESERVED_IPTT_CNT; ++ shost->cmd_per_lun = hisi_hba->hw->max_command_entries - ++ HISI_SAS_RESERVED_IPTT_CNT; ++ } + + sha->sas_ha_name = DRV_NAME; + sha->dev = hisi_hba->dev; +--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +@@ -1807,7 +1807,6 @@ static struct scsi_host_template sht_v1_ + .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, +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -770,7 +770,7 @@ static u32 hisi_sas_phy_read32(struct hi + + /* This function needs to be protected from pre-emption. */ + static int +-slot_index_alloc_quirk_v2_hw(struct hisi_hba *hisi_hba, int *slot_idx, ++slot_index_alloc_quirk_v2_hw(struct hisi_hba *hisi_hba, + struct domain_device *device) + { + int sata_dev = dev_is_sata(device); +@@ -778,6 +778,7 @@ slot_index_alloc_quirk_v2_hw(struct hisi + struct hisi_sas_device *sas_dev = device->lldd_dev; + int sata_idx = sas_dev->sata_idx; + int start, end; ++ unsigned long flags; + + if (!sata_dev) { + /* +@@ -801,6 +802,7 @@ slot_index_alloc_quirk_v2_hw(struct hisi + end = 64 * (sata_idx + 2); + } + ++ spin_lock_irqsave(&hisi_hba->lock, flags); + while (1) { + start = find_next_zero_bit(bitmap, + hisi_hba->slot_index_count, start); +@@ -815,8 +817,8 @@ slot_index_alloc_quirk_v2_hw(struct hisi + } + + set_bit(start, bitmap); +- *slot_idx = start; +- return 0; ++ spin_unlock_irqrestore(&hisi_hba->lock, flags); ++ return start; + } + + static bool sata_index_alloc_v2_hw(struct hisi_hba *hisi_hba, int *idx) +@@ -3558,7 +3560,6 @@ static struct scsi_host_template sht_v2_ + .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, +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -2108,7 +2108,6 @@ static struct scsi_host_template sht_v3_ + .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, +@@ -2118,6 +2117,7 @@ static struct scsi_host_template sht_v3_ + .target_destroy = sas_target_destroy, + .ioctl = sas_ioctl, + .shost_attrs = host_attrs, ++ .tag_alloc_policy = BLK_TAG_ALLOC_RR, + }; + + static const struct hisi_sas_hw hisi_sas_v3_hw = { +@@ -2255,8 +2255,10 @@ hisi_sas_v3_probe(struct pci_dev *pdev, + shost->max_channel = 1; + shost->max_cmd_len = 16; + shost->sg_tablesize = min_t(u16, SG_ALL, HISI_SAS_SGE_PAGE_CNT); +- shost->can_queue = hisi_hba->hw->max_command_entries; +- shost->cmd_per_lun = hisi_hba->hw->max_command_entries; ++ shost->can_queue = hisi_hba->hw->max_command_entries - ++ HISI_SAS_RESERVED_IPTT_CNT; ++ shost->cmd_per_lun = hisi_hba->hw->max_command_entries - ++ HISI_SAS_RESERVED_IPTT_CNT; + + sha->sas_ha_name = DRV_NAME; + sha->dev = dev; diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0007-scsi-hisi_sas-Update-v3-hw-AIP_LIMIT-and-CFG_AGING_T.patch b/debian/patches/bugfix/arm64/huawei-taishan/0007-scsi-hisi_sas-Update-v3-hw-AIP_LIMIT-and-CFG_AGING_T.patch new file mode 100644 index 000000000..440ad1a4a --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0007-scsi-hisi_sas-Update-v3-hw-AIP_LIMIT-and-CFG_AGING_T.patch @@ -0,0 +1,54 @@ +From 4fdcfb8a09d75fbabf4454a60001224b89245c82 Mon Sep 17 00:00:00 2001 +From: Xiang Chen <chenxiang66@hisilicon.com> +Date: Mon, 24 Sep 2018 23:06:34 +0800 +Subject: [PATCH 07/31] scsi: hisi_sas: Update v3 hw AIP_LIMIT and + CFG_AGING_TIME register values +Origin: https://git.kernel.org/linus/3bccfba8312762becfb05b35d698ba8cffd440f2 + +Update registers as follows: +- Default value of AIP timer is 1ms, and it is easy for some expanders to + cause IO error. Change the value to max value 65ms to avoid IO error for + those expanders. + +- A CQ completion will be reported by HW when 4 CQs have occurred or the + aging timer expires, whichever happens first. Sor serial IO scenario, it + will still wait 8us for every IO before it is reported. So in the + situation, the performance is poor. So to improve it, change the limit + time to the least value. + For other scenario, it does little affect to the performance. + +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> +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 3 +++ + 1 file changed, 3 insertions(+) + +Index: linux/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +=================================================================== +--- linux.orig/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ linux/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -127,6 +127,7 @@ + #define PHY_CTRL_RESET_OFF 0 + #define PHY_CTRL_RESET_MSK (0x1 << PHY_CTRL_RESET_OFF) + #define SL_CFG (PORT_BASE + 0x84) ++#define AIP_LIMIT (PORT_BASE + 0x90) + #define SL_CONTROL (PORT_BASE + 0x94) + #define SL_CONTROL_NOTIFY_EN_OFF 0 + #define SL_CONTROL_NOTIFY_EN_MSK (0x1 << SL_CONTROL_NOTIFY_EN_OFF) +@@ -431,6 +432,7 @@ static void init_reg_v3_hw(struct hisi_h + (u32)((1ULL << hisi_hba->queue_count) - 1)); + hisi_sas_write32(hisi_hba, CFG_MAX_TAG, 0xfff0400); + hisi_sas_write32(hisi_hba, HGC_SAS_TXFAIL_RETRY_CTRL, 0x108); ++ hisi_sas_write32(hisi_hba, CFG_AGING_TIME, 0x1); + hisi_sas_write32(hisi_hba, INT_COAL_EN, 0x1); + hisi_sas_write32(hisi_hba, OQ_INT_COAL_TIME, 0x1); + hisi_sas_write32(hisi_hba, OQ_INT_COAL_CNT, 0x1); +@@ -495,6 +497,7 @@ static void init_reg_v3_hw(struct hisi_h + hisi_sas_phy_write32(hisi_hba, i, SAS_SSP_CON_TIMER_CFG, 0x32); + /* used for 12G negotiate */ + hisi_sas_phy_write32(hisi_hba, i, COARSETUNE_TIME, 0x1e); ++ hisi_sas_phy_write32(hisi_hba, i, AIP_LIMIT, 0x2ffff); + } + + for (i = 0; i < hisi_hba->queue_count; i++) { diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0008-scsi-hisi_sas-Fix-spin-lock-management-in-slot_index.patch b/debian/patches/bugfix/arm64/huawei-taishan/0008-scsi-hisi_sas-Fix-spin-lock-management-in-slot_index.patch new file mode 100644 index 000000000..1dbe7390b --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0008-scsi-hisi_sas-Fix-spin-lock-management-in-slot_index.patch @@ -0,0 +1,33 @@ +From f27f6edaf4983b00a3c0e2f6ab720cfa3150a147 Mon Sep 17 00:00:00 2001 +From: John Garry <john.garry@huawei.com> +Date: Tue, 16 Oct 2018 23:00:36 +0800 +Subject: [PATCH 08/31] scsi: hisi_sas: Fix spin lock management in + slot_index_alloc_quirk_v2_hw() +Origin: https://git.kernel.org/linus/fe5fb42de36227c1c2dbb1e7403329ec8a915c20 + +Currently a spin_unlock_irqrestore() call is missing on the error path, +so add it. + +Reported-by: Julia Lawall <julia.lawall@lip6.fr> +Signed-off-by: John Garry <john.garry@huawei.com> +Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> +--- + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +Index: linux/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +=================================================================== +--- linux.orig/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ linux/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -806,8 +806,10 @@ slot_index_alloc_quirk_v2_hw(struct hisi + while (1) { + start = find_next_zero_bit(bitmap, + hisi_hba->slot_index_count, start); +- if (start >= end) ++ if (start >= end) { ++ spin_unlock_irqrestore(&hisi_hba->lock, flags); + return -SAS_QUEUE_FULL; ++ } + /* + * SAS IPTT bit0 should be 1, and SATA IPTT bit0 should be 0. + */ diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0009-scsi-hisi_sas-use-dma_set_mask_and_coherent.patch b/debian/patches/bugfix/arm64/huawei-taishan/0009-scsi-hisi_sas-use-dma_set_mask_and_coherent.patch new file mode 100644 index 000000000..9e466ba4c --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0009-scsi-hisi_sas-use-dma_set_mask_and_coherent.patch @@ -0,0 +1,40 @@ +From 59bc5f2f2492ef9949cd723fc98bafa7d8a6c287 Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig <hch@lst.de> +Date: Thu, 18 Oct 2018 15:10:17 +0200 +Subject: [PATCH 09/31] scsi: hisi_sas: use dma_set_mask_and_coherent +Origin: https://git.kernel.org/linus/e4db40e7a1a2cd6af3b6d5f8f3fba15533872398 + +The driver currently uses pci_set_dma_mask despite otherwise using the +generic DMA API. Switch it over to the better generic DMA API. + +Signed-off-by: Christoph Hellwig <hch@lst.de> +Acked-by: John Garry <john.garry@huawei.com> +Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +Index: linux/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +=================================================================== +--- linux.orig/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ linux/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -2199,14 +2199,11 @@ hisi_sas_v3_probe(struct pci_dev *pdev, + if (rc) + goto err_out_disable_device; + +- if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) || +- (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)) != 0)) { +- if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) || +- (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)) { +- dev_err(dev, "No usable DMA addressing method\n"); +- rc = -EIO; +- goto err_out_regions; +- } ++ if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) || ++ dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) { ++ dev_err(dev, "No usable DMA addressing method\n"); ++ rc = -EIO; ++ goto err_out_regions; + } + + shost = hisi_sas_shost_alloc_pci(pdev); diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0010-scsi-hisi_sas-Create-separate-host-attributes-per-HB.patch b/debian/patches/bugfix/arm64/huawei-taishan/0010-scsi-hisi_sas-Create-separate-host-attributes-per-HB.patch new file mode 100644 index 000000000..5bbf33aa2 --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0010-scsi-hisi_sas-Create-separate-host-attributes-per-HB.patch @@ -0,0 +1,116 @@ +From 4e63bca6e8c3a7fac800ee6c27f9afab13774fde Mon Sep 17 00:00:00 2001 +From: Xiang Chen <chenxiang66@hisilicon.com> +Date: Fri, 9 Nov 2018 22:06:32 +0800 +Subject: [PATCH 10/31] scsi: hisi_sas: Create separate host attributes per HBA +Origin: https://git.kernel.org/linus/c3566f9a617de3288739fd3b8e7539951bf2b04d + +Currently all the three HBA (v1/v2/v3 HW) share the same host attributes. + +To support each HBA having separate attributes in future, create per-HBA +attributes. + +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> +--- + drivers/scsi/hisi_sas/hisi_sas.h | 1 - + drivers/scsi/hisi_sas/hisi_sas_main.c | 6 ------ + drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 7 ++++++- + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 7 ++++++- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 7 ++++++- + 5 files changed, 18 insertions(+), 10 deletions(-) + +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -468,7 +468,6 @@ extern int hisi_sas_remove(struct platfo + 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, +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -2021,12 +2021,6 @@ 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[] = { +- &dev_attr_phy_event_threshold, +- NULL, +-}; +-EXPORT_SYMBOL_GPL(host_attrs); +- + static struct sas_domain_function_template hisi_sas_transport_ops = { + .lldd_dev_found = hisi_sas_dev_found, + .lldd_dev_gone = hisi_sas_dev_gone, +--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +@@ -1797,6 +1797,11 @@ static int hisi_sas_v1_init(struct hisi_ + return 0; + } + ++static struct device_attribute *host_attrs_v1_hw[] = { ++ &dev_attr_phy_event_threshold, ++ NULL ++}; ++ + static struct scsi_host_template sht_v1_hw = { + .name = DRV_NAME, + .module = THIS_MODULE, +@@ -1816,7 +1821,7 @@ static struct scsi_host_template sht_v1_ + .slave_alloc = sas_slave_alloc, + .target_destroy = sas_target_destroy, + .ioctl = sas_ioctl, +- .shost_attrs = host_attrs, ++ .shost_attrs = host_attrs_v1_hw, + }; + + static const struct hisi_sas_hw hisi_sas_v1_hw = { +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -3552,6 +3552,11 @@ static void wait_cmds_complete_timeout_v + dev_dbg(dev, "wait commands complete %dms\n", time); + } + ++struct device_attribute *host_attrs_v2_hw[] = { ++ &dev_attr_phy_event_threshold, ++ NULL ++}; ++ + static struct scsi_host_template sht_v2_hw = { + .name = DRV_NAME, + .module = THIS_MODULE, +@@ -3571,7 +3576,7 @@ static struct scsi_host_template sht_v2_ + .slave_alloc = sas_slave_alloc, + .target_destroy = sas_target_destroy, + .ioctl = sas_ioctl, +- .shost_attrs = host_attrs, ++ .shost_attrs = host_attrs_v2_hw, + }; + + static const struct hisi_sas_hw hisi_sas_v2_hw = { +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -2101,6 +2101,11 @@ static void wait_cmds_complete_timeout_v + dev_dbg(dev, "wait commands complete %dms\n", time); + } + ++struct device_attribute *host_attrs_v3_hw[] = { ++ &dev_attr_phy_event_threshold, ++ NULL ++}; ++ + static struct scsi_host_template sht_v3_hw = { + .name = DRV_NAME, + .module = THIS_MODULE, +@@ -2120,7 +2125,7 @@ static struct scsi_host_template sht_v3_ + .slave_alloc = sas_slave_alloc, + .target_destroy = sas_target_destroy, + .ioctl = sas_ioctl, +- .shost_attrs = host_attrs, ++ .shost_attrs = host_attrs_v3_hw, + .tag_alloc_policy = BLK_TAG_ALLOC_RR, + }; + diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0011-scsi-hisi_sas-Add-support-for-interrupt-converge-for.patch b/debian/patches/bugfix/arm64/huawei-taishan/0011-scsi-hisi_sas-Add-support-for-interrupt-converge-for.patch new file mode 100644 index 000000000..ae1b2d718 --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0011-scsi-hisi_sas-Add-support-for-interrupt-converge-for.patch @@ -0,0 +1,113 @@ +From 7e5e4c2dfd67e156956e46c4d503466726a5359c Mon Sep 17 00:00:00 2001 +From: Xiang Chen <chenxiang66@hisilicon.com> +Date: Fri, 9 Nov 2018 22:06:33 +0800 +Subject: [PATCH 11/31] scsi: hisi_sas: Add support for interrupt converge for + v3 hw +Origin: https://git.kernel.org/linus/488cf558e3d7c95daf737d9cae165019ee3f2840 + +If CQ_INT_CONVERGE_EN is enabled, the interrupts of all the 16 CQ queues +will be reported by CQ0. + +So we need to change the process of CQ tasklet for this situation. + +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> +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 29 +++++++++++++++++++++----- + 1 file changed, 24 insertions(+), 5 deletions(-) + +Index: linux/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +=================================================================== +--- linux.orig/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ linux/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -42,6 +42,7 @@ + #define MAX_CON_TIME_LIMIT_TIME 0xa4 + #define BUS_INACTIVE_LIMIT_TIME 0xa8 + #define REJECT_TO_OPEN_LIMIT_TIME 0xac ++#define CQ_INT_CONVERGE_EN 0xb0 + #define CFG_AGING_TIME 0xbc + #define HGC_DFX_CFG2 0xc0 + #define CFG_ABT_SET_QUERY_IPTT 0xd4 +@@ -371,6 +372,9 @@ struct hisi_sas_err_record_v3 { + ((fis.command == ATA_CMD_DEV_RESET) && \ + ((fis.control & ATA_SRST) != 0))) + ++static bool hisi_sas_intr_conv; ++MODULE_PARM_DESC(intr_conv, "interrupt converge enable (0-1)"); ++ + static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off) + { + void __iomem *regs = hisi_hba->regs + off; +@@ -436,6 +440,8 @@ static void init_reg_v3_hw(struct hisi_h + hisi_sas_write32(hisi_hba, INT_COAL_EN, 0x1); + hisi_sas_write32(hisi_hba, OQ_INT_COAL_TIME, 0x1); + hisi_sas_write32(hisi_hba, OQ_INT_COAL_CNT, 0x1); ++ hisi_sas_write32(hisi_hba, CQ_INT_CONVERGE_EN, ++ hisi_sas_intr_conv); + hisi_sas_write32(hisi_hba, OQ_INT_SRC, 0xffff); + hisi_sas_write32(hisi_hba, ENT_INT_SRC1, 0xffffffff); + hisi_sas_write32(hisi_hba, ENT_INT_SRC2, 0xffffffff); +@@ -1878,10 +1884,12 @@ static int interrupt_init_v3_hw(struct h + for (i = 0; i < hisi_hba->queue_count; i++) { + struct hisi_sas_cq *cq = &hisi_hba->cq[i]; + struct tasklet_struct *t = &cq->tasklet; ++ int nr = hisi_sas_intr_conv ? 16 : 16 + i; ++ unsigned long irqflags = hisi_sas_intr_conv ? IRQF_SHARED : 0; + +- rc = devm_request_irq(dev, pci_irq_vector(pdev, i+16), +- cq_interrupt_v3_hw, 0, +- DRV_NAME " cq", cq); ++ rc = devm_request_irq(dev, pci_irq_vector(pdev, nr), ++ cq_interrupt_v3_hw, irqflags, ++ DRV_NAME " cq", cq); + if (rc) { + dev_err(dev, + "could not request cq%d interrupt, rc=%d\n", +@@ -1898,8 +1906,9 @@ static int interrupt_init_v3_hw(struct h + free_cq_irqs: + for (k = 0; k < i; k++) { + struct hisi_sas_cq *cq = &hisi_hba->cq[k]; ++ int nr = hisi_sas_intr_conv ? 16 : 16 + k; + +- free_irq(pci_irq_vector(pdev, k+16), cq); ++ free_irq(pci_irq_vector(pdev, nr), cq); + } + free_irq(pci_irq_vector(pdev, 11), hisi_hba); + free_chnl_interrupt: +@@ -2089,8 +2098,16 @@ static void wait_cmds_complete_timeout_v + dev_dbg(dev, "wait commands complete %dms\n", time); + } + ++static ssize_t intr_conv_v3_hw_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ return scnprintf(buf, PAGE_SIZE, "%u\n", hisi_sas_intr_conv); ++} ++static DEVICE_ATTR_RO(intr_conv_v3_hw); ++ + struct device_attribute *host_attrs_v3_hw[] = { + &dev_attr_phy_event_threshold, ++ &dev_attr_intr_conv_v3_hw, + NULL + }; + +@@ -2303,8 +2320,9 @@ hisi_sas_v3_destroy_irqs(struct pci_dev + free_irq(pci_irq_vector(pdev, 11), hisi_hba); + for (i = 0; i < hisi_hba->queue_count; i++) { + struct hisi_sas_cq *cq = &hisi_hba->cq[i]; ++ int nr = hisi_sas_intr_conv ? 16 : 16 + i; + +- free_irq(pci_irq_vector(pdev, i+16), cq); ++ free_irq(pci_irq_vector(pdev, nr), cq); + } + pci_free_irq_vectors(pdev); + } +@@ -2626,6 +2644,7 @@ static struct pci_driver sas_v3_pci_driv + }; + + module_pci_driver(sas_v3_pci_driver); ++module_param_named(intr_conv, hisi_sas_intr_conv, bool, 0444); + + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("John Garry <john.garry@huawei.com>"); diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0012-scsi-hisi_sas-Add-support-for-interrupt-coalescing-f.patch b/debian/patches/bugfix/arm64/huawei-taishan/0012-scsi-hisi_sas-Add-support-for-interrupt-coalescing-f.patch new file mode 100644 index 000000000..4595633a2 --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0012-scsi-hisi_sas-Add-support-for-interrupt-coalescing-f.patch @@ -0,0 +1,150 @@ +From 20ca5e4f2c4a2c08340225f074c56f7be1c86f5b Mon Sep 17 00:00:00 2001 +From: Xiang Chen <chenxiang66@hisilicon.com> +Date: Fri, 9 Nov 2018 22:06:34 +0800 +Subject: [PATCH 12/31] scsi: hisi_sas: Add support for interrupt coalescing + for v3 hw +Origin: https://git.kernel.org/linus/37359798ec44ae03fab383a9bef3b7c9df819063 + +If INT_COAL_EN is enabled, configure time and count of interrupt +coalescing. Then if CQ collects count of CQ entries in time, it will +report the interrupt. Or if CQ doesn't collect enough CQ entries in time, +it will report the interrupt at timeout. + +As all the registers are not supported to be changed dynamically, we need +to config those register between disable and enable PHYs. + +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> +--- + drivers/scsi/hisi_sas/hisi_sas.h | 2 + + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 100 +++++++++++++++++++++++++ + 2 files changed, 102 insertions(+) + +Index: linux/drivers/scsi/hisi_sas/hisi_sas.h +=================================================================== +--- linux.orig/drivers/scsi/hisi_sas/hisi_sas.h ++++ linux/drivers/scsi/hisi_sas/hisi_sas.h +@@ -322,6 +322,8 @@ struct hisi_hba { + unsigned long sata_dev_bitmap[BITS_TO_LONGS(HISI_SAS_MAX_DEVICES)]; + struct work_struct rst_work; + u32 phy_state; ++ u32 intr_coal_ticks; /* Time of interrupt coalesce in us */ ++ u32 intr_coal_count; /* Interrupt count to coalesce */ + }; + + /* Generic HW DMA host memory structures */ +Index: linux/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +=================================================================== +--- linux.orig/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ linux/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -2105,9 +2105,109 @@ static ssize_t intr_conv_v3_hw_show(stru + } + static DEVICE_ATTR_RO(intr_conv_v3_hw); + ++static void config_intr_coal_v3_hw(struct hisi_hba *hisi_hba) ++{ ++ /* config those registers between enable and disable PHYs */ ++ hisi_sas_stop_phys(hisi_hba); ++ ++ if (hisi_hba->intr_coal_ticks == 0 || ++ hisi_hba->intr_coal_count == 0) { ++ hisi_sas_write32(hisi_hba, INT_COAL_EN, 0x1); ++ hisi_sas_write32(hisi_hba, OQ_INT_COAL_TIME, 0x1); ++ hisi_sas_write32(hisi_hba, OQ_INT_COAL_CNT, 0x1); ++ } else { ++ hisi_sas_write32(hisi_hba, INT_COAL_EN, 0x3); ++ hisi_sas_write32(hisi_hba, OQ_INT_COAL_TIME, ++ hisi_hba->intr_coal_ticks); ++ hisi_sas_write32(hisi_hba, OQ_INT_COAL_CNT, ++ hisi_hba->intr_coal_count); ++ } ++ phys_init_v3_hw(hisi_hba); ++} ++ ++static ssize_t intr_coal_ticks_v3_hw_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct Scsi_Host *shost = class_to_shost(dev); ++ struct hisi_hba *hisi_hba = shost_priv(shost); ++ ++ return scnprintf(buf, PAGE_SIZE, "%u\n", ++ hisi_hba->intr_coal_ticks); ++} ++ ++static ssize_t intr_coal_ticks_v3_hw_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct Scsi_Host *shost = class_to_shost(dev); ++ struct hisi_hba *hisi_hba = shost_priv(shost); ++ u32 intr_coal_ticks; ++ int ret; ++ ++ ret = kstrtou32(buf, 10, &intr_coal_ticks); ++ if (ret) { ++ dev_err(dev, "Input data of interrupt coalesce unmatch\n"); ++ return -EINVAL; ++ } ++ ++ if (intr_coal_ticks >= BIT(24)) { ++ dev_err(dev, "intr_coal_ticks must be less than 2^24!\n"); ++ return -EINVAL; ++ } ++ ++ hisi_hba->intr_coal_ticks = intr_coal_ticks; ++ ++ config_intr_coal_v3_hw(hisi_hba); ++ ++ return count; ++} ++static DEVICE_ATTR_RW(intr_coal_ticks_v3_hw); ++ ++static ssize_t intr_coal_count_v3_hw_show(struct device *dev, ++ struct device_attribute ++ *attr, char *buf) ++{ ++ struct Scsi_Host *shost = class_to_shost(dev); ++ struct hisi_hba *hisi_hba = shost_priv(shost); ++ ++ return scnprintf(buf, PAGE_SIZE, "%u\n", ++ hisi_hba->intr_coal_count); ++} ++ ++static ssize_t intr_coal_count_v3_hw_store(struct device *dev, ++ struct device_attribute ++ *attr, const char *buf, size_t count) ++{ ++ struct Scsi_Host *shost = class_to_shost(dev); ++ struct hisi_hba *hisi_hba = shost_priv(shost); ++ u32 intr_coal_count; ++ int ret; ++ ++ ret = kstrtou32(buf, 10, &intr_coal_count); ++ if (ret) { ++ dev_err(dev, "Input data of interrupt coalesce unmatch\n"); ++ return -EINVAL; ++ } ++ ++ if (intr_coal_count >= BIT(8)) { ++ dev_err(dev, "intr_coal_count must be less than 2^8!\n"); ++ return -EINVAL; ++ } ++ ++ hisi_hba->intr_coal_count = intr_coal_count; ++ ++ config_intr_coal_v3_hw(hisi_hba); ++ ++ return count; ++} ++static DEVICE_ATTR_RW(intr_coal_count_v3_hw); ++ + struct device_attribute *host_attrs_v3_hw[] = { + &dev_attr_phy_event_threshold, + &dev_attr_intr_conv_v3_hw, ++ &dev_attr_intr_coal_ticks_v3_hw, ++ &dev_attr_intr_coal_count_v3_hw, + NULL + }; + diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0013-scsi-hisi_sas-Relocate-some-codes-to-avoid-an-unused.patch b/debian/patches/bugfix/arm64/huawei-taishan/0013-scsi-hisi_sas-Relocate-some-codes-to-avoid-an-unused.patch new file mode 100644 index 000000000..060fbcfb8 --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0013-scsi-hisi_sas-Relocate-some-codes-to-avoid-an-unused.patch @@ -0,0 +1,92 @@ +From 22834ed6cec2690817120e960d43bbf76ddfda17 Mon Sep 17 00:00:00 2001 +From: Xiang Chen <chenxiang66@hisilicon.com> +Date: Fri, 9 Nov 2018 22:06:35 +0800 +Subject: [PATCH 13/31] scsi: hisi_sas: Relocate some codes to avoid an unused + check +Origin: https://git.kernel.org/linus/745b6847634c11dda1079d0290781a443eddb4b7 + +In function hisi_sas_task_prep(), we check asd_sas_port, but in function +hisi_sas_task_exec(), we already refer to asd_sas_port by using function +dev_to_hisi_hba() implicitly. So to avoid this possible invalid +dereference, relocate the check to function hisi_sas_task_prep(). + +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> +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 44 ++++++++++++++------------- + 1 file changed, 23 insertions(+), 21 deletions(-) + +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -303,36 +303,19 @@ static int hisi_sas_task_prep(struct sas + int *pass) + { + struct domain_device *device = task->dev; +- struct hisi_hba *hisi_hba; ++ 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; + struct hisi_sas_cmd_hdr *cmd_hdr_base; + struct asd_sas_port *sas_port = device->port; +- struct device *dev; ++ 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; + struct hisi_sas_dq *dq; + unsigned long flags; + int wr_q_index; + +- if (!sas_port) { +- struct task_status_struct *ts = &task->task_status; +- +- ts->resp = SAS_TASK_UNDELIVERED; +- ts->stat = SAS_PHY_DOWN; +- /* +- * libsas will use dev->port, should +- * not call task_done for sata +- */ +- if (device->dev_type != SAS_SATA_DEV) +- task->task_done(task); +- return -ECOMM; +- } +- +- hisi_hba = dev_to_hisi_hba(device); +- dev = hisi_hba->dev; +- + if (DEV_IS_GONE(sas_dev)) { + if (sas_dev) + dev_info(dev, "task prep: device %d not ready\n", +@@ -507,10 +490,29 @@ static int hisi_sas_task_exec(struct sas + u32 rc; + u32 pass = 0; + unsigned long flags; +- 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; ++ struct domain_device *device = task->dev; ++ struct asd_sas_port *sas_port = device->port; + struct hisi_sas_dq *dq = NULL; + ++ if (!sas_port) { ++ struct task_status_struct *ts = &task->task_status; ++ ++ ts->resp = SAS_TASK_UNDELIVERED; ++ ts->stat = SAS_PHY_DOWN; ++ /* ++ * libsas will use dev->port, should ++ * not call task_done for sata ++ */ ++ if (device->dev_type != SAS_SATA_DEV) ++ task->task_done(task); ++ return -ECOMM; ++ } ++ ++ hisi_hba = dev_to_hisi_hba(device); ++ dev = hisi_hba->dev; ++ + if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags))) { + /* + * For IOs from upper layer, it may already disable preempt diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0014-scsi-hisi_sas-Fix-warnings-detected-by-sparse.patch b/debian/patches/bugfix/arm64/huawei-taishan/0014-scsi-hisi_sas-Fix-warnings-detected-by-sparse.patch new file mode 100644 index 000000000..1f9ed71c0 --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0014-scsi-hisi_sas-Fix-warnings-detected-by-sparse.patch @@ -0,0 +1,429 @@ +From 13dda01985003ca1b930b42bb3927f7522f4ce69 Mon Sep 17 00:00:00 2001 +From: John Garry <john.garry@huawei.com> +Date: Thu, 6 Dec 2018 21:34:40 +0800 +Subject: [PATCH 14/31] scsi: hisi_sas: Fix warnings detected by sparse +Origin: https://git.kernel.org/linus/735bcc77e6ba83e464665cea9041072190ede37e + +This patchset fixes some warnings detected by the sparse tool, like these: +drivers/scsi/hisi_sas/hisi_sas_main.c:1469:52: warning: incorrect type in assignment (different base types) +drivers/scsi/hisi_sas/hisi_sas_main.c:1469:52: expected unsigned short [unsigned] [assigned] [usertype] tag_of_task_to_be_managed +drivers/scsi/hisi_sas/hisi_sas_main.c:1469:52: got restricted __le16 [usertype] <noident> +drivers/scsi/hisi_sas/hisi_sas_main.c:1723:52: warning: incorrect type in assignment (different base types) +drivers/scsi/hisi_sas/hisi_sas_main.c:1723:52: expected unsigned short [unsigned] [assigned] [usertype] tag_of_task_to_be_managed +drivers/scsi/hisi_sas/hisi_sas_main.c:1723:52: got restricted __le16 [usertype] <noident> + +Signed-off-by: John Garry <john.garry@huawei.com> +Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> +--- + drivers/scsi/hisi_sas/hisi_sas.h | 2 +- + drivers/scsi/hisi_sas/hisi_sas_main.c | 6 +-- + drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 15 +++--- + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 66 +++++++++++++++----------- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 37 +++++++++------ + 5 files changed, 71 insertions(+), 55 deletions(-) + +Index: linux/drivers/scsi/hisi_sas/hisi_sas.h +=================================================================== +--- linux.orig/drivers/scsi/hisi_sas/hisi_sas.h ++++ linux/drivers/scsi/hisi_sas/hisi_sas.h +@@ -211,7 +211,7 @@ struct hisi_sas_slot { + /* Do not reorder/change members after here */ + void *buf; + dma_addr_t buf_dma; +- int idx; ++ u16 idx; + }; + + struct hisi_sas_hw { +Index: linux/drivers/scsi/hisi_sas/hisi_sas_main.c +=================================================================== +--- linux.orig/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ linux/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1463,12 +1463,12 @@ static int hisi_sas_abort_task(struct sa + if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) { + struct scsi_cmnd *cmnd = task->uldd_task; + struct hisi_sas_slot *slot = task->lldd_task; +- u32 tag = slot->idx; ++ u16 tag = slot->idx; + int rc2; + + int_to_scsilun(cmnd->device->lun, &lun); + tmf_task.tmf = TMF_ABORT_TASK; +- tmf_task.tag_of_task_to_be_managed = cpu_to_le16(tag); ++ tmf_task.tag_of_task_to_be_managed = tag; + + rc = hisi_sas_debug_issue_ssp_tmf(task->dev, lun.scsi_lun, + &tmf_task); +@@ -1722,7 +1722,7 @@ static int hisi_sas_query_task(struct sa + + int_to_scsilun(cmnd->device->lun, &lun); + tmf_task.tmf = TMF_QUERY_TASK; +- tmf_task.tag_of_task_to_be_managed = cpu_to_le16(tag); ++ tmf_task.tag_of_task_to_be_managed = tag; + + rc = hisi_sas_debug_issue_ssp_tmf(device, + lun.scsi_lun, +Index: linux/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +=================================================================== +--- linux.orig/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c ++++ linux/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +@@ -510,6 +510,7 @@ static void setup_itct_v1_hw(struct hisi + struct hisi_sas_itct *itct = &hisi_hba->itct[device_id]; + struct asd_sas_port *sas_port = device->port; + struct hisi_sas_port *port = to_hisi_sas_port(sas_port); ++ u64 sas_addr; + + memset(itct, 0, sizeof(*itct)); + +@@ -534,8 +535,8 @@ static void setup_itct_v1_hw(struct hisi + itct->qw0 = cpu_to_le64(qw0); + + /* qw1 */ +- memcpy(&itct->sas_addr, device->sas_addr, SAS_ADDR_SIZE); +- itct->sas_addr = __swab64(itct->sas_addr); ++ memcpy(&sas_addr, device->sas_addr, SAS_ADDR_SIZE); ++ itct->sas_addr = cpu_to_le64(__swab64(sas_addr)); + + /* qw2 */ + itct->qw2 = cpu_to_le64((500ULL << ITCT_HDR_IT_NEXUS_LOSS_TL_OFF) | +@@ -561,7 +562,7 @@ static void clear_itct_v1_hw(struct hisi + reg_val &= ~CFG_AGING_TIME_ITCT_REL_MSK; + hisi_sas_write32(hisi_hba, CFG_AGING_TIME, reg_val); + +- qw0 = cpu_to_le64(itct->qw0); ++ qw0 = le64_to_cpu(itct->qw0); + qw0 &= ~ITCT_HDR_VALID_MSK; + itct->qw0 = cpu_to_le64(qw0); + } +@@ -1100,7 +1101,7 @@ static void slot_err_v1_hw(struct hisi_h + case SAS_PROTOCOL_SSP: + { + int error = -1; +- u32 dma_err_type = cpu_to_le32(err_record->dma_err_type); ++ u32 dma_err_type = le32_to_cpu(err_record->dma_err_type); + u32 dma_tx_err_type = ((dma_err_type & + ERR_HDR_DMA_TX_ERR_TYPE_MSK)) >> + ERR_HDR_DMA_TX_ERR_TYPE_OFF; +@@ -1108,9 +1109,9 @@ static void slot_err_v1_hw(struct hisi_h + ERR_HDR_DMA_RX_ERR_TYPE_MSK)) >> + ERR_HDR_DMA_RX_ERR_TYPE_OFF; + u32 trans_tx_fail_type = +- cpu_to_le32(err_record->trans_tx_fail_type); ++ le32_to_cpu(err_record->trans_tx_fail_type); + u32 trans_rx_fail_type = +- cpu_to_le32(err_record->trans_rx_fail_type); ++ le32_to_cpu(err_record->trans_rx_fail_type); + + if (dma_tx_err_type) { + /* dma tx err */ +@@ -1558,7 +1559,7 @@ static irqreturn_t cq_interrupt_v1_hw(in + u32 cmplt_hdr_data; + + complete_hdr = &complete_queue[rd_point]; +- cmplt_hdr_data = cpu_to_le32(complete_hdr->data); ++ cmplt_hdr_data = le32_to_cpu(complete_hdr->data); + idx = (cmplt_hdr_data & CMPLT_HDR_IPTT_MSK) >> + CMPLT_HDR_IPTT_OFF; + slot = &hisi_hba->slot_info[idx]; +Index: linux/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +=================================================================== +--- linux.orig/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ linux/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -934,6 +934,7 @@ static void setup_itct_v2_hw(struct hisi + struct domain_device *parent_dev = device->parent; + struct asd_sas_port *sas_port = device->port; + struct hisi_sas_port *port = to_hisi_sas_port(sas_port); ++ u64 sas_addr; + + memset(itct, 0, sizeof(*itct)); + +@@ -966,8 +967,8 @@ static void setup_itct_v2_hw(struct hisi + itct->qw0 = cpu_to_le64(qw0); + + /* qw1 */ +- memcpy(&itct->sas_addr, device->sas_addr, SAS_ADDR_SIZE); +- itct->sas_addr = __swab64(itct->sas_addr); ++ memcpy(&sas_addr, device->sas_addr, SAS_ADDR_SIZE); ++ itct->sas_addr = cpu_to_le64(__swab64(sas_addr)); + + /* qw2 */ + if (!dev_is_sata(device)) +@@ -2044,11 +2045,11 @@ static void slot_err_v2_hw(struct hisi_h + struct task_status_struct *ts = &task->task_status; + struct hisi_sas_err_record_v2 *err_record = + hisi_sas_status_buf_addr_mem(slot); +- u32 trans_tx_fail_type = cpu_to_le32(err_record->trans_tx_fail_type); +- u32 trans_rx_fail_type = cpu_to_le32(err_record->trans_rx_fail_type); +- u16 dma_tx_err_type = cpu_to_le16(err_record->dma_tx_err_type); +- u16 sipc_rx_err_type = cpu_to_le16(err_record->sipc_rx_err_type); +- u32 dma_rx_err_type = cpu_to_le32(err_record->dma_rx_err_type); ++ u32 trans_tx_fail_type = le32_to_cpu(err_record->trans_tx_fail_type); ++ u32 trans_rx_fail_type = le32_to_cpu(err_record->trans_rx_fail_type); ++ u16 dma_tx_err_type = le16_to_cpu(err_record->dma_tx_err_type); ++ u16 sipc_rx_err_type = le16_to_cpu(err_record->sipc_rx_err_type); ++ u32 dma_rx_err_type = le32_to_cpu(err_record->dma_rx_err_type); + int error = -1; + + if (err_phase == 1) { +@@ -2059,8 +2060,7 @@ static void slot_err_v2_hw(struct hisi_h + trans_tx_fail_type); + } else if (err_phase == 2) { + /* error in RX phase, the priority is: DW1 > DW3 > DW2 */ +- error = parse_trans_rx_err_code_v2_hw( +- trans_rx_fail_type); ++ error = parse_trans_rx_err_code_v2_hw(trans_rx_fail_type); + if (error == -1) { + error = parse_dma_rx_err_code_v2_hw( + dma_rx_err_type); +@@ -2358,6 +2358,7 @@ slot_complete_v2_hw(struct hisi_hba *his + &complete_queue[slot->cmplt_queue_slot]; + unsigned long flags; + bool is_internal = slot->is_internal; ++ u32 dw0; + + if (unlikely(!task || !task->lldd_task || !task->dev)) + return -EINVAL; +@@ -2382,8 +2383,9 @@ slot_complete_v2_hw(struct hisi_hba *his + } + + /* Use SAS+TMF status codes */ +- switch ((complete_hdr->dw0 & CMPLT_HDR_ABORT_STAT_MSK) +- >> CMPLT_HDR_ABORT_STAT_OFF) { ++ dw0 = le32_to_cpu(complete_hdr->dw0); ++ switch ((dw0 & CMPLT_HDR_ABORT_STAT_MSK) >> ++ CMPLT_HDR_ABORT_STAT_OFF) { + case STAT_IO_ABORTED: + /* this io has been aborted by abort command */ + ts->stat = SAS_ABORTED_TASK; +@@ -2408,9 +2410,8 @@ slot_complete_v2_hw(struct hisi_hba *his + break; + } + +- if ((complete_hdr->dw0 & CMPLT_HDR_ERX_MSK) && +- (!(complete_hdr->dw0 & CMPLT_HDR_RSPNS_XFRD_MSK))) { +- u32 err_phase = (complete_hdr->dw0 & CMPLT_HDR_ERR_PHASE_MSK) ++ if ((dw0 & CMPLT_HDR_ERX_MSK) && (!(dw0 & CMPLT_HDR_RSPNS_XFRD_MSK))) { ++ u32 err_phase = (dw0 & CMPLT_HDR_ERR_PHASE_MSK) + >> CMPLT_HDR_ERR_PHASE_OFF; + u32 *error_info = hisi_sas_status_buf_addr_mem(slot); + +@@ -2526,22 +2527,23 @@ static void prep_ata_v2_hw(struct hisi_h + struct hisi_sas_tmf_task *tmf = slot->tmf; + u8 *buf_cmd; + int has_data = 0, hdr_tag = 0; +- u32 dw1 = 0, dw2 = 0; ++ u32 dw0, dw1 = 0, dw2 = 0; + + /* create header */ + /* dw0 */ +- hdr->dw0 = cpu_to_le32(port->id << CMD_HDR_PORT_OFF); ++ dw0 = port->id << CMD_HDR_PORT_OFF; + if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) +- hdr->dw0 |= cpu_to_le32(3 << CMD_HDR_CMD_OFF); ++ dw0 |= 3 << CMD_HDR_CMD_OFF; + else +- hdr->dw0 |= cpu_to_le32(4 << CMD_HDR_CMD_OFF); ++ dw0 |= 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); ++ dw0 |= CMD_HDR_FORCE_PHY_MSK; ++ dw0 |= (1 << tmf->phy_id) << CMD_HDR_PHY_ID_OFF; + } + ++ hdr->dw0 = cpu_to_le32(dw0); ++ + /* dw1 */ + switch (task->data_dir) { + case DMA_TO_DEVICE: +@@ -3152,20 +3154,24 @@ static void cq_tasklet_v2_hw(unsigned lo + + /* Check for NCQ completion */ + if (complete_hdr->act) { +- u32 act_tmp = complete_hdr->act; ++ u32 act_tmp = le32_to_cpu(complete_hdr->act); + int ncq_tag_count = ffs(act_tmp); ++ u32 dw1 = le32_to_cpu(complete_hdr->dw1); + +- dev_id = (complete_hdr->dw1 & CMPLT_HDR_DEV_ID_MSK) >> ++ dev_id = (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]; ++ __le64 *_ncq_tag = &itct->qw4_15[0], __ncq_tag; ++ u64 ncq_tag; + +- ncq_tag_count -= 1; +- iptt = (ncq_tag[ncq_tag_count / 5] +- >> (ncq_tag_count % 5) * 12) & 0xfff; ++ ncq_tag_count--; ++ __ncq_tag = _ncq_tag[ncq_tag_count / 5]; ++ ncq_tag = le64_to_cpu(__ncq_tag); ++ iptt = (ncq_tag >> (ncq_tag_count % 5) * 12) & ++ 0xfff; + + slot = &hisi_hba->slot_info[iptt]; + slot->cmplt_queue_slot = rd_point; +@@ -3176,7 +3182,9 @@ static void cq_tasklet_v2_hw(unsigned lo + ncq_tag_count = ffs(act_tmp); + } + } else { +- iptt = (complete_hdr->dw1) & CMPLT_HDR_IPTT_MSK; ++ u32 dw1 = le32_to_cpu(complete_hdr->dw1); ++ ++ iptt = dw1 & CMPLT_HDR_IPTT_MSK; + slot = &hisi_hba->slot_info[iptt]; + slot->cmplt_queue_slot = rd_point; + slot->cmplt_queue = queue; +@@ -3552,7 +3560,7 @@ static void wait_cmds_complete_timeout_v + dev_dbg(dev, "wait commands complete %dms\n", time); + } + +-struct device_attribute *host_attrs_v2_hw[] = { ++static struct device_attribute *host_attrs_v2_hw[] = { + &dev_attr_phy_event_threshold, + NULL + }; +Index: linux/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +=================================================================== +--- linux.orig/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ linux/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -628,6 +628,7 @@ static void setup_itct_v3_hw(struct hisi + struct domain_device *parent_dev = device->parent; + struct asd_sas_port *sas_port = device->port; + struct hisi_sas_port *port = to_hisi_sas_port(sas_port); ++ u64 sas_addr; + + memset(itct, 0, sizeof(*itct)); + +@@ -660,8 +661,8 @@ static void setup_itct_v3_hw(struct hisi + itct->qw0 = cpu_to_le64(qw0); + + /* qw1 */ +- memcpy(&itct->sas_addr, device->sas_addr, SAS_ADDR_SIZE); +- itct->sas_addr = __swab64(itct->sas_addr); ++ memcpy(&sas_addr, device->sas_addr, SAS_ADDR_SIZE); ++ itct->sas_addr = cpu_to_le64(__swab64(sas_addr)); + + /* qw2 */ + if (!dev_is_sata(device)) +@@ -1590,15 +1591,16 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba + &complete_queue[slot->cmplt_queue_slot]; + struct hisi_sas_err_record_v3 *record = + hisi_sas_status_buf_addr_mem(slot); +- u32 dma_rx_err_type = record->dma_rx_err_type; +- u32 trans_tx_fail_type = record->trans_tx_fail_type; ++ u32 dma_rx_err_type = le32_to_cpu(record->dma_rx_err_type); ++ u32 trans_tx_fail_type = le32_to_cpu(record->trans_tx_fail_type); ++ u32 dw3 = le32_to_cpu(complete_hdr->dw3); + + switch (task->task_proto) { + case SAS_PROTOCOL_SSP: + if (dma_rx_err_type & RX_DATA_LEN_UNDERFLOW_MSK) { + ts->residual = trans_tx_fail_type; + ts->stat = SAS_DATA_UNDERRUN; +- } else if (complete_hdr->dw3 & CMPLT_HDR_IO_IN_TARGET_MSK) { ++ } else if (dw3 & CMPLT_HDR_IO_IN_TARGET_MSK) { + ts->stat = SAS_QUEUE_FULL; + slot->abort = 1; + } else { +@@ -1612,7 +1614,7 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba + if (dma_rx_err_type & RX_DATA_LEN_UNDERFLOW_MSK) { + ts->residual = trans_tx_fail_type; + ts->stat = SAS_DATA_UNDERRUN; +- } else if (complete_hdr->dw3 & CMPLT_HDR_IO_IN_TARGET_MSK) { ++ } else if (dw3 & CMPLT_HDR_IO_IN_TARGET_MSK) { + ts->stat = SAS_PHY_DOWN; + slot->abort = 1; + } else { +@@ -1645,6 +1647,7 @@ slot_complete_v3_hw(struct hisi_hba *his + &complete_queue[slot->cmplt_queue_slot]; + unsigned long flags; + bool is_internal = slot->is_internal; ++ u32 dw0, dw1, dw3; + + if (unlikely(!task || !task->lldd_task || !task->dev)) + return -EINVAL; +@@ -1668,11 +1671,14 @@ slot_complete_v3_hw(struct hisi_hba *his + goto out; + } + ++ dw0 = le32_to_cpu(complete_hdr->dw0); ++ dw1 = le32_to_cpu(complete_hdr->dw1); ++ dw3 = le32_to_cpu(complete_hdr->dw3); ++ + /* + * Use SAS+TMF status codes + */ +- switch ((complete_hdr->dw0 & CMPLT_HDR_ABORT_STAT_MSK) +- >> CMPLT_HDR_ABORT_STAT_OFF) { ++ switch ((dw0 & CMPLT_HDR_ABORT_STAT_MSK) >> CMPLT_HDR_ABORT_STAT_OFF) { + case STAT_IO_ABORTED: + /* this IO has been aborted by abort command */ + ts->stat = SAS_ABORTED_TASK; +@@ -1695,7 +1701,7 @@ slot_complete_v3_hw(struct hisi_hba *his + } + + /* check for erroneous completion */ +- if ((complete_hdr->dw0 & CMPLT_HDR_CMPLT_MSK) == 0x3) { ++ if ((dw0 & CMPLT_HDR_CMPLT_MSK) == 0x3) { + u32 *error_info = hisi_sas_status_buf_addr_mem(slot); + + slot_err_v3_hw(hisi_hba, task, slot); +@@ -1704,8 +1710,7 @@ slot_complete_v3_hw(struct hisi_hba *his + "CQ hdr: 0x%x 0x%x 0x%x 0x%x " + "Error info: 0x%x 0x%x 0x%x 0x%x\n", + slot->idx, task, sas_dev->device_id, +- complete_hdr->dw0, complete_hdr->dw1, +- complete_hdr->act, complete_hdr->dw3, ++ dw0, dw1, complete_hdr->act, dw3, + error_info[0], error_info[1], + error_info[2], error_info[3]); + if (unlikely(slot->abort)) +@@ -1803,11 +1808,13 @@ static void cq_tasklet_v3_hw(unsigned lo + while (rd_point != wr_point) { + struct hisi_sas_complete_v3_hdr *complete_hdr; + struct device *dev = hisi_hba->dev; ++ u32 dw1; + int iptt; + + complete_hdr = &complete_queue[rd_point]; ++ dw1 = le32_to_cpu(complete_hdr->dw1); + +- iptt = (complete_hdr->dw1) & CMPLT_HDR_IPTT_MSK; ++ iptt = dw1 & CMPLT_HDR_IPTT_MSK; + if (likely(iptt < HISI_SAS_COMMAND_ENTRIES_V3_HW)) { + slot = &hisi_hba->slot_info[iptt]; + slot->cmplt_queue_slot = rd_point; +@@ -2203,7 +2210,7 @@ static ssize_t intr_coal_count_v3_hw_sto + } + static DEVICE_ATTR_RW(intr_coal_count_v3_hw); + +-struct device_attribute *host_attrs_v3_hw[] = { ++static struct device_attribute *host_attrs_v3_hw[] = { + &dev_attr_phy_event_threshold, + &dev_attr_intr_conv_v3_hw, + &dev_attr_intr_coal_ticks_v3_hw, +@@ -2649,7 +2656,7 @@ static int hisi_sas_v3_suspend(struct pc + struct hisi_hba *hisi_hba = sha->lldd_ha; + struct device *dev = hisi_hba->dev; + struct Scsi_Host *shost = hisi_hba->shost; +- u32 device_state; ++ pci_power_t device_state; + int rc; + + if (!pdev->pm_cap) { +@@ -2695,7 +2702,7 @@ static int hisi_sas_v3_resume(struct pci + struct Scsi_Host *shost = hisi_hba->shost; + struct device *dev = hisi_hba->dev; + unsigned int rc; +- u32 device_state = pdev->current_state; ++ pci_power_t device_state = pdev->current_state; + + dev_warn(dev, "resuming from operating state [D%d]\n", + device_state); diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0015-scsi-hisi_sas-Relocate-some-code-to-reduce-complexit.patch b/debian/patches/bugfix/arm64/huawei-taishan/0015-scsi-hisi_sas-Relocate-some-code-to-reduce-complexit.patch new file mode 100644 index 000000000..1e44aa3b8 --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0015-scsi-hisi_sas-Relocate-some-code-to-reduce-complexit.patch @@ -0,0 +1,187 @@ +From 9e9903e8e143c32498565cb49a7aab6081734782 Mon Sep 17 00:00:00 2001 +From: Xiang Chen <chenxiang66@hisilicon.com> +Date: Thu, 6 Dec 2018 21:34:41 +0800 +Subject: [PATCH 15/31] scsi: hisi_sas: Relocate some code to reduce complexity +Origin: https://git.kernel.org/linus/6e1b731b535231e199c7810451c851398afccd33 + +Relocate the codes related to dma_map/unmap in hisi_sas_task_prep() to +reduce complexity, with a view to add DIF/DIX support. + +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> +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 146 ++++++++++++++++---------- + 1 file changed, 90 insertions(+), 56 deletions(-) + +Index: linux/drivers/scsi/hisi_sas/hisi_sas_main.c +=================================================================== +--- linux.orig/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ linux/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -297,6 +297,90 @@ static void hisi_sas_task_prep_abort(str + device_id, abort_flag, tag_to_abort); + } + ++static void hisi_sas_dma_unmap(struct hisi_hba *hisi_hba, ++ struct sas_task *task, int n_elem, ++ int n_elem_req, int n_elem_resp) ++{ ++ struct device *dev = hisi_hba->dev; ++ ++ if (!sas_protocol_ata(task->task_proto)) { ++ if (task->num_scatter) { ++ if (n_elem) ++ 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); ++ } ++ } ++} ++ ++static int hisi_sas_dma_map(struct hisi_hba *hisi_hba, ++ struct sas_task *task, int *n_elem, ++ int *n_elem_req, int *n_elem_resp) ++{ ++ struct device *dev = hisi_hba->dev; ++ int rc; ++ ++ if (sas_protocol_ata(task->task_proto)) { ++ *n_elem = task->num_scatter; ++ } else { ++ unsigned int req_len, resp_len; ++ ++ if (task->num_scatter) { ++ *n_elem = dma_map_sg(dev, task->scatter, ++ task->num_scatter, task->data_dir); ++ if (!*n_elem) { ++ 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_resp) { ++ rc = -ENOMEM; ++ goto err_out_dma_unmap; ++ } ++ resp_len = sg_dma_len(&task->smp_task.smp_resp); ++ if (resp_len & 0x3) { ++ rc = -EINVAL; ++ goto err_out_dma_unmap; ++ } ++ } ++ } ++ ++ 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; ++ } ++ return 0; ++ ++err_out_dma_unmap: ++ /* It would be better to call dma_unmap_sg() here, but it's messy */ ++ hisi_sas_dma_unmap(hisi_hba, task, *n_elem, ++ *n_elem_req, *n_elem_resp); ++prep_out: ++ return rc; ++} ++ + static int hisi_sas_task_prep(struct sas_task *task, + struct hisi_sas_dq **dq_pointer, + bool is_tmf, struct hisi_sas_tmf_task *tmf, +@@ -339,49 +423,10 @@ static int hisi_sas_task_prep(struct sas + return -ECOMM; + } + +- 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); +- if (!n_elem) { +- 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_resp) { +- rc = -ENOMEM; +- goto err_out_dma_unmap; +- } +- resp_len = sg_dma_len(&task->smp_task.smp_resp); +- if (resp_len & 0x3) { +- rc = -EINVAL; +- goto err_out_dma_unmap; +- } +- } +- } else +- n_elem = task->num_scatter; +- +- 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; +- } ++ rc = hisi_sas_dma_map(hisi_hba, task, &n_elem, ++ &n_elem_req, &n_elem_resp); ++ if (rc < 0) ++ goto prep_out; + + if (hisi_hba->hw->slot_index_alloc) + rc = hisi_hba->hw->slot_index_alloc(hisi_hba, device); +@@ -466,19 +511,8 @@ static int hisi_sas_task_prep(struct sas + err_out_tag: + hisi_sas_slot_index_free(hisi_hba, slot_idx); + 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); +- } +- } ++ hisi_sas_dma_unmap(hisi_hba, task, n_elem, ++ n_elem_req, n_elem_resp); + prep_out: + dev_err(dev, "task prep: failed[%d]!\n", rc); + return rc; diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0016-scsi-hisi_sas-Make-sg_tablesize-consistent-value.patch b/debian/patches/bugfix/arm64/huawei-taishan/0016-scsi-hisi_sas-Make-sg_tablesize-consistent-value.patch new file mode 100644 index 000000000..e025687be --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0016-scsi-hisi_sas-Make-sg_tablesize-consistent-value.patch @@ -0,0 +1,82 @@ +From 8baf75dd36d8e311434162c6a2c74a45262dc0d4 Mon Sep 17 00:00:00 2001 +From: Xiang Chen <chenxiang66@hisilicon.com> +Date: Thu, 6 Dec 2018 21:34:42 +0800 +Subject: [PATCH 16/31] scsi: hisi_sas: Make sg_tablesize consistent value +Origin: https://git.kernel.org/linus/6db831f4ef764ca19d7300d56ab9455af3cb930d + +Sht->sg_tablesize is set in the driver, and it will be assigned to +shost->sg_tablesize in SCSI mid-layer. So it is not necessary to assign +shost->sg_table one more time in the driver. + +In addition to the change, change each scsi_host_template.sg_tablesize +to HISI_SAS_SGE_PAGE_CNT instead of SG_ALL. + +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> +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 1 - + drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 2 +- + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2 +- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 3 +-- + 4 files changed, 3 insertions(+), 5 deletions(-) + +Index: linux/drivers/scsi/hisi_sas/hisi_sas_main.c +=================================================================== +--- linux.orig/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ linux/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -2426,7 +2426,6 @@ int hisi_sas_probe(struct platform_devic + shost->max_lun = ~0; + shost->max_channel = 1; + shost->max_cmd_len = 16; +- shost->sg_tablesize = min_t(u16, SG_ALL, HISI_SAS_SGE_PAGE_CNT); + if (hisi_hba->hw->slot_index_alloc) { + shost->can_queue = hisi_hba->hw->max_command_entries; + shost->cmd_per_lun = hisi_hba->hw->max_command_entries; +Index: linux/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +=================================================================== +--- linux.orig/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c ++++ linux/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +@@ -1814,7 +1814,7 @@ static struct scsi_host_template sht_v1_ + .change_queue_depth = sas_change_queue_depth, + .bios_param = sas_bios_param, + .this_id = -1, +- .sg_tablesize = SG_ALL, ++ .sg_tablesize = HISI_SAS_SGE_PAGE_CNT, + .max_sectors = SCSI_DEFAULT_MAX_SECTORS, + .use_clustering = ENABLE_CLUSTERING, + .eh_device_reset_handler = sas_eh_device_reset_handler, +Index: linux/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +=================================================================== +--- linux.orig/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ linux/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -3576,7 +3576,7 @@ static struct scsi_host_template sht_v2_ + .change_queue_depth = sas_change_queue_depth, + .bios_param = sas_bios_param, + .this_id = -1, +- .sg_tablesize = SG_ALL, ++ .sg_tablesize = HISI_SAS_SGE_PAGE_CNT, + .max_sectors = SCSI_DEFAULT_MAX_SECTORS, + .use_clustering = ENABLE_CLUSTERING, + .eh_device_reset_handler = sas_eh_device_reset_handler, +Index: linux/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +=================================================================== +--- linux.orig/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ linux/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -2229,7 +2229,7 @@ static struct scsi_host_template sht_v3_ + .change_queue_depth = sas_change_queue_depth, + .bios_param = sas_bios_param, + .this_id = -1, +- .sg_tablesize = SG_ALL, ++ .sg_tablesize = HISI_SAS_SGE_PAGE_CNT, + .max_sectors = SCSI_DEFAULT_MAX_SECTORS, + .use_clustering = ENABLE_CLUSTERING, + .eh_device_reset_handler = sas_eh_device_reset_handler, +@@ -2371,7 +2371,6 @@ hisi_sas_v3_probe(struct pci_dev *pdev, + shost->max_lun = ~0; + shost->max_channel = 1; + shost->max_cmd_len = 16; +- shost->sg_tablesize = min_t(u16, SG_ALL, HISI_SAS_SGE_PAGE_CNT); + shost->can_queue = hisi_hba->hw->max_command_entries - + HISI_SAS_RESERVED_IPTT_CNT; + shost->cmd_per_lun = hisi_hba->hw->max_command_entries - diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0017-net-hns3-remove-unnecessary-configuration-recapture-.patch b/debian/patches/bugfix/arm64/huawei-taishan/0017-net-hns3-remove-unnecessary-configuration-recapture-.patch new file mode 100644 index 000000000..377ee58bd --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0017-net-hns3-remove-unnecessary-configuration-recapture-.patch @@ -0,0 +1,43 @@ +From 341487a9b370af5c2566fb0c3fe5384c96bdbda7 Mon Sep 17 00:00:00 2001 +From: Huazhong Tan <tanhuazhong@huawei.com> +Date: Tue, 18 Dec 2018 19:37:52 +0800 +Subject: [PATCH 17/31] net: hns3: remove unnecessary configuration recapture + while resetting +Origin: https://git.kernel.org/linus/b51c366df70da0100193d13975980f1990a2d47b + +When doing reset, it is unnecessary to get the hardware's default +configuration again, otherwise, the user's configuration will be +overwritten. + +Fixes: 4ed340ab8f49 ("net: hns3: Add reset process in hclge_main") +Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com> +Signed-off-by: Peng Li <lipeng321@huawei.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + .../net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 13 ------------- + 1 file changed, 13 deletions(-) + +Index: linux/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +=================================================================== +--- linux.orig/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c ++++ linux/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +@@ -5814,19 +5814,6 @@ static int hclge_reset_ae_dev(struct hna + return ret; + } + +- ret = hclge_get_cap(hdev); +- if (ret) { +- dev_err(&pdev->dev, "get hw capability error, ret = %d.\n", +- ret); +- return ret; +- } +- +- ret = hclge_configure(hdev); +- if (ret) { +- dev_err(&pdev->dev, "Configure dev error, ret = %d.\n", ret); +- return ret; +- } +- + ret = hclge_map_tqp(hdev); + if (ret) { + dev_err(&pdev->dev, "Map tqp error, ret = %d.\n", ret); diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0018-net-hns3-remove-1000M-half-support-of-phy.patch b/debian/patches/bugfix/arm64/huawei-taishan/0018-net-hns3-remove-1000M-half-support-of-phy.patch new file mode 100644 index 000000000..e5141d719 --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0018-net-hns3-remove-1000M-half-support-of-phy.patch @@ -0,0 +1,29 @@ +From 7740fe91e657e23f25e750d9e34da059a6f607ac Mon Sep 17 00:00:00 2001 +From: Fuyun Liang <liangfuyun1@huawei.com> +Date: Tue, 18 Dec 2018 19:37:55 +0800 +Subject: [PATCH 18/31] net: hns3: remove 1000M/half support of phy +Origin: https://git.kernel.org/linus/8362089d787724bb252f13f942921051943369c7 + +Our phy does not support 1000M/half, this patch removes 1000M/half from +PHY_SUPPORTED_FEATURES. + +Signed-off-by: Fuyun Liang <liangfuyun1@huawei.com> +Signed-off-by: Peng Li <lipeng321@huawei.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: linux/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c +=================================================================== +--- linux.orig/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c ++++ linux/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c +@@ -14,7 +14,7 @@ + SUPPORTED_Asym_Pause | \ + PHY_10BT_FEATURES | \ + PHY_100BT_FEATURES | \ +- PHY_1000BT_FEATURES) ++ SUPPORTED_1000baseT_Full) + + enum hclge_mdio_c22_op_seq { + HCLGE_MDIO_C22_WRITE = 1, diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0019-net-hns3-synchronize-speed-and-duplex-from-phy-when-.patch b/debian/patches/bugfix/arm64/huawei-taishan/0019-net-hns3-synchronize-speed-and-duplex-from-phy-when-.patch new file mode 100644 index 000000000..6769afdcf --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0019-net-hns3-synchronize-speed-and-duplex-from-phy-when-.patch @@ -0,0 +1,32 @@ +From 4f28c6b52ffb62eb5a0a5a85af4fa10658fecee5 Mon Sep 17 00:00:00 2001 +From: Peng Li <lipeng321@huawei.com> +Date: Tue, 18 Dec 2018 19:37:56 +0800 +Subject: [PATCH 19/31] net: hns3: synchronize speed and duplex from phy when + phy link up +Origin: https://git.kernel.org/linus/0ad5ea5dbd6cb1e62bac547db5e61bab15af4f44 + +Driver calls phy_connect_direct and registers hclge_mac_adjust_link +to synchronize mac speed and duplex from phy. It is better to +synchronize mac speed and duplex from phy when phy link up. + +Signed-off-by: Peng Li <lipeng321@huawei.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c | 4 ++++ + 1 file changed, 4 insertions(+) + +Index: linux/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c +=================================================================== +--- linux.orig/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c ++++ linux/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c +@@ -181,6 +181,10 @@ static void hclge_mac_adjust_link(struct + int duplex, speed; + int ret; + ++ /* When phy link down, do nothing */ ++ if (netdev->phydev->link == 0) ++ return; ++ + speed = netdev->phydev->speed; + duplex = netdev->phydev->duplex; + diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0020-net-hns3-getting-tx-and-dv-buffer-size-through-firmw.patch b/debian/patches/bugfix/arm64/huawei-taishan/0020-net-hns3-getting-tx-and-dv-buffer-size-through-firmw.patch new file mode 100644 index 000000000..de4795be4 --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0020-net-hns3-getting-tx-and-dv-buffer-size-through-firmw.patch @@ -0,0 +1,157 @@ +From caeef6247aa6f5250d14108b33cef5458ba6c58e Mon Sep 17 00:00:00 2001 +From: Yunsheng Lin <linyunsheng@huawei.com> +Date: Tue, 18 Dec 2018 19:37:57 +0800 +Subject: [PATCH 20/31] net: hns3: getting tx and dv buffer size through + firmware +Origin: https://git.kernel.org/linus/368686be234daf365ef184a6ee1c4a6c18ede3b1 + +This patch adds support of getting tx and dv buffer size through +firmware, because different version of hardware requires different +size of tx and dv buffer. + +This patch also add dv_buf_size to tc' private buffer size even if +pfc is not enable for the tc. + +Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com> +Signed-off-by: Peng Li <lipeng321@huawei.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + .../hisilicon/hns3/hns3pf/hclge_cmd.h | 5 ++- + .../hisilicon/hns3/hns3pf/hclge_main.c | 41 ++++++++++++++----- + .../hisilicon/hns3/hns3pf/hclge_main.h | 3 ++ + 3 files changed, 38 insertions(+), 11 deletions(-) + +Index: linux/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +=================================================================== +--- linux.orig/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h ++++ linux/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +@@ -365,7 +365,9 @@ struct hclge_pf_res_cmd { + #define HCLGE_PF_VEC_NUM_M GENMASK(7, 0) + __le16 pf_intr_vector_number; + __le16 pf_own_fun_number; +- __le32 rsv[3]; ++ __le16 tx_buf_size; ++ __le16 dv_buf_size; ++ __le32 rsv[2]; + }; + + #define HCLGE_CFG_OFFSET_S 0 +@@ -791,6 +793,7 @@ struct hclge_serdes_lb_cmd { + #define HCLGE_TOTAL_PKT_BUF 0x108000 /* 1.03125M bytes */ + #define HCLGE_DEFAULT_DV 0xA000 /* 40k byte */ + #define HCLGE_DEFAULT_NON_DCB_DV 0x7800 /* 30K byte */ ++#define HCLGE_NON_DCB_ADDITIONAL_BUF 0x200 /* 512 byte */ + + #define HCLGE_TYPE_CRQ 0 + #define HCLGE_TYPE_CSQ 1 +Index: linux/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +=================================================================== +--- linux.orig/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c ++++ linux/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +@@ -931,6 +931,18 @@ static int hclge_query_pf_resource(struc + hdev->num_tqps = __le16_to_cpu(req->tqp_num); + hdev->pkt_buf_size = __le16_to_cpu(req->buf_size) << HCLGE_BUF_UNIT_S; + ++ if (req->tx_buf_size) ++ hdev->tx_buf_size = ++ __le16_to_cpu(req->tx_buf_size) << HCLGE_BUF_UNIT_S; ++ else ++ hdev->tx_buf_size = HCLGE_DEFAULT_TX_BUF; ++ ++ if (req->dv_buf_size) ++ hdev->dv_buf_size = ++ __le16_to_cpu(req->dv_buf_size) << HCLGE_BUF_UNIT_S; ++ else ++ hdev->dv_buf_size = HCLGE_DEFAULT_DV; ++ + if (hnae3_dev_roce_supported(hdev)) { + hdev->roce_base_msix_offset = + hnae3_get_field(__le16_to_cpu(req->msixcap_localid_ba_rocee), +@@ -1591,9 +1603,10 @@ static bool hclge_is_rx_buf_ok(struct h + pfc_enable_num = hclge_get_pfc_enalbe_num(hdev); + + if (hnae3_dev_dcb_supported(hdev)) +- shared_buf_min = 2 * hdev->mps + HCLGE_DEFAULT_DV; ++ shared_buf_min = 2 * hdev->mps + hdev->dv_buf_size; + else +- shared_buf_min = 2 * hdev->mps + HCLGE_DEFAULT_NON_DCB_DV; ++ shared_buf_min = hdev->mps + HCLGE_NON_DCB_ADDITIONAL_BUF ++ + hdev->dv_buf_size; + + shared_buf_tc = pfc_enable_num * hdev->mps + + (tc_num - pfc_enable_num) * hdev->mps / 2 + +@@ -1606,8 +1619,15 @@ static bool hclge_is_rx_buf_ok(struct h + + shared_buf = rx_all - rx_priv; + buf_alloc->s_buf.buf_size = shared_buf; +- buf_alloc->s_buf.self.high = shared_buf; +- buf_alloc->s_buf.self.low = 2 * hdev->mps; ++ if (hnae3_dev_dcb_supported(hdev)) { ++ buf_alloc->s_buf.self.high = shared_buf - hdev->dv_buf_size; ++ buf_alloc->s_buf.self.low = buf_alloc->s_buf.self.high ++ - hdev->mps / 2; ++ } else { ++ buf_alloc->s_buf.self.high = hdev->mps + ++ HCLGE_NON_DCB_ADDITIONAL_BUF; ++ buf_alloc->s_buf.self.low = hdev->mps / 2; ++ } + + for (i = 0; i < HCLGE_MAX_TC_NUM; i++) { + if ((hdev->hw_tc_map & BIT(i)) && +@@ -1634,11 +1654,11 @@ static int hclge_tx_buffer_calc(struct h + for (i = 0; i < HCLGE_MAX_TC_NUM; i++) { + struct hclge_priv_buf *priv = &buf_alloc->priv_buf[i]; + +- if (total_size < HCLGE_DEFAULT_TX_BUF) ++ if (total_size < hdev->tx_buf_size) + return -ENOMEM; + + if (hdev->hw_tc_map & BIT(i)) +- priv->tx_buf_size = HCLGE_DEFAULT_TX_BUF; ++ priv->tx_buf_size = hdev->tx_buf_size; + else + priv->tx_buf_size = 0; + +@@ -1684,11 +1704,12 @@ static int hclge_rx_buffer_calc(struct h + priv->wl.low = aligned_mps; + priv->wl.high = priv->wl.low + aligned_mps; + priv->buf_size = priv->wl.high + +- HCLGE_DEFAULT_DV; ++ hdev->dv_buf_size; + } else { + priv->wl.low = 0; + priv->wl.high = 2 * aligned_mps; +- priv->buf_size = priv->wl.high; ++ priv->buf_size = priv->wl.high + ++ hdev->dv_buf_size; + } + } else { + priv->enable = 0; +@@ -1720,11 +1741,11 @@ static int hclge_rx_buffer_calc(struct h + if (hdev->tm_info.hw_pfc_map & BIT(i)) { + priv->wl.low = 128; + priv->wl.high = priv->wl.low + aligned_mps; +- priv->buf_size = priv->wl.high + HCLGE_DEFAULT_DV; ++ priv->buf_size = priv->wl.high + hdev->dv_buf_size; + } else { + priv->wl.low = 0; + priv->wl.high = aligned_mps; +- priv->buf_size = priv->wl.high; ++ priv->buf_size = priv->wl.high + hdev->dv_buf_size; + } + } + +Index: linux/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +=================================================================== +--- linux.orig/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h ++++ linux/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +@@ -545,6 +545,9 @@ struct hclge_dev { + u32 flag; + + u32 pkt_buf_size; /* Total pf buf size for tx/rx */ ++ u32 tx_buf_size; /* Tx buffer size for each TC */ ++ u32 dv_buf_size; /* Dv buffer size for each TC */ ++ + u32 mps; /* Max packet size */ + + enum hclge_mta_dmac_sel_type mta_mac_sel_type; diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0021-net-hns3-aligning-buffer-size-in-SSU-to-256-bytes.patch b/debian/patches/bugfix/arm64/huawei-taishan/0021-net-hns3-aligning-buffer-size-in-SSU-to-256-bytes.patch new file mode 100644 index 000000000..e5c403de9 --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0021-net-hns3-aligning-buffer-size-in-SSU-to-256-bytes.patch @@ -0,0 +1,144 @@ +From 234c314e892d40daa37e97e9057e04d3e3a0c285 Mon Sep 17 00:00:00 2001 +From: Yunsheng Lin <linyunsheng@huawei.com> +Date: Tue, 18 Dec 2018 19:37:58 +0800 +Subject: [PATCH 21/31] net: hns3: aligning buffer size in SSU to 256 bytes +Origin: https://git.kernel.org/linus/b9a400ac295728b2d47445e09814e1880409b311 + +The hardware expects the buffer size set to SSU is aligned to +256 bytes, this patch aligns the buffer size to 256 byte using +roundup or rounddown function. + +Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com> +Signed-off-by: Peng Li <lipeng321@huawei.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + .../hisilicon/hns3/hns3pf/hclge_main.c | 45 ++++++++++++------- + 1 file changed, 28 insertions(+), 17 deletions(-) + +Index: linux/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +=================================================================== +--- linux.orig/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c ++++ linux/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +@@ -31,6 +31,10 @@ static int hclge_set_mta_filter_mode(str + enum hclge_mta_dmac_sel_type mta_mac_sel, + bool enable); + static int hclge_set_mtu(struct hnae3_handle *handle, int new_mtu); ++ ++#define HCLGE_BUF_SIZE_UNIT 256 ++ ++static int hclge_set_mac_mtu(struct hclge_dev *hdev, int new_mps); + static int hclge_init_vlan_config(struct hclge_dev *hdev); + static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev); + +@@ -937,12 +941,16 @@ static int hclge_query_pf_resource(struc + else + hdev->tx_buf_size = HCLGE_DEFAULT_TX_BUF; + ++ hdev->tx_buf_size = roundup(hdev->tx_buf_size, HCLGE_BUF_SIZE_UNIT); ++ + if (req->dv_buf_size) + hdev->dv_buf_size = + __le16_to_cpu(req->dv_buf_size) << HCLGE_BUF_UNIT_S; + else + hdev->dv_buf_size = HCLGE_DEFAULT_DV; + ++ hdev->dv_buf_size = roundup(hdev->dv_buf_size, HCLGE_BUF_SIZE_UNIT); ++ + if (hnae3_dev_roce_supported(hdev)) { + hdev->roce_base_msix_offset = + hnae3_get_field(__le16_to_cpu(req->msixcap_localid_ba_rocee), +@@ -1595,48 +1603,50 @@ static bool hclge_is_rx_buf_ok(struct h + { + u32 shared_buf_min, shared_buf_tc, shared_std; + int tc_num, pfc_enable_num; +- u32 shared_buf; ++ u32 shared_buf, aligned_mps; + u32 rx_priv; + int i; + + tc_num = hclge_get_tc_num(hdev); + pfc_enable_num = hclge_get_pfc_enalbe_num(hdev); ++ aligned_mps = roundup(hdev->mps, HCLGE_BUF_SIZE_UNIT); + + if (hnae3_dev_dcb_supported(hdev)) +- shared_buf_min = 2 * hdev->mps + hdev->dv_buf_size; ++ shared_buf_min = 2 * aligned_mps + hdev->dv_buf_size; + else +- shared_buf_min = hdev->mps + HCLGE_NON_DCB_ADDITIONAL_BUF ++ shared_buf_min = aligned_mps + HCLGE_NON_DCB_ADDITIONAL_BUF + + hdev->dv_buf_size; + +- shared_buf_tc = pfc_enable_num * hdev->mps + +- (tc_num - pfc_enable_num) * hdev->mps / 2 + +- hdev->mps; ++ shared_buf_tc = pfc_enable_num * aligned_mps + ++ (tc_num - pfc_enable_num) * aligned_mps / 2 + ++ aligned_mps; + shared_std = max_t(u32, shared_buf_min, shared_buf_tc); + + rx_priv = hclge_get_rx_priv_buff_alloced(buf_alloc); + if (rx_all <= rx_priv + shared_std) + return false; + +- shared_buf = rx_all - rx_priv; ++ shared_buf = rounddown(rx_all - rx_priv, HCLGE_BUF_SIZE_UNIT); + buf_alloc->s_buf.buf_size = shared_buf; + if (hnae3_dev_dcb_supported(hdev)) { + buf_alloc->s_buf.self.high = shared_buf - hdev->dv_buf_size; + buf_alloc->s_buf.self.low = buf_alloc->s_buf.self.high +- - hdev->mps / 2; ++ - roundup(aligned_mps / 2, HCLGE_BUF_SIZE_UNIT); + } else { +- buf_alloc->s_buf.self.high = hdev->mps + ++ buf_alloc->s_buf.self.high = aligned_mps + + HCLGE_NON_DCB_ADDITIONAL_BUF; +- buf_alloc->s_buf.self.low = hdev->mps / 2; ++ buf_alloc->s_buf.self.low = ++ roundup(aligned_mps / 2, HCLGE_BUF_SIZE_UNIT); + } + + for (i = 0; i < HCLGE_MAX_TC_NUM; i++) { + if ((hdev->hw_tc_map & BIT(i)) && + (hdev->tm_info.hw_pfc_map & BIT(i))) { +- buf_alloc->s_buf.tc_thrd[i].low = hdev->mps; +- buf_alloc->s_buf.tc_thrd[i].high = 2 * hdev->mps; ++ buf_alloc->s_buf.tc_thrd[i].low = aligned_mps; ++ buf_alloc->s_buf.tc_thrd[i].high = 2 * aligned_mps; + } else { + buf_alloc->s_buf.tc_thrd[i].low = 0; +- buf_alloc->s_buf.tc_thrd[i].high = hdev->mps; ++ buf_alloc->s_buf.tc_thrd[i].high = aligned_mps; + } + } + +@@ -1676,7 +1686,6 @@ static int hclge_tx_buffer_calc(struct h + static int hclge_rx_buffer_calc(struct hclge_dev *hdev, + struct hclge_pkt_buf_alloc *buf_alloc) + { +-#define HCLGE_BUF_SIZE_UNIT 128 + u32 rx_all = hdev->pkt_buf_size, aligned_mps; + int no_pfc_priv_num, pfc_priv_num; + struct hclge_priv_buf *priv; +@@ -1702,9 +1711,11 @@ static int hclge_rx_buffer_calc(struct h + priv->enable = 1; + if (hdev->tm_info.hw_pfc_map & BIT(i)) { + priv->wl.low = aligned_mps; +- priv->wl.high = priv->wl.low + aligned_mps; ++ priv->wl.high = ++ roundup(priv->wl.low + aligned_mps, ++ HCLGE_BUF_SIZE_UNIT); + priv->buf_size = priv->wl.high + +- hdev->dv_buf_size; ++ hdev->dv_buf_size; + } else { + priv->wl.low = 0; + priv->wl.high = 2 * aligned_mps; +@@ -1739,7 +1750,7 @@ static int hclge_rx_buffer_calc(struct h + priv->enable = 1; + + if (hdev->tm_info.hw_pfc_map & BIT(i)) { +- priv->wl.low = 128; ++ priv->wl.low = 256; + priv->wl.high = priv->wl.low + aligned_mps; + priv->buf_size = priv->wl.high + hdev->dv_buf_size; + } else { diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0022-net-hns3-fix-a-SSU-buffer-checking-bug.patch b/debian/patches/bugfix/arm64/huawei-taishan/0022-net-hns3-fix-a-SSU-buffer-checking-bug.patch new file mode 100644 index 000000000..26cee78ea --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0022-net-hns3-fix-a-SSU-buffer-checking-bug.patch @@ -0,0 +1,45 @@ +From 4d887b7901d59b472df97bd8a2f8bdeb43be7ced Mon Sep 17 00:00:00 2001 +From: Yunsheng Lin <linyunsheng@huawei.com> +Date: Tue, 18 Dec 2018 19:37:59 +0800 +Subject: [PATCH 22/31] net: hns3: fix a SSU buffer checking bug +Origin: https://git.kernel.org/linus/af854724e51e4047f534ac6d19b3ef9fb3c35c49 + +When caculating the SSU buffer, it first allocate tx and +rx private buffer, then the remaining buffer is for rx +shared buffer. The remaining buffer size should be at +least bigger than or equal to the shared_std, which is the +minimum shared buffer size required by the driver, but +currently if the remaining buffer size is equal to the +shared_std, it returns failure, which causes SSU buffer +allocation failure problem. + +This patch fixes this problem by rounding up shared_std before +checking the the remaining buffer size bigger than or equal to +the shared_std. + +Fixes: 46a3df9f9718 ("net: hns3: Add HNS3 Acceleration Engine & Compatibility Layer Support") +Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com> +Signed-off-by: Peng Li <lipeng321@huawei.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +Index: linux/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +=================================================================== +--- linux.orig/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c ++++ linux/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +@@ -1620,10 +1620,11 @@ static bool hclge_is_rx_buf_ok(struct h + shared_buf_tc = pfc_enable_num * aligned_mps + + (tc_num - pfc_enable_num) * aligned_mps / 2 + + aligned_mps; +- shared_std = max_t(u32, shared_buf_min, shared_buf_tc); ++ shared_std = roundup(max_t(u32, shared_buf_min, shared_buf_tc), ++ HCLGE_BUF_SIZE_UNIT); + + rx_priv = hclge_get_rx_priv_buff_alloced(buf_alloc); +- if (rx_all <= rx_priv + shared_std) ++ if (rx_all < rx_priv + shared_std) + return false; + + shared_buf = rounddown(rx_all - rx_priv, HCLGE_BUF_SIZE_UNIT); diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0023-net-hns3-change-default-tc-state-to-close.patch b/debian/patches/bugfix/arm64/huawei-taishan/0023-net-hns3-change-default-tc-state-to-close.patch new file mode 100644 index 000000000..ad8ccd77f --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0023-net-hns3-change-default-tc-state-to-close.patch @@ -0,0 +1,30 @@ +From ea3eff7a2ef69730c8e48715fbf965cb9da8b0bc Mon Sep 17 00:00:00 2001 +From: Jian Shen <shenjian15@huawei.com> +Date: Thu, 20 Dec 2018 11:51:59 +0800 +Subject: [PATCH 23/31] net: hns3: change default tc state to close +Origin: https://git.kernel.org/linus/a298797532d9dc244abf349d7c2ed063732c6ba3 + +In original codes, default tc value is set to the max tc. It's more +reasonable to close tc by changing default tc value to 1. Users can +enable it with lldp tool when they want to use tc. + +Signed-off-by: Jian Shen <shenjian15@huawei.com> +Signed-off-by: Peng Li <lipeng321@huawei.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: linux/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +=================================================================== +--- linux.orig/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c ++++ linux/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +@@ -1200,7 +1200,7 @@ static int hclge_configure(struct hclge_ + hdev->pfc_max = hdev->tc_max; + } + +- hdev->tm_info.num_tc = hdev->tc_max; ++ hdev->tm_info.num_tc = 1; + + /* Currently not support uncontiuous tc */ + for (i = 0; i < hdev->tm_info.num_tc; i++) diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0024-net-hns3-fix-a-bug-caused-by-udelay.patch b/debian/patches/bugfix/arm64/huawei-taishan/0024-net-hns3-fix-a-bug-caused-by-udelay.patch new file mode 100644 index 000000000..b3c3464ca --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0024-net-hns3-fix-a-bug-caused-by-udelay.patch @@ -0,0 +1,39 @@ +From 0f27af14383edac1efaf140d7cbe2d7dfdab7318 Mon Sep 17 00:00:00 2001 +From: Peng Li <lipeng321@huawei.com> +Date: Thu, 20 Dec 2018 11:52:00 +0800 +Subject: [PATCH 24/31] net: hns3: fix a bug caused by udelay +Origin: https://git.kernel.org/linus/1b7d7b0581173219b82abbd81c88cf8aa7d402c2 + +udelay() in driver may always occupancy processor. If there is only +one cpu in system, the VF driver may initialize fail when insmod +PF and VF driver in the same system. This patch use msleep() to free +cpu when VF wait PF message. + +Signed-off-by: Peng Li <lipeng321@huawei.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +Index: linux/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c +=================================================================== +--- linux.orig/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c ++++ linux/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c +@@ -26,7 +26,7 @@ static int hclgevf_get_mbx_resp(struct h + u8 *resp_data, u16 resp_len) + { + #define HCLGEVF_MAX_TRY_TIMES 500 +-#define HCLGEVF_SLEEP_USCOEND 1000 ++#define HCLGEVF_SLEEP_USECOND 1000 + struct hclgevf_mbx_resp_status *mbx_resp; + u16 r_code0, r_code1; + int i = 0; +@@ -40,7 +40,7 @@ static int hclgevf_get_mbx_resp(struct h + } + + while ((!hdev->mbx_resp.received_resp) && (i < HCLGEVF_MAX_TRY_TIMES)) { +- udelay(HCLGEVF_SLEEP_USCOEND); ++ usleep_range(HCLGEVF_SLEEP_USECOND, HCLGEVF_SLEEP_USECOND * 2); + i++; + } + diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0025-net-hns3-remove-redundant-variable-initialization.patch b/debian/patches/bugfix/arm64/huawei-taishan/0025-net-hns3-remove-redundant-variable-initialization.patch new file mode 100644 index 000000000..2dcf9f2ef --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0025-net-hns3-remove-redundant-variable-initialization.patch @@ -0,0 +1,28 @@ +From 883a7a53d7f6a6494e3a0df73fb02f76ecc42bc1 Mon Sep 17 00:00:00 2001 +From: Peng Li <lipeng321@huawei.com> +Date: Thu, 20 Dec 2018 11:52:06 +0800 +Subject: [PATCH 25/31] net: hns3: remove redundant variable initialization +Origin: https://git.kernel.org/linus/1154bb26c879fea51c20aee167ddce4345caa255 + +This patch removes the redundant variable initialization, +as driver will devm_kzalloc to set value to hdev soon. + +Signed-off-by: Peng Li <lipeng321@huawei.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: linux/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +=================================================================== +--- linux.orig/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c ++++ linux/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +@@ -1360,7 +1360,7 @@ static int hclgevf_configure(struct hclg + static int hclgevf_alloc_hdev(struct hnae3_ae_dev *ae_dev) + { + struct pci_dev *pdev = ae_dev->pdev; +- struct hclgevf_dev *hdev = ae_dev->priv; ++ struct hclgevf_dev *hdev; + + hdev = devm_kzalloc(&pdev->dev, sizeof(*hdev), GFP_KERNEL); + if (!hdev) diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0026-net-hns3-call-hns3_nic_net_open-while-doing-HNAE3_UP.patch b/debian/patches/bugfix/arm64/huawei-taishan/0026-net-hns3-call-hns3_nic_net_open-while-doing-HNAE3_UP.patch new file mode 100644 index 000000000..9eddea483 --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0026-net-hns3-call-hns3_nic_net_open-while-doing-HNAE3_UP.patch @@ -0,0 +1,46 @@ +From a4e5945057386872cb9add271aea76ca2413f481 Mon Sep 17 00:00:00 2001 +From: Huazhong Tan <tanhuazhong@huawei.com> +Date: Mon, 31 Dec 2018 10:58:29 +0800 +Subject: [PATCH 26/31] net: hns3: call hns3_nic_net_open() while doing + HNAE3_UP_CLIENT +Origin: https://git.kernel.org/linus/e888402789b9db5de4fcda361331d66dbf0cd9fd + +For HNAE3_DOWN_CLIENT calling hns3_nic_net_stop(), HNAE3_UP_CLIENT +should call hns3_nic_net_open(), since if the number of queue or +the map of TC has is changed before HHAE3_UP_CLIENT is called, +it will cause problem. + +Also the HNS3_NIC_STATE_RESETTING flag needs to be cleared before +hns3_nic_net_open() called, and set it back while hns3_nic_net_open() +failed. + +Fixes: bb6b94a896d4 ("net: hns3: Add reset interface implementation in client") +Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com> +Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com> +Signed-off-by: Peng Li <lipeng321@huawei.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +Index: linux/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +=================================================================== +--- linux.orig/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c ++++ linux/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +@@ -3439,11 +3439,15 @@ static int hns3_reset_notify_down_enet(s + static int hns3_reset_notify_up_enet(struct hnae3_handle *handle) + { + struct hnae3_knic_private_info *kinfo = &handle->kinfo; ++ struct hns3_nic_priv *priv = netdev_priv(kinfo->netdev); + int ret = 0; + ++ clear_bit(HNS3_NIC_STATE_RESETTING, &priv->state); ++ + if (netif_running(kinfo->netdev)) { +- ret = hns3_nic_net_up(kinfo->netdev); ++ ret = hns3_nic_net_open(kinfo->netdev); + if (ret) { ++ set_bit(HNS3_NIC_STATE_RESETTING, &priv->state); + netdev_err(kinfo->netdev, + "hns net up fail, ret=%d!\n", ret); + return ret; diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0029-RDMA-hns-Add-constraint-on-the-setting-of-local-ACK-.patch b/debian/patches/bugfix/arm64/huawei-taishan/0029-RDMA-hns-Add-constraint-on-the-setting-of-local-ACK-.patch new file mode 100644 index 000000000..48e2022bd --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0029-RDMA-hns-Add-constraint-on-the-setting-of-local-ACK-.patch @@ -0,0 +1,43 @@ +From 84193e72c505286e4681b3c566c64eea3e25f7fd Mon Sep 17 00:00:00 2001 +From: Lijun Ou <oulijun@huawei.com> +Date: Wed, 12 Dec 2018 17:49:08 +0800 +Subject: [PATCH 29/31] RDMA/hns: Add constraint on the setting of local ACK + timeout +Origin: https://git.kernel.org/linus/44754b95dd35ee07c462b5425ae9c4cde8c7e7c8 + +According to IB protocol, local ACK timeout shall be a 5 bit +value. Currently, hip08 could not support the possible max value 31. Fail +the request in this case. + +Signed-off-by: Yixian Liu <liuyixian@huawei.com> +Signed-off-by: Lijun Ou <oulijun@huawei.com> +Signed-off-by: Jason Gunthorpe <jgg@mellanox.com> +--- + drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +Index: linux/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +=================================================================== +--- linux.orig/drivers/infiniband/hw/hns/hns_roce_hw_v2.c ++++ linux/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +@@ -3398,10 +3398,16 @@ static int modify_qp_rtr_to_rts(struct i + V2_QPC_BYTE_212_LSN_S, 0); + + if (attr_mask & IB_QP_TIMEOUT) { +- roce_set_field(context->byte_28_at_fl, V2_QPC_BYTE_28_AT_M, +- V2_QPC_BYTE_28_AT_S, attr->timeout); +- roce_set_field(qpc_mask->byte_28_at_fl, V2_QPC_BYTE_28_AT_M, +- V2_QPC_BYTE_28_AT_S, 0); ++ if (attr->timeout < 31) { ++ roce_set_field(context->byte_28_at_fl, ++ V2_QPC_BYTE_28_AT_M, V2_QPC_BYTE_28_AT_S, ++ attr->timeout); ++ roce_set_field(qpc_mask->byte_28_at_fl, ++ V2_QPC_BYTE_28_AT_M, V2_QPC_BYTE_28_AT_S, ++ 0); ++ } else { ++ dev_warn(dev, "Local ACK timeout shall be 0 to 30.\n"); ++ } + } + + roce_set_field(context->byte_172_sq_psn, V2_QPC_BYTE_172_SQ_CUR_PSN_M, diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0030-RDMA-hns-Modify-the-pbl-ba-page-size-for-hip08.patch b/debian/patches/bugfix/arm64/huawei-taishan/0030-RDMA-hns-Modify-the-pbl-ba-page-size-for-hip08.patch new file mode 100644 index 000000000..612b481ff --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0030-RDMA-hns-Modify-the-pbl-ba-page-size-for-hip08.patch @@ -0,0 +1,28 @@ +From 454bc02382f8ed2eb3ebc7db4867ed419e3f0241 Mon Sep 17 00:00:00 2001 +From: Lijun Ou <oulijun@huawei.com> +Date: Wed, 12 Dec 2018 17:49:09 +0800 +Subject: [PATCH 30/31] RDMA/hns: Modify the pbl ba page size for hip08 +Origin: https://git.kernel.org/linus/91fb4d83b88a7b544ce564c44167aad29d4154f0 + +Modify the pbl ba page size to 16K for in order to support 4G MR size. + +Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com> +Signed-off-by: Lijun Ou <oulijun@huawei.com> +Signed-off-by: Jason Gunthorpe <jgg@mellanox.com> +--- + drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: linux/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +=================================================================== +--- linux.orig/drivers/infiniband/hw/hns/hns_roce_hw_v2.c ++++ linux/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +@@ -1235,7 +1235,7 @@ static int hns_roce_v2_profile(struct hn + caps->mpt_ba_pg_sz = 0; + caps->mpt_buf_pg_sz = 0; + caps->mpt_hop_num = HNS_ROCE_CONTEXT_HOP_NUM; +- caps->pbl_ba_pg_sz = 0; ++ caps->pbl_ba_pg_sz = 2; + caps->pbl_buf_pg_sz = 0; + caps->pbl_hop_num = HNS_ROCE_PBL_HOP_NUM; + caps->mtt_ba_pg_sz = 0; diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0031-RDMA-hns-RDMA-hns-Assign-rq-head-pointer-when-enable.patch b/debian/patches/bugfix/arm64/huawei-taishan/0031-RDMA-hns-RDMA-hns-Assign-rq-head-pointer-when-enable.patch new file mode 100644 index 000000000..4f9e5f6be --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0031-RDMA-hns-RDMA-hns-Assign-rq-head-pointer-when-enable.patch @@ -0,0 +1,63 @@ +From 07a7830061e657ce352e690dbe0a794ffb10d22e Mon Sep 17 00:00:00 2001 +From: Lijun Ou <oulijun@huawei.com> +Date: Sat, 12 Jan 2019 18:36:29 +0800 +Subject: [PATCH 31/31] RDMA/hns: RDMA/hns: Assign rq head pointer when enable + rq record db +Origin: https://git.kernel.org/linus/de77503a59403e7045c18c6bb0a10c245a99b648 + +When flush cqe, it needs to get the pointer of rq and sq from db address +space of user and update it into qp context by modified qp. if rq does not +exist, it will not get the value from db address space of user. + +Signed-off-by: Lijun Ou <oulijun@huawei.com> +Signed-off-by: Jason Gunthorpe <jgg@mellanox.com> +--- + drivers/infiniband/hw/hns/hns_roce_qp.c | 19 ++++++++++--------- + 1 file changed, 10 insertions(+), 9 deletions(-) + +Index: linux/drivers/infiniband/hw/hns/hns_roce_qp.c +=================================================================== +--- linux.orig/drivers/infiniband/hw/hns/hns_roce_qp.c ++++ linux/drivers/infiniband/hw/hns/hns_roce_qp.c +@@ -652,6 +652,10 @@ static int hns_roce_create_qp_common(str + dev_err(dev, "rq record doorbell map failed!\n"); + goto err_sq_dbmap; + } ++ ++ /* indicate kernel supports rq record db */ ++ resp.cap_flags |= HNS_ROCE_SUPPORT_RQ_RECORD_DB; ++ hr_qp->rdb_en = 1; + } + } else { + if (init_attr->create_flags & +@@ -760,16 +764,11 @@ static int hns_roce_create_qp_common(str + else + hr_qp->doorbell_qpn = cpu_to_le64(hr_qp->qpn); + +- if (ib_pd->uobject && (udata->outlen >= sizeof(resp)) && +- (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RECORD_DB)) { +- +- /* indicate kernel supports rq record db */ +- resp.cap_flags |= HNS_ROCE_SUPPORT_RQ_RECORD_DB; +- ret = ib_copy_to_udata(udata, &resp, sizeof(resp)); ++ if (udata) { ++ ret = ib_copy_to_udata(udata, &resp, ++ min(udata->outlen, sizeof(resp))); + if (ret) + goto err_qp; +- +- hr_qp->rdb_en = 1; + } + hr_qp->event = hns_roce_ib_qp_event; + +@@ -946,7 +945,9 @@ int hns_roce_modify_qp(struct ib_qp *ibq + (attr_mask & IB_QP_STATE) && new_state == IB_QPS_ERR) { + if (hr_qp->sdb_en == 1) { + hr_qp->sq.head = *(int *)(hr_qp->sdb.virt_addr); +- hr_qp->rq.head = *(int *)(hr_qp->rdb.virt_addr); ++ ++ if (hr_qp->rdb_en == 1) ++ hr_qp->rq.head = *(int *)(hr_qp->rdb.virt_addr); + } else { + dev_warn(dev, "flush cqe is not supported in userspace!\n"); + goto out; diff --git a/debian/patches/bugfix/arm64/huawei-taishan/0033-scsi-hisi_sas-fix-calls-to-dma_set_mask_and_coherent.patch b/debian/patches/bugfix/arm64/huawei-taishan/0033-scsi-hisi_sas-fix-calls-to-dma_set_mask_and_coherent.patch new file mode 100644 index 000000000..68374aee8 --- /dev/null +++ b/debian/patches/bugfix/arm64/huawei-taishan/0033-scsi-hisi_sas-fix-calls-to-dma_set_mask_and_coherent.patch @@ -0,0 +1,70 @@ +From badecc38102204f5297ad6ce1d7c7875e514c6f7 Mon Sep 17 00:00:00 2001 +From: Hannes Reinecke <hare@suse.de> +Date: Mon, 18 Feb 2019 08:34:25 +0100 +Subject: [PATCH] scsi: hisi_sas: fix calls to dma_set_mask_and_coherent() +Origin: https://git.kernel.org/linus/d9a00459effc30f6de2cdd887b64f15c6c54ae71 + +The change to use dma_set_mask_and_coherent() incorrectly made a second +call with the 32 bit DMA mask value when the call with the 64 bit DMA +mask value succeeded. + +[mkp: fixed commit message] + +Fixes: e4db40e7a1a2 ("scsi: hisi_sas: use dma_set_mask_and_coherent") +Cc: <stable@vger.kernel.org> +Suggested-by: Ewan D. Milne <emilne@redhat.com> +Signed-off-by: Hannes Reinecke <hare@suse.com> +Reviewed-by: Christoph Hellwig <hch@lst.de> +Signed-off-by: Hannes Reinecke <hare@suse.com> +Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 8 ++++++-- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 8 +++++--- + 2 files changed, 11 insertions(+), 5 deletions(-) + +Index: linux/drivers/scsi/hisi_sas/hisi_sas_main.c +=================================================================== +--- linux.orig/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ linux/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -2339,6 +2339,7 @@ static struct Scsi_Host *hisi_sas_shost_ + struct Scsi_Host *shost; + struct hisi_hba *hisi_hba; + struct device *dev = &pdev->dev; ++ int error; + + shost = scsi_host_alloc(hw->sht, sizeof(*hisi_hba)); + if (!shost) { +@@ -2359,8 +2360,11 @@ static struct Scsi_Host *hisi_sas_shost_ + if (hisi_sas_get_fw_info(hisi_hba) < 0) + goto err_out; + +- if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)) && +- dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) { ++ error = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); ++ if (error) ++ error = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); ++ ++ if (error) { + dev_err(dev, "No usable DMA addressing method\n"); + goto err_out; + } +Index: linux/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +=================================================================== +--- linux.orig/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ linux/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -2328,10 +2328,12 @@ hisi_sas_v3_probe(struct pci_dev *pdev, + if (rc) + goto err_out_disable_device; + +- if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) || +- dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) { ++ rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); ++ if (rc) ++ rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); ++ if (rc) { + dev_err(dev, "No usable DMA addressing method\n"); +- rc = -EIO; ++ rc = -ENODEV; + goto err_out_regions; + } + |