diff options
author | Kashyap, Desai <kashyap.desai@lsi.com> | 2010-11-12 18:05:30 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-12-21 13:24:05 -0500 |
commit | 7f6f794dee50ba33710145140f39de59f5ec764e (patch) | |
tree | 0a08ef98b9ecc0a58bb8b024735c8bc02b65f2e7 /drivers/scsi/mpt2sas/mpt2sas_scsih.c | |
parent | 35f805b52c94f8e6cb22907ef32517132a15cb96 (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/mpt2sas/mpt2sas_scsih.c')
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_scsih.c | 143 |
1 files changed, 66 insertions, 77 deletions
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 | */ |
4354 | static void | 4357 | void |
4355 | _scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address) | 4358 | mpt2sas_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 | */ | ||
4670 | void | ||
4671 | mpt2sas_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 */ |