From patchwork Wed Jul 11 20:31:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heiner Kallweit X-Patchwork-Id: 942700 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="FIYjSTUE"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 41QrMc6kCwz9s1R for ; Thu, 12 Jul 2018 06:31:56 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389588AbeGKUh5 (ORCPT ); Wed, 11 Jul 2018 16:37:57 -0400 Received: from mail-wm0-f65.google.com ([74.125.82.65]:54071 "EHLO mail-wm0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387593AbeGKUh4 (ORCPT ); Wed, 11 Jul 2018 16:37:56 -0400 Received: by mail-wm0-f65.google.com with SMTP id b188-v6so3574661wme.3 for ; Wed, 11 Jul 2018 13:31:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=subject:from:to:cc:references:message-id:date:user-agent :mime-version:in-reply-to:content-language:content-transfer-encoding; bh=4yFj2mkS8GJC3b7J5Cht4sOuA7Ze3NG75U/JpHSbQQY=; b=FIYjSTUE5MvfLKihEkA4v0wq7+JbLOfIzeKsa1ooj+obSgZc0yQ71PsumxhqGUXtK1 aulr2ZFU+Mw6Zp/yfmtGnLChuPLpMCT9aYkVb8BXmdpLcaTVe23cTRkbk7yZyYtL8YXl 32T0u6tS8j5r6HsH761pfVxigUxaN+/bYjtXmW9BSkWzq/itfkNB+LI6WPMlZOwGvL6u H0SqvRKTAsjU7tqpZC4e4V8otUeAstW6xQai53wMCJmhmbIFhExKU0LXeiv+96XLOCIt d5M9KlagyGctSkTqC+s1pjVU8IQVLcgh9Hft6wXcmY49/1lUiwgFYhZFUR6KzVD7vhBc tnqA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:from:to:cc:references:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=4yFj2mkS8GJC3b7J5Cht4sOuA7Ze3NG75U/JpHSbQQY=; b=oHQdlo+Lh5CwQfJxkWGAlR9+IPU7AQS5uAVVYZ7iTeTgnnrRtoZ7toSSZZQ/zG74fC Ux+SPCLwjTLYLNtg1YjAXaQ5dV9EOhgESb5pR0P6kjET+WRLd83gIuxShk7+l+8AXhH3 boU4IrJp+tv68VXK6QHUTke9wZjhVtpXo79EIHvmY9C/CRimAe3aPBZ/qgymafSGIwdT ypWUujcmv5GxdmoZYgK8w4YQkP4PZeb2HgtXvqCy/YKgxEobTcHg2bQIWcBN6T+UNjKP TqaaESICWhzwIfiB3yi94sMbxvbcrXmWcu9GeybqsIJt0tlV00ecEbcd6Og2RoxWYTwf JkVw== X-Gm-Message-State: AOUpUlENbCYFDIC1BetG7rPGmZUVbQdKe8FpM1HXbVjVnwsPvFERX/YR Ny+rGOvcqZO4pgt0T35mnCW89w== X-Google-Smtp-Source: AAOMgpfexMxwjlj5kvubwNEagI6BxfYT7L2hQU2CZ2//+C8X6xM2i6C6DxzJyFjQkKEV4CCdCxrHHQ== X-Received: by 2002:a1c:cf81:: with SMTP id f123-v6mr38034wmg.3.1531341112153; Wed, 11 Jul 2018 13:31:52 -0700 (PDT) Received: from ?IPv6:2003:ea:8bd4:d600:515e:2bda:3457:11f2? (p200300EA8BD4D600515E2BDA345711F2.dip0.t-ipconnect.de. [2003:ea:8bd4:d600:515e:2bda:3457:11f2]) by smtp.googlemail.com with ESMTPSA id q1-v6sm3673816wrw.42.2018.07.11.13.31.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 11 Jul 2018 13:31:51 -0700 (PDT) Subject: [PATCH net-next 2/2] net: phy: add phy_speed_down and phy_speed_up From: Heiner Kallweit To: Andrew Lunn , Florian Fainelli , David Miller Cc: "netdev@vger.kernel.org" References: <0d031081-4a7f-ddde-87c0-2c1c6be543c3@gmail.com> Message-ID: <407ed2cd-db27-f179-8b98-0d1e61513e07@gmail.com> Date: Wed, 11 Jul 2018 22:31:42 +0200 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.8.0 MIME-Version: 1.0 In-Reply-To: <0d031081-4a7f-ddde-87c0-2c1c6be543c3@gmail.com> Content-Language: en-US Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Some network drivers include functionality to speed down the PHY when suspending and just waiting for a WoL packet because this saves energy. This functionality is quite generic, therefore let's factor it out to phylib. Signed-off-by: Heiner Kallweit --- drivers/net/phy/phy.c | 78 +++++++++++++++++++++++++++++++++++++++++++ include/linux/phy.h | 2 ++ 2 files changed, 80 insertions(+) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index c4aa360d..0547c603 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -551,6 +551,84 @@ int phy_start_aneg(struct phy_device *phydev) } EXPORT_SYMBOL(phy_start_aneg); +static int phy_poll_aneg_done(struct phy_device *phydev) +{ + unsigned int retries = 100; + int ret; + + do { + msleep(100); + ret = phy_aneg_done(phydev); + } while (!ret && --retries); + + if (!ret) + return -ETIMEDOUT; + + return ret < 0 ? ret : 0; +} + +/** + * phy_speed_down - set speed to lowest speed supported by both link partners + * @phydev: the phy_device struct + * @sync: perform action synchronously + * + * Description: Typically used to save energy when waiting for a WoL packet + */ +int phy_speed_down(struct phy_device *phydev, bool sync) +{ + u32 adv = phydev->lp_advertising & phydev->supported; + u32 adv_old = phydev->advertising; + int ret; + + if (phydev->autoneg != AUTONEG_ENABLE) + return 0; + + if (adv & PHY_10BT_FEATURES) + phydev->advertising &= ~(PHY_100BT_FEATURES | + PHY_1000BT_FEATURES); + else if (adv & PHY_100BT_FEATURES) + phydev->advertising &= ~PHY_1000BT_FEATURES; + + if (phydev->advertising == adv_old) + return 0; + + ret = phy_config_aneg(phydev); + if (ret) + return ret; + + return sync ? phy_poll_aneg_done(phydev) : 0; +} +EXPORT_SYMBOL_GPL(phy_speed_down); + +/** + * phy_speed_up - (re)set advertised speeds to all supported speeds + * @phydev: the phy_device struct + * @sync: perform action synchronously + * + * Description: Used to revert the effect of phy_speed_down + */ +int phy_speed_up(struct phy_device *phydev, bool sync) +{ + u32 mask = PHY_10BT_FEATURES | PHY_100BT_FEATURES | PHY_1000BT_FEATURES; + u32 adv_old = phydev->advertising; + int ret; + + if (phydev->autoneg != AUTONEG_ENABLE) + return 0; + + phydev->advertising = (adv_old & ~mask) | (phydev->supported & mask); + + if (phydev->advertising == adv_old) + return 0; + + ret = phy_config_aneg(phydev); + if (ret) + return ret; + + return sync ? phy_poll_aneg_done(phydev) : 0; +} +EXPORT_SYMBOL_GPL(phy_speed_up); + /** * phy_start_machine - start PHY state machine tracking * @phydev: the phy_device struct diff --git a/include/linux/phy.h b/include/linux/phy.h index 6cd09098..275f528e 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -942,6 +942,8 @@ void phy_start(struct phy_device *phydev); void phy_stop(struct phy_device *phydev); int phy_start_aneg(struct phy_device *phydev); int phy_aneg_done(struct phy_device *phydev); +int phy_speed_down(struct phy_device *phydev, bool sync); +int phy_speed_up(struct phy_device *phydev, bool sync); int phy_stop_interrupts(struct phy_device *phydev); int phy_restart_aneg(struct phy_device *phydev);