[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20231201173545.1215940-3-tobias@waldekranz.com>
Date: Fri, 1 Dec 2023 18:35:44 +0100
From: Tobias Waldekranz <tobias@...dekranz.com>
To: davem@...emloft.net,
kuba@...nel.org
Cc: andrew@...n.ch,
gregory.clement@...tlin.com,
sebastian.hesselbarth@...il.com,
robh+dt@...nel.org,
krzysztof.kozlowski+dt@...aro.org,
conor+dt@...nel.org,
netdev@...r.kernel.org
Subject: [PATCH net-next 2/3] net: mvmdio: Avoid excessive sleeps in polled mode
Before this change, when operating in polled mode, i.e. no IRQ is
available, every individual C45 access would be hit with a 150us sleep
after the bus access.
For example, on a board with a CN9130 SoC connected to an MV88X3310
PHY, a single C45 read would take around 165us:
root@...ix:~$ mdio f212a600.mdio-mii mmd 4:1 bench 0xc003
Performed 1000 reads in 165ms
By replacing the long sleep with a tighter poll loop, we observe a 10x
increase in bus throughput:
root@...ix:~$ mdio f212a600.mdio-mii mmd 4:1 bench 0xc003
Performed 1000 reads in 15ms
Signed-off-by: Tobias Waldekranz <tobias@...dekranz.com>
---
drivers/net/ethernet/marvell/mvmdio.c | 41 +++++++++++----------------
1 file changed, 16 insertions(+), 25 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index 89f26402f8fb..1de2175269bf 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -23,6 +23,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
@@ -58,11 +59,6 @@
* - Armada 370 (Globalscale Mirabox): 41us to 43us (Polled)
*/
#define MVMDIO_SMI_TIMEOUT 1000 /* 1000us = 1ms */
-#define MVMDIO_SMI_POLL_INTERVAL_MIN 45
-#define MVMDIO_SMI_POLL_INTERVAL_MAX 55
-
-#define MVMDIO_XSMI_POLL_INTERVAL_MIN 150
-#define MVMDIO_XSMI_POLL_INTERVAL_MAX 160
struct orion_mdio_dev {
void __iomem *regs;
@@ -84,8 +80,6 @@ enum orion_mdio_bus_type {
struct orion_mdio_ops {
int (*is_done)(struct orion_mdio_dev *);
- unsigned int poll_interval_min;
- unsigned int poll_interval_max;
};
/* Wait for the SMI unit to be ready for another operation
@@ -94,23 +88,24 @@ static int orion_mdio_wait_ready(const struct orion_mdio_ops *ops,
struct mii_bus *bus)
{
struct orion_mdio_dev *dev = bus->priv;
- unsigned long timeout = usecs_to_jiffies(MVMDIO_SMI_TIMEOUT);
- unsigned long end = jiffies + timeout;
- int timedout = 0;
+ unsigned long end, timeout;
+ int done, timedout;
- while (1) {
- if (ops->is_done(dev))
+ if (dev->err_interrupt <= 0) {
+ if (!read_poll_timeout_atomic(ops->is_done, done, done, 2,
+ MVMDIO_SMI_TIMEOUT, false, dev))
return 0;
- else if (timedout)
- break;
-
- if (dev->err_interrupt <= 0) {
- usleep_range(ops->poll_interval_min,
- ops->poll_interval_max);
+ } else {
+ timeout = usecs_to_jiffies(MVMDIO_SMI_TIMEOUT);
+ end = jiffies + timeout;
+ timedout = 0;
+
+ while (1) {
+ if (ops->is_done(dev))
+ return 0;
+ else if (timedout)
+ break;
- if (time_is_before_jiffies(end))
- ++timedout;
- } else {
/* wait_event_timeout does not guarantee a delay of at
* least one whole jiffie, so timeout must be no less
* than two.
@@ -135,8 +130,6 @@ static int orion_mdio_smi_is_done(struct orion_mdio_dev *dev)
static const struct orion_mdio_ops orion_mdio_smi_ops = {
.is_done = orion_mdio_smi_is_done,
- .poll_interval_min = MVMDIO_SMI_POLL_INTERVAL_MIN,
- .poll_interval_max = MVMDIO_SMI_POLL_INTERVAL_MAX,
};
static int orion_mdio_smi_read(struct mii_bus *bus, int mii_id,
@@ -194,8 +187,6 @@ static int orion_mdio_xsmi_is_done(struct orion_mdio_dev *dev)
static const struct orion_mdio_ops orion_mdio_xsmi_ops = {
.is_done = orion_mdio_xsmi_is_done,
- .poll_interval_min = MVMDIO_XSMI_POLL_INTERVAL_MIN,
- .poll_interval_max = MVMDIO_XSMI_POLL_INTERVAL_MAX,
};
static int orion_mdio_xsmi_read_c45(struct mii_bus *bus, int mii_id,
--
2.34.1
Powered by blists - more mailing lists