[PATCH] scsi: megaraid: fix spelling mistake "maibox" -> "mailbox"
From: Colin Ian King Trivial fix to spelling mistake in warning message and comments Signed-off-by: Colin Ian King --- drivers/scsi/megaraid/megaraid_mbox.c | 4 ++-- drivers/scsi/megaraid/megaraid_mbox.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index 530358cdcb39..2013523605c5 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -484,7 +484,7 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) // Start the mailbox based controller if (megaraid_init_mbox(adapter) != 0) { con_log(CL_ANN, (KERN_WARNING - "megaraid: maibox adapter did not initialize\n")); + "megaraid: mailbox adapter did not initialize\n")); goto out_free_adapter; } @@ -950,7 +950,7 @@ megaraid_fini_mbox(adapter_t *adapter) * megaraid_alloc_cmd_packets - allocate shared mailbox * @adapter: soft state of the raid controller * - * Allocate and align the shared mailbox. This maibox is used to issue + * Allocate and align the shared mailbox. This mailbox is used to issue * all the commands. For IO based controllers, the mailbox is also registered * with the FW. Allocate memory for all commands as well. * This is our big allocator. diff --git a/drivers/scsi/megaraid/megaraid_mbox.h b/drivers/scsi/megaraid/megaraid_mbox.h index c1d86d961a92..e075aeb4012f 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.h +++ b/drivers/scsi/megaraid/megaraid_mbox.h @@ -117,7 +117,7 @@ * @raw_mbox : raw mailbox pointer * @mbox : mailbox * @mbox64 : extended mailbox - * @mbox_dma_h : maibox dma address + * @mbox_dma_h : mailbox dma address * @sgl64 : 64-bit scatter-gather list * @sgl32 : 32-bit scatter-gather list * @sgl_dma_h : dma handle for the scatter-gather list -- 2.17.1
[PATCH] scsi: ufs: use PTR_ERR_OR_ZERO in ufs_hisi_get_resource()
This patch uses PTR_ERR_OR_ZERO instead of IF_ERR() return PTR_ERR(). Signed-off-by: Joshua Abraham --- drivers/scsi/ufs/ufs-hisi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/scsi/ufs/ufs-hisi.c b/drivers/scsi/ufs/ufs-hisi.c index 46df707e6f2c..e79499469cb3 100644 --- a/drivers/scsi/ufs/ufs-hisi.c +++ b/drivers/scsi/ufs/ufs-hisi.c @@ -505,10 +505,8 @@ static int ufs_hisi_get_resource(struct ufs_hisi_host *host) /* get resource of ufs sys ctrl */ mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); host->ufs_sys_ctrl = devm_ioremap_resource(dev, mem_res); - if (IS_ERR(host->ufs_sys_ctrl)) - return PTR_ERR(host->ufs_sys_ctrl); - return 0; + return PTR_ERR_OR_ZERO(host->ufs_sys_ctrl); } static void ufs_hisi_set_pm_lvl(struct ufs_hba *hba) -- 2.17.1
[PATCH V14 1/2] scsi: ufs: set the device reference clock setting
From: Subhash Jadavani UFS host supplies the reference clock to UFS device and UFS device specification allows host to provide one of the 4 frequencies (19.2 MHz, 26 MHz, 38.4 MHz, 52 MHz) for reference clock. Host should set the device reference clock frequency setting in the device based on what frequency it is supplying to UFS device. Signed-off-by: Subhash Jadavani Signed-off-by: Can Guo Signed-off-by: Sayali Lokhande Reviewed-by: Evan Green --- drivers/scsi/ufs/ufs.h | 14 +++ drivers/scsi/ufs/ufshcd-pltfrm.c | 2 + drivers/scsi/ufs/ufshcd.c| 87 drivers/scsi/ufs/ufshcd.h| 2 + 4 files changed, 105 insertions(+) diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index 14e5bf7..a2e76b1 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -378,6 +378,20 @@ enum query_opcode { UPIU_QUERY_OPCODE_TOGGLE_FLAG = 0x8, }; +/* bRefClkFreq attribute values */ +enum ufs_ref_clk_freq { + REF_CLK_FREQ_19_2_MHZ = 0, + REF_CLK_FREQ_26_MHZ = 1, + REF_CLK_FREQ_38_4_MHZ = 2, + REF_CLK_FREQ_52_MHZ = 3, + REF_CLK_FREQ_INVAL = -1, +}; + +struct ufs_ref_clk { + u32 freq_hz; + enum ufs_ref_clk_freq val; +}; + /* Query response result code */ enum { QUERY_RESULT_SUCCESS= 0x00, diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c index e82bde0..0953563 100644 --- a/drivers/scsi/ufs/ufshcd-pltfrm.c +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c @@ -343,6 +343,8 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); + ufshcd_parse_dev_ref_clk_freq(hba); + ufshcd_init_lanes_per_dir(hba); err = ufshcd_init(hba, mmio_base, irq); diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index c5b1bf1..64c62db 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -6296,6 +6296,86 @@ static void ufshcd_def_desc_sizes(struct ufs_hba *hba) hba->desc_size.hlth_desc = QUERY_DESC_HEALTH_DEF_SIZE; } +static struct ufs_ref_clk ufs_ref_clk_freqs[] = { + {1920, REF_CLK_FREQ_19_2_MHZ}, + {2600, REF_CLK_FREQ_26_MHZ}, + {3840, REF_CLK_FREQ_38_4_MHZ}, + {5200, REF_CLK_FREQ_52_MHZ}, + {0, REF_CLK_FREQ_INVAL}, +}; + +static inline enum ufs_ref_clk_freq +ufs_get_bref_clk_from_hz(u32 freq) +{ + int i = 0; + + while (ufs_ref_clk_freqs[i].freq_hz != freq) { + if (!ufs_ref_clk_freqs[i].freq_hz) + return REF_CLK_FREQ_INVAL; + i++; + } + + return ufs_ref_clk_freqs[i].val; +} + +void ufshcd_parse_dev_ref_clk_freq(struct ufs_hba *hba) +{ + struct device *dev = hba->dev; + struct device_node *np = dev->of_node; + struct clk *refclk = NULL; + u32 freq = 0; + + if (!np) + return; + + refclk = of_clk_get_by_name(np, "ref_clk"); + if (!refclk) + return; + + freq = clk_get_rate(refclk); + + hba->dev_ref_clk_freq = + ufs_get_bref_clk_from_hz(freq); + + if (hba->dev_ref_clk_freq == REF_CLK_FREQ_INVAL) + dev_err(hba->dev, + "%s: invalid ref_clk setting = %d\n", + __func__, freq); +} + +static int ufshcd_set_dev_ref_clk(struct ufs_hba *hba) +{ + int err, ref_clk = -1; + u32 freq = hba->dev_ref_clk_freq; + + err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR, + QUERY_ATTR_IDN_REF_CLK_FREQ, 0, 0, &ref_clk); + + if (err) { + dev_err(hba->dev, "%s: failed reading bRefClkFreq. err = %d\n", +__func__, err); + goto out; + } + + if (ref_clk == hba->dev_ref_clk_freq) + goto out; /* nothing to update */ + + err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR, + QUERY_ATTR_IDN_REF_CLK_FREQ, 0, 0, &freq); + + if (err) { + dev_err(hba->dev, "%s: bRefClkFreq setting to %u Hz failed\n", + __func__, ufs_ref_clk_freqs[freq].freq_hz); + goto out; + } + + dev_dbg(hba->dev, "%s: bRefClkFreq setting to %u Hz succeeded\n", + __func__, ufs_ref_clk_freqs[freq].freq_hz); + +out: + return err; +} + /** * ufshcd_probe_hba - probe hba to detect device and initialize * @hba: per-adapter instance @@ -6361,6 +6441,12 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) "%s: Failed getting max supported power mode\n", __func__); } else { + /* +* Set the right value to bRefClkFreq before attempting to +* switch to HS gears. +*/ + if (hba->dev_ref_clk_freq != REF_CLK_FREQ_INVAL) +
[PATCH V14 2/2] scsi: ufs: Add configfs support for UFS provisioning
This patch adds configfs support to provision UFS device at runtime. This feature can be primarily useful in factory or assembly line as some devices may be required to be configured multiple times during initial system development phase. Configuration Descriptors can be written multiple times until bConfigDescrLock attribute is zero. Configuration descriptor buffer consists of Device and Unit descriptor configurable parameters which are parsed from vendor specific provisioning file and then passed via configfs node at runtime to provision ufs device. CONFIG_CONFIGFS_FS and CONFIG_SCSI_UFS_PROVISION needs to be enabled for using this feature. Usage: 1) To read current configuration descriptor with index X (where index X can be 0/1/2/3) : cat /config//ufs_config_desc_X 2) To write configuration descriptor with index X : echo > /config//ufs_config_desc_X Signed-off-by: Sayali Lokhande --- Documentation/ABI/testing/configfs-driver-ufs | 12 ++ drivers/scsi/ufs/Kconfig | 10 ++ drivers/scsi/ufs/Makefile | 1 + drivers/scsi/ufs/ufs-configfs.c | 237 ++ drivers/scsi/ufs/ufshcd.c | 3 +- drivers/scsi/ufs/ufshcd.h | 18 ++ 6 files changed, 280 insertions(+), 1 deletion(-) create mode 100644 Documentation/ABI/testing/configfs-driver-ufs create mode 100644 drivers/scsi/ufs/ufs-configfs.c diff --git a/Documentation/ABI/testing/configfs-driver-ufs b/Documentation/ABI/testing/configfs-driver-ufs new file mode 100644 index 000..6743ea9 --- /dev/null +++ b/Documentation/ABI/testing/configfs-driver-ufs @@ -0,0 +1,12 @@ +What: /config/*/ufs_config_desc_X +Date: Jun 2018 +KernelVersion: 4.20 +Description: + This file shows bytes of the current ufs configuration descriptor + with index X (where X = 0/1/2/3) set in device. This can be used to + provision ufs device if bConfigDescrLock is 0. + For more details, refer 14.1.6.3 Configuration Descriptor and + table 14-12 - Unit Descriptor configurable parameters from specs for + description and format of each configuration descriptor parameter. + Parameters of Configuration descriptor buffer for respective index + needs to be passed as bytes in space separated format. diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig index e27b4d4..6e7ff35 100644 --- a/drivers/scsi/ufs/Kconfig +++ b/drivers/scsi/ufs/Kconfig @@ -100,3 +100,13 @@ config SCSI_UFS_QCOM Select this if you have UFS controller on QCOM chipset. If unsure, say N. + +config SCSI_UFS_PROVISION + bool "Runtime UFS Provisioning support" + depends on SCSI_UFSHCD && CONFIGFS_FS + help + This enables runtime UFS provisioning support. This can be used + primarily during assembly line as some devices may be required to + be configured multiple times during initial development phase. + + If unsure, say N. diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile index 918f579..09880b9 100644 --- a/drivers/scsi/ufs/Makefile +++ b/drivers/scsi/ufs/Makefile @@ -5,5 +5,6 @@ obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o tc-d obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o ufshcd-core-objs := ufshcd.o ufs-sysfs.o +obj-$(CONFIG_SCSI_UFS_PROVISION) += ufs-configfs.o obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o diff --git a/drivers/scsi/ufs/ufs-configfs.c b/drivers/scsi/ufs/ufs-configfs.c new file mode 100644 index 000..8f6a5d3 --- /dev/null +++ b/drivers/scsi/ufs/ufs-configfs.c @@ -0,0 +1,237 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright (c) 2018, Linux Foundation. + +#include +#include +#include + +#include "ufs.h" +#include "ufshcd.h" + +static inline struct ufs_hba *config_item_to_hba(struct config_item *item) +{ + struct config_group *group = to_config_group(item); + struct configfs_subsystem *subsys = to_configfs_subsystem(group); + struct ufs_hba *hba = container_of(subsys, struct ufs_hba, subsys); + + return hba; +} + +static ssize_t ufs_config_desc_show(struct config_item *item, char *buf, + u8 index) +{ + struct ufs_hba *hba = config_item_to_hba(item); + u8 *desc_buf = NULL; + int desc_buf_len = hba->desc_size.conf_desc; + int i, ret, curr_len = 0; + + desc_buf = kzalloc(desc_buf_len, GFP_KERNEL); + if (!desc_buf) + return -ENOMEM; + + ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC, + QUERY_DESC_IDN_CONFIGURATION, index, + 0, desc_buf, &desc_buf_len); + if (ret) + goto out; + +
Re: aacraid: latest driver results in Host adapter abort request. / Outstanding commands on (0,0,0,0):
Am 22.09.2018 um 23:40 schrieb Bart Van Assche: > On 9/18/18 11:10 PM, Stefan Priebe - Profihost AG wrote: >> after upgrading the aacraid driver / kernel from aacraid 50792 to >> aacraid 50877. > > The aacraid driver version was updated to 50792 in commit 0662cc968ace > ("scsi: aacraid: Update driver version") and to 50877 in commit > 1cdb74b80f93 ("scsi: aacraid: Update driver version to 50877"). That > means that the regression you encountered got introduced after commit > 0662cc968ace. 114 changes got checked in after that commit. That's too > much to find the root cause by rereading all these changes. Is there any > way to trigger the problem faster such that it becomes feasible to run a > bisect? Sadly i'm not able. May be also something else in the kernel has changed. I'm now trying the original out of tree driver from microsemi / adaptec: Adaptec aacraid driver 1.2.1.56008src No idea how those driver versions corespond to the kernel ones. Greets, Stefan > $ git log 0662cc968ace..master drivers/scsi/aacraid | grep -c ^commit > 114 > > Bart.
Re: aacraid: latest driver results in Host adapter abort request. / Outstanding commands on (0,0,0,0):
Am 23.09.2018 um 20:22 schrieb Stefan Priebe - Profihost AG: > > Am 22.09.2018 um 23:40 schrieb Bart Van Assche: >> On 9/18/18 11:10 PM, Stefan Priebe - Profihost AG wrote: >>> after upgrading the aacraid driver / kernel from aacraid 50792 to >>> aacraid 50877. >> >> The aacraid driver version was updated to 50792 in commit 0662cc968ace >> ("scsi: aacraid: Update driver version") and to 50877 in commit >> 1cdb74b80f93 ("scsi: aacraid: Update driver version to 50877"). That >> means that the regression you encountered got introduced after commit >> 0662cc968ace. 114 changes got checked in after that commit. That's too >> much to find the root cause by rereading all these changes. Is there any >> way to trigger the problem faster such that it becomes feasible to run a >> bisect? > > Sadly i'm not able. May be also something else in the kernel has changed. > > I'm now trying the original out of tree driver from microsemi / adaptec: > Adaptec aacraid driver 1.2.1.56008src > > No idea how those driver versions corespond to the kernel ones. OK the out of tree also timed out and the whole system went unreachable. The output just looked different: 2018-09-24 03:00:29 aacraid :03:00.0: AAC0:aac_eh_abort:Host adapter abort request (0,0,1,0) 2018-09-24 03:00:29 aacraid :03:00.0: AAC0:aac_eh_abort:Timed out Command: 2a 00 c0 98 6f a2 00 00 28 00 00 00 00 00 00 00 2018-09-24 03:00:29 aacraid :03:00.0: AAC0:aac_eh_abort:FIB = 950ca6706780 : bac49220 Command = 502 XferState = 830ad Wait Time = 120Sec 2018-09-24 03:00:29 aacraid :03:00.0: AAC0:aac_eh_abort:Host adapter abort request (0,0,1,0) 2018-09-24 03:00:29 aacraid :03:00.0: AAC0:aac_eh_abort:Timed out Command: 2a 00 c0 98 6d a2 00 02 00 00 00 00 00 00 00 00 2018-09-24 03:00:29 aacraid :03:00.0: AAC0:aac_eh_abort:FIB = 950ca67066c8 : bac48a00 Command = 502 XferState = 830ad Wait Time = 120Sec 2018-09-24 03:00:29 aacraid :03:00.0: AAC0:aac_eh_abort:Host adapter abort request (0,0,1,0) 2018-09-24 03:00:29 aacraid :03:00.0: AAC0:aac_eh_abort:Timed out Command: 2a 00 c0 98 6b a2 00 02 00 00 00 00 00 00 00 00 2018-09-24 03:00:29 aacraid :03:00.0: AAC0:aac_eh_abort:FIB = 950ca6706610 : bac481e0 Command = 502 XferState = 830ad Wait Time = 120Sec 2018-09-24 03:00:29 aacraid :03:00.0: AAC0:aac_eh_abort:Host adapter abort request (0,0,1,0) 2018-09-24 03:00:29 aacraid :03:00.0: AAC0:aac_eh_abort:Timed out Command: 2a 00 c0 98 69 a2 00 02 00 00 00 00 00 00 00 00 2018-09-24 03:00:29 aacraid :03:00.0: AAC0:aac_eh_abort:FIB = 950ca6706558 : bac479c0 Command = 502 XferState = 830ad Wait Time = 120Sec all series 6 controllers are those with problems when high load happens. Greets, Stefan > >> $ git log 0662cc968ace..master drivers/scsi/aacraid | grep -c ^commit >> 114 >> >> Bart.
[PATCH V14 0/2] Add UFS provisioning support in driver
This patch adds Configfs support to provision UFS device at runtime. This feature can be primarily useful in factory or assembly line as some devices may be required to be configured multiple times during initial system development phase. Configuration Descriptors can be written multiple times until bConfigDescrLock attribute is zero. Configuration descriptor buffer consists of Device and Unit descriptor configurable parameters which are parsed from vendor specific provisioning file and then passed via configfs node at runtime to provision ufs device. Changes since V13: 1)scsi: ufs: set the device reference clock setting Removed extra comment. 2)scsi: ufs: Add configfs support for UFS provisioning Used snprintf for limiting configfs item name length to 20 and thus avoid overrun. Changes since V12: 1)scsi: ufs: set the device reference clock setting No update. 2)scsi: ufs: Add configfs support for UFS provisioning Minor fixes related to return statement, updated indentation as per checkpatch script and added logic to first read config descriptor before updating with user provied buffer so that old configuration can be retained in case user buffer length is less than expected config descriptor length. Changes since V11: 1)scsi: ufs: set the device reference clock setting No update. 2)scsi: ufs: Add configfs support for UFS provisioning Minor fixes related to missing kfree(), return statement and indentation. Changes since V10: 1)scsi: ufs: set the device reference clock setting No update. 2)scsi: ufs: Add configfs support for UFS provisioning Added support for all config descriptors (namely with index 0,1,2,3). Updated config descriptor length to reflect actual length of each descriptor instead of hard coded macro. Updated documentation as per new added fields (for each config descriptor). Added support for multiple ufs hba's. Changes since V9: 1)scsi: ufs: set the device reference clock setting Minor fixes related to naming format, if check conditions. 2)scsi: ufs: Add configfs support for UFS provisioning Minor fixes related to naming format, function return type. Changes since V8: 1)scsi: ufs: set the device reference clock setting Updated one common enum for both ref_clk_freq in Hz and bref_attr and used same in parsing api. Moved call to parse api to ufshcd_alloc_host() instead of calling from pltfrm_init(), so that it can be called via other paths(which dont use pltfrm_init) and hba->dev_ref_clk can get intialized to either valid/invalid value. 2)scsi: ufs: Add configfs support for UFS provisioning Updated error returns and removed few unnecessary sanity check as per comments. Changes since V7: 1)scsi: ufs: set the device reference clock setting Updated return statements and condition checks as per comments. Added struct ufs_ref_clk_freqs which holds both bref_clk_attr val and respective ref clk frequency in Hz and used same while parsing ref_clk. 2)scsi: ufs: Add configfs support for UFS provisioning Updated return statements and conditional check as per comments. Changes since V6: 1)scsi: ufs: set the device reference clock setting Re-introduced this patch to provisioning patch set(as per comments from Evan). Used of_clk_get_by_name() and clk_get_rate() to set ref_clk frequency instead of passing freq via DT. 2)scsi: ufs: Add configfs support for UFS provisioning Updated error handling in case if kstrtoint fails while parsing input configuration buffer. Changes since V5: 1)scsi: ufs: set the device reference clock setting Removed this patch from provisioning patch set(as its not required to be set as dependent changes). This will be uploaded as a separate patch later. 2)scsi: ufs: Add configfs support for UFS provisioning Removed few extra debug prints. Updated permission of ufs_provision attribute from 0666 to 0644. Pass UFS device name as part of ufshcd_configfs_init() to support multiple UFS controller for embedded and removable UFS card. Changes since V4: 1)scsi: ufs: set the device reference clock setting Used "assigned-clock-rates" DT property to pass required ref clk frequency. 2)scsi: ufs: Add configfs support for ufs provisioning Combined previous patch(2) and patch(3) into single patch which adds configfs provisioning support in driver. Removed extra sw provisioning related fields (like lun_to_grow, commit) a
[PATCH v3 0/6] mpt3sas: Hot-Plug Surprise removal support on IOC.
Posting below set of patches to support PCIe Hot Plug surprise removal, and few defect fixes. This is NOT the normal PCIe Hot Plug support, whereby the user informs the OS that a hot removal is desired, the OS does an orderly shutdown of the driver on the device, special hot plug circuitry removes power from the PCIe slot, then the user can remove the device and replace it (where orderly bring-up of the device is done). With a true surprise removal (just removing HBA from a slot) there is a possibility to get all kinds of PCIe transaction errors, Below patches addresses those issues and remove HBA without bringing the system down. For surprise removal detection, driver does a PCI read of IOC's vendor field in IOC's PCI configuration space. If the read value is 0x this indicates that the device might have hot removed and the device will be removed from driver. V1 changes: In Patch 0001 - unlock mutex, if active reset is in progress. V2 changes: Replaced mpt3sas_base_pci_device_is_unplugged with pci_device_is_present. V3 Change Set: Simplified function "mpt3sas_base_pci_device_is_available" and made inline Suganath Prabu S (6): mpt3sas: Introduce mpt3sas_base_pci_device_is_available mpt3sas: Separate out mpt3sas_wait_for_ioc_to_operational mpt3sas: Introdude _scsih_get_shost_and_ioc. mpt3sas: Fix Sync cache command failure during driver unload. mpt3sas: Fix driver modifying NVRAM/persistent data. mpt3sas: Bump driver version to 27.100.00.00. drivers/scsi/mpt3sas/mpt3sas_base.c | 135 +++--- drivers/scsi/mpt3sas/mpt3sas_base.h | 11 +- drivers/scsi/mpt3sas/mpt3sas_config.c| 32 +- drivers/scsi/mpt3sas/mpt3sas_ctl.c | 26 + drivers/scsi/mpt3sas/mpt3sas_scsih.c | 189 +++ drivers/scsi/mpt3sas/mpt3sas_transport.c | 82 +++--- 6 files changed, 298 insertions(+), 177 deletions(-) -- 1.8.3.1
[PATCH v3 2/6] mpt3sas: Separate out mpt3sas_wait_for_ioc_to_operational
Introduce mpt3sas_wait_for_ioc_to_operational. This section of code "wait for IOC to be operational" is used in many places across the driver, and hence moved this section of code in to the function "mpt3sas_wait_for_ioc_to_operational". Also added HBA hot unplug checks, and this returns with error code EFAULT, if it detects HBA is hot unplugged or IOC is not in operational state. V2 change set: used pci_device_is_present instead of mpt3sas_base_pci_device_is_unplugged Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_base.c | 92 +++- drivers/scsi/mpt3sas/mpt3sas_base.h | 4 ++ drivers/scsi/mpt3sas/mpt3sas_config.c| 28 +++--- drivers/scsi/mpt3sas/mpt3sas_ctl.c | 26 ++--- drivers/scsi/mpt3sas/mpt3sas_transport.c | 75 +- 5 files changed, 81 insertions(+), 144 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index c98d8e2..55e6fd0 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -5176,6 +5176,53 @@ _base_send_ioc_reset(struct MPT3SAS_ADAPTER *ioc, u8 reset_type, int timeout) } /** + * mpt3sas_wait_for_ioc_to_operational - IOC's operational + * state and HBA hot unplug status are checked here. + * @ioc: per adapter object + * @wait_count: timeout in seconds + * + * Return: Returns EFAULT, if HBA is hot unplugged or IOC is + * not in operational state, within the wait_count. + * And returns 0, If not hot unplugged Or ioc is in + * operational state. + */ + +int +mpt3sas_wait_for_ioc_to_operational(struct MPT3SAS_ADAPTER *ioc, + int wait_count) +{ + int wait_state_count = 0; + u32 ioc_state; + + if (!pci_device_is_present(ioc->pdev)) + return -EFAULT; + + ioc_state = mpt3sas_base_get_iocstate(ioc, 1); + while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { + + if (!pci_device_is_present(ioc->pdev)) + return -EFAULT; + + if (wait_state_count++ == wait_count) { + pr_err(MPT3SAS_FMT + "%s: failed due to ioc not operational\n", + ioc->name, __func__); + return -EFAULT; + } + ssleep(1); + ioc_state = mpt3sas_base_get_iocstate(ioc, 1); + pr_info(MPT3SAS_FMT "%s: waiting for " + "operational state(count=%d)\n", ioc->name, + __func__, wait_state_count); + } + if (wait_state_count) + pr_info(MPT3SAS_FMT "%s: ioc is operational\n", + ioc->name, __func__); + + return 0; +} + +/** * _base_handshake_req_reply_wait - send request thru doorbell interface * @ioc: per adapter object * @request_bytes: request length @@ -5316,11 +5363,9 @@ mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER *ioc, Mpi2SasIoUnitControlRequest_t *mpi_request) { u16 smid; - u32 ioc_state; u8 issue_reset = 0; int rc; void *request; - u16 wait_state_count; dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, __func__)); @@ -5334,22 +5379,10 @@ mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER *ioc, goto out; } - wait_state_count = 0; - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - if (wait_state_count++ == 10) { - pr_err(MPT3SAS_FMT - "%s: failed due to ioc not operational\n", - ioc->name, __func__); - rc = -EFAULT; - goto out; - } - ssleep(1); - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - pr_info(MPT3SAS_FMT - "%s: waiting for operational state(count=%d)\n", - ioc->name, __func__, wait_state_count); - } + rc = mpt3sas_wait_for_ioc_to_operational(ioc, + IOC_OPERATIONAL_WAIT_COUNT); + if (rc) + goto out; smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx); if (!smid) { @@ -5416,11 +5449,9 @@ mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc, Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request) { u16 smid; - u32 ioc_state; u8 issue_reset = 0; int rc; void *request; - u16 wait_state_count; dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, __func__)); @@ -5434,23 +5465,10 @@ mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc, goto out; } - wait_state_count = 0; - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - while (ioc_state != MPI2_IOC_STAT
[PATCH v3 1/6] mpt3sas: Introduce mpt3sas_base_pci_device_is_available
* Driver uses "pci_device_is_present" to check whether If Hot unplugged: the outstanding IOs with 'DID_NO_CONNECT' before removing the drives attached to the HBA. "DID_NO_CONNECT" status and free the smid, if driver detects that HBA is hot unplugged. * In the hard reset flush out all the outstanding IOs even if diag reset fails and also if driver detects that HBA is hot unplugged. v1 change set: == unlock mutex before goto "out_unlocked", if active reset is in progress. v2 change set: == 1) Use pci_device_is_present instead of mpt3sas_base_pci_device_is_unplugged. 2) As suggested by Lukas, removed using watchdog thread for checking hba hot unplug(Patch 02 of V1). Added Hot unplug checks in scan finish and reset paths. v3 Change Set: = Simplified function "mpt3sas_base_pci_device_is_available" and made inline. Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_base.c | 41 + drivers/scsi/mpt3sas/mpt3sas_base.h | 3 ++- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 50 3 files changed, 88 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 59d7844..c98d8e2 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -543,6 +543,20 @@ static int mpt3sas_remove_dead_ioc_func(void *arg) } /** + * mpt3sas_base_pci_device_is_available - check whether pci device is + * available for any transactions with FW + * + * @ioc: per adapter object + * + * Return 1 if pci device state is up and running else return 0. + */ +inline bool +mpt3sas_base_pci_device_is_available(struct MPT3SAS_ADAPTER *ioc) +{ + return !ioc->pci_error_recovery && pci_device_is_present(ioc->pdev); +} + +/** * _base_fault_reset_work - workq handling ioc fault conditions * @work: input argument, used to derive ioc * @@ -6122,6 +6136,11 @@ _base_diag_reset(struct MPT3SAS_ADAPTER *ioc) count = 0; do { + if (!pci_device_is_present(ioc->pdev)) { + ioc->remove_host = 1; + pr_err(MPT3SAS_FMT "Hba Hot unplugged\n", ioc->name); + goto out; + } /* Write magic sequence to WriteSequence register * Loop until in diagnostic mode */ @@ -6853,6 +6872,14 @@ mpt3sas_wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc) ioc->pending_io_count = 0; + if (!mpt3sas_base_pci_device_is_available(ioc)) { + pr_err(MPT3SAS_FMT + "%s: pci error recovery reset or" + " pci device unplug occurred\n", + ioc->name, __func__); + return; + } + ioc_state = mpt3sas_base_get_iocstate(ioc, 0); if ((ioc_state & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL) return; @@ -6899,6 +6926,20 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, /* wait for an active reset in progress to complete */ mutex_lock(&ioc->reset_in_progress_mutex); + if (!mpt3sas_base_pci_device_is_available(ioc)) { + pr_err(MPT3SAS_FMT + "%s: pci error recovery reset or" + " pci device unplug occurred\n", + ioc->name, __func__); + if (!pci_device_is_present(ioc->pdev)) + ioc->schedule_dead_ioc_flush_running_cmds(ioc); + r = 0; + mutex_unlock(&ioc->reset_in_progress_mutex); + goto out_unlocked; + } + + mpt3sas_halt_firmware(ioc); + spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); ioc->shost_recovery = 1; spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 96dc15e..a802ad4 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1474,7 +1474,8 @@ void mpt3sas_base_update_missing_delay(struct MPT3SAS_ADAPTER *ioc, u16 device_missing_delay, u8 io_missing_delay); int mpt3sas_port_enable(struct MPT3SAS_ADAPTER *ioc); - +inline bool mpt3sas_base_pci_device_is_available( + struct MPT3SAS_ADAPTER *ioc); void mpt3sas_wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc); diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 53133cf..566a550 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -2846,9 +2846,19 @@ scsih_abort(struct scsi_cmnd *scmd) "attempting task abort! scmd(%p)\n", scmd); _scsih_tm_display_info(ioc, scmd); + if (!pci_device_is_present(ioc->pdev) || ioc->remove_host) { + sdev_printk(KERN_INFO, scmd->device, "%s scmd(%p)\n", +
[PATCH v3 5/6] mpt3sas: Fix driver modifying NVRAM/persistent data.
* If EEDPTagMode field in manufacturing page11 is set, unset it. This is needed to fix a hardware bug in SAS3/SAS2 cards, So, skipping EEDPTagMode changes in Manufacturing page11 for SAS35 controllers. * Fix driver modifying NVRAM/persistent data in Manufacturing page11 along with current copy. Driver should change only current copy of Manufacturing page11 Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_base.c | 2 +- drivers/scsi/mpt3sas/mpt3sas_config.c | 4 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 55e6fd0..87a67fe 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -4122,7 +4122,7 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc) * flag unset in NVDATA. */ mpt3sas_config_get_manufacturing_pg11(ioc, &mpi_reply, &ioc->manu_pg11); - if (ioc->manu_pg11.EEDPTagMode == 0) { + if ((!ioc->is_gen35_ioc) && (ioc->manu_pg11.EEDPTagMode == 0)) { pr_err("%s: overriding NVDATA EEDPTagMode setting\n", ioc->name); ioc->manu_pg11.EEDPTagMode &= ~0x3; diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/mpt3sas_config.c index 5713a2d..f2a326a 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_config.c +++ b/drivers/scsi/mpt3sas/mpt3sas_config.c @@ -676,10 +676,6 @@ mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc, r = _config_request(ioc, &mpi_request, mpi_reply, MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sizeof(*config_page)); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); out: return r; } -- 1.8.3.1
[PATCH v3 3/6] mpt3sas: Introdude _scsih_get_shost_and_ioc.
The code for getting shost and IOC is redundant so moved that to function "scsih_get_shost_and_ioc". Also checks for NULL are added to IOC and shost. Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 98 ++-- 1 file changed, 82 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 566a550..f6e92eb 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -9809,6 +9809,35 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc) } /** + * _scsih_get_shost_and_ioc - get shost and ioc + * and verify whether they are NULL or not + * @pdev: PCI device struct + * @shost: address of scsi host pointer + * @ioc: address of HBA adapter pointer + * + * Return zero if *shost and *ioc are not NULL otherwise return error number. + */ +static int +_scsih_get_shost_and_ioc(struct pci_dev *pdev, + struct Scsi_Host **shost, struct MPT3SAS_ADAPTER **ioc) +{ + *shost = pci_get_drvdata(pdev); + if (*shost == NULL) { + dev_err(&pdev->dev, "pdev's driver data is null\n"); + return -ENXIO; + } + + *ioc = shost_priv(*shost); + if (*ioc == NULL) { + dev_err(&pdev->dev, "shost's private data is null\n"); + return -ENXIO; + } + + return 0; +} + + +/** * scsih_remove - detach and remove add host * @pdev: PCI device struct * @@ -9816,8 +9845,8 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc) */ static void scsih_remove(struct pci_dev *pdev) { - struct Scsi_Host *shost = pci_get_drvdata(pdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); + struct Scsi_Host *shost = NULL; + struct MPT3SAS_ADAPTER *ioc = NULL; struct _sas_port *mpt3sas_port, *next_port; struct _raid_device *raid_device, *next; struct MPT3SAS_TARGET *sas_target_priv_data; @@ -9825,6 +9854,10 @@ static void scsih_remove(struct pci_dev *pdev) struct workqueue_struct *wq; unsigned long flags; + if (_scsih_get_shost_and_ioc(pdev, &shost, &ioc)) { + dev_err(&pdev->dev, "unable to remove device\n"); + return; + } ioc->remove_host = 1; mpt3sas_wait_for_commands_to_complete(ioc); @@ -9898,11 +9931,16 @@ static void scsih_remove(struct pci_dev *pdev) static void scsih_shutdown(struct pci_dev *pdev) { - struct Scsi_Host *shost = pci_get_drvdata(pdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); + struct Scsi_Host *shost = NULL; + struct MPT3SAS_ADAPTER *ioc = NULL; struct workqueue_struct *wq; unsigned long flags; + if (_scsih_get_shost_and_ioc(pdev, &shost, &ioc)) { + dev_err(&pdev->dev, "unable to shutdown device\n"); + return; + } + ioc->remove_host = 1; mpt3sas_wait_for_commands_to_complete(ioc); @@ -10727,10 +10765,16 @@ out_add_shost_fail: static int scsih_suspend(struct pci_dev *pdev, pm_message_t state) { - struct Scsi_Host *shost = pci_get_drvdata(pdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); + struct Scsi_Host *shost = NULL; + struct MPT3SAS_ADAPTER *ioc = NULL; pci_power_t device_state; + int rc; + rc = _scsih_get_shost_and_ioc(pdev, &shost, &ioc); + if (rc) { + dev_err(&pdev->dev, "unable to suspend device\n"); + return rc; + } mpt3sas_base_stop_watchdog(ioc); flush_scheduled_work(); scsi_block_requests(shost); @@ -10754,11 +10798,17 @@ scsih_suspend(struct pci_dev *pdev, pm_message_t state) static int scsih_resume(struct pci_dev *pdev) { - struct Scsi_Host *shost = pci_get_drvdata(pdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); + struct Scsi_Host *shost = NULL; + struct MPT3SAS_ADAPTER *ioc = NULL; pci_power_t device_state = pdev->current_state; int r; + r = _scsih_get_shost_and_ioc(pdev, &shost, &ioc); + if (r) { + dev_err(&pdev->dev, "unable to resume device\n"); + return r; + } + pr_info(MPT3SAS_FMT "pdev=0x%p, slot=%s, previous operating state [D%d]\n", ioc->name, pdev, pci_name(pdev), device_state); @@ -10790,9 +10840,13 @@ scsih_resume(struct pci_dev *pdev) static pci_ers_result_t scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) { - struct Scsi_Host *shost = pci_get_drvdata(pdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); + struct Scsi_Host *shost = NULL; + struct MPT3SAS_ADAPTER *ioc = NULL; + if (_scsih_get_shost_and_ioc(pdev, &shost, &ioc)) { + dev_err(&pdev->dev, "device unavailable\n"); + return PCI_ERS_RESULT_DISCONNECT; + } pr_info(MPT3SAS_FMT "PCI err
[PATCH v3 6/6] mpt3sas: Bump driver version to 27.100.00.00.
Modify driver version to 27.100.00.00 (which is equivalent to PH8 OOB driver) Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_base.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index f0351a2..b880d79 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -74,8 +74,8 @@ #define MPT3SAS_DRIVER_NAME"mpt3sas" #define MPT3SAS_AUTHOR "Avago Technologies " #define MPT3SAS_DESCRIPTION"LSI MPT Fusion SAS 3.0 Device Driver" -#define MPT3SAS_DRIVER_VERSION "26.100.00.00" -#define MPT3SAS_MAJOR_VERSION 26 +#define MPT3SAS_DRIVER_VERSION "27.100.00.00" +#define MPT3SAS_MAJOR_VERSION 27 #define MPT3SAS_MINOR_VERSION 100 #define MPT3SAS_BUILD_VERSION 0 #define MPT3SAS_RELEASE_VERSION00 -- 1.8.3.1
[PATCH v3 4/6] mpt3sas: Fix Sync cache command failure during driver unload.
This is to fix Sync cache and start stop command failures with DID_NO_CONNECT during driver unload. 1) Release drives first from SML, then remove internally in driver. 2) And allow sync cache and Start stop commands to firmware, even when remove_host flag is set v2 Changeset: Replaced this function mpt3sas_base_pci_device_is_unplugged with pci_device_is_present Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 41 ++-- drivers/scsi/mpt3sas/mpt3sas_transport.c | 7 -- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index f6e92eb..5d15d06 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -3806,6 +3806,43 @@ _scsih_tm_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, return _scsih_check_for_pending_tm(ioc, smid); } +/** _scsih_allow_scmd_to_device - check whether scmd needs to + * issue to IOC or not. + * @ioc: per adapter object + * @scmd: pointer to scsi command object + * + * Returns true if scmd can be issued to IOC otherwise returns false. + */ +inline bool _scsih_allow_scmd_to_device(struct MPT3SAS_ADAPTER *ioc, + struct scsi_cmnd *scmd) +{ + + if (ioc->pci_error_recovery) + return false; + + if (ioc->hba_mpi_version_belonged == MPI2_VERSION) { + if (ioc->remove_host) + return false; + + return true; + } + + + if (ioc->remove_host) { + if (!pci_device_is_present(ioc->pdev)) + return false; + + switch (scmd->cmnd[0]) { + case SYNCHRONIZE_CACHE: + case START_STOP: + return true; + default: + return false; + } + } + + return true; +} /** * _scsih_sas_control_complete - completion routine @@ -4640,7 +4677,7 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd) return 0; } - if (ioc->pci_error_recovery || ioc->remove_host) { + if (!(_scsih_allow_scmd_to_device(ioc, scmd))) { scmd->result = DID_NO_CONNECT << 16; scmd->scsi_done(scmd); return 0; @@ -9874,6 +9911,7 @@ static void scsih_remove(struct pci_dev *pdev) /* release all the volumes */ _scsih_ir_shutdown(ioc); + sas_remove_host(shost); list_for_each_entry_safe(raid_device, next, &ioc->raid_device_list, list) { if (raid_device->starget) { @@ -9916,7 +9954,6 @@ static void scsih_remove(struct pci_dev *pdev) ioc->sas_hba.num_phys = 0; } - sas_remove_host(shost); mpt3sas_base_detach(ioc); spin_lock(&gioc_lock); list_del(&ioc->list); diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c index b10d73e..742da74 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_transport.c +++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c @@ -817,10 +817,13 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, mpt3sas_port->remote_identify.sas_address, mpt3sas_phy->phy_id); mpt3sas_phy->phy_belongs_to_port = 0; - sas_port_delete_phy(mpt3sas_port->port, mpt3sas_phy->phy); + if (!ioc->remove_host) + sas_port_delete_phy(mpt3sas_port->port, + mpt3sas_phy->phy); list_del(&mpt3sas_phy->port_siblings); } - sas_port_delete(mpt3sas_port->port); + if (!ioc->remove_host) + sas_port_delete(mpt3sas_port->port); kfree(mpt3sas_port); } -- 1.8.3.1