From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.1 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8FB45C43381 for ; Fri, 1 Mar 2019 19:41:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 46DFE2084D for ; Fri, 1 Mar 2019 19:41:10 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="NvEDgTZe" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726457AbfCATlI (ORCPT ); Fri, 1 Mar 2019 14:41:08 -0500 Received: from mail-wm1-f67.google.com ([209.85.128.67]:50410 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725974AbfCATlI (ORCPT ); Fri, 1 Mar 2019 14:41:08 -0500 Received: by mail-wm1-f67.google.com with SMTP id x7so13511026wmj.0 for ; Fri, 01 Mar 2019 11:41:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:subject:to:cc:message-id:date:user-agent:mime-version :content-language:content-transfer-encoding; bh=B5qcRATD5KmdN+XSJnQ/lsR60s2tBUBmADVh/0d0/xc=; b=NvEDgTZehMj1lr9L/MjaSpx9HQS28t7hKEbGrLmUF9638EkxRyr87ulng+NEzXmplz Bs0qjZywDP31xX2NeEoGJbWY0PdYnYWdz+QCcsoWl+eF1w7ESHneO3Zo3Un27pY8JOJN uDGmznvMqK+jwtMXzXIOcWnI9poSozzQGBTZbrKdeTw00JiJXSwokyEqP4bwF31tqxfA OcSmdBfi+ebEo5pKKU3NK5d5foyFYzjNIdSYIisQ4gkq4BaYwLpBH96GO8FOxsYqbSxn mTHbC7MJTefanxq4KCp3GdmqvEdXobe+ZBT/2WFWkfghp3VVby5C36lIIXuBD0JPvnhR OAVw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:subject:to:cc:message-id:date:user-agent :mime-version:content-language:content-transfer-encoding; bh=B5qcRATD5KmdN+XSJnQ/lsR60s2tBUBmADVh/0d0/xc=; b=qd7kke9SQzgnJpULnen5eXfXZs4pV90VsWMC8TJ10ctckC2wpXiNHRAGUkCRGTGfr9 NRVtfiejHjVnntU0TQ4r+EfCmkNtGTLtxlzbaN+OxuXVjGaKgxLyt8oMaJwPW/XdMcuL FKc1tL2lZfLJxyxz53ndXgfk9780b8NGIwQaCN9t1UirU55MMsaMLVxBRrrpvTd0qk8W KlVXTT/Fqj4+J6wJfeBeGo/lmBynDgMKoT1Ut8Tc22QQXCcIjlzgBbQ7NNR7QupWhmh+ WYAyIgu5QdBvGJsJvV3MRW26Fh8Nh032QKMIfUGeTfhBFXNeD7/mzB1aN8nS1rpKhBH6 Vz/w== X-Gm-Message-State: APjAAAX3jhb4zJRlw2dKLypeBZiZccSrHQmC6UwCmHaJZib48LFSyK0b IpUDerhSFhByoh/ok1HLplw= X-Google-Smtp-Source: AHgI3IanarJuVm9cG4iwOLVah1yWb1RxJTrBBB/n0csFPxZ6VSKKkBxFb7dENjJAX+BnGJ4yDrj+gA== X-Received: by 2002:a7b:c0d5:: with SMTP id s21mr4520588wmh.153.1551469266150; Fri, 01 Mar 2019 11:41:06 -0800 (PST) Received: from ?IPv6:2003:ea:8bf1:e200:1933:14e5:bff9:e5d0? (p200300EA8BF1E200193314E5BFF9E5D0.dip0.t-ipconnect.de. [2003:ea:8bf1:e200:1933:14e5:bff9:e5d0]) by smtp.googlemail.com with ESMTPSA id c126sm15747543wma.0.2019.03.01.11.41.04 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 01 Mar 2019 11:41:05 -0800 (PST) From: Heiner Kallweit Subject: [PATCH net-next] net: dsa: mv88e6xxx: support in-band signalling on SGMII ports with external PHYs To: Vivien Didelot , Andrew Lunn , Florian Fainelli , David Miller Cc: "netdev@vger.kernel.org" , Russell King - ARM Linux Message-ID: <3e483c0c-0822-d185-1df5-3bb046ebd400@gmail.com> Date: Fri, 1 Mar 2019 20:41:00 +0100 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101 Thunderbird/60.5.1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org If an external PHY is connected via SGMII and uses in-band signalling then the auto-negotiated values aren't propagated to the port, resulting in a broken link. See discussion in [0]. This patch adds this propagation. We need to call mv88e6xxx_port_setup_mac(), therefore export it from chip.c. Successfully tested on a ZII DTU with 88E6390 switch and an Aquantia AQCS109 PHY connected via SGMII to port 9. [0] https://marc.info/?t=155130287200001&r=1&w=2 Signed-off-by: Heiner Kallweit --- I consider this rather a missing feature than a bug. Therefore net-next. --- drivers/net/dsa/mv88e6xxx/chip.c | 6 ++-- drivers/net/dsa/mv88e6xxx/chip.h | 3 ++ drivers/net/dsa/mv88e6xxx/serdes.c | 49 +++++++++++++++++++++++------- drivers/net/dsa/mv88e6xxx/serdes.h | 8 +++++ 4 files changed, 52 insertions(+), 14 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 47128cae2..d9f311791 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -549,9 +549,9 @@ int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, u16 update) return mv88e6xxx_write(chip, addr, reg, val); } -static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, - int link, int speed, int duplex, int pause, - phy_interface_t mode) +int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link, + int speed, int duplex, int pause, + phy_interface_t mode) { int err; diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 546651d8c..adcf60779 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -579,6 +579,9 @@ int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val); int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, u16 update); int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask); +int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link, + int speed, int duplex, int pause, + phy_interface_t mode); struct mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip); #endif /* _MV88E6XXX_CHIP_H */ diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c index 1bfc5ff8d..6a5de1b72 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.c +++ b/drivers/net/dsa/mv88e6xxx/serdes.c @@ -510,21 +510,48 @@ static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip, int port, int lane) { struct dsa_switch *ds = chip->ds; + int duplex = DUPLEX_UNKNOWN; + int speed = SPEED_UNKNOWN; + int link, err; u16 status; - bool up; - mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_SGMII_STATUS, &status); + err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, + MV88E6390_SGMII_PHY_STATUS, &status); + if (err) { + dev_err(chip->dev, "can't read SGMII PHY status: %d\n", err); + return; + } - /* Status must be read twice in order to give the current link - * status. Otherwise the change in link status since the last - * read of the register is returned. - */ - mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_SGMII_STATUS, &status); - up = status & MV88E6390_SGMII_STATUS_LINK; + link = status & MV88E6390_SGMII_PHY_STATUS_LINK ? + LINK_FORCED_UP : LINK_FORCED_DOWN; + + if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) { + duplex = status & MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ? + DUPLEX_FULL : DUPLEX_HALF; + + switch (status & MV88E6390_SGMII_PHY_STATUS_SPEED_MASK) { + case MV88E6390_SGMII_PHY_STATUS_SPEED_1000: + speed = SPEED_1000; + break; + case MV88E6390_SGMII_PHY_STATUS_SPEED_100: + speed = SPEED_100; + break; + case MV88E6390_SGMII_PHY_STATUS_SPEED_10: + speed = SPEED_10; + break; + default: + dev_err(chip->dev, "invalid PHY speed\n"); + return; + } + } - dsa_port_phylink_mac_change(ds, port, up); + err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex, + PAUSE_OFF, PHY_INTERFACE_MODE_NA); + if (err) + dev_err(chip->dev, "can't propagate PHY settings to MAC: %d\n", + err); + else + dsa_port_phylink_mac_change(ds, port, link == LINK_FORCED_UP); } static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip, diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h index 573dce8b1..c2e7eedfa 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.h +++ b/drivers/net/dsa/mv88e6xxx/serdes.h @@ -69,6 +69,14 @@ #define MV88E6390_SGMII_INT_SYMBOL_ERROR BIT(8) #define MV88E6390_SGMII_INT_FALSE_CARRIER BIT(7) #define MV88E6390_SGMII_INT_STATUS 0xa002 +#define MV88E6390_SGMII_PHY_STATUS 0xa003 +#define MV88E6390_SGMII_PHY_STATUS_SPEED_MASK GENMASK(15, 14) +#define MV88E6390_SGMII_PHY_STATUS_SPEED_1000 0x8000 +#define MV88E6390_SGMII_PHY_STATUS_SPEED_100 0x4000 +#define MV88E6390_SGMII_PHY_STATUS_SPEED_10 0x0000 +#define MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL BIT(13) +#define MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID BIT(11) +#define MV88E6390_SGMII_PHY_STATUS_LINK BIT(10) int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); -- 2.21.0