All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/14] mpt3sas: Add support for multi-port path topology
@ 2020-10-09 17:14 Sreekanth Reddy
  2020-10-09 17:14 ` [PATCH 01/14] mpt3sas: Define hba_port structure Sreekanth Reddy
                   ` (13 more replies)
  0 siblings, 14 replies; 18+ messages in thread
From: Sreekanth Reddy @ 2020-10-09 17:14 UTC (permalink / raw)
  To: martin.petersen
  Cc: linux-scsi, sathya.prakash, suganath-prabu.subramani, Sreekanth Reddy

[-- Attachment #1: Type: text/plain, Size: 4278 bytes --]

Multi-port path topology example:
    
         Zone 1             Zone 2
 |-----------------|   |----------------|
 |  HD1 ..... HD25 |   | HD26 ......HD50|
 | |==================================| |
 | |               |   |              | |
 | |              Expander            | |
 | |==================================| |
 |           |     |   |    |           |
 |-----------|-----|   |----|-----------|
           x8|              |x8 
      _______|______________|_______
      |            HBA             |
      |____________________________|

In this topology, zoning is enabled in such a way that drives from HD1
to HD25 are accessible only through zone1 and drives from HD26 to HD50 are
accessible only through zone2. Here the first x8 connection bw HBA to
Expander in zone1 will have one PortID and second x8 connection bw HBA to
Expander in Zone2 will another PortID.

Problem statement:
When zoning is enabled in expander then we will have two expander
instances (for a single real expander), one instance is accessible through
the first x8 connection and second instance is accessible through
second x8 connection from HBA. But for both the instances the
SAS Address of the expander will be the same.
But in current mpt3sas driver, driver add's only one expander instance,
when second expander instance's 'add' event comes then driver ignores
this event assumues that it is duplicate instance as it already
has a sas_expander object in it's sas_expander_list list with
the same SAS Address. So in this topology users will see only 25 drives
instead of 50 drives.

Current mpt3sas driver use ‘SAS Address’ as a key to uniquely identify
the End devices or Expander devices, but on the multi-port path topologies
(such as above topology) HBA firmware will provide multiple device entries
with different Device handles for a single device.
So here driver can't use ‘SAS Address’ as a key instead driver can use
‘SAS Address’ & ‘PhysicalPort (i.e. PortID)’ number as key to uniquely
identify the device.

where, PhysicalPort is a HBA port number through which the device is
accessible.

Solution:
Now driver uses both 'SAS Address' & 'PhysicalPort' number as a key to
uniquely identify the device object from the corresponding device
list's. So, when 'add' event comes for second instance of expander,
now driver can't find the sas_expander object with same 'SAS Address' &
'PhysicalPort' number (since for this second instance PhysicalPort
number will be different from first instance's PhysicalPort number)
from the sas_expander_list list. So the driver processes this event and
will create a new sas_expander object for this expander instance
and adds it sas_expander_list.
With this solution, the driver will have two sas_expander objects, one
object is for the first instance of the expander, another object is for
second instance of the driver. Now users will access all 50 drives from
above topology.

Like device SAS Address, PhysicalPort number is readily available
from below config pages,
* SAS IO Unit Page 0,
* SAS Device Page 0,
* SAS Expander Page 0,
* SAS Phy Page 0, etc

Through this patch set, the driver now manages the sas_device &
sas_expander objects using 'SAS Address' & 'PhysicalPort'
number as key.

Sreekanth Reddy (14):
  mpt3sas: Define hba_port structure
  mpt3sas: Allocate memory for hba_port objects
  mpt3sas: Rearrange _scsih_mark_responding_sas_device()
  mpt3sas: Update hba_port's sas_address & phy_mask
  mpt3sas: Get device objects using sas_address & portID
  mpt3sas: Rename transport_del_phy_from_an_existing_port
  mpt3sas: Get sas_device objects using device's rphy
  mpt3sas: Update hba_port objects after host reset
  mpt3sas: Set valid PhysicalPort in SMPPassThrough
  mpt3sas: Handling HBA vSES device
  mpt3sas: Add bypass_dirty_port_flag parameter
  mpt3sas: Handle vSES vphy object during HBA reset
  mpt3sas: add module parameter multipath_on_hba
  mpt3sas: Bump driver version to 35.101.00.00

 drivers/scsi/mpt3sas/mpt3sas_base.h      |  102 +-
 drivers/scsi/mpt3sas/mpt3sas_ctl.c       |    6 +-
 drivers/scsi/mpt3sas/mpt3sas_scsih.c     | 1237 +++++++++++++++++++---
 drivers/scsi/mpt3sas/mpt3sas_transport.c |  312 +++++-
 4 files changed, 1455 insertions(+), 202 deletions(-)

-- 
2.18.4


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4175 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 01/14] mpt3sas: Define hba_port structure
  2020-10-09 17:14 [PATCH 00/14] mpt3sas: Add support for multi-port path topology Sreekanth Reddy
@ 2020-10-09 17:14 ` Sreekanth Reddy
  2020-10-09 17:14 ` [PATCH 02/14] mpt3sas: Allocate memory for hba_port objects Sreekanth Reddy
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 18+ messages in thread
From: Sreekanth Reddy @ 2020-10-09 17:14 UTC (permalink / raw)
  To: martin.petersen
  Cc: linux-scsi, sathya.prakash, suganath-prabu.subramani, Sreekanth Reddy

[-- Attachment #1: Type: text/plain, Size: 4845 bytes --]

Defined a new hba_port structure with hold below variables,
- port_id       : Port ID of the narrow/wide port of the HBA
- sas_address   : SAS Address of the remote device that is
                  attached to the current HBA port
- phy_mask      : HBA’s phy bits to which above SAS addressed
                  device is attached
- flags         : this field is used to refresh this port details
                  during HBA reset.

Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.h | 35 ++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
index bc8beb1..2dde574 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -420,6 +420,7 @@ struct Mpi2ManufacturingPage11_t {
  * @flags: MPT_TARGET_FLAGS_XXX flags
  * @deleted: target flaged for deletion
  * @tm_busy: target is busy with TM request.
+ * @port: hba port entry containing target's port number info
  * @sas_dev: The sas_device associated with this target
  * @pcie_dev: The pcie device associated with this target
  */
@@ -432,6 +433,7 @@ struct MPT3SAS_TARGET {
 	u32	flags;
 	u8	deleted;
 	u8	tm_busy;
+	struct hba_port *port;
 	struct _sas_device *sas_dev;
 	struct _pcie_device *pcie_dev;
 };
@@ -534,6 +536,7 @@ struct _internal_cmd {
  *	addition routine.
  * @chassis_slot: chassis slot
  * @is_chassis_slot_valid: chassis slot valid or not
+ * @port: hba port entry containing device's port number info
  */
 struct _sas_device {
 	struct list_head list;
@@ -560,6 +563,7 @@ struct _sas_device {
 	u8	is_chassis_slot_valid;
 	u8	connector_name[5];
 	struct kref refcount;
+	struct hba_port *port;
 };
 
 static inline void sas_device_get(struct _sas_device *s)
@@ -730,6 +734,7 @@ struct _boot_device {
  * @remote_identify: attached device identification
  * @rphy: sas transport rphy object
  * @port: sas transport wide/narrow port object
+ * @hba_port: hba port entry containing port's port number info
  * @phy_list: _sas_phy list objects belonging to this port
  */
 struct _sas_port {
@@ -738,6 +743,7 @@ struct _sas_port {
 	struct sas_identify remote_identify;
 	struct sas_rphy *rphy;
 	struct sas_port *port;
+	struct hba_port *hba_port;
 	struct list_head phy_list;
 };
 
@@ -751,6 +757,7 @@ struct _sas_port {
  * @handle: device handle for this phy
  * @attached_handle: device handle for attached device
  * @phy_belongs_to_port: port has been created for this phy
+ * @port: hba port entry containing port number info
  */
 struct _sas_phy {
 	struct list_head port_siblings;
@@ -761,6 +768,7 @@ struct _sas_phy {
 	u16	handle;
 	u16	attached_handle;
 	u8	phy_belongs_to_port;
+	struct hba_port *port;
 };
 
 /**
@@ -776,6 +784,7 @@ struct _sas_phy {
  * @responding: used in _scsih_expander_device_mark_responding
  * @phy: a list of phys that make up this sas_host/expander
  * @sas_port_list: list of ports attached to this sas_host/expander
+ * @port: hba port entry containing node's port number info
  */
 struct _sas_node {
 	struct list_head list;
@@ -787,11 +796,11 @@ struct _sas_node {
 	u16	enclosure_handle;
 	u64	enclosure_logical_id;
 	u8	responding;
+	struct hba_port *port;
 	struct	_sas_phy *phy;
 	struct list_head sas_port_list;
 };
 
-
 /**
  * struct _enclosure_node - enclosure information
  * @list: list of enclosures
@@ -1009,6 +1018,27 @@ struct reply_post_struct {
 	dma_addr_t			reply_post_free_dma;
 };
 
+/**
+ * struct hba_port - Saves each HBA's Wide/Narrow port info
+ * @sas_address: sas address of this wide/narrow port's attached device
+ * @phy_mask: HBA PHY's belonging to this port
+ * @port_id: port number
+ * @flags: hba port flags
+ */
+struct hba_port {
+	struct list_head list;
+	u64	sas_address;
+	u32	phy_mask;
+	u8      port_id;
+	u8	flags;
+};
+
+/* hba port flags */
+#define HBA_PORT_FLAG_DIRTY_PORT       0x01
+#define HBA_PORT_FLAG_NEW_PORT         0x02
+
+#define MULTIPATH_DISABLED_PORT_ID     0xFF
+
 typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
 /**
  * struct MPT3SAS_ADAPTER - per adapter struct
@@ -1191,6 +1221,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.
+ * @port_table_list: list containing HBA's wide/narrow port's info
  */
 struct MPT3SAS_ADAPTER {
 	struct list_head list;
@@ -1483,6 +1514,8 @@ struct MPT3SAS_ADAPTER {
 	PUT_SMID_IO_FP_HIP put_smid_hi_priority;
 	PUT_SMID_DEFAULT put_smid_default;
 	GET_MSIX_INDEX get_msix_index_for_smlio;
+
+	struct list_head port_table_list;
 };
 
 struct mpt3sas_debugfs_buffer {
-- 
2.18.4


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4175 bytes --]

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 02/14] mpt3sas: Allocate memory for hba_port objects
  2020-10-09 17:14 [PATCH 00/14] mpt3sas: Add support for multi-port path topology Sreekanth Reddy
  2020-10-09 17:14 ` [PATCH 01/14] mpt3sas: Define hba_port structure Sreekanth Reddy
@ 2020-10-09 17:14 ` Sreekanth Reddy
  2020-10-09 17:14 ` [PATCH 03/14] mpt3sas: Rearrange _scsih_mark_responding_sas_device() Sreekanth Reddy
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 18+ messages in thread
From: Sreekanth Reddy @ 2020-10-09 17:14 UTC (permalink / raw)
  To: martin.petersen
  Cc: linux-scsi, sathya.prakash, suganath-prabu.subramani, Sreekanth Reddy

[-- Attachment #1: Type: text/plain, Size: 5162 bytes --]

Allocate hba_port object whenever a new HBA's wide/narrow
port is identified while processing the SASIOUnitPage0's
phy data and add this object to port_table_list.
And deallocate these objects during driver unload.

Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 73 ++++++++++++++++++++++++++--
 1 file changed, 69 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index db9c816..a40fa7e 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -356,6 +356,30 @@ _scsih_srch_boot_encl_slot(u64 enclosure_logical_id, u16 slot_number,
 	    SlotNumber)) ? 1 : 0;
 }
 
+/**
+ * mpt3sas_get_port_by_id - get hba port entry corresponding to provided
+ *			  port number from port list
+ * @ioc: per adapter object
+ * @port_id: port number
+ *
+ * Search for hba port entry corresponding to provided port number,
+ * if available return port object otherwise return NULL.
+ */
+struct hba_port *
+mpt3sas_get_port_by_id(struct MPT3SAS_ADAPTER *ioc, u8 port_id)
+{
+	struct hba_port *port, *port_next;
+
+	list_for_each_entry_safe(port, port_next,
+	    &ioc->port_table_list, list) {
+		if (port->port_id == port_id &&
+		    !(port->flags & HBA_PORT_FLAG_DIRTY_PORT))
+			return port;
+	}
+
+	return NULL;
+}
+
 /**
  * _scsih_is_boot_device - search for matching boot device.
  * @sas_address: sas address
@@ -5732,7 +5756,8 @@ _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc)
 	Mpi2ConfigReply_t mpi_reply;
 	Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
 	u16 attached_handle;
-	u8 link_rate;
+	u8 link_rate, port_id;
+	struct hba_port *port;
 
 	dtmprintk(ioc,
 		  ioc_info(ioc, "updating handles for sas_host(0x%016llx)\n",
@@ -5756,13 +5781,28 @@ _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc)
 	for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
 		link_rate = sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4;
 		if (i == 0)
-			ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
-			    PhyData[0].ControllerDevHandle);
+			ioc->sas_hba.handle = le16_to_cpu(
+			    sas_iounit_pg0->PhyData[0].ControllerDevHandle);
+		port_id = sas_iounit_pg0->PhyData[i].Port;
+		if (!(mpt3sas_get_port_by_id(ioc, port_id))) {
+			port = kzalloc(sizeof(struct hba_port), GFP_KERNEL);
+			if (!port)
+				goto out;
+
+			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);
+			if (ioc->shost_recovery)
+				port->flags = HBA_PORT_FLAG_NEW_PORT;
+			list_add_tail(&port->list, &ioc->port_table_list);
+		}
 		ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
 		attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i].
 		    AttachedDevHandle);
 		if (attached_handle && link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
 			link_rate = MPI2_SAS_NEG_LINK_RATE_1_5;
+		ioc->sas_hba.phy[i].port = mpt3sas_get_port_by_id(ioc, port_id);
 		mpt3sas_transport_update_links(ioc, ioc->sas_hba.sas_address,
 		    attached_handle, i, link_rate);
 	}
@@ -5789,7 +5829,8 @@ _scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc)
 	u16 ioc_status;
 	u16 sz;
 	u8 device_missing_delay;
-	u8 num_phys;
+	u8 num_phys, port_id;
+	struct hba_port *port;
 
 	mpt3sas_config_get_number_hba_phys(ioc, &num_phys);
 	if (!num_phys) {
@@ -5882,8 +5923,24 @@ _scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc)
 		if (i == 0)
 			ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
 			    PhyData[0].ControllerDevHandle);
+
+		port_id = sas_iounit_pg0->PhyData[i].Port;
+		if (!(mpt3sas_get_port_by_id(ioc, port_id))) {
+			port = kzalloc(sizeof(struct hba_port), GFP_KERNEL);
+			if (!port)
+				goto out;
+
+			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);
+		}
+
 		ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
 		ioc->sas_hba.phy[i].phy_id = i;
+		ioc->sas_hba.phy[i].port = mpt3sas_get_port_by_id(ioc, port_id);
 		mpt3sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i],
 		    phy_pg0, ioc->sas_hba.parent_dev);
 	}
@@ -10136,6 +10193,7 @@ static void scsih_remove(struct pci_dev *pdev)
 	struct workqueue_struct	*wq;
 	unsigned long flags;
 	Mpi2ConfigReply_t mpi_reply;
+	struct hba_port *port, *port_next;
 
 	if (_scsih_get_shost_and_ioc(pdev, &shost, &ioc))
 		return;
@@ -10198,6 +10256,12 @@ static void scsih_remove(struct pci_dev *pdev)
 			    mpt3sas_port->remote_identify.sas_address);
 	}
 
+	list_for_each_entry_safe(port, port_next,
+	    &ioc->port_table_list, list) {
+		list_del(&port->list);
+		kfree(port);
+	}
+
 	/* free phys attached to the sas_host */
 	if (ioc->sas_hba.num_phys) {
 		kfree(ioc->sas_hba.phy);
@@ -10987,6 +11051,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	INIT_LIST_HEAD(&ioc->delayed_event_ack_list);
 	INIT_LIST_HEAD(&ioc->delayed_tr_volume_list);
 	INIT_LIST_HEAD(&ioc->reply_queue_list);
+	INIT_LIST_HEAD(&ioc->port_table_list);
 
 	sprintf(ioc->name, "%s_cm%d", ioc->driver_name, ioc->id);
 
-- 
2.18.4


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4175 bytes --]

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 03/14] mpt3sas: Rearrange _scsih_mark_responding_sas_device()
  2020-10-09 17:14 [PATCH 00/14] mpt3sas: Add support for multi-port path topology Sreekanth Reddy
  2020-10-09 17:14 ` [PATCH 01/14] mpt3sas: Define hba_port structure Sreekanth Reddy
  2020-10-09 17:14 ` [PATCH 02/14] mpt3sas: Allocate memory for hba_port objects Sreekanth Reddy
@ 2020-10-09 17:14 ` Sreekanth Reddy
  2020-10-09 17:14 ` [PATCH 04/14] mpt3sas: Update hba_port's sas_address & phy_mask Sreekanth Reddy
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 18+ messages in thread
From: Sreekanth Reddy @ 2020-10-09 17:14 UTC (permalink / raw)
  To: martin.petersen
  Cc: linux-scsi, sathya.prakash, suganath-prabu.subramani, Sreekanth Reddy

[-- Attachment #1: Type: text/plain, Size: 4962 bytes --]

Rearrange _scsih_mark_responding_sas_device function for better
code management. No functional change.

Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 116 +++++++++++++--------------
 1 file changed, 58 insertions(+), 58 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index a40fa7e..e8ffe1e 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -8742,69 +8742,69 @@ Mpi2SasDevicePage0_t *sas_device_pg0)
 	}
 	spin_lock_irqsave(&ioc->sas_device_lock, flags);
 	list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
-		if ((sas_device->sas_address == le64_to_cpu(
-		    sas_device_pg0->SASAddress)) && (sas_device->slot ==
-		    le16_to_cpu(sas_device_pg0->Slot))) {
-			sas_device->responding = 1;
-			starget = sas_device->starget;
-			if (starget && starget->hostdata) {
-				sas_target_priv_data = starget->hostdata;
-				sas_target_priv_data->tm_busy = 0;
-				sas_target_priv_data->deleted = 0;
-			} else
-				sas_target_priv_data = NULL;
-			if (starget) {
-				starget_printk(KERN_INFO, starget,
-				    "handle(0x%04x), sas_addr(0x%016llx)\n",
-				    le16_to_cpu(sas_device_pg0->DevHandle),
-				    (unsigned long long)
-				    sas_device->sas_address);
+		if (sas_device->sas_address != le64_to_cpu(
+		    sas_device_pg0->SASAddress))
+			continue;
+		if (sas_device->slot != le16_to_cpu(sas_device_pg0->Slot))
+			continue;
+		sas_device->responding = 1;
+		starget = sas_device->starget;
+		if (starget && starget->hostdata) {
+			sas_target_priv_data = starget->hostdata;
+			sas_target_priv_data->tm_busy = 0;
+			sas_target_priv_data->deleted = 0;
+		} else
+			sas_target_priv_data = NULL;
+		if (starget) {
+			starget_printk(KERN_INFO, starget,
+			    "handle(0x%04x), sas_addr(0x%016llx)\n",
+			    le16_to_cpu(sas_device_pg0->DevHandle),
+			    (unsigned long long)
+			    sas_device->sas_address);
 
-				if (sas_device->enclosure_handle != 0)
-					starget_printk(KERN_INFO, starget,
-					 "enclosure logical id(0x%016llx),"
-					 " slot(%d)\n",
-					 (unsigned long long)
-					 sas_device->enclosure_logical_id,
-					 sas_device->slot);
-			}
-			if (le16_to_cpu(sas_device_pg0->Flags) &
-			      MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
-				sas_device->enclosure_level =
-				   sas_device_pg0->EnclosureLevel;
-				memcpy(&sas_device->connector_name[0],
-					&sas_device_pg0->ConnectorName[0], 4);
-			} else {
-				sas_device->enclosure_level = 0;
-				sas_device->connector_name[0] = '\0';
-			}
+			if (sas_device->enclosure_handle != 0)
+				starget_printk(KERN_INFO, starget,
+				 "enclosure logical id(0x%016llx), slot(%d)\n",
+				 (unsigned long long)
+				 sas_device->enclosure_logical_id,
+				 sas_device->slot);
+		}
+		if (le16_to_cpu(sas_device_pg0->Flags) &
+		      MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
+			sas_device->enclosure_level =
+			   sas_device_pg0->EnclosureLevel;
+			memcpy(&sas_device->connector_name[0],
+				&sas_device_pg0->ConnectorName[0], 4);
+		} else {
+			sas_device->enclosure_level = 0;
+			sas_device->connector_name[0] = '\0';
+		}
 
-			sas_device->enclosure_handle =
-				le16_to_cpu(sas_device_pg0->EnclosureHandle);
-			sas_device->is_chassis_slot_valid = 0;
-			if (enclosure_dev) {
-				sas_device->enclosure_logical_id = le64_to_cpu(
-					enclosure_dev->pg0.EnclosureLogicalID);
-				if (le16_to_cpu(enclosure_dev->pg0.Flags) &
-				    MPI2_SAS_ENCLS0_FLAGS_CHASSIS_SLOT_VALID) {
-					sas_device->is_chassis_slot_valid = 1;
-					sas_device->chassis_slot =
-						enclosure_dev->pg0.ChassisSlot;
-				}
+		sas_device->enclosure_handle =
+			le16_to_cpu(sas_device_pg0->EnclosureHandle);
+		sas_device->is_chassis_slot_valid = 0;
+		if (enclosure_dev) {
+			sas_device->enclosure_logical_id = le64_to_cpu(
+				enclosure_dev->pg0.EnclosureLogicalID);
+			if (le16_to_cpu(enclosure_dev->pg0.Flags) &
+			    MPI2_SAS_ENCLS0_FLAGS_CHASSIS_SLOT_VALID) {
+				sas_device->is_chassis_slot_valid = 1;
+				sas_device->chassis_slot =
+					enclosure_dev->pg0.ChassisSlot;
 			}
+		}
 
-			if (sas_device->handle == le16_to_cpu(
-			    sas_device_pg0->DevHandle))
-				goto out;
-			pr_info("\thandle changed from(0x%04x)!!!\n",
-			    sas_device->handle);
-			sas_device->handle = le16_to_cpu(
-			    sas_device_pg0->DevHandle);
-			if (sas_target_priv_data)
-				sas_target_priv_data->handle =
-				    le16_to_cpu(sas_device_pg0->DevHandle);
+		if (sas_device->handle == le16_to_cpu(
+		    sas_device_pg0->DevHandle))
 			goto out;
-		}
+		pr_info("\thandle changed from(0x%04x)!!!\n",
+		    sas_device->handle);
+		sas_device->handle = le16_to_cpu(
+		    sas_device_pg0->DevHandle);
+		if (sas_target_priv_data)
+			sas_target_priv_data->handle =
+			    le16_to_cpu(sas_device_pg0->DevHandle);
+		goto out;
 	}
  out:
 	spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-- 
2.18.4


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4175 bytes --]

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 04/14] mpt3sas: Update hba_port's sas_address & phy_mask
  2020-10-09 17:14 [PATCH 00/14] mpt3sas: Add support for multi-port path topology Sreekanth Reddy
                   ` (2 preceding siblings ...)
  2020-10-09 17:14 ` [PATCH 03/14] mpt3sas: Rearrange _scsih_mark_responding_sas_device() Sreekanth Reddy
@ 2020-10-09 17:14 ` Sreekanth Reddy
  2020-10-09 17:14 ` [PATCH 05/14] mpt3sas: Get device objects using sas_address & portID Sreekanth Reddy
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 18+ messages in thread
From: Sreekanth Reddy @ 2020-10-09 17:14 UTC (permalink / raw)
  To: martin.petersen
  Cc: linux-scsi, sathya.prakash, suganath-prabu.subramani, Sreekanth Reddy

[-- Attachment #1: Type: text/plain, Size: 22048 bytes --]

Update hba_port's sas_address & phy_mask fields whenever
a direct expander or sas/sata target devices are
added or removed.

- When any direct attached device is discovered then driver
        - gets the hba_port object corresponding to device's
          PhysicalPort number,
        - update's the hba_port's sas_address field with
          device's SAS Address,
        - update's the hba_port's phy_mask filed with device's
          narrow/wide port Phy number bits.

        Also,
        - if any sas/sata end device (not only direct
          direct attached devices) is added then
          corresponding sas_device object's port variable
          is assigned with hba_port object's address who's
          port_id matches with device's PhysicalPort number.
        - if any expander device is added then corresponding
          sas_expander object's port variable is assigned
          with hba_port object's address who's port_id
          matches with expander device's PhysicalPort number.

- When any direct attached device is detached then driver
  will delete the hba_port object's corresponding to
  device's PhysicalPort number.

- Whenever any HBA phy's link (of direct attached device's port)
  comes up then update the phy_mask field of corresponding
  hba_port object.

- Added a new function parameter named 'port' of type
  struct hba_port to below functions,
  * mpt3sas_transport_port_add()
  * mpt3sas_transport_port_remove()
  * mpt3sas_transport_update_links()

Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.h      |  7 +-
 drivers/scsi/mpt3sas/mpt3sas_scsih.c     | 81 ++++++++++++++++++------
 drivers/scsi/mpt3sas/mpt3sas_transport.c | 65 +++++++++++++++++--
 3 files changed, 126 insertions(+), 27 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 2dde574..aef872a 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -1792,16 +1792,17 @@ extern struct scsi_transport_template *mpt3sas_transport_template;
 u8 mpt3sas_transport_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
 	u32 reply);
 struct _sas_port *mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc,
-	u16 handle, u64 sas_address);
+	u16 handle, u64 sas_address, struct hba_port *port);
 void mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
-	u64 sas_address_parent);
+	u64 sas_address_parent, struct hba_port *port);
 int mpt3sas_transport_add_host_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy
 	*mpt3sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev);
 int mpt3sas_transport_add_expander_phy(struct MPT3SAS_ADAPTER *ioc,
 	struct _sas_phy *mpt3sas_phy, Mpi2ExpanderPage1_t expander_pg1,
 	struct device *parent_dev);
 void mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc,
-	u64 sas_address, u16 handle, u8 phy_number, u8 link_rate);
+	u64 sas_address, u16 handle, u8 phy_number, u8 link_rate,
+	struct hba_port *port);
 extern struct sas_function_template mpt3sas_transport_functions;
 extern struct scsi_transport_template *mpt3sas_transport_template;
 /* trigger data externs */
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index e8ffe1e..0067025 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -908,7 +908,7 @@ _scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc,
 	}
 
 	if (!mpt3sas_transport_port_add(ioc, sas_device->handle,
-	     sas_device->sas_address_parent)) {
+	     sas_device->sas_address_parent, sas_device->port)) {
 		_scsih_sas_device_remove(ioc, sas_device);
 	} else if (!sas_device->starget) {
 		/*
@@ -919,7 +919,8 @@ _scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc,
 		if (!ioc->is_driver_loading) {
 			mpt3sas_transport_port_remove(ioc,
 			    sas_device->sas_address,
-			    sas_device->sas_address_parent);
+			    sas_device->sas_address_parent,
+			    sas_device->port);
 			_scsih_sas_device_remove(ioc, sas_device);
 		}
 	} else
@@ -1768,6 +1769,7 @@ scsih_target_alloc(struct scsi_target *starget)
 		if (pcie_device) {
 			sas_target_priv_data->handle = pcie_device->handle;
 			sas_target_priv_data->sas_address = pcie_device->wwid;
+			sas_target_priv_data->port = NULL;
 			sas_target_priv_data->pcie_dev = pcie_device;
 			pcie_device->starget = starget;
 			pcie_device->id = starget->id;
@@ -1791,6 +1793,7 @@ scsih_target_alloc(struct scsi_target *starget)
 	if (sas_device) {
 		sas_target_priv_data->handle = sas_device->handle;
 		sas_target_priv_data->sas_address = sas_device->sas_address;
+		sas_target_priv_data->port = sas_device->port;
 		sas_target_priv_data->sas_dev = sas_device;
 		sas_device->starget = starget;
 		sas_device->id = starget->id;
@@ -5804,7 +5807,8 @@ _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc)
 			link_rate = MPI2_SAS_NEG_LINK_RATE_1_5;
 		ioc->sas_hba.phy[i].port = mpt3sas_get_port_by_id(ioc, port_id);
 		mpt3sas_transport_update_links(ioc, ioc->sas_hba.sas_address,
-		    attached_handle, i, link_rate);
+		    attached_handle, i, link_rate,
+		    ioc->sas_hba.phy[i].port);
 	}
  out:
 	kfree(sas_iounit_pg0);
@@ -5994,6 +5998,7 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 	int i;
 	unsigned long flags;
 	struct _sas_port *mpt3sas_port = NULL;
+	u8 port_id;
 
 	int rc = 0;
 
@@ -6026,6 +6031,8 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 			__FILE__, __LINE__, __func__);
 		return -1;
 	}
+
+	port_id = expander_pg0.PhysicalPort;
 	if (sas_address_parent != ioc->sas_hba.sas_address) {
 		spin_lock_irqsave(&ioc->sas_node_lock, flags);
 		sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
@@ -6059,6 +6066,13 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 	sas_expander->num_phys = expander_pg0.NumPhys;
 	sas_expander->sas_address_parent = sas_address_parent;
 	sas_expander->sas_address = sas_address;
+	sas_expander->port = mpt3sas_get_port_by_id(ioc, port_id);
+	if (!sas_expander->port) {
+		ioc_err(ioc, "failure at %s:%d/%s()!\n",
+		    __FILE__, __LINE__, __func__);
+		rc = -1;
+		goto out_fail;
+	}
 
 	ioc_info(ioc, "expander_add: handle(0x%04x), parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n",
 		 handle, parent_handle,
@@ -6077,7 +6091,7 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 
 	INIT_LIST_HEAD(&sas_expander->sas_port_list);
 	mpt3sas_port = mpt3sas_transport_port_add(ioc, handle,
-	    sas_address_parent);
+	    sas_address_parent, sas_expander->port);
 	if (!mpt3sas_port) {
 		ioc_err(ioc, "failure at %s:%d/%s()!\n",
 			__FILE__, __LINE__, __func__);
@@ -6096,6 +6110,7 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 		}
 		sas_expander->phy[i].handle = handle;
 		sas_expander->phy[i].phy_id = i;
+		sas_expander->phy[i].port = mpt3sas_get_port_by_id(ioc, port_id);
 
 		if ((mpt3sas_transport_add_expander_phy(ioc,
 		    &sas_expander->phy[i], expander_pg1,
@@ -6123,7 +6138,7 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 
 	if (mpt3sas_port)
 		mpt3sas_transport_port_remove(ioc, sas_expander->sas_address,
-		    sas_address_parent);
+		    sas_address_parent, sas_expander->port);
 	kfree(sas_expander);
 	return rc;
 }
@@ -6388,6 +6403,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
 	u32 ioc_status;
 	u64 sas_address;
 	u32 device_info;
+	u8 port_id;
 
 	if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
 	    MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
@@ -6424,6 +6440,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
 	    sas_device_pg0.AccessStatus))
 		return -1;
 
+	port_id = sas_device_pg0.PhysicalPort;
 	sas_device = mpt3sas_get_sdev_by_addr(ioc,
 					sas_address);
 	if (sas_device) {
@@ -6466,6 +6483,12 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
 	sas_device->phy = sas_device_pg0.PhyNum;
 	sas_device->fast_path = (le16_to_cpu(sas_device_pg0.Flags) &
 	    MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) ? 1 : 0;
+	sas_device->port = mpt3sas_get_port_by_id(ioc, port_id);
+	if (!sas_device->port) {
+		ioc_err(ioc, "failure at %s:%d/%s()!\n",
+		    __FILE__, __LINE__, __func__);
+		goto out;
+	}
 
 	if (le16_to_cpu(sas_device_pg0.Flags)
 		& MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
@@ -6499,6 +6522,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
 	else
 		_scsih_sas_device_add(ioc, sas_device);
 
+out:
 	sas_device_put(sas_device);
 	return 0;
 }
@@ -6539,7 +6563,8 @@ _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc,
 	if (!ioc->hide_drives)
 		mpt3sas_transport_port_remove(ioc,
 		    sas_device->sas_address,
-		    sas_device->sas_address_parent);
+		    sas_device->sas_address_parent,
+		    sas_device->port);
 
 	ioc_info(ioc, "removing handle(0x%04x), sas_addr(0x%016llx)\n",
 		 sas_device->handle, (u64)sas_device->sas_address);
@@ -6650,6 +6675,7 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
 	u64 sas_address;
 	unsigned long flags;
 	u8 link_rate, prev_link_rate;
+	struct hba_port *port;
 	Mpi2EventDataSasTopologyChangeList_t *event_data =
 		(Mpi2EventDataSasTopologyChangeList_t *)
 		fw_event->event_data;
@@ -6671,6 +6697,7 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
 	}
 
 	parent_handle = le16_to_cpu(event_data->ExpanderDevHandle);
+	port = mpt3sas_get_port_by_id(ioc, event_data->PhysicalPort);
 
 	/* handle expander add */
 	if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED)
@@ -6683,6 +6710,7 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
 	if (sas_expander) {
 		sas_address = sas_expander->sas_address;
 		max_phys = sas_expander->num_phys;
+		port = sas_expander->port;
 	} else if (parent_handle < ioc->sas_hba.num_phys) {
 		sas_address = ioc->sas_hba.sas_address;
 		max_phys = ioc->sas_hba.num_phys;
@@ -6725,7 +6753,7 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
 				break;
 
 			mpt3sas_transport_update_links(ioc, sas_address,
-			    handle, phy_number, link_rate);
+			    handle, phy_number, link_rate, port);
 
 			if (link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
 				break;
@@ -6744,7 +6772,7 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
 				break;
 
 			mpt3sas_transport_update_links(ioc, sas_address,
-			    handle, phy_number, link_rate);
+			    handle, phy_number, link_rate, port);
 
 			_scsih_add_device(ioc, handle, phy_number, 0);
 
@@ -8300,7 +8328,8 @@ _scsih_sas_pd_add(struct MPT3SAS_ADAPTER *ioc,
 	parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
 	if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
 		mpt3sas_transport_update_links(ioc, sas_address, handle,
-		    sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
+		    sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5,
+		    mpt3sas_get_port_by_id(ioc, sas_device_pg0.PhysicalPort));
 
 	_scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
 	_scsih_add_device(ioc, handle, 0, 1);
@@ -8606,7 +8635,9 @@ _scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc,
 		parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
 		if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
 			mpt3sas_transport_update_links(ioc, sas_address, handle,
-			    sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
+			    sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5,
+			    mpt3sas_get_port_by_id(ioc,
+			    sas_device_pg0.PhysicalPort));
 
 		_scsih_add_device(ioc, handle, 0, 1);
 
@@ -9345,7 +9376,8 @@ _scsih_refresh_expander_links(struct MPT3SAS_ADAPTER *ioc,
 
 		mpt3sas_transport_update_links(ioc, sas_expander->sas_address,
 		    le16_to_cpu(expander_pg1.AttachedDevHandle), i,
-		    expander_pg1.NegotiatedLinkRate >> 4);
+		    expander_pg1.NegotiatedLinkRate >> 4,
+		    sas_expander->port);
 	}
 }
 
@@ -9364,7 +9396,7 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
 	Mpi2RaidPhysDiskPage0_t pd_pg0;
 	Mpi2EventIrConfigElement_t element;
 	Mpi2ConfigReply_t mpi_reply;
-	u8 phys_disk_num;
+	u8 phys_disk_num, port_id;
 	u16 ioc_status;
 	u16 handle, parent_handle;
 	u64 sas_address;
@@ -9454,9 +9486,11 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
 			ioc_info(ioc, "\tBEFORE adding phys disk: handle (0x%04x), sas_addr(0x%016llx)\n",
 				 handle,
 				 (u64)le64_to_cpu(sas_device_pg0.SASAddress));
+			port_id = sas_device_pg0.PhysicalPort;
 			mpt3sas_transport_update_links(ioc, sas_address,
 			    handle, sas_device_pg0.PhyNum,
-			    MPI2_SAS_NEG_LINK_RATE_1_5);
+			    MPI2_SAS_NEG_LINK_RATE_1_5,
+			    mpt3sas_get_port_by_id(ioc, port_id));
 			set_bit(handle, ioc->pd_handles);
 			retry_count = 0;
 			/* This will retry adding the end device.
@@ -9542,6 +9576,7 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
 		if (!(_scsih_is_end_device(
 		    le32_to_cpu(sas_device_pg0.DeviceInfo))))
 			continue;
+		port_id = sas_device_pg0.PhysicalPort;
 		sas_device = mpt3sas_get_sdev_by_addr(ioc,
 		    le64_to_cpu(sas_device_pg0.SASAddress));
 		if (sas_device) {
@@ -9554,7 +9589,8 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
 				 handle,
 				 (u64)le64_to_cpu(sas_device_pg0.SASAddress));
 			mpt3sas_transport_update_links(ioc, sas_address, handle,
-			    sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
+			    sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5,
+			    mpt3sas_get_port_by_id(ioc, port_id));
 			retry_count = 0;
 			/* This will retry adding the end device.
 			 * _scsih_add_device() will decide on retries and
@@ -9997,7 +10033,7 @@ _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc,
 	}
 
 	mpt3sas_transport_port_remove(ioc, sas_expander->sas_address,
-	    sas_expander->sas_address_parent);
+	    sas_expander->sas_address_parent, sas_expander->port);
 
 	ioc_info(ioc, "expander_remove: handle(0x%04x), sas_addr(0x%016llx)\n",
 		 sas_expander->handle, (unsigned long long)
@@ -10341,6 +10377,7 @@ _scsih_probe_boot_devices(struct MPT3SAS_ADAPTER *ioc)
 	unsigned long flags;
 	int rc;
 	int tid;
+	struct hba_port *port;
 
 	 /* no Bios, return immediately */
 	if (!ioc->bios_pg3.BiosVersion)
@@ -10382,19 +10419,24 @@ _scsih_probe_boot_devices(struct MPT3SAS_ADAPTER *ioc)
 		handle = sas_device->handle;
 		sas_address_parent = sas_device->sas_address_parent;
 		sas_address = sas_device->sas_address;
+		port = sas_device->port;
 		list_move_tail(&sas_device->list, &ioc->sas_device_list);
 		spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
 
 		if (ioc->hide_drives)
 			return;
+
+		if (!port)
+			return;
+
 		if (!mpt3sas_transport_port_add(ioc, handle,
-		    sas_address_parent)) {
+		    sas_address_parent, port)) {
 			_scsih_sas_device_remove(ioc, sas_device);
 		} else if (!sas_device->starget) {
 			if (!ioc->is_driver_loading) {
 				mpt3sas_transport_port_remove(ioc,
 				    sas_address,
-				    sas_address_parent);
+				    sas_address_parent, port);
 				_scsih_sas_device_remove(ioc, sas_device);
 			}
 		}
@@ -10482,7 +10524,7 @@ _scsih_probe_sas(struct MPT3SAS_ADAPTER *ioc)
 
 	while ((sas_device = get_next_sas_device(ioc))) {
 		if (!mpt3sas_transport_port_add(ioc, sas_device->handle,
-		    sas_device->sas_address_parent)) {
+		    sas_device->sas_address_parent, sas_device->port)) {
 			_scsih_sas_device_remove(ioc, sas_device);
 			sas_device_put(sas_device);
 			continue;
@@ -10496,7 +10538,8 @@ _scsih_probe_sas(struct MPT3SAS_ADAPTER *ioc)
 			if (!ioc->is_driver_loading) {
 				mpt3sas_transport_port_remove(ioc,
 				    sas_device->sas_address,
-				    sas_device->sas_address_parent);
+				    sas_device->sas_address_parent,
+				    sas_device->port);
 				_scsih_sas_device_remove(ioc, sas_device);
 				sas_device_put(sas_device);
 				continue;
diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c
index 6ec5b7f..aab3b14 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_transport.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c
@@ -594,6 +594,7 @@ _transport_sanity_check(struct MPT3SAS_ADAPTER *ioc, struct _sas_node *sas_node,
  * @ioc: per adapter object
  * @handle: handle of attached device
  * @sas_address: sas address of parent expander or sas host
+ * @port: hba port entry
  * Context: This function will acquire ioc->sas_node_lock.
  *
  * Adding new port object to the sas_node->sas_port_list.
@@ -602,7 +603,7 @@ _transport_sanity_check(struct MPT3SAS_ADAPTER *ioc, struct _sas_node *sas_node,
  */
 struct _sas_port *
 mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
-	u64 sas_address)
+	u64 sas_address, struct hba_port *hba_port)
 {
 	struct _sas_phy *mpt3sas_phy, *next;
 	struct _sas_port *mpt3sas_port;
@@ -613,6 +614,12 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
 	int i;
 	struct sas_port *port;
 
+	if (!hba_port) {
+		ioc_err(ioc, "failure at %s:%d/%s()!\n",
+		    __FILE__, __LINE__, __func__);
+		return NULL;
+	}
+
 	mpt3sas_port = kzalloc(sizeof(struct _sas_port),
 	    GFP_KERNEL);
 	if (!mpt3sas_port) {
@@ -646,6 +653,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
 		goto out_fail;
 	}
 
+	mpt3sas_port->hba_port = hba_port;
 	_transport_sanity_check(ioc, sas_node,
 	    mpt3sas_port->remote_identify.sas_address);
 
@@ -653,8 +661,12 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
 		if (sas_node->phy[i].remote_identify.sas_address !=
 		    mpt3sas_port->remote_identify.sas_address)
 			continue;
+		if (sas_node->phy[i].port != hba_port)
+			continue;
 		list_add_tail(&sas_node->phy[i].port_siblings,
 		    &mpt3sas_port->phy_list);
+		if (sas_node->handle <= ioc->sas_hba.num_phys)
+			hba_port->phy_mask |= (1 << i);
 		mpt3sas_port->num_phys++;
 	}
 
@@ -686,14 +698,21 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
 			    mpt3sas_phy->phy_id);
 		sas_port_add_phy(port, mpt3sas_phy->phy);
 		mpt3sas_phy->phy_belongs_to_port = 1;
+		mpt3sas_phy->port = hba_port;
 	}
 
 	mpt3sas_port->port = port;
-	if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE)
+	if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) {
 		rphy = sas_end_device_alloc(port);
-	else
+		if (sas_node->handle <= ioc->sas_hba.num_phys)
+			hba_port->sas_address = sas_device->sas_address;
+	} else {
 		rphy = sas_expander_alloc(port,
 		    mpt3sas_port->remote_identify.device_type);
+		if (sas_node->handle <= ioc->sas_hba.num_phys)
+			hba_port->sas_address =
+			    mpt3sas_port->remote_identify.sas_address;
+	}
 
 	rphy->identify = mpt3sas_port->remote_identify;
 
@@ -751,6 +770,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
  * @ioc: per adapter object
  * @sas_address: sas address of attached device
  * @sas_address_parent: sas address of parent expander or sas host
+ * @port: hba port entry
  * Context: This function will acquire ioc->sas_node_lock.
  *
  * Removing object and freeing associated memory from the
@@ -758,7 +778,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
  */
 void
 mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
-	u64 sas_address_parent)
+	u64 sas_address_parent, struct hba_port *port)
 {
 	int i;
 	unsigned long flags;
@@ -766,6 +786,10 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
 	struct _sas_node *sas_node;
 	u8 found = 0;
 	struct _sas_phy *mpt3sas_phy, *next_phy;
+	struct hba_port *hba_port_next, *hba_port = NULL;
+
+	if (!port)
+		return;
 
 	spin_lock_irqsave(&ioc->sas_node_lock, flags);
 	sas_node = _transport_sas_node_find_by_sas_address(ioc,
@@ -778,6 +802,8 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
 	    port_list) {
 		if (mpt3sas_port->remote_identify.sas_address != sas_address)
 			continue;
+		if (mpt3sas_port->hba_port != port)
+			continue;
 		found = 1;
 		list_del(&mpt3sas_port->port_list);
 		goto out;
@@ -788,6 +814,21 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
 		return;
 	}
 
+	if (sas_node->handle <= ioc->sas_hba.num_phys) {
+		list_for_each_entry_safe(hba_port, hba_port_next,
+		    &ioc->port_table_list, list) {
+			if (hba_port != port)
+				continue;
+			if (hba_port->sas_address != sas_address)
+				continue;
+			ioc_info(ioc,
+			    "remove hba_port entry: %p port: %d from hba_port list\n",
+			    hba_port, hba_port->port_id);
+			list_del(&hba_port->list);
+			kfree(hba_port);
+		}
+	}
+
 	for (i = 0; i < sas_node->num_phys; i++) {
 		if (sas_node->phy[i].remote_identify.sas_address == sas_address)
 			memset(&sas_node->phy[i].remote_identify, 0 ,
@@ -961,14 +1002,19 @@ mpt3sas_transport_add_expander_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy
  * @handle: attached device handle
  * @phy_number: phy number
  * @link_rate: new link rate
+ * @port: hba port entry
+ *
+ * Return nothing.
  */
 void
 mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc,
-	u64 sas_address, u16 handle, u8 phy_number, u8 link_rate)
+	u64 sas_address, u16 handle, u8 phy_number, u8 link_rate,
+	struct hba_port *port)
 {
 	unsigned long flags;
 	struct _sas_node *sas_node;
 	struct _sas_phy *mpt3sas_phy;
+	struct hba_port *hba_port = NULL;
 
 	if (ioc->shost_recovery || ioc->pci_error_recovery)
 		return;
@@ -988,6 +1034,15 @@ mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc,
 		    &mpt3sas_phy->remote_identify);
 		_transport_add_phy_to_an_existing_port(ioc, sas_node,
 		    mpt3sas_phy, mpt3sas_phy->remote_identify.sas_address);
+		if (sas_node->handle <= ioc->sas_hba.num_phys) {
+			list_for_each_entry(hba_port,
+			    &ioc->port_table_list, list) {
+				if (hba_port->sas_address == sas_address &&
+				    hba_port == port)
+					hba_port->phy_mask |=
+					    (1 << mpt3sas_phy->phy_id);
+			}
+		}
 	} else
 		memset(&mpt3sas_phy->remote_identify, 0 , sizeof(struct
 		    sas_identify));
-- 
2.18.4


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4175 bytes --]

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 05/14] mpt3sas: Get device objects using sas_address & portID
  2020-10-09 17:14 [PATCH 00/14] mpt3sas: Add support for multi-port path topology Sreekanth Reddy
                   ` (3 preceding siblings ...)
  2020-10-09 17:14 ` [PATCH 04/14] mpt3sas: Update hba_port's sas_address & phy_mask Sreekanth Reddy
@ 2020-10-09 17:14 ` Sreekanth Reddy
  2020-10-09 17:14 ` [PATCH 06/14] mpt3sas: Rename transport_del_phy_from_an_existing_port Sreekanth Reddy
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 18+ messages in thread
From: Sreekanth Reddy @ 2020-10-09 17:14 UTC (permalink / raw)
  To: martin.petersen
  Cc: linux-scsi, sathya.prakash, suganath-prabu.subramani, Sreekanth Reddy

[-- Attachment #1: Type: text/plain, Size: 30146 bytes --]

Currently driver retrieve the sas_devie/sas_expander objects
from corresponding object's lists using just device's
SAS Address. Now driver will retrieve the objects from the
corresponding objects list using device's SAS Address
and PhysicalPort(or PortID) number.

where
PhysicalPort number - Port number of the HBA through which this
device is accessing.

Here are the list of objects that driver retrieves based on
SAS Address & PhysicalPort number,

* Retrieve sas_device object from sas_device_list using device's
  SAS Address & PhysicalPort number,
* Retrieve sas_expander object from sas_expander_list using expander
  device's SAS Address & PhysicalPort number,

Also, where ever driver is matching the objects with device's
SAS Address, now, in addition to it driver has to match the device
PhysicalPort number also.

Added additional function parameter named 'port' of type
struct hba_port in below list of functions,
 * mpt3sas_expander_remove()
 * mpt3sas_device_remove_by_sas_address()
 * mpt3sas_scsih_expander_find_by_sas_address()
 * mpt3sas_get_sdev_by_addr()
 * __mpt3sas_get_sdev_by_addr()
 * _scsih_ublock_io_device()
 * _transport_sas_node_find_by_sas_address()
 * _transport_sanity_check()

Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.h      |  16 ++-
 drivers/scsi/mpt3sas/mpt3sas_scsih.c     | 175 ++++++++++++++++-------
 drivers/scsi/mpt3sas/mpt3sas_transport.c |  74 ++++++----
 3 files changed, 178 insertions(+), 87 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
index aef872a..b5d1fc5 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -1652,20 +1652,26 @@ int mpt3sas_scsih_issue_locked_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle,
 
 void mpt3sas_scsih_set_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle);
 void mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle);
-void mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
+void mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
+	struct hba_port *port);
 void mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
-	u64 sas_address);
+	u64 sas_address, struct hba_port *port);
 u8 mpt3sas_check_for_pending_internal_cmds(struct MPT3SAS_ADAPTER *ioc,
 	u16 smid);
+struct hba_port *
+mpt3sas_get_port_by_id(struct MPT3SAS_ADAPTER *ioc, u8 port);
 
 struct _sas_node *mpt3sas_scsih_expander_find_by_handle(
 	struct MPT3SAS_ADAPTER *ioc, u16 handle);
 struct _sas_node *mpt3sas_scsih_expander_find_by_sas_address(
-	struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
+	struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
+	struct hba_port *port);
 struct _sas_device *mpt3sas_get_sdev_by_addr(
-	 struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
+	 struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
+	 struct hba_port *port);
 struct _sas_device *__mpt3sas_get_sdev_by_addr(
-	 struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
+	 struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
+	 struct hba_port *port);
 struct _sas_device *mpt3sas_get_sdev_by_handle(struct MPT3SAS_ADAPTER *ioc,
 	u16 handle);
 struct _pcie_device *mpt3sas_get_pdev_by_handle(struct MPT3SAS_ADAPTER *ioc,
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 0067025..4542d66 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -638,48 +638,67 @@ mpt3sas_get_pdev_from_target(struct MPT3SAS_ADAPTER *ioc,
 	return ret;
 }
 
+/**
+ * mpt3sas_get_sdev_by_addr - get _sas_device object corresponding to provided
+ *				sas address from sas_device_list list
+ * @ioc: per adapter object
+ * @port: port number
+ *
+ * Search for _sas_device object corresponding to provided sas address,
+ * if available return _sas_device object address otherwise return NULL.
+ */
 struct _sas_device *
 __mpt3sas_get_sdev_by_addr(struct MPT3SAS_ADAPTER *ioc,
-					u64 sas_address)
+	u64 sas_address, struct hba_port *port)
 {
 	struct _sas_device *sas_device;
 
+	if (!port)
+		return NULL;
+
 	assert_spin_locked(&ioc->sas_device_lock);
 
-	list_for_each_entry(sas_device, &ioc->sas_device_list, list)
-		if (sas_device->sas_address == sas_address)
-			goto found_device;
+	list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
+		if (sas_device->sas_address != sas_address)
+			continue;
+		if (sas_device->port != port)
+			continue;
+		sas_device_get(sas_device);
+		return sas_device;
+	}
 
-	list_for_each_entry(sas_device, &ioc->sas_device_init_list, list)
-		if (sas_device->sas_address == sas_address)
-			goto found_device;
+	list_for_each_entry(sas_device, &ioc->sas_device_init_list, list) {
+		if (sas_device->sas_address != sas_address)
+			continue;
+		if (sas_device->port != port)
+			continue;
+		sas_device_get(sas_device);
+		return sas_device;
+	}
 
 	return NULL;
-
-found_device:
-	sas_device_get(sas_device);
-	return sas_device;
 }
 
 /**
  * mpt3sas_get_sdev_by_addr - sas device search
  * @ioc: per adapter object
  * @sas_address: sas address
+ * @port: hba port entry
  * Context: Calling function should acquire ioc->sas_device_lock
  *
- * This searches for sas_device based on sas_address, then return sas_device
- * object.
+ * This searches for sas_device based on sas_address & port number,
+ * then return sas_device object.
  */
 struct _sas_device *
 mpt3sas_get_sdev_by_addr(struct MPT3SAS_ADAPTER *ioc,
-	u64 sas_address)
+	u64 sas_address, struct hba_port *port)
 {
 	struct _sas_device *sas_device;
 	unsigned long flags;
 
 	spin_lock_irqsave(&ioc->sas_device_lock, flags);
 	sas_device = __mpt3sas_get_sdev_by_addr(ioc,
-			sas_address);
+	    sas_address, port);
 	spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
 
 	return sas_device;
@@ -848,13 +867,17 @@ _scsih_device_remove_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 }
 
 /**
- * mpt3sas_device_remove_by_sas_address - removing device object by sas address
+ * mpt3sas_device_remove_by_sas_address - removing device object by
+ *					sas address & port number
  * @ioc: per adapter object
  * @sas_address: device sas_address
+ * @port: hba port entry
+ *
+ * Return nothing.
  */
 void
 mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
-	u64 sas_address)
+	u64 sas_address, struct hba_port *port)
 {
 	struct _sas_device *sas_device;
 	unsigned long flags;
@@ -863,7 +886,7 @@ mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
 		return;
 
 	spin_lock_irqsave(&ioc->sas_device_lock, flags);
-	sas_device = __mpt3sas_get_sdev_by_addr(ioc, sas_address);
+	sas_device = __mpt3sas_get_sdev_by_addr(ioc, sas_address, port);
 	if (sas_device) {
 		list_del_init(&sas_device->list);
 		sas_device_put(sas_device);
@@ -1457,21 +1480,26 @@ out:
  * mpt3sas_scsih_expander_find_by_sas_address - expander device search
  * @ioc: per adapter object
  * @sas_address: sas address
+ * @port: hba port entry
  * Context: Calling function should acquire ioc->sas_node_lock.
  *
- * This searches for expander device based on sas_address, then returns the
- * sas_node object.
+ * This searches for expander device based on sas_address & port number,
+ * then returns the sas_node object.
  */
 struct _sas_node *
 mpt3sas_scsih_expander_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
-	u64 sas_address)
+	u64 sas_address, struct hba_port *port)
 {
-	struct _sas_node *sas_expander, *r;
+	struct _sas_node *sas_expander, *r = NULL;
+
+	if (!port)
+		return r;
 
-	r = NULL;
 	list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
 		if (sas_expander->sas_address != sas_address)
 			continue;
+		if (sas_expander->port != port)
+			continue;
 		r = sas_expander;
 		goto out;
 	}
@@ -1788,7 +1816,7 @@ scsih_target_alloc(struct scsi_target *starget)
 	spin_lock_irqsave(&ioc->sas_device_lock, flags);
 	rphy = dev_to_rphy(starget->dev.parent);
 	sas_device = __mpt3sas_get_sdev_by_addr(ioc,
-	   rphy->identify.sas_address);
+	   rphy->identify.sas_address, NULL);
 
 	if (sas_device) {
 		sas_target_priv_data->handle = sas_device->handle;
@@ -1949,7 +1977,8 @@ scsih_slave_alloc(struct scsi_device *sdev)
 	} else  if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) {
 		spin_lock_irqsave(&ioc->sas_device_lock, flags);
 		sas_device = __mpt3sas_get_sdev_by_addr(ioc,
-					sas_target_priv_data->sas_address);
+		    sas_target_priv_data->sas_address,
+		    sas_target_priv_data->port);
 		if (sas_device && (sas_device->starget == NULL)) {
 			sdev_printk(KERN_INFO, sdev,
 			"%s : sas_device->starget set to starget @ %d\n",
@@ -2554,7 +2583,8 @@ scsih_slave_configure(struct scsi_device *sdev)
 
 	spin_lock_irqsave(&ioc->sas_device_lock, flags);
 	sas_device = __mpt3sas_get_sdev_by_addr(ioc,
-	   sas_device_priv_data->sas_target->sas_address);
+	   sas_device_priv_data->sas_target->sas_address,
+	   sas_device_priv_data->sas_target->port);
 	if (!sas_device) {
 		spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
 		dfailprintk(ioc,
@@ -3669,11 +3699,13 @@ _scsih_ublock_io_all_device(struct MPT3SAS_ADAPTER *ioc)
  * _scsih_ublock_io_device - prepare device to be deleted
  * @ioc: per adapter object
  * @sas_address: sas address
+ * @port: hba port entry
  *
  * unblock then put device in offline state
  */
 static void
-_scsih_ublock_io_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address)
+_scsih_ublock_io_device(struct MPT3SAS_ADAPTER *ioc,
+	u64 sas_address, struct hba_port *port)
 {
 	struct MPT3SAS_DEVICE *sas_device_priv_data;
 	struct scsi_device *sdev;
@@ -3685,6 +3717,8 @@ _scsih_ublock_io_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address)
 		if (sas_device_priv_data->sas_target->sas_address
 		    != sas_address)
 			continue;
+		if (sas_device_priv_data->sas_target->port != port)
+			continue;
 		if (sas_device_priv_data->block)
 			_scsih_internal_device_unblock(sdev,
 				sas_device_priv_data);
@@ -3785,7 +3819,8 @@ _scsih_block_io_to_children_attached_to_ex(struct MPT3SAS_ADAPTER *ioc,
 		    SAS_END_DEVICE) {
 			spin_lock_irqsave(&ioc->sas_device_lock, flags);
 			sas_device = __mpt3sas_get_sdev_by_addr(ioc,
-			    mpt3sas_port->remote_identify.sas_address);
+			    mpt3sas_port->remote_identify.sas_address,
+			    mpt3sas_port->hba_port);
 			if (sas_device) {
 				set_bit(sas_device->handle,
 						ioc->blocking_handles);
@@ -3804,7 +3839,8 @@ _scsih_block_io_to_children_attached_to_ex(struct MPT3SAS_ADAPTER *ioc,
 		    SAS_FANOUT_EXPANDER_DEVICE) {
 			expander_sibling =
 			    mpt3sas_scsih_expander_find_by_sas_address(
-			    ioc, mpt3sas_port->remote_identify.sas_address);
+			    ioc, mpt3sas_port->remote_identify.sas_address,
+			    mpt3sas_port->hba_port);
 			_scsih_block_io_to_children_attached_to_ex(ioc,
 			    expander_sibling);
 		}
@@ -3893,6 +3929,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 	struct _tr_list *delayed_tr;
 	u32 ioc_state;
 	u8 tr_method = 0;
+	struct hba_port *port = NULL;
 
 	if (ioc->pci_error_recovery) {
 		dewtprintk(ioc,
@@ -3921,6 +3958,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 		sas_target_priv_data = sas_device->starget->hostdata;
 		sas_target_priv_data->deleted = 1;
 		sas_address = sas_device->sas_address;
+		port = sas_device->port;
 	}
 	spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
 	if (!sas_device) {
@@ -3968,7 +4006,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 						    pcie_device->enclosure_level,
 						    pcie_device->connector_name));
 		}
-		_scsih_ublock_io_device(ioc, sas_address);
+		_scsih_ublock_io_device(ioc, sas_address, port);
 		sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE;
 	}
 
@@ -6036,7 +6074,7 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 	if (sas_address_parent != ioc->sas_hba.sas_address) {
 		spin_lock_irqsave(&ioc->sas_node_lock, flags);
 		sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
-		    sas_address_parent);
+		    sas_address_parent, mpt3sas_get_port_by_id(ioc, port_id));
 		spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 		if (!sas_expander) {
 			rc = _scsih_expander_add(ioc, parent_handle);
@@ -6048,7 +6086,7 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 	spin_lock_irqsave(&ioc->sas_node_lock, flags);
 	sas_address = le64_to_cpu(expander_pg0.SASAddress);
 	sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
-	    sas_address);
+	    sas_address, mpt3sas_get_port_by_id(ioc, port_id));
 	spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 
 	if (sas_expander)
@@ -6149,7 +6187,8 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle)
  * @sas_address: expander sas_address
  */
 void
-mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address)
+mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
+	struct hba_port *port)
 {
 	struct _sas_node *sas_expander;
 	unsigned long flags;
@@ -6157,9 +6196,12 @@ mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address)
 	if (ioc->shost_recovery)
 		return;
 
+	if (!port)
+		return;
+
 	spin_lock_irqsave(&ioc->sas_node_lock, flags);
 	sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
-	    sas_address);
+	    sas_address, port);
 	spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 	if (sas_expander)
 		_scsih_expander_node_remove(ioc, sas_expander);
@@ -6282,7 +6324,7 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
 {
 	Mpi2ConfigReply_t mpi_reply;
 	Mpi2SasDevicePage0_t sas_device_pg0;
-	struct _sas_device *sas_device;
+	struct _sas_device *sas_device = NULL;
 	struct _enclosure_node *enclosure_dev = NULL;
 	u32 ioc_status;
 	unsigned long flags;
@@ -6290,6 +6332,7 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
 	struct scsi_target *starget;
 	struct MPT3SAS_TARGET *sas_target_priv_data;
 	u32 device_info;
+	struct hba_port *port;
 
 	if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
 	    MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle)))
@@ -6312,8 +6355,11 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
 
 	spin_lock_irqsave(&ioc->sas_device_lock, flags);
 	sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
+	port = mpt3sas_get_port_by_id(ioc, sas_device_pg0.PhysicalPort);
+	if (!port)
+		goto out_unlock;
 	sas_device = __mpt3sas_get_sdev_by_addr(ioc,
-	    sas_address);
+	    sas_address, port);
 
 	if (!sas_device)
 		goto out_unlock;
@@ -6369,7 +6415,7 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
 		goto out_unlock;
 
 	spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-	_scsih_ublock_io_device(ioc, sas_address);
+	_scsih_ublock_io_device(ioc, sas_address, port);
 
 	if (sas_device)
 		sas_device_put(sas_device);
@@ -6442,7 +6488,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
 
 	port_id = sas_device_pg0.PhysicalPort;
 	sas_device = mpt3sas_get_sdev_by_addr(ioc,
-					sas_address);
+	    sas_address, mpt3sas_get_port_by_id(ioc, port_id));
 	if (sas_device) {
 		clear_bit(handle, ioc->pend_os_device_add);
 		sas_device_put(sas_device);
@@ -6555,7 +6601,8 @@ _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc,
 	if (sas_device->starget && sas_device->starget->hostdata) {
 		sas_target_priv_data = sas_device->starget->hostdata;
 		sas_target_priv_data->deleted = 1;
-		_scsih_ublock_io_device(ioc, sas_device->sas_address);
+		_scsih_ublock_io_device(ioc, sas_device->sas_address,
+		    sas_device->port);
 		sas_target_priv_data->handle =
 		     MPT3SAS_INVALID_DEVICE_HANDLE;
 	}
@@ -6787,7 +6834,7 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
 	/* handle expander removal */
 	if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING &&
 	    sas_expander)
-		mpt3sas_expander_remove(ioc, sas_address);
+		mpt3sas_expander_remove(ioc, sas_address, port);
 
 	return 0;
 }
@@ -6888,7 +6935,7 @@ _scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc,
 	spin_lock_irqsave(&ioc->sas_device_lock, flags);
 	sas_address = le64_to_cpu(event_data->SASAddress);
 	sas_device = __mpt3sas_get_sdev_by_addr(ioc,
-	    sas_address);
+	    sas_address, mpt3sas_get_port_by_id(ioc, event_data->PhysicalPort));
 
 	if (!sas_device || !sas_device->starget)
 		goto out;
@@ -7037,7 +7084,7 @@ _scsih_pcie_device_remove_from_sml(struct MPT3SAS_ADAPTER *ioc,
 	if (pcie_device->starget && pcie_device->starget->hostdata) {
 		sas_target_priv_data = pcie_device->starget->hostdata;
 		sas_target_priv_data->deleted = 1;
-		_scsih_ublock_io_device(ioc, pcie_device->wwid);
+		_scsih_ublock_io_device(ioc, pcie_device->wwid, NULL);
 		sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE;
 	}
 
@@ -7159,7 +7206,7 @@ _scsih_pcie_check_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 	spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);
 	pcie_device_put(pcie_device);
 
-	_scsih_ublock_io_device(ioc, wwid);
+	_scsih_ublock_io_device(ioc, wwid, NULL);
 
 	return;
 }
@@ -8762,6 +8809,8 @@ Mpi2SasDevicePage0_t *sas_device_pg0)
 	struct _sas_device *sas_device = NULL;
 	struct _enclosure_node *enclosure_dev = NULL;
 	unsigned long flags;
+	struct hba_port *port = mpt3sas_get_port_by_id(
+	    ioc, sas_device_pg0->PhysicalPort);
 
 	if (sas_device_pg0->EnclosureHandle) {
 		enclosure_dev =
@@ -8778,6 +8827,8 @@ Mpi2SasDevicePage0_t *sas_device_pg0)
 			continue;
 		if (sas_device->slot != le16_to_cpu(sas_device_pg0->Slot))
 			continue;
+		if (sas_device->port != port)
+			continue;
 		sas_device->responding = 1;
 		starget = sas_device->starget;
 		if (starget && starget->hostdata) {
@@ -9186,6 +9237,8 @@ _scsih_mark_responding_expander(struct MPT3SAS_ADAPTER *ioc,
 	u16 handle = le16_to_cpu(expander_pg0->DevHandle);
 	u16 enclosure_handle = le16_to_cpu(expander_pg0->EnclosureHandle);
 	u64 sas_address = le64_to_cpu(expander_pg0->SASAddress);
+	struct hba_port *port = mpt3sas_get_port_by_id(
+	    ioc, expander_pg0->PhysicalPort);
 
 	if (enclosure_handle)
 		enclosure_dev =
@@ -9196,6 +9249,8 @@ _scsih_mark_responding_expander(struct MPT3SAS_ADAPTER *ioc,
 	list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
 		if (sas_expander->sas_address != sas_address)
 			continue;
+		if (sas_expander->port != port)
+			continue;
 		sas_expander->responding = 1;
 
 		if (enclosure_dev) {
@@ -9252,9 +9307,10 @@ _scsih_search_responding_expanders(struct MPT3SAS_ADAPTER *ioc)
 
 		handle = le16_to_cpu(expander_pg0.DevHandle);
 		sas_address = le64_to_cpu(expander_pg0.SASAddress);
-		pr_info("\texpander present: handle(0x%04x), sas_addr(0x%016llx)\n",
-			handle,
-		    (unsigned long long)sas_address);
+		pr_info(
+		    "\texpander present: handle(0x%04x), sas_addr(0x%016llx), port:%d\n",
+		    handle, (unsigned long long)sas_address,
+		    expander_pg0.PhysicalPort);
 		_scsih_mark_responding_expander(ioc, &expander_pg0);
 	}
 
@@ -9426,8 +9482,10 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
 		}
 		handle = le16_to_cpu(expander_pg0.DevHandle);
 		spin_lock_irqsave(&ioc->sas_node_lock, flags);
+		port_id = expander_pg0.PhysicalPort;
 		expander_device = mpt3sas_scsih_expander_find_by_sas_address(
-		    ioc, le64_to_cpu(expander_pg0.SASAddress));
+		    ioc, le64_to_cpu(expander_pg0.SASAddress),
+		    mpt3sas_get_port_by_id(ioc, port_id));
 		spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 		if (expander_device)
 			_scsih_refresh_expander_links(ioc, expander_device,
@@ -9578,7 +9636,8 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
 			continue;
 		port_id = sas_device_pg0.PhysicalPort;
 		sas_device = mpt3sas_get_sdev_by_addr(ioc,
-		    le64_to_cpu(sas_device_pg0.SASAddress));
+		    le64_to_cpu(sas_device_pg0.SASAddress),
+		    mpt3sas_get_port_by_id(ioc, port_id));
 		if (sas_device) {
 			sas_device_put(sas_device);
 			continue;
@@ -10023,21 +10082,25 @@ _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc,
 		if (mpt3sas_port->remote_identify.device_type ==
 		    SAS_END_DEVICE)
 			mpt3sas_device_remove_by_sas_address(ioc,
-			    mpt3sas_port->remote_identify.sas_address);
+			    mpt3sas_port->remote_identify.sas_address,
+			    mpt3sas_port->hba_port);
 		else if (mpt3sas_port->remote_identify.device_type ==
 		    SAS_EDGE_EXPANDER_DEVICE ||
 		    mpt3sas_port->remote_identify.device_type ==
 		    SAS_FANOUT_EXPANDER_DEVICE)
 			mpt3sas_expander_remove(ioc,
-			    mpt3sas_port->remote_identify.sas_address);
+			    mpt3sas_port->remote_identify.sas_address,
+			    mpt3sas_port->hba_port);
 	}
 
 	mpt3sas_transport_port_remove(ioc, sas_expander->sas_address,
 	    sas_expander->sas_address_parent, sas_expander->port);
 
-	ioc_info(ioc, "expander_remove: handle(0x%04x), sas_addr(0x%016llx)\n",
-		 sas_expander->handle, (unsigned long long)
-		 sas_expander->sas_address);
+	ioc_info(ioc,
+	    "expander_remove: handle(0x%04x), sas_addr(0x%016llx), port:%d\n",
+	    sas_expander->handle, (unsigned long long)
+	    sas_expander->sas_address,
+	    sas_expander->port->port_id);
 
 	spin_lock_irqsave(&ioc->sas_node_lock, flags);
 	list_del(&sas_expander->list);
@@ -10283,13 +10346,15 @@ static void scsih_remove(struct pci_dev *pdev)
 		if (mpt3sas_port->remote_identify.device_type ==
 		    SAS_END_DEVICE)
 			mpt3sas_device_remove_by_sas_address(ioc,
-			    mpt3sas_port->remote_identify.sas_address);
+			    mpt3sas_port->remote_identify.sas_address,
+			    mpt3sas_port->hba_port);
 		else if (mpt3sas_port->remote_identify.device_type ==
 		    SAS_EDGE_EXPANDER_DEVICE ||
 		    mpt3sas_port->remote_identify.device_type ==
 		    SAS_FANOUT_EXPANDER_DEVICE)
 			mpt3sas_expander_remove(ioc,
-			    mpt3sas_port->remote_identify.sas_address);
+			    mpt3sas_port->remote_identify.sas_address,
+			    mpt3sas_port->hba_port);
 	}
 
 	list_for_each_entry_safe(port, port_next,
diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c
index aab3b14..54c004e 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_transport.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c
@@ -64,6 +64,7 @@
  * _transport_sas_node_find_by_sas_address - sas node search
  * @ioc: per adapter object
  * @sas_address: sas address of expander or sas host
+ * @port: hba port entry
  * Context: Calling function should acquire ioc->sas_node_lock.
  *
  * Search for either hba phys or expander device based on handle, then returns
@@ -71,13 +72,13 @@
  */
 static struct _sas_node *
 _transport_sas_node_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
-	u64 sas_address)
+	u64 sas_address, struct hba_port *port)
 {
 	if (ioc->sas_hba.sas_address == sas_address)
 		return &ioc->sas_hba;
 	else
 		return mpt3sas_scsih_expander_find_by_sas_address(ioc,
-		    sas_address);
+		    sas_address, port);
 }
 
 /**
@@ -439,6 +440,7 @@ _transport_delete_port(struct MPT3SAS_ADAPTER *ioc,
 	struct _sas_port *mpt3sas_port)
 {
 	u64 sas_address = mpt3sas_port->remote_identify.sas_address;
+	struct hba_port *port = mpt3sas_port->hba_port;
 	enum sas_device_type device_type =
 	    mpt3sas_port->remote_identify.device_type;
 
@@ -448,10 +450,11 @@ _transport_delete_port(struct MPT3SAS_ADAPTER *ioc,
 
 	ioc->logging_level |= MPT_DEBUG_TRANSPORT;
 	if (device_type == SAS_END_DEVICE)
-		mpt3sas_device_remove_by_sas_address(ioc, sas_address);
+		mpt3sas_device_remove_by_sas_address(ioc,
+		    sas_address, port);
 	else if (device_type == SAS_EDGE_EXPANDER_DEVICE ||
 	    device_type == SAS_FANOUT_EXPANDER_DEVICE)
-		mpt3sas_expander_remove(ioc, sas_address);
+		mpt3sas_expander_remove(ioc, sas_address, port);
 	ioc->logging_level &= ~MPT_DEBUG_TRANSPORT;
 }
 
@@ -571,18 +574,21 @@ _transport_del_phy_from_an_existing_port(struct MPT3SAS_ADAPTER *ioc,
  * @ioc: per adapter object
  * @sas_node: sas node object (either expander or sas host)
  * @sas_address: sas address of device being added
+ * @port: hba port entry
  *
  * See the explanation above from _transport_delete_duplicate_port
  */
 static void
 _transport_sanity_check(struct MPT3SAS_ADAPTER *ioc, struct _sas_node *sas_node,
-	u64 sas_address)
+	u64 sas_address, struct hba_port *port)
 {
 	int i;
 
 	for (i = 0; i < sas_node->num_phys; i++) {
 		if (sas_node->phy[i].remote_identify.sas_address != sas_address)
 			continue;
+		if (sas_node->phy[i].port != port)
+			continue;
 		if (sas_node->phy[i].phy_belongs_to_port == 1)
 			_transport_del_phy_from_an_existing_port(ioc, sas_node,
 			    &sas_node->phy[i]);
@@ -631,7 +637,8 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
 	INIT_LIST_HEAD(&mpt3sas_port->port_list);
 	INIT_LIST_HEAD(&mpt3sas_port->phy_list);
 	spin_lock_irqsave(&ioc->sas_node_lock, flags);
-	sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
+	sas_node = _transport_sas_node_find_by_sas_address(ioc,
+	    sas_address, hba_port);
 	spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 
 	if (!sas_node) {
@@ -655,7 +662,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
 
 	mpt3sas_port->hba_port = hba_port;
 	_transport_sanity_check(ioc, sas_node,
-	    mpt3sas_port->remote_identify.sas_address);
+	    mpt3sas_port->remote_identify.sas_address, hba_port);
 
 	for (i = 0; i < sas_node->num_phys; i++) {
 		if (sas_node->phy[i].remote_identify.sas_address !=
@@ -676,6 +683,18 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
 		goto out_fail;
 	}
 
+	if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) {
+		sas_device = mpt3sas_get_sdev_by_addr(ioc,
+		    mpt3sas_port->remote_identify.sas_address,
+		    mpt3sas_port->hba_port);
+		if (!sas_device) {
+			ioc_err(ioc, "failure at %s:%d/%s()!\n",
+			    __FILE__, __LINE__, __func__);
+			goto out_fail;
+		}
+		sas_device->pend_sas_rphy_add = 1;
+	}
+
 	if (!sas_node->parent_dev) {
 		ioc_err(ioc, "failure at %s:%d/%s()!\n",
 			__FILE__, __LINE__, __func__);
@@ -716,18 +735,6 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
 
 	rphy->identify = mpt3sas_port->remote_identify;
 
-	if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) {
-		sas_device = mpt3sas_get_sdev_by_addr(ioc,
-				    mpt3sas_port->remote_identify.sas_address);
-		if (!sas_device) {
-			dfailprintk(ioc,
-				    ioc_info(ioc, "failure at %s:%d/%s()!\n",
-					     __FILE__, __LINE__, __func__));
-			goto out_fail;
-		}
-		sas_device->pend_sas_rphy_add = 1;
-	}
-
 	if ((sas_rphy_add(rphy))) {
 		ioc_err(ioc, "failure at %s:%d/%s()!\n",
 			__FILE__, __LINE__, __func__);
@@ -793,7 +800,7 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
 
 	spin_lock_irqsave(&ioc->sas_node_lock, flags);
 	sas_node = _transport_sas_node_find_by_sas_address(ioc,
-	    sas_address_parent);
+	    sas_address_parent, port);
 	if (!sas_node) {
 		spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 		return;
@@ -1020,7 +1027,8 @@ mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc,
 		return;
 
 	spin_lock_irqsave(&ioc->sas_node_lock, flags);
-	sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
+	sas_node = _transport_sas_node_find_by_sas_address(ioc,
+	    sas_address, port);
 	if (!sas_node) {
 		spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 		return;
@@ -1267,10 +1275,13 @@ _transport_get_linkerrors(struct sas_phy *phy)
 	unsigned long flags;
 	Mpi2ConfigReply_t mpi_reply;
 	Mpi2SasPhyPage1_t phy_pg1;
+	struct hba_port *port = phy->hostdata;
+	int port_id = port->port_id;
 
 	spin_lock_irqsave(&ioc->sas_node_lock, flags);
 	if (_transport_sas_node_find_by_sas_address(ioc,
-	    phy->identify.sas_address) == NULL) {
+	    phy->identify.sas_address,
+	    mpt3sas_get_port_by_id(ioc, port_id)) == NULL) {
 		spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 		return -EINVAL;
 	}
@@ -1321,7 +1332,7 @@ _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
 
 	spin_lock_irqsave(&ioc->sas_device_lock, flags);
 	sas_device = __mpt3sas_get_sdev_by_addr(ioc,
-	    rphy->identify.sas_address);
+	    rphy->identify.sas_address, 0);
 	if (sas_device) {
 		*identifier = sas_device->enclosure_logical_id;
 		rc = 0;
@@ -1351,7 +1362,7 @@ _transport_get_bay_identifier(struct sas_rphy *rphy)
 
 	spin_lock_irqsave(&ioc->sas_device_lock, flags);
 	sas_device = __mpt3sas_get_sdev_by_addr(ioc,
-	    rphy->identify.sas_address);
+	    rphy->identify.sas_address, 0);
 	if (sas_device) {
 		rc = sas_device->slot;
 		sas_device_put(sas_device);
@@ -1554,11 +1565,14 @@ _transport_phy_reset(struct sas_phy *phy, int hard_reset)
 	struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
 	Mpi2SasIoUnitControlReply_t mpi_reply;
 	Mpi2SasIoUnitControlRequest_t mpi_request;
+	struct hba_port *port = phy->hostdata;
+	int port_id = port->port_id;
 	unsigned long flags;
 
 	spin_lock_irqsave(&ioc->sas_node_lock, flags);
 	if (_transport_sas_node_find_by_sas_address(ioc,
-	    phy->identify.sas_address) == NULL) {
+	    phy->identify.sas_address,
+	    mpt3sas_get_port_by_id(ioc, port_id)) == NULL) {
 		spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 		return -EINVAL;
 	}
@@ -1611,10 +1625,13 @@ _transport_phy_enable(struct sas_phy *phy, int enable)
 	int rc = 0;
 	unsigned long flags;
 	int i, discovery_active;
+	struct hba_port *port = phy->hostdata;
+	int port_id = port->port_id;
 
 	spin_lock_irqsave(&ioc->sas_node_lock, flags);
 	if (_transport_sas_node_find_by_sas_address(ioc,
-	    phy->identify.sas_address) == NULL) {
+	    phy->identify.sas_address,
+	    mpt3sas_get_port_by_id(ioc, port_id)) == NULL) {
 		spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 		return -EINVAL;
 	}
@@ -1748,10 +1765,13 @@ _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
 	int i;
 	int rc = 0;
 	unsigned long flags;
+	struct hba_port *port = phy->hostdata;
+	int port_id = port->port_id;
 
 	spin_lock_irqsave(&ioc->sas_node_lock, flags);
 	if (_transport_sas_node_find_by_sas_address(ioc,
-	    phy->identify.sas_address) == NULL) {
+	    phy->identify.sas_address,
+	    mpt3sas_get_port_by_id(ioc, port_id)) == NULL) {
 		spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 		return -EINVAL;
 	}
-- 
2.18.4


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4175 bytes --]

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 06/14] mpt3sas: Rename transport_del_phy_from_an_existing_port
  2020-10-09 17:14 [PATCH 00/14] mpt3sas: Add support for multi-port path topology Sreekanth Reddy
                   ` (4 preceding siblings ...)
  2020-10-09 17:14 ` [PATCH 05/14] mpt3sas: Get device objects using sas_address & portID Sreekanth Reddy
@ 2020-10-09 17:14 ` Sreekanth Reddy
  2020-10-09 17:14 ` [PATCH 07/14] mpt3sas: Get sas_device objects using device's rphy Sreekanth Reddy
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 18+ messages in thread
From: Sreekanth Reddy @ 2020-10-09 17:14 UTC (permalink / raw)
  To: martin.petersen
  Cc: linux-scsi, sathya.prakash, suganath-prabu.subramani, Sreekanth Reddy

[-- Attachment #1: Type: text/plain, Size: 5698 bytes --]

* Renamed _transport_add_phy_to_an_existing_port to
  mpt3sas_transport_add_phy_to_an_existing_port &
  _transport_del_phy_from_an_existing_port to
  mpt3sas_transport_del_phy_from_an_existing_port,
  as driver has to call these functions from outside
  mpt3sas_transport.c file now.

* Added extra function argument 'port' of type
  struct hba_port in above renamed functions.

* Also in above functions, check for portID before
  adding/removing the phy from the _sas_port object.
  i.e. add/remove the phy from _sas_port object only
  if _sas_port's port object and phy's port object
  are the same.

Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.h      |  7 +++++
 drivers/scsi/mpt3sas/mpt3sas_transport.c | 35 ++++++++++++++++--------
 2 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
index b5d1fc5..24db627 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -1811,6 +1811,13 @@ void mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc,
 	struct hba_port *port);
 extern struct sas_function_template mpt3sas_transport_functions;
 extern struct scsi_transport_template *mpt3sas_transport_template;
+void
+mpt3sas_transport_del_phy_from_an_existing_port(struct MPT3SAS_ADAPTER *ioc,
+	struct _sas_node *sas_node, struct _sas_phy *mpt3sas_phy);
+void
+mpt3sas_transport_add_phy_to_an_existing_port(struct MPT3SAS_ADAPTER *ioc,
+	struct _sas_node *sas_node, struct _sas_phy *mpt3sas_phy,
+	u64 sas_address, struct hba_port *port);
 /* trigger data externs */
 void mpt3sas_send_trigger_data_event(struct MPT3SAS_ADAPTER *ioc,
 	struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c
index 54c004e..560ce32 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_transport.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c
@@ -503,16 +503,17 @@ _transport_add_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_port *mpt3sas_port,
 }
 
 /**
- * _transport_add_phy_to_an_existing_port - adding new phy to existing port
+ * mpt3sas_transport_add_phy_to_an_existing_port - adding new phy to existing port
  * @ioc: per adapter object
  * @sas_node: sas node object (either expander or sas host)
  * @mpt3sas_phy: mpt3sas per phy object
  * @sas_address: sas address of device/expander were phy needs to be added to
+ * @port: hba port entry
  */
-static void
-_transport_add_phy_to_an_existing_port(struct MPT3SAS_ADAPTER *ioc,
+void
+mpt3sas_transport_add_phy_to_an_existing_port(struct MPT3SAS_ADAPTER *ioc,
 	struct _sas_node *sas_node, struct _sas_phy *mpt3sas_phy,
-	u64 sas_address)
+	u64 sas_address, struct hba_port *port)
 {
 	struct _sas_port *mpt3sas_port;
 	struct _sas_phy *phy_srch;
@@ -520,11 +521,16 @@ _transport_add_phy_to_an_existing_port(struct MPT3SAS_ADAPTER *ioc,
 	if (mpt3sas_phy->phy_belongs_to_port == 1)
 		return;
 
+	if (!port)
+		return;
+
 	list_for_each_entry(mpt3sas_port, &sas_node->sas_port_list,
 	    port_list) {
 		if (mpt3sas_port->remote_identify.sas_address !=
 		    sas_address)
 			continue;
+		if (mpt3sas_port->hba_port != port)
+			continue;
 		list_for_each_entry(phy_srch, &mpt3sas_port->phy_list,
 		    port_siblings) {
 			if (phy_srch == mpt3sas_phy)
@@ -537,13 +543,13 @@ _transport_add_phy_to_an_existing_port(struct MPT3SAS_ADAPTER *ioc,
 }
 
 /**
- * _transport_del_phy_from_an_existing_port - delete phy from existing port
+ * mpt3sas_transport_del_phy_from_an_existing_port - delete phy from existing port
  * @ioc: per adapter object
  * @sas_node: sas node object (either expander or sas host)
  * @mpt3sas_phy: mpt3sas per phy object
  */
-static void
-_transport_del_phy_from_an_existing_port(struct MPT3SAS_ADAPTER *ioc,
+void
+mpt3sas_transport_del_phy_from_an_existing_port(struct MPT3SAS_ADAPTER *ioc,
 	struct _sas_node *sas_node, struct _sas_phy *mpt3sas_phy)
 {
 	struct _sas_port *mpt3sas_port, *next;
@@ -559,7 +565,11 @@ _transport_del_phy_from_an_existing_port(struct MPT3SAS_ADAPTER *ioc,
 			if (phy_srch != mpt3sas_phy)
 				continue;
 
-			if (mpt3sas_port->num_phys == 1)
+			/*
+			 * Don't delete port during host reset,
+			 * just delete phy.
+			 */
+			if (mpt3sas_port->num_phys == 1 && !ioc->shost_recovery)
 				_transport_delete_port(ioc, mpt3sas_port);
 			else
 				_transport_delete_phy(ioc, mpt3sas_port,
@@ -590,8 +600,8 @@ _transport_sanity_check(struct MPT3SAS_ADAPTER *ioc, struct _sas_node *sas_node,
 		if (sas_node->phy[i].port != port)
 			continue;
 		if (sas_node->phy[i].phy_belongs_to_port == 1)
-			_transport_del_phy_from_an_existing_port(ioc, sas_node,
-			    &sas_node->phy[i]);
+			mpt3sas_transport_del_phy_from_an_existing_port(ioc,
+			    sas_node, &sas_node->phy[i]);
 	}
 }
 
@@ -1040,8 +1050,6 @@ 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);
-		_transport_add_phy_to_an_existing_port(ioc, sas_node,
-		    mpt3sas_phy, mpt3sas_phy->remote_identify.sas_address);
 		if (sas_node->handle <= ioc->sas_hba.num_phys) {
 			list_for_each_entry(hba_port,
 			    &ioc->port_table_list, list) {
@@ -1051,6 +1059,9 @@ mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc,
 					    (1 << mpt3sas_phy->phy_id);
 			}
 		}
+		mpt3sas_transport_add_phy_to_an_existing_port(ioc, sas_node,
+		    mpt3sas_phy, mpt3sas_phy->remote_identify.sas_address,
+		    port);
 	} else
 		memset(&mpt3sas_phy->remote_identify, 0 , sizeof(struct
 		    sas_identify));
-- 
2.18.4


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4175 bytes --]

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 07/14] mpt3sas: Get sas_device objects using device's rphy
  2020-10-09 17:14 [PATCH 00/14] mpt3sas: Add support for multi-port path topology Sreekanth Reddy
                   ` (5 preceding siblings ...)
  2020-10-09 17:14 ` [PATCH 06/14] mpt3sas: Rename transport_del_phy_from_an_existing_port Sreekanth Reddy
@ 2020-10-09 17:14 ` Sreekanth Reddy
  2020-10-09 17:14 ` [PATCH 08/14] mpt3sas: Update hba_port objects after host reset Sreekanth Reddy
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 18+ messages in thread
From: Sreekanth Reddy @ 2020-10-09 17:14 UTC (permalink / raw)
  To: martin.petersen
  Cc: linux-scsi, sathya.prakash, suganath-prabu.subramani, Sreekanth Reddy

[-- Attachment #1: Type: text/plain, Size: 5299 bytes --]

In below scsi_host_template & sas_function_template callback
functions, the driver won't have PhysicalPort number information
to retrieve the sas_device object using SAS Address & PhysicalPort
number. So, in these callback functions the device's rphy
object is used to retrieve sas_device object for the device.

.target_alloc,
.get_enclosure_identifier
.get_bay_identifier

When a rphy (of type sas_rphy) object is allocated then it's
address is saved in corresponding sas_device object's rphy
field. so in __mpt3sas_get_sdev_by_rphy(), driver loops over
all the sas_device objects from sas_device_list list to
retrieve the sas_device objects who's rphy matches with
provided rphy.

Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.h      |  5 +++
 drivers/scsi/mpt3sas/mpt3sas_scsih.c     | 41 ++++++++++++++++++++++--
 drivers/scsi/mpt3sas/mpt3sas_transport.c |  7 ++--
 3 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 24db627..047d234 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -537,6 +537,8 @@ struct _internal_cmd {
  * @chassis_slot: chassis slot
  * @is_chassis_slot_valid: chassis slot valid or not
  * @port: hba port entry containing device's port number info
+ * @rphy: device's sas_rphy address used to identify this device structure in
+ *	target_alloc callback function
  */
 struct _sas_device {
 	struct list_head list;
@@ -564,6 +566,7 @@ struct _sas_device {
 	u8	connector_name[5];
 	struct kref refcount;
 	struct hba_port *port;
+	struct sas_rphy *rphy;
 };
 
 static inline void sas_device_get(struct _sas_device *s)
@@ -1681,6 +1684,8 @@ void mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc);
 struct _raid_device *
 mpt3sas_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle);
 void mpt3sas_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
+struct _sas_device *
+__mpt3sas_get_sdev_by_rphy(struct MPT3SAS_ADAPTER *ioc, struct sas_rphy *rphy);
 
 /* config shared API */
 u8 mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 4542d66..afb381d 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -638,6 +638,44 @@ mpt3sas_get_pdev_from_target(struct MPT3SAS_ADAPTER *ioc,
 	return ret;
 }
 
+
+/**
+ * __mpt3sas_get_sdev_by_rphy - sas device search
+ * @ioc: per adapter object
+ * @rphy: sas_rphy pointer
+ *
+ * Context: This function will acquire ioc->sas_device_lock and will release
+ * before returning the sas_device object.
+ *
+ * This searches for sas_device from rphy object
+ * then return sas_device object.
+ */
+struct _sas_device *
+__mpt3sas_get_sdev_by_rphy(struct MPT3SAS_ADAPTER *ioc,
+	struct sas_rphy *rphy)
+{
+	struct _sas_device *sas_device;
+
+	assert_spin_locked(&ioc->sas_device_lock);
+
+	list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
+		if (sas_device->rphy != rphy)
+			continue;
+		sas_device_get(sas_device);
+		return sas_device;
+	}
+
+	sas_device = NULL;
+	list_for_each_entry(sas_device, &ioc->sas_device_init_list, list) {
+		if (sas_device->rphy != rphy)
+			continue;
+		sas_device_get(sas_device);
+		return sas_device;
+	}
+
+	return NULL;
+}
+
 /**
  * mpt3sas_get_sdev_by_addr - get _sas_device object corresponding to provided
  *				sas address from sas_device_list list
@@ -1815,8 +1853,7 @@ scsih_target_alloc(struct scsi_target *starget)
 	/* sas/sata devices */
 	spin_lock_irqsave(&ioc->sas_device_lock, flags);
 	rphy = dev_to_rphy(starget->dev.parent);
-	sas_device = __mpt3sas_get_sdev_by_addr(ioc,
-	   rphy->identify.sas_address, NULL);
+	sas_device = __mpt3sas_get_sdev_by_rphy(ioc, rphy);
 
 	if (sas_device) {
 		sas_target_priv_data->handle = sas_device->handle;
diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c
index 560ce32..3cc78c2 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_transport.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c
@@ -733,6 +733,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
 	mpt3sas_port->port = port;
 	if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) {
 		rphy = sas_end_device_alloc(port);
+		sas_device->rphy = rphy;
 		if (sas_node->handle <= ioc->sas_hba.num_phys)
 			hba_port->sas_address = sas_device->sas_address;
 	} else {
@@ -1342,8 +1343,7 @@ _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
 	int rc;
 
 	spin_lock_irqsave(&ioc->sas_device_lock, flags);
-	sas_device = __mpt3sas_get_sdev_by_addr(ioc,
-	    rphy->identify.sas_address, 0);
+	sas_device = __mpt3sas_get_sdev_by_rphy(ioc, rphy);
 	if (sas_device) {
 		*identifier = sas_device->enclosure_logical_id;
 		rc = 0;
@@ -1372,8 +1372,7 @@ _transport_get_bay_identifier(struct sas_rphy *rphy)
 	int rc;
 
 	spin_lock_irqsave(&ioc->sas_device_lock, flags);
-	sas_device = __mpt3sas_get_sdev_by_addr(ioc,
-	    rphy->identify.sas_address, 0);
+	sas_device = __mpt3sas_get_sdev_by_rphy(ioc, rphy);
 	if (sas_device) {
 		rc = sas_device->slot;
 		sas_device_put(sas_device);
-- 
2.18.4


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4175 bytes --]

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 08/14] mpt3sas: Update hba_port objects after host reset
  2020-10-09 17:14 [PATCH 00/14] mpt3sas: Add support for multi-port path topology Sreekanth Reddy
                   ` (6 preceding siblings ...)
  2020-10-09 17:14 ` [PATCH 07/14] mpt3sas: Get sas_device objects using device's rphy Sreekanth Reddy
@ 2020-10-09 17:14 ` Sreekanth Reddy
  2020-10-12 12:22     ` Dan Carpenter
  2020-10-09 17:14 ` [PATCH 09/14] mpt3sas: Set valid PhysicalPort in SMPPassThrough Sreekanth Reddy
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 18+ messages in thread
From: Sreekanth Reddy @ 2020-10-09 17:14 UTC (permalink / raw)
  To: martin.petersen
  Cc: linux-scsi, sathya.prakash, suganath-prabu.subramani, Sreekanth Reddy

[-- Attachment #1: Type: text/plain, Size: 18932 bytes --]

During host reset there are chances that the Port number
allocated by the firmware for the attached devices may change.
Also it may be possible that some HBA phy’s may go down/come up
after reset. So the driver can’t just trust the HBA Port table
that it has populated before host reset as valid. So it has to
update the HBA Port table in such a way that it shouldn’t
disturb the drives which are still accessible even after
host reset.

Driver follows below algorithm to update the ‘HBA Port table’
during host reset,
  I. After host reset operation and before marking the
     devices as responding/non-responding, create a temporary
     Port table called “New Port table” by parsing each of the
     HBA PHY’s Phy data info read from SAS IOUnit Page0,
        a. Check whether Phy’s negotiated link rate is greater
           than 1.5Gbps, if not go to next Phy,
        b. Get the SAS Address of the attached device,
        c. Create a new entry in the ‘New Port table’ with
           SAS Address field filled with attached device’s
           SAS Address, port number with Phy’s Port number
           (read from SAS IOUnit Page0) and enable bit in the
           ‘Phy mask’ field corresponding to current Phy number.
           New entry is created only if the driver won’t find
           any entry in the ‘New Port table’ which matches with
           attached device ‘SAS Address’ & ‘Port Number’. If it
           finds an entry with matches with attached device
           ‘SAS Address’ & ‘Port Number’ then the driver takes
           that matched entry and will enable current Phy number
           bit in the ‘Phy mask’ field.
        d. After parsing all the HBA phy’s info, the driver will
           have complete Port table info in “New Port table”.
  II. Mark all the existing sas_device & sas_expander device
      structures as ‘dirty’.
  III. Mark each entry of the HBA Port list’s as ‘dirty’.
  IV. Take each entry from ‘New Port table’ one by one and check
      whether the taken entry has any corresponding matched entry
      (which is marked as ‘dirty’) in the HBA Port table or not.
      While looking for a corresponding matched entry, look for
      matched entry in the sequence from top row to bottom row
      listed in below table. If you find any matched entry
      (according to any of the rules tabulated below) then perform
      the action mentioned in the ‘Action’ column in that matched rule.
===========================================================================
|Search  |SAS     | Phy Mask | Port    | Possibilities| Action            |
|every   |Address |    or    | Number  |              | required          |
|entry   |matched?| subset of| matched?|              |                   |
|in below|        | phy mask |         |              |                   |
|sequence|        | matched? |         |              |                   |
===========================================================================
|  1     |matched | matched  | matched | nothing      |* unmark HBA port  |
|        |        |          |         | changed      |table entry as     |
|        |        |          |         |              |dirty              |
---------------------------------------------------------------------------
|  2     |matched | matched  | not     | port number  |* Update port      |
|        |        |          | matched | is changed   |number in the      |
|        |        |          |         |              |matched port table |
|        |        |          |         |              |entry              |
|        |        |          |         |              |* unmask HBA port  |
|        |        |          |         |              |table entry as     |
|        |        |          |         |              | dirty             |
---------------------------------------------------------------------------
|  3.a   |matched | subset of| matched |some phys     |*Add these new phys|
|        |        | phy mask | (or)    |might have    |to current port in |
|        |        | matched  | not     |enabled which |STL                |
|        |        |          | matched |are previously|* Update phy mask  |
|        |        |          | (but    |disabled      |field in HBA's port|
|        |        |          | first   |              |tables's matched   |
|        |        |          | look for|              |entry,             |
|        |        |          | matched |              |*Update port number|
|        |        |          | one)    |              |in the matched port|
|        |        |          |         |              |table entry (if    |
|        |        |          |         |              |port number is     |
|        |        |          |         |              |changed),          |
|        |        |          |         |              |* Unmask HBA port  |
|        |        |          |         |              |table entry as     |
|        |        |          |         |              |dirty              |
---------------------------------------------------------------------------
|  3.b   |matched | subset of| matched |some phys     |*Remove these phys |
|        |        | phy mask | (or)    |might have    |from current port  |
|        |        | matched  | not     |disabled which|in STL             |
|        |        |          | matched |are previously|* Update phy mask  |
|        |        |          | (but    |enabled       |field in HBA's port|
|        |        |          | first   |              |tables's matched   |
|        |        |          | look for|              |entry,             |
|        |        |          | matched |              |*Update port number|
|        |        |          | one)    |              |in the matched port|
|        |        |          |         |              |table entry (if    |
|        |        |          |         |              |port number is     |
|        |        |          |         |              |changed),          |
|        |        |          |         |              |* Unmask HBA port  |
|        |        |          |         |              |table entry as     |
|        |        |          |         |              |dirty              |
---------------------------------------------------------------------------
|  4     |matched | not      | matched |A cable       |*Remove old phys & |
|        |        | matched  | (or)    |attached to an|new phys to current|
|        |        |          | not     |expander is   |port in STL        |
|        |        |          | matched |changed to    |* Update phy mask  |
|        |        |          |         |another HBA   |field in HBA's port|
|        |        |          |         |port during   |tables's matched   |
|        |        |          |         |reset         |entry,             |
|        |        |          |         |              |*Update port number|
|        |        |          |         |              |in the matched port|
|        |        |          |         |              |table entry (if    |
|        |        |          |         |              |port number is     |
|        |        |          |         |              |changed),          |
|        |        |          |         |              |* Unmask HBA port  |
|        |        |          |         |              |table entry as     |
|        |        |          |         |              |dirty              |
---------------------------------------------------------------------------

V. Delete the hba_port objects which are still marked as dirty.

Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 337 +++++++++++++++++++++++++++
 1 file changed, 337 insertions(+)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index afb381d..05d43c4 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -5816,6 +5816,341 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
 	return 0;
 }
 
+/**
+ * _scsih_get_port_table_after_reset - Construct temporary port table
+ * @ioc: per adapter object
+ * @port_table: address where port table needs to be constructed
+ *
+ * return number of HBA port entries available after reset.
+ */
+static int
+_scsih_get_port_table_after_reset(struct MPT3SAS_ADAPTER *ioc,
+	struct hba_port *port_table)
+{
+	u16 sz, ioc_status;
+	int i, j;
+	Mpi2ConfigReply_t mpi_reply;
+	Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
+	u16 attached_handle;
+	u64 attached_sas_addr;
+	u8 found = 0, port_count = 0, port_id;
+
+	sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys
+	    * sizeof(Mpi2SasIOUnit0PhyData_t));
+	sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
+	if (!sas_iounit_pg0) {
+		ioc_err(ioc, "failure at %s:%d/%s()!\n",
+		    __FILE__, __LINE__, __func__);
+		return port_count;
+	}
+
+	if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
+	    sas_iounit_pg0, sz)) != 0)
+		goto out;
+	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
+	if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
+		goto out;
+	for (i = 0; i < ioc->sas_hba.num_phys; i++) {
+		found = 0;
+		if ((sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4) <
+		    MPI2_SAS_NEG_LINK_RATE_1_5)
+			continue;
+		attached_handle =
+		    le16_to_cpu(sas_iounit_pg0->PhyData[i].AttachedDevHandle);
+		if (_scsih_get_sas_address(
+		    ioc, attached_handle, &attached_sas_addr) != 0) {
+			ioc_err(ioc, "failure at %s:%d/%s()!\n",
+			    __FILE__, __LINE__, __func__);
+			continue;
+		}
+
+		for (j = 0; j < port_count; j++) {
+			port_id = sas_iounit_pg0->PhyData[i].Port;
+			if (port_table[j].port_id == port_id &&
+			    port_table[j].sas_address == attached_sas_addr) {
+				port_table[j].phy_mask |= (1 << i);
+				found = 1;
+				break;
+			}
+		}
+
+		if (found)
+			continue;
+
+		port_id = sas_iounit_pg0->PhyData[i].Port;
+		port_table[port_count].port_id = port_id;
+		port_table[port_count].phy_mask = (1 << i);
+		port_table[port_count].sas_address = attached_sas_addr;
+		port_count++;
+	}
+out:
+	kfree(sas_iounit_pg0);
+	return port_count;
+}
+
+enum hba_port_matched_codes {
+	MATCHED_WITH_ADDR_AND_PHYMASK = 1,
+	MATCHED_WITH_ADDR_SUBPHYMASK_AND_PORT,
+	MATCHED_WITH_ADDR_AND_SUBPHYMASK,
+	MATCHED_WITH_ADDR,
+};
+
+/**
+ * _scsih_look_and_get_matched_port_entry - Get matched hba port entry
+ *					from HBA port table
+ * @ioc: per adapter object
+ * @port_entry - hba port entry from temporary port table which needs to be
+ *		searched for matched entry in the HBA port table
+ * @matched_port_entry - save matched hba port entry here
+ * @count - count of matched entries
+ *
+ * return type of matched entry found.
+ */
+static enum hba_port_matched_codes
+_scsih_look_and_get_matched_port_entry(struct MPT3SAS_ADAPTER *ioc,
+	struct hba_port *port_entry,
+	struct hba_port **matched_port_entry, int *count)
+{
+	struct hba_port *port_table_entry, *matched_port = NULL;
+	enum hba_port_matched_codes matched_code;
+	int lcount = 0;
+	*matched_port_entry = NULL;
+
+	list_for_each_entry(port_table_entry, &ioc->port_table_list, list) {
+		if (!(port_table_entry->flags & HBA_PORT_FLAG_DIRTY_PORT))
+			continue;
+
+		if ((port_table_entry->sas_address == port_entry->sas_address)
+		    && (port_table_entry->phy_mask == port_entry->phy_mask)) {
+			matched_code = MATCHED_WITH_ADDR_AND_PHYMASK;
+			matched_port = port_table_entry;
+			break;
+		}
+
+		if ((port_table_entry->sas_address == port_entry->sas_address)
+		    && (port_table_entry->phy_mask & port_entry->phy_mask)
+		    && (port_table_entry->port_id == port_entry->port_id)) {
+			matched_code = MATCHED_WITH_ADDR_SUBPHYMASK_AND_PORT;
+			matched_port = port_table_entry;
+			continue;
+		}
+
+		if ((port_table_entry->sas_address == port_entry->sas_address)
+		    && (port_table_entry->phy_mask & port_entry->phy_mask)) {
+			if (matched_code ==
+			    MATCHED_WITH_ADDR_SUBPHYMASK_AND_PORT)
+				continue;
+			matched_code = MATCHED_WITH_ADDR_AND_SUBPHYMASK;
+			matched_port = port_table_entry;
+			continue;
+		}
+
+		if (port_table_entry->sas_address == port_entry->sas_address) {
+			if (matched_code ==
+			    MATCHED_WITH_ADDR_SUBPHYMASK_AND_PORT)
+				continue;
+			if (matched_code == MATCHED_WITH_ADDR_AND_SUBPHYMASK)
+				continue;
+			matched_code = MATCHED_WITH_ADDR;
+			matched_port = port_table_entry;
+			lcount++;
+		}
+	}
+
+	*matched_port_entry = matched_port;
+	if (matched_code ==  MATCHED_WITH_ADDR)
+		*count = lcount;
+	return matched_code;
+}
+
+/**
+ * _scsih_del_phy_part_of_anther_port - remove phy if it
+ *				is a part of anther port
+ *@ioc: per adapter object
+ *@port_table: port table after reset
+ *@index: hba port entry index
+ *@port_count: number of ports available after host reset
+ *@offset: HBA phy bit offset
+ *
+ */
+static void
+_scsih_del_phy_part_of_anther_port(struct MPT3SAS_ADAPTER *ioc,
+	struct hba_port *port_table,
+	int index, u8 port_count, int offset)
+{
+	struct _sas_node *sas_node = &ioc->sas_hba;
+	u32 i, found = 0;
+
+	for (i = 0; i < port_count; i++) {
+		if (i == index)
+			continue;
+
+		if (port_table[i].phy_mask & (1 << offset)) {
+			mpt3sas_transport_del_phy_from_an_existing_port(
+			    ioc, sas_node, &sas_node->phy[offset]);
+			found = 1;
+			break;
+		}
+	}
+	if (!found)
+		port_table[index].phy_mask |= (1 << offset);
+}
+
+/**
+ * _scsih_add_or_del_phys_from_existing_port - add/remove phy to/from
+ *						right port
+ *@ioc: per adapter object
+ *@hba_port_entry: hba port table entry
+ *@port_table: temporary port table
+ *@index: hba port entry index
+ *@port_count: number of ports available after host reset
+ *
+ */
+static void
+_scsih_add_or_del_phys_from_existing_port(struct MPT3SAS_ADAPTER *ioc,
+	struct hba_port *hba_port_entry, struct hba_port *port_table,
+	int index, int port_count)
+{
+	u32 phy_mask, offset = 0;
+	struct _sas_node *sas_node = &ioc->sas_hba;
+
+	phy_mask = hba_port_entry->phy_mask ^ port_table[index].phy_mask;
+
+	for (offset = 0; offset < ioc->sas_hba.num_phys; offset++) {
+		if (phy_mask & (1 << offset)) {
+			if (!(port_table[index].phy_mask & (1 << offset))) {
+				_scsih_del_phy_part_of_anther_port(
+				    ioc, port_table, index, port_count,
+				    offset);
+				continue;
+			}
+			if (sas_node->phy[offset].phy_belongs_to_port)
+				mpt3sas_transport_del_phy_from_an_existing_port(
+				    ioc, sas_node, &sas_node->phy[offset]);
+			mpt3sas_transport_add_phy_to_an_existing_port(
+			    ioc, sas_node, &sas_node->phy[offset],
+			    hba_port_entry->sas_address,
+			    hba_port_entry);
+		}
+	}
+}
+
+/**
+ * _scsih_del_dirty_port_entries - delete dirty port entries from port list
+ *					after host reset
+ *@ioc: per adapter object
+ *
+ */
+static void
+_scsih_del_dirty_port_entries(struct MPT3SAS_ADAPTER *ioc)
+{
+	struct hba_port *port, *port_next;
+
+	list_for_each_entry_safe(port, port_next,
+	    &ioc->port_table_list, list) {
+		if (!(port->flags & HBA_PORT_FLAG_DIRTY_PORT) ||
+		    port->flags & HBA_PORT_FLAG_NEW_PORT)
+			continue;
+
+		drsprintk(ioc, ioc_info(ioc,
+		    "Deleting port table entry %p having Port: %d\t Phy_mask 0x%08x\n",
+		    port, port->port_id, port->phy_mask));
+		list_del(&port->list);
+		kfree(port);
+	}
+}
+
+/**
+ * _scsih_sas_port_refresh - Update HBA port table after host reset
+ * @ioc: per adapter object
+ */
+static void
+_scsih_sas_port_refresh(struct MPT3SAS_ADAPTER *ioc)
+{
+	u32 port_count = 0;
+	struct hba_port *port_table;
+	struct hba_port *port_table_entry;
+	struct hba_port *port_entry = NULL;
+	int i, j, count = 0, lcount = 0;
+	int ret;
+	u64 sas_addr;
+
+	drsprintk(ioc, ioc_info(ioc,
+	    "updating ports for sas_host(0x%016llx)\n",
+	    (unsigned long long)ioc->sas_hba.sas_address));
+
+	port_table = kcalloc(ioc->sas_hba.num_phys,
+	    sizeof(struct hba_port), GFP_KERNEL);
+	if (!port_table)
+		return;
+
+	port_count = _scsih_get_port_table_after_reset(ioc, port_table);
+	if (!port_count)
+		return;
+
+	drsprintk(ioc, ioc_info(ioc, "New Port table\n"));
+	for (j = 0; j < port_count; j++)
+		drsprintk(ioc, ioc_info(ioc,
+		    "Port: %d\t Phy_mask 0x%08x\t sas_addr(0x%016llx)\n",
+		    port_table[j].port_id,
+		    port_table[j].phy_mask, port_table[j].sas_address));
+
+	list_for_each_entry(port_table_entry, &ioc->port_table_list, list)
+		port_table_entry->flags |= HBA_PORT_FLAG_DIRTY_PORT;
+
+	drsprintk(ioc, ioc_info(ioc, "Old Port table\n"));
+	port_table_entry = NULL;
+	list_for_each_entry(port_table_entry, &ioc->port_table_list, list) {
+		drsprintk(ioc, ioc_info(ioc,
+		    "Port: %d\t Phy_mask 0x%08x\t sas_addr(0x%016llx)\n",
+		    port_table_entry->port_id,
+		    port_table_entry->phy_mask,
+		    port_table_entry->sas_address));
+	}
+
+	for (j = 0; j < port_count; j++) {
+		ret = _scsih_look_and_get_matched_port_entry(ioc,
+		    &port_table[j], &port_entry, &count);
+		if (!port_entry) {
+			drsprintk(ioc, ioc_info(ioc,
+			    "No Matched entry for sas_addr(0x%16llx), Port:%d\n",
+			    port_table[j].sas_address,
+			    port_table[j].port_id));
+			continue;
+		}
+
+		switch (ret) {
+		case MATCHED_WITH_ADDR_SUBPHYMASK_AND_PORT:
+		case MATCHED_WITH_ADDR_AND_SUBPHYMASK:
+			_scsih_add_or_del_phys_from_existing_port(ioc,
+			    port_entry, port_table, j, port_count);
+			break;
+		case MATCHED_WITH_ADDR:
+			sas_addr = port_table[j].sas_address;
+			for (i = 0; i < port_count; i++) {
+				if (port_table[i].sas_address == sas_addr)
+					lcount++;
+			}
+
+			if (count > 1 || lcount > 1)
+				port_entry = NULL;
+			else
+				_scsih_add_or_del_phys_from_existing_port(ioc,
+				    port_entry, port_table, j, port_count);
+		}
+
+		if (!port_entry)
+			continue;
+
+		if (port_entry->port_id != port_table[j].port_id)
+			port_entry->port_id = port_table[j].port_id;
+		port_entry->flags &= ~HBA_PORT_FLAG_DIRTY_PORT;
+		port_entry->phy_mask = port_table[j].phy_mask;
+	}
+
+	port_table_entry = NULL;
+}
+
 /**
  * _scsih_sas_host_refresh - refreshing sas host object contents
  * @ioc: per adapter object
@@ -9790,6 +10125,7 @@ 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_prep_device_scan(ioc);
 		_scsih_create_enclosure_list_after_reset(ioc);
 		_scsih_search_responding_sas_devices(ioc);
@@ -9837,6 +10173,7 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
 			ssleep(1);
 		}
 		_scsih_remove_unresponding_devices(ioc);
+		_scsih_del_dirty_port_entries(ioc);
 		_scsih_scan_for_devices_after_reset(ioc);
 		_scsih_set_nvme_max_shutdown_latency(ioc);
 		break;
-- 
2.18.4


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4175 bytes --]

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 09/14] mpt3sas: Set valid PhysicalPort in SMPPassThrough
  2020-10-09 17:14 [PATCH 00/14] mpt3sas: Add support for multi-port path topology Sreekanth Reddy
                   ` (7 preceding siblings ...)
  2020-10-09 17:14 ` [PATCH 08/14] mpt3sas: Update hba_port objects after host reset Sreekanth Reddy
@ 2020-10-09 17:14 ` Sreekanth Reddy
  2020-10-09 17:14 ` [PATCH 10/14] mpt3sas: Handling HBA vSES device Sreekanth Reddy
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 18+ messages in thread
From: Sreekanth Reddy @ 2020-10-09 17:14 UTC (permalink / raw)
  To: martin.petersen
  Cc: linux-scsi, sathya.prakash, suganath-prabu.subramani, Sreekanth Reddy

[-- Attachment #1: Type: text/plain, Size: 7381 bytes --]

Current driver is always setting PhysicalPort field as 0xFF for
SMPPassthrough Request message. So in zoning topologies this
SMPPassthrough command always operates on devices in one zone
(default zone) even when user issues SMP command for other zone
drives.

Now helper functions _transport_get_port_id_by_rphy() &
_transport_get_port_id_by_sas_phy() are defined to get Physical
Port number from sas_rphy & sas_phy respectively for
SMPPassthrough request message so that SMP Passthrough request
message is send to intended zone device.

Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.h      |  2 +
 drivers/scsi/mpt3sas/mpt3sas_scsih.c     |  1 +
 drivers/scsi/mpt3sas/mpt3sas_transport.c | 75 ++++++++++++++++++++++--
 3 files changed, 72 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 047d234..a8e42d1 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -788,6 +788,7 @@ struct _sas_phy {
  * @phy: a list of phys that make up this sas_host/expander
  * @sas_port_list: list of ports attached to this sas_host/expander
  * @port: hba port entry containing node's port number info
+ * @rphy: sas_rphy object of this expander
  */
 struct _sas_node {
 	struct list_head list;
@@ -802,6 +803,7 @@ struct _sas_node {
 	struct hba_port *port;
 	struct	_sas_phy *phy;
 	struct list_head sas_port_list;
+	struct sas_rphy *rphy;
 };
 
 /**
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 05d43c4..855d1ec 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -6509,6 +6509,7 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 		goto out_fail;
 	}
 	sas_expander->parent_dev = &mpt3sas_port->rphy->dev;
+	sas_expander->rphy = mpt3sas_port->rphy;
 
 	for (i = 0 ; i < sas_expander->num_phys ; i++) {
 		if ((mpt3sas_config_get_expander_pg1(ioc, &mpi_reply,
diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c
index 3cc78c2..d52d8b3 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_transport.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c
@@ -60,6 +60,24 @@
 
 #include "mpt3sas_base.h"
 
+/**
+ * _transport_get_port_id_by_sas_phy - get zone's port id that Phy belong to
+ * @phy - sas_phy object
+ *
+ * Return Port number
+ */
+static inline u8
+_transport_get_port_id_by_sas_phy(struct sas_phy *phy)
+{
+	u8 port_id = 0xFF;
+	struct hba_port *port = phy->hostdata;
+
+	if (port)
+		port_id = port->port_id;
+
+	return port_id;
+}
+
 /**
  * _transport_sas_node_find_by_sas_address - sas node search
  * @ioc: per adapter object
@@ -81,6 +99,49 @@ _transport_sas_node_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
 		    sas_address, port);
 }
 
+/**
+ * _transport_get_port_id_by_rphy - Get Port number from rphy object
+ * @ioc: per adapter object
+ * @rphy: sas_rphy object
+ *
+ * Returns Port number.
+ */
+static u8
+_transport_get_port_id_by_rphy(struct MPT3SAS_ADAPTER *ioc,
+	struct sas_rphy *rphy)
+{
+	struct _sas_node *sas_expander;
+	struct _sas_device *sas_device;
+	unsigned long flags;
+	u8 port_id = 0xFF;
+
+	if (!rphy)
+		return port_id;
+
+	if (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE ||
+	    rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE) {
+		spin_lock_irqsave(&ioc->sas_node_lock, flags);
+		list_for_each_entry(sas_expander,
+		    &ioc->sas_expander_list, list) {
+			if (sas_expander->rphy == rphy) {
+				port_id = sas_expander->port->port_id;
+				break;
+			}
+		}
+		spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+	} else if (rphy->identify.device_type == SAS_END_DEVICE) {
+		spin_lock_irqsave(&ioc->sas_device_lock, flags);
+		sas_device = __mpt3sas_get_sdev_by_rphy(ioc, rphy);
+		if (sas_device) {
+			port_id = sas_device->port->port_id;
+			sas_device_put(sas_device);
+		}
+		spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+	}
+
+	return port_id;
+}
+
 /**
  * _transport_convert_phy_link_rate -
  * @link_rate: link rate returned from mpt firmware
@@ -289,7 +350,7 @@ struct rep_manu_reply {
  */
 static int
 _transport_expander_report_manufacture(struct MPT3SAS_ADAPTER *ioc,
-	u64 sas_address, struct sas_expander_device *edev)
+	u64 sas_address, struct sas_expander_device *edev, u8 port_id)
 {
 	Mpi2SmpPassthroughRequest_t *mpi_request;
 	Mpi2SmpPassthroughReply_t *mpi_reply;
@@ -356,7 +417,7 @@ _transport_expander_report_manufacture(struct MPT3SAS_ADAPTER *ioc,
 
 	memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
 	mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
-	mpi_request->PhysicalPort = 0xFF;
+	mpi_request->PhysicalPort = port_id;
 	mpi_request->SASAddress = cpu_to_le64(sas_address);
 	mpi_request->RequestDataLength = cpu_to_le16(data_out_sz);
 	psge = &mpi_request->SGL;
@@ -772,7 +833,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
 	    MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER)
 		_transport_expander_report_manufacture(ioc,
 		    mpt3sas_port->remote_identify.sas_address,
-		    rphy_to_expander_device(rphy));
+		    rphy_to_expander_device(rphy), hba_port->port_id);
 	return mpt3sas_port;
 
  out_fail:
@@ -923,6 +984,7 @@ mpt3sas_transport_add_host_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy
 	    phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
 	phy->maximum_linkrate = _transport_convert_phy_link_rate(
 	    phy_pg0.ProgrammedLinkRate >> 4);
+	phy->hostdata = mpt3sas_phy->port;
 
 	if ((sas_phy_add(phy))) {
 		ioc_err(ioc, "failure at %s:%d/%s()!\n",
@@ -993,6 +1055,7 @@ mpt3sas_transport_add_expander_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy
 	    expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
 	phy->maximum_linkrate = _transport_convert_phy_link_rate(
 	    expander_pg1.ProgrammedLinkRate >> 4);
+	phy->hostdata = mpt3sas_phy->port;
 
 	if ((sas_phy_add(phy))) {
 		ioc_err(ioc, "failure at %s:%d/%s()!\n",
@@ -1197,7 +1260,7 @@ _transport_get_expander_phy_error_log(struct MPT3SAS_ADAPTER *ioc,
 
 	memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
 	mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
-	mpi_request->PhysicalPort = 0xFF;
+	mpi_request->PhysicalPort = _transport_get_port_id_by_sas_phy(phy);
 	mpi_request->VF_ID = 0; /* TODO */
 	mpi_request->VP_ID = 0;
 	mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
@@ -1493,7 +1556,7 @@ _transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc,
 
 	memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
 	mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
-	mpi_request->PhysicalPort = 0xFF;
+	mpi_request->PhysicalPort = _transport_get_port_id_by_sas_phy(phy);
 	mpi_request->VF_ID = 0; /* TODO */
 	mpi_request->VP_ID = 0;
 	mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
@@ -1983,7 +2046,7 @@ _transport_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
 
 	memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
 	mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
-	mpi_request->PhysicalPort = 0xFF;
+	mpi_request->PhysicalPort = _transport_get_port_id_by_rphy(ioc, rphy);
 	mpi_request->SASAddress = (rphy) ?
 	    cpu_to_le64(rphy->identify.sas_address) :
 	    cpu_to_le64(ioc->sas_hba.sas_address);
-- 
2.18.4


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4175 bytes --]

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 10/14] mpt3sas: Handling HBA vSES device
  2020-10-09 17:14 [PATCH 00/14] mpt3sas: Add support for multi-port path topology Sreekanth Reddy
                   ` (8 preceding siblings ...)
  2020-10-09 17:14 ` [PATCH 09/14] mpt3sas: Set valid PhysicalPort in SMPPassThrough Sreekanth Reddy
@ 2020-10-09 17:14 ` Sreekanth Reddy
  2020-10-09 17:14 ` [PATCH 11/14] mpt3sas: Add bypass_dirty_port_flag parameter Sreekanth Reddy
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 18+ messages in thread
From: Sreekanth Reddy @ 2020-10-09 17:14 UTC (permalink / raw)
  To: martin.petersen
  Cc: linux-scsi, sathya.prakash, suganath-prabu.subramani, Sreekanth Reddy

[-- Attachment #1: Type: text/plain, Size: 12152 bytes --]

Each direct attached device will have a unique Port ID,
but with an exception. i.e. HBA vSES may use the same
Port ID of another direct attached device Port's ID.
So special handling is needed for vSES.

Create a virtual_phy object when a new HBA vSES device
is detected and add this virtual_phy object to
vphys_list of port ID's hba_port object.
When the HBA vSES device is removed then remove the
corresponding virtual_phy object from it's parent's
hba_port's vphy_list and free this virtual_vphy object.

Below are variables of virtual_phy objects,
sas_address:    SAS address of vSES device,
phy_mask:       HBA phy bit which is assigned to vSES device
flag:           used during host reset to refresh this virtual_phy object

In hba_port object added vphy_mask field to hold the list
of HBA phy bits which are assigned to vSES devices, Also added
vphy_list list to hold list of virtual_phy objects which holds
the same portID of current hba_port's portID.

Also, added a hba_vphy field in _sas_phy object to determine
whether this _sas_phy object belongs to vSES device or not.

- Allocate a virtual_phy object whenever a virtual phy is detected
  while processing the SASIOUnitPage0's phy data. And this allocated
  virtual_phy object to corresponding PortID''s hba_port's vphy_list.

- When a vSES device is added to the SML then initialize the corresponding
  virtual_phy objects's sas_address field with vSES device's SAS
  Address.

- Free this virtual_phy object during driver unload time and when
  this vSES device is removed.

Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.h      |  23 +++++
 drivers/scsi/mpt3sas/mpt3sas_scsih.c     | 106 +++++++++++++++++++++++
 drivers/scsi/mpt3sas/mpt3sas_transport.c |  80 ++++++++++++++---
 3 files changed, 198 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
index a8e42d1..e7d047a 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -771,6 +771,7 @@ struct _sas_phy {
 	u16	handle;
 	u16	attached_handle;
 	u8	phy_belongs_to_port;
+	u8	hba_vphy;
 	struct hba_port *port;
 };
 
@@ -1023,12 +1024,29 @@ struct reply_post_struct {
 	dma_addr_t			reply_post_free_dma;
 };
 
+/**
+ * struct virtual_phy - vSES phy structure
+ * sas_address: SAS Address of vSES device
+ * phy_mask: vSES device's phy number
+ * flags: flags used to manage this structure
+ */
+struct virtual_phy {
+	struct	list_head list;
+	u64	sas_address;
+	u32	phy_mask;
+	u8	flags;
+};
+
+#define MPT_VPHY_FLAG_DIRTY_PHY	0x01
+
 /**
  * struct hba_port - Saves each HBA's Wide/Narrow port info
  * @sas_address: sas address of this wide/narrow port's attached device
  * @phy_mask: HBA PHY's belonging to this port
  * @port_id: port number
  * @flags: hba port flags
+ * @vphys_mask : mask of vSES devices Phy number
+ * @vphys_list : list containing vSES device structures
  */
 struct hba_port {
 	struct list_head list;
@@ -1036,6 +1054,8 @@ struct hba_port {
 	u32	phy_mask;
 	u8      port_id;
 	u8	flags;
+	u32	vphys_mask;
+	struct list_head vphys_list;
 };
 
 /* hba port flags */
@@ -1688,6 +1708,9 @@ mpt3sas_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle);
 void mpt3sas_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
 struct _sas_device *
 __mpt3sas_get_sdev_by_rphy(struct MPT3SAS_ADAPTER *ioc, struct sas_rphy *rphy);
+struct virtual_phy *
+mpt3sas_get_vphy_by_phy(struct MPT3SAS_ADAPTER *ioc,
+	struct hba_port *port, u32 phy);
 
 /* config shared API */
 u8 mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 855d1ec..22ffc50 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -380,6 +380,30 @@ mpt3sas_get_port_by_id(struct MPT3SAS_ADAPTER *ioc, u8 port_id)
 	return NULL;
 }
 
+/**
+ * mpt3sas_get_vphy_by_phy - get virtual_phy object corresponding to phy number
+ * @ioc: per adapter object
+ * @port: hba_port object
+ * @phy: phy number
+ *
+ * Return virtual_phy object corresponding to phy number.
+ */
+struct virtual_phy *
+mpt3sas_get_vphy_by_phy(struct MPT3SAS_ADAPTER *ioc,
+	struct hba_port *port, u32 phy)
+{
+	struct virtual_phy *vphy, *vphy_next;
+
+	if (!port->vphys_mask)
+		return NULL;
+
+	list_for_each_entry_safe(vphy, vphy_next, &port->vphys_list, list) {
+		if (vphy->phy_mask & (1 << phy))
+			return vphy;
+	}
+	return NULL;
+}
+
 /**
  * _scsih_is_boot_device - search for matching boot device.
  * @sas_address: sas address
@@ -6151,6 +6175,47 @@ _scsih_sas_port_refresh(struct MPT3SAS_ADAPTER *ioc)
 	port_table_entry = NULL;
 }
 
+/**
+ * _scsih_alloc_vphy - allocate virtual_phy object
+ * @ioc: per adapter object
+ * @port_id: Port ID number
+ * @phy_num: HBA Phy number
+ *
+ * Returns allocated virtual_phy object.
+ */
+static struct virtual_phy *
+_scsih_alloc_vphy(struct MPT3SAS_ADAPTER *ioc, u8 port_id, u8 phy_num)
+{
+	struct virtual_phy *vphy;
+	struct hba_port *port;
+
+	port = mpt3sas_get_port_by_id(ioc, port_id);
+	if (!port)
+		return NULL;
+
+	vphy = mpt3sas_get_vphy_by_phy(ioc, port, phy_num);
+	if (!vphy) {
+		vphy = kzalloc(sizeof(struct virtual_phy), GFP_KERNEL);
+		if (!vphy)
+			return NULL;
+
+		/*
+		 * Enable bit corresponding to HBA phy number on it's
+		 * parent hba_port object's vphys_mask field.
+		 */
+		port->vphys_mask |= (1 << phy_num);
+		vphy->phy_mask |= (1 << phy_num);
+
+		INIT_LIST_HEAD(&port->vphys_list);
+		list_add_tail(&vphy->list, &port->vphys_list);
+
+		ioc_info(ioc,
+		    "vphy entry: %p, port id: %d, phy:%d is added to port's vphys_list\n",
+		    vphy, port->port_id, phy_num);
+	}
+	return vphy;
+}
+
 /**
  * _scsih_sas_host_refresh - refreshing sas host object contents
  * @ioc: per adapter object
@@ -6171,6 +6236,7 @@ _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc)
 	u16 attached_handle;
 	u8 link_rate, port_id;
 	struct hba_port *port;
+	Mpi2SasPhyPage0_t phy_pg0;
 
 	dtmprintk(ioc,
 		  ioc_info(ioc, "updating handles for sas_host(0x%016llx)\n",
@@ -6210,6 +6276,31 @@ _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc)
 				port->flags = HBA_PORT_FLAG_NEW_PORT;
 			list_add_tail(&port->list, &ioc->port_table_list);
 		}
+		/*
+		 * Check whether current Phy belongs to HBA vSES device or not.
+		 */
+		if (le32_to_cpu(sas_iounit_pg0->PhyData[i].ControllerPhyDeviceInfo) &
+		    MPI2_SAS_DEVICE_INFO_SEP &&
+		    (link_rate >=  MPI2_SAS_NEG_LINK_RATE_1_5)) {
+			if ((mpt3sas_config_get_phy_pg0(ioc, &mpi_reply,
+			    &phy_pg0, i))) {
+				ioc_err(ioc,
+				    "failure at %s:%d/%s()!\n",
+				     __FILE__, __LINE__, __func__);
+				goto out;
+			}
+			if (!(le32_to_cpu(phy_pg0.PhyInfo) &
+			    MPI2_SAS_PHYINFO_VIRTUAL_PHY))
+				continue;
+			/*
+			 * Allocate a virtual_phy object for vSES device, if
+			 * this vSES device is hot added.
+			 */
+			if (!_scsih_alloc_vphy(ioc, port_id, i))
+				goto out;
+			ioc->sas_hba.phy[i].hba_vphy = 1;
+		}
+
 		ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
 		attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i].
 		    AttachedDevHandle);
@@ -6352,6 +6443,21 @@ _scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc)
 			    &ioc->port_table_list);
 		}
 
+		/*
+		 * Check whether current Phy belongs to HBA vSES device or not.
+		 */
+		if ((le32_to_cpu(phy_pg0.PhyInfo) &
+		    MPI2_SAS_PHYINFO_VIRTUAL_PHY) &&
+		    (phy_pg0.NegotiatedLinkRate >> 4) >=
+		    MPI2_SAS_NEG_LINK_RATE_1_5) {
+			/*
+			 * Allocate a virtual_phy object for vSES device.
+			 */
+			if (!_scsih_alloc_vphy(ioc, port_id, i))
+				goto out;
+			ioc->sas_hba.phy[i].hba_vphy = 1;
+		}
+
 		ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
 		ioc->sas_hba.phy[i].phy_id = i;
 		ioc->sas_hba.phy[i].port = mpt3sas_get_port_by_id(ioc, port_id);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c
index d52d8b3..256dae1 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_transport.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c
@@ -690,6 +690,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
 	struct _sas_device *sas_device = NULL;
 	int i;
 	struct sas_port *port;
+	struct virtual_phy *vphy = NULL;
 
 	if (!hba_port) {
 		ioc_err(ioc, "failure at %s:%d/%s()!\n",
@@ -743,9 +744,20 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
 			continue;
 		list_add_tail(&sas_node->phy[i].port_siblings,
 		    &mpt3sas_port->phy_list);
-		if (sas_node->handle <= ioc->sas_hba.num_phys)
-			hba_port->phy_mask |= (1 << i);
 		mpt3sas_port->num_phys++;
+		if (sas_node->handle <= ioc->sas_hba.num_phys) {
+			if (!sas_node->phy[i].hba_vphy) {
+				hba_port->phy_mask |= (1 << i);
+				continue;
+			}
+
+			vphy = mpt3sas_get_vphy_by_phy(ioc, hba_port, i);
+			if (!vphy) {
+				ioc_err(ioc, "failure at %s:%d/%s()!\n",
+				    __FILE__, __LINE__, __func__);
+				goto out_fail;
+			}
+		}
 	}
 
 	if (!mpt3sas_port->num_phys) {
@@ -795,8 +807,14 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
 	if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) {
 		rphy = sas_end_device_alloc(port);
 		sas_device->rphy = rphy;
-		if (sas_node->handle <= ioc->sas_hba.num_phys)
-			hba_port->sas_address = sas_device->sas_address;
+		if (sas_node->handle <= ioc->sas_hba.num_phys) {
+			if (!vphy)
+				hba_port->sas_address =
+				    sas_device->sas_address;
+			else
+				vphy->sas_address =
+				    sas_device->sas_address;
+		}
 	} else {
 		rphy = sas_expander_alloc(port,
 		    mpt3sas_port->remote_identify.device_type);
@@ -866,6 +884,7 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
 	u8 found = 0;
 	struct _sas_phy *mpt3sas_phy, *next_phy;
 	struct hba_port *hba_port_next, *hba_port = NULL;
+	struct virtual_phy *vphy, *vphy_next = NULL;
 
 	if (!port)
 		return;
@@ -894,17 +913,56 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
 	}
 
 	if (sas_node->handle <= ioc->sas_hba.num_phys) {
+		if (port->vphys_mask) {
+			list_for_each_entry_safe(vphy, vphy_next,
+			    &port->vphys_list, list) {
+				if (vphy->sas_address != sas_address)
+					continue;
+				ioc_info(ioc,
+				    "remove vphy entry: %p of port:%p,from %d port's vphys list\n",
+				    vphy, port, port->port_id);
+				port->vphys_mask &= ~vphy->phy_mask;
+				list_del(&vphy->list);
+				kfree(vphy);
+			}
+		}
+
 		list_for_each_entry_safe(hba_port, hba_port_next,
 		    &ioc->port_table_list, list) {
 			if (hba_port != port)
 				continue;
-			if (hba_port->sas_address != sas_address)
-				continue;
-			ioc_info(ioc,
-			    "remove hba_port entry: %p port: %d from hba_port list\n",
-			    hba_port, hba_port->port_id);
-			list_del(&hba_port->list);
-			kfree(hba_port);
+			/*
+			 * Delete hba_port object if
+			 *  - hba_port object's sas address matches with current
+			 *    removed device's sas address and no vphy's
+			 *    associated with it.
+			 *  - Current removed device is a vSES device and
+			 *    none of the other direct attached device have
+			 *    this vSES device's port number (hence hba_port
+			 *    object sas_address field will be zero).
+			 */
+			if ((hba_port->sas_address == sas_address ||
+			    !hba_port->sas_address) && !hba_port->vphys_mask) {
+				ioc_info(ioc,
+				    "remove hba_port entry: %p port: %d from hba_port list\n",
+				    hba_port, hba_port->port_id);
+				list_del(&hba_port->list);
+				kfree(hba_port);
+			} else if (hba_port->sas_address == sas_address &&
+			    hba_port->vphys_mask) {
+				/*
+				 * Current removed device is a non vSES device
+				 * and a vSES device has the same port number
+				 * as of current device's port number. Hence
+				 * only clear the sas_address filed, don't
+				 * delete the hba_port object.
+				 */
+				ioc_info(ioc,
+				    "clearing sas_address from hba_port entry: %p port: %d from hba_port list\n",
+				    hba_port, hba_port->port_id);
+				port->sas_address = 0;
+			}
+			break;
 		}
 	}
 
-- 
2.18.4


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4175 bytes --]

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 11/14] mpt3sas: Add bypass_dirty_port_flag parameter
  2020-10-09 17:14 [PATCH 00/14] mpt3sas: Add support for multi-port path topology Sreekanth Reddy
                   ` (9 preceding siblings ...)
  2020-10-09 17:14 ` [PATCH 10/14] mpt3sas: Handling HBA vSES device Sreekanth Reddy
@ 2020-10-09 17:14 ` Sreekanth Reddy
  2020-10-09 17:14 ` [PATCH 12/14] mpt3sas: Handle vSES vphy object during HBA reset Sreekanth Reddy
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 18+ messages in thread
From: Sreekanth Reddy @ 2020-10-09 17:14 UTC (permalink / raw)
  To: martin.petersen
  Cc: linux-scsi, sathya.prakash, suganath-prabu.subramani, Sreekanth Reddy

[-- Attachment #1: Type: text/plain, Size: 13491 bytes --]

Added a new parameter bypass_dirty_port_flag in function
mpt3sas_get_port_by_id(). When this parameter is set to one
then search for matching hba port entry from port_table_list
even when this hba_port entry is marked as dirty.

Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.h      |  3 +-
 drivers/scsi/mpt3sas/mpt3sas_scsih.c     | 63 ++++++++++++++----------
 drivers/scsi/mpt3sas/mpt3sas_transport.c |  8 +--
 3 files changed, 44 insertions(+), 30 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
index e7d047a..cca14ab 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -1684,7 +1684,8 @@ void mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
 u8 mpt3sas_check_for_pending_internal_cmds(struct MPT3SAS_ADAPTER *ioc,
 	u16 smid);
 struct hba_port *
-mpt3sas_get_port_by_id(struct MPT3SAS_ADAPTER *ioc, u8 port);
+mpt3sas_get_port_by_id(struct MPT3SAS_ADAPTER *ioc, u8 port,
+	u8 bypass_dirty_port_flag);
 
 struct _sas_node *mpt3sas_scsih_expander_find_by_handle(
 	struct MPT3SAS_ADAPTER *ioc, u16 handle);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 22ffc50..522e4d0 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -361,20 +361,27 @@ _scsih_srch_boot_encl_slot(u64 enclosure_logical_id, u16 slot_number,
  *			  port number from port list
  * @ioc: per adapter object
  * @port_id: port number
+ * @bypass_dirty_port_flag: when set look the matching hba port entry even
+ *			if hba port entry is marked as dirty.
  *
  * Search for hba port entry corresponding to provided port number,
  * if available return port object otherwise return NULL.
  */
 struct hba_port *
-mpt3sas_get_port_by_id(struct MPT3SAS_ADAPTER *ioc, u8 port_id)
+mpt3sas_get_port_by_id(struct MPT3SAS_ADAPTER *ioc,
+	u8 port_id, u8 bypass_dirty_port_flag)
 {
 	struct hba_port *port, *port_next;
 
 	list_for_each_entry_safe(port, port_next,
 	    &ioc->port_table_list, list) {
-		if (port->port_id == port_id &&
-		    !(port->flags & HBA_PORT_FLAG_DIRTY_PORT))
+		if (port->port_id != port_id)
+			continue;
+		if (bypass_dirty_port_flag)
 			return port;
+		if (port->flags & HBA_PORT_FLAG_DIRTY_PORT)
+			continue;
+		return port;
 	}
 
 	return NULL;
@@ -6189,7 +6196,7 @@ _scsih_alloc_vphy(struct MPT3SAS_ADAPTER *ioc, u8 port_id, u8 phy_num)
 	struct virtual_phy *vphy;
 	struct hba_port *port;
 
-	port = mpt3sas_get_port_by_id(ioc, port_id);
+	port = mpt3sas_get_port_by_id(ioc, port_id, 0);
 	if (!port)
 		return NULL;
 
@@ -6263,7 +6270,7 @@ _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc)
 			ioc->sas_hba.handle = le16_to_cpu(
 			    sas_iounit_pg0->PhyData[0].ControllerDevHandle);
 		port_id = sas_iounit_pg0->PhyData[i].Port;
-		if (!(mpt3sas_get_port_by_id(ioc, port_id))) {
+		if (!(mpt3sas_get_port_by_id(ioc, port_id, 0))) {
 			port = kzalloc(sizeof(struct hba_port), GFP_KERNEL);
 			if (!port)
 				goto out;
@@ -6306,7 +6313,8 @@ _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc)
 		    AttachedDevHandle);
 		if (attached_handle && link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
 			link_rate = MPI2_SAS_NEG_LINK_RATE_1_5;
-		ioc->sas_hba.phy[i].port = mpt3sas_get_port_by_id(ioc, port_id);
+		ioc->sas_hba.phy[i].port =
+		    mpt3sas_get_port_by_id(ioc, port_id, 0);
 		mpt3sas_transport_update_links(ioc, ioc->sas_hba.sas_address,
 		    attached_handle, i, link_rate,
 		    ioc->sas_hba.phy[i].port);
@@ -6430,7 +6438,7 @@ _scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc)
 			    PhyData[0].ControllerDevHandle);
 
 		port_id = sas_iounit_pg0->PhyData[i].Port;
-		if (!(mpt3sas_get_port_by_id(ioc, port_id))) {
+		if (!(mpt3sas_get_port_by_id(ioc, port_id, 0))) {
 			port = kzalloc(sizeof(struct hba_port), GFP_KERNEL);
 			if (!port)
 				goto out;
@@ -6460,7 +6468,8 @@ _scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc)
 
 		ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
 		ioc->sas_hba.phy[i].phy_id = i;
-		ioc->sas_hba.phy[i].port = mpt3sas_get_port_by_id(ioc, port_id);
+		ioc->sas_hba.phy[i].port =
+		    mpt3sas_get_port_by_id(ioc, port_id, 0);
 		mpt3sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i],
 		    phy_pg0, ioc->sas_hba.parent_dev);
 	}
@@ -6552,7 +6561,8 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 	if (sas_address_parent != ioc->sas_hba.sas_address) {
 		spin_lock_irqsave(&ioc->sas_node_lock, flags);
 		sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
-		    sas_address_parent, mpt3sas_get_port_by_id(ioc, port_id));
+		    sas_address_parent,
+		    mpt3sas_get_port_by_id(ioc, port_id, 0));
 		spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 		if (!sas_expander) {
 			rc = _scsih_expander_add(ioc, parent_handle);
@@ -6564,7 +6574,7 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 	spin_lock_irqsave(&ioc->sas_node_lock, flags);
 	sas_address = le64_to_cpu(expander_pg0.SASAddress);
 	sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
-	    sas_address, mpt3sas_get_port_by_id(ioc, port_id));
+	    sas_address, mpt3sas_get_port_by_id(ioc, port_id, 0));
 	spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 
 	if (sas_expander)
@@ -6582,7 +6592,7 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 	sas_expander->num_phys = expander_pg0.NumPhys;
 	sas_expander->sas_address_parent = sas_address_parent;
 	sas_expander->sas_address = sas_address;
-	sas_expander->port = mpt3sas_get_port_by_id(ioc, port_id);
+	sas_expander->port = mpt3sas_get_port_by_id(ioc, port_id, 0);
 	if (!sas_expander->port) {
 		ioc_err(ioc, "failure at %s:%d/%s()!\n",
 		    __FILE__, __LINE__, __func__);
@@ -6627,7 +6637,8 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 		}
 		sas_expander->phy[i].handle = handle;
 		sas_expander->phy[i].phy_id = i;
-		sas_expander->phy[i].port = mpt3sas_get_port_by_id(ioc, port_id);
+		sas_expander->phy[i].port =
+		    mpt3sas_get_port_by_id(ioc, port_id, 0);
 
 		if ((mpt3sas_transport_add_expander_phy(ioc,
 		    &sas_expander->phy[i], expander_pg1,
@@ -6834,7 +6845,7 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
 
 	spin_lock_irqsave(&ioc->sas_device_lock, flags);
 	sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
-	port = mpt3sas_get_port_by_id(ioc, sas_device_pg0.PhysicalPort);
+	port = mpt3sas_get_port_by_id(ioc, sas_device_pg0.PhysicalPort, 0);
 	if (!port)
 		goto out_unlock;
 	sas_device = __mpt3sas_get_sdev_by_addr(ioc,
@@ -6967,7 +6978,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
 
 	port_id = sas_device_pg0.PhysicalPort;
 	sas_device = mpt3sas_get_sdev_by_addr(ioc,
-	    sas_address, mpt3sas_get_port_by_id(ioc, port_id));
+	    sas_address, mpt3sas_get_port_by_id(ioc, port_id, 0));
 	if (sas_device) {
 		clear_bit(handle, ioc->pend_os_device_add);
 		sas_device_put(sas_device);
@@ -7008,7 +7019,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
 	sas_device->phy = sas_device_pg0.PhyNum;
 	sas_device->fast_path = (le16_to_cpu(sas_device_pg0.Flags) &
 	    MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) ? 1 : 0;
-	sas_device->port = mpt3sas_get_port_by_id(ioc, port_id);
+	sas_device->port = mpt3sas_get_port_by_id(ioc, port_id, 0);
 	if (!sas_device->port) {
 		ioc_err(ioc, "failure at %s:%d/%s()!\n",
 		    __FILE__, __LINE__, __func__);
@@ -7223,7 +7234,7 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
 	}
 
 	parent_handle = le16_to_cpu(event_data->ExpanderDevHandle);
-	port = mpt3sas_get_port_by_id(ioc, event_data->PhysicalPort);
+	port = mpt3sas_get_port_by_id(ioc, event_data->PhysicalPort, 0);
 
 	/* handle expander add */
 	if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED)
@@ -7414,7 +7425,8 @@ _scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc,
 	spin_lock_irqsave(&ioc->sas_device_lock, flags);
 	sas_address = le64_to_cpu(event_data->SASAddress);
 	sas_device = __mpt3sas_get_sdev_by_addr(ioc,
-	    sas_address, mpt3sas_get_port_by_id(ioc, event_data->PhysicalPort));
+	    sas_address,
+	    mpt3sas_get_port_by_id(ioc, event_data->PhysicalPort, 0));
 
 	if (!sas_device || !sas_device->starget)
 		goto out;
@@ -8855,7 +8867,8 @@ _scsih_sas_pd_add(struct MPT3SAS_ADAPTER *ioc,
 	if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
 		mpt3sas_transport_update_links(ioc, sas_address, handle,
 		    sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5,
-		    mpt3sas_get_port_by_id(ioc, sas_device_pg0.PhysicalPort));
+		    mpt3sas_get_port_by_id(ioc,
+		    sas_device_pg0.PhysicalPort, 0));
 
 	_scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
 	_scsih_add_device(ioc, handle, 0, 1);
@@ -9163,7 +9176,7 @@ _scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc,
 			mpt3sas_transport_update_links(ioc, sas_address, handle,
 			    sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5,
 			    mpt3sas_get_port_by_id(ioc,
-			    sas_device_pg0.PhysicalPort));
+			    sas_device_pg0.PhysicalPort, 0));
 
 		_scsih_add_device(ioc, handle, 0, 1);
 
@@ -9289,7 +9302,7 @@ Mpi2SasDevicePage0_t *sas_device_pg0)
 	struct _enclosure_node *enclosure_dev = NULL;
 	unsigned long flags;
 	struct hba_port *port = mpt3sas_get_port_by_id(
-	    ioc, sas_device_pg0->PhysicalPort);
+	    ioc, sas_device_pg0->PhysicalPort, 0);
 
 	if (sas_device_pg0->EnclosureHandle) {
 		enclosure_dev =
@@ -9717,7 +9730,7 @@ _scsih_mark_responding_expander(struct MPT3SAS_ADAPTER *ioc,
 	u16 enclosure_handle = le16_to_cpu(expander_pg0->EnclosureHandle);
 	u64 sas_address = le64_to_cpu(expander_pg0->SASAddress);
 	struct hba_port *port = mpt3sas_get_port_by_id(
-	    ioc, expander_pg0->PhysicalPort);
+	    ioc, expander_pg0->PhysicalPort, 0);
 
 	if (enclosure_handle)
 		enclosure_dev =
@@ -9964,7 +9977,7 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
 		port_id = expander_pg0.PhysicalPort;
 		expander_device = mpt3sas_scsih_expander_find_by_sas_address(
 		    ioc, le64_to_cpu(expander_pg0.SASAddress),
-		    mpt3sas_get_port_by_id(ioc, port_id));
+		    mpt3sas_get_port_by_id(ioc, port_id, 0));
 		spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 		if (expander_device)
 			_scsih_refresh_expander_links(ioc, expander_device,
@@ -10027,7 +10040,7 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
 			mpt3sas_transport_update_links(ioc, sas_address,
 			    handle, sas_device_pg0.PhyNum,
 			    MPI2_SAS_NEG_LINK_RATE_1_5,
-			    mpt3sas_get_port_by_id(ioc, port_id));
+			    mpt3sas_get_port_by_id(ioc, port_id, 0));
 			set_bit(handle, ioc->pd_handles);
 			retry_count = 0;
 			/* This will retry adding the end device.
@@ -10116,7 +10129,7 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
 		port_id = sas_device_pg0.PhysicalPort;
 		sas_device = mpt3sas_get_sdev_by_addr(ioc,
 		    le64_to_cpu(sas_device_pg0.SASAddress),
-		    mpt3sas_get_port_by_id(ioc, port_id));
+		    mpt3sas_get_port_by_id(ioc, port_id, 0));
 		if (sas_device) {
 			sas_device_put(sas_device);
 			continue;
@@ -10128,7 +10141,7 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
 				 (u64)le64_to_cpu(sas_device_pg0.SASAddress));
 			mpt3sas_transport_update_links(ioc, sas_address, handle,
 			    sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5,
-			    mpt3sas_get_port_by_id(ioc, port_id));
+			    mpt3sas_get_port_by_id(ioc, port_id, 0));
 			retry_count = 0;
 			/* This will retry adding the end device.
 			 * _scsih_add_device() will decide on retries and
diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c
index 256dae1..0d06025 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_transport.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c
@@ -1414,7 +1414,7 @@ _transport_get_linkerrors(struct sas_phy *phy)
 	spin_lock_irqsave(&ioc->sas_node_lock, flags);
 	if (_transport_sas_node_find_by_sas_address(ioc,
 	    phy->identify.sas_address,
-	    mpt3sas_get_port_by_id(ioc, port_id)) == NULL) {
+	    mpt3sas_get_port_by_id(ioc, port_id, 0)) == NULL) {
 		spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 		return -EINVAL;
 	}
@@ -1703,7 +1703,7 @@ _transport_phy_reset(struct sas_phy *phy, int hard_reset)
 	spin_lock_irqsave(&ioc->sas_node_lock, flags);
 	if (_transport_sas_node_find_by_sas_address(ioc,
 	    phy->identify.sas_address,
-	    mpt3sas_get_port_by_id(ioc, port_id)) == NULL) {
+	    mpt3sas_get_port_by_id(ioc, port_id, 0)) == NULL) {
 		spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 		return -EINVAL;
 	}
@@ -1762,7 +1762,7 @@ _transport_phy_enable(struct sas_phy *phy, int enable)
 	spin_lock_irqsave(&ioc->sas_node_lock, flags);
 	if (_transport_sas_node_find_by_sas_address(ioc,
 	    phy->identify.sas_address,
-	    mpt3sas_get_port_by_id(ioc, port_id)) == NULL) {
+	    mpt3sas_get_port_by_id(ioc, port_id, 0)) == NULL) {
 		spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 		return -EINVAL;
 	}
@@ -1902,7 +1902,7 @@ _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
 	spin_lock_irqsave(&ioc->sas_node_lock, flags);
 	if (_transport_sas_node_find_by_sas_address(ioc,
 	    phy->identify.sas_address,
-	    mpt3sas_get_port_by_id(ioc, port_id)) == NULL) {
+	    mpt3sas_get_port_by_id(ioc, port_id, 0)) == NULL) {
 		spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 		return -EINVAL;
 	}
-- 
2.18.4


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4175 bytes --]

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 12/14] mpt3sas: Handle vSES vphy object during HBA reset
  2020-10-09 17:14 [PATCH 00/14] mpt3sas: Add support for multi-port path topology Sreekanth Reddy
                   ` (10 preceding siblings ...)
  2020-10-09 17:14 ` [PATCH 11/14] mpt3sas: Add bypass_dirty_port_flag parameter Sreekanth Reddy
@ 2020-10-09 17:14 ` Sreekanth Reddy
  2020-10-09 17:14 ` [PATCH 13/14] mpt3sas: add module parameter multipath_on_hba Sreekanth Reddy
  2020-10-09 17:14 ` [PATCH 14/14] mpt3sas: Bump driver version to 35.101.00.00 Sreekanth Reddy
  13 siblings, 0 replies; 18+ messages in thread
From: Sreekanth Reddy @ 2020-10-09 17:14 UTC (permalink / raw)
  To: martin.petersen
  Cc: linux-scsi, sathya.prakash, suganath-prabu.subramani, Sreekanth Reddy

[-- Attachment #1: Type: text/plain, Size: 10725 bytes --]

During HBA reset, Port ID of vSES device may change.
So, need to refresh virtual_phy objects after reset.

Each Port’s vphy_list table needs to be updated after updating the
HBA port table. Follow the below algorithm to update each
Port’s vphy_list table.
• Loop over each port entry from HBA port table
  * Loop over each virtual phy entry from port’s vphys_list table
    - Mark virtual phy entry as dirty by setting dirty bit in virtual phy
      entry’s flags field
• Read SASIOUnitPage0 page
• Loop over each HBA Phy’s Phy data from SASIOUnitPage0
  * If phy’s remote attached device is not SES device then continue with
    processing next HBA Phy’s Phy data,
  * Read SASPhyPage0 data for this Phy number and determine whether
    current phy is a virtual phy or not. If it is not a virtual phy
    then continue with next Phy data,
  * Get the current phy’s remote attached vSES device’s SAS Address,
  * Loop over each port entry from HBA port table
    - If Port’s vphys_mask field is zero then continue with
      next Port entry,
    - Loop over each virtual phy entry from Port’s vphy_list table
      • If the current phy’s remote SAS Address is different from
        virtual phy entry’s SAS Address then continue with next
        virtual phy entry,
      • Set bit corresponding to current phy number in virtual phy
        entry’s of phy_mask field,
      • Get the HBA port table’s Port entry corresponding to
        Phy data’s ‘Port’ value,
	* If there is no Port entry corresponding to Phy data’s ‘Port’
	  value in HBA port table then create a new port entry and
          add it to HBA port table.
      • If this retrieved Port entry is the same as the current Port
        entry then don’t do anything, just clear the dirty bit from
        virtual phy entry’s flag field and continue with processing
        next HBA Phy’s Phy data.
      • If this retrieved Port entry is different from the current Port
        entry then move the current virtual phy entry from current Port’s
        vphys_list to retrieved Port entry’s vphys_list.
        * Clear current phy bit in current Port entry’s vphys_mask and
          set the current phy bit in the retrieved Port entry’s
          vphys_mask field.
        * Clear the dirty bit from virtual phy entry’s flag field and
          continue with next HBA Phy’s Phy data.
• Delete the ‘virtual phy’ entries and HBA’s ‘Port table’
  entries which are still marked as ‘dirty’.

Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 233 +++++++++++++++++++++++++++
 1 file changed, 233 insertions(+)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 522e4d0..da4ffa6 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -5847,6 +5847,204 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
 	return 0;
 }
 
+/**
+ * _scsih_update_vphys_after_reset - update the Port's
+ *			vphys_list after reset
+ * @ioc: per adapter object
+ *
+ * Returns nothing.
+ */
+static void
+_scsih_update_vphys_after_reset(struct MPT3SAS_ADAPTER *ioc)
+{
+	u16 sz, ioc_status;
+	int i;
+	Mpi2ConfigReply_t mpi_reply;
+	Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
+	u16 attached_handle;
+	u64 attached_sas_addr;
+	u8 found = 0, port_id;
+	Mpi2SasPhyPage0_t phy_pg0;
+	struct hba_port *port, *port_next, *mport;
+	struct virtual_phy *vphy, *vphy_next;
+	struct _sas_device *sas_device;
+
+	/*
+	 * Mark all the vphys objects as dirty.
+	 */
+	list_for_each_entry_safe(port, port_next,
+	    &ioc->port_table_list, list) {
+		if (!port->vphys_mask)
+			continue;
+		list_for_each_entry_safe(vphy, vphy_next,
+		    &port->vphys_list, list) {
+			vphy->flags |= MPT_VPHY_FLAG_DIRTY_PHY;
+		}
+	}
+
+	/*
+	 * Read SASIOUnitPage0 to get each HBA Phy's data.
+	 */
+	sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) +
+	    (ioc->sas_hba.num_phys * sizeof(Mpi2SasIOUnit0PhyData_t));
+	sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
+	if (!sas_iounit_pg0) {
+		ioc_err(ioc, "failure at %s:%d/%s()!\n",
+		    __FILE__, __LINE__, __func__);
+		return;
+	}
+	if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
+	    sas_iounit_pg0, sz)) != 0)
+		goto out;
+	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
+	if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
+		goto out;
+	/*
+	 * Loop over each HBA Phy.
+	 */
+	for (i = 0; i < ioc->sas_hba.num_phys; i++) {
+		/*
+		 * Check whether Phy's Negotiation Link Rate is > 1.5G or not.
+		 */
+		if ((sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4) <
+		    MPI2_SAS_NEG_LINK_RATE_1_5)
+			continue;
+		/*
+		 * Check whether Phy is connected to SEP device or not,
+		 * if it is SEP device then read the Phy's SASPHYPage0 data to
+		 * determine whether Phy is a virtual Phy or not. if it is
+		 * virtual phy then it is conformed that the attached remote
+		 * device is a HBA's vSES device.
+		 */
+		if (!(le32_to_cpu(
+		    sas_iounit_pg0->PhyData[i].ControllerPhyDeviceInfo) &
+		    MPI2_SAS_DEVICE_INFO_SEP))
+			continue;
+
+		if ((mpt3sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
+		    i))) {
+			ioc_err(ioc, "failure at %s:%d/%s()!\n",
+			    __FILE__, __LINE__, __func__);
+			continue;
+		}
+
+		if (!(le32_to_cpu(phy_pg0.PhyInfo) &
+		    MPI2_SAS_PHYINFO_VIRTUAL_PHY))
+			continue;
+		/*
+		 * Get the vSES device's SAS Address.
+		 */
+		attached_handle = le16_to_cpu(
+		    sas_iounit_pg0->PhyData[i].AttachedDevHandle);
+		if (_scsih_get_sas_address(ioc, attached_handle,
+		    &attached_sas_addr) != 0) {
+			ioc_err(ioc, "failure at %s:%d/%s()!\n",
+			    __FILE__, __LINE__, __func__);
+			continue;
+		}
+
+		found = 0;
+		port = port_next = NULL;
+		/*
+		 * Loop over each virtual_phy object from
+		 * each port's vphys_list.
+		 */
+		list_for_each_entry_safe(port,
+		    port_next, &ioc->port_table_list, list) {
+			if (!port->vphys_mask)
+				continue;
+			list_for_each_entry_safe(vphy, vphy_next,
+			    &port->vphys_list, list) {
+				/*
+				 * Continue with next virtual_phy object
+				 * if the object is not marked as dirty.
+				 */
+				if (!(vphy->flags & MPT_VPHY_FLAG_DIRTY_PHY))
+					continue;
+
+				/*
+				 * Continue with next virtual_phy object
+				 * if the object's SAS Address is not equals
+				 * to current Phy's vSES device SAS Address.
+				 */
+				if (vphy->sas_address != attached_sas_addr)
+					continue;
+				/*
+				 * Enable current Phy number bit in object's
+				 * phy_mask field.
+				 */
+				if (!(vphy->phy_mask & (1 << i)))
+					vphy->phy_mask = (1 << i);
+				/*
+				 * Get hba_port object from hba_port table
+				 * corresponding to current phy's Port ID.
+				 * if there is no hba_port object corresponding
+				 * to Phy's Port ID then create a new hba_port
+				 * object & add to hba_port table.
+				 */
+				port_id = sas_iounit_pg0->PhyData[i].Port;
+				mport = mpt3sas_get_port_by_id(ioc, port_id, 1);
+				if (!mport) {
+					mport = kzalloc(
+					    sizeof(struct hba_port), GFP_KERNEL);
+					if (!mport)
+						break;
+					mport->port_id = port_id;
+					ioc_info(ioc,
+					    "%s: hba_port entry: %p, port: %d is added to hba_port list\n",
+					    __func__, mport, mport->port_id);
+					list_add_tail(&mport->list,
+						&ioc->port_table_list);
+				}
+				/*
+				 * If mport & port pointers are not pointing to
+				 * same hba_port object then it means that vSES
+				 * device's Port ID got changed after reset and
+				 * hence move current virtual_phy object from
+				 * port's vphys_list to mport's vphys_list.
+				 */
+				if (port != mport) {
+					if (!mport->vphys_mask)
+						INIT_LIST_HEAD(
+						    &mport->vphys_list);
+					mport->vphys_mask |= (1 << i);
+					port->vphys_mask &= ~(1 << i);
+					list_move(&vphy->list,
+					    &mport->vphys_list);
+					sas_device = mpt3sas_get_sdev_by_addr(
+					    ioc, attached_sas_addr, port);
+					if (sas_device)
+						sas_device->port = mport;
+				}
+				/*
+				 * Earlier while updating the hba_port table,
+				 * it is determined that there is no other
+				 * direct attached device with mport's Port ID,
+				 * Hence mport was marked as dirty. Only vSES
+				 * device has this Port ID, so unmark the mport
+				 * as dirt.
+				 */
+				if (mport->flags & HBA_PORT_FLAG_DIRTY_PORT) {
+					mport->sas_address = 0;
+					mport->phy_mask = 0;
+					mport->flags &=
+					    ~HBA_PORT_FLAG_DIRTY_PORT;
+				}
+				/*
+				 * Unmark current virtual_phy object as dirty.
+				 */
+				vphy->flags &= ~MPT_VPHY_FLAG_DIRTY_PHY;
+				found = 1;
+				break;
+			}
+			if (found)
+				break;
+		}
+	}
+out:
+	kfree(sas_iounit_pg0);
+}
+
 /**
  * _scsih_get_port_table_after_reset - Construct temporary port table
  * @ioc: per adapter object
@@ -6066,6 +6264,39 @@ _scsih_add_or_del_phys_from_existing_port(struct MPT3SAS_ADAPTER *ioc,
 	}
 }
 
+/**
+ * _scsih_del_dirty_vphy - delete virtual_phy objects marked as dirty.
+ * @ioc: per adapter object
+ *
+ * Returns nothing.
+ */
+static void
+_scsih_del_dirty_vphy(struct MPT3SAS_ADAPTER *ioc)
+{
+	struct hba_port *port, *port_next;
+	struct virtual_phy *vphy, *vphy_next;
+
+	list_for_each_entry_safe(port, port_next,
+	    &ioc->port_table_list, list) {
+		if (!port->vphys_mask)
+			continue;
+		list_for_each_entry_safe(vphy, vphy_next,
+		    &port->vphys_list, list) {
+			if (vphy->flags & MPT_VPHY_FLAG_DIRTY_PHY) {
+				drsprintk(ioc, ioc_info(ioc,
+				    "Deleting vphy %p entry from port id: %d\t, Phy_mask 0x%08x\n",
+				    vphy, port->port_id,
+				    vphy->phy_mask));
+				port->vphys_mask &= ~vphy->phy_mask;
+				list_del(&vphy->list);
+				kfree(vphy);
+			}
+		}
+		if (!port->vphys_mask && !port->sas_address)
+			port->flags |= HBA_PORT_FLAG_DIRTY_PORT;
+	}
+}
+
 /**
  * _scsih_del_dirty_port_entries - delete dirty port entries from port list
  *					after host reset
@@ -10246,6 +10477,7 @@ mpt3sas_scsih_reset_done_handler(struct MPT3SAS_ADAPTER *ioc)
 	if ((!ioc->is_driver_loading) && !(disable_discovery > 0 &&
 					   !ioc->sas_hba.num_phys)) {
 		_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);
@@ -10293,6 +10525,7 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
 			ssleep(1);
 		}
 		_scsih_remove_unresponding_devices(ioc);
+		_scsih_del_dirty_vphy(ioc);
 		_scsih_del_dirty_port_entries(ioc);
 		_scsih_scan_for_devices_after_reset(ioc);
 		_scsih_set_nvme_max_shutdown_latency(ioc);
-- 
2.18.4


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4175 bytes --]

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 13/14] mpt3sas: add module parameter multipath_on_hba
  2020-10-09 17:14 [PATCH 00/14] mpt3sas: Add support for multi-port path topology Sreekanth Reddy
                   ` (11 preceding siblings ...)
  2020-10-09 17:14 ` [PATCH 12/14] mpt3sas: Handle vSES vphy object during HBA reset Sreekanth Reddy
@ 2020-10-09 17:14 ` Sreekanth Reddy
  2020-10-09 17:14 ` [PATCH 14/14] mpt3sas: Bump driver version to 35.101.00.00 Sreekanth Reddy
  13 siblings, 0 replies; 18+ messages in thread
From: Sreekanth Reddy @ 2020-10-09 17:14 UTC (permalink / raw)
  To: martin.petersen
  Cc: linux-scsi, sathya.prakash, suganath-prabu.subramani, Sreekanth Reddy

[-- Attachment #1: Type: text/plain, Size: 7475 bytes --]

Add module parameter multipath_on_hba to enable/disable
the support a multi-port path topology.
By default this feature is enabled on SAS3.5 HBA device
and disabled on SAS3 &SAS2.5 HBA devices.

when this module parameter is disabled then driver uses
a default PhysicalPort(PortID) number i.e. 255 instead of
PhysicalPort number provided by HBA firmware.

Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.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 cca14ab..badd823 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 5c32dbb..af2d3e3 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 da4ffa6..699fc9a 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;
 }
 
@@ -10013,6 +10048,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");
 
@@ -10030,10 +10066,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);
 	}
 
@@ -10476,8 +10514,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);
@@ -11765,6 +11805,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:
@@ -11826,6 +11872,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 0d06025..6f47082 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 &&
-- 
2.18.4


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4175 bytes --]

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 14/14] mpt3sas: Bump driver version to 35.101.00.00
  2020-10-09 17:14 [PATCH 00/14] mpt3sas: Add support for multi-port path topology Sreekanth Reddy
                   ` (12 preceding siblings ...)
  2020-10-09 17:14 ` [PATCH 13/14] mpt3sas: add module parameter multipath_on_hba Sreekanth Reddy
@ 2020-10-09 17:14 ` Sreekanth Reddy
  13 siblings, 0 replies; 18+ messages in thread
From: Sreekanth Reddy @ 2020-10-09 17:14 UTC (permalink / raw)
  To: martin.petersen
  Cc: linux-scsi, sathya.prakash, suganath-prabu.subramani, Sreekanth Reddy

[-- Attachment #1: Type: text/plain, Size: 902 bytes --]

Bump mpt3sas driver version to 35.101.00.00

Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
---
 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 badd823..7dab579 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -76,9 +76,9 @@
 #define MPT3SAS_DRIVER_NAME		"mpt3sas"
 #define MPT3SAS_AUTHOR "Avago Technologies <MPT-FusionLinux.pdl@avagotech.com>"
 #define MPT3SAS_DESCRIPTION	"LSI MPT Fusion SAS 3.0 Device Driver"
-#define MPT3SAS_DRIVER_VERSION		"35.100.00.00"
+#define MPT3SAS_DRIVER_VERSION		"35.101.00.00"
 #define MPT3SAS_MAJOR_VERSION		35
-#define MPT3SAS_MINOR_VERSION		100
+#define MPT3SAS_MINOR_VERSION		101
 #define MPT3SAS_BUILD_VERSION		0
 #define MPT3SAS_RELEASE_VERSION	00
 
-- 
2.18.4


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4175 bytes --]

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH 08/14] mpt3sas: Update hba_port objects after host reset
  2020-10-09 17:14 ` [PATCH 08/14] mpt3sas: Update hba_port objects after host reset Sreekanth Reddy
  2020-10-12 12:22     ` Dan Carpenter
@ 2020-10-12 12:22     ` Dan Carpenter
  0 siblings, 0 replies; 18+ messages in thread
From: Dan Carpenter @ 2020-10-12 12:22 UTC (permalink / raw)
  To: kbuild, Sreekanth Reddy, martin.petersen
  Cc: lkp, kbuild-all, linux-scsi, sathya.prakash,
	suganath-prabu.subramani, Sreekanth Reddy

[-- Attachment #1: Type: text/plain, Size: 6226 bytes --]

Hi Sreekanth,

url:    https://github.com/0day-ci/linux/commits/Sreekanth-Reddy/mpt3sas-Add-support-for-multi-port-path-topology/20201010-011607
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git for-next
config: s390-randconfig-m031-20201009 (attached as .config)
compiler: s390-linux-gcc (GCC) 9.3.0

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>

New smatch warnings:
drivers/scsi/mpt3sas/mpt3sas_scsih.c:5940 _scsih_look_and_get_matched_port_entry() error: uninitialized symbol 'matched_code'.

Old smatch warnings:
drivers/scsi/mpt3sas/mpt3sas_scsih.c:5949 _scsih_look_and_get_matched_port_entry() error: uninitialized symbol 'matched_code'.
drivers/scsi/mpt3sas/mpt3sas_scsih.c:5961 _scsih_look_and_get_matched_port_entry() error: uninitialized symbol 'matched_code'.
drivers/scsi/mpt3sas/mpt3sas_scsih.c:6472 _scsih_expander_add() warn: returning -1 instead of -ENOMEM is sloppy
drivers/scsi/mpt3sas/mpt3sas_scsih.c:10234 _mpt3sas_fw_work() warn: inconsistent indenting

vim +/matched_code +5940 drivers/scsi/mpt3sas/mpt3sas_scsih.c

2756bd46f6fdde Sreekanth Reddy 2020-10-09  5909  static enum hba_port_matched_codes
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5910  _scsih_look_and_get_matched_port_entry(struct MPT3SAS_ADAPTER *ioc,
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5911  	struct hba_port *port_entry,
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5912  	struct hba_port **matched_port_entry, int *count)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5913  {
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5914  	struct hba_port *port_table_entry, *matched_port = NULL;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5915  	enum hba_port_matched_codes matched_code;
                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

2756bd46f6fdde Sreekanth Reddy 2020-10-09  5916  	int lcount = 0;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5917  	*matched_port_entry = NULL;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5918  
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5919  	list_for_each_entry(port_table_entry, &ioc->port_table_list, list) {
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5920  		if (!(port_table_entry->flags & HBA_PORT_FLAG_DIRTY_PORT))
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5921  			continue;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5922  
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5923  		if ((port_table_entry->sas_address == port_entry->sas_address)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5924  		    && (port_table_entry->phy_mask == port_entry->phy_mask)) {
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5925  			matched_code = MATCHED_WITH_ADDR_AND_PHYMASK;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5926  			matched_port = port_table_entry;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5927  			break;

This is a break statement.

2756bd46f6fdde Sreekanth Reddy 2020-10-09  5928  		}
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5929  
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5930  		if ((port_table_entry->sas_address == port_entry->sas_address)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5931  		    && (port_table_entry->phy_mask & port_entry->phy_mask)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5932  		    && (port_table_entry->port_id == port_entry->port_id)) {

This is only true if "port_table_entry->port_id == port_entry->port_id"

2756bd46f6fdde Sreekanth Reddy 2020-10-09  5933  			matched_code = MATCHED_WITH_ADDR_SUBPHYMASK_AND_PORT;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5934  			matched_port = port_table_entry;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5935  			continue;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5936  		}
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5937  
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5938  		if ((port_table_entry->sas_address == port_entry->sas_address)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5939  		    && (port_table_entry->phy_mask & port_entry->phy_mask)) {
2756bd46f6fdde Sreekanth Reddy 2020-10-09 @5940  			if (matched_code ==
                                                                            ^^^^^^^^^^^^
Possibly uninitialized.  Smatch only complains about the first
intance otherwise it would probably complain about after the loop as
well.

2756bd46f6fdde Sreekanth Reddy 2020-10-09  5941  			    MATCHED_WITH_ADDR_SUBPHYMASK_AND_PORT)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5942  				continue;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5943  			matched_code = MATCHED_WITH_ADDR_AND_SUBPHYMASK;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5944  			matched_port = port_table_entry;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5945  			continue;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5946  		}
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5947  
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5948  		if (port_table_entry->sas_address == port_entry->sas_address) {
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5949  			if (matched_code ==
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5950  			    MATCHED_WITH_ADDR_SUBPHYMASK_AND_PORT)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5951  				continue;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5952  			if (matched_code == MATCHED_WITH_ADDR_AND_SUBPHYMASK)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5953  				continue;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5954  			matched_code = MATCHED_WITH_ADDR;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5955  			matched_port = port_table_entry;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5956  			lcount++;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5957  		}
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5958  	}
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5959  
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5960  	*matched_port_entry = matched_port;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5961  	if (matched_code ==  MATCHED_WITH_ADDR)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5962  		*count = lcount;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5963  	return matched_code;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5964  }

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 29356 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 08/14] mpt3sas: Update hba_port objects after host reset
@ 2020-10-12 12:22     ` Dan Carpenter
  0 siblings, 0 replies; 18+ messages in thread
From: Dan Carpenter @ 2020-10-12 12:22 UTC (permalink / raw)
  To: kbuild

[-- Attachment #1: Type: text/plain, Size: 6323 bytes --]

Hi Sreekanth,

url:    https://github.com/0day-ci/linux/commits/Sreekanth-Reddy/mpt3sas-Add-support-for-multi-port-path-topology/20201010-011607
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git for-next
config: s390-randconfig-m031-20201009 (attached as .config)
compiler: s390-linux-gcc (GCC) 9.3.0

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>

New smatch warnings:
drivers/scsi/mpt3sas/mpt3sas_scsih.c:5940 _scsih_look_and_get_matched_port_entry() error: uninitialized symbol 'matched_code'.

Old smatch warnings:
drivers/scsi/mpt3sas/mpt3sas_scsih.c:5949 _scsih_look_and_get_matched_port_entry() error: uninitialized symbol 'matched_code'.
drivers/scsi/mpt3sas/mpt3sas_scsih.c:5961 _scsih_look_and_get_matched_port_entry() error: uninitialized symbol 'matched_code'.
drivers/scsi/mpt3sas/mpt3sas_scsih.c:6472 _scsih_expander_add() warn: returning -1 instead of -ENOMEM is sloppy
drivers/scsi/mpt3sas/mpt3sas_scsih.c:10234 _mpt3sas_fw_work() warn: inconsistent indenting

vim +/matched_code +5940 drivers/scsi/mpt3sas/mpt3sas_scsih.c

2756bd46f6fdde Sreekanth Reddy 2020-10-09  5909  static enum hba_port_matched_codes
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5910  _scsih_look_and_get_matched_port_entry(struct MPT3SAS_ADAPTER *ioc,
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5911  	struct hba_port *port_entry,
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5912  	struct hba_port **matched_port_entry, int *count)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5913  {
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5914  	struct hba_port *port_table_entry, *matched_port = NULL;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5915  	enum hba_port_matched_codes matched_code;
                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

2756bd46f6fdde Sreekanth Reddy 2020-10-09  5916  	int lcount = 0;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5917  	*matched_port_entry = NULL;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5918  
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5919  	list_for_each_entry(port_table_entry, &ioc->port_table_list, list) {
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5920  		if (!(port_table_entry->flags & HBA_PORT_FLAG_DIRTY_PORT))
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5921  			continue;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5922  
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5923  		if ((port_table_entry->sas_address == port_entry->sas_address)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5924  		    && (port_table_entry->phy_mask == port_entry->phy_mask)) {
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5925  			matched_code = MATCHED_WITH_ADDR_AND_PHYMASK;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5926  			matched_port = port_table_entry;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5927  			break;

This is a break statement.

2756bd46f6fdde Sreekanth Reddy 2020-10-09  5928  		}
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5929  
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5930  		if ((port_table_entry->sas_address == port_entry->sas_address)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5931  		    && (port_table_entry->phy_mask & port_entry->phy_mask)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5932  		    && (port_table_entry->port_id == port_entry->port_id)) {

This is only true if "port_table_entry->port_id == port_entry->port_id"

2756bd46f6fdde Sreekanth Reddy 2020-10-09  5933  			matched_code = MATCHED_WITH_ADDR_SUBPHYMASK_AND_PORT;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5934  			matched_port = port_table_entry;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5935  			continue;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5936  		}
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5937  
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5938  		if ((port_table_entry->sas_address == port_entry->sas_address)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5939  		    && (port_table_entry->phy_mask & port_entry->phy_mask)) {
2756bd46f6fdde Sreekanth Reddy 2020-10-09 @5940  			if (matched_code ==
                                                                            ^^^^^^^^^^^^
Possibly uninitialized.  Smatch only complains about the first
intance otherwise it would probably complain about after the loop as
well.

2756bd46f6fdde Sreekanth Reddy 2020-10-09  5941  			    MATCHED_WITH_ADDR_SUBPHYMASK_AND_PORT)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5942  				continue;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5943  			matched_code = MATCHED_WITH_ADDR_AND_SUBPHYMASK;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5944  			matched_port = port_table_entry;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5945  			continue;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5946  		}
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5947  
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5948  		if (port_table_entry->sas_address == port_entry->sas_address) {
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5949  			if (matched_code ==
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5950  			    MATCHED_WITH_ADDR_SUBPHYMASK_AND_PORT)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5951  				continue;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5952  			if (matched_code == MATCHED_WITH_ADDR_AND_SUBPHYMASK)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5953  				continue;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5954  			matched_code = MATCHED_WITH_ADDR;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5955  			matched_port = port_table_entry;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5956  			lcount++;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5957  		}
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5958  	}
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5959  
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5960  	*matched_port_entry = matched_port;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5961  	if (matched_code ==  MATCHED_WITH_ADDR)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5962  		*count = lcount;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5963  	return matched_code;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5964  }

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 29356 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 08/14] mpt3sas: Update hba_port objects after host reset
@ 2020-10-12 12:22     ` Dan Carpenter
  0 siblings, 0 replies; 18+ messages in thread
From: Dan Carpenter @ 2020-10-12 12:22 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 6323 bytes --]

Hi Sreekanth,

url:    https://github.com/0day-ci/linux/commits/Sreekanth-Reddy/mpt3sas-Add-support-for-multi-port-path-topology/20201010-011607
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git for-next
config: s390-randconfig-m031-20201009 (attached as .config)
compiler: s390-linux-gcc (GCC) 9.3.0

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>

New smatch warnings:
drivers/scsi/mpt3sas/mpt3sas_scsih.c:5940 _scsih_look_and_get_matched_port_entry() error: uninitialized symbol 'matched_code'.

Old smatch warnings:
drivers/scsi/mpt3sas/mpt3sas_scsih.c:5949 _scsih_look_and_get_matched_port_entry() error: uninitialized symbol 'matched_code'.
drivers/scsi/mpt3sas/mpt3sas_scsih.c:5961 _scsih_look_and_get_matched_port_entry() error: uninitialized symbol 'matched_code'.
drivers/scsi/mpt3sas/mpt3sas_scsih.c:6472 _scsih_expander_add() warn: returning -1 instead of -ENOMEM is sloppy
drivers/scsi/mpt3sas/mpt3sas_scsih.c:10234 _mpt3sas_fw_work() warn: inconsistent indenting

vim +/matched_code +5940 drivers/scsi/mpt3sas/mpt3sas_scsih.c

2756bd46f6fdde Sreekanth Reddy 2020-10-09  5909  static enum hba_port_matched_codes
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5910  _scsih_look_and_get_matched_port_entry(struct MPT3SAS_ADAPTER *ioc,
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5911  	struct hba_port *port_entry,
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5912  	struct hba_port **matched_port_entry, int *count)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5913  {
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5914  	struct hba_port *port_table_entry, *matched_port = NULL;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5915  	enum hba_port_matched_codes matched_code;
                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

2756bd46f6fdde Sreekanth Reddy 2020-10-09  5916  	int lcount = 0;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5917  	*matched_port_entry = NULL;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5918  
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5919  	list_for_each_entry(port_table_entry, &ioc->port_table_list, list) {
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5920  		if (!(port_table_entry->flags & HBA_PORT_FLAG_DIRTY_PORT))
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5921  			continue;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5922  
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5923  		if ((port_table_entry->sas_address == port_entry->sas_address)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5924  		    && (port_table_entry->phy_mask == port_entry->phy_mask)) {
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5925  			matched_code = MATCHED_WITH_ADDR_AND_PHYMASK;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5926  			matched_port = port_table_entry;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5927  			break;

This is a break statement.

2756bd46f6fdde Sreekanth Reddy 2020-10-09  5928  		}
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5929  
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5930  		if ((port_table_entry->sas_address == port_entry->sas_address)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5931  		    && (port_table_entry->phy_mask & port_entry->phy_mask)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5932  		    && (port_table_entry->port_id == port_entry->port_id)) {

This is only true if "port_table_entry->port_id == port_entry->port_id"

2756bd46f6fdde Sreekanth Reddy 2020-10-09  5933  			matched_code = MATCHED_WITH_ADDR_SUBPHYMASK_AND_PORT;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5934  			matched_port = port_table_entry;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5935  			continue;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5936  		}
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5937  
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5938  		if ((port_table_entry->sas_address == port_entry->sas_address)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5939  		    && (port_table_entry->phy_mask & port_entry->phy_mask)) {
2756bd46f6fdde Sreekanth Reddy 2020-10-09 @5940  			if (matched_code ==
                                                                            ^^^^^^^^^^^^
Possibly uninitialized.  Smatch only complains about the first
intance otherwise it would probably complain about after the loop as
well.

2756bd46f6fdde Sreekanth Reddy 2020-10-09  5941  			    MATCHED_WITH_ADDR_SUBPHYMASK_AND_PORT)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5942  				continue;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5943  			matched_code = MATCHED_WITH_ADDR_AND_SUBPHYMASK;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5944  			matched_port = port_table_entry;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5945  			continue;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5946  		}
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5947  
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5948  		if (port_table_entry->sas_address == port_entry->sas_address) {
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5949  			if (matched_code ==
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5950  			    MATCHED_WITH_ADDR_SUBPHYMASK_AND_PORT)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5951  				continue;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5952  			if (matched_code == MATCHED_WITH_ADDR_AND_SUBPHYMASK)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5953  				continue;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5954  			matched_code = MATCHED_WITH_ADDR;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5955  			matched_port = port_table_entry;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5956  			lcount++;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5957  		}
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5958  	}
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5959  
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5960  	*matched_port_entry = matched_port;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5961  	if (matched_code ==  MATCHED_WITH_ADDR)
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5962  		*count = lcount;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5963  	return matched_code;
2756bd46f6fdde Sreekanth Reddy 2020-10-09  5964  }

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 29356 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2020-10-12 12:25 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-09 17:14 [PATCH 00/14] mpt3sas: Add support for multi-port path topology Sreekanth Reddy
2020-10-09 17:14 ` [PATCH 01/14] mpt3sas: Define hba_port structure Sreekanth Reddy
2020-10-09 17:14 ` [PATCH 02/14] mpt3sas: Allocate memory for hba_port objects Sreekanth Reddy
2020-10-09 17:14 ` [PATCH 03/14] mpt3sas: Rearrange _scsih_mark_responding_sas_device() Sreekanth Reddy
2020-10-09 17:14 ` [PATCH 04/14] mpt3sas: Update hba_port's sas_address & phy_mask Sreekanth Reddy
2020-10-09 17:14 ` [PATCH 05/14] mpt3sas: Get device objects using sas_address & portID Sreekanth Reddy
2020-10-09 17:14 ` [PATCH 06/14] mpt3sas: Rename transport_del_phy_from_an_existing_port Sreekanth Reddy
2020-10-09 17:14 ` [PATCH 07/14] mpt3sas: Get sas_device objects using device's rphy Sreekanth Reddy
2020-10-09 17:14 ` [PATCH 08/14] mpt3sas: Update hba_port objects after host reset Sreekanth Reddy
2020-10-12 12:22   ` Dan Carpenter
2020-10-12 12:22     ` Dan Carpenter
2020-10-12 12:22     ` Dan Carpenter
2020-10-09 17:14 ` [PATCH 09/14] mpt3sas: Set valid PhysicalPort in SMPPassThrough Sreekanth Reddy
2020-10-09 17:14 ` [PATCH 10/14] mpt3sas: Handling HBA vSES device Sreekanth Reddy
2020-10-09 17:14 ` [PATCH 11/14] mpt3sas: Add bypass_dirty_port_flag parameter Sreekanth Reddy
2020-10-09 17:14 ` [PATCH 12/14] mpt3sas: Handle vSES vphy object during HBA reset Sreekanth Reddy
2020-10-09 17:14 ` [PATCH 13/14] mpt3sas: add module parameter multipath_on_hba Sreekanth Reddy
2020-10-09 17:14 ` [PATCH 14/14] mpt3sas: Bump driver version to 35.101.00.00 Sreekanth Reddy

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.