summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.h16
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_scsih.c175
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_transport.c74
3 files changed, 178 insertions, 87 deletions
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
index aef872aa509d..b5d1fc5b665b 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 11cb9619c01c..0bc68cde2f42 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 aab3b1451e31..54c004e96170 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;
}