diff options
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_transport.c | 61 |
1 files changed, 59 insertions, 2 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c index fed8b163afef..865deb9a5e5a 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_transport.c +++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c | |||
@@ -1639,11 +1639,13 @@ _transport_phy_enable(struct sas_phy *phy, int enable) | |||
1639 | { | 1639 | { |
1640 | struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy); | 1640 | struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy); |
1641 | Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL; | 1641 | Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL; |
1642 | Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; | ||
1642 | Mpi2ConfigReply_t mpi_reply; | 1643 | Mpi2ConfigReply_t mpi_reply; |
1643 | u16 ioc_status; | 1644 | u16 ioc_status; |
1644 | u16 sz; | 1645 | u16 sz; |
1645 | int rc = 0; | 1646 | int rc = 0; |
1646 | unsigned long flags; | 1647 | unsigned long flags; |
1648 | int i, discovery_active; | ||
1647 | 1649 | ||
1648 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | 1650 | spin_lock_irqsave(&ioc->sas_node_lock, flags); |
1649 | if (_transport_sas_node_find_by_sas_address(ioc, | 1651 | if (_transport_sas_node_find_by_sas_address(ioc, |
@@ -1661,7 +1663,50 @@ _transport_phy_enable(struct sas_phy *phy, int enable) | |||
1661 | 1663 | ||
1662 | /* handle hba phys */ | 1664 | /* handle hba phys */ |
1663 | 1665 | ||
1664 | /* sas_iounit page 1 */ | 1666 | /* read sas_iounit page 0 */ |
1667 | sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys * | ||
1668 | sizeof(Mpi2SasIOUnit0PhyData_t)); | ||
1669 | sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL); | ||
1670 | if (!sas_iounit_pg0) { | ||
1671 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
1672 | ioc->name, __FILE__, __LINE__, __func__); | ||
1673 | rc = -ENOMEM; | ||
1674 | goto out; | ||
1675 | } | ||
1676 | if ((mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply, | ||
1677 | sas_iounit_pg0, sz))) { | ||
1678 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
1679 | ioc->name, __FILE__, __LINE__, __func__); | ||
1680 | rc = -ENXIO; | ||
1681 | goto out; | ||
1682 | } | ||
1683 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
1684 | MPI2_IOCSTATUS_MASK; | ||
1685 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
1686 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
1687 | ioc->name, __FILE__, __LINE__, __func__); | ||
1688 | rc = -EIO; | ||
1689 | goto out; | ||
1690 | } | ||
1691 | |||
1692 | /* unable to enable/disable phys when when discovery is active */ | ||
1693 | for (i = 0, discovery_active = 0; i < ioc->sas_hba.num_phys ; i++) { | ||
1694 | if (sas_iounit_pg0->PhyData[i].PortFlags & | ||
1695 | MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS) { | ||
1696 | printk(MPT2SAS_ERR_FMT "discovery is active on " | ||
1697 | "port = %d, phy = %d: unable to enable/disable " | ||
1698 | "phys, try again later!\n", ioc->name, | ||
1699 | sas_iounit_pg0->PhyData[i].Port, i); | ||
1700 | discovery_active = 1; | ||
1701 | } | ||
1702 | } | ||
1703 | |||
1704 | if (discovery_active) { | ||
1705 | rc = -EAGAIN; | ||
1706 | goto out; | ||
1707 | } | ||
1708 | |||
1709 | /* read sas_iounit page 1 */ | ||
1665 | sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys * | 1710 | sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys * |
1666 | sizeof(Mpi2SasIOUnit1PhyData_t)); | 1711 | sizeof(Mpi2SasIOUnit1PhyData_t)); |
1667 | sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL); | 1712 | sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL); |
@@ -1686,7 +1731,18 @@ _transport_phy_enable(struct sas_phy *phy, int enable) | |||
1686 | rc = -EIO; | 1731 | rc = -EIO; |
1687 | goto out; | 1732 | goto out; |
1688 | } | 1733 | } |
1689 | 1734 | /* copy Port/PortFlags/PhyFlags from page 0 */ | |
1735 | for (i = 0; i < ioc->sas_hba.num_phys ; i++) { | ||
1736 | sas_iounit_pg1->PhyData[i].Port = | ||
1737 | sas_iounit_pg0->PhyData[i].Port; | ||
1738 | sas_iounit_pg1->PhyData[i].PortFlags = | ||
1739 | (sas_iounit_pg0->PhyData[i].PortFlags & | ||
1740 | MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG); | ||
1741 | sas_iounit_pg1->PhyData[i].PhyFlags = | ||
1742 | (sas_iounit_pg0->PhyData[i].PhyFlags & | ||
1743 | (MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED + | ||
1744 | MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED)); | ||
1745 | } | ||
1690 | if (enable) | 1746 | if (enable) |
1691 | sas_iounit_pg1->PhyData[phy->number].PhyFlags | 1747 | sas_iounit_pg1->PhyData[phy->number].PhyFlags |
1692 | &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; | 1748 | &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; |
@@ -1702,6 +1758,7 @@ _transport_phy_enable(struct sas_phy *phy, int enable) | |||
1702 | 1758 | ||
1703 | out: | 1759 | out: |
1704 | kfree(sas_iounit_pg1); | 1760 | kfree(sas_iounit_pg1); |
1761 | kfree(sas_iounit_pg0); | ||
1705 | return rc; | 1762 | return rc; |
1706 | } | 1763 | } |
1707 | 1764 | ||