From: Sreekanth Reddy sreekanth.reddy@broadcom.com
Commit 324c122fc0a41d258239c853854eefd186ae1290 upstream.
Add module parameter multipath_on_hba to enable/disable multi-port path topology support. By default this feature is enabled on SAS3.5 HBA device and disabled on SAS3 &SAS2.5 HBA devices.
When this feature is disabled then driver uses a default PhysicalPort(PortID) number i.e. 255 instead of the PhysicalPort number provided by HBA firmware.
Link: https://lore.kernel.org/r/20201027130847.9962-14-sreekanth.reddy@broadcom.co... Signed-off-by: Sreekanth Reddy sreekanth.reddy@broadcom.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Integrated-by: Siyu Zhang siyu.zhang@windriver.com --- drivers/scsi/mpt3sas/mpt3sas_base.h | 2 + drivers/scsi/mpt3sas/mpt3sas_ctl.c | 6 ++- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 69 ++++++++++++++++++++++-- drivers/scsi/mpt3sas/mpt3sas_transport.c | 6 ++- 4 files changed, 76 insertions(+), 7 deletions(-)
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 372b9e95f14a..13c27f54209a 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1246,6 +1246,7 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc); * which ensures the syncrhonization between cli/sysfs_show path. * @atomic_desc_capable: Atomic Request Descriptor support. * @GET_MSIX_INDEX: Get the msix index of high iops queues. + * @multipath_on_hba: flag to determine multipath on hba is enabled or not * @port_table_list: list containing HBA's wide/narrow port's info */ struct MPT3SAS_ADAPTER { @@ -1540,6 +1541,7 @@ struct MPT3SAS_ADAPTER { PUT_SMID_DEFAULT put_smid_default; GET_MSIX_INDEX get_msix_index_for_smlio;
+ u8 multipath_on_hba; struct list_head port_table_list; };
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index edd26a2570fa..c8a0ce18f2c5 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -902,8 +902,10 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, (Mpi2SmpPassthroughRequest_t *)mpi_request; u8 *data;
- /* ioc determines which port to use */ - smp_request->PhysicalPort = 0xFF; + if (!ioc->multipath_on_hba) { + /* ioc determines which port to use */ + smp_request->PhysicalPort = 0xFF; + } if (smp_request->PassthroughFlags & MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE) data = (u8 *)&smp_request->SGL; diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 91fcead16599..60893248efad 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -159,6 +159,15 @@ module_param(enable_sdev_max_qd, bool, 0444); MODULE_PARM_DESC(enable_sdev_max_qd, "Enable sdev max qd as can_queue, def=disabled(0)");
+static int multipath_on_hba = -1; +module_param(multipath_on_hba, int, 0); +MODULE_PARM_DESC(multipath_on_hba, + "Multipath support to add same target device\n\t\t" + "as many times as it is visible to HBA from various paths\n\t\t" + "(by default:\n\t\t" + "\t SAS 2.0 & SAS 3.0 HBA - This will be disabled,\n\t\t" + "\t SAS 3.5 HBA - This will be enabled)"); + /* raid transport support */ static struct raid_template *mpt3sas_raid_template; static struct raid_template *mpt2sas_raid_template; @@ -373,6 +382,14 @@ mpt3sas_get_port_by_id(struct MPT3SAS_ADAPTER *ioc, { struct hba_port *port, *port_next;
+ /* + * When multipath_on_hba is disabled then + * search the hba_port entry using default + * port id i.e. 255 + */ + if (!ioc->multipath_on_hba) + port_id = MULTIPATH_DISABLED_PORT_ID; + list_for_each_entry_safe(port, port_next, &ioc->port_table_list, list) { if (port->port_id != port_id) @@ -384,6 +401,24 @@ mpt3sas_get_port_by_id(struct MPT3SAS_ADAPTER *ioc, return port; }
+ /* + * Allocate hba_port object for default port id (i.e. 255) + * when multipath_on_hba is disabled for the HBA. + * And add this object to port_table_list. + */ + if (!ioc->multipath_on_hba) { + port = kzalloc(sizeof(struct hba_port), GFP_KERNEL); + if (!port) + return NULL; + + port->port_id = port_id; + ioc_info(ioc, + "hba_port entry: %p, port: %d is added to hba_port list\n", + port, port->port_id); + list_add_tail(&port->list, + &ioc->port_table_list); + return port; + } return NULL; }
@@ -10038,6 +10073,7 @@ _scsih_search_responding_expanders(struct MPT3SAS_ADAPTER *ioc) u16 ioc_status; u64 sas_address; u16 handle; + u8 port;
ioc_info(ioc, "search for expanders: start\n");
@@ -10055,10 +10091,12 @@ _scsih_search_responding_expanders(struct MPT3SAS_ADAPTER *ioc)
handle = le16_to_cpu(expander_pg0.DevHandle); sas_address = le64_to_cpu(expander_pg0.SASAddress); + port = expander_pg0.PhysicalPort; pr_info( "\texpander present: handle(0x%04x), sas_addr(0x%016llx), port:%d\n", handle, (unsigned long long)sas_address, - expander_pg0.PhysicalPort); + (ioc->multipath_on_hba ? + port : MULTIPATH_DISABLED_PORT_ID)); _scsih_mark_responding_expander(ioc, &expander_pg0); }
@@ -10501,8 +10539,10 @@ mpt3sas_scsih_reset_done_handler(struct MPT3SAS_ADAPTER *ioc) dtmprintk(ioc, ioc_info(ioc, "%s: MPT3_IOC_DONE_RESET\n", __func__)); if ((!ioc->is_driver_loading) && !(disable_discovery > 0 && !ioc->sas_hba.num_phys)) { - _scsih_sas_port_refresh(ioc); - _scsih_update_vphys_after_reset(ioc); + if (ioc->multipath_on_hba) { + _scsih_sas_port_refresh(ioc); + _scsih_update_vphys_after_reset(ioc); + } _scsih_prep_device_scan(ioc); _scsih_create_enclosure_list_after_reset(ioc); _scsih_search_responding_sas_devices(ioc); @@ -11796,6 +11836,12 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS; break; } + + if (multipath_on_hba == -1 || multipath_on_hba == 0) + ioc->multipath_on_hba = 0; + else + ioc->multipath_on_hba = 1; + break; case MPI25_VERSION: case MPI26_VERSION: @@ -11857,6 +11903,23 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc->combined_reply_index_count = MPT3_SUP_REPLY_POST_HOST_INDEX_REG_COUNT_G3; } + + switch (ioc->is_gen35_ioc) { + case 0: + if (multipath_on_hba == -1 || multipath_on_hba == 0) + ioc->multipath_on_hba = 0; + else + ioc->multipath_on_hba = 1; + break; + case 1: + if (multipath_on_hba == -1 || multipath_on_hba > 0) + ioc->multipath_on_hba = 1; + else + ioc->multipath_on_hba = 0; + default: + break; + } + break; default: return -ENODEV; diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c index 0d06025d7102..6f4708224755 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_transport.c +++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c @@ -912,7 +912,8 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, return; }
- if (sas_node->handle <= ioc->sas_hba.num_phys) { + if (sas_node->handle <= ioc->sas_hba.num_phys && + (ioc->multipath_on_hba)) { if (port->vphys_mask) { list_for_each_entry_safe(vphy, vphy_next, &port->vphys_list, list) { @@ -1172,7 +1173,8 @@ mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc, if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) { _transport_set_identify(ioc, handle, &mpt3sas_phy->remote_identify); - if (sas_node->handle <= ioc->sas_hba.num_phys) { + if ((sas_node->handle <= ioc->sas_hba.num_phys) && + (ioc->multipath_on_hba)) { list_for_each_entry(hba_port, &ioc->port_table_list, list) { if (hba_port->sas_address == sas_address &&