xref: /freebsd/sys/dev/e1000/if_igbv.c (revision 612f87c949a2aa3363258890bca2abaea99d3fd6)
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