aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_transport_sas.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_transport_sas.c')
-rw-r--r--drivers/scsi/scsi_transport_sas.c60
1 files changed, 56 insertions, 4 deletions
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index 9d9330ae4213..f7565fc4f0e3 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -615,6 +615,7 @@ do_sas_phy_reset(struct device *dev, size_t count, int hard_reset)
615 error = i->f->phy_reset(phy, hard_reset); 615 error = i->f->phy_reset(phy, hard_reset);
616 if (error) 616 if (error)
617 return error; 617 return error;
618 phy->enabled = 1;
618 return count; 619 return count;
619}; 620};
620 621
@@ -652,9 +653,21 @@ sas_phy_linkerror_attr(running_disparity_error_count);
652sas_phy_linkerror_attr(loss_of_dword_sync_count); 653sas_phy_linkerror_attr(loss_of_dword_sync_count);
653sas_phy_linkerror_attr(phy_reset_problem_count); 654sas_phy_linkerror_attr(phy_reset_problem_count);
654 655
656static int sas_phy_setup(struct transport_container *tc, struct device *dev,
657 struct device *cdev)
658{
659 struct sas_phy *phy = dev_to_phy(dev);
660 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
661 struct sas_internal *i = to_sas_internal(shost->transportt);
662
663 if (i->f->phy_setup)
664 i->f->phy_setup(phy);
665
666 return 0;
667}
655 668
656static DECLARE_TRANSPORT_CLASS(sas_phy_class, 669static DECLARE_TRANSPORT_CLASS(sas_phy_class,
657 "sas_phy", NULL, NULL, NULL); 670 "sas_phy", sas_phy_setup, NULL, NULL);
658 671
659static int sas_phy_match(struct attribute_container *cont, struct device *dev) 672static int sas_phy_match(struct attribute_container *cont, struct device *dev)
660{ 673{
@@ -678,7 +691,11 @@ static int sas_phy_match(struct attribute_container *cont, struct device *dev)
678static void sas_phy_release(struct device *dev) 691static void sas_phy_release(struct device *dev)
679{ 692{
680 struct sas_phy *phy = dev_to_phy(dev); 693 struct sas_phy *phy = dev_to_phy(dev);
694 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
695 struct sas_internal *i = to_sas_internal(shost->transportt);
681 696
697 if (i->f->phy_release)
698 i->f->phy_release(phy);
682 put_device(dev->parent); 699 put_device(dev->parent);
683 kfree(phy); 700 kfree(phy);
684} 701}
@@ -1044,6 +1061,29 @@ int scsi_is_sas_port(const struct device *dev)
1044EXPORT_SYMBOL(scsi_is_sas_port); 1061EXPORT_SYMBOL(scsi_is_sas_port);
1045 1062
1046/** 1063/**
1064 * sas_port_get_phy - try to take a reference on a port member
1065 * @port: port to check
1066 */
1067struct sas_phy *sas_port_get_phy(struct sas_port *port)
1068{
1069 struct sas_phy *phy;
1070
1071 mutex_lock(&port->phy_list_mutex);
1072 if (list_empty(&port->phy_list))
1073 phy = NULL;
1074 else {
1075 struct list_head *ent = port->phy_list.next;
1076
1077 phy = list_entry(ent, typeof(*phy), port_siblings);
1078 get_device(&phy->dev);
1079 }
1080 mutex_unlock(&port->phy_list_mutex);
1081
1082 return phy;
1083}
1084EXPORT_SYMBOL(sas_port_get_phy);
1085
1086/**
1047 * sas_port_add_phy - add another phy to a port to form a wide port 1087 * sas_port_add_phy - add another phy to a port to form a wide port
1048 * @port: port to add the phy to 1088 * @port: port to add the phy to
1049 * @phy: phy to add 1089 * @phy: phy to add
@@ -1603,6 +1643,20 @@ sas_rphy_delete(struct sas_rphy *rphy)
1603EXPORT_SYMBOL(sas_rphy_delete); 1643EXPORT_SYMBOL(sas_rphy_delete);
1604 1644
1605/** 1645/**
1646 * sas_rphy_unlink - unlink SAS remote PHY
1647 * @rphy: SAS remote phy to unlink from its parent port
1648 *
1649 * Removes port reference to an rphy
1650 */
1651void sas_rphy_unlink(struct sas_rphy *rphy)
1652{
1653 struct sas_port *parent = dev_to_sas_port(rphy->dev.parent);
1654
1655 parent->rphy = NULL;
1656}
1657EXPORT_SYMBOL(sas_rphy_unlink);
1658
1659/**
1606 * sas_rphy_remove - remove SAS remote PHY 1660 * sas_rphy_remove - remove SAS remote PHY
1607 * @rphy: SAS remote phy to remove 1661 * @rphy: SAS remote phy to remove
1608 * 1662 *
@@ -1612,7 +1666,6 @@ void
1612sas_rphy_remove(struct sas_rphy *rphy) 1666sas_rphy_remove(struct sas_rphy *rphy)
1613{ 1667{
1614 struct device *dev = &rphy->dev; 1668 struct device *dev = &rphy->dev;
1615 struct sas_port *parent = dev_to_sas_port(dev->parent);
1616 1669
1617 switch (rphy->identify.device_type) { 1670 switch (rphy->identify.device_type) {
1618 case SAS_END_DEVICE: 1671 case SAS_END_DEVICE:
@@ -1626,10 +1679,9 @@ sas_rphy_remove(struct sas_rphy *rphy)
1626 break; 1679 break;
1627 } 1680 }
1628 1681
1682 sas_rphy_unlink(rphy);
1629 transport_remove_device(dev); 1683 transport_remove_device(dev);
1630 device_del(dev); 1684 device_del(dev);
1631
1632 parent->rphy = NULL;
1633} 1685}
1634EXPORT_SYMBOL(sas_rphy_remove); 1686EXPORT_SYMBOL(sas_rphy_remove);
1635 1687