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 E74CAC282C2 for ; Sun, 10 Feb 2019 19:00:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id AA73920873 for ; Sun, 10 Feb 2019 19:00:15 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="k/G7dmU9" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726363AbfBJTAO (ORCPT ); Sun, 10 Feb 2019 14:00:14 -0500 Received: from mail-wm1-f66.google.com ([209.85.128.66]:55956 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726035AbfBJTAO (ORCPT ); Sun, 10 Feb 2019 14:00:14 -0500 Received: by mail-wm1-f66.google.com with SMTP id r17so13172251wmh.5 for ; Sun, 10 Feb 2019 11:00:12 -0800 (PST) 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=uGz11fLM7Gw5+Ky4DIJT7PPCOpJti3FzIfuc21X+C64=; b=k/G7dmU9D6kgeXoKZau1viysiUAs6JRGy5qebz0pJ1Wmg50bDXDD43tIvUaNyB7f+z x2pqldli0tdpRMIPXF7Ay0sVLuAkHr2LI9gVItt/geJf28cbVeEzctzmt15pr/jtyi3b Nr3a654TxiwDKnTQMZzCriipSgzgSjSeKBf75HQ/6w+TA91czKfOwIVUyowWuHpR9l1q Hsx8AdR98QwevH9j/osfSIaEmnhFGmN9Zdu1icPvbn63LssGieYTZKq+GVWlRii+Dine 7N6Mcp5rlh+LhTRRpzLTnTgDqup3NB+uCLyVzAgUrEBMcdHD5IFPM9bWbmIOiue5X9yA SGpA== 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=uGz11fLM7Gw5+Ky4DIJT7PPCOpJti3FzIfuc21X+C64=; b=DOa2EZfIpAW0EB3WUJg8y8tuW0Efpp5Wnsjq2qMtOVCeLzp57j3SFoTbby5jXHU41J f+DTJut+CYB6M4M8GkSra0/lkhoOtaXvnXPbbZ1JsKMeoE8TFdnqwMJrvugyiqCmD9iN GjEh2EFTcFnJsvngfteugoKYRFnjK1Ywh9xn0inT4z91wcfzF1SeRZTk3WHhsmjtO+yc cY07x+0/Nd4meudeJb680xtODr4IItzVQOtdYGv/zatjRzXyT8eHZv0UlyzNZHRwrKAY lkHw7AA3kolDeI59b4MX+00Zq1G+2gV8fWARP5q7iu0kBeKayjUmB/WfqG8jQp+HNyHM jlbQ== X-Gm-Message-State: AHQUAuYCj6bcuxpPJebjP5HyJSyBu/8bP9pt1bAYmIjgK+uiskag0G9X 1cVroU2lHPaCsX9xW/TTKzND8YjC X-Google-Smtp-Source: AHgI3IYN9zlDUiGBoUVIOPCz2dlERmcRunkcp0RxEHVcQgBPOeIZ2kBOZqX7qcyVA15dC0qe1kspgQ== X-Received: by 2002:a7b:c932:: with SMTP id h18mr1105775wml.12.1549825211583; Sun, 10 Feb 2019 11:00:11 -0800 (PST) Received: from ?IPv6:2003:ea:8bf1:e200:417c:8049:705f:3547? (p200300EA8BF1E200417C8049705F3547.dip0.t-ipconnect.de. [2003:ea:8bf1:e200:417c:8049:705f:3547]) by smtp.googlemail.com with ESMTPSA id i12sm2160275wrq.21.2019.02.10.11.00.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 10 Feb 2019 11:00:10 -0800 (PST) Subject: [PATCH net-next 1/3] net: phy: add register modifying helpers returning 1 on change From: Heiner Kallweit To: Andrew Lunn , Florian Fainelli , David Miller Cc: "netdev@vger.kernel.org" References: Message-ID: Date: Sun, 10 Feb 2019 19:57:56 +0100 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101 Thunderbird/60.5.0 MIME-Version: 1.0 In-Reply-To: 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 When modifying registers there are scenarios where we need to know whether the register content actually changed. This patch adds new helpers to not break users of the current ones, phy_modify() etc. Signed-off-by: Heiner Kallweit --- drivers/net/phy/phy-core.c | 127 ++++++++++++++++++++++++++++++++++--- include/linux/phy.h | 12 +++- 2 files changed, 128 insertions(+), 11 deletions(-) diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c index 7d6aad287..cdea028d1 100644 --- a/drivers/net/phy/phy-core.c +++ b/drivers/net/phy/phy-core.c @@ -531,7 +531,7 @@ int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val) EXPORT_SYMBOL(phy_write_mmd); /** - * __phy_modify() - Convenience function for modifying a PHY register + * __phy_modify_changed() - Convenience function for modifying a PHY register * @phydev: a pointer to a &struct phy_device * @regnum: register number * @mask: bit mask of bits to clear @@ -539,16 +539,69 @@ EXPORT_SYMBOL(phy_write_mmd); * * Unlocked helper function which allows a PHY register to be modified as * new register value = (old register value & ~mask) | set + * + * Returns negative errno, 0 if there was no change, and 1 in case of change */ -int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set) +int __phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask, + u16 set) { - int ret; + int new, ret; ret = __phy_read(phydev, regnum); if (ret < 0) return ret; - ret = __phy_write(phydev, regnum, (ret & ~mask) | set); + new = (ret & ~mask) | set; + if (new == ret) + return 0; + + ret = __phy_write(phydev, regnum, new); + + return ret < 0 ? ret : 1; +} +EXPORT_SYMBOL_GPL(__phy_modify_changed); + +/** + * phy_modify_changed - Function for modifying a PHY register + * @phydev: the phy_device struct + * @regnum: register number to modify + * @mask: bit mask of bits to clear + * @set: new value of bits set in mask to write to @regnum + * + * NOTE: MUST NOT be called from interrupt context, + * because the bus read/write functions may wait for an interrupt + * to conclude the operation. + * + * Returns negative errno, 0 if there was no change, and 1 in case of change + */ +int phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask, u16 set) +{ + int ret; + + mutex_lock(&phydev->mdio.bus->mdio_lock); + ret = __phy_modify_changed(phydev, regnum, mask, set); + mutex_unlock(&phydev->mdio.bus->mdio_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(phy_modify_changed); + +/** + * __phy_modify - Convenience function for modifying a PHY register + * @phydev: the phy_device struct + * @regnum: register number to modify + * @mask: bit mask of bits to clear + * @set: new value of bits set in mask to write to @regnum + * + * NOTE: MUST NOT be called from interrupt context, + * because the bus read/write functions may wait for an interrupt + * to conclude the operation. + */ +int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set) +{ + int ret; + + ret = __phy_modify_changed(phydev, regnum, mask, set); return ret < 0 ? ret : 0; } @@ -578,7 +631,7 @@ int phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set) EXPORT_SYMBOL_GPL(phy_modify); /** - * __phy_modify_mmd - Convenience function for modifying a register on MMD + * __phy_modify_mmd_changed - Function for modifying a register on MMD * @phydev: the phy_device struct * @devad: the MMD containing register to modify * @regnum: register number to modify @@ -587,17 +640,73 @@ EXPORT_SYMBOL_GPL(phy_modify); * * Unlocked helper function which allows a MMD register to be modified as * new register value = (old register value & ~mask) | set + * + * Returns negative errno, 0 if there was no change, and 1 in case of change */ -int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum, - u16 mask, u16 set) +int __phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum, + u16 mask, u16 set) { - int ret; + int new, ret; ret = __phy_read_mmd(phydev, devad, regnum); if (ret < 0) return ret; - ret = __phy_write_mmd(phydev, devad, regnum, (ret & ~mask) | set); + new = (ret & ~mask) | set; + if (new == ret) + return 0; + + ret = __phy_write_mmd(phydev, devad, regnum, new); + + return ret < 0 ? ret : 1; +} +EXPORT_SYMBOL_GPL(__phy_modify_mmd_changed); + +/** + * phy_modify_mmd_changed - Function for modifying a register on MMD + * @phydev: the phy_device struct + * @devad: the MMD containing register to modify + * @regnum: register number to modify + * @mask: bit mask of bits to clear + * @set: new value of bits set in mask to write to @regnum + * + * NOTE: MUST NOT be called from interrupt context, + * because the bus read/write functions may wait for an interrupt + * to conclude the operation. + * + * Returns negative errno, 0 if there was no change, and 1 in case of change + */ +int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum, + u16 mask, u16 set) +{ + int ret; + + mutex_lock(&phydev->mdio.bus->mdio_lock); + ret = __phy_modify_mmd_changed(phydev, devad, regnum, mask, set); + mutex_unlock(&phydev->mdio.bus->mdio_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(phy_modify_mmd_changed); + +/** + * __phy_modify_mmd - Convenience function for modifying a register on MMD + * @phydev: the phy_device struct + * @devad: the MMD containing register to modify + * @regnum: register number to modify + * @mask: bit mask of bits to clear + * @set: new value of bits set in mask to write to @regnum + * + * NOTE: MUST NOT be called from interrupt context, + * because the bus read/write functions may wait for an interrupt + * to conclude the operation. + */ +int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum, + u16 mask, u16 set) +{ + int ret; + + ret = __phy_modify_mmd_changed(phydev, devad, regnum, mask, set); return ret < 0 ? ret : 0; } diff --git a/include/linux/phy.h b/include/linux/phy.h index d2ffae992..378da9a61 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -799,13 +799,21 @@ int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val); */ int __phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val); +int __phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask, + u16 set); +int phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask, + u16 set); int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set); int phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set); +int __phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum, + u16 mask, u16 set); +int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum, + u16 mask, u16 set); int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum, - u16 mask, u16 set); + u16 mask, u16 set); int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum, - u16 mask, u16 set); + u16 mask, u16 set); /** * __phy_set_bits - Convenience function for setting bits in a PHY register -- 2.20.1