lkml.org 
[lkml]   [2019]   [Nov]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 4.14 121/127] scsi: libsas: Support SATA PHY connection rate unmatch fixing during discovery
    Date
    From: John Garry <john.garry@huawei.com>

    [ Upstream commit cec9771d2e954650095aa37a6a97722c8194e7d2 ]

    +----------+ +----------+
    | | | |
    | |--- 3.0 G ---| |--- 6.0 G --- SAS disk
    | | | |
    | |--- 3.0 G ---| |--- 6.0 G --- SAS disk
    |initiator | | |
    | device |--- 3.0 G ---| Expander |--- 6.0 G --- SAS disk
    | | | |
    | |--- 3.0 G ---| |--- 6.0 G --- SATA disk -->failed to connect
    | | | |
    | | | |--- 6.0 G --- SATA disk -->failed to connect
    | | | |
    +----------+ +----------+

    According to Serial Attached SCSI - 1.1 (SAS-1.1):
    If an expander PHY attached to a SATA PHY is using a physical link rate
    greater than the maximum connection rate supported by the pathway from an
    STP initiator port, a management application client should use the SMP PHY
    CONTROL function (see 10.4.3.10) to set the PROGRAMMED MAXIMUM PHYSICAL
    LINK RATE field of the expander PHY to the maximum connection rate
    supported by the pathway from that STP initiator port.

    Currently libsas does not support checking if this condition occurs, nor
    rectifying when it does.

    Such a condition is not at all common, however it has been seen on some
    pre-silicon environments where the initiator PHY only supports a 1.5 Gbit
    maximum linkrate, mated with 12G expander PHYs and 3/6G SATA phy.

    This patch adds support for checking and rectifying this condition during
    initial device discovery only.

    We do support checking min pathway connection rate during revalidation phase,
    when new devices can be detected in the topology. However we do not
    support in the case of the the user reprogramming PHY linkrates, such that
    min pathway condition is not met/maintained.

    A note on root port PHY rates:
    The libsas root port PHY rates calculation is broken. Libsas sets the
    rates (min, max, and current linkrate) of a root port to the same linkrate
    of the first PHY member of that same port. In doing so, it assumes that
    all other PHYs which subsequently join the port to have the same
    negotiated linkrate, when they could actually be different.

    In practice this doesn't happen, as initiator and expander PHYs are
    normally initialised with consistent min/max linkrates.

    This has not caused an issue so far, so leave alone for now.

    Tested-by: Jian Luo <luojian5@huawei.com>
    Signed-off-by: John Garry <john.garry@huawei.com>
    Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/scsi/libsas/sas_expander.c | 20 ++++++++++++++++++++
    1 file changed, 20 insertions(+)

    diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
    index 259ee0d3c3e61..819a655473588 100644
    --- a/drivers/scsi/libsas/sas_expander.c
    +++ b/drivers/scsi/libsas/sas_expander.c
    @@ -817,6 +817,26 @@ static struct domain_device *sas_ex_discover_end_dev(

    #ifdef CONFIG_SCSI_SAS_ATA
    if ((phy->attached_tproto & SAS_PROTOCOL_STP) || phy->attached_sata_dev) {
    + if (child->linkrate > parent->min_linkrate) {
    + struct sas_phy_linkrates rates = {
    + .maximum_linkrate = parent->min_linkrate,
    + .minimum_linkrate = parent->min_linkrate,
    + };
    + int ret;
    +
    + pr_notice("ex %016llx phy%02d SATA device linkrate > min pathway connection rate, attempting to lower device linkrate\n",
    + SAS_ADDR(child->sas_addr), phy_id);
    + ret = sas_smp_phy_control(parent, phy_id,
    + PHY_FUNC_LINK_RESET, &rates);
    + if (ret) {
    + pr_err("ex %016llx phy%02d SATA device could not set linkrate (%d)\n",
    + SAS_ADDR(child->sas_addr), phy_id, ret);
    + goto out_free;
    + }
    + pr_notice("ex %016llx phy%02d SATA device set linkrate successfully\n",
    + SAS_ADDR(child->sas_addr), phy_id);
    + child->linkrate = child->min_linkrate;
    + }
    res = sas_get_ata_info(child, phy);
    if (res)
    goto out_free;
    --
    2.20.1
    \
     
     \ /
      Last update: 2019-11-22 06:58    [W:4.103 / U:0.348 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site