From 650fd322b5f4960d9ae638b40f86b5b578a51224 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Jun 24 2019 08:33:54 +0000 Subject: Merge branch 'SLE15-SP1' into SLE15-SP1_EMBARGO --- diff --git a/patches.drivers/scsi-megaraid_sas-Add-support-for-DEVICE_LIST-DCMD-i.patch b/patches.drivers/scsi-megaraid_sas-Add-support-for-DEVICE_LIST-DCMD-i.patch new file mode 100644 index 0000000..ce54b21 --- /dev/null +++ b/patches.drivers/scsi-megaraid_sas-Add-support-for-DEVICE_LIST-DCMD-i.patch @@ -0,0 +1,464 @@ +From: Shivasharan S +Date: Tue, 29 Jan 2019 01:38:14 -0800 +Subject: [PATCH] scsi: megaraid_sas: Add support for DEVICE_LIST DCMD in + driver +References: bsc#1136271 +Git-commit: f6fe57310811780d55d79e30da51db98677f1a90 +Patch-mainline: v5.1-rc1 + +This patch adds support for the new DEVICE_LIST DCMD. + +Driver currently sends two separate DCMDs for getting the list of PDs and +LDs that are exposed to host. The new DCMD provides a single interface to +get a list of both PDs and LDs that are exposed to the host. Based on the +list of target IDs that are returned by this DCMD, driver will add the +devices (PD/LD) to SML. Driver will check for FW support for this new DCMD +and based on the support will either send the new DCMD or will fall back to +the earlier method of sending two separate DCMDs for PD and LD list. + +Signed-off-by: Kashyap Desai +Signed-off-by: Shivasharan S +Signed-off-by: Martin K. Petersen +Signed-off-by: Hannes Reinecke +--- + drivers/scsi/megaraid/megaraid_sas.h | 49 +++++- + drivers/scsi/megaraid/megaraid_sas_base.c | 222 +++++++++++++++++++++++++--- + drivers/scsi/megaraid/megaraid_sas_fusion.c | 1 + + drivers/scsi/megaraid/megaraid_sas_fusion.h | 1 + + 4 files changed, 250 insertions(+), 23 deletions(-) + +diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h +index 16536c41f0c5..fe1173f02c54 100644 +--- a/drivers/scsi/megaraid/megaraid_sas.h ++++ b/drivers/scsi/megaraid/megaraid_sas.h +@@ -790,6 +790,37 @@ struct MR_LD_TARGETID_LIST { + u8 targetId[MAX_LOGICAL_DRIVES_EXT]; + }; + ++struct MR_HOST_DEVICE_LIST_ENTRY { ++ struct { ++ union { ++ struct { ++#if defined(__BIG_ENDIAN_BITFIELD) ++ u8 reserved:7; ++ u8 is_sys_pd:1; ++#else ++ u8 is_sys_pd:1; ++ u8 reserved:7; ++#endif ++ } bits; ++ u8 byte; ++ } u; ++ } flags; ++ u8 scsi_type; ++ __le16 target_id; ++ u8 reserved[2]; ++ __le64 sas_addr[2]; ++} __packed; ++ ++struct MR_HOST_DEVICE_LIST { ++ __le32 size; ++ __le32 count; ++ struct MR_HOST_DEVICE_LIST_ENTRY host_device_list[1]; ++} __packed; ++ ++#define HOST_DEVICE_LIST_SZ (sizeof(struct MR_HOST_DEVICE_LIST) + \ ++ (sizeof(struct MR_HOST_DEVICE_LIST_ENTRY) * \ ++ (MEGASAS_MAX_PD + MAX_LOGICAL_DRIVES_EXT - 1))) ++ + + /* + * SAS controller properties +@@ -870,13 +901,17 @@ struct megasas_ctrl_prop { + u8 viewSpace; + struct { + #if defined(__BIG_ENDIAN_BITFIELD) +- u16 reserved2:11; ++ u16 reserved3:9; ++ u16 enable_fw_dev_list:1; ++ u16 reserved2:1; + u16 enable_snap_dump:1; + u16 reserved1:4; + #else + u16 reserved1:4; + u16 enable_snap_dump:1; +- u16 reserved2:11; ++ u16 reserved2:1; ++ u16 enable_fw_dev_list:1; ++ u16 reserved3:9; + #endif + } on_off_properties2; + }; +@@ -1685,7 +1720,8 @@ union megasas_sgl_frame { + typedef union _MFI_CAPABILITIES { + struct { + #if defined(__BIG_ENDIAN_BITFIELD) +- u32 reserved:17; ++ u32 reserved:16; ++ u32 support_fw_exposed_dev_list:1; + u32 support_nvme_passthru:1; + u32 support_64bit_mode:1; + u32 support_pd_map_target_id:1; +@@ -1717,7 +1753,8 @@ typedef union _MFI_CAPABILITIES { + u32 support_pd_map_target_id:1; + u32 support_64bit_mode:1; + u32 support_nvme_passthru:1; +- u32 reserved:17; ++ u32 support_fw_exposed_dev_list:1; ++ u32 reserved:16; + #endif + } mfi_capabilities; + __le32 reg; +@@ -2202,6 +2239,9 @@ struct megasas_instance { + struct MR_LD_TARGETID_LIST *ld_targetid_list_buf; + dma_addr_t ld_targetid_list_buf_h; + ++ struct MR_HOST_DEVICE_LIST *host_device_list_buf; ++ dma_addr_t host_device_list_buf_h; ++ + struct MR_SNAPDUMP_PROPERTIES *snapdump_prop; + dma_addr_t snapdump_prop_h; + +@@ -2337,6 +2377,7 @@ struct megasas_instance { + u8 task_abort_tmo; + u8 max_reset_tmo; + u8 snapdump_wait_time; ++ u8 enable_fw_dev_list; + }; + struct MR_LD_VF_MAP { + u32 size; +diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c +index e6dd1aab9931..37e811d9c4c4 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_base.c ++++ b/drivers/scsi/megaraid/megaraid_sas_base.c +@@ -4640,6 +4640,123 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type) + return ret; + } + ++/** ++ * dcmd.opcode - MR_DCMD_CTRL_DEVICE_LIST_GET ++ * dcmd.mbox - reserved ++ * dcmd.sge IN - ptr to return MR_HOST_DEVICE_LIST structure ++ * Desc: This DCMD will return the combined device list ++ * Status: MFI_STAT_OK - List returned successfully ++ * MFI_STAT_INVALID_CMD - Firmware support for the feature has been ++ * disabled ++ * @instance: Adapter soft state ++ * @is_probe: Driver probe check ++ * Return: 0 if DCMD succeeded ++ * non-zero if failed ++ */ ++int ++megasas_host_device_list_query(struct megasas_instance *instance, ++ bool is_probe) ++{ ++ int ret, i, target_id; ++ struct megasas_cmd *cmd; ++ struct megasas_dcmd_frame *dcmd; ++ struct MR_HOST_DEVICE_LIST *ci; ++ u32 count; ++ dma_addr_t ci_h; ++ ++ ci = instance->host_device_list_buf; ++ ci_h = instance->host_device_list_buf_h; ++ ++ cmd = megasas_get_cmd(instance); ++ ++ if (!cmd) { ++ dev_warn(&instance->pdev->dev, ++ "%s: failed to get cmd\n", ++ __func__); ++ return -ENOMEM; ++ } ++ ++ dcmd = &cmd->frame->dcmd; ++ ++ memset(ci, 0, sizeof(*ci)); ++ memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); ++ ++ dcmd->mbox.b[0] = is_probe ? 0 : 1; ++ dcmd->cmd = MFI_CMD_DCMD; ++ dcmd->cmd_status = MFI_STAT_INVALID_STATUS; ++ dcmd->sge_count = 1; ++ dcmd->flags = MFI_FRAME_DIR_READ; ++ dcmd->timeout = 0; ++ dcmd->pad_0 = 0; ++ dcmd->data_xfer_len = cpu_to_le32(HOST_DEVICE_LIST_SZ); ++ dcmd->opcode = cpu_to_le32(MR_DCMD_CTRL_DEVICE_LIST_GET); ++ ++ megasas_set_dma_settings(instance, dcmd, ci_h, HOST_DEVICE_LIST_SZ); ++ ++ if (!instance->mask_interrupts) { ++ ret = megasas_issue_blocked_cmd(instance, cmd, ++ MFI_IO_TIMEOUT_SECS); ++ } else { ++ ret = megasas_issue_polled(instance, cmd); ++ cmd->flags |= DRV_DCMD_SKIP_REFIRE; ++ } ++ ++ switch (ret) { ++ case DCMD_SUCCESS: ++ /* Fill the internal pd_list and ld_ids array based on ++ * targetIds returned by FW ++ */ ++ count = le32_to_cpu(ci->count); ++ ++ memset(instance->local_pd_list, 0, ++ MEGASAS_MAX_PD * sizeof(struct megasas_pd_list)); ++ memset(instance->ld_ids, 0xff, MAX_LOGICAL_DRIVES_EXT); ++ for (i = 0; i < count; i++) { ++ target_id = le16_to_cpu(ci->host_device_list[i].target_id); ++ if (ci->host_device_list[i].flags.u.bits.is_sys_pd) { ++ instance->local_pd_list[target_id].tid = target_id; ++ instance->local_pd_list[target_id].driveType = ++ ci->host_device_list[i].scsi_type; ++ instance->local_pd_list[target_id].driveState = ++ MR_PD_STATE_SYSTEM; ++ } else { ++ instance->ld_ids[target_id] = target_id; ++ } ++ } ++ ++ memcpy(instance->pd_list, instance->local_pd_list, ++ sizeof(instance->pd_list)); ++ break; ++ ++ case DCMD_TIMEOUT: ++ switch (dcmd_timeout_ocr_possible(instance)) { ++ case INITIATE_OCR: ++ cmd->flags |= DRV_DCMD_SKIP_REFIRE; ++ megasas_reset_fusion(instance->host, ++ MFI_IO_TIMEOUT_OCR); ++ break; ++ case KILL_ADAPTER: ++ megaraid_sas_kill_hba(instance); ++ break; ++ case IGNORE_TIMEOUT: ++ dev_info(&instance->pdev->dev, "Ignore DCMD timeout: %s %d\n", ++ __func__, __LINE__); ++ break; ++ } ++ break; ++ case DCMD_FAILED: ++ dev_err(&instance->pdev->dev, ++ "%s: MR_DCMD_CTRL_DEVICE_LIST_GET failed\n", ++ __func__); ++ break; ++ } ++ ++ if (ret != DCMD_TIMEOUT) ++ megasas_return_cmd(instance, cmd); ++ ++ return ret; ++} ++ + /* + * megasas_update_ext_vd_details : Update details w.r.t Extended VD + * instance : Controller's instance +@@ -4867,6 +4984,9 @@ megasas_get_ctrl_info(struct megasas_instance *instance) + (ci->properties.on_off_properties2.enable_snap_dump ? + MEGASAS_DEFAULT_SNAP_DUMP_WAIT_TIME : 0); + ++ instance->enable_fw_dev_list = ++ ci->properties.on_off_properties2.enable_fw_dev_list; ++ + dev_info(&instance->pdev->dev, + "controller type\t: %s(%dMB)\n", + instance->is_imr ? "iMR" : "MR", +@@ -5331,6 +5451,8 @@ static void megasas_setup_reply_map(struct megasas_instance *instance) + * @return: Success or failure + * + * Issue DCMDs to Firmware to get the PD and LD list. ++ * Based on the FW support, driver sends the HOST_DEVICE_LIST or combination ++ * of PD_LIST/LD_LIST_QUERY DCMDs to get the device list. + */ + static + int megasas_get_device_list(struct megasas_instance *instance) +@@ -5339,15 +5461,20 @@ int megasas_get_device_list(struct megasas_instance *instance) + (MEGASAS_MAX_PD * sizeof(struct megasas_pd_list))); + memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); + +- if (megasas_get_pd_list(instance) < 0) { +- dev_err(&instance->pdev->dev, "failed to get PD list\n"); +- return FAILED; +- } ++ if (instance->enable_fw_dev_list) { ++ if (megasas_host_device_list_query(instance, true)) ++ return FAILED; ++ } else { ++ if (megasas_get_pd_list(instance) < 0) { ++ dev_err(&instance->pdev->dev, "failed to get PD list\n"); ++ return FAILED; ++ } + +- if (megasas_ld_list_query(instance, +- MR_LD_QUERY_TYPE_EXPOSED_TO_HOST)) { +- dev_err(&instance->pdev->dev, "failed to get LD list\n"); +- return FAILED; ++ if (megasas_ld_list_query(instance, ++ MR_LD_QUERY_TYPE_EXPOSED_TO_HOST)) { ++ dev_err(&instance->pdev->dev, "failed to get LD list\n"); ++ return FAILED; ++ } + } + + return SUCCESS; +@@ -6449,6 +6576,18 @@ int megasas_alloc_ctrl_dma_buffers(struct megasas_instance *instance) + if (!instance->snapdump_prop) + dev_err(&pdev->dev, + "Failed to allocate snapdump properties buffer\n"); ++ ++ instance->host_device_list_buf = dma_alloc_coherent(&pdev->dev, ++ HOST_DEVICE_LIST_SZ, ++ &instance->host_device_list_buf_h, ++ GFP_KERNEL); ++ ++ if (!instance->host_device_list_buf) { ++ dev_err(&pdev->dev, ++ "Failed to allocate targetid list buffer\n"); ++ return -ENOMEM; ++ } ++ + } + + instance->pd_list_buf = +@@ -6598,6 +6737,13 @@ void megasas_free_ctrl_dma_buffers(struct megasas_instance *instance) + sizeof(struct MR_SNAPDUMP_PROPERTIES), + instance->snapdump_prop, + instance->snapdump_prop_h); ++ ++ if (instance->host_device_list_buf) ++ dma_free_coherent(&pdev->dev, ++ HOST_DEVICE_LIST_SZ, ++ instance->host_device_list_buf, ++ instance->host_device_list_buf_h); ++ + } + + /* +@@ -6771,7 +6917,9 @@ static int megasas_probe_one(struct pci_dev *pdev, + /* + * Trigger SCSI to scan our drives + */ +- scsi_scan_host(host); ++ if (!instance->enable_fw_dev_list || ++ (instance->host_device_list_buf->count > 0)) ++ scsi_scan_host(host); + + /* + * Initiate AEN (Asynchronous Event Notification) +@@ -7900,6 +8048,8 @@ static inline void megasas_remove_scsi_device(struct scsi_device *sdev) + * @return: Success or failure + * + * Issue DCMDs to Firmware to update the internal device list in driver. ++ * Based on the FW support, driver sends the HOST_DEVICE_LIST or combination ++ * of PD_LIST/LD_LIST_QUERY DCMDs to get the device list. + */ + static + int megasas_update_device_list(struct megasas_instance *instance, +@@ -7907,22 +8057,28 @@ int megasas_update_device_list(struct megasas_instance *instance, + { + int dcmd_ret = DCMD_SUCCESS; + +- if (event_type & SCAN_PD_CHANNEL) { +- dcmd_ret = megasas_get_pd_list(instance); +- ++ if (instance->enable_fw_dev_list) { ++ dcmd_ret = megasas_host_device_list_query(instance, false); + if (dcmd_ret != DCMD_SUCCESS) + goto out; +- } ++ } else { ++ if (event_type & SCAN_PD_CHANNEL) { ++ dcmd_ret = megasas_get_pd_list(instance); + +- if (event_type & SCAN_VD_CHANNEL) { +- if (!instance->requestorId || +- (instance->requestorId && +- megasas_get_ld_vf_affiliation(instance, 0))) { +- dcmd_ret = megasas_ld_list_query(instance, +- MR_LD_QUERY_TYPE_EXPOSED_TO_HOST); + if (dcmd_ret != DCMD_SUCCESS) + goto out; + } ++ ++ if (event_type & SCAN_VD_CHANNEL) { ++ if (!instance->requestorId || ++ (instance->requestorId && ++ megasas_get_ld_vf_affiliation(instance, 0))) { ++ dcmd_ret = megasas_ld_list_query(instance, ++ MR_LD_QUERY_TYPE_EXPOSED_TO_HOST); ++ if (dcmd_ret != DCMD_SUCCESS) ++ goto out; ++ } ++ } + } + + out: +@@ -7943,11 +8099,39 @@ void megasas_add_remove_devices(struct megasas_instance *instance, + int i, j; + u16 pd_index = 0; + u16 ld_index = 0; ++ u16 channel = 0, id = 0; + struct Scsi_Host *host; + struct scsi_device *sdev1; ++ struct MR_HOST_DEVICE_LIST *targetid_list = NULL; ++ struct MR_HOST_DEVICE_LIST_ENTRY *targetid_entry = NULL; + + host = instance->host; + ++ if (instance->enable_fw_dev_list) { ++ targetid_list = instance->host_device_list_buf; ++ for (i = 0; i < targetid_list->count; i++) { ++ targetid_entry = &targetid_list->host_device_list[i]; ++ if (targetid_entry->flags.u.bits.is_sys_pd) { ++ channel = le16_to_cpu(targetid_entry->target_id) / ++ MEGASAS_MAX_DEV_PER_CHANNEL; ++ id = le16_to_cpu(targetid_entry->target_id) % ++ MEGASAS_MAX_DEV_PER_CHANNEL; ++ } else { ++ channel = MEGASAS_MAX_PD_CHANNELS + ++ (le16_to_cpu(targetid_entry->target_id) / ++ MEGASAS_MAX_DEV_PER_CHANNEL); ++ id = le16_to_cpu(targetid_entry->target_id) % ++ MEGASAS_MAX_DEV_PER_CHANNEL; ++ } ++ sdev1 = scsi_device_lookup(host, channel, id, 0); ++ if (!sdev1) { ++ scsi_add_device(host, channel, id, 0); ++ } else { ++ scsi_device_put(sdev1); ++ } ++ } ++ } ++ + if (scan_type & SCAN_PD_CHANNEL) { + for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) { + for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) { +diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c +index 3cecee38b192..4e912e01bb89 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c ++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c +@@ -1074,6 +1074,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) + drv_ops->mfi_capabilities.support_qd_throttling = 1; + drv_ops->mfi_capabilities.support_pd_map_target_id = 1; + drv_ops->mfi_capabilities.support_nvme_passthru = 1; ++ drv_ops->mfi_capabilities.support_fw_exposed_dev_list = 1; + + if (instance->consistent_mask_64bit) + drv_ops->mfi_capabilities.support_64bit_mode = 1; +diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h +index ca73c50fe723..1481bf029490 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_fusion.h ++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h +@@ -724,6 +724,7 @@ struct MPI2_IOC_INIT_REQUEST { + #define MR_DCMD_LD_VF_MAP_GET_ALL_LDS_111 0x03200200 + #define MR_DCMD_LD_VF_MAP_GET_ALL_LDS 0x03150200 + #define MR_DCMD_CTRL_SNAPDUMP_GET_PROPERTIES 0x01200100 ++#define MR_DCMD_CTRL_DEVICE_LIST_GET 0x01190600 + + struct MR_DEV_HANDLE_INFO { + __le16 curDevHdl; +-- +2.16.4 + diff --git a/patches.drivers/scsi-megaraid_sas-Retry-reads-of-outbound_intr_statu.patch b/patches.drivers/scsi-megaraid_sas-Retry-reads-of-outbound_intr_statu.patch new file mode 100644 index 0000000..48dc023 --- /dev/null +++ b/patches.drivers/scsi-megaraid_sas-Retry-reads-of-outbound_intr_statu.patch @@ -0,0 +1,37 @@ +From: Shivasharan S +Date: Wed, 9 Jan 2019 05:08:37 -0800 +Subject: [PATCH] scsi: megaraid_sas: Retry reads of outbound_intr_status reg +References: bsc#1136271 +Git-commit: c65bfc8163696dd171e081488b0321beb630b708 +Patch-mainline: v5.0-rc3 + +commit 272652fcbf1a ("scsi: megaraid_sas: add retry logic in megasas_readl") +missed changing readl to megasas_readl in megasas_clear_intr_fusion(). For +Aero controllers, reads of outbound_intr_status register needs to be +retried. + +Reported-by: Tomas Henzl +Signed-off-by: Shivasharan S +Signed-off-by: Martin K. Petersen +Signed-off-by: Hannes Reinecke +--- + drivers/scsi/megaraid/megaraid_sas_fusion.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c +index 91e673212582..3cecee38b192 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c ++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c +@@ -175,7 +175,8 @@ megasas_clear_intr_fusion(struct megasas_instance *instance) + /* + * Check if it is our interrupt + */ +- status = readl(®s->outbound_intr_status); ++ status = megasas_readl(instance, ++ ®s->outbound_intr_status); + + if (status & 1) { + writel(status, ®s->outbound_intr_status); +-- +2.16.4 + diff --git a/patches.drivers/scsi-megaraid_sas-Rework-code-to-get-PD-and-LD-list.patch b/patches.drivers/scsi-megaraid_sas-Rework-code-to-get-PD-and-LD-list.patch new file mode 100644 index 0000000..9a7be0b --- /dev/null +++ b/patches.drivers/scsi-megaraid_sas-Rework-code-to-get-PD-and-LD-list.patch @@ -0,0 +1,93 @@ +From: Shivasharan S +Date: Tue, 29 Jan 2019 01:38:12 -0800 +Subject: [PATCH] scsi: megaraid_sas: Rework code to get PD and LD list +References: bsc#1136271 +Git-commit: daa0681118c9f4fc4afffb3757a1e085fba2d069 +Patch-mainline: v5.1-rc1 + +During FW init, combine the code to get the PD and LD list from FW into a +single function. This patch is in preparation for adding support for +HOST_DEVICE_LIST DCMD. + +Signed-off-by: Shivasharan S +Signed-off-by: Martin K. Petersen +Signed-off-by: Hannes Reinecke +--- + drivers/scsi/megaraid/megaraid_sas_base.c | 44 ++++++++++++++++++++++--------- + 1 file changed, 31 insertions(+), 13 deletions(-) + +diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c +index 86978cd8f733..35e40d475859 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_base.c ++++ b/drivers/scsi/megaraid/megaraid_sas_base.c +@@ -5325,6 +5325,33 @@ static void megasas_setup_reply_map(struct megasas_instance *instance) + instance->reply_map[cpu] = cpu % instance->msix_vectors; + } + ++/** ++ * megasas_get_device_list - Get the PD and LD device list from FW. ++ * @instance: Adapter soft state ++ * @return: Success or failure ++ * ++ * Issue DCMDs to Firmware to get the PD and LD list. ++ */ ++static ++int megasas_get_device_list(struct megasas_instance *instance) ++{ ++ memset(instance->pd_list, 0, ++ (MEGASAS_MAX_PD * sizeof(struct megasas_pd_list))); ++ memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); ++ ++ if (megasas_get_pd_list(instance) < 0) { ++ dev_err(&instance->pdev->dev, "failed to get PD list\n"); ++ return FAILED; ++ } ++ ++ if (megasas_ld_list_query(instance, ++ MR_LD_QUERY_TYPE_EXPOSED_TO_HOST)) { ++ dev_err(&instance->pdev->dev, "failed to get LD list\n"); ++ return FAILED; ++ } ++ ++ return SUCCESS; ++} + /** + * megasas_init_fw - Initializes the FW + * @instance: Adapter soft state +@@ -5577,18 +5604,13 @@ static int megasas_init_fw(struct megasas_instance *instance) + + megasas_setup_jbod_map(instance); + +- /** for passthrough +- * the following function will get the PD LIST. +- */ +- memset(instance->pd_list, 0, +- (MEGASAS_MAX_PD * sizeof(struct megasas_pd_list))); +- if (megasas_get_pd_list(instance) < 0) { +- dev_err(&instance->pdev->dev, "failed to get PD list\n"); ++ if (megasas_get_device_list(instance) != SUCCESS) { ++ dev_err(&instance->pdev->dev, ++ "%s: megasas_get_device_list failed\n", ++ __func__); + goto fail_get_ld_pd_list; + } + +- memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); +- + /* stream detection initialization */ + if (instance->adapter_type >= VENTURA_SERIES) { + fusion->stream_detect_by_ld = +@@ -5618,10 +5640,6 @@ static int megasas_init_fw(struct megasas_instance *instance) + } + } + +- if (megasas_ld_list_query(instance, +- MR_LD_QUERY_TYPE_EXPOSED_TO_HOST)) +- goto fail_get_ld_pd_list; +- + /* + * Compute the max allowed sectors per IO: The controller info has two + * limits on max sectors. Driver should use the minimum of these two. +-- +2.16.4 + diff --git a/patches.drivers/scsi-megaraid_sas-Rework-device-add-code-in-AEN-path.patch b/patches.drivers/scsi-megaraid_sas-Rework-device-add-code-in-AEN-path.patch new file mode 100644 index 0000000..5ea1e13 --- /dev/null +++ b/patches.drivers/scsi-megaraid_sas-Rework-device-add-code-in-AEN-path.patch @@ -0,0 +1,254 @@ +From: Shivasharan S +Date: Tue, 29 Jan 2019 01:38:13 -0800 +Subject: [PATCH] scsi: megaraid_sas: Rework device add code in AEN path +References: bsc#1136271 +Git-commit: 44abbaf64b5d8feae04c9cb5bdc60d6c22da3035 +Patch-mainline: v5.1-rc1 + +In preparation of adding support for the DEVICE_LIST DCMD, this patch +refactors the code in the AEN event handling path. Add new function to +update the PD and LD list in driver. Move the code to scan PD and VD +channels into separate function. + +Signed-off-by: Shivasharan S +Signed-off-by: Martin K. Petersen +Signed-off-by: Hannes Reinecke +--- + drivers/scsi/megaraid/megaraid_sas_base.c | 173 ++++++++++++++++++------------ + 1 file changed, 107 insertions(+), 66 deletions(-) + +diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c +index 35e40d475859..e6dd1aab9931 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_base.c ++++ b/drivers/scsi/megaraid/megaraid_sas_base.c +@@ -7891,6 +7891,103 @@ static inline void megasas_remove_scsi_device(struct scsi_device *sdev) + scsi_device_put(sdev); + } + ++/** ++ * megasas_update_device_list - Update the PD and LD device list from FW ++ * after an AEN event notification ++ * @instance: Adapter soft state ++ * @event_type: Indicates type of event (PD or LD event) ++ * ++ * @return: Success or failure ++ * ++ * Issue DCMDs to Firmware to update the internal device list in driver. ++ */ ++static ++int megasas_update_device_list(struct megasas_instance *instance, ++ int event_type) ++{ ++ int dcmd_ret = DCMD_SUCCESS; ++ ++ if (event_type & SCAN_PD_CHANNEL) { ++ dcmd_ret = megasas_get_pd_list(instance); ++ ++ if (dcmd_ret != DCMD_SUCCESS) ++ goto out; ++ } ++ ++ if (event_type & SCAN_VD_CHANNEL) { ++ if (!instance->requestorId || ++ (instance->requestorId && ++ megasas_get_ld_vf_affiliation(instance, 0))) { ++ dcmd_ret = megasas_ld_list_query(instance, ++ MR_LD_QUERY_TYPE_EXPOSED_TO_HOST); ++ if (dcmd_ret != DCMD_SUCCESS) ++ goto out; ++ } ++ } ++ ++out: ++ return dcmd_ret; ++} ++ ++/** ++ * megasas_add_remove_devices - Add/remove devices to SCSI mid-layer ++ * after an AEN event notification ++ * @instance: Adapter soft state ++ * @scan_type: Indicates type of devices (PD/LD) to add ++ * @return void ++ */ ++static ++void megasas_add_remove_devices(struct megasas_instance *instance, ++ int scan_type) ++{ ++ int i, j; ++ u16 pd_index = 0; ++ u16 ld_index = 0; ++ struct Scsi_Host *host; ++ struct scsi_device *sdev1; ++ ++ host = instance->host; ++ ++ if (scan_type & SCAN_PD_CHANNEL) { ++ for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) { ++ for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) { ++ pd_index = i * MEGASAS_MAX_DEV_PER_CHANNEL + j; ++ sdev1 = scsi_device_lookup(host, i, j, 0); ++ if (instance->pd_list[pd_index].driveState == ++ MR_PD_STATE_SYSTEM) { ++ if (!sdev1) ++ scsi_add_device(host, i, j, 0); ++ else ++ scsi_device_put(sdev1); ++ } else { ++ if (sdev1) ++ megasas_remove_scsi_device(sdev1); ++ } ++ } ++ } ++ } ++ ++ if (scan_type & SCAN_VD_CHANNEL) { ++ for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { ++ for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) { ++ ld_index = (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; ++ sdev1 = scsi_device_lookup(host, ++ MEGASAS_MAX_PD_CHANNELS + i, j, 0); ++ if (instance->ld_ids[ld_index] != 0xff) { ++ if (!sdev1) ++ scsi_add_device(host, MEGASAS_MAX_PD_CHANNELS + i, j, 0); ++ else ++ scsi_device_put(sdev1); ++ } else { ++ if (sdev1) ++ megasas_remove_scsi_device(sdev1); ++ } ++ } ++ } ++ } ++ ++} ++ + static void + megasas_aen_polling(struct work_struct *work) + { +@@ -7898,11 +7995,7 @@ megasas_aen_polling(struct work_struct *work) + container_of(work, struct megasas_aen_event, hotplug_work.work); + struct megasas_instance *instance = ev->instance; + union megasas_evt_class_locale class_locale; +- struct Scsi_Host *host; +- struct scsi_device *sdev1; +- u16 pd_index = 0; +- u16 ld_index = 0; +- int i, j, doscan = 0; ++ int event_type = 0; + u32 seq_num, wait_time = MEGASAS_RESET_WAIT_TIME; + int error; + u8 dcmd_ret = DCMD_SUCCESS; +@@ -7921,7 +8014,6 @@ megasas_aen_polling(struct work_struct *work) + mutex_lock(&instance->reset_mutex); + + instance->ev = NULL; +- host = instance->host; + if (instance->evt_detail) { + megasas_decode_evt(instance); + +@@ -7929,40 +8021,20 @@ megasas_aen_polling(struct work_struct *work) + + case MR_EVT_PD_INSERTED: + case MR_EVT_PD_REMOVED: +- dcmd_ret = megasas_get_pd_list(instance); +- if (dcmd_ret == DCMD_SUCCESS) +- doscan = SCAN_PD_CHANNEL; ++ event_type = SCAN_PD_CHANNEL; + break; + + case MR_EVT_LD_OFFLINE: + case MR_EVT_CFG_CLEARED: + case MR_EVT_LD_DELETED: + case MR_EVT_LD_CREATED: +- if (!instance->requestorId || +- (instance->requestorId && megasas_get_ld_vf_affiliation(instance, 0))) +- dcmd_ret = megasas_ld_list_query(instance, MR_LD_QUERY_TYPE_EXPOSED_TO_HOST); +- +- if (dcmd_ret == DCMD_SUCCESS) +- doscan = SCAN_VD_CHANNEL; +- ++ event_type = SCAN_VD_CHANNEL; + break; + + case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED: + case MR_EVT_FOREIGN_CFG_IMPORTED: + case MR_EVT_LD_STATE_CHANGE: +- dcmd_ret = megasas_get_pd_list(instance); +- +- if (dcmd_ret != DCMD_SUCCESS) +- break; +- +- if (!instance->requestorId || +- (instance->requestorId && megasas_get_ld_vf_affiliation(instance, 0))) +- dcmd_ret = megasas_ld_list_query(instance, MR_LD_QUERY_TYPE_EXPOSED_TO_HOST); +- +- if (dcmd_ret != DCMD_SUCCESS) +- break; +- +- doscan = SCAN_VD_CHANNEL | SCAN_PD_CHANNEL; ++ event_type = SCAN_PD_CHANNEL | SCAN_VD_CHANNEL; + dev_info(&instance->pdev->dev, "scanning for scsi%d...\n", + instance->host->host_no); + break; +@@ -7978,7 +8050,7 @@ megasas_aen_polling(struct work_struct *work) + } + break; + default: +- doscan = 0; ++ event_type = 0; + break; + } + } else { +@@ -7988,44 +8060,13 @@ megasas_aen_polling(struct work_struct *work) + return; + } + +- mutex_unlock(&instance->reset_mutex); ++ if (event_type) ++ dcmd_ret = megasas_update_device_list(instance, event_type); + +- if (doscan & SCAN_PD_CHANNEL) { +- for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) { +- for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) { +- pd_index = i*MEGASAS_MAX_DEV_PER_CHANNEL + j; +- sdev1 = scsi_device_lookup(host, i, j, 0); +- if (instance->pd_list[pd_index].driveState == +- MR_PD_STATE_SYSTEM) { +- if (!sdev1) +- scsi_add_device(host, i, j, 0); +- else +- scsi_device_put(sdev1); +- } else { +- if (sdev1) +- megasas_remove_scsi_device(sdev1); +- } +- } +- } +- } ++ mutex_unlock(&instance->reset_mutex); + +- if (doscan & SCAN_VD_CHANNEL) { +- for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { +- for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) { +- ld_index = (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; +- sdev1 = scsi_device_lookup(host, MEGASAS_MAX_PD_CHANNELS + i, j, 0); +- if (instance->ld_ids[ld_index] != 0xff) { +- if (!sdev1) +- scsi_add_device(host, MEGASAS_MAX_PD_CHANNELS + i, j, 0); +- else +- scsi_device_put(sdev1); +- } else { +- if (sdev1) +- megasas_remove_scsi_device(sdev1); +- } +- } +- } +- } ++ if (event_type && dcmd_ret == DCMD_SUCCESS) ++ megasas_add_remove_devices(instance, event_type); + + if (dcmd_ret == DCMD_SUCCESS) + seq_num = le32_to_cpu(instance->evt_detail->seq_num) + 1; +-- +2.16.4 + diff --git a/patches.drivers/scsi-megaraid_sas-Update-structures-for-HOST_DEVICE_.patch b/patches.drivers/scsi-megaraid_sas-Update-structures-for-HOST_DEVICE_.patch new file mode 100644 index 0000000..c3ec63f --- /dev/null +++ b/patches.drivers/scsi-megaraid_sas-Update-structures-for-HOST_DEVICE_.patch @@ -0,0 +1,42 @@ +From: Shivasharan S +Date: Fri, 8 Feb 2019 00:22:46 -0800 +Subject: [PATCH] scsi: megaraid_sas: Update structures for HOST_DEVICE_LIST + DCMD +References: bsc#1136271 +Git-commit: a3742d68484083ce55de8fec492be2db2fff2cfa +Patch-mainline: v5.1-rc1 + +Add padding to make the structure variables in MR_HOST_DEVICE_LIST_ENTRY +64-bit aligned. Also, add reserved fields to MR_HOST_DEVICE_LIST for +future firmware usage. + +Signed-off-by: Shivasharan S +Signed-off-by: Martin K. Petersen +Signed-off-by: Hannes Reinecke +--- + drivers/scsi/megaraid/megaraid_sas.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h +index fe1173f02c54..eb48ca17dca0 100644 +--- a/drivers/scsi/megaraid/megaraid_sas.h ++++ b/drivers/scsi/megaraid/megaraid_sas.h +@@ -807,13 +807,14 @@ struct MR_HOST_DEVICE_LIST_ENTRY { + } flags; + u8 scsi_type; + __le16 target_id; +- u8 reserved[2]; ++ u8 reserved[4]; + __le64 sas_addr[2]; + } __packed; + + struct MR_HOST_DEVICE_LIST { + __le32 size; + __le32 count; ++ __le32 reserved[2]; + struct MR_HOST_DEVICE_LIST_ENTRY host_device_list[1]; + } __packed; + +-- +2.16.4 + diff --git a/patches.drivers/scsi-megaraid_sas-correct-an-info-message.patch b/patches.drivers/scsi-megaraid_sas-correct-an-info-message.patch new file mode 100644 index 0000000..bbe1c04 --- /dev/null +++ b/patches.drivers/scsi-megaraid_sas-correct-an-info-message.patch @@ -0,0 +1,33 @@ +From: Tomas Henzl +Date: Wed, 2 Jan 2019 16:07:25 +0100 +Subject: [PATCH] scsi: megaraid_sas: correct an info message +References: bsc#1136271 +Git-commit: d1f38d995e984db36449661fcbad1649c21883e7 +Patch-Mainline: v5.0-rc3 + +This was apparently forgotten in +894169db1 ("scsi: megaraid_sas: Use 63-bit DMA addressing"). + +Signed-off-by: Tomas Henzl +Signed-off-by: Martin K. Petersen +Signed-off-by: Hannes Reinecke +--- + drivers/scsi/megaraid/megaraid_sas_base.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c +index 889cb9d3afe3..86978cd8f733 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_base.c ++++ b/drivers/scsi/megaraid/megaraid_sas_base.c +@@ -6243,7 +6243,7 @@ megasas_set_dma_mask(struct megasas_instance *instance) + instance->consistent_mask_64bit = true; + + dev_info(&pdev->dev, "%s bit DMA mask and %s bit consistent mask\n", +- ((*pdev->dev.dma_mask == DMA_BIT_MASK(64)) ? "63" : "32"), ++ ((*pdev->dev.dma_mask == DMA_BIT_MASK(63)) ? "63" : "32"), + (instance->consistent_mask_64bit ? "63" : "32")); + + return 0; +-- +2.16.4 + diff --git a/patches.drivers/scsi-megaraid_sas-driver-version-update-to-07.707.51.00.patch b/patches.drivers/scsi-megaraid_sas-driver-version-update-to-07.707.51.00.patch new file mode 100644 index 0000000..ba81f6f --- /dev/null +++ b/patches.drivers/scsi-megaraid_sas-driver-version-update-to-07.707.51.00.patch @@ -0,0 +1,32 @@ +From: Shivasharan S +Date: Fri, 8 Feb 2019 00:22:47 -0800 +Subject: [PATCH] scsi: megaraid_sas: driver version update +References: bsc#1136271 +Git-commit: 0de05405122406bcada51cdfd8531dc279deb8b2 +Patch-mainline: v5.1-rc1 + +Signed-off-by: Shivasharan S +Signed-off-by: Martin K. Petersen +Signed-off-by: Hannes Reinecke +--- + drivers/scsi/megaraid/megaraid_sas.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h +index eb48ca17dca0..6fd57f7f0b1e 100644 +--- a/drivers/scsi/megaraid/megaraid_sas.h ++++ b/drivers/scsi/megaraid/megaraid_sas.h +@@ -33,8 +33,8 @@ + /* + * MegaRAID SAS Driver meta data + */ +-#define MEGASAS_VERSION "07.707.50.00-rc1" +-#define MEGASAS_RELDATE "December 18, 2018" ++#define MEGASAS_VERSION "07.707.51.00-rc1" ++#define MEGASAS_RELDATE "February 7, 2019" + + /* + * Device IDs +-- +2.16.4 + diff --git a/patches.fixes/s390-dasd-fix-using-offset-into-zero-size-array-error b/patches.fixes/s390-dasd-fix-using-offset-into-zero-size-array-error new file mode 100644 index 0000000..1e59cbb --- /dev/null +++ b/patches.fixes/s390-dasd-fix-using-offset-into-zero-size-array-error @@ -0,0 +1,91 @@ +From: Stefan Haberland +Date: Wed, 21 Nov 2018 12:39:47 +0100 +Subject: s390/dasd: fix using offset into zero size array error +Git-commit: 4a8ef6999bce998fa5813023a9a6b56eea329dba +Patch-mainline: v5.0-rc7 +References: bsc#1051510 + +Dan Carpenter reported the following: + +The patch 52898025cf7d: "[S390] dasd: security and PSF update patch +for EMC CKD ioctl" from Mar 8, 2010, leads to the following static +checker warning: + + drivers/s390/block/dasd_eckd.c:4486 dasd_symm_io() + error: using offset into zero size array 'psf_data[]' + +drivers/s390/block/dasd_eckd.c + 4458 /* Copy parms from caller */ + 4459 rc = -EFAULT; + 4460 if (copy_from_user(&usrparm, argp, sizeof(usrparm))) + ^^^^^^^ +The user can specify any "usrparm.psf_data_len". They choose zero by +mistake. + + 4461 goto out; + 4462 if (is_compat_task()) { + 4463 /* Make sure pointers are sane even on 31 bit. */ + 4464 rc = -EINVAL; + 4465 if ((usrparm.psf_data >> 32) != 0) + 4466 goto out; + 4467 if ((usrparm.rssd_result >> 32) != 0) + 4468 goto out; + 4469 usrparm.psf_data &= 0x7fffffffULL; + 4470 usrparm.rssd_result &= 0x7fffffffULL; + 4471 } + 4472 /* alloc I/O data area */ + 4473 psf_data = kzalloc(usrparm.psf_data_len, GFP_KERNEL + | GFP_DMA); + 4474 rssd_result = kzalloc(usrparm.rssd_result_len, GFP_KERNEL + | GFP_DMA); + 4475 if (!psf_data || !rssd_result) { + +kzalloc() returns a ZERO_SIZE_PTR (0x16). + + 4476 rc = -ENOMEM; + 4477 goto out_free; + 4478 } + 4479 + 4480 /* get syscall header from user space */ + 4481 rc = -EFAULT; + 4482 if (copy_from_user(psf_data, + 4483 (void __user *)(unsigned long) + usrparm.psf_data, + 4484 usrparm.psf_data_len)) + +That all works great. + + 4485 goto out_free; + 4486 psf0 = psf_data[0]; + 4487 psf1 = psf_data[1]; + +But now we're assuming that "->psf_data_len" was at least 2 bytes. + +Fix this by checking the user specified length psf_data_len. + +Fixes: 52898025cf7d ("[S390] dasd: security and PSF update patch for EMC CKD ioctl") +Reported-by: Dan Carpenter +Signed-off-by: Stefan Haberland +Signed-off-by: Martin Schwidefsky +Acked-by: Petr Tesarik +--- + drivers/s390/block/dasd_eckd.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/s390/block/dasd_eckd.c ++++ b/drivers/s390/block/dasd_eckd.c +@@ -4522,6 +4522,14 @@ static int dasd_symm_io(struct dasd_devi + usrparm.psf_data &= 0x7fffffffULL; + usrparm.rssd_result &= 0x7fffffffULL; + } ++ /* at least 2 bytes are accessed and should be allocated */ ++ if (usrparm.psf_data_len < 2) { ++ DBF_DEV_EVENT(DBF_WARNING, device, ++ "Symmetrix ioctl invalid data length %d", ++ usrparm.psf_data_len); ++ rc = -EINVAL; ++ goto out; ++ } + /* alloc I/O data area */ + psf_data = kzalloc(usrparm.psf_data_len, GFP_KERNEL | GFP_DMA); + rssd_result = kzalloc(usrparm.rssd_result_len, GFP_KERNEL | GFP_DMA); diff --git a/patches.fixes/s390-qeth-fix-race-when-initializing-the-ip-address-table b/patches.fixes/s390-qeth-fix-race-when-initializing-the-ip-address-table new file mode 100644 index 0000000..5605f68 --- /dev/null +++ b/patches.fixes/s390-qeth-fix-race-when-initializing-the-ip-address-table @@ -0,0 +1,37 @@ +From: Julian Wiedmann +Date: Mon, 18 Mar 2019 16:40:55 +0100 +Subject: s390/qeth: fix race when initializing the IP address table +Git-commit: 7221b727f0079a32aca91f657141e1de564d4b97 +Patch-mainline: v5.1-rc3 +References: bsc#1051510 + +The ucast IP table is utilized by some of the L3-specific sysfs attributes +that qeth_l3_create_device_attributes() provides. So initialize the table +_before_ registering the attributes. + +Fixes: ebccc7397e4a ("s390/qeth: add missing hash table initializations") +Signed-off-by: Julian Wiedmann +Signed-off-by: David S. Miller +Acked-by: Petr Tesarik +--- + drivers/s390/net/qeth_l3_main.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/s390/net/qeth_l3_main.c ++++ b/drivers/s390/net/qeth_l3_main.c +@@ -3002,12 +3002,14 @@ static int qeth_l3_probe_device(struct c + struct qeth_card *card = dev_get_drvdata(&gdev->dev); + int rc; + ++ hash_init(card->ip_htable); ++ + if (gdev->dev.type == &qeth_generic_devtype) { + rc = qeth_l3_create_device_attributes(&gdev->dev); + if (rc) + return rc; + } +- hash_init(card->ip_htable); ++ + hash_init(card->ip_mc_htable); + card->info.hwtrap = 0; + return 0; diff --git a/patches.fixes/s390-qeth-fix-vlan-attribute-in-bridge_hostnotify-udev-event b/patches.fixes/s390-qeth-fix-vlan-attribute-in-bridge_hostnotify-udev-event new file mode 100644 index 0000000..0d2c825 --- /dev/null +++ b/patches.fixes/s390-qeth-fix-vlan-attribute-in-bridge_hostnotify-udev-event @@ -0,0 +1,46 @@ +From: Alexandra Winter +Date: Wed, 5 Jun 2019 13:48:50 +0200 +Subject: s390/qeth: fix VLAN attribute in bridge_hostnotify udev event +Git-commit: 335726195e460cb6b3f795b695bfd31f0ea70ef0 +Patch-mainline: v5.2-rc1 +References: bsc#1051510 + +Enabling sysfs attribute bridge_hostnotify triggers a series of udev events +for the MAC addresses of all currently connected peers. In case no VLAN is +set for a peer, the device reports the corresponding MAC addresses with +VLAN ID 4096. This currently results in attribute VLAN=4096 for all +non-VLAN interfaces in the initial series of events after host-notify is +enabled. + +Instead, no VLAN attribute should be reported in the udev event for +non-VLAN interfaces. + +Only the initial events face this issue. For dynamic changes that are +reported later, the device uses a validity flag. + +This also changes the code so that it now sets the VLAN attribute for +MAC addresses with VID 0. On Linux, no qeth interface will ever be +registered with VID 0: Linux kernel registers VID 0 on all network +interfaces initially, but qeth will drop .ndo_vlan_rx_add_vid for VID 0. +Peers with other OSs could register MACs with VID 0. + +Fixes: 9f48b9db9a22 ("qeth: bridgeport support - address notifications") +Signed-off-by: Alexandra Winter +Signed-off-by: Julian Wiedmann +Signed-off-by: David S. Miller +Acked-by: Petr Tesarik +--- + drivers/s390/net/qeth_l2_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/s390/net/qeth_l2_main.c ++++ b/drivers/s390/net/qeth_l2_main.c +@@ -2053,7 +2053,7 @@ static void qeth_bridgeport_an_set_cb(vo + + l2entry = (struct qdio_brinfo_entry_l2 *)entry; + code = IPA_ADDR_CHANGE_CODE_MACADDR; +- if (l2entry->addr_lnid.lnid) ++ if (l2entry->addr_lnid.lnid < VLAN_N_VID) + code |= IPA_ADDR_CHANGE_CODE_VLANID; + qeth_bridge_emit_host_event(card, anev_reg_unreg, code, + (struct net_if_token *)&l2entry->nit, diff --git a/patches.fixes/s390-setup-fix-early-warning-messages b/patches.fixes/s390-setup-fix-early-warning-messages new file mode 100644 index 0000000..c75b1b3 --- /dev/null +++ b/patches.fixes/s390-setup-fix-early-warning-messages @@ -0,0 +1,104 @@ +From: Martin Schwidefsky +Date: Thu, 14 Feb 2019 15:40:56 +0100 +Subject: s390/setup: fix early warning messages +Git-commit: 8727638426b0aea59d7f904ad8ddf483f9234f88 +Patch-mainline: v5.1-rc1 +References: bsc#1051510 + +The setup_lowcore() function creates a new prefix page for the boot CPU. +The PSW mask for the system_call, external interrupt, i/o interrupt and +the program check handler have the DAT bit set in this new prefix page. + +At the time setup_lowcore is called the system still runs without virtual +address translation, the paging_init() function creates the kernel page +table and loads the CR13 with the kernel ASCE. + +Any code between setup_lowcore() and the end of paging_init() that has +a BUG or WARN statement will create a program check that can not be +handled correctly as there is no kernel page table yet. + +To allow early WARN statements initially setup the lowcore with DAT off +and set the DAT bit only after paging_init() has completed. + +Cc: stable@vger.kernel.org +Signed-off-by: Martin Schwidefsky +Acked-by: Petr Tesarik +--- + arch/s390/kernel/setup.c | 32 +++++++++++++++++++++++--------- + 1 file changed, 23 insertions(+), 9 deletions(-) + +--- a/arch/s390/kernel/setup.c ++++ b/arch/s390/kernel/setup.c +@@ -300,7 +300,7 @@ early_param("vmalloc", parse_vmalloc); + + void *restart_stack __section(.data); + +-static void __init setup_lowcore(void) ++static void __init setup_lowcore_dat_off(void) + { + struct lowcore *lc; + +@@ -311,19 +311,16 @@ static void __init setup_lowcore(void) + lc = memblock_virt_alloc_low(sizeof(*lc), sizeof(*lc)); + lc->restart_psw.mask = PSW_KERNEL_BITS; + lc->restart_psw.addr = (unsigned long) restart_int_handler; +- lc->external_new_psw.mask = PSW_KERNEL_BITS | +- PSW_MASK_DAT | PSW_MASK_MCHECK; ++ lc->external_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_MCHECK; + lc->external_new_psw.addr = (unsigned long) ext_int_handler; + lc->svc_new_psw.mask = PSW_KERNEL_BITS | +- PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK; ++ PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK; + lc->svc_new_psw.addr = (unsigned long) system_call; +- lc->program_new_psw.mask = PSW_KERNEL_BITS | +- PSW_MASK_DAT | PSW_MASK_MCHECK; ++ lc->program_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_MCHECK; + lc->program_new_psw.addr = (unsigned long) pgm_check_handler; + lc->mcck_new_psw.mask = PSW_KERNEL_BITS; + lc->mcck_new_psw.addr = (unsigned long) mcck_int_handler; +- lc->io_new_psw.mask = PSW_KERNEL_BITS | +- PSW_MASK_DAT | PSW_MASK_MCHECK; ++ lc->io_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_MCHECK; + lc->io_new_psw.addr = (unsigned long) io_int_handler; + lc->clock_comparator = -1ULL; + lc->kernel_stack = ((unsigned long) &init_thread_union) +@@ -391,6 +388,17 @@ static void __init setup_lowcore(void) + lowcore_ptr[0] = lc; + } + ++static void __init setup_lowcore_dat_on(void) ++{ ++ struct lowcore *lc; ++ ++ lc = lowcore_ptr[0]; ++ lc->external_new_psw.mask |= PSW_MASK_DAT; ++ lc->svc_new_psw.mask |= PSW_MASK_DAT; ++ lc->program_new_psw.mask |= PSW_MASK_DAT; ++ lc->io_new_psw.mask |= PSW_MASK_DAT; ++} ++ + static struct resource code_resource = { + .name = "Kernel code", + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM, +@@ -945,7 +953,7 @@ void __init setup_arch(char **cmdline_p) + #endif + + setup_resources(); +- setup_lowcore(); ++ setup_lowcore_dat_off(); + smp_fill_possible_mask(); + cpu_detect_mhz_feature(); + cpu_init(); +@@ -958,6 +966,12 @@ void __init setup_arch(char **cmdline_p) + */ + paging_init(); + ++ /* ++ * After paging_init created the kernel page table, the new PSWs ++ * in lowcore can now run with DAT enabled. ++ */ ++ setup_lowcore_dat_on(); ++ + /* Setup default console */ + conmode_default(); + set_preferred_console(); diff --git a/patches.fixes/s390-virtio-handle-find-on-invalid-queue-gracefully b/patches.fixes/s390-virtio-handle-find-on-invalid-queue-gracefully new file mode 100644 index 0000000..61c492a --- /dev/null +++ b/patches.fixes/s390-virtio-handle-find-on-invalid-queue-gracefully @@ -0,0 +1,41 @@ +From: Halil Pasic +Date: Mon, 21 Jan 2019 13:19:43 +0100 +Subject: s390/virtio: handle find on invalid queue gracefully +Git-commit: 3438b2c039b4bf26881786a1f3450f016d66ad11 +Patch-mainline: v5.1-rc1 +References: bsc#1051510 + +A queue with a capacity of zero is clearly not a valid virtio queue. +Some emulators report zero queue size if queried with an invalid queue +index. Instead of crashing in this case let us just return -ENOENT. To +make that work properly, let us fix the notifier cleanup logic as well. + +Cc: stable@vger.kernel.org +Signed-off-by: Halil Pasic +Signed-off-by: Cornelia Huck +Signed-off-by: Michael S. Tsirkin +Acked-by: Petr Tesarik +--- + drivers/s390/virtio/virtio_ccw.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/s390/virtio/virtio_ccw.c ++++ b/drivers/s390/virtio/virtio_ccw.c +@@ -275,6 +275,8 @@ static void virtio_ccw_drop_indicators(s + { + struct virtio_ccw_vq_info *info; + ++ if (!vcdev->airq_info) ++ return; + list_for_each_entry(info, &vcdev->virtqueues, node) + drop_airq_indicator(info->vq, vcdev->airq_info); + } +@@ -416,7 +418,7 @@ static int virtio_ccw_read_vq_conf(struc + ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_VQ_CONF); + if (ret) + return ret; +- return vcdev->config_block->num; ++ return vcdev->config_block->num ?: -ENOENT; + } + + static void virtio_ccw_del_vq(struct virtqueue *vq, struct ccw1 *ccw) diff --git a/patches.fixes/scsi-zfcp-fix-missing-zfcp_port-reference-put-on-ebusy-from-port_remove b/patches.fixes/scsi-zfcp-fix-missing-zfcp_port-reference-put-on-ebusy-from-port_remove new file mode 100644 index 0000000..5ab2d2e --- /dev/null +++ b/patches.fixes/scsi-zfcp-fix-missing-zfcp_port-reference-put-on-ebusy-from-port_remove @@ -0,0 +1,33 @@ +From: Steffen Maier +Date: Thu, 23 May 2019 15:23:45 +0200 +Subject: scsi: zfcp: fix missing zfcp_port reference put on -EBUSY from + port_remove +Git-commit: d27e5e07f9c49bf2a6a4ef254ce531c1b4fb5a38 +Patch-mainline: v5.2-rc1 +References: bsc#1051510 + +With this early return due to zfcp_unit child(ren), we don't use the +zfcp_port reference from the earlier zfcp_get_port_by_wwpn() anymore and +need to put it. + +Signed-off-by: Steffen Maier +Fixes: d99b601b6338 ("[SCSI] zfcp: restore refcount check on port_remove") +Cc: #3.7+ +Reviewed-by: Jens Remus +Reviewed-by: Benjamin Block +Signed-off-by: Martin K. Petersen +Acked-by: Petr Tesarik +--- + drivers/s390/scsi/zfcp_sysfs.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/s390/scsi/zfcp_sysfs.c ++++ b/drivers/s390/scsi/zfcp_sysfs.c +@@ -263,6 +263,7 @@ static ssize_t zfcp_sysfs_port_remove_st + if (atomic_read(&port->units) > 0) { + retval = -EBUSY; + mutex_unlock(&zfcp_sysfs_port_units_mutex); ++ put_device(&port->dev); /* undo zfcp_get_port_by_wwpn() */ + goto out; + } + /* port is about to be removed, so no more unit_add */ diff --git a/patches.fixes/scsi-zfcp-fix-rport-unblock-if-deleted-scsi-devices-on-scsi_host b/patches.fixes/scsi-zfcp-fix-rport-unblock-if-deleted-scsi-devices-on-scsi_host new file mode 100644 index 0000000..4df9fc3 --- /dev/null +++ b/patches.fixes/scsi-zfcp-fix-rport-unblock-if-deleted-scsi-devices-on-scsi_host @@ -0,0 +1,80 @@ +From: Steffen Maier +Date: Tue, 26 Mar 2019 14:36:58 +0100 +Subject: scsi: zfcp: fix rport unblock if deleted SCSI devices on Scsi_Host +Git-commit: fe67888fc007a76b81e37da23ce5bd8fb95890b0 +Patch-mainline: v5.1-rc3 +References: bsc#1051510 + +An already deleted SCSI device can exist on the Scsi_Host and remain there +because something still holds a reference. A new SCSI device with the same +H:C:T:L and FCP device, target port WWPN, and FCP LUN can be created. When +we try to unblock an rport, we still find the deleted SCSI device and +return early because the zfcp_scsi_dev of that SCSI device is not +ZFCP_STATUS_COMMON_UNBLOCKED. Hence we miss to unblock the rport, even if +the new proper SCSI device would be in good state. + +Therefore, skip deleted SCSI devices when iterating the sdevs of the shost. +[cf. __scsi_device_lookup{_by_target}() or scsi_device_get()] + +The following abbreviated trace sequence can indicate such problem: + +Area : REC +Tag : ersfs_3 +LUN : 0x4045400300000000 +WWPN : 0x50050763031bd327 +LUN status : 0x40000000 not ZFCP_STATUS_COMMON_UNBLOCKED +Ready count : n not incremented yet +Running count : 0x00000000 +ERP want : 0x01 +ERP need : 0xc1 ZFCP_ERP_ACTION_NONE + +Area : REC +Tag : ersfs_3 +LUN : 0x4045400300000000 +WWPN : 0x50050763031bd327 +LUN status : 0x41000000 +Ready count : n+1 +Running count : 0x00000000 +ERP want : 0x01 +ERP need : 0x01 + +... + +Area : REC +Level : 4 only with increased trace level +Tag : ertru_l +LUN : 0x4045400300000000 +WWPN : 0x50050763031bd327 +LUN status : 0x40000000 +Request ID : 0x0000000000000000 +ERP status : 0x01800000 +ERP step : 0x1000 +ERP action : 0x01 +ERP count : 0x00 + +NOT followed by a trace record with tag "scpaddy" +for WWPN 0x50050763031bd327. + +Signed-off-by: Steffen Maier +Fixes: 6f2ce1c6af37 ("scsi: zfcp: fix rport unblock race with LUN recovery") +Cc: #2.6.32+ +Reviewed-by: Jens Remus +Reviewed-by: Benjamin Block +Signed-off-by: Martin K. Petersen +Acked-by: Petr Tesarik +--- + drivers/s390/scsi/zfcp_erp.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/s390/scsi/zfcp_erp.c ++++ b/drivers/s390/scsi/zfcp_erp.c +@@ -1306,6 +1306,9 @@ static void zfcp_erp_try_rport_unblock(s + struct zfcp_scsi_dev *zsdev = sdev_to_zfcp(sdev); + int lun_status; + ++ if (sdev->sdev_state == SDEV_DEL || ++ sdev->sdev_state == SDEV_CANCEL) ++ continue; + if (zsdev->port != port) + continue; + /* LUN under port of interest */ diff --git a/patches.fixes/scsi-zfcp-fix-scsi_eh-host-reset-with-port_forced-erp-for-non-npiv-fcp-devices b/patches.fixes/scsi-zfcp-fix-scsi_eh-host-reset-with-port_forced-erp-for-non-npiv-fcp-devices new file mode 100644 index 0000000..2a855c2 --- /dev/null +++ b/patches.fixes/scsi-zfcp-fix-scsi_eh-host-reset-with-port_forced-erp-for-non-npiv-fcp-devices @@ -0,0 +1,92 @@ +From: Steffen Maier +Date: Tue, 26 Mar 2019 14:36:59 +0100 +Subject: scsi: zfcp: fix scsi_eh host reset with port_forced ERP for non-NPIV + FCP devices +Git-commit: 242ec1455151267fe35a0834aa9038e4c4670884 +Patch-mainline: v5.1-rc3 +References: bsc#1051510 + +Suppose more than one non-NPIV FCP device is active on the same channel. +Send I/O to storage and have some of the pending I/O run into a SCSI +command timeout, e.g. due to bit errors on the fibre. Now the error +situation stops. However, we saw FCP requests continue to timeout in the +channel. The abort will be successful, but the subsequent TUR fails. +Scsi_eh starts. The LUN reset fails. The target reset fails. The host +reset only did an FCP device recovery. However, for non-NPIV FCP devices, +this does not close and reopen ports on the SAN-side if other non-NPIV FCP +device(s) share the same open ports. + +In order to resolve the continuing FCP request timeouts, we need to +explicitly close and reopen ports on the SAN-side. + +This was missing since the beginning of zfcp in v2.6.0 history commit +ea127f975424 ("[PATCH] s390 (7/7): zfcp host adapter."). + +Note: The FSF requests for forced port reopen could run into FSF request +timeouts due to other reasons. This would trigger an internal FCP device +recovery. Pending forced port reopen recoveries would get dismissed. So +some ports might not get fully reopened during this host reset handler. +However, subsequent I/O would trigger the above described escalation and +eventually all ports would be forced reopen to resolve any continuing FCP +request timeouts due to earlier bit errors. + +Signed-off-by: Steffen Maier +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: #3.0+ +Reviewed-by: Jens Remus +Reviewed-by: Benjamin Block +Signed-off-by: Martin K. Petersen +Acked-by: Petr Tesarik +--- + drivers/s390/scsi/zfcp_erp.c | 14 ++++++++++++++ + drivers/s390/scsi/zfcp_ext.h | 2 ++ + drivers/s390/scsi/zfcp_scsi.c | 4 ++++ + 3 files changed, 20 insertions(+) + +--- a/drivers/s390/scsi/zfcp_erp.c ++++ b/drivers/s390/scsi/zfcp_erp.c +@@ -652,6 +652,20 @@ static void zfcp_erp_strategy_memwait(st + add_timer(&erp_action->timer); + } + ++void zfcp_erp_port_forced_reopen_all(struct zfcp_adapter *adapter, ++ int clear, char *dbftag) ++{ ++ unsigned long flags; ++ struct zfcp_port *port; ++ ++ write_lock_irqsave(&adapter->erp_lock, flags); ++ read_lock(&adapter->port_list_lock); ++ list_for_each_entry(port, &adapter->port_list, list) ++ _zfcp_erp_port_forced_reopen(port, clear, dbftag); ++ read_unlock(&adapter->port_list_lock); ++ write_unlock_irqrestore(&adapter->erp_lock, flags); ++} ++ + static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, + int clear, char *id) + { +--- a/drivers/s390/scsi/zfcp_ext.h ++++ b/drivers/s390/scsi/zfcp_ext.h +@@ -68,6 +68,8 @@ extern void zfcp_erp_clear_port_status(s + extern int zfcp_erp_port_reopen(struct zfcp_port *, int, char *); + extern void zfcp_erp_port_shutdown(struct zfcp_port *, int, char *); + extern void zfcp_erp_port_forced_reopen(struct zfcp_port *, int, char *); ++extern void zfcp_erp_port_forced_reopen_all(struct zfcp_adapter *adapter, ++ int clear, char *dbftag); + extern void zfcp_erp_set_lun_status(struct scsi_device *, u32); + extern void zfcp_erp_clear_lun_status(struct scsi_device *, u32); + extern void zfcp_erp_lun_reopen(struct scsi_device *, int, char *); +--- a/drivers/s390/scsi/zfcp_scsi.c ++++ b/drivers/s390/scsi/zfcp_scsi.c +@@ -326,6 +326,10 @@ static int zfcp_scsi_eh_host_reset_handl + struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; + int ret = SUCCESS, fc_ret; + ++ if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE)) { ++ zfcp_erp_port_forced_reopen_all(adapter, 0, "schrh_p"); ++ zfcp_erp_wait(adapter); ++ } + zfcp_erp_adapter_reopen(adapter, 0, "schrh_1"); + zfcp_erp_wait(adapter); + fc_ret = fc_block_scsi_eh(scpnt); diff --git a/patches.fixes/scsi-zfcp-fix-to-prevent-port_remove-with-pure-auto-scan-luns-only-sdevs b/patches.fixes/scsi-zfcp-fix-to-prevent-port_remove-with-pure-auto-scan-luns-only-sdevs new file mode 100644 index 0000000..1ee44c3 --- /dev/null +++ b/patches.fixes/scsi-zfcp-fix-to-prevent-port_remove-with-pure-auto-scan-luns-only-sdevs @@ -0,0 +1,184 @@ +From: Steffen Maier +Date: Thu, 23 May 2019 15:23:46 +0200 +Subject: scsi: zfcp: fix to prevent port_remove with pure auto scan LUNs (only + sdevs) +Git-commit: ef4021fe5fd77ced0323cede27979d80a56211ca +Patch-mainline: v5.2-rc1 +References: bsc#1051510 + +When the user tries to remove a zfcp port via sysfs, we only rejected it if +there are zfcp unit children under the port. With purely automatically +scanned LUNs there are no zfcp units but only SCSI devices. In such cases, +the port_remove erroneously continued. We close the port and this +implicitly closes all LUNs under the port. The SCSI devices survive with +their private zfcp_scsi_dev still holding a reference to the "removed" +zfcp_port (still allocated but invisible in sysfs) [zfcp_get_port_by_wwpn +in zfcp_scsi_slave_alloc]. This is not a problem as long as the fc_rport +stays blocked. Once (auto) port scan brings back the removed port, we +unblock its fc_rport again by design. However, there is no mechanism that +would recover (open) the LUNs under the port (no "ersfs_3" without +zfcp_unit [zfcp_erp_strategy_followup_success]). Any pending or new I/O to +such LUN leads to repeated: + + Done: NEEDS_RETRY Result: hostbyte=DID_IMM_RETRY driverbyte=DRIVER_OK + +See also v4.10 commit 6f2ce1c6af37 ("scsi: zfcp: fix rport unblock race +with LUN recovery"). Even a manual LUN recovery +(echo 0 > /sys/bus/scsi/devices/H:C:T:L/zfcp_failed) +does not help, as the LUN links to the old "removed" port which remains +to lack ZFCP_STATUS_COMMON_RUNNING [zfcp_erp_required_act]. +The only workaround is to first ensure that the fc_rport is blocked +(e.g. port_remove again in case it was re-discovered by (auto) port scan), +then delete the SCSI devices, and finally re-discover by (auto) port scan. +The port scan includes an fc_rport unblock, which in turn triggers +a new scan on the scsi target to freshly get new pure auto scan LUNs. + +Fix this by rejecting port_remove also if there are SCSI devices +(even without any zfcp_unit) under this port. Re-use mechanics from v3.7 +commit d99b601b6338 ("[SCSI] zfcp: restore refcount check on port_remove"). +However, we have to give up zfcp_sysfs_port_units_mutex earlier in unit_add +to prevent a deadlock with scsi_host scan taking shost->scan_mutex first +and then zfcp_sysfs_port_units_mutex now in our zfcp_scsi_slave_alloc(). + +Signed-off-by: Steffen Maier +Fixes: b62a8d9b45b9 ("[SCSI] zfcp: Use SCSI device data zfcp scsi dev instead of zfcp unit") +Fixes: f8210e34887e ("[SCSI] zfcp: Allow midlayer to scan for LUNs when running in NPIV mode") +Cc: #2.6.37+ +Reviewed-by: Benjamin Block +Signed-off-by: Martin K. Petersen +Acked-by: Petr Tesarik +--- + drivers/s390/scsi/zfcp_ext.h | 1 + drivers/s390/scsi/zfcp_scsi.c | 9 ++++++ + drivers/s390/scsi/zfcp_sysfs.c | 54 ++++++++++++++++++++++++++++++++++++----- + drivers/s390/scsi/zfcp_unit.c | 8 +++++- + 4 files changed, 65 insertions(+), 7 deletions(-) + +--- a/drivers/s390/scsi/zfcp_ext.h ++++ b/drivers/s390/scsi/zfcp_ext.h +@@ -161,6 +161,7 @@ extern const struct attribute_group *zfc + extern struct mutex zfcp_sysfs_port_units_mutex; + extern struct device_attribute *zfcp_sysfs_sdev_attrs[]; + extern struct device_attribute *zfcp_sysfs_shost_attrs[]; ++bool zfcp_sysfs_port_is_removing(const struct zfcp_port *const port); + + /* zfcp_unit.c */ + extern int zfcp_unit_add(struct zfcp_port *, u64); +--- a/drivers/s390/scsi/zfcp_scsi.c ++++ b/drivers/s390/scsi/zfcp_scsi.c +@@ -124,6 +124,15 @@ static int zfcp_scsi_slave_alloc(struct + + zfcp_sdev->erp_action.port = port; + ++ mutex_lock(&zfcp_sysfs_port_units_mutex); ++ if (zfcp_sysfs_port_is_removing(port)) { ++ /* port is already gone */ ++ mutex_unlock(&zfcp_sysfs_port_units_mutex); ++ put_device(&port->dev); /* undo zfcp_get_port_by_wwpn() */ ++ return -ENXIO; ++ } ++ mutex_unlock(&zfcp_sysfs_port_units_mutex); ++ + unit = zfcp_unit_find(port, zfcp_scsi_dev_lun(sdev)); + if (unit) + put_device(&unit->dev); +--- a/drivers/s390/scsi/zfcp_sysfs.c ++++ b/drivers/s390/scsi/zfcp_sysfs.c +@@ -237,6 +237,53 @@ static ZFCP_DEV_ATTR(adapter, port_resca + + DEFINE_MUTEX(zfcp_sysfs_port_units_mutex); + ++static void zfcp_sysfs_port_set_removing(struct zfcp_port *const port) ++{ ++ lockdep_assert_held(&zfcp_sysfs_port_units_mutex); ++ atomic_set(&port->units, -1); ++} ++ ++bool zfcp_sysfs_port_is_removing(const struct zfcp_port *const port) ++{ ++ lockdep_assert_held(&zfcp_sysfs_port_units_mutex); ++ return atomic_read(&port->units) == -1; ++} ++ ++static bool zfcp_sysfs_port_in_use(struct zfcp_port *const port) ++{ ++ struct zfcp_adapter *const adapter = port->adapter; ++ unsigned long flags; ++ struct scsi_device *sdev; ++ bool in_use = true; ++ ++ mutex_lock(&zfcp_sysfs_port_units_mutex); ++ if (atomic_read(&port->units) > 0) ++ goto unlock_port_units_mutex; /* zfcp_unit(s) under port */ ++ ++ spin_lock_irqsave(adapter->scsi_host->host_lock, flags); ++ __shost_for_each_device(sdev, adapter->scsi_host) { ++ const struct zfcp_scsi_dev *zsdev = sdev_to_zfcp(sdev); ++ ++ if (sdev->sdev_state == SDEV_DEL || ++ sdev->sdev_state == SDEV_CANCEL) ++ continue; ++ if (zsdev->port != port) ++ continue; ++ /* alive scsi_device under port of interest */ ++ goto unlock_host_lock; ++ } ++ ++ /* port is about to be removed, so no more unit_add or slave_alloc */ ++ zfcp_sysfs_port_set_removing(port); ++ in_use = false; ++ ++unlock_host_lock: ++ spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags); ++unlock_port_units_mutex: ++ mutex_unlock(&zfcp_sysfs_port_units_mutex); ++ return in_use; ++} ++ + static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +@@ -259,16 +306,11 @@ static ssize_t zfcp_sysfs_port_remove_st + else + retval = 0; + +- mutex_lock(&zfcp_sysfs_port_units_mutex); +- if (atomic_read(&port->units) > 0) { ++ if (zfcp_sysfs_port_in_use(port)) { + retval = -EBUSY; +- mutex_unlock(&zfcp_sysfs_port_units_mutex); + put_device(&port->dev); /* undo zfcp_get_port_by_wwpn() */ + goto out; + } +- /* port is about to be removed, so no more unit_add */ +- atomic_set(&port->units, -1); +- mutex_unlock(&zfcp_sysfs_port_units_mutex); + + write_lock_irq(&adapter->port_list_lock); + list_del(&port->list); +--- a/drivers/s390/scsi/zfcp_unit.c ++++ b/drivers/s390/scsi/zfcp_unit.c +@@ -123,7 +123,7 @@ int zfcp_unit_add(struct zfcp_port *port + int retval = 0; + + mutex_lock(&zfcp_sysfs_port_units_mutex); +- if (atomic_read(&port->units) == -1) { ++ if (zfcp_sysfs_port_is_removing(port)) { + /* port is already gone */ + retval = -ENODEV; + goto out; +@@ -167,8 +167,14 @@ int zfcp_unit_add(struct zfcp_port *port + write_lock_irq(&port->unit_list_lock); + list_add_tail(&unit->list, &port->unit_list); + write_unlock_irq(&port->unit_list_lock); ++ /* ++ * lock order: shost->scan_mutex before zfcp_sysfs_port_units_mutex ++ * due to zfcp_unit_scsi_scan() => zfcp_scsi_slave_alloc() ++ */ ++ mutex_unlock(&zfcp_sysfs_port_units_mutex); + + zfcp_unit_scsi_scan(unit); ++ return retval; + + out: + mutex_unlock(&zfcp_sysfs_port_units_mutex); diff --git a/patches.fixes/vfio-ccw-only-free-cp-on-final-interrupt b/patches.fixes/vfio-ccw-only-free-cp-on-final-interrupt new file mode 100644 index 0000000..8c109ab --- /dev/null +++ b/patches.fixes/vfio-ccw-only-free-cp-on-final-interrupt @@ -0,0 +1,56 @@ +From: Cornelia Huck +Date: Mon, 11 Mar 2019 10:59:53 +0100 +Subject: vfio: ccw: only free cp on final interrupt +Git-commit: 50b7f1b7236bab08ebbbecf90521e84b068d7a17 +Patch-mainline: v5.1-rc3 +References: bsc#1051510 + +When we get an interrupt for a channel program, it is not +necessarily the final interrupt; for example, the issuing +guest may request an intermediate interrupt by specifying +the program-controlled-interrupt flag on a ccw. + +We must not switch the state to idle if the interrupt is not +yet final; even more importantly, we must not free the translated +channel program if the interrupt is not yet final, or the host +can crash during cp rewind. + +Fixes: e5f84dbaea59 ("vfio: ccw: return I/O results asynchronously") +Cc: stable@vger.kernel.org # v4.12+ +Reviewed-by: Eric Farman +Signed-off-by: Cornelia Huck +Acked-by: Petr Tesarik +--- + drivers/s390/cio/vfio_ccw_drv.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/s390/cio/vfio_ccw_drv.c ++++ b/drivers/s390/cio/vfio_ccw_drv.c +@@ -71,21 +71,25 @@ static void vfio_ccw_sch_io_todo(struct + struct vfio_ccw_private *private; + struct subchannel *sch; + struct irb *irb; ++ bool is_final; + + private = container_of(work, struct vfio_ccw_private, io_work); + irb = &private->irb; + sch = private->sch; + ++ is_final = !(scsw_actl(&irb->scsw) & ++ (SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT)); + if (scsw_is_solicited(&irb->scsw)) { + cp_update_scsw(&private->cp, &irb->scsw); +- cp_free(&private->cp); ++ if (is_final) ++ cp_free(&private->cp); + } + memcpy(private->io_region.irb_area, irb, sizeof(*irb)); + + if (private->io_trigger) + eventfd_signal(private->io_trigger, 1); + +- if (private->mdev) ++ if (private->mdev && is_final) + private->state = VFIO_CCW_STATE_IDLE; + } + diff --git a/series.conf b/series.conf index 4c29949..6334f3c 100644 --- a/series.conf +++ b/series.conf @@ -44577,9 +44577,11 @@ patches.fixes/blockdev-Fix-livelocks-on-loop-device.patch patches.fixes/nvmet-tcp-fix-uninitialized-variable-access.patch patches.fixes/block-Cleanup-license-notice.patch + patches.drivers/scsi-megaraid_sas-correct-an-info-message.patch patches.fixes/scsi-smartpqi_init-fix-boolean-expression-in-pqi_device_remove_start patches.drivers/scsi-hisi_sas-set-protection-parameters-prior-to-adding-scsi-host.patch patches.drivers/scsi-qedi-add-ep_state-for-login-completion-on-un-reachable-targets + patches.drivers/scsi-megaraid_sas-Retry-reads-of-outbound_intr_statu.patch patches.fixes/scsi-ufs-Fix-geometry-descriptor-size.patch patches.drivers/xprtrdma-Double-free-in-rpcrdma_sendctxs_create.patch patches.fixes/nfit-mark-some-functions-as-_maybe_unused.patch @@ -44890,6 +44892,7 @@ patches.drivers/dmaengine-bcm2835-Fix-interrupt-race-on-RT.patch patches.drivers/dmaengine-bcm2835-Fix-abort-of-transactions.patch patches.drivers/dmaengine-dmatest-Abort-test-in-case-of-mapping-erro.patch + patches.fixes/s390-dasd-fix-using-offset-into-zero-size-array-error patches.arch/s390-sles15-zcrypt-fix-specification-exception.patch patches.drivers/ALSA-hda-Add-quirk-for-HP-EliteBook-840-G5.patch patches.drivers/ALSA-usb-audio-Fix-implicit-fb-endpoint-setup-by-qui.patch @@ -45366,6 +45369,7 @@ patches.arch/s390-pci-improve-bar-check patches.arch/s390-pci-map-iov-resources patches.arch/s390-jump_label-Use-jdd-constraint-on-gcc9.patch + patches.fixes/s390-setup-fix-early-warning-messages patches.arch/s390-ism-ignore-some-errors-during-deregistration patches.fixes/0001-s390-vfio_ap-link-the-vfio_ap-devices-to-the-vfio_ap.patch patches.drivers/clocksource-drivers-sun5i-Fail-gracefully-when-clock.patch @@ -45688,6 +45692,9 @@ patches.drivers/scsi-hisi_sas-remove-the-check-of-sas_dev-status-in-hisi_sas_i_t_nexus_reset patches.fixes/scsi-hisi_sas-fix-to-only-call-scsi_get_prot_op-for-non-null-scsi_cmnd.patch patches.drivers/scsi-qla2xxx-Add-new-FC-NVMe-enable-BIT-to-enable-FC.patch + patches.drivers/scsi-megaraid_sas-Rework-code-to-get-PD-and-LD-list.patch + patches.drivers/scsi-megaraid_sas-Rework-device-add-code-in-AEN-path.patch + patches.drivers/scsi-megaraid_sas-Add-support-for-DEVICE_LIST-DCMD-i.patch patches.drivers/scsi-qla2xxx-Fix-N2N-target-discovery-with-Local-loo.patch patches.drivers/scsi-qla2xxx-Add-pci-function-reset-support.patch patches.drivers/scsi-qla2xxx-Change-default-ZIO-threshold.patch @@ -45727,6 +45734,8 @@ patches.drivers/scsi-lpfc-Fix-nvmet-issues-when-link-bounce-under-IO.patch patches.drivers/scsi-lpfc-Update-12.2.0.0-file-copyrights-to-2019.patch patches.drivers/scsi-lpfc-Update-lpfc-version-to-12.2.0.0.patch + patches.drivers/scsi-megaraid_sas-Update-structures-for-HOST_DEVICE_.patch + patches.drivers/scsi-megaraid_sas-driver-version-update-to-07.707.51.00.patch patches.drivers/scsi-qla2xxx-Move-debug-messages-before-sending-srb-.patch patches.drivers/scsi-qla2xxx-remove-redundant-null-check-on-pointer-.patch patches.drivers/scsi-qla2xxx-Fix-LUN-discovery-if-loop-id-is-not-ass.patch @@ -45752,6 +45761,7 @@ patches.arch/0003-dma-introduce-dma_max_mapping_size patches.arch/0004-virtio-introduce-virtio_max_dma_size patches.arch/0005-virtio-blk-consider-virtio_max_dma_size-for-maximum-segment-size + patches.fixes/s390-virtio-handle-find-on-invalid-queue-gracefully patches.drivers/platform-x86-mlx-platform-Add-support-for-fan-direct.patch patches.drivers/platform_data-mlxreg-Document-fixes-for-core-platfor.patch patches.drivers/platform_data-mlxreg-Add-capability-field-to-core-pl.patch @@ -46017,6 +46027,7 @@ patches.suse/packets-Always-register-packet-sk-in-the-same-order.patch patches.suse/sctp-get-sctphdr-by-offset-in-sctp_compute_cksum.patch patches.drivers/mISDN-hfcpci-Test-both-vendor-device-ID-for-Digium-H.patch + patches.fixes/s390-qeth-fix-race-when-initializing-the-ip-address-table patches.suse/net-stmmac-fix-memory-corruption-with-large-MTUs.patch patches.suse/tcp-do-not-use-ipv6-header-for-ipv4-flow.patch patches.suse/dccp-do-not-use-ipv6-header-for-ipv4-flow.patch @@ -46031,6 +46042,7 @@ patches.drivers/net-phy-don-t-clear-BMCR-in-genphy_soft_reset.patch patches.drivers/chelsio-use-BUG-instead-of-BUG_ON-1.patch patches.arch/ARM-imx6q-cpuidle-fix-bug-that-CPU-might-not-wake-up.patch + patches.fixes/vfio-ccw-only-free-cp-on-final-interrupt patches.drm/drm-tegra-hub-Fix-dereference-before-check.patch patches.drm/drm-vgem-fix-use-after-free-when-drm_gem_handle_crea.patch patches.drm/drm-vkms-fix-use-after-free-when-drm_gem_handle_crea.patch @@ -46061,6 +46073,8 @@ patches.drivers/ALSA-pcm-Don-t-suspend-stream-in-unrecoverable-PCM-s.patch patches.drivers/ALSA-hda-realtek-Fix-speakers-on-Acer-Predator-Helio.patch patches.drivers/i2c-i801-Add-support-for-Intel-Comet-Lake.patch + patches.fixes/scsi-zfcp-fix-rport-unblock-if-deleted-scsi-devices-on-scsi_host + patches.fixes/scsi-zfcp-fix-scsi_eh-host-reset-with-port_forced-erp-for-non-npiv-fcp-devices patches.drivers/iommu-don-t-print-warning-when-iommu-driver-only-supports-unmanaged-domains patches.drivers/iommu-amd-reserve-exclusion-range-in-iova-domain patches.fixes/mm-Fix-modifying-of-page-protection-by-insert_pfn.patch @@ -47168,6 +47182,8 @@ patches.arch/s390-pci-fix-assignment-of-bus-resources patches.suse/memcg-make-it-work-on-sparse-non-0-node-systems.patch patches.suse/kernel-signal.c-trace_signal_deliver-when-signal_gro.patch + patches.fixes/scsi-zfcp-fix-missing-zfcp_port-reference-put-on-ebusy-from-port_remove + patches.fixes/scsi-zfcp-fix-to-prevent-port_remove-with-pure-auto-scan-luns-only-sdevs patches.drivers/leds-avoid-flush_work-in-atomic-context.patch patches.drivers/i2c-dev-fix-potential-memory-leak-in-i2cdev_ioctl_rd.patch patches.drivers/i2c-synquacer-fix-synquacer_i2c_doxfer-return-value.patch @@ -47176,6 +47192,7 @@ patches.fixes/efi-x86-Add-missing-error-handling-to-old_memmap-1-1.patch patches.arch/x86-cpu-amd-don-t-force-the-cpb-cap-when-running-under-a-hypervisor.patch patches.fixes/fuse-fallocate-fix-return-with-locked-inode.patch + patches.fixes/s390-qeth-fix-vlan-attribute-in-bridge_hostnotify-udev-event patches.drivers/hwmon-core-add-thermal-sensors-only-if-dev-of_node-i.patch patches.drivers/hwmon-pmbus-core-Treat-parameters-as-paged-if-on-mul.patch patches.drm/drm-i915-gvt-Initialize-intel_gvt_gtt_entry-in-stack.patch