1316f6f2fSKevin Bowling /*-
2316f6f2fSKevin Bowling * SPDX-License-Identifier: BSD-2-Clause
3316f6f2fSKevin Bowling *
4316f6f2fSKevin Bowling * Copyright (c) 2001-2024, Intel Corporation
5316f6f2fSKevin Bowling * Copyright (c) 2026 Kevin Bowling <kbowling@FreeBSD.org>
6316f6f2fSKevin Bowling *
7316f6f2fSKevin Bowling * Redistribution and use in source and binary forms, with or without
8316f6f2fSKevin Bowling * modification, are permitted provided that the following conditions
9316f6f2fSKevin Bowling * are met:
10316f6f2fSKevin Bowling * 1. Redistributions of source code must retain the above copyright
11316f6f2fSKevin Bowling * notice, this list of conditions and the following disclaimer.
12316f6f2fSKevin Bowling * 2. Redistributions in binary form must reproduce the above copyright
13316f6f2fSKevin Bowling * notice, this list of conditions and the following disclaimer in the
14316f6f2fSKevin Bowling * documentation and/or other materials provided with the distribution.
15316f6f2fSKevin Bowling *
16316f6f2fSKevin Bowling * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17316f6f2fSKevin Bowling * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18316f6f2fSKevin Bowling * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19316f6f2fSKevin Bowling * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20316f6f2fSKevin Bowling * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21316f6f2fSKevin Bowling * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22316f6f2fSKevin Bowling * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23316f6f2fSKevin Bowling * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24316f6f2fSKevin Bowling * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25316f6f2fSKevin Bowling * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26316f6f2fSKevin Bowling * SUCH DAMAGE.
27316f6f2fSKevin Bowling */
28316f6f2fSKevin Bowling
29316f6f2fSKevin Bowling #include "if_em.h"
30316f6f2fSKevin Bowling
31316f6f2fSKevin Bowling #include <sys/sbuf.h>
32316f6f2fSKevin Bowling
33a77257d6SKevin Bowling #define IGBV_82576_QUEUES 2
34a77257d6SKevin Bowling #define IGBV_I350_QUEUES 1
359332fd55SKevin Bowling #define IGBV_MAX_MAC_FILTERS 3
36a77257d6SKevin Bowling #define IGBV_QUEUE_DISABLE_BUSY_RETRIES 10
37a77257d6SKevin Bowling #define IGBV_QUEUE_DISABLE_DELAY_US 10
38a77257d6SKevin Bowling #define IGBV_QUEUE_DISABLE_PAUSE (100 * SBT_1US)
39a77257d6SKevin Bowling #define IGBV_QUEUE_DISABLE_RETRIES 20
40a77257d6SKevin Bowling #define IGBV_QUEUE_SANITIZE_ATTEMPTS 3
41fdce3830SKevin Bowling #define IGBV_VLAN_RETRY_BATCH 4
42fdce3830SKevin Bowling #define IGBV_VLAN_RETRY_WINDOW (8 * SBT_1S)
439332fd55SKevin Bowling
44a77257d6SKevin Bowling static const struct timeval igbv_queue_log_interval = { 2, 0 };
45*612f87c9SKevin Bowling static const struct timeval igbv_mbx_log_interval = { 60, 0 };
46a77257d6SKevin Bowling static const sbintime_t igbv_queue_retry_delay[] = {
47a77257d6SKevin Bowling 100 * SBT_1MS,
48a77257d6SKevin Bowling 500 * SBT_1MS,
49a77257d6SKevin Bowling };
50*612f87c9SKevin Bowling static const sbintime_t igbv_mbx_retry_delay[] = {
51*612f87c9SKevin Bowling 250 * SBT_1MS,
52*612f87c9SKevin Bowling 1 * SBT_1S,
53*612f87c9SKevin Bowling 4 * SBT_1S,
54*612f87c9SKevin Bowling 8 * SBT_1S,
55*612f87c9SKevin Bowling };
56a77257d6SKevin Bowling _Static_assert(nitems(igbv_queue_retry_delay) + 1 ==
57a77257d6SKevin Bowling IGBV_QUEUE_SANITIZE_ATTEMPTS, "missing queue retry delay");
58a77257d6SKevin Bowling
599332fd55SKevin Bowling struct igb_vf_uc_addr_list {
609332fd55SKevin Bowling struct e1000_softc *sc;
619332fd55SKevin Bowling u8 addrs[IGBV_MAX_MAC_FILTERS][ETHER_ADDR_LEN];
629332fd55SKevin Bowling };
639332fd55SKevin Bowling
64a6bb3850SKevin Bowling static bool igbv_tx_pending(struct e1000_softc *);
65fdce3830SKevin Bowling static bool igbv_vlan_retry_pending(const struct e1000_softc *);
66fdce3830SKevin Bowling static void igbv_vlan_retry_tick(struct e1000_softc *);
67fdce3830SKevin Bowling
68a77257d6SKevin Bowling static void
igbv_queue_retry_callout(void * arg)69a77257d6SKevin Bowling igbv_queue_retry_callout(void *arg)
70a77257d6SKevin Bowling {
71a77257d6SKevin Bowling struct e1000_softc *sc;
72a77257d6SKevin Bowling if_t ifp;
73a77257d6SKevin Bowling
74a77257d6SKevin Bowling sc = arg;
75a77257d6SKevin Bowling if (atomic_readandclear_32(&sc->vf_queue_retry_pending) == 0)
76a77257d6SKevin Bowling return;
77a77257d6SKevin Bowling ifp = iflib_get_ifp(sc->ctx);
78a77257d6SKevin Bowling if ((if_getflags(ifp) & IFF_UP) == 0) {
79a77257d6SKevin Bowling atomic_set_32(&sc->vf_queue_retry_new_epoch, 1);
80a77257d6SKevin Bowling return;
81a77257d6SKevin Bowling }
82*612f87c9SKevin Bowling iflib_request_reset_if_up(sc->ctx);
83a77257d6SKevin Bowling iflib_admin_intr_deferred(sc->ctx);
84a77257d6SKevin Bowling }
85a77257d6SKevin Bowling
86*612f87c9SKevin Bowling /*
87*612f87c9SKevin Bowling * A missing PF can make the posted reset handshake wait for a full mailbox
88*612f87c9SKevin Bowling * timeout. Keep that work out of stopped status paths. An administratively
89*612f87c9SKevin Bowling * up VF retries complete initialization with an exponential delay capped at
90*612f87c9SKevin Bowling * eight seconds, so it recovers without creating a tight mailbox poller.
91*612f87c9SKevin Bowling */
92*612f87c9SKevin Bowling static void
igbv_mbx_retry_callout(void * arg)93*612f87c9SKevin Bowling igbv_mbx_retry_callout(void *arg)
94*612f87c9SKevin Bowling {
95*612f87c9SKevin Bowling struct e1000_softc *sc;
96*612f87c9SKevin Bowling if_t ifp;
97*612f87c9SKevin Bowling
98*612f87c9SKevin Bowling sc = arg;
99*612f87c9SKevin Bowling if (atomic_readandclear_32(&sc->vf_mbx_retry_pending) == 0 ||
100*612f87c9SKevin Bowling atomic_load_acq_32(&sc->vf_mbx_ready) != 0 ||
101*612f87c9SKevin Bowling iflib_in_detach(sc->ctx))
102*612f87c9SKevin Bowling return;
103*612f87c9SKevin Bowling ifp = iflib_get_ifp(sc->ctx);
104*612f87c9SKevin Bowling if ((if_getflags(ifp) & IFF_UP) == 0)
105*612f87c9SKevin Bowling return;
106*612f87c9SKevin Bowling
107*612f87c9SKevin Bowling iflib_request_reset_if_up(sc->ctx);
108*612f87c9SKevin Bowling iflib_admin_intr_deferred(sc->ctx);
109*612f87c9SKevin Bowling }
110*612f87c9SKevin Bowling
111*612f87c9SKevin Bowling static const char *
igbv_reset_error_desc(s32 error)112*612f87c9SKevin Bowling igbv_reset_error_desc(s32 error)
113*612f87c9SKevin Bowling {
114*612f87c9SKevin Bowling
115*612f87c9SKevin Bowling switch (error) {
116*612f87c9SKevin Bowling case -E1000_ERR_RESET:
117*612f87c9SKevin Bowling return ("PF reset acknowledgement timed out");
118*612f87c9SKevin Bowling case -E1000_ERR_MAC_INIT:
119*612f87c9SKevin Bowling return ("PF returned an invalid VF reset response");
120*612f87c9SKevin Bowling case -E1000_ERR_MBX:
121*612f87c9SKevin Bowling return ("PF mailbox reset exchange failed");
122*612f87c9SKevin Bowling default:
123*612f87c9SKevin Bowling return ("VF reset handshake failed");
124*612f87c9SKevin Bowling }
125*612f87c9SKevin Bowling }
126*612f87c9SKevin Bowling
127*612f87c9SKevin Bowling void
igbv_log_reset_failure(struct e1000_softc * sc,s32 error,bool attaching)128*612f87c9SKevin Bowling igbv_log_reset_failure(struct e1000_softc *sc, s32 error, bool attaching)
129*612f87c9SKevin Bowling {
130*612f87c9SKevin Bowling
131*612f87c9SKevin Bowling /* Report each backoff stage, then limit the steady eight-second retry. */
132*612f87c9SKevin Bowling if (sc->vf_mbx_retry_stage == nitems(igbv_mbx_retry_delay) - 1 &&
133*612f87c9SKevin Bowling !ratecheck(&sc->vf_last_mbx_log, &igbv_mbx_log_interval))
134*612f87c9SKevin Bowling return;
135*612f87c9SKevin Bowling device_printf(sc->dev, "%s (%d)%s\n", igbv_reset_error_desc(error),
136*612f87c9SKevin Bowling error, attaching ? "; continuing attach" : "");
137*612f87c9SKevin Bowling }
138*612f87c9SKevin Bowling
139*612f87c9SKevin Bowling void
igbv_mbx_retry_detach(struct e1000_softc * sc)140*612f87c9SKevin Bowling igbv_mbx_retry_detach(struct e1000_softc *sc)
141*612f87c9SKevin Bowling {
142*612f87c9SKevin Bowling
143*612f87c9SKevin Bowling if (!sc->vf_mbx_retry_initialized)
144*612f87c9SKevin Bowling return;
145*612f87c9SKevin Bowling atomic_readandclear_32(&sc->vf_mbx_retry_pending);
146*612f87c9SKevin Bowling callout_drain(&sc->vf_mbx_retry);
147*612f87c9SKevin Bowling sc->vf_mbx_retry_initialized = false;
148*612f87c9SKevin Bowling }
149*612f87c9SKevin Bowling
150*612f87c9SKevin Bowling void
igbv_mbx_retry_prepare(struct e1000_softc * sc)151*612f87c9SKevin Bowling igbv_mbx_retry_prepare(struct e1000_softc *sc)
152*612f87c9SKevin Bowling {
153*612f87c9SKevin Bowling
154*612f87c9SKevin Bowling if (!sc->vf_mbx_retry_initialized)
155*612f87c9SKevin Bowling return;
156*612f87c9SKevin Bowling atomic_readandclear_32(&sc->vf_mbx_retry_pending);
157*612f87c9SKevin Bowling callout_drain(&sc->vf_mbx_retry);
158*612f87c9SKevin Bowling }
159*612f87c9SKevin Bowling
160*612f87c9SKevin Bowling void
igbv_mbx_retry_stop(struct e1000_softc * sc)161*612f87c9SKevin Bowling igbv_mbx_retry_stop(struct e1000_softc *sc)
162*612f87c9SKevin Bowling {
163*612f87c9SKevin Bowling if_t ifp;
164*612f87c9SKevin Bowling
165*612f87c9SKevin Bowling if (!sc->vf_mbx_retry_initialized)
166*612f87c9SKevin Bowling return;
167*612f87c9SKevin Bowling atomic_readandclear_32(&sc->vf_mbx_retry_pending);
168*612f87c9SKevin Bowling callout_drain(&sc->vf_mbx_retry);
169*612f87c9SKevin Bowling ifp = iflib_get_ifp(sc->ctx);
170*612f87c9SKevin Bowling if ((if_getflags(ifp) & IFF_UP) == 0)
171*612f87c9SKevin Bowling sc->vf_mbx_retry_stage = 0;
172*612f87c9SKevin Bowling }
173*612f87c9SKevin Bowling
174*612f87c9SKevin Bowling void
igbv_mbx_retry_failed(if_ctx_t ctx)175*612f87c9SKevin Bowling igbv_mbx_retry_failed(if_ctx_t ctx)
176*612f87c9SKevin Bowling {
177*612f87c9SKevin Bowling struct e1000_softc *sc;
178*612f87c9SKevin Bowling if_t ifp;
179*612f87c9SKevin Bowling sbintime_t delay;
180*612f87c9SKevin Bowling u_int stage;
181*612f87c9SKevin Bowling
182*612f87c9SKevin Bowling sc = iflib_get_softc(ctx);
183*612f87c9SKevin Bowling atomic_store_rel_32(&sc->vf_mbx_ready, 0);
184*612f87c9SKevin Bowling sc->link_speed = 0;
185*612f87c9SKevin Bowling sc->link_duplex = 0;
186*612f87c9SKevin Bowling if (sc->link_state != EM_LINK_STATE_DOWN) {
187*612f87c9SKevin Bowling sc->link_state = EM_LINK_STATE_DOWN;
188*612f87c9SKevin Bowling iflib_link_state_change(ctx, LINK_STATE_DOWN, 0);
189*612f87c9SKevin Bowling }
190*612f87c9SKevin Bowling iflib_init_failed(ctx);
191*612f87c9SKevin Bowling
192*612f87c9SKevin Bowling ifp = iflib_get_ifp(ctx);
193*612f87c9SKevin Bowling if (!sc->vf_mbx_retry_initialized ||
194*612f87c9SKevin Bowling (if_getflags(ifp) & IFF_UP) == 0)
195*612f87c9SKevin Bowling return;
196*612f87c9SKevin Bowling stage = sc->vf_mbx_retry_stage;
197*612f87c9SKevin Bowling if (stage >= nitems(igbv_mbx_retry_delay))
198*612f87c9SKevin Bowling stage = nitems(igbv_mbx_retry_delay) - 1;
199*612f87c9SKevin Bowling delay = igbv_mbx_retry_delay[stage];
200*612f87c9SKevin Bowling if (sc->vf_mbx_retry_stage + 1 < nitems(igbv_mbx_retry_delay))
201*612f87c9SKevin Bowling sc->vf_mbx_retry_stage++;
202*612f87c9SKevin Bowling atomic_set_32(&sc->vf_mbx_retry_pending, 1);
203*612f87c9SKevin Bowling callout_reset_sbt(&sc->vf_mbx_retry, delay, 0,
204*612f87c9SKevin Bowling igbv_mbx_retry_callout, sc, C_PREL(1));
205*612f87c9SKevin Bowling }
206*612f87c9SKevin Bowling
207*612f87c9SKevin Bowling static void
igbv_mbx_retry_succeeded(struct e1000_softc * sc)208*612f87c9SKevin Bowling igbv_mbx_retry_succeeded(struct e1000_softc *sc)
209*612f87c9SKevin Bowling {
210*612f87c9SKevin Bowling
211*612f87c9SKevin Bowling atomic_store_rel_32(&sc->vf_mbx_ready, 1);
212*612f87c9SKevin Bowling atomic_readandclear_32(&sc->vf_mbx_retry_pending);
213*612f87c9SKevin Bowling if (sc->vf_mbx_retry_initialized)
214*612f87c9SKevin Bowling callout_stop(&sc->vf_mbx_retry);
215*612f87c9SKevin Bowling sc->vf_mbx_retry_stage = 0;
216*612f87c9SKevin Bowling sc->vf_last_mbx_log.tv_sec = 0;
217*612f87c9SKevin Bowling sc->vf_last_mbx_log.tv_usec = 0;
218*612f87c9SKevin Bowling }
219*612f87c9SKevin Bowling
220a77257d6SKevin Bowling void
igbv_queue_retry_detach(struct e1000_softc * sc)221a77257d6SKevin Bowling igbv_queue_retry_detach(struct e1000_softc *sc)
222a77257d6SKevin Bowling {
223a77257d6SKevin Bowling
224a77257d6SKevin Bowling if (!sc->vf_queue_retry_initialized)
225a77257d6SKevin Bowling return;
226a77257d6SKevin Bowling atomic_readandclear_32(&sc->vf_queue_retry_pending);
227a77257d6SKevin Bowling callout_drain(&sc->vf_queue_retry);
228a77257d6SKevin Bowling sc->vf_queue_retry_initialized = false;
229a77257d6SKevin Bowling }
230a77257d6SKevin Bowling
231a77257d6SKevin Bowling void
igbv_queue_retry_stop(struct e1000_softc * sc)232a77257d6SKevin Bowling igbv_queue_retry_stop(struct e1000_softc *sc)
233a77257d6SKevin Bowling {
234a77257d6SKevin Bowling
235a77257d6SKevin Bowling if (!sc->vf_queue_retry_initialized)
236a77257d6SKevin Bowling return;
237a77257d6SKevin Bowling if (atomic_readandclear_32(&sc->vf_queue_retry_pending) != 0)
238a77257d6SKevin Bowling atomic_set_32(&sc->vf_queue_retry_new_epoch, 1);
239a77257d6SKevin Bowling callout_stop(&sc->vf_queue_retry);
240a77257d6SKevin Bowling }
241a77257d6SKevin Bowling
242a77257d6SKevin Bowling void
igbv_queue_retry_prepare(struct e1000_softc * sc)243a77257d6SKevin Bowling igbv_queue_retry_prepare(struct e1000_softc *sc)
244a77257d6SKevin Bowling {
245a77257d6SKevin Bowling bool new_epoch;
246a77257d6SKevin Bowling
247a77257d6SKevin Bowling new_epoch =
248a77257d6SKevin Bowling atomic_readandclear_32(&sc->vf_queue_retry_new_epoch) != 0;
249a77257d6SKevin Bowling if (!sc->vf_queue_gave_up && !new_epoch)
250a77257d6SKevin Bowling return;
251a77257d6SKevin Bowling sc->vf_queue_failures = 0;
252a77257d6SKevin Bowling sc->vf_queue_gave_up = false;
253a77257d6SKevin Bowling }
254a77257d6SKevin Bowling
255a77257d6SKevin Bowling static void
igbv_queue_retry_succeeded(struct e1000_softc * sc)256a77257d6SKevin Bowling igbv_queue_retry_succeeded(struct e1000_softc *sc)
257a77257d6SKevin Bowling {
258a77257d6SKevin Bowling
259a77257d6SKevin Bowling atomic_readandclear_32(&sc->vf_queue_retry_pending);
260a77257d6SKevin Bowling atomic_readandclear_32(&sc->vf_queue_retry_new_epoch);
261a77257d6SKevin Bowling if (sc->vf_queue_retry_initialized)
262a77257d6SKevin Bowling callout_stop(&sc->vf_queue_retry);
263a77257d6SKevin Bowling sc->vf_queue_failures = 0;
264a77257d6SKevin Bowling sc->vf_queue_gave_up = false;
265a77257d6SKevin Bowling }
266a77257d6SKevin Bowling
267a77257d6SKevin Bowling void
igbv_queue_retry_failed(if_ctx_t ctx)268a77257d6SKevin Bowling igbv_queue_retry_failed(if_ctx_t ctx)
269a77257d6SKevin Bowling {
270a77257d6SKevin Bowling struct e1000_softc *sc;
271a77257d6SKevin Bowling sbintime_t delay;
272a77257d6SKevin Bowling
273a77257d6SKevin Bowling sc = iflib_get_softc(ctx);
274a77257d6SKevin Bowling KASSERT(sc->vf_ifp, ("%s called for a PF", __func__));
275a77257d6SKevin Bowling
276a77257d6SKevin Bowling if (sc->vf_queue_failures < IGBV_QUEUE_SANITIZE_ATTEMPTS)
277a77257d6SKevin Bowling sc->vf_queue_failures++;
278a77257d6SKevin Bowling if (sc->vf_queue_failures < IGBV_QUEUE_SANITIZE_ATTEMPTS) {
279a77257d6SKevin Bowling delay = igbv_queue_retry_delay[sc->vf_queue_failures - 1];
280a77257d6SKevin Bowling atomic_set_32(&sc->vf_queue_retry_pending, 1);
281a77257d6SKevin Bowling callout_reset_sbt(&sc->vf_queue_retry, delay, 0,
282a77257d6SKevin Bowling igbv_queue_retry_callout, sc, C_PREL(1));
283a77257d6SKevin Bowling } else if (!sc->vf_queue_gave_up) {
284a77257d6SKevin Bowling atomic_readandclear_32(&sc->vf_queue_retry_pending);
285a77257d6SKevin Bowling callout_stop(&sc->vf_queue_retry);
286a77257d6SKevin Bowling sc->vf_queue_gave_up = true;
287a77257d6SKevin Bowling device_printf(sc->dev,
288a77257d6SKevin Bowling "retained VF queues remained active after %u attempts; "
289a77257d6SKevin Bowling "interface left down; toggle it down/up to retry\n",
290a77257d6SKevin Bowling sc->vf_queue_failures);
291a77257d6SKevin Bowling }
292a77257d6SKevin Bowling
293a77257d6SKevin Bowling iflib_link_state_change(ctx, LINK_STATE_DOWN, 0);
294*612f87c9SKevin Bowling iflib_init_failed(ctx);
295a77257d6SKevin Bowling }
296a77257d6SKevin Bowling
297fdce3830SKevin Bowling void
igbv_vlan_retry_add(struct e1000_softc * sc,u16 vid)298fdce3830SKevin Bowling igbv_vlan_retry_add(struct e1000_softc *sc, u16 vid)
299fdce3830SKevin Bowling {
300fdce3830SKevin Bowling bool pending;
301fdce3830SKevin Bowling
302fdce3830SKevin Bowling KASSERT(sc->vf_ifp, ("%s called for a PF", __func__));
303fdce3830SKevin Bowling pending = igbv_vlan_retry_pending(sc);
304fdce3830SKevin Bowling sc->vf_vfta_retry[vid >> 5] |= 1U << (vid & 0x1f);
305fdce3830SKevin Bowling /* Bound the whole batch from its first failure, not each new VID. */
306fdce3830SKevin Bowling if (!pending)
307fdce3830SKevin Bowling sc->vf_vlan_retry_deadline =
308fdce3830SKevin Bowling getsbinuptime() + IGBV_VLAN_RETRY_WINDOW;
309fdce3830SKevin Bowling }
310fdce3830SKevin Bowling
311fdce3830SKevin Bowling void
igbv_vlan_retry_clear(struct e1000_softc * sc,u16 vid)312fdce3830SKevin Bowling igbv_vlan_retry_clear(struct e1000_softc *sc, u16 vid)
313fdce3830SKevin Bowling {
314fdce3830SKevin Bowling
315fdce3830SKevin Bowling KASSERT(sc->vf_ifp, ("%s called for a PF", __func__));
316fdce3830SKevin Bowling sc->vf_vfta_retry[vid >> 5] &= ~(1U << (vid & 0x1f));
317fdce3830SKevin Bowling }
318fdce3830SKevin Bowling
319fdce3830SKevin Bowling static bool
igbv_vlan_retry_pending(const struct e1000_softc * sc)320fdce3830SKevin Bowling igbv_vlan_retry_pending(const struct e1000_softc *sc)
321fdce3830SKevin Bowling {
322fdce3830SKevin Bowling int i;
323fdce3830SKevin Bowling
324fdce3830SKevin Bowling for (i = 0; i < EM_VFTA_SIZE; i++)
325fdce3830SKevin Bowling if (sc->vf_vfta_retry[i] != 0)
326fdce3830SKevin Bowling return (true);
327fdce3830SKevin Bowling return (false);
328fdce3830SKevin Bowling }
329fdce3830SKevin Bowling
330fdce3830SKevin Bowling static void
igbv_vlan_retry_tick(struct e1000_softc * sc)331fdce3830SKevin Bowling igbv_vlan_retry_tick(struct e1000_softc *sc)
332fdce3830SKevin Bowling {
333fdce3830SKevin Bowling u32 bit;
334fdce3830SKevin Bowling u16 vid;
335fdce3830SKevin Bowling int attempts, i, remaining;
336fdce3830SKevin Bowling
337fdce3830SKevin Bowling if (!igbv_vlan_retry_pending(sc)) {
338fdce3830SKevin Bowling sc->vf_vlan_retry_deadline = 0;
339fdce3830SKevin Bowling return;
340fdce3830SKevin Bowling }
341fdce3830SKevin Bowling if (getsbinuptime() >= sc->vf_vlan_retry_deadline) {
342fdce3830SKevin Bowling remaining = 0;
343fdce3830SKevin Bowling for (i = 0; i < EM_VFTA_SIZE; i++)
344fdce3830SKevin Bowling remaining += bitcount32(sc->vf_vfta_retry[i]);
345fdce3830SKevin Bowling memset(sc->vf_vfta_retry, 0, sizeof(sc->vf_vfta_retry));
346fdce3830SKevin Bowling sc->vf_vlan_retry_deadline = 0;
347fdce3830SKevin Bowling device_printf(sc->dev,
348fdce3830SKevin Bowling "VF VLAN restore retries exhausted for %d VIDs\n",
349fdce3830SKevin Bowling remaining);
350fdce3830SKevin Bowling return;
351fdce3830SKevin Bowling }
352fdce3830SKevin Bowling
353fdce3830SKevin Bowling /*
354fdce3830SKevin Bowling * The mailbox NACK does not distinguish a transient PF rate limit
355fdce3830SKevin Bowling * from permanent VLVF exhaustion. Retry at the PF's sustained
356fdce3830SKevin Bowling * allowance, but bound the entire recovery window so ENOSPC cannot
357fdce3830SKevin Bowling * create a permanent mailbox poller.
358fdce3830SKevin Bowling */
359fdce3830SKevin Bowling for (attempts = 0, i = 0;
360fdce3830SKevin Bowling attempts < IGBV_VLAN_RETRY_BATCH && i < 4096; i++) {
361fdce3830SKevin Bowling vid = sc->vf_vlan_retry_cursor;
362fdce3830SKevin Bowling sc->vf_vlan_retry_cursor = (vid + 1) & 0xfff;
363fdce3830SKevin Bowling bit = 1U << (vid & 0x1f);
364fdce3830SKevin Bowling if ((sc->vf_vfta_retry[vid >> 5] & bit) == 0)
365fdce3830SKevin Bowling continue;
366fdce3830SKevin Bowling attempts++;
367fdce3830SKevin Bowling if ((sc->shadow_vfta[vid >> 5] & bit) == 0 ||
368fdce3830SKevin Bowling e1000_vfta_set_vf(&sc->hw, vid, true) ==
369fdce3830SKevin Bowling E1000_SUCCESS)
370fdce3830SKevin Bowling sc->vf_vfta_retry[vid >> 5] &= ~bit;
371fdce3830SKevin Bowling }
372fdce3830SKevin Bowling if (!igbv_vlan_retry_pending(sc))
373fdce3830SKevin Bowling sc->vf_vlan_retry_deadline = 0;
374fdce3830SKevin Bowling }
375a6bb3850SKevin Bowling
376316f6f2fSKevin Bowling int
igbv_if_attach_pre(if_ctx_t ctx)377316f6f2fSKevin Bowling igbv_if_attach_pre(if_ctx_t ctx)
378316f6f2fSKevin Bowling {
379a77257d6SKevin Bowling struct e1000_softc *sc;
380316f6f2fSKevin Bowling device_t dev;
381316f6f2fSKevin Bowling int error;
382316f6f2fSKevin Bowling
383316f6f2fSKevin Bowling dev = iflib_get_dev(ctx);
384316f6f2fSKevin Bowling if (pci_msix_count(dev) < 2) {
385316f6f2fSKevin Bowling device_printf(dev, "VF operation requires two MSI-X vectors\n");
386316f6f2fSKevin Bowling return (ENXIO);
387316f6f2fSKevin Bowling }
388316f6f2fSKevin Bowling error = em_if_attach_pre(ctx);
389316f6f2fSKevin Bowling if (error != 0)
390316f6f2fSKevin Bowling return (error);
391316f6f2fSKevin Bowling
392a77257d6SKevin Bowling sc = iflib_get_softc(ctx);
393a77257d6SKevin Bowling callout_init(&sc->vf_queue_retry, 1);
394a77257d6SKevin Bowling sc->vf_queue_retry_initialized = true;
395*612f87c9SKevin Bowling callout_init(&sc->vf_mbx_retry, 1);
396*612f87c9SKevin Bowling sc->vf_mbx_retry_initialized = true;
397a77257d6SKevin Bowling
398a77257d6SKevin Bowling KASSERT(sc->vf_ifp &&
399316f6f2fSKevin Bowling (iflib_get_sctx(ctx)->isc_flags & IFLIB_IS_VF) != 0,
400316f6f2fSKevin Bowling ("%s: igbv attached without VF policy", __func__));
401316f6f2fSKevin Bowling return (0);
402316f6f2fSKevin Bowling }
403316f6f2fSKevin Bowling
404316f6f2fSKevin Bowling int
igbv_if_attach_post(if_ctx_t ctx)405316f6f2fSKevin Bowling igbv_if_attach_post(if_ctx_t ctx)
406316f6f2fSKevin Bowling {
407316f6f2fSKevin Bowling struct e1000_softc *sc;
408316f6f2fSKevin Bowling int error;
409316f6f2fSKevin Bowling
410316f6f2fSKevin Bowling sc = iflib_get_softc(ctx);
411316f6f2fSKevin Bowling KASSERT(sc->vf_ifp, ("%s called for a PF", __func__));
412316f6f2fSKevin Bowling if (sc->intr_type != IFLIB_INTR_MSIX) {
413316f6f2fSKevin Bowling device_printf(sc->dev, "VF operation requires MSI-X\n");
414316f6f2fSKevin Bowling return (ENXIO);
415316f6f2fSKevin Bowling }
416316f6f2fSKevin Bowling error = em_if_attach_post(ctx);
417316f6f2fSKevin Bowling if (error != 0)
418316f6f2fSKevin Bowling return (error);
419316f6f2fSKevin Bowling
420316f6f2fSKevin Bowling /*
421316f6f2fSKevin Bowling * Attach failures can leave the device sysctl tree registered when
422316f6f2fSKevin Bowling * hw.bus.disable_failed_devices is set. Do not publish handlers with
423316f6f2fSKevin Bowling * softc arguments until iflib has successfully allocated MSI-X.
424316f6f2fSKevin Bowling */
425316f6f2fSKevin Bowling em_add_device_sysctls(sc);
426316f6f2fSKevin Bowling return (0);
427316f6f2fSKevin Bowling }
428316f6f2fSKevin Bowling
429a6bb3850SKevin Bowling int
igbv_if_media_change(if_ctx_t ctx __unused)430a6bb3850SKevin Bowling igbv_if_media_change(if_ctx_t ctx __unused)
431a6bb3850SKevin Bowling {
432a6bb3850SKevin Bowling
433a6bb3850SKevin Bowling return (EOPNOTSUPP);
434a6bb3850SKevin Bowling }
435a6bb3850SKevin Bowling
436a6bb3850SKevin Bowling void
igbv_if_update_admin_status(if_ctx_t ctx)437a6bb3850SKevin Bowling igbv_if_update_admin_status(if_ctx_t ctx)
438a6bb3850SKevin Bowling {
439a6bb3850SKevin Bowling struct e1000_softc *sc;
440a6bb3850SKevin Bowling struct e1000_hw *hw;
441a6bb3850SKevin Bowling device_t dev;
442fdce3830SKevin Bowling bool link_check, timer_tick;
443a6bb3850SKevin Bowling
444a6bb3850SKevin Bowling sc = iflib_get_softc(ctx);
445a6bb3850SKevin Bowling hw = &sc->hw;
446a6bb3850SKevin Bowling dev = iflib_get_dev(ctx);
447a6bb3850SKevin Bowling KASSERT(sc->vf_ifp, ("%s called for a PF", __func__));
448a6bb3850SKevin Bowling
449*612f87c9SKevin Bowling if ((if_getdrvflags(iflib_get_ifp(ctx)) & IFF_DRV_RUNNING) == 0 ||
450*612f87c9SKevin Bowling !sc->vf_queues_sanitized ||
451*612f87c9SKevin Bowling atomic_load_acq_32(&sc->vf_mbx_ready) == 0) {
452*612f87c9SKevin Bowling if (sc->link_state != EM_LINK_STATE_DOWN) {
453*612f87c9SKevin Bowling sc->link_speed = 0;
454*612f87c9SKevin Bowling sc->link_duplex = 0;
455*612f87c9SKevin Bowling sc->link_state = EM_LINK_STATE_DOWN;
456*612f87c9SKevin Bowling iflib_link_state_change(ctx, LINK_STATE_DOWN, 0);
457*612f87c9SKevin Bowling }
458a77257d6SKevin Bowling return;
459a77257d6SKevin Bowling }
460a77257d6SKevin Bowling
461a6bb3850SKevin Bowling if (!sc->vf_reset_pending &&
462a6bb3850SKevin Bowling atomic_readandclear_32(&sc->promisc_pending) != 0)
463a6bb3850SKevin Bowling (void)em_if_set_promisc_impl(ctx,
464a6bb3850SKevin Bowling if_getflags(iflib_get_ifp(ctx)));
465a6bb3850SKevin Bowling
466a6bb3850SKevin Bowling if (e1000_check_for_link(hw) != E1000_SUCCESS &&
467a6bb3850SKevin Bowling !sc->vf_reset_pending) {
468a6bb3850SKevin Bowling sc->vf_reset_pending = true;
469a6bb3850SKevin Bowling iflib_request_reset(ctx);
470a6bb3850SKevin Bowling iflib_admin_intr_deferred(ctx);
471a6bb3850SKevin Bowling }
472a6bb3850SKevin Bowling link_check = !hw->mac.get_link_status;
473a6bb3850SKevin Bowling
474a6bb3850SKevin Bowling if (link_check &&
475a6bb3850SKevin Bowling (sc->link_state == EM_LINK_STATE_DOWN ||
476a6bb3850SKevin Bowling sc->link_state == EM_LINK_STATE_DOWN_RESET_PENDING)) {
477a6bb3850SKevin Bowling e1000_get_speed_and_duplex(hw, &sc->link_speed,
478a6bb3850SKevin Bowling &sc->link_duplex);
479a6bb3850SKevin Bowling if (bootverbose)
480a6bb3850SKevin Bowling device_printf(dev, "Link is up %d Mbps %s\n",
481a6bb3850SKevin Bowling sc->link_speed,
482a6bb3850SKevin Bowling sc->link_duplex == FULL_DUPLEX ?
483a6bb3850SKevin Bowling "Full Duplex" : "Half Duplex");
484a6bb3850SKevin Bowling sc->link_state = EM_LINK_STATE_UP;
485a6bb3850SKevin Bowling iflib_link_state_change(ctx, LINK_STATE_UP,
486a6bb3850SKevin Bowling IF_Mbps(sc->link_speed));
487a6bb3850SKevin Bowling } else if (!link_check &&
488a6bb3850SKevin Bowling (sc->link_state == EM_LINK_STATE_UP ||
489a6bb3850SKevin Bowling sc->link_state == EM_LINK_STATE_UP_RESET_PENDING)) {
490a6bb3850SKevin Bowling sc->link_speed = 0;
491a6bb3850SKevin Bowling sc->link_duplex = 0;
492a6bb3850SKevin Bowling sc->link_state = EM_LINK_STATE_DOWN;
493a6bb3850SKevin Bowling iflib_link_state_change(ctx, LINK_STATE_DOWN, 0);
494a6bb3850SKevin Bowling }
495a6bb3850SKevin Bowling
496a6bb3850SKevin Bowling /*
497a6bb3850SKevin Bowling * A VF stops transmit DMA when its PF reports link down. Reset if
498a6bb3850SKevin Bowling * descriptors remain queued so they cannot be sent stale when carrier
499a6bb3850SKevin Bowling * returns, matching the periodic check in Linux igbvf.
500a6bb3850SKevin Bowling */
501a6bb3850SKevin Bowling if (!link_check && !sc->vf_reset_pending && igbv_tx_pending(sc)) {
502a6bb3850SKevin Bowling sc->vf_reset_pending = true;
503a6bb3850SKevin Bowling iflib_request_reset(ctx);
504a6bb3850SKevin Bowling iflib_admin_intr_deferred(ctx);
505a6bb3850SKevin Bowling }
506a6bb3850SKevin Bowling /* em_if_init() establishes a new counter baseline after the reset. */
507fdce3830SKevin Bowling timer_tick = !sc->vf_reset_pending &&
508fdce3830SKevin Bowling atomic_readandclear_32(&sc->stats_pending) != 0;
509fdce3830SKevin Bowling if (timer_tick) {
510a6bb3850SKevin Bowling em_update_stats_counters(sc);
51175538a0fSKevin Bowling /* iflib clears RUNNING before stop; do not replay after reset. */
51275538a0fSKevin Bowling if ((if_getdrvflags(iflib_get_ifp(ctx)) &
51375538a0fSKevin Bowling IFF_DRV_RUNNING) != 0)
514fdce3830SKevin Bowling igbv_vlan_retry_tick(sc);
515fdce3830SKevin Bowling }
516a6bb3850SKevin Bowling }
517a6bb3850SKevin Bowling
518a6bb3850SKevin Bowling static bool
igbv_tx_pending(struct e1000_softc * sc)519a6bb3850SKevin Bowling igbv_tx_pending(struct e1000_softc *sc)
520a6bb3850SKevin Bowling {
521a6bb3850SKevin Bowling struct tx_ring *txr;
522a6bb3850SKevin Bowling u32 head, tail;
523a6bb3850SKevin Bowling
524a6bb3850SKevin Bowling for (int i = 0; i < sc->tx_num_queues; i++) {
525a6bb3850SKevin Bowling txr = &sc->tx_queues[i].txr;
526a6bb3850SKevin Bowling head = E1000_READ_REG(&sc->hw, E1000_TDH(txr->me));
527a6bb3850SKevin Bowling tail = E1000_READ_REG(&sc->hw, E1000_TDT(txr->me));
528a6bb3850SKevin Bowling if (head != tail)
529a6bb3850SKevin Bowling return (true);
530a6bb3850SKevin Bowling }
531a6bb3850SKevin Bowling return (false);
532a6bb3850SKevin Bowling }
533a6bb3850SKevin Bowling
534a77257d6SKevin Bowling static bool
igbv_sanitize_queues(struct e1000_softc * sc)535a77257d6SKevin Bowling igbv_sanitize_queues(struct e1000_softc *sc)
536a77257d6SKevin Bowling {
537a77257d6SKevin Bowling struct e1000_hw *hw;
538a77257d6SKevin Bowling u32 rxdctl, txdctl;
539a77257d6SKevin Bowling int i, nqueues, retry;
540a77257d6SKevin Bowling
541a77257d6SKevin Bowling hw = &sc->hw;
542a77257d6SKevin Bowling switch (hw->mac.type) {
543a77257d6SKevin Bowling case e1000_vfadapt:
544a77257d6SKevin Bowling nqueues = IGBV_82576_QUEUES;
545a77257d6SKevin Bowling break;
546a77257d6SKevin Bowling case e1000_vfadapt_i350:
547a77257d6SKevin Bowling nqueues = IGBV_I350_QUEUES;
548a77257d6SKevin Bowling break;
549a77257d6SKevin Bowling default:
550a77257d6SKevin Bowling return (true);
551a77257d6SKevin Bowling }
552a77257d6SKevin Bowling
553a77257d6SKevin Bowling /*
554a77257d6SKevin Bowling * The 82576 and I350 specification updates, Software Clarification 3,
555a77257d6SKevin Bowling * note that VFLR leaves this queue configuration intact. Clear it
556a77257d6SKevin Bowling * before programming the new rings so igbv does not depend on its PF
557a77257d6SKevin Bowling * to sanitize state left by a previous VF owner. igbv uses only queue
558a77257d6SKevin Bowling * zero, but must also clear the unused second 82576 queue.
559a77257d6SKevin Bowling *
560a77257d6SKevin Bowling * Disable every queue first and wait for outstanding DMA activity to
561a77257d6SKevin Bowling * stop before programming TDWBAL/H. Spin only for the normal fast
562a77257d6SKevin Bowling * transition, then sleep until the bounded deadline.
563a77257d6SKevin Bowling */
564a77257d6SKevin Bowling for (i = 0; i < nqueues; i++) {
565a77257d6SKevin Bowling E1000_WRITE_REG(hw, E1000_RXDCTL(i), 0);
566a77257d6SKevin Bowling E1000_WRITE_REG(hw, E1000_TXDCTL(i), 0);
567a77257d6SKevin Bowling }
568a77257d6SKevin Bowling E1000_WRITE_FLUSH(hw);
569a77257d6SKevin Bowling for (retry = 0; retry < IGBV_QUEUE_DISABLE_RETRIES; retry++) {
570a77257d6SKevin Bowling for (i = 0; i < nqueues; i++) {
571a77257d6SKevin Bowling rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(i));
572a77257d6SKevin Bowling txdctl = E1000_READ_REG(hw, E1000_TXDCTL(i));
573a77257d6SKevin Bowling if ((rxdctl & E1000_RXDCTL_QUEUE_ENABLE) != 0 ||
574a77257d6SKevin Bowling (txdctl & E1000_TXDCTL_QUEUE_ENABLE) != 0)
575a77257d6SKevin Bowling break;
576a77257d6SKevin Bowling }
577a77257d6SKevin Bowling if (i == nqueues)
578a77257d6SKevin Bowling break;
579a77257d6SKevin Bowling if (retry + 1 < IGBV_QUEUE_DISABLE_RETRIES) {
580a77257d6SKevin Bowling if (retry < IGBV_QUEUE_DISABLE_BUSY_RETRIES)
581a77257d6SKevin Bowling DELAY(IGBV_QUEUE_DISABLE_DELAY_US);
582a77257d6SKevin Bowling else
583a77257d6SKevin Bowling pause_sbt("igbvqds",
584a77257d6SKevin Bowling IGBV_QUEUE_DISABLE_PAUSE, 0,
585a77257d6SKevin Bowling C_PREL(1));
586a77257d6SKevin Bowling }
587a77257d6SKevin Bowling }
588a77257d6SKevin Bowling if (retry == IGBV_QUEUE_DISABLE_RETRIES) {
589a77257d6SKevin Bowling if (ratecheck(&sc->vf_last_queue_log,
590a77257d6SKevin Bowling &igbv_queue_log_interval))
591a77257d6SKevin Bowling device_printf(sc->dev,
592a77257d6SKevin Bowling "could not disable retained VF queues; "
593a77257d6SKevin Bowling "reset deferred\n");
594a77257d6SKevin Bowling return (false);
595a77257d6SKevin Bowling }
596a77257d6SKevin Bowling
597a77257d6SKevin Bowling for (i = 0; i < nqueues; i++) {
598a77257d6SKevin Bowling E1000_WRITE_REG(hw, E1000_SRRCTL(i), 0);
599a77257d6SKevin Bowling E1000_WRITE_REG(hw, E1000_DCA_RXCTRL(i), 0);
600a77257d6SKevin Bowling E1000_WRITE_REG(hw, E1000_TDWBAL(i), 0);
601a77257d6SKevin Bowling E1000_WRITE_REG(hw, E1000_TDWBAH(i), 0);
602a77257d6SKevin Bowling E1000_WRITE_REG(hw, E1000_DCA_TXCTRL(i), 0);
603a77257d6SKevin Bowling }
604a77257d6SKevin Bowling E1000_WRITE_REG(hw, E1000_VFPSRTYPE, 0);
605a77257d6SKevin Bowling E1000_WRITE_FLUSH(hw);
606a77257d6SKevin Bowling return (true);
607a77257d6SKevin Bowling }
608a77257d6SKevin Bowling
609316f6f2fSKevin Bowling bool
igbv_reset(if_ctx_t ctx)610316f6f2fSKevin Bowling igbv_reset(if_ctx_t ctx)
611316f6f2fSKevin Bowling {
612316f6f2fSKevin Bowling struct e1000_softc *sc;
613316f6f2fSKevin Bowling struct e1000_hw *hw;
614a77257d6SKevin Bowling s32 error;
615316f6f2fSKevin Bowling
616316f6f2fSKevin Bowling sc = iflib_get_softc(ctx);
617316f6f2fSKevin Bowling hw = &sc->hw;
618316f6f2fSKevin Bowling KASSERT(sc->vf_ifp, ("%s called for a PF", __func__));
619316f6f2fSKevin Bowling
620316f6f2fSKevin Bowling /*
621316f6f2fSKevin Bowling * Receive-buffer allocation and flow control are port resources owned
622316f6f2fSKevin Bowling * by the PF. Zero is an unavailable PBA sentinel, not a per-VF size.
623316f6f2fSKevin Bowling */
624316f6f2fSKevin Bowling sc->pba = 0;
625316f6f2fSKevin Bowling hw->fc = (struct e1000_fc_info){
626316f6f2fSKevin Bowling .current_mode = e1000_fc_none,
627316f6f2fSKevin Bowling .requested_mode = e1000_fc_none,
628316f6f2fSKevin Bowling };
629316f6f2fSKevin Bowling
630a77257d6SKevin Bowling error = e1000_reset_hw(hw);
631*612f87c9SKevin Bowling atomic_store_rel_32(&sc->vf_mbx_ready, 0);
632a77257d6SKevin Bowling sc->vf_queues_sanitized = igbv_sanitize_queues(sc);
633a77257d6SKevin Bowling if (!sc->vf_queues_sanitized) {
634a77257d6SKevin Bowling return (false);
635a77257d6SKevin Bowling }
636a77257d6SKevin Bowling igbv_queue_retry_succeeded(sc);
637a77257d6SKevin Bowling if (error != E1000_SUCCESS) {
638*612f87c9SKevin Bowling igbv_log_reset_failure(sc, error, false);
639316f6f2fSKevin Bowling return (false);
640316f6f2fSKevin Bowling }
641a6bb3850SKevin Bowling memset(sc->vf_vfta_stale, 0, sizeof(sc->vf_vfta_stale));
642fdce3830SKevin Bowling memset(sc->vf_vfta_retry, 0, sizeof(sc->vf_vfta_retry));
643fdce3830SKevin Bowling sc->vf_vlan_retry_deadline = 0;
644fdce3830SKevin Bowling sc->vf_vlan_retry_cursor = 0;
645316f6f2fSKevin Bowling if (e1000_init_hw(hw) < 0) {
646316f6f2fSKevin Bowling device_printf(sc->dev, "Hardware Initialization Failed\n");
647316f6f2fSKevin Bowling return (false);
648316f6f2fSKevin Bowling }
649316f6f2fSKevin Bowling e1000_check_for_link(hw);
650*612f87c9SKevin Bowling igbv_mbx_retry_succeeded(sc);
651316f6f2fSKevin Bowling return (true);
652316f6f2fSKevin Bowling }
653316f6f2fSKevin Bowling
654316f6f2fSKevin Bowling void
igbv_initialize_transmit_unit(if_ctx_t ctx)655316f6f2fSKevin Bowling igbv_initialize_transmit_unit(if_ctx_t ctx)
656316f6f2fSKevin Bowling {
657316f6f2fSKevin Bowling
658316f6f2fSKevin Bowling KASSERT(((struct e1000_softc *)iflib_get_softc(ctx))->vf_ifp,
659316f6f2fSKevin Bowling ("%s called for a PF", __func__));
660316f6f2fSKevin Bowling em_initialize_transmit_rings(ctx);
661316f6f2fSKevin Bowling }
662316f6f2fSKevin Bowling
663316f6f2fSKevin Bowling void
igbv_initialize_receive_unit(if_ctx_t ctx)664316f6f2fSKevin Bowling igbv_initialize_receive_unit(if_ctx_t ctx)
665316f6f2fSKevin Bowling {
666316f6f2fSKevin Bowling
667316f6f2fSKevin Bowling KASSERT(((struct e1000_softc *)iflib_get_softc(ctx))->vf_ifp,
668316f6f2fSKevin Bowling ("%s called for a PF", __func__));
669316f6f2fSKevin Bowling igb_initialize_receive_rings(ctx, true);
670316f6f2fSKevin Bowling }
671316f6f2fSKevin Bowling
672316f6f2fSKevin Bowling void
igbv_if_intr_enable(if_ctx_t ctx)673316f6f2fSKevin Bowling igbv_if_intr_enable(if_ctx_t ctx)
674316f6f2fSKevin Bowling {
675316f6f2fSKevin Bowling struct e1000_softc *sc;
676316f6f2fSKevin Bowling struct e1000_hw *hw;
677316f6f2fSKevin Bowling u32 mask;
678316f6f2fSKevin Bowling
679316f6f2fSKevin Bowling sc = iflib_get_softc(ctx);
680316f6f2fSKevin Bowling hw = &sc->hw;
681316f6f2fSKevin Bowling KASSERT(sc->vf_ifp, ("%s called for a PF", __func__));
682*612f87c9SKevin Bowling if (!sc->vf_queues_sanitized ||
683*612f87c9SKevin Bowling atomic_load_acq_32(&sc->vf_mbx_ready) == 0)
684a77257d6SKevin Bowling return;
685316f6f2fSKevin Bowling mask = sc->que_mask | sc->link_mask;
686316f6f2fSKevin Bowling
687316f6f2fSKevin Bowling E1000_WRITE_REG(hw, E1000_EIAC, mask);
688316f6f2fSKevin Bowling E1000_WRITE_REG(hw, E1000_EIAM, mask);
689316f6f2fSKevin Bowling E1000_WRITE_REG(hw, E1000_EIMS, mask);
690316f6f2fSKevin Bowling E1000_WRITE_FLUSH(hw);
691316f6f2fSKevin Bowling }
692316f6f2fSKevin Bowling
693316f6f2fSKevin Bowling void
igbv_if_intr_disable(if_ctx_t ctx)694316f6f2fSKevin Bowling igbv_if_intr_disable(if_ctx_t ctx)
695316f6f2fSKevin Bowling {
696316f6f2fSKevin Bowling struct e1000_softc *sc;
697316f6f2fSKevin Bowling struct e1000_hw *hw;
698316f6f2fSKevin Bowling
699316f6f2fSKevin Bowling sc = iflib_get_softc(ctx);
700316f6f2fSKevin Bowling hw = &sc->hw;
701316f6f2fSKevin Bowling KASSERT(sc->vf_ifp, ("%s called for a PF", __func__));
702316f6f2fSKevin Bowling
703316f6f2fSKevin Bowling E1000_WRITE_REG(hw, E1000_EIMC, 0xffffffff);
704316f6f2fSKevin Bowling E1000_WRITE_REG(hw, E1000_EIAC, 0);
705316f6f2fSKevin Bowling E1000_WRITE_FLUSH(hw);
706316f6f2fSKevin Bowling }
707316f6f2fSKevin Bowling
708316f6f2fSKevin Bowling int
igbv_get_regs(SYSCTL_HANDLER_ARGS)709316f6f2fSKevin Bowling igbv_get_regs(SYSCTL_HANDLER_ARGS)
710316f6f2fSKevin Bowling {
711316f6f2fSKevin Bowling struct e1000_softc *sc;
712316f6f2fSKevin Bowling struct e1000_hw *hw;
713316f6f2fSKevin Bowling struct sbuf *sb;
714316f6f2fSKevin Bowling int error;
715316f6f2fSKevin Bowling
716316f6f2fSKevin Bowling sc = (struct e1000_softc *)arg1;
717316f6f2fSKevin Bowling hw = &sc->hw;
718316f6f2fSKevin Bowling KASSERT(sc->vf_ifp, ("%s called for a PF", __func__));
719316f6f2fSKevin Bowling
720316f6f2fSKevin Bowling sb = sbuf_new_for_sysctl(NULL, NULL, 512, req);
721316f6f2fSKevin Bowling if (sb == NULL)
722316f6f2fSKevin Bowling return (ENOMEM);
723316f6f2fSKevin Bowling
724316f6f2fSKevin Bowling /*
725316f6f2fSKevin Bowling * Limited VF register set:
726316f6f2fSKevin Bowling * Don't read EICR here because it is clear-on-read. The VF register
727316f6f2fSKevin Bowling * file exposes its queue pair at index zero, so this diagnostic does
728316f6f2fSKevin Bowling * not depend on the narrower lifetime of iflib's queue arrays.
729316f6f2fSKevin Bowling */
730316f6f2fSKevin Bowling sbuf_printf(sb, "VF Registers\n");
731316f6f2fSKevin Bowling sbuf_printf(sb, "\tVTCTRL\t %08x\n",
732316f6f2fSKevin Bowling E1000_READ_REG(hw, E1000_CTRL));
733316f6f2fSKevin Bowling sbuf_printf(sb, "\tSTATUS\t %08x\n",
734316f6f2fSKevin Bowling E1000_READ_REG(hw, E1000_STATUS));
735316f6f2fSKevin Bowling sbuf_printf(sb, "\tRDLEN\t %08x\n",
736316f6f2fSKevin Bowling E1000_READ_REG(hw, E1000_RDLEN(0)));
737316f6f2fSKevin Bowling sbuf_printf(sb, "\tRDH\t %08x\n",
738316f6f2fSKevin Bowling E1000_READ_REG(hw, E1000_RDH(0)));
739316f6f2fSKevin Bowling sbuf_printf(sb, "\tRDT\t %08x\n",
740316f6f2fSKevin Bowling E1000_READ_REG(hw, E1000_RDT(0)));
741316f6f2fSKevin Bowling sbuf_printf(sb, "\tTDLEN\t %08x\n",
742316f6f2fSKevin Bowling E1000_READ_REG(hw, E1000_TDLEN(0)));
743316f6f2fSKevin Bowling sbuf_printf(sb, "\tTDH\t %08x\n",
744316f6f2fSKevin Bowling E1000_READ_REG(hw, E1000_TDH(0)));
745316f6f2fSKevin Bowling sbuf_printf(sb, "\tTDT\t %08x\n",
746316f6f2fSKevin Bowling E1000_READ_REG(hw, E1000_TDT(0)));
747316f6f2fSKevin Bowling
748316f6f2fSKevin Bowling error = sbuf_finish(sb);
749316f6f2fSKevin Bowling sbuf_delete(sb);
750316f6f2fSKevin Bowling return (error);
751316f6f2fSKevin Bowling }
752a6bb3850SKevin Bowling
7539332fd55SKevin Bowling static u_int
igbv_copy_uc_addr(void * arg,struct sockaddr_dl * sdl,u_int idx)7549332fd55SKevin Bowling igbv_copy_uc_addr(void *arg, struct sockaddr_dl *sdl, u_int idx)
7559332fd55SKevin Bowling {
7569332fd55SKevin Bowling struct igb_vf_uc_addr_list *list;
7579332fd55SKevin Bowling const u8 *addr;
7589332fd55SKevin Bowling
7599332fd55SKevin Bowling list = arg;
7609332fd55SKevin Bowling addr = (const u8 *)LLADDR(sdl);
7619332fd55SKevin Bowling if (memcmp(addr, list->sc->hw.mac.addr, ETHER_ADDR_LEN) == 0)
7629332fd55SKevin Bowling return (0);
7639332fd55SKevin Bowling if (idx < IGBV_MAX_MAC_FILTERS)
7649332fd55SKevin Bowling memcpy(list->addrs[idx], addr, ETHER_ADDR_LEN);
7659332fd55SKevin Bowling return (1);
7669332fd55SKevin Bowling }
7679332fd55SKevin Bowling
7689332fd55SKevin Bowling void
igbv_update_uc_addr_list(struct e1000_softc * sc,if_t ifp)7699332fd55SKevin Bowling igbv_update_uc_addr_list(struct e1000_softc *sc, if_t ifp)
7709332fd55SKevin Bowling {
7719332fd55SKevin Bowling struct igb_vf_uc_addr_list list = {
7729332fd55SKevin Bowling .sc = sc,
7739332fd55SKevin Bowling };
7749332fd55SKevin Bowling u_int count;
7759332fd55SKevin Bowling
7769332fd55SKevin Bowling count = if_foreach_lladdr(ifp, igbv_copy_uc_addr, &list);
7779332fd55SKevin Bowling if (count > IGBV_MAX_MAC_FILTERS) {
7789332fd55SKevin Bowling device_printf(sc->dev,
7799332fd55SKevin Bowling "too many secondary unicast addresses; maximum is %u\n",
7809332fd55SKevin Bowling IGBV_MAX_MAC_FILTERS);
7819332fd55SKevin Bowling }
7829332fd55SKevin Bowling if (count == 0 && !sc->vf_uc_filters_set)
7839332fd55SKevin Bowling return;
7849332fd55SKevin Bowling /*
7859332fd55SKevin Bowling * Linux igb PFs validate the address field before dispatching the CLR
7869332fd55SKevin Bowling * subcommand. Supply the primary address rather than the zero payload
7879332fd55SKevin Bowling * used by igbvf so those PFs actually remove the old filters. FreeBSD
7889332fd55SKevin Bowling * PFs dispatch CLR before inspecting the otherwise-ignored address.
7899332fd55SKevin Bowling */
7909332fd55SKevin Bowling if (e1000_set_uc_addr_vf(&sc->hw, E1000_VF_MAC_FILTER_CLR,
7919332fd55SKevin Bowling sc->hw.mac.addr) != E1000_SUCCESS) {
7929332fd55SKevin Bowling device_printf(sc->dev,
7939332fd55SKevin Bowling "VF secondary unicast filter clear request failed\n");
7949332fd55SKevin Bowling return;
7959332fd55SKevin Bowling }
7969332fd55SKevin Bowling sc->vf_uc_filters_set = false;
7979332fd55SKevin Bowling if (count > IGBV_MAX_MAC_FILTERS)
7989332fd55SKevin Bowling return;
7999332fd55SKevin Bowling
8009332fd55SKevin Bowling for (u_int i = 0; i < count; i++) {
8019332fd55SKevin Bowling if (e1000_set_uc_addr_vf(&sc->hw, E1000_VF_MAC_FILTER_ADD,
8029332fd55SKevin Bowling list.addrs[i]) != E1000_SUCCESS) {
8039332fd55SKevin Bowling device_printf(sc->dev,
8049332fd55SKevin Bowling "VF secondary unicast filter add request failed "
8059332fd55SKevin Bowling "for %6D\n", list.addrs[i], ":");
8069332fd55SKevin Bowling } else
8079332fd55SKevin Bowling sc->vf_uc_filters_set = true;
8089332fd55SKevin Bowling usec_delay(200);
8099332fd55SKevin Bowling }
8109332fd55SKevin Bowling }
8119332fd55SKevin Bowling
812a6bb3850SKevin Bowling void
igbv_reconcile_mac(struct e1000_softc * sc,if_t ifp)813a6bb3850SKevin Bowling igbv_reconcile_mac(struct e1000_softc *sc, if_t ifp)
814a6bb3850SKevin Bowling {
815a6bb3850SKevin Bowling u8 *lladdr;
816a6bb3850SKevin Bowling
817a6bb3850SKevin Bowling if (!em_is_valid_ether_addr(sc->hw.mac.addr))
818a6bb3850SKevin Bowling return;
819a6bb3850SKevin Bowling lladdr = (u8 *)if_getlladdr(ifp);
820a6bb3850SKevin Bowling if (memcmp(lladdr, sc->hw.mac.addr, ETHER_ADDR_LEN) == 0)
821a6bb3850SKevin Bowling return;
822a6bb3850SKevin Bowling
823a6bb3850SKevin Bowling device_printf(sc->dev,
824a6bb3850SKevin Bowling "PF rejected or replaced the requested MAC; using %6D\n",
825a6bb3850SKevin Bowling sc->hw.mac.addr, ":");
826a6bb3850SKevin Bowling /*
827a6bb3850SKevin Bowling * if_setlladdr() would re-enter the driver's address-change path.
828a6bb3850SKevin Bowling * Initialization already holds the context lock, so update the
829a6bb3850SKevin Bowling * storage directly and issue the notification it would have sent.
830a6bb3850SKevin Bowling */
831a6bb3850SKevin Bowling memcpy(lladdr, sc->hw.mac.addr, ETHER_ADDR_LEN);
832a6bb3850SKevin Bowling
833a6bb3850SKevin Bowling CURVNET_SET_QUIET(if_getvnet(ifp));
834a6bb3850SKevin Bowling EVENTHANDLER_INVOKE(iflladdr_event, ifp);
835a6bb3850SKevin Bowling CURVNET_RESTORE();
836a6bb3850SKevin Bowling }
837