diff options
-rw-r--r-- | drivers/scsi/isci/core/intel_sas.h | 197 | ||||
-rw-r--r-- | drivers/scsi/isci/core/scic_sds_smp_request.c | 20 | ||||
-rw-r--r-- | drivers/scsi/isci/remote_device.c | 138 | ||||
-rw-r--r-- | drivers/scsi/isci/remote_node_context.c | 5 |
4 files changed, 23 insertions, 337 deletions
diff --git a/drivers/scsi/isci/core/intel_sas.h b/drivers/scsi/isci/core/intel_sas.h index d9c9f33a7af5..b57f39c2cfc2 100644 --- a/drivers/scsi/isci/core/intel_sas.h +++ b/drivers/scsi/isci/core/intel_sas.h | |||
@@ -628,202 +628,6 @@ struct smp_response_report_manufacturer_information { | |||
628 | 628 | ||
629 | }; | 629 | }; |
630 | 630 | ||
631 | #define SMP_RESPONSE_DISCOVER_FORMAT_1_1_SIZE 52 | ||
632 | #define SMP_RESPONSE_DISCOVER_FORMAT_2_SIZE 116 | ||
633 | |||
634 | /** | ||
635 | * struct smp_discover_response_protocols - This structure depicts the discover | ||
636 | * response where the supported protocols by the remote phy are specified. | ||
637 | * | ||
638 | * For specific information on each of these individual fields please reference | ||
639 | * the SAS specification Link layer section on address frames. | ||
640 | */ | ||
641 | struct smp_discover_response_protocols { | ||
642 | union { | ||
643 | struct { | ||
644 | u16 attached_sata_host:1; | ||
645 | u16 attached_smp_initiator:1; | ||
646 | u16 attached_stp_initiator:1; | ||
647 | u16 attached_ssp_initiator:1; | ||
648 | u16 reserved3:4; | ||
649 | u16 attached_sata_device:1; | ||
650 | u16 attached_smp_target:1; | ||
651 | u16 attached_stp_target:1; | ||
652 | u16 attached_ssp_target:1; | ||
653 | u16 reserved4:3; | ||
654 | u16 attached_sata_port_selector:1; | ||
655 | } bits; | ||
656 | |||
657 | u16 all; | ||
658 | } u; | ||
659 | |||
660 | }; | ||
661 | |||
662 | /** | ||
663 | * struct SMP_RESPONSE_DISCOVER_FORMAT - This structure defines the SMP phy | ||
664 | * discover response format. It handles both SAS1.1 and SAS 2 definitions. | ||
665 | * The unions indicate locations where the SAS specification versions differ | ||
666 | * from one another. | ||
667 | * | ||
668 | * | ||
669 | */ | ||
670 | struct smp_response_discover { | ||
671 | |||
672 | union { | ||
673 | struct { | ||
674 | u8 reserved[2]; | ||
675 | } sas1_1; | ||
676 | |||
677 | struct { | ||
678 | u16 expander_change_count; | ||
679 | } sas2; | ||
680 | |||
681 | } u1; | ||
682 | |||
683 | u8 reserved1[3]; | ||
684 | u8 phy_identifier; | ||
685 | u8 reserved2[2]; | ||
686 | |||
687 | union { | ||
688 | struct { | ||
689 | u16 reserved1:4; | ||
690 | u16 attached_device_type:3; | ||
691 | u16 reserved2:1; | ||
692 | u16 negotiated_physical_link_rate:4; | ||
693 | u16 reserved3:4; | ||
694 | } sas1_1; | ||
695 | |||
696 | struct { | ||
697 | u16 attached_reason:4; | ||
698 | u16 attached_device_type:3; | ||
699 | u16 reserved2:1; | ||
700 | u16 negotiated_logical_link_rate:4; | ||
701 | u16 reserved3:4; | ||
702 | } sas2; | ||
703 | |||
704 | } u2; | ||
705 | |||
706 | struct smp_discover_response_protocols protocols; | ||
707 | struct sci_sas_address sas_address; | ||
708 | struct sci_sas_address attached_sas_address; | ||
709 | |||
710 | u8 attached_phy_identifier; | ||
711 | |||
712 | union { | ||
713 | struct { | ||
714 | u8 reserved; | ||
715 | } sas1_1; | ||
716 | |||
717 | struct { | ||
718 | u8 attached_break_reply_capable:1; | ||
719 | u8 attached_requested_inside_zpsds:1; | ||
720 | u8 attached_inside_zpsds_persistent:1; | ||
721 | u8 reserved1:5; | ||
722 | } sas2; | ||
723 | |||
724 | } u3; | ||
725 | |||
726 | u8 reserved_for_identify[6]; | ||
727 | |||
728 | u32 hardware_min_physical_link_rate:4; | ||
729 | u32 programmed_min_physical_link_rate:4; | ||
730 | u32 hardware_max_physical_link_rate:4; | ||
731 | u32 programmed_max_physical_link_rate:4; | ||
732 | u32 phy_change_count:8; | ||
733 | u32 partial_pathway_timeout_value:4; | ||
734 | u32 reserved5:3; | ||
735 | u32 virtual_phy:1; | ||
736 | |||
737 | u32 routing_attribute:4; | ||
738 | u32 reserved6:4; | ||
739 | u32 connector_type:7; | ||
740 | u32 reserved7:1; | ||
741 | u32 connector_element_index:8; | ||
742 | u32 connector_physical_link:8; | ||
743 | |||
744 | u16 reserved8; | ||
745 | u16 vendor_specific; | ||
746 | |||
747 | union { | ||
748 | struct { | ||
749 | /** | ||
750 | * In the SAS 1.1 specification this structure ends after 52 bytes. | ||
751 | * As a result, the contents of this field should never have a | ||
752 | * real value. It is undefined. | ||
753 | */ | ||
754 | u8 undefined[SMP_RESPONSE_DISCOVER_FORMAT_2_SIZE | ||
755 | - SMP_RESPONSE_DISCOVER_FORMAT_1_1_SIZE]; | ||
756 | } sas1_1; | ||
757 | |||
758 | struct { | ||
759 | struct sci_sas_address attached_device_name; | ||
760 | |||
761 | u32 zoning_enabled:1; | ||
762 | u32 inside_zpsds:1; | ||
763 | u32 zone_group_persistent:1; | ||
764 | u32 reserved1:1; | ||
765 | u32 requested_inside_zpsds:1; | ||
766 | u32 inside_zpsds_persistent:1; | ||
767 | u32 requested_inside_zpsds_changed_by_expander:1; | ||
768 | u32 reserved2:1; | ||
769 | u32 reserved_for_zoning_fields:16; | ||
770 | u32 zone_group:8; | ||
771 | |||
772 | u8 self_configuration_status; | ||
773 | u8 self_configuration_levels_completed; | ||
774 | u16 reserved_for_self_config_fields; | ||
775 | |||
776 | struct sci_sas_address self_configuration_sas_address; | ||
777 | |||
778 | u32 programmed_phy_capabilities; | ||
779 | u32 current_phy_capabilities; | ||
780 | u32 attached_phy_capabilities; | ||
781 | |||
782 | u32 reserved3; | ||
783 | |||
784 | u32 reserved4:16; | ||
785 | u32 negotiated_physical_link_rate:4; | ||
786 | u32 reason:4; | ||
787 | u32 hardware_muxing_supported:1; | ||
788 | u32 negotiated_ssc:1; | ||
789 | u32 reserved5:6; | ||
790 | |||
791 | u32 default_zoning_enabled:1; | ||
792 | u32 reserved6:1; | ||
793 | u32 default_zone_group_persistent:1; | ||
794 | u32 reserved7:1; | ||
795 | u32 default_requested_inside_zpsds:1; | ||
796 | u32 default_inside_zpsds_persistent:1; | ||
797 | u32 reserved8:2; | ||
798 | u32 reserved9:16; | ||
799 | u32 default_zone_group:8; | ||
800 | |||
801 | u32 saved_zoning_enabled:1; | ||
802 | u32 reserved10:1; | ||
803 | u32 saved_zone_group_persistent:1; | ||
804 | u32 reserved11:1; | ||
805 | u32 saved_requested_inside_zpsds:1; | ||
806 | u32 saved_inside_zpsds_persistent:1; | ||
807 | u32 reserved12:18; | ||
808 | u32 saved_zone_group:8; | ||
809 | |||
810 | u32 reserved14:2; | ||
811 | u32 shadow_zone_group_persistent:1; | ||
812 | u32 reserved15:1; | ||
813 | u32 shadow_requested_inside_zpsds:1; | ||
814 | u32 shadow_inside_zpsds_persistent:1; | ||
815 | u32 reserved16:18; | ||
816 | u32 shadow_zone_group:8; | ||
817 | |||
818 | u8 device_slot_number; | ||
819 | u8 device_slot_group_number; | ||
820 | u8 device_slot_group_output_connector[6]; | ||
821 | } sas2; | ||
822 | |||
823 | } u4; | ||
824 | |||
825 | }; | ||
826 | |||
827 | /** | 631 | /** |
828 | * struct smp_response_report_phy_sata - This structure depicts the contents of | 632 | * struct smp_response_report_phy_sata - This structure depicts the contents of |
829 | * the SAS SMP REPORT PHY SATA frame. For specific information on each of | 633 | * the SAS SMP REPORT PHY SATA frame. For specific information on each of |
@@ -857,7 +661,6 @@ struct smp_response_vendor_specific { | |||
857 | union smp_response_body { | 661 | union smp_response_body { |
858 | struct smp_response_report_general report_general; | 662 | struct smp_response_report_general report_general; |
859 | struct smp_response_report_manufacturer_information report_manufacturer_information; | 663 | struct smp_response_report_manufacturer_information report_manufacturer_information; |
860 | struct smp_response_discover discover; | ||
861 | struct smp_response_report_phy_sata report_phy_sata; | 664 | struct smp_response_report_phy_sata report_phy_sata; |
862 | struct smp_response_vendor_specific vendor_specific_response; | 665 | struct smp_response_vendor_specific vendor_specific_response; |
863 | }; | 666 | }; |
diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c index 1790f25758d1..d4009e57acaf 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c | |||
@@ -339,26 +339,6 @@ static enum sci_status scic_sds_smp_request_await_response_frame_handler( | |||
339 | smp_response_buffer, | 339 | smp_response_buffer, |
340 | sizeof(union smp_response_body) / sizeof(u32) | 340 | sizeof(union smp_response_body) / sizeof(u32) |
341 | ); | 341 | ); |
342 | if (rsp_hdr->function == SMP_FUNCTION_DISCOVER) { | ||
343 | struct smp_response *smp_resp; | ||
344 | |||
345 | smp_resp = (struct smp_response *)user_smp_buffer; | ||
346 | |||
347 | /* | ||
348 | * Some expanders only report an attached SATA device, and | ||
349 | * not an STP target. Since the core depends on the STP | ||
350 | * target attribute to correctly build I/O, set the bit now | ||
351 | * if necessary. */ | ||
352 | if (smp_resp->response.discover.protocols.u.bits.attached_sata_device | ||
353 | && !smp_resp->response.discover.protocols.u.bits.attached_stp_target) { | ||
354 | smp_resp->response.discover.protocols.u.bits.attached_stp_target = 1; | ||
355 | |||
356 | dev_dbg(scic_to_dev(sci_req->owning_controller), | ||
357 | "%s: scic_sds_smp_request_await_response_frame_handler(0x%p) Found SATA dev, setting STP bit.\n", | ||
358 | __func__, sci_req); | ||
359 | } | ||
360 | } | ||
361 | |||
362 | /* | 342 | /* |
363 | * Don't need to copy to user space. User instead will refer to | 343 | * Don't need to copy to user space. User instead will refer to |
364 | * core request's response buffer. */ | 344 | * core request's response buffer. */ |
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 | } |
diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index 285232fd5e63..59f878f11f33 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c | |||
@@ -124,8 +124,9 @@ static void scic_sds_remote_node_context_construct_buffer( | |||
124 | rnc->ssp.logical_port_index = | 124 | rnc->ssp.logical_port_index = |
125 | scic_sds_remote_device_get_port_index(sci_dev); | 125 | scic_sds_remote_device_get_port_index(sci_dev); |
126 | 126 | ||
127 | rnc->ssp.remote_sas_address_hi = SCIC_SWAP_DWORD(sci_dev->device_address.high); | 127 | /* address is always big endian, destination is always little */ |
128 | rnc->ssp.remote_sas_address_lo = SCIC_SWAP_DWORD(sci_dev->device_address.low); | 128 | rnc->ssp.remote_sas_address_hi = swab32(sci_dev->device_address.high); |
129 | rnc->ssp.remote_sas_address_lo = swab32(sci_dev->device_address.low); | ||
129 | 130 | ||
130 | rnc->ssp.nexus_loss_timer_enable = true; | 131 | rnc->ssp.nexus_loss_timer_enable = true; |
131 | rnc->ssp.check_bit = false; | 132 | rnc->ssp.check_bit = false; |