aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorKashyap, Desai <kashyap.desai@lsi.com>2010-11-12 18:05:30 -0500
committerJames Bottomley <James.Bottomley@suse.de>2010-12-21 13:24:05 -0500
commit7f6f794dee50ba33710145140f39de59f5ec764e (patch)
tree0a08ef98b9ecc0a58bb8b024735c8bc02b65f2e7 /drivers/scsi
parent35f805b52c94f8e6cb22907ef32517132a15cb96 (diff)
[SCSI] mpt2sas: Modify code to support Expander switch
Issue : Switch swap doesn't work when device missing delay is enabled. (1) add support to individually add and remove phys to and from existing ports. This replaces the routine _transport_delete_duplicate_port. (2) _scsih_sas_host_refresh - was modified to change the link rate from zero to 1.5 GB rate when the firmware reports there is an attached device with zero link. (3) add new function mpt2sas_device_remove, this is wrapper function deletes some redundant code through out driver by combining into one subrountine (4) two subroutines were modified so the sas_device, raid_device, and port lists are traversed once when objects are deleted from the list. Previously it was looping back each time an object was deleted from the list. Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h2
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c143
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_transport.c185
3 files changed, 206 insertions, 124 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index edf1a028db6c..428a8c2cf7e0 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -849,6 +849,8 @@ int mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle,
849 ulong timeout, struct scsi_cmnd *scmd); 849 ulong timeout, struct scsi_cmnd *scmd);
850void mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle); 850void mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
851void mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle); 851void mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
852void mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
853void mpt2sas_device_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
852struct _sas_node *mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc, 854struct _sas_node *mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc,
853 u16 handle); 855 u16 handle);
854struct _sas_node *mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER 856struct _sas_node *mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index 3e9c78aa4ccb..50c6bdf3fddd 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -2584,9 +2584,9 @@ _scsih_block_io_to_children_attached_to_ex(struct MPT2SAS_ADAPTER *ioc,
2584 &sas_expander->sas_port_list, port_list) { 2584 &sas_expander->sas_port_list, port_list) {
2585 2585
2586 if (mpt2sas_port->remote_identify.device_type == 2586 if (mpt2sas_port->remote_identify.device_type ==
2587 MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER || 2587 SAS_EDGE_EXPANDER_DEVICE ||
2588 mpt2sas_port->remote_identify.device_type == 2588 mpt2sas_port->remote_identify.device_type ==
2589 MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) { 2589 SAS_FANOUT_EXPANDER_DEVICE) {
2590 2590
2591 spin_lock_irqsave(&ioc->sas_node_lock, flags); 2591 spin_lock_irqsave(&ioc->sas_node_lock, flags);
2592 expander_sibling = 2592 expander_sibling =
@@ -3972,6 +3972,7 @@ _scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc)
3972 Mpi2ConfigReply_t mpi_reply; 3972 Mpi2ConfigReply_t mpi_reply;
3973 Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; 3973 Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
3974 u16 attached_handle; 3974 u16 attached_handle;
3975 u8 link_rate;
3975 3976
3976 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT 3977 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT
3977 "updating handles for sas_host(0x%016llx)\n", 3978 "updating handles for sas_host(0x%016llx)\n",
@@ -3993,15 +3994,17 @@ _scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc)
3993 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) 3994 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
3994 goto out; 3995 goto out;
3995 for (i = 0; i < ioc->sas_hba.num_phys ; i++) { 3996 for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
3997 link_rate = sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4;
3996 if (i == 0) 3998 if (i == 0)
3997 ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0-> 3999 ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
3998 PhyData[0].ControllerDevHandle); 4000 PhyData[0].ControllerDevHandle);
3999 ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle; 4001 ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
4000 attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i]. 4002 attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i].
4001 AttachedDevHandle); 4003 AttachedDevHandle);
4004 if (attached_handle && link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
4005 link_rate = MPI2_SAS_NEG_LINK_RATE_1_5;
4002 mpt2sas_transport_update_links(ioc, ioc->sas_hba.sas_address, 4006 mpt2sas_transport_update_links(ioc, ioc->sas_hba.sas_address,
4003 attached_handle, i, sas_iounit_pg0->PhyData[i]. 4007 attached_handle, i, link_rate);
4004 NegotiatedLinkRate >> 4);
4005 } 4008 }
4006 out: 4009 out:
4007 kfree(sas_iounit_pg0); 4010 kfree(sas_iounit_pg0);
@@ -4345,14 +4348,14 @@ _scsih_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
4345} 4348}
4346 4349
4347/** 4350/**
4348 * _scsih_expander_remove - removing expander object 4351 * mpt2sas_expander_remove - removing expander object
4349 * @ioc: per adapter object 4352 * @ioc: per adapter object
4350 * @sas_address: expander sas_address 4353 * @sas_address: expander sas_address
4351 * 4354 *
4352 * Return nothing. 4355 * Return nothing.
4353 */ 4356 */
4354static void 4357void
4355_scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address) 4358mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
4356{ 4359{
4357 struct _sas_node *sas_expander; 4360 struct _sas_node *sas_expander;
4358 unsigned long flags; 4361 unsigned long flags;
@@ -4363,6 +4366,11 @@ _scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
4363 spin_lock_irqsave(&ioc->sas_node_lock, flags); 4366 spin_lock_irqsave(&ioc->sas_node_lock, flags);
4364 sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc, 4367 sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
4365 sas_address); 4368 sas_address);
4369 if (!sas_expander) {
4370 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
4371 return;
4372 }
4373 list_del(&sas_expander->list);
4366 spin_unlock_irqrestore(&ioc->sas_node_lock, flags); 4374 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
4367 _scsih_expander_node_remove(ioc, sas_expander); 4375 _scsih_expander_node_remove(ioc, sas_expander);
4368} 4376}
@@ -4652,6 +4660,33 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc,
4652 sas_device_backup.sas_address)); 4660 sas_device_backup.sas_address));
4653} 4661}
4654 4662
4663/**
4664 * mpt2sas_device_remove - removing device object
4665 * @ioc: per adapter object
4666 * @sas_address: expander sas_address
4667 *
4668 * Return nothing.
4669 */
4670void
4671mpt2sas_device_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
4672{
4673 struct _sas_device *sas_device;
4674 unsigned long flags;
4675
4676 if (ioc->shost_recovery)
4677 return;
4678
4679 spin_lock_irqsave(&ioc->sas_device_lock, flags);
4680 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
4681 sas_address);
4682 if (!sas_device) {
4683 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4684 return;
4685 }
4686 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4687 _scsih_remove_device(ioc, sas_device);
4688}
4689
4655#ifdef CONFIG_SCSI_MPT2SAS_LOGGING 4690#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
4656/** 4691/**
4657 * _scsih_sas_topology_change_event_debug - debug for topology event 4692 * _scsih_sas_topology_change_event_debug - debug for topology event
@@ -4853,7 +4888,7 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
4853 /* handle expander removal */ 4888 /* handle expander removal */
4854 if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING && 4889 if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING &&
4855 sas_expander) 4890 sas_expander)
4856 _scsih_expander_remove(ioc, sas_address); 4891 mpt2sas_expander_remove(ioc, sas_address);
4857 4892
4858} 4893}
4859 4894
@@ -6228,7 +6263,7 @@ _scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
6228 sas_expander->responding = 0; 6263 sas_expander->responding = 0;
6229 continue; 6264 continue;
6230 } 6265 }
6231 _scsih_expander_remove(ioc, sas_expander->sas_address); 6266 mpt2sas_expander_remove(ioc, sas_expander->sas_address);
6232 goto retry_expander_search; 6267 goto retry_expander_search;
6233 } 6268 }
6234} 6269}
@@ -6499,56 +6534,23 @@ static void
6499_scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc, 6534_scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
6500 struct _sas_node *sas_expander) 6535 struct _sas_node *sas_expander)
6501{ 6536{
6502 struct _sas_port *mpt2sas_port; 6537 struct _sas_port *mpt2sas_port, *next;
6503 struct _sas_device *sas_device;
6504 struct _sas_node *expander_sibling;
6505 unsigned long flags;
6506
6507 if (!sas_expander)
6508 return;
6509 6538
6510 /* remove sibling ports attached to this expander */ 6539 /* remove sibling ports attached to this expander */
6511 retry_device_search: 6540 list_for_each_entry_safe(mpt2sas_port, next,
6512 list_for_each_entry(mpt2sas_port,
6513 &sas_expander->sas_port_list, port_list) {
6514 if (mpt2sas_port->remote_identify.device_type ==
6515 SAS_END_DEVICE) {
6516 spin_lock_irqsave(&ioc->sas_device_lock, flags);
6517 sas_device =
6518 mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
6519 mpt2sas_port->remote_identify.sas_address);
6520 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6521 if (!sas_device)
6522 continue;
6523 _scsih_remove_device(ioc, sas_device);
6524 if (ioc->shost_recovery)
6525 return;
6526 goto retry_device_search;
6527 }
6528 }
6529
6530 retry_expander_search:
6531 list_for_each_entry(mpt2sas_port,
6532 &sas_expander->sas_port_list, port_list) { 6541 &sas_expander->sas_port_list, port_list) {
6533 6542 if (ioc->shost_recovery)
6543 return;
6534 if (mpt2sas_port->remote_identify.device_type == 6544 if (mpt2sas_port->remote_identify.device_type ==
6535 MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER || 6545 SAS_END_DEVICE)
6546 mpt2sas_device_remove(ioc,
6547 mpt2sas_port->remote_identify.sas_address);
6548 else if (mpt2sas_port->remote_identify.device_type ==
6549 SAS_EDGE_EXPANDER_DEVICE ||
6536 mpt2sas_port->remote_identify.device_type == 6550 mpt2sas_port->remote_identify.device_type ==
6537 MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) { 6551 SAS_FANOUT_EXPANDER_DEVICE)
6538 6552 mpt2sas_expander_remove(ioc,
6539 spin_lock_irqsave(&ioc->sas_node_lock, flags); 6553 mpt2sas_port->remote_identify.sas_address);
6540 expander_sibling =
6541 mpt2sas_scsih_expander_find_by_sas_address(
6542 ioc, mpt2sas_port->remote_identify.sas_address);
6543 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
6544 if (!expander_sibling)
6545 continue;
6546 _scsih_expander_remove(ioc,
6547 expander_sibling->sas_address);
6548 if (ioc->shost_recovery)
6549 return;
6550 goto retry_expander_search;
6551 }
6552 } 6554 }
6553 6555
6554 mpt2sas_transport_port_remove(ioc, sas_expander->sas_address, 6556 mpt2sas_transport_port_remove(ioc, sas_expander->sas_address,
@@ -6559,7 +6561,6 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
6559 sas_expander->handle, (unsigned long long) 6561 sas_expander->handle, (unsigned long long)
6560 sas_expander->sas_address); 6562 sas_expander->sas_address);
6561 6563
6562 list_del(&sas_expander->list);
6563 kfree(sas_expander->phy); 6564 kfree(sas_expander->phy);
6564 kfree(sas_expander); 6565 kfree(sas_expander);
6565} 6566}
@@ -6677,9 +6678,7 @@ _scsih_remove(struct pci_dev *pdev)
6677{ 6678{
6678 struct Scsi_Host *shost = pci_get_drvdata(pdev); 6679 struct Scsi_Host *shost = pci_get_drvdata(pdev);
6679 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); 6680 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
6680 struct _sas_port *mpt2sas_port; 6681 struct _sas_port *mpt2sas_port, *next_port;
6681 struct _sas_device *sas_device;
6682 struct _sas_node *expander_sibling;
6683 struct _raid_device *raid_device, *next; 6682 struct _raid_device *raid_device, *next;
6684 struct MPT2SAS_TARGET *sas_target_priv_data; 6683 struct MPT2SAS_TARGET *sas_target_priv_data;
6685 struct workqueue_struct *wq; 6684 struct workqueue_struct *wq;
@@ -6711,28 +6710,18 @@ _scsih_remove(struct pci_dev *pdev)
6711 } 6710 }
6712 6711
6713 /* free ports attached to the sas_host */ 6712 /* free ports attached to the sas_host */
6714 retry_again: 6713 list_for_each_entry_safe(mpt2sas_port, next_port,
6715 list_for_each_entry(mpt2sas_port,
6716 &ioc->sas_hba.sas_port_list, port_list) { 6714 &ioc->sas_hba.sas_port_list, port_list) {
6717 if (mpt2sas_port->remote_identify.device_type == 6715 if (mpt2sas_port->remote_identify.device_type ==
6718 SAS_END_DEVICE) { 6716 SAS_END_DEVICE)
6719 sas_device = 6717 mpt2sas_device_remove(ioc,
6720 mpt2sas_scsih_sas_device_find_by_sas_address(ioc, 6718 mpt2sas_port->remote_identify.sas_address);
6721 mpt2sas_port->remote_identify.sas_address); 6719 else if (mpt2sas_port->remote_identify.device_type ==
6722 if (sas_device) { 6720 SAS_EDGE_EXPANDER_DEVICE ||
6723 _scsih_remove_device(ioc, sas_device); 6721 mpt2sas_port->remote_identify.device_type ==
6724 goto retry_again; 6722 SAS_FANOUT_EXPANDER_DEVICE)
6725 } 6723 mpt2sas_expander_remove(ioc,
6726 } else {
6727 expander_sibling =
6728 mpt2sas_scsih_expander_find_by_sas_address(ioc,
6729 mpt2sas_port->remote_identify.sas_address); 6724 mpt2sas_port->remote_identify.sas_address);
6730 if (expander_sibling) {
6731 _scsih_expander_remove(ioc,
6732 expander_sibling->sas_address);
6733 goto retry_again;
6734 }
6735 }
6736 } 6725 }
6737 6726
6738 /* free phys attached to the sas_host */ 6727 /* free phys attached to the sas_host */
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c
index b55c6dc07470..cb1cdecbe0f8 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_transport.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c
@@ -465,62 +465,149 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
465 return rc; 465 return rc;
466} 466}
467 467
468/**
469 * _transport_delete_port - helper function to removing a port
470 * @ioc: per adapter object
471 * @mpt2sas_port: mpt2sas per port object
472 *
473 * Returns nothing.
474 */
475static void
476_transport_delete_port(struct MPT2SAS_ADAPTER *ioc,
477 struct _sas_port *mpt2sas_port)
478{
479 u64 sas_address = mpt2sas_port->remote_identify.sas_address;
480 enum sas_device_type device_type =
481 mpt2sas_port->remote_identify.device_type;
482
483 dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
484 "remove: sas_addr(0x%016llx)\n",
485 (unsigned long long) sas_address);
486
487 ioc->logging_level |= MPT_DEBUG_TRANSPORT;
488 if (device_type == SAS_END_DEVICE)
489 mpt2sas_device_remove(ioc, sas_address);
490 else if (device_type == SAS_EDGE_EXPANDER_DEVICE ||
491 device_type == SAS_FANOUT_EXPANDER_DEVICE)
492 mpt2sas_expander_remove(ioc, sas_address);
493 ioc->logging_level &= ~MPT_DEBUG_TRANSPORT;
494}
468 495
469/** 496/**
470 * _transport_delete_duplicate_port - (see below description) 497 * _transport_delete_phy - helper function to removing single phy from port
471 * @ioc: per adapter object 498 * @ioc: per adapter object
472 * @sas_node: sas node object (either expander or sas host) 499 * @mpt2sas_port: mpt2sas per port object
473 * @sas_address: sas address of device being added 500 * @mpt2sas_phy: mpt2sas per phy object
474 * @phy_num: phy number
475 * 501 *
476 * This function is called when attempting to add a new port that is claiming 502 * Returns nothing.
477 * the same phy resources already in use by another port. If we don't release 503 */
478 * the claimed phy resources, the sas transport layer will hang from the BUG 504static void
479 * in sas_port_add_phy. 505_transport_delete_phy(struct MPT2SAS_ADAPTER *ioc,
506 struct _sas_port *mpt2sas_port, struct _sas_phy *mpt2sas_phy)
507{
508 u64 sas_address = mpt2sas_port->remote_identify.sas_address;
509
510 dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
511 "remove: sas_addr(0x%016llx), phy(%d)\n",
512 (unsigned long long) sas_address, mpt2sas_phy->phy_id);
513
514 list_del(&mpt2sas_phy->port_siblings);
515 mpt2sas_port->num_phys--;
516 sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
517 mpt2sas_phy->phy_belongs_to_port = 0;
518}
519
520/**
521 * _transport_add_phy - helper function to adding single phy to port
522 * @ioc: per adapter object
523 * @mpt2sas_port: mpt2sas per port object
524 * @mpt2sas_phy: mpt2sas per phy object
480 * 525 *
481 * The reason we would hit this issue is becuase someone is changing the 526 * Returns nothing.
482 * sas address of a device on the fly, meanwhile controller firmware sends
483 * EVENTs out of order when removing the previous instance of the device.
484 */ 527 */
485static void 528static void
486_transport_delete_duplicate_port(struct MPT2SAS_ADAPTER *ioc, 529_transport_add_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_port *mpt2sas_port,
487 struct _sas_node *sas_node, u64 sas_address, int phy_num) 530 struct _sas_phy *mpt2sas_phy)
488{ 531{
489 struct _sas_port *mpt2sas_port, *mpt2sas_port_duplicate; 532 u64 sas_address = mpt2sas_port->remote_identify.sas_address;
490 struct _sas_phy *mpt2sas_phy;
491 533
492 printk(MPT2SAS_ERR_FMT "new device located at sas_addr(0x%016llx), " 534 dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
493 "phy_id(%d)\n", ioc->name, (unsigned long long)sas_address, 535 "add: sas_addr(0x%016llx), phy(%d)\n", (unsigned long long)
494 phy_num); 536 sas_address, mpt2sas_phy->phy_id);
495 537
496 mpt2sas_port_duplicate = NULL; 538 list_add_tail(&mpt2sas_phy->port_siblings, &mpt2sas_port->phy_list);
497 list_for_each_entry(mpt2sas_port, &sas_node->sas_port_list, port_list) { 539 mpt2sas_port->num_phys++;
498 dev_printk(KERN_ERR, &mpt2sas_port->port->dev, 540 sas_port_add_phy(mpt2sas_port->port, mpt2sas_phy->phy);
499 "existing device at sas_addr(0x%016llx), num_phys(%d)\n", 541 mpt2sas_phy->phy_belongs_to_port = 1;
500 (unsigned long long) 542}
501 mpt2sas_port->remote_identify.sas_address, 543
502 mpt2sas_port->num_phys); 544/**
503 list_for_each_entry(mpt2sas_phy, &mpt2sas_port->phy_list, 545 * _transport_add_phy_to_an_existing_port - adding new phy to existing port
546 * @ioc: per adapter object
547 * @sas_node: sas node object (either expander or sas host)
548 * @mpt2sas_phy: mpt2sas per phy object
549 * @sas_address: sas address of device/expander were phy needs to be added to
550 *
551 * Returns nothing.
552 */
553static void
554_transport_add_phy_to_an_existing_port(struct MPT2SAS_ADAPTER *ioc,
555struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy, u64 sas_address)
556{
557 struct _sas_port *mpt2sas_port;
558 struct _sas_phy *phy_srch;
559
560 if (mpt2sas_phy->phy_belongs_to_port == 1)
561 return;
562
563 list_for_each_entry(mpt2sas_port, &sas_node->sas_port_list,
564 port_list) {
565 if (mpt2sas_port->remote_identify.sas_address !=
566 sas_address)
567 continue;
568 list_for_each_entry(phy_srch, &mpt2sas_port->phy_list,
504 port_siblings) { 569 port_siblings) {
505 dev_printk(KERN_ERR, &mpt2sas_phy->phy->dev, 570 if (phy_srch == mpt2sas_phy)
506 "phy_number(%d)\n", mpt2sas_phy->phy_id); 571 return;
507 if (mpt2sas_phy->phy_id == phy_num)
508 mpt2sas_port_duplicate = mpt2sas_port;
509 } 572 }
573 _transport_add_phy(ioc, mpt2sas_port, mpt2sas_phy);
574 return;
510 } 575 }
511 576
512 if (!mpt2sas_port_duplicate) 577}
578
579/**
580 * _transport_del_phy_from_an_existing_port - delete phy from existing port
581 * @ioc: per adapter object
582 * @sas_node: sas node object (either expander or sas host)
583 * @mpt2sas_phy: mpt2sas per phy object
584 *
585 * Returns nothing.
586 */
587static void
588_transport_del_phy_from_an_existing_port(struct MPT2SAS_ADAPTER *ioc,
589 struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy)
590{
591 struct _sas_port *mpt2sas_port, *next;
592 struct _sas_phy *phy_srch;
593
594 if (mpt2sas_phy->phy_belongs_to_port == 0)
513 return; 595 return;
514 596
515 dev_printk(KERN_ERR, &mpt2sas_port_duplicate->port->dev, 597 list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
516 "deleting duplicate device at sas_addr(0x%016llx), phy(%d)!!!!\n", 598 port_list) {
517 (unsigned long long) 599 list_for_each_entry(phy_srch, &mpt2sas_port->phy_list,
518 mpt2sas_port_duplicate->remote_identify.sas_address, phy_num); 600 port_siblings) {
519 ioc->logging_level |= MPT_DEBUG_TRANSPORT; 601 if (phy_srch != mpt2sas_phy)
520 mpt2sas_transport_port_remove(ioc, 602 continue;
521 mpt2sas_port_duplicate->remote_identify.sas_address, 603 if (mpt2sas_port->num_phys == 1)
522 sas_node->sas_address); 604 _transport_delete_port(ioc, mpt2sas_port);
523 ioc->logging_level &= ~MPT_DEBUG_TRANSPORT; 605 else
606 _transport_delete_phy(ioc, mpt2sas_port,
607 mpt2sas_phy);
608 return;
609 }
610 }
524} 611}
525 612
526/** 613/**
@@ -537,11 +624,13 @@ _transport_sanity_check(struct MPT2SAS_ADAPTER *ioc, struct _sas_node *sas_node,
537{ 624{
538 int i; 625 int i;
539 626
540 for (i = 0; i < sas_node->num_phys; i++) 627 for (i = 0; i < sas_node->num_phys; i++) {
541 if (sas_node->phy[i].remote_identify.sas_address == sas_address) 628 if (sas_node->phy[i].remote_identify.sas_address != sas_address)
542 if (sas_node->phy[i].phy_belongs_to_port) 629 continue;
543 _transport_delete_duplicate_port(ioc, sas_node, 630 if (sas_node->phy[i].phy_belongs_to_port == 1)
544 sas_address, i); 631 _transport_del_phy_from_an_existing_port(ioc, sas_node,
632 &sas_node->phy[i]);
633 }
545} 634}
546 635
547/** 636/**
@@ -905,10 +994,12 @@ mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc,
905 994
906 mpt2sas_phy = &sas_node->phy[phy_number]; 995 mpt2sas_phy = &sas_node->phy[phy_number];
907 mpt2sas_phy->attached_handle = handle; 996 mpt2sas_phy->attached_handle = handle;
908 if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) 997 if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) {
909 _transport_set_identify(ioc, handle, 998 _transport_set_identify(ioc, handle,
910 &mpt2sas_phy->remote_identify); 999 &mpt2sas_phy->remote_identify);
911 else 1000 _transport_add_phy_to_an_existing_port(ioc, sas_node,
1001 mpt2sas_phy, mpt2sas_phy->remote_identify.sas_address);
1002 } else
912 memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct 1003 memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct
913 sas_identify)); 1004 sas_identify));
914 1005