developer | 394d5eb | 2023-04-14 16:46:45 +0800 | [diff] [blame] | 1 | From patchwork Mon Mar 23 15:05:51 2020 |
| 2 | Content-Type: text/plain; charset="utf-8" |
| 3 | MIME-Version: 1.0 |
| 4 | Content-Transfer-Encoding: 7bit |
| 5 | X-Patchwork-Submitter: Dejin Zheng <zhengdejin5@gmail.com> |
| 6 | X-Patchwork-Id: 1260097 |
| 7 | X-Patchwork-Delegate: davem@davemloft.net |
| 8 | Return-Path: <netdev-owner@vger.kernel.org> |
| 9 | X-Original-To: patchwork-incoming-netdev@ozlabs.org |
| 10 | Delivered-To: patchwork-incoming-netdev@ozlabs.org |
| 11 | Authentication-Results: ozlabs.org; spf=none (no SPF record) |
| 12 | smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; |
| 13 | helo=vger.kernel.org; |
| 14 | envelope-from=netdev-owner@vger.kernel.org; |
| 15 | receiver=<UNKNOWN>) |
| 16 | Authentication-Results: ozlabs.org; |
| 17 | dmarc=pass (p=none dis=none) header.from=gmail.com |
| 18 | Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; |
| 19 | unprotected) header.d=gmail.com header.i=@gmail.com |
| 20 | header.a=rsa-sha256 header.s=20161025 header.b=N1ACwCYl; |
| 21 | dkim-atps=neutral |
| 22 | Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) |
| 23 | by ozlabs.org (Postfix) with ESMTP id 48mHlP3Hzhz9sSs |
| 24 | for <patchwork-incoming-netdev@ozlabs.org>; |
| 25 | Tue, 24 Mar 2020 02:06:25 +1100 (AEDT) |
| 26 | Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand |
| 27 | id S1727267AbgCWPGW (ORCPT |
| 28 | <rfc822;patchwork-incoming-netdev@ozlabs.org>); |
| 29 | Mon, 23 Mar 2020 11:06:22 -0400 |
| 30 | Received: from mail-pj1-f68.google.com ([209.85.216.68]:50286 "EHLO |
| 31 | mail-pj1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org |
| 32 | with ESMTP id S1727024AbgCWPGV (ORCPT |
| 33 | <rfc822;netdev@vger.kernel.org>); Mon, 23 Mar 2020 11:06:21 -0400 |
| 34 | Received: by mail-pj1-f68.google.com with SMTP id v13so6312358pjb.0; |
| 35 | Mon, 23 Mar 2020 08:06:20 -0700 (PDT) |
| 36 | DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; |
| 37 | d=gmail.com; s=20161025; |
| 38 | h=from:to:cc:subject:date:message-id:in-reply-to:references |
| 39 | :mime-version:content-transfer-encoding; |
| 40 | bh=GmXKgcJDZee4jC3cNKHKWCJhJ0kS9L2vONq2fIA+AaY=; |
| 41 | b=N1ACwCYlon7WkTCOGFsGWeQq6lNeUjbuQa8UGIBK7O82wFqYoTVzGY8MUnU/tEjer9 |
| 42 | AtZt9996i6pDsvhpbunlFffuKPui1YOisSe6Xcn6Ur2AiFvfJr1DMpWE2PdmlLGH2bkH |
| 43 | /Oiqbikpi9dSUfgFJ7JfIyISqKyP15jsdhhl8xtA30gWb6CuhlhBuWuLV5CqTAZKGWab |
| 44 | LMFipg2GDKlx0udJoUoNAPi/hcypdWJW8DtamDxwH/OmZk2evJsfhm2MwG/1qAb95nJ0 |
| 45 | rU/60e4BhqadPHfO9cyvgdbR+xcCJkuSIqKWH6utfd9RamZDS2djU3XDWhFW2blmcVLb |
| 46 | Ue5w== |
| 47 | X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; |
| 48 | d=1e100.net; s=20161025; |
| 49 | h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to |
| 50 | :references:mime-version:content-transfer-encoding; |
| 51 | bh=GmXKgcJDZee4jC3cNKHKWCJhJ0kS9L2vONq2fIA+AaY=; |
| 52 | b=AwMmzIpdEKD6duSw3Dl9aQkzxRMmPOysumBp0nIE9FvhZJ+67auGBvMa7G80/DyF4x |
| 53 | BbrwsUrYoDLXs7fuLEjjZgxKwSCtYfWyPDdM/ezShIx9KZIfPiXhn6uH3eXP+g4feJN4 |
| 54 | IlWVwvJMDzRJOhdZVzg934FJeMs4bW7XNm07jKxjsqksHGcw5JoHsP53xNegPbIpNb8X |
| 55 | h7+AwHXYAKzVC9aGYTA8bgxSD0d+SlO7CJ4nY+lHXcBR266/rt7rDFOwCdv9TUUAMCkY |
| 56 | rXrgSb8vThpKY/wZ8rK3SyJcPdvDt6TnmdZO7LqTbbzAHjzJml7s+5vYhk3CSOvjGTHt |
| 57 | KcMA== |
| 58 | X-Gm-Message-State: ANhLgQ1lOBl50y5dc6fz/BIFJrpgXnM0GF/1DvoZm8oJbZIt2H9n38WA |
| 59 | pBi6LVse2n2Ed5tvz68N8x8= |
| 60 | X-Google-Smtp-Source: |
| 61 | ADFU+vtPoQt/0UFiy7Bq0L9uIMvQbBOJzH8+jTojBCcjj2V26XqJvxqSMSsy9g8ZZ96F/Q8I4cpXYw== |
| 62 | X-Received: by 2002:a17:902:9a09:: with SMTP id |
| 63 | v9mr21358610plp.341.1584975980336; |
| 64 | Mon, 23 Mar 2020 08:06:20 -0700 (PDT) |
| 65 | Received: from localhost (176.122.158.203.16clouds.com. [176.122.158.203]) |
| 66 | by smtp.gmail.com with ESMTPSA id |
| 67 | j19sm13485589pfe.102.2020.03.23.08.06.19 |
| 68 | (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); |
| 69 | Mon, 23 Mar 2020 08:06:19 -0700 (PDT) |
| 70 | From: Dejin Zheng <zhengdejin5@gmail.com> |
| 71 | To: andrew@lunn.ch, f.fainelli@gmail.com, hkallweit1@gmail.com, |
| 72 | linux@armlinux.org.uk, davem@davemloft.net, corbet@lwn.net, |
| 73 | tglx@linutronix.de, gregkh@linuxfoundation.org, |
| 74 | allison@lohutok.net, mchehab+samsung@kernel.org, netdev@vger.kernel.org |
| 75 | Cc: linux-kernel@vger.kernel.org, Dejin Zheng <zhengdejin5@gmail.com> |
| 76 | Subject: [PATCH net-next v7 01/10] iopoll: introduce read_poll_timeout macro |
| 77 | Date: Mon, 23 Mar 2020 23:05:51 +0800 |
| 78 | Message-Id: <20200323150600.21382-2-zhengdejin5@gmail.com> |
| 79 | X-Mailer: git-send-email 2.25.0 |
| 80 | In-Reply-To: <20200323150600.21382-1-zhengdejin5@gmail.com> |
| 81 | References: <20200323150600.21382-1-zhengdejin5@gmail.com> |
| 82 | MIME-Version: 1.0 |
| 83 | Sender: netdev-owner@vger.kernel.org |
| 84 | Precedence: bulk |
| 85 | List-ID: <netdev.vger.kernel.org> |
| 86 | X-Mailing-List: netdev@vger.kernel.org |
| 87 | |
| 88 | this macro is an extension of readx_poll_timeout macro. the accessor |
| 89 | function op just supports only one parameter in the readx_poll_timeout |
| 90 | macro, but this macro can supports multiple variable parameters for |
| 91 | it. so functions like phy_read(struct phy_device *phydev, u32 regnum) |
| 92 | and phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum) can |
| 93 | also use this poll timeout core. and also expand it can sleep some time |
| 94 | before read operation. |
| 95 | |
| 96 | Signed-off-by: Dejin Zheng <zhengdejin5@gmail.com> |
| 97 | --- |
| 98 | v6 -> v7: |
| 99 | - add a parameter sleep_before_read to support that it can sleep |
| 100 | some time before read operation in read_poll_timeout macro. |
| 101 | v5 -> v6: |
| 102 | - no changed |
| 103 | v4 -> v5: |
| 104 | - no changed |
| 105 | v3 -> v4: |
| 106 | - no changed |
| 107 | v2 -> v3: |
| 108 | - no changed |
| 109 | v1 -> v2: |
| 110 | - no changed |
| 111 | |
| 112 | include/linux/iopoll.h | 44 ++++++++++++++++++++++++++++++++++++++++++ |
| 113 | 1 file changed, 44 insertions(+) |
| 114 | |
| 115 | --- a/include/linux/iopoll.h |
| 116 | +++ b/include/linux/iopoll.h |
| 117 | @@ -14,36 +14,41 @@ |
| 118 | #include <linux/io.h> |
| 119 | |
| 120 | /** |
| 121 | - * readx_poll_timeout - Periodically poll an address until a condition is met or a timeout occurs |
| 122 | - * @op: accessor function (takes @addr as its only argument) |
| 123 | - * @addr: Address to poll |
| 124 | + * read_poll_timeout - Periodically poll an address until a condition is |
| 125 | + * met or a timeout occurs |
| 126 | + * @op: accessor function (takes @args as its arguments) |
| 127 | * @val: Variable to read the value into |
| 128 | * @cond: Break condition (usually involving @val) |
| 129 | * @sleep_us: Maximum time to sleep between reads in us (0 |
| 130 | * tight-loops). Should be less than ~20ms since usleep_range |
| 131 | * is used (see Documentation/timers/timers-howto.rst). |
| 132 | * @timeout_us: Timeout in us, 0 means never timeout |
| 133 | + * @sleep_before_read: if it is true, sleep @sleep_us before read. |
| 134 | + * @args: arguments for @op poll |
| 135 | * |
| 136 | * Returns 0 on success and -ETIMEDOUT upon a timeout. In either |
| 137 | - * case, the last read value at @addr is stored in @val. Must not |
| 138 | + * case, the last read value at @args is stored in @val. Must not |
| 139 | * be called from atomic context if sleep_us or timeout_us are used. |
| 140 | * |
| 141 | * When available, you'll probably want to use one of the specialized |
| 142 | * macros defined below rather than this macro directly. |
| 143 | */ |
| 144 | -#define readx_poll_timeout(op, addr, val, cond, sleep_us, timeout_us) \ |
| 145 | +#define read_poll_timeout(op, val, cond, sleep_us, timeout_us, \ |
| 146 | + sleep_before_read, args...) \ |
| 147 | ({ \ |
| 148 | u64 __timeout_us = (timeout_us); \ |
| 149 | unsigned long __sleep_us = (sleep_us); \ |
| 150 | ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \ |
| 151 | might_sleep_if((__sleep_us) != 0); \ |
| 152 | + if (sleep_before_read && __sleep_us) \ |
| 153 | + usleep_range((__sleep_us >> 2) + 1, __sleep_us); \ |
| 154 | for (;;) { \ |
| 155 | - (val) = op(addr); \ |
| 156 | + (val) = op(args); \ |
| 157 | if (cond) \ |
| 158 | break; \ |
| 159 | if (__timeout_us && \ |
| 160 | ktime_compare(ktime_get(), __timeout) > 0) { \ |
| 161 | - (val) = op(addr); \ |
| 162 | + (val) = op(args); \ |
| 163 | break; \ |
| 164 | } \ |
| 165 | if (__sleep_us) \ |
| 166 | @@ -53,6 +58,27 @@ |
| 167 | }) |
| 168 | |
| 169 | /** |
| 170 | + * readx_poll_timeout - Periodically poll an address until a condition is met or a timeout occurs |
| 171 | + * @op: accessor function (takes @addr as its only argument) |
| 172 | + * @addr: Address to poll |
| 173 | + * @val: Variable to read the value into |
| 174 | + * @cond: Break condition (usually involving @val) |
| 175 | + * @sleep_us: Maximum time to sleep between reads in us (0 |
| 176 | + * tight-loops). Should be less than ~20ms since usleep_range |
| 177 | + * is used (see Documentation/timers/timers-howto.rst). |
| 178 | + * @timeout_us: Timeout in us, 0 means never timeout |
| 179 | + * |
| 180 | + * Returns 0 on success and -ETIMEDOUT upon a timeout. In either |
| 181 | + * case, the last read value at @addr is stored in @val. Must not |
| 182 | + * be called from atomic context if sleep_us or timeout_us are used. |
| 183 | + * |
| 184 | + * When available, you'll probably want to use one of the specialized |
| 185 | + * macros defined below rather than this macro directly. |
| 186 | + */ |
| 187 | +#define readx_poll_timeout(op, addr, val, cond, sleep_us, timeout_us) \ |
| 188 | + read_poll_timeout(op, val, cond, sleep_us, timeout_us, false, addr) |
| 189 | + |
| 190 | +/** |
| 191 | * readx_poll_timeout_atomic - Periodically poll an address until a condition is met or a timeout occurs |
| 192 | * @op: accessor function (takes @addr as its only argument) |
| 193 | * @addr: Address to poll |
| 194 | --- a/include/linux/phy.h |
| 195 | +++ b/include/linux/phy.h |
| 196 | @@ -21,6 +21,7 @@ |
| 197 | #include <linux/timer.h> |
| 198 | #include <linux/workqueue.h> |
| 199 | #include <linux/mod_devicetable.h> |
| 200 | +#include <linux/iopoll.h> |
| 201 | |
| 202 | #include <linux/atomic.h> |
| 203 | |
| 204 | @@ -714,6 +715,19 @@ static inline int phy_read(struct phy_de |
| 205 | return mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, regnum); |
| 206 | } |
| 207 | |
| 208 | +#define phy_read_poll_timeout(phydev, regnum, val, cond, sleep_us, \ |
| 209 | + timeout_us, sleep_before_read) \ |
| 210 | +({ \ |
| 211 | + int __ret = read_poll_timeout(phy_read, val, (cond) || val < 0, \ |
| 212 | + sleep_us, timeout_us, sleep_before_read, phydev, regnum); \ |
| 213 | + if (val < 0) \ |
| 214 | + __ret = val; \ |
| 215 | + if (__ret) \ |
| 216 | + phydev_err(phydev, "%s failed: %d\n", __func__, __ret); \ |
| 217 | + __ret; \ |
| 218 | +}) |
| 219 | + |
| 220 | + |
| 221 | /** |
| 222 | * __phy_read - convenience function for reading a given PHY register |
| 223 | * @phydev: the phy_device struct |
| 224 | @@ -766,6 +780,19 @@ static inline int __phy_write(struct phy |
| 225 | */ |
| 226 | int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum); |
| 227 | |
| 228 | +#define phy_read_mmd_poll_timeout(phydev, devaddr, regnum, val, cond, \ |
| 229 | + sleep_us, timeout_us, sleep_before_read) \ |
| 230 | +({ \ |
| 231 | + int __ret = read_poll_timeout(phy_read_mmd, val, (cond) || val < 0, \ |
| 232 | + sleep_us, timeout_us, sleep_before_read, \ |
| 233 | + phydev, devaddr, regnum); \ |
| 234 | + if (val < 0) \ |
| 235 | + __ret = val; \ |
| 236 | + if (__ret) \ |
| 237 | + phydev_err(phydev, "%s failed: %d\n", __func__, __ret); \ |
| 238 | + __ret; \ |
| 239 | +}) |
| 240 | + |
| 241 | /** |
| 242 | * __phy_read_mmd - Convenience function for reading a register |
| 243 | * from an MMD on a given PHY. |
| 244 | --- a/drivers/net/phy/phy_device.c |
| 245 | +++ b/drivers/net/phy/phy_device.c |
| 246 | @@ -1056,18 +1056,12 @@ EXPORT_SYMBOL(phy_disconnect); |
| 247 | static int phy_poll_reset(struct phy_device *phydev) |
| 248 | { |
| 249 | /* Poll until the reset bit clears (50ms per retry == 0.6 sec) */ |
| 250 | - unsigned int retries = 12; |
| 251 | - int ret; |
| 252 | - |
| 253 | - do { |
| 254 | - msleep(50); |
| 255 | - ret = phy_read(phydev, MII_BMCR); |
| 256 | - if (ret < 0) |
| 257 | - return ret; |
| 258 | - } while (ret & BMCR_RESET && --retries); |
| 259 | - if (ret & BMCR_RESET) |
| 260 | - return -ETIMEDOUT; |
| 261 | + int ret, val; |
| 262 | |
| 263 | + ret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val & BMCR_RESET), |
| 264 | + 50000, 600000, true); |
| 265 | + if (ret) |
| 266 | + return ret; |
| 267 | /* Some chips (smsc911x) may still need up to another 1ms after the |
| 268 | * BMCR_RESET bit is cleared before they are usable. |
| 269 | */ |