diff options
Diffstat (limited to 'drivers/scsi/isci/remote_device.c')
-rw-r--r-- | drivers/scsi/isci/remote_device.c | 138 |
1 files changed, 20 insertions, 118 deletions
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index fc79a5b47f72..5ba3b5dca4d5 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c | |||
@@ -1533,21 +1533,8 @@ static enum sci_status scic_remote_device_da_construct(struct scic_sds_port *sci | |||
1533 | return SCI_SUCCESS; | 1533 | return SCI_SUCCESS; |
1534 | } | 1534 | } |
1535 | 1535 | ||
1536 | static void scic_sds_remote_device_get_info_from_smp_discover_response( | ||
1537 | struct scic_sds_remote_device *sci_dev, | ||
1538 | struct smp_response_discover *discover_response) | ||
1539 | { | ||
1540 | /* decode discover_response to set sas_address to sci_dev. */ | ||
1541 | sci_dev->device_address.high = | ||
1542 | discover_response->attached_sas_address.high; | ||
1543 | |||
1544 | sci_dev->device_address.low = | ||
1545 | discover_response->attached_sas_address.low; | ||
1546 | } | ||
1547 | |||
1548 | /** | 1536 | /** |
1549 | * scic_remote_device_ea_construct() - construct expander attached device | 1537 | * scic_remote_device_ea_construct() - construct expander attached device |
1550 | * @discover_response: data to build remote device | ||
1551 | * | 1538 | * |
1552 | * Remote node context(s) is/are a global resource allocated by this | 1539 | * Remote node context(s) is/are a global resource allocated by this |
1553 | * routine, freed by scic_remote_device_destruct(). | 1540 | * routine, freed by scic_remote_device_destruct(). |
@@ -1559,17 +1546,14 @@ static void scic_sds_remote_device_get_info_from_smp_discover_response( | |||
1559 | * SCI_FAILURE_INSUFFICIENT_RESOURCES - remote node contexts exhausted. | 1546 | * SCI_FAILURE_INSUFFICIENT_RESOURCES - remote node contexts exhausted. |
1560 | */ | 1547 | */ |
1561 | static enum sci_status scic_remote_device_ea_construct(struct scic_sds_port *sci_port, | 1548 | static enum sci_status scic_remote_device_ea_construct(struct scic_sds_port *sci_port, |
1562 | struct scic_sds_remote_device *sci_dev, | 1549 | struct scic_sds_remote_device *sci_dev) |
1563 | struct smp_response_discover *discover_response) | ||
1564 | { | 1550 | { |
1565 | struct scic_sds_controller *scic = sci_port->owning_controller; | 1551 | struct scic_sds_controller *scic = sci_port->owning_controller; |
1566 | struct domain_device *dev = sci_dev_to_domain(sci_dev); | 1552 | struct domain_device *dev = sci_dev_to_domain(sci_dev); |
1567 | enum sci_status status; | 1553 | enum sci_status status; |
1568 | 1554 | ||
1569 | scic_remote_device_construct(sci_port, sci_dev); | 1555 | scic_remote_device_construct(sci_port, sci_dev); |
1570 | 1556 | memcpy(&sci_dev->device_address, dev->sas_addr, SAS_ADDR_SIZE); | |
1571 | scic_sds_remote_device_get_info_from_smp_discover_response( | ||
1572 | sci_dev, discover_response); | ||
1573 | 1557 | ||
1574 | status = scic_sds_controller_allocate_remote_node_context( | 1558 | status = scic_sds_controller_allocate_remote_node_context( |
1575 | scic, sci_dev, &sci_dev->rnc.remote_node_index); | 1559 | scic, sci_dev, &sci_dev->rnc.remote_node_index); |
@@ -1605,7 +1589,7 @@ static enum sci_status scic_remote_device_ea_construct(struct scic_sds_port *sci | |||
1605 | * physical. Furthermore, the SAS-2 and SAS-1.1 fields overlay | 1589 | * physical. Furthermore, the SAS-2 and SAS-1.1 fields overlay |
1606 | * one another, so this code works for both situations. */ | 1590 | * one another, so this code works for both situations. */ |
1607 | sci_dev->connection_rate = min_t(u16, scic_sds_port_get_max_allowed_speed(sci_port), | 1591 | sci_dev->connection_rate = min_t(u16, scic_sds_port_get_max_allowed_speed(sci_port), |
1608 | discover_response->u2.sas1_1.negotiated_physical_link_rate); | 1592 | dev->linkrate); |
1609 | 1593 | ||
1610 | /* / @todo Should I assign the port width by reading all of the phys on the port? */ | 1594 | /* / @todo Should I assign the port width by reading all of the phys on the port? */ |
1611 | sci_dev->device_port_width = 1; | 1595 | sci_dev->device_port_width = 1; |
@@ -1632,117 +1616,35 @@ static enum sci_status scic_remote_device_start(struct scic_sds_remote_device *s | |||
1632 | return sci_dev->state_handlers->start_handler(sci_dev); | 1616 | return sci_dev->state_handlers->start_handler(sci_dev); |
1633 | } | 1617 | } |
1634 | 1618 | ||
1635 | /** | 1619 | static enum sci_status isci_remote_device_construct(struct isci_port *iport, |
1636 | * isci_remote_device_construct() - This function calls the scic remote device | 1620 | struct isci_remote_device *idev) |
1637 | * construct and start functions, it waits on the remote device start | ||
1638 | * completion. | ||
1639 | * @port: This parameter specifies the isci port with the remote device. | ||
1640 | * @isci_device: This parameter specifies the isci remote device | ||
1641 | * | ||
1642 | * status from the scic calls, the caller to this function should clean up | ||
1643 | * resources as appropriate. | ||
1644 | */ | ||
1645 | static enum sci_status isci_remote_device_construct( | ||
1646 | struct isci_port *port, | ||
1647 | struct isci_remote_device *isci_device) | ||
1648 | { | 1621 | { |
1649 | enum sci_status status = SCI_SUCCESS; | 1622 | struct scic_sds_port *sci_port = iport->sci_port_handle; |
1650 | 1623 | struct isci_host *ihost = iport->isci_host; | |
1651 | if (isci_device->domain_dev->parent && | 1624 | struct domain_device *dev = idev->domain_dev; |
1652 | dev_is_expander(isci_device->domain_dev->parent)) { | 1625 | enum sci_status status; |
1653 | int i; | ||
1654 | |||
1655 | /* struct smp_response_discover discover_response; */ | ||
1656 | struct discover_resp discover_response; | ||
1657 | struct domain_device *parent = | ||
1658 | isci_device->domain_dev->parent; | ||
1659 | |||
1660 | struct expander_device *parent_ex = &parent->ex_dev; | ||
1661 | |||
1662 | for (i = 0; i < parent_ex->num_phys; i++) { | ||
1663 | |||
1664 | struct ex_phy *phy = &parent_ex->ex_phy[i]; | ||
1665 | |||
1666 | if ((phy->phy_state == PHY_VACANT) || | ||
1667 | (phy->phy_state == PHY_NOT_PRESENT)) | ||
1668 | continue; | ||
1669 | |||
1670 | if (SAS_ADDR(phy->attached_sas_addr) | ||
1671 | == SAS_ADDR(isci_device->domain_dev->sas_addr)) { | ||
1672 | |||
1673 | discover_response.attached_dev_type | ||
1674 | = phy->attached_dev_type; | ||
1675 | discover_response.linkrate | ||
1676 | = phy->linkrate; | ||
1677 | discover_response.attached_sata_host | ||
1678 | = phy->attached_sata_host; | ||
1679 | discover_response.attached_sata_dev | ||
1680 | = phy->attached_sata_dev; | ||
1681 | discover_response.attached_sata_ps | ||
1682 | = phy->attached_sata_ps; | ||
1683 | discover_response.iproto | ||
1684 | = phy->attached_iproto >> 1; | ||
1685 | discover_response.tproto | ||
1686 | = phy->attached_tproto >> 1; | ||
1687 | memcpy( | ||
1688 | discover_response.attached_sas_addr, | ||
1689 | phy->attached_sas_addr, | ||
1690 | SAS_ADDR_SIZE | ||
1691 | ); | ||
1692 | discover_response.attached_phy_id | ||
1693 | = phy->attached_phy_id; | ||
1694 | discover_response.change_count | ||
1695 | = phy->phy_change_count; | ||
1696 | discover_response.routing_attr | ||
1697 | = phy->routing_attr; | ||
1698 | discover_response.hmin_linkrate | ||
1699 | = phy->phy->minimum_linkrate_hw; | ||
1700 | discover_response.hmax_linkrate | ||
1701 | = phy->phy->maximum_linkrate_hw; | ||
1702 | discover_response.pmin_linkrate | ||
1703 | = phy->phy->minimum_linkrate; | ||
1704 | discover_response.pmax_linkrate | ||
1705 | = phy->phy->maximum_linkrate; | ||
1706 | } | ||
1707 | } | ||
1708 | |||
1709 | |||
1710 | dev_dbg(&port->isci_host->pdev->dev, | ||
1711 | "%s: parent->dev_type = EDGE_DEV\n", | ||
1712 | __func__); | ||
1713 | |||
1714 | status = scic_remote_device_ea_construct(port->sci_port_handle, | ||
1715 | &isci_device->sci, | ||
1716 | (struct smp_response_discover *)&discover_response); | ||
1717 | |||
1718 | } else | ||
1719 | status = scic_remote_device_da_construct(port->sci_port_handle, | ||
1720 | &isci_device->sci); | ||
1721 | 1626 | ||
1627 | if (dev->parent && dev_is_expander(dev->parent)) | ||
1628 | status = scic_remote_device_ea_construct(sci_port, &idev->sci); | ||
1629 | else | ||
1630 | status = scic_remote_device_da_construct(sci_port, &idev->sci); | ||
1722 | 1631 | ||
1723 | if (status != SCI_SUCCESS) { | 1632 | if (status != SCI_SUCCESS) { |
1724 | dev_dbg(&port->isci_host->pdev->dev, | 1633 | dev_dbg(&ihost->pdev->dev, "%s: construct failed: %d\n", |
1725 | "%s: scic_remote_device_da_construct failed - " | 1634 | __func__, status); |
1726 | "isci_device = %p\n", | ||
1727 | __func__, | ||
1728 | isci_device); | ||
1729 | 1635 | ||
1730 | return status; | 1636 | return status; |
1731 | } | 1637 | } |
1732 | 1638 | ||
1733 | /* XXX will be killed with sci_base_object removal */ | 1639 | /* XXX will be killed with sci_base_object removal */ |
1734 | sci_object_set_association(&isci_device->sci, isci_device); | 1640 | sci_object_set_association(&idev->sci, idev); |
1735 | 1641 | ||
1736 | /* start the device. */ | 1642 | /* start the device. */ |
1737 | status = scic_remote_device_start(&isci_device->sci, | 1643 | status = scic_remote_device_start(&idev->sci, ISCI_REMOTE_DEVICE_START_TIMEOUT); |
1738 | ISCI_REMOTE_DEVICE_START_TIMEOUT); | ||
1739 | 1644 | ||
1740 | if (status != SCI_SUCCESS) { | 1645 | if (status != SCI_SUCCESS) |
1741 | dev_warn(&port->isci_host->pdev->dev, | 1646 | dev_warn(&ihost->pdev->dev, "remote device start failed: %d\n", |
1742 | "%s: scic_remote_device_start failed\n", | 1647 | status); |
1743 | __func__); | ||
1744 | return status; | ||
1745 | } | ||
1746 | 1648 | ||
1747 | return status; | 1649 | return status; |
1748 | } | 1650 | } |