diff options
Diffstat (limited to 'drivers/scsi/scsi_transport_sas.c')
-rw-r--r-- | drivers/scsi/scsi_transport_sas.c | 60 |
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); | |||
652 | sas_phy_linkerror_attr(loss_of_dword_sync_count); | 653 | sas_phy_linkerror_attr(loss_of_dword_sync_count); |
653 | sas_phy_linkerror_attr(phy_reset_problem_count); | 654 | sas_phy_linkerror_attr(phy_reset_problem_count); |
654 | 655 | ||
656 | static 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 | ||
656 | static DECLARE_TRANSPORT_CLASS(sas_phy_class, | 669 | static DECLARE_TRANSPORT_CLASS(sas_phy_class, |
657 | "sas_phy", NULL, NULL, NULL); | 670 | "sas_phy", sas_phy_setup, NULL, NULL); |
658 | 671 | ||
659 | static int sas_phy_match(struct attribute_container *cont, struct device *dev) | 672 | static 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) | |||
678 | static void sas_phy_release(struct device *dev) | 691 | static 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) | |||
1044 | EXPORT_SYMBOL(scsi_is_sas_port); | 1061 | EXPORT_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 | */ | ||
1067 | struct 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 | } | ||
1084 | EXPORT_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) | |||
1603 | EXPORT_SYMBOL(sas_rphy_delete); | 1643 | EXPORT_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 | */ | ||
1651 | void 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 | } | ||
1657 | EXPORT_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 | |||
1612 | sas_rphy_remove(struct sas_rphy *rphy) | 1666 | sas_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 | } |
1634 | EXPORT_SYMBOL(sas_rphy_remove); | 1686 | EXPORT_SYMBOL(sas_rphy_remove); |
1635 | 1687 | ||