scsi: mpt3sas: Add module parameter multipath_on_hba

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.com
Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Sreekanth Reddy 2020-10-27 18:38:46 +05:30 committed by Martin K. Petersen
parent ffa381d637
commit 324c122fc0
4 changed files with 76 additions and 7 deletions

View File

@ -1246,6 +1246,7 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
* which ensures the syncrhonization between cli/sysfs_show path. * which ensures the syncrhonization between cli/sysfs_show path.
* @atomic_desc_capable: Atomic Request Descriptor support. * @atomic_desc_capable: Atomic Request Descriptor support.
* @GET_MSIX_INDEX: Get the msix index of high iops queues. * @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 * @port_table_list: list containing HBA's wide/narrow port's info
*/ */
struct MPT3SAS_ADAPTER { struct MPT3SAS_ADAPTER {
@ -1540,6 +1541,7 @@ struct MPT3SAS_ADAPTER {
PUT_SMID_DEFAULT put_smid_default; PUT_SMID_DEFAULT put_smid_default;
GET_MSIX_INDEX get_msix_index_for_smlio; GET_MSIX_INDEX get_msix_index_for_smlio;
u8 multipath_on_hba;
struct list_head port_table_list; struct list_head port_table_list;
}; };

View File

@ -902,8 +902,10 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
(Mpi2SmpPassthroughRequest_t *)mpi_request; (Mpi2SmpPassthroughRequest_t *)mpi_request;
u8 *data; u8 *data;
/* ioc determines which port to use */ if (!ioc->multipath_on_hba) {
smp_request->PhysicalPort = 0xFF; /* ioc determines which port to use */
smp_request->PhysicalPort = 0xFF;
}
if (smp_request->PassthroughFlags & if (smp_request->PassthroughFlags &
MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE) MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE)
data = (u8 *)&smp_request->SGL; data = (u8 *)&smp_request->SGL;

View File

@ -159,6 +159,15 @@ module_param(enable_sdev_max_qd, bool, 0444);
MODULE_PARM_DESC(enable_sdev_max_qd, MODULE_PARM_DESC(enable_sdev_max_qd,
"Enable sdev max qd as can_queue, def=disabled(0)"); "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 */ /* raid transport support */
static struct raid_template *mpt3sas_raid_template; static struct raid_template *mpt3sas_raid_template;
static struct raid_template *mpt2sas_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; 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, list_for_each_entry_safe(port, port_next,
&ioc->port_table_list, list) { &ioc->port_table_list, list) {
if (port->port_id != port_id) if (port->port_id != port_id)
@ -384,6 +401,24 @@ mpt3sas_get_port_by_id(struct MPT3SAS_ADAPTER *ioc,
return port; 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; return NULL;
} }
@ -10014,6 +10049,7 @@ _scsih_search_responding_expanders(struct MPT3SAS_ADAPTER *ioc)
u16 ioc_status; u16 ioc_status;
u64 sas_address; u64 sas_address;
u16 handle; u16 handle;
u8 port;
ioc_info(ioc, "search for expanders: start\n"); ioc_info(ioc, "search for expanders: start\n");
@ -10031,10 +10067,12 @@ _scsih_search_responding_expanders(struct MPT3SAS_ADAPTER *ioc)
handle = le16_to_cpu(expander_pg0.DevHandle); handle = le16_to_cpu(expander_pg0.DevHandle);
sas_address = le64_to_cpu(expander_pg0.SASAddress); sas_address = le64_to_cpu(expander_pg0.SASAddress);
port = expander_pg0.PhysicalPort;
pr_info( pr_info(
"\texpander present: handle(0x%04x), sas_addr(0x%016llx), port:%d\n", "\texpander present: handle(0x%04x), sas_addr(0x%016llx), port:%d\n",
handle, (unsigned long long)sas_address, 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); _scsih_mark_responding_expander(ioc, &expander_pg0);
} }
@ -10477,8 +10515,10 @@ mpt3sas_scsih_reset_done_handler(struct MPT3SAS_ADAPTER *ioc)
dtmprintk(ioc, ioc_info(ioc, "%s: MPT3_IOC_DONE_RESET\n", __func__)); dtmprintk(ioc, ioc_info(ioc, "%s: MPT3_IOC_DONE_RESET\n", __func__));
if ((!ioc->is_driver_loading) && !(disable_discovery > 0 && if ((!ioc->is_driver_loading) && !(disable_discovery > 0 &&
!ioc->sas_hba.num_phys)) { !ioc->sas_hba.num_phys)) {
_scsih_sas_port_refresh(ioc); if (ioc->multipath_on_hba) {
_scsih_update_vphys_after_reset(ioc); _scsih_sas_port_refresh(ioc);
_scsih_update_vphys_after_reset(ioc);
}
_scsih_prep_device_scan(ioc); _scsih_prep_device_scan(ioc);
_scsih_create_enclosure_list_after_reset(ioc); _scsih_create_enclosure_list_after_reset(ioc);
_scsih_search_responding_sas_devices(ioc); _scsih_search_responding_sas_devices(ioc);
@ -11766,6 +11806,12 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS; ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS;
break; break;
} }
if (multipath_on_hba == -1 || multipath_on_hba == 0)
ioc->multipath_on_hba = 0;
else
ioc->multipath_on_hba = 1;
break; break;
case MPI25_VERSION: case MPI25_VERSION:
case MPI26_VERSION: case MPI26_VERSION:
@ -11827,6 +11873,23 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->combined_reply_index_count = ioc->combined_reply_index_count =
MPT3_SUP_REPLY_POST_HOST_INDEX_REG_COUNT_G3; 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; break;
default: default:
return -ENODEV; return -ENODEV;

View File

@ -912,7 +912,8 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
return; 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) { if (port->vphys_mask) {
list_for_each_entry_safe(vphy, vphy_next, list_for_each_entry_safe(vphy, vphy_next,
&port->vphys_list, list) { &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)) { if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) {
_transport_set_identify(ioc, handle, _transport_set_identify(ioc, handle,
&mpt3sas_phy->remote_identify); &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, list_for_each_entry(hba_port,
&ioc->port_table_list, list) { &ioc->port_table_list, list) {
if (hba_port->sas_address == sas_address && if (hba_port->sas_address == sas_address &&