Skip to content

Commit 9ff2aa4

Browse files
vladimirolteananguy11
authored andcommitted
net: ethtool: mm: extract stmmac verification logic into common library
It appears that stmmac is not the only hardware which requires a software-driven verification state machine for the MAC Merge layer. While on the one hand it's good to encourage hardware implementations, on the other hand it's quite difficult to tolerate multiple drivers implementing independently fairly non-trivial logic. Extract the hardware-independent logic from stmmac into library code and put it in ethtool. Name the state structure "mmsv" for MAC Merge Software Verification. Let this expose an operations structure for executing the hardware stuff: sync hardware with the tx_active boolean (result of verification process), enable/disable the pMAC, send mPackets, notify library of external events (reception of mPackets), as well as link state changes. Note that it is assumed that the external events are received in hardirq context. If they are not, it is probably a good idea to disable hardirqs when calling ethtool_mmsv_event_handle(), because the library does not do so. Also, the MM software verification process has no business with the tx_min_frag_size, that is all the driver's to handle. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Co-developed-by: Choong Yong Liang <yong.liang.choong@linux.intel.com> Signed-off-by: Choong Yong Liang <yong.liang.choong@linux.intel.com> Tested-by: Choong Yong Liang <yong.liang.choong@linux.intel.com> Tested-by: Furong Xu <0x1207@gmail.com> Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: Faizal Rahim <faizal.abdul.rahim@linux.intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
1 parent b375984 commit 9ff2aa4

File tree

8 files changed

+392
-202
lines changed

8 files changed

+392
-202
lines changed

drivers/net/ethernet/stmicro/stmmac/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ config STMMAC_ETH
33
tristate "STMicroelectronics Multi-Gigabit Ethernet driver"
44
depends on HAS_IOMEM && HAS_DMA
55
depends on PTP_1588_CLOCK_OPTIONAL
6+
depends on ETHTOOL_NETLINK
67
select MII
78
select PCS_XPCS
89
select PAGE_POOL

drivers/net/ethernet/stmicro/stmmac/stmmac.h

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -149,21 +149,9 @@ struct stmmac_channel {
149149
};
150150

151151
struct stmmac_fpe_cfg {
152-
/* Serialize access to MAC Merge state between ethtool requests
153-
* and link state updates.
154-
*/
155-
spinlock_t lock;
156-
152+
struct ethtool_mmsv mmsv;
157153
const struct stmmac_fpe_reg *reg;
158-
u32 fpe_csr; /* MAC_FPE_CTRL_STS reg cache */
159-
160-
enum ethtool_mm_verify_status status;
161-
struct timer_list verify_timer;
162-
bool verify_enabled;
163-
int verify_retries;
164-
bool pmac_enabled;
165-
u32 verify_time;
166-
bool tx_enabled;
154+
u32 fpe_csr; /* MAC_FPE_CTRL_STS reg cache */
167155
};
168156

169157
struct stmmac_tc_entry {

drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c

Lines changed: 2 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,7 +1210,6 @@ static int stmmac_get_mm(struct net_device *ndev,
12101210
struct ethtool_mm_state *state)
12111211
{
12121212
struct stmmac_priv *priv = netdev_priv(ndev);
1213-
unsigned long flags;
12141213
u32 frag_size;
12151214

12161215
if (!stmmac_fpe_supported(priv))
@@ -1220,26 +1219,7 @@ static int stmmac_get_mm(struct net_device *ndev,
12201219
frag_size = stmmac_fpe_get_add_frag_size(priv);
12211220
state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(frag_size);
12221221

1223-
spin_lock_irqsave(&priv->fpe_cfg.lock, flags);
1224-
1225-
state->max_verify_time = STMMAC_FPE_MM_MAX_VERIFY_TIME_MS;
1226-
state->verify_enabled = priv->fpe_cfg.verify_enabled;
1227-
state->pmac_enabled = priv->fpe_cfg.pmac_enabled;
1228-
state->verify_time = priv->fpe_cfg.verify_time;
1229-
state->tx_enabled = priv->fpe_cfg.tx_enabled;
1230-
state->verify_status = priv->fpe_cfg.status;
1231-
1232-
/* FPE active if common tx_enabled and
1233-
* (verification success or disabled(forced))
1234-
*/
1235-
if (state->tx_enabled &&
1236-
(state->verify_status == ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED ||
1237-
state->verify_status == ETHTOOL_MM_VERIFY_STATUS_DISABLED))
1238-
state->tx_active = true;
1239-
else
1240-
state->tx_active = false;
1241-
1242-
spin_unlock_irqrestore(&priv->fpe_cfg.lock, flags);
1222+
ethtool_mmsv_get_mm(&priv->fpe_cfg.mmsv, state);
12431223

12441224
return 0;
12451225
}
@@ -1248,8 +1228,6 @@ static int stmmac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
12481228
struct netlink_ext_ack *extack)
12491229
{
12501230
struct stmmac_priv *priv = netdev_priv(ndev);
1251-
struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
1252-
unsigned long flags;
12531231
u32 frag_size;
12541232
int err;
12551233

@@ -1259,23 +1237,7 @@ static int stmmac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
12591237
return err;
12601238

12611239
stmmac_fpe_set_add_frag_size(priv, frag_size);
1262-
1263-
/* Wait for the verification that's currently in progress to finish */
1264-
timer_shutdown_sync(&fpe_cfg->verify_timer);
1265-
1266-
spin_lock_irqsave(&fpe_cfg->lock, flags);
1267-
1268-
fpe_cfg->verify_enabled = cfg->verify_enabled;
1269-
fpe_cfg->pmac_enabled = cfg->pmac_enabled;
1270-
fpe_cfg->verify_time = cfg->verify_time;
1271-
fpe_cfg->tx_enabled = cfg->tx_enabled;
1272-
1273-
if (!cfg->verify_enabled)
1274-
fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
1275-
1276-
stmmac_fpe_apply(priv);
1277-
1278-
spin_unlock_irqrestore(&fpe_cfg->lock, flags);
1240+
ethtool_mmsv_set_mm(&priv->fpe_cfg.mmsv, cfg);
12791241

12801242
return 0;
12811243
}

drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c

Lines changed: 36 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,6 @@
2727
#define STMMAC_MAC_FPE_CTRL_STS_SVER BIT(1)
2828
#define STMMAC_MAC_FPE_CTRL_STS_EFPE BIT(0)
2929

30-
/* FPE link-partner hand-shaking mPacket type */
31-
enum stmmac_mpacket_type {
32-
MPACKET_VERIFY = 0,
33-
MPACKET_RESPONSE = 1,
34-
};
35-
3630
struct stmmac_fpe_reg {
3731
const u32 mac_fpe_reg; /* offset of MAC_FPE_CTRL_STS */
3832
const u32 mtl_fpe_reg; /* offset of MTL_FPE_CTRL_STS */
@@ -48,10 +42,10 @@ bool stmmac_fpe_supported(struct stmmac_priv *priv)
4842
priv->hw->mac->fpe_map_preemption_class;
4943
}
5044

51-
static void stmmac_fpe_configure(struct stmmac_priv *priv, bool tx_enable,
52-
bool pmac_enable)
45+
static void stmmac_fpe_configure_tx(struct ethtool_mmsv *mmsv, bool tx_enable)
5346
{
54-
struct stmmac_fpe_cfg *cfg = &priv->fpe_cfg;
47+
struct stmmac_fpe_cfg *cfg = container_of(mmsv, struct stmmac_fpe_cfg, mmsv);
48+
struct stmmac_priv *priv = container_of(cfg, struct stmmac_priv, fpe_cfg);
5549
const struct stmmac_fpe_reg *reg = cfg->reg;
5650
u32 num_rxq = priv->plat->rx_queues_to_use;
5751
void __iomem *ioaddr = priv->ioaddr;
@@ -68,6 +62,15 @@ static void stmmac_fpe_configure(struct stmmac_priv *priv, bool tx_enable,
6862
cfg->fpe_csr = 0;
6963
}
7064
writel(cfg->fpe_csr, ioaddr + reg->mac_fpe_reg);
65+
}
66+
67+
static void stmmac_fpe_configure_pmac(struct ethtool_mmsv *mmsv, bool pmac_enable)
68+
{
69+
struct stmmac_fpe_cfg *cfg = container_of(mmsv, struct stmmac_fpe_cfg, mmsv);
70+
struct stmmac_priv *priv = container_of(cfg, struct stmmac_priv, fpe_cfg);
71+
const struct stmmac_fpe_reg *reg = cfg->reg;
72+
void __iomem *ioaddr = priv->ioaddr;
73+
u32 value;
7174

7275
value = readl(ioaddr + reg->int_en_reg);
7376

@@ -85,47 +88,45 @@ static void stmmac_fpe_configure(struct stmmac_priv *priv, bool tx_enable,
8588
writel(value, ioaddr + reg->int_en_reg);
8689
}
8790

88-
static void stmmac_fpe_send_mpacket(struct stmmac_priv *priv,
89-
enum stmmac_mpacket_type type)
91+
static void stmmac_fpe_send_mpacket(struct ethtool_mmsv *mmsv,
92+
enum ethtool_mpacket type)
9093
{
91-
const struct stmmac_fpe_reg *reg = priv->fpe_cfg.reg;
94+
struct stmmac_fpe_cfg *cfg = container_of(mmsv, struct stmmac_fpe_cfg, mmsv);
95+
struct stmmac_priv *priv = container_of(cfg, struct stmmac_priv, fpe_cfg);
96+
const struct stmmac_fpe_reg *reg = cfg->reg;
9297
void __iomem *ioaddr = priv->ioaddr;
93-
u32 value = priv->fpe_cfg.fpe_csr;
98+
u32 value = cfg->fpe_csr;
9499

95-
if (type == MPACKET_VERIFY)
100+
if (type == ETHTOOL_MPACKET_VERIFY)
96101
value |= STMMAC_MAC_FPE_CTRL_STS_SVER;
97-
else if (type == MPACKET_RESPONSE)
102+
else if (type == ETHTOOL_MPACKET_RESPONSE)
98103
value |= STMMAC_MAC_FPE_CTRL_STS_SRSP;
99104

100105
writel(value, ioaddr + reg->mac_fpe_reg);
101106
}
102107

108+
static const struct ethtool_mmsv_ops stmmac_mmsv_ops = {
109+
.configure_tx = stmmac_fpe_configure_tx,
110+
.configure_pmac = stmmac_fpe_configure_pmac,
111+
.send_mpacket = stmmac_fpe_send_mpacket,
112+
};
113+
103114
static void stmmac_fpe_event_status(struct stmmac_priv *priv, int status)
104115
{
105116
struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
117+
struct ethtool_mmsv *mmsv = &fpe_cfg->mmsv;
106118

107-
/* This is interrupt context, just spin_lock() */
108-
spin_lock(&fpe_cfg->lock);
109-
110-
if (!fpe_cfg->pmac_enabled || status == FPE_EVENT_UNKNOWN)
111-
goto unlock_out;
119+
if (status == FPE_EVENT_UNKNOWN)
120+
return;
112121

113-
/* LP has sent verify mPacket */
114122
if ((status & FPE_EVENT_RVER) == FPE_EVENT_RVER)
115-
stmmac_fpe_send_mpacket(priv, MPACKET_RESPONSE);
123+
ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LP_SENT_VERIFY_MPACKET);
116124

117-
/* Local has sent verify mPacket */
118-
if ((status & FPE_EVENT_TVER) == FPE_EVENT_TVER &&
119-
fpe_cfg->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED)
120-
fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_VERIFYING;
125+
if ((status & FPE_EVENT_TVER) == FPE_EVENT_TVER)
126+
ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LD_SENT_VERIFY_MPACKET);
121127

122-
/* LP has sent response mPacket */
123-
if ((status & FPE_EVENT_RRSP) == FPE_EVENT_RRSP &&
124-
fpe_cfg->status == ETHTOOL_MM_VERIFY_STATUS_VERIFYING)
125-
fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED;
126-
127-
unlock_out:
128-
spin_unlock(&fpe_cfg->lock);
128+
if ((status & FPE_EVENT_RRSP) == FPE_EVENT_RRSP)
129+
ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LP_SENT_RESPONSE_MPACKET);
129130
}
130131

131132
void stmmac_fpe_irq_status(struct stmmac_priv *priv)
@@ -164,119 +165,16 @@ void stmmac_fpe_irq_status(struct stmmac_priv *priv)
164165
stmmac_fpe_event_status(priv, status);
165166
}
166167

167-
/**
168-
* stmmac_fpe_verify_timer - Timer for MAC Merge verification
169-
* @t: timer_list struct containing private info
170-
*
171-
* Verify the MAC Merge capability in the local TX direction, by
172-
* transmitting Verify mPackets up to 3 times. Wait until link
173-
* partner responds with a Response mPacket, otherwise fail.
174-
*/
175-
static void stmmac_fpe_verify_timer(struct timer_list *t)
176-
{
177-
struct stmmac_fpe_cfg *fpe_cfg = from_timer(fpe_cfg, t, verify_timer);
178-
struct stmmac_priv *priv = container_of(fpe_cfg, struct stmmac_priv,
179-
fpe_cfg);
180-
unsigned long flags;
181-
bool rearm = false;
182-
183-
spin_lock_irqsave(&fpe_cfg->lock, flags);
184-
185-
switch (fpe_cfg->status) {
186-
case ETHTOOL_MM_VERIFY_STATUS_INITIAL:
187-
case ETHTOOL_MM_VERIFY_STATUS_VERIFYING:
188-
if (fpe_cfg->verify_retries != 0) {
189-
stmmac_fpe_send_mpacket(priv, MPACKET_VERIFY);
190-
rearm = true;
191-
} else {
192-
fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_FAILED;
193-
}
194-
195-
fpe_cfg->verify_retries--;
196-
break;
197-
198-
case ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED:
199-
stmmac_fpe_configure(priv, true, true);
200-
break;
201-
202-
default:
203-
break;
204-
}
205-
206-
if (rearm) {
207-
mod_timer(&fpe_cfg->verify_timer,
208-
jiffies + msecs_to_jiffies(fpe_cfg->verify_time));
209-
}
210-
211-
spin_unlock_irqrestore(&fpe_cfg->lock, flags);
212-
}
213-
214-
static void stmmac_fpe_verify_timer_arm(struct stmmac_fpe_cfg *fpe_cfg)
215-
{
216-
if (fpe_cfg->pmac_enabled && fpe_cfg->tx_enabled &&
217-
fpe_cfg->verify_enabled &&
218-
fpe_cfg->status != ETHTOOL_MM_VERIFY_STATUS_FAILED &&
219-
fpe_cfg->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED) {
220-
timer_setup(&fpe_cfg->verify_timer, stmmac_fpe_verify_timer, 0);
221-
mod_timer(&fpe_cfg->verify_timer, jiffies);
222-
}
223-
}
224-
225168
void stmmac_fpe_init(struct stmmac_priv *priv)
226169
{
227-
priv->fpe_cfg.verify_retries = STMMAC_FPE_MM_MAX_VERIFY_RETRIES;
228-
priv->fpe_cfg.verify_time = STMMAC_FPE_MM_MAX_VERIFY_TIME_MS;
229-
priv->fpe_cfg.status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
230-
timer_setup(&priv->fpe_cfg.verify_timer, stmmac_fpe_verify_timer, 0);
231-
spin_lock_init(&priv->fpe_cfg.lock);
170+
ethtool_mmsv_init(&priv->fpe_cfg.mmsv, priv->dev,
171+
&stmmac_mmsv_ops);
232172

233173
if ((!priv->fpe_cfg.reg || !priv->hw->mac->fpe_map_preemption_class) &&
234174
priv->dma_cap.fpesel)
235175
dev_info(priv->device, "FPE is not supported by driver.\n");
236176
}
237177

238-
void stmmac_fpe_apply(struct stmmac_priv *priv)
239-
{
240-
struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
241-
242-
/* If verification is disabled, configure FPE right away.
243-
* Otherwise let the timer code do it.
244-
*/
245-
if (!fpe_cfg->verify_enabled) {
246-
stmmac_fpe_configure(priv, fpe_cfg->tx_enabled,
247-
fpe_cfg->pmac_enabled);
248-
} else {
249-
fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_INITIAL;
250-
fpe_cfg->verify_retries = STMMAC_FPE_MM_MAX_VERIFY_RETRIES;
251-
252-
if (netif_running(priv->dev))
253-
stmmac_fpe_verify_timer_arm(fpe_cfg);
254-
}
255-
}
256-
257-
void stmmac_fpe_link_state_handle(struct stmmac_priv *priv, bool is_up)
258-
{
259-
struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
260-
unsigned long flags;
261-
262-
timer_shutdown_sync(&fpe_cfg->verify_timer);
263-
264-
spin_lock_irqsave(&fpe_cfg->lock, flags);
265-
266-
if (is_up && fpe_cfg->pmac_enabled) {
267-
/* VERIFY process requires pmac enabled when NIC comes up */
268-
stmmac_fpe_configure(priv, false, true);
269-
270-
/* New link => maybe new partner => new verification process */
271-
stmmac_fpe_apply(priv);
272-
} else {
273-
/* No link => turn off EFPE */
274-
stmmac_fpe_configure(priv, false, false);
275-
}
276-
277-
spin_unlock_irqrestore(&fpe_cfg->lock, flags);
278-
}
279-
280178
int stmmac_fpe_get_add_frag_size(struct stmmac_priv *priv)
281179
{
282180
const struct stmmac_fpe_reg *reg = priv->fpe_cfg.reg;

drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,10 @@
99
#include <linux/types.h>
1010
#include <linux/netdevice.h>
1111

12-
#define STMMAC_FPE_MM_MAX_VERIFY_RETRIES 3
13-
#define STMMAC_FPE_MM_MAX_VERIFY_TIME_MS 128
14-
1512
struct stmmac_priv;
1613

17-
void stmmac_fpe_link_state_handle(struct stmmac_priv *priv, bool is_up);
1814
bool stmmac_fpe_supported(struct stmmac_priv *priv);
1915
void stmmac_fpe_init(struct stmmac_priv *priv);
20-
void stmmac_fpe_apply(struct stmmac_priv *priv);
2116
void stmmac_fpe_irq_status(struct stmmac_priv *priv);
2217
int stmmac_fpe_get_add_frag_size(struct stmmac_priv *priv);
2318
void stmmac_fpe_set_add_frag_size(struct stmmac_priv *priv, u32 add_frag_size);

drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -946,7 +946,7 @@ static void stmmac_mac_link_down(struct phylink_config *config,
946946
stmmac_set_eee_pls(priv, priv->hw, false);
947947

948948
if (stmmac_fpe_supported(priv))
949-
stmmac_fpe_link_state_handle(priv, false);
949+
ethtool_mmsv_link_state_handle(&priv->fpe_cfg.mmsv, false);
950950
}
951951

952952
static void stmmac_mac_link_up(struct phylink_config *config,
@@ -1064,7 +1064,7 @@ static void stmmac_mac_link_up(struct phylink_config *config,
10641064
stmmac_set_eee_pls(priv, priv->hw, true);
10651065

10661066
if (stmmac_fpe_supported(priv))
1067-
stmmac_fpe_link_state_handle(priv, true);
1067+
ethtool_mmsv_link_state_handle(&priv->fpe_cfg.mmsv, true);
10681068

10691069
if (priv->plat->flags & STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY)
10701070
stmmac_hwtstamp_correct_latency(priv, priv);
@@ -4152,7 +4152,7 @@ static int stmmac_release(struct net_device *dev)
41524152
stmmac_release_ptp(priv);
41534153

41544154
if (stmmac_fpe_supported(priv))
4155-
timer_shutdown_sync(&priv->fpe_cfg.verify_timer);
4155+
ethtool_mmsv_stop(&priv->fpe_cfg.mmsv);
41564156

41574157
pm_runtime_put(priv->device);
41584158

@@ -7871,7 +7871,7 @@ int stmmac_suspend(struct device *dev)
78717871
rtnl_unlock();
78727872

78737873
if (stmmac_fpe_supported(priv))
7874-
timer_shutdown_sync(&priv->fpe_cfg.verify_timer);
7874+
ethtool_mmsv_stop(&priv->fpe_cfg.mmsv);
78757875

78767876
return 0;
78777877
}

0 commit comments

Comments
 (0)