xref: /freebsd/sys/dev/ixl/ixl_pf_iflib.c (revision 15f0b8c3)
1 /******************************************************************************
2 
3   Copyright (c) 2013-2020, Intel Corporation
4   All rights reserved.
5 
6   Redistribution and use in source and binary forms, with or without
7   modification, are permitted provided that the following conditions are met:
8 
9    1. Redistributions of source code must retain the above copyright notice,
10       this list of conditions and the following disclaimer.
11 
12    2. Redistributions in binary form must reproduce the above copyright
13       notice, this list of conditions and the following disclaimer in the
14       documentation and/or other materials provided with the distribution.
15 
16    3. Neither the name of the Intel Corporation nor the names of its
17       contributors may be used to endorse or promote products derived from
18       this software without specific prior written permission.
19 
20   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   POSSIBILITY OF SUCH DAMAGE.
31 
32 ******************************************************************************/
33 /*$FreeBSD$*/
34 
35 #include "ixl_pf.h"
36 
37 void
38 ixl_configure_tx_itr(struct ixl_pf *pf)
39 {
40 	struct i40e_hw		*hw = &pf->hw;
41 	struct ixl_vsi		*vsi = &pf->vsi;
42 	struct ixl_tx_queue	*que = vsi->tx_queues;
43 
44 	vsi->tx_itr_setting = pf->tx_itr;
45 
46 	for (int i = 0; i < vsi->num_tx_queues; i++, que++) {
47 		struct tx_ring	*txr = &que->txr;
48 
49 		wr32(hw, I40E_PFINT_ITRN(IXL_TX_ITR, i),
50 		    vsi->tx_itr_setting);
51 		txr->itr = vsi->tx_itr_setting;
52 		txr->latency = IXL_AVE_LATENCY;
53 	}
54 }
55 
56 void
57 ixl_configure_rx_itr(struct ixl_pf *pf)
58 {
59 	struct i40e_hw		*hw = &pf->hw;
60 	struct ixl_vsi		*vsi = &pf->vsi;
61 	struct ixl_rx_queue	*que = vsi->rx_queues;
62 
63 	vsi->rx_itr_setting = pf->rx_itr;
64 
65 	for (int i = 0; i < vsi->num_rx_queues; i++, que++) {
66 		struct rx_ring 	*rxr = &que->rxr;
67 
68 		wr32(hw, I40E_PFINT_ITRN(IXL_RX_ITR, i),
69 		    vsi->rx_itr_setting);
70 		rxr->itr = vsi->rx_itr_setting;
71 		rxr->latency = IXL_AVE_LATENCY;
72 	}
73 }
74 
75 int
76 ixl_intr(void *arg)
77 {
78 	struct ixl_pf		*pf = arg;
79 	struct i40e_hw		*hw =  &pf->hw;
80 	struct ixl_vsi		*vsi = &pf->vsi;
81 	struct ixl_rx_queue	*que = vsi->rx_queues;
82         u32			icr0;
83 
84 	++que->irqs;
85 
86 	/* Clear PBA at start of ISR if using legacy interrupts */
87 	if (vsi->shared->isc_intr == IFLIB_INTR_LEGACY)
88 		wr32(hw, I40E_PFINT_DYN_CTL0,
89 		    I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
90 		    (IXL_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT));
91 
92 	icr0 = rd32(hw, I40E_PFINT_ICR0);
93 
94 
95 #ifdef PCI_IOV
96 	if (icr0 & I40E_PFINT_ICR0_VFLR_MASK)
97 		iflib_iov_intr_deferred(vsi->ctx);
98 #endif
99 
100 	if (icr0 & I40E_PFINT_ICR0_ADMINQ_MASK)
101 		iflib_admin_intr_deferred(vsi->ctx);
102 
103 	ixl_enable_intr0(hw);
104 
105 	if (icr0 & I40E_PFINT_ICR0_QUEUE_0_MASK)
106 		return (FILTER_SCHEDULE_THREAD);
107 	else
108 		return (FILTER_HANDLED);
109 }
110 
111 /*********************************************************************
112  *
113  *  MSI-X VSI Interrupt Service routine
114  *
115  **********************************************************************/
116 int
117 ixl_msix_que(void *arg)
118 {
119 	struct ixl_rx_queue *rx_que = arg;
120 
121 	++rx_que->irqs;
122 
123 	ixl_set_queue_rx_itr(rx_que);
124 
125 	return (FILTER_SCHEDULE_THREAD);
126 }
127 
128 /*********************************************************************
129  *
130  *  MSI-X Admin Queue Interrupt Service routine
131  *
132  **********************************************************************/
133 int
134 ixl_msix_adminq(void *arg)
135 {
136 	struct ixl_pf	*pf = arg;
137 	struct i40e_hw	*hw = &pf->hw;
138 	device_t	dev = pf->dev;
139 	u32		reg, mask, rstat_reg;
140 	bool		do_task = FALSE;
141 
142 	DDPRINTF(dev, "begin");
143 
144 	++pf->admin_irq;
145 
146 	reg = rd32(hw, I40E_PFINT_ICR0);
147 	/*
148 	 * For masking off interrupt causes that need to be handled before
149 	 * they can be re-enabled
150 	 */
151 	mask = rd32(hw, I40E_PFINT_ICR0_ENA);
152 
153 	/* Check on the cause */
154 	if (reg & I40E_PFINT_ICR0_ADMINQ_MASK) {
155 		mask &= ~I40E_PFINT_ICR0_ENA_ADMINQ_MASK;
156 		do_task = TRUE;
157 	}
158 
159 	if (reg & I40E_PFINT_ICR0_MAL_DETECT_MASK) {
160 		mask &= ~I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK;
161 		atomic_set_32(&pf->state, IXL_PF_STATE_MDD_PENDING);
162 		do_task = TRUE;
163 	}
164 
165 	if (reg & I40E_PFINT_ICR0_GRST_MASK) {
166 		const char *reset_type;
167 		mask &= ~I40E_PFINT_ICR0_ENA_GRST_MASK;
168 		rstat_reg = rd32(hw, I40E_GLGEN_RSTAT);
169 		rstat_reg = (rstat_reg & I40E_GLGEN_RSTAT_RESET_TYPE_MASK)
170 		    >> I40E_GLGEN_RSTAT_RESET_TYPE_SHIFT;
171 		switch (rstat_reg) {
172 		/* These others might be handled similarly to an EMPR reset */
173 		case I40E_RESET_CORER:
174 			reset_type = "CORER";
175 			break;
176 		case I40E_RESET_GLOBR:
177 			reset_type = "GLOBR";
178 			break;
179 		case I40E_RESET_EMPR:
180 			reset_type = "EMPR";
181 			break;
182 		default:
183 			reset_type = "POR";
184 			break;
185 		}
186 		device_printf(dev, "Reset Requested! (%s)\n", reset_type);
187 		/* overload admin queue task to check reset progress */
188 		atomic_set_int(&pf->state, IXL_PF_STATE_RESETTING);
189 		do_task = TRUE;
190 	}
191 
192 	/*
193 	 * PE / PCI / ECC exceptions are all handled in the same way:
194 	 * mask out these three causes, then request a PF reset
195 	 */
196 	if (reg & I40E_PFINT_ICR0_ECC_ERR_MASK)
197 		device_printf(dev, "ECC Error detected!\n");
198 	if (reg & I40E_PFINT_ICR0_PCI_EXCEPTION_MASK)
199 		device_printf(dev, "PCI Exception detected!\n");
200 	if (reg & I40E_PFINT_ICR0_PE_CRITERR_MASK)
201 		device_printf(dev, "Critical Protocol Engine Error detected!\n");
202 	/* Checks against the conditions above */
203 	if (reg & IXL_ICR0_CRIT_ERR_MASK) {
204 		mask &= ~IXL_ICR0_CRIT_ERR_MASK;
205 		atomic_set_32(&pf->state,
206 		    IXL_PF_STATE_PF_RESET_REQ | IXL_PF_STATE_PF_CRIT_ERR);
207 		do_task = TRUE;
208 	}
209 
210 	if (reg & I40E_PFINT_ICR0_HMC_ERR_MASK) {
211 		reg = rd32(hw, I40E_PFHMC_ERRORINFO);
212 		if (reg & I40E_PFHMC_ERRORINFO_ERROR_DETECTED_MASK) {
213 			device_printf(dev, "HMC Error detected!\n");
214 			device_printf(dev, "INFO 0x%08x\n", reg);
215 			reg = rd32(hw, I40E_PFHMC_ERRORDATA);
216 			device_printf(dev, "DATA 0x%08x\n", reg);
217 			wr32(hw, I40E_PFHMC_ERRORINFO, 0);
218 		}
219 	}
220 
221 #ifdef PCI_IOV
222 	if (reg & I40E_PFINT_ICR0_VFLR_MASK) {
223 		mask &= ~I40E_PFINT_ICR0_ENA_VFLR_MASK;
224 		iflib_iov_intr_deferred(pf->vsi.ctx);
225 	}
226 #endif
227 
228 	wr32(hw, I40E_PFINT_ICR0_ENA, mask);
229 	ixl_enable_intr0(hw);
230 
231 	if (do_task)
232 		return (FILTER_SCHEDULE_THREAD);
233 	else
234 		return (FILTER_HANDLED);
235 }
236 
237 /*
238  * Configure queue interrupt cause registers in hardware.
239  *
240  * Linked list for each vector LNKLSTN(i) -> RQCTL(i) -> TQCTL(i) -> EOL
241  */
242 void
243 ixl_configure_queue_intr_msix(struct ixl_pf *pf)
244 {
245 	struct i40e_hw *hw = &pf->hw;
246 	struct ixl_vsi *vsi = &pf->vsi;
247 	u32		reg;
248 	u16		vector = 1;
249 
250 	for (int i = 0; i < max(vsi->num_rx_queues, vsi->num_tx_queues); i++, vector++) {
251 		/* Make sure interrupt is disabled */
252 		wr32(hw, I40E_PFINT_DYN_CTLN(i), 0);
253 		/* Set linked list head to point to corresponding RX queue
254 		 * e.g. vector 1 (LNKLSTN register 0) points to queue pair 0's RX queue */
255 		reg = ((i << I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT)
256 		        & I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK) |
257 		    ((I40E_QUEUE_TYPE_RX << I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)
258 		        & I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_MASK);
259 		wr32(hw, I40E_PFINT_LNKLSTN(i), reg);
260 
261 		reg = I40E_QINT_RQCTL_CAUSE_ENA_MASK |
262 		(IXL_RX_ITR << I40E_QINT_RQCTL_ITR_INDX_SHIFT) |
263 		(vector << I40E_QINT_RQCTL_MSIX_INDX_SHIFT) |
264 		(i << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) |
265 		(I40E_QUEUE_TYPE_TX << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT);
266 		wr32(hw, I40E_QINT_RQCTL(i), reg);
267 
268 		reg = I40E_QINT_TQCTL_CAUSE_ENA_MASK |
269 		(IXL_TX_ITR << I40E_QINT_TQCTL_ITR_INDX_SHIFT) |
270 		(vector << I40E_QINT_TQCTL_MSIX_INDX_SHIFT) |
271 		(IXL_QUEUE_EOL << I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT) |
272 		(I40E_QUEUE_TYPE_RX << I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT);
273 		wr32(hw, I40E_QINT_TQCTL(i), reg);
274 	}
275 }
276 
277 /*
278  * Configure for single interrupt vector operation
279  */
280 void
281 ixl_configure_legacy(struct ixl_pf *pf)
282 {
283 	struct i40e_hw	*hw = &pf->hw;
284 	struct ixl_vsi	*vsi = &pf->vsi;
285 	u32 reg;
286 
287 	vsi->rx_queues[0].rxr.itr = vsi->rx_itr_setting;
288 
289 	/* Setup "other" causes */
290 	reg = I40E_PFINT_ICR0_ENA_ECC_ERR_MASK
291 	    | I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK
292 	    | I40E_PFINT_ICR0_ENA_GRST_MASK
293 	    | I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_MASK
294 	    | I40E_PFINT_ICR0_ENA_HMC_ERR_MASK
295 	    | I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK
296 	    | I40E_PFINT_ICR0_ENA_VFLR_MASK
297 	    | I40E_PFINT_ICR0_ENA_ADMINQ_MASK
298 	    ;
299 	wr32(hw, I40E_PFINT_ICR0_ENA, reg);
300 
301 	/* No ITR for non-queue interrupts */
302 	wr32(hw, I40E_PFINT_STAT_CTL0,
303 	    IXL_ITR_NONE << I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT);
304 
305 	/* FIRSTQ_INDX = 0, FIRSTQ_TYPE = 0 (rx) */
306 	wr32(hw, I40E_PFINT_LNKLST0, 0);
307 
308 	/* Associate the queue pair to the vector and enable the q int */
309 	reg = I40E_QINT_RQCTL_CAUSE_ENA_MASK
310 	    | (IXL_RX_ITR << I40E_QINT_RQCTL_ITR_INDX_SHIFT)
311 	    | (I40E_QUEUE_TYPE_TX << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT);
312 	wr32(hw, I40E_QINT_RQCTL(0), reg);
313 
314 	reg = I40E_QINT_TQCTL_CAUSE_ENA_MASK
315 	    | (IXL_TX_ITR << I40E_QINT_TQCTL_ITR_INDX_SHIFT)
316 	    | (IXL_QUEUE_EOL << I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT);
317 	wr32(hw, I40E_QINT_TQCTL(0), reg);
318 }
319 
320 void
321 ixl_free_pci_resources(struct ixl_pf *pf)
322 {
323 	struct ixl_vsi		*vsi = &pf->vsi;
324 	device_t		dev = iflib_get_dev(vsi->ctx);
325 	struct ixl_rx_queue	*rx_que = vsi->rx_queues;
326 
327 	/* We may get here before stations are set up */
328 	if (rx_que == NULL)
329 		goto early;
330 
331 	/*
332 	**  Release all MSI-X VSI resources:
333 	*/
334 	iflib_irq_free(vsi->ctx, &vsi->irq);
335 
336 	for (int i = 0; i < vsi->num_rx_queues; i++, rx_que++)
337 		iflib_irq_free(vsi->ctx, &rx_que->que_irq);
338 early:
339 	if (pf->pci_mem != NULL)
340 		bus_release_resource(dev, SYS_RES_MEMORY,
341 		    rman_get_rid(pf->pci_mem), pf->pci_mem);
342 }
343 
344 /*********************************************************************
345  *
346  *  Setup networking device structure and register an interface.
347  *
348  **********************************************************************/
349 int
350 ixl_setup_interface(device_t dev, struct ixl_pf *pf)
351 {
352 	struct ixl_vsi *vsi = &pf->vsi;
353 	if_ctx_t ctx = vsi->ctx;
354 	struct i40e_hw *hw = &pf->hw;
355 	if_t ifp = iflib_get_ifp(ctx);
356 	struct i40e_aq_get_phy_abilities_resp abilities;
357 	enum i40e_status_code aq_error = 0;
358 
359 	INIT_DBG_DEV(dev, "begin");
360 
361 	vsi->shared->isc_max_frame_size =
362 	    if_getmtu(ifp) + ETHER_HDR_LEN + ETHER_CRC_LEN
363 	    + ETHER_VLAN_ENCAP_LEN;
364 
365 	if (IXL_PF_IN_RECOVERY_MODE(pf))
366 		goto only_auto;
367 
368 	aq_error = i40e_aq_get_phy_capabilities(hw,
369 	    FALSE, TRUE, &abilities, NULL);
370 	/* May need delay to detect fiber correctly */
371 	if (aq_error == I40E_ERR_UNKNOWN_PHY) {
372 		i40e_msec_delay(200);
373 		aq_error = i40e_aq_get_phy_capabilities(hw, FALSE,
374 		    TRUE, &abilities, NULL);
375 	}
376 	if (aq_error) {
377 		if (aq_error == I40E_ERR_UNKNOWN_PHY)
378 			device_printf(dev, "Unknown PHY type detected!\n");
379 		else
380 			device_printf(dev,
381 			    "Error getting supported media types, err %d,"
382 			    " AQ error %d\n", aq_error, hw->aq.asq_last_status);
383 	} else {
384 		pf->supported_speeds = abilities.link_speed;
385 		if_setbaudrate(ifp, ixl_max_aq_speed_to_value(pf->supported_speeds));
386 
387 		ixl_add_ifmedia(vsi->media, hw->phy.phy_types);
388 	}
389 
390 only_auto:
391 	/* Use autoselect media by default */
392 	ifmedia_add(vsi->media, IFM_ETHER | IFM_AUTO, 0, NULL);
393 	ifmedia_set(vsi->media, IFM_ETHER | IFM_AUTO);
394 
395 	return (0);
396 }
397 
398 /*
399 ** Run when the Admin Queue gets a link state change interrupt.
400 */
401 void
402 ixl_link_event(struct ixl_pf *pf, struct i40e_arq_event_info *e)
403 {
404 	struct i40e_hw *hw = &pf->hw;
405 	device_t dev = iflib_get_dev(pf->vsi.ctx);
406 	struct i40e_link_status *link_info = &hw->phy.link_info;
407 
408 	/* Driver needs to re-enable delivering of link status events
409 	 * by FW after each event reception. Call i40e_get_link_status
410 	 * to do that. To not lose information about link state changes,
411 	 * which happened between receiving an event and the call,
412 	 * do not rely on status from event but use most recent
413 	 * status information retrieved by the call. */
414 	hw->phy.get_link_info = TRUE;
415 	i40e_get_link_status(hw, &pf->link_up);
416 
417 	/* Print out message if an unqualified module is found */
418 	if ((link_info->link_info & I40E_AQ_MEDIA_AVAILABLE) &&
419 	    (pf->advertised_speed) &&
420 	    (if_getflags(pf->vsi.ifp) & IFF_UP) &&
421 	    (!(link_info->an_info & I40E_AQ_QUALIFIED_MODULE)) &&
422 	    (!(link_info->link_info & I40E_AQ_LINK_UP)))
423 		device_printf(dev, "Link failed because "
424 		    "an unqualified module was detected!\n");
425 
426 	/* OS link info is updated elsewhere */
427 }
428 
429 /*********************************************************************
430  *
431  *  Initialize the VSI:  this handles contexts, which means things
432  *  			 like the number of descriptors, buffer size,
433  *			 plus we init the rings thru this function.
434  *
435  **********************************************************************/
436 int
437 ixl_initialize_vsi(struct ixl_vsi *vsi)
438 {
439 	struct ixl_pf *pf = vsi->back;
440 	if_softc_ctx_t		scctx = iflib_get_softc_ctx(vsi->ctx);
441 	struct ixl_tx_queue	*tx_que = vsi->tx_queues;
442 	struct ixl_rx_queue	*rx_que = vsi->rx_queues;
443 	device_t		dev = iflib_get_dev(vsi->ctx);
444 	struct i40e_hw		*hw = vsi->hw;
445 	struct i40e_vsi_context	ctxt;
446 	int 			tc_queues;
447 	int			err = 0;
448 
449 	memset(&ctxt, 0, sizeof(ctxt));
450 	ctxt.seid = vsi->seid;
451 	if (pf->veb_seid != 0)
452 		ctxt.uplink_seid = pf->veb_seid;
453 	ctxt.pf_num = hw->pf_id;
454 	err = i40e_aq_get_vsi_params(hw, &ctxt, NULL);
455 	if (err) {
456 		device_printf(dev, "i40e_aq_get_vsi_params() failed, error %d"
457 		    " aq_error %d\n", err, hw->aq.asq_last_status);
458 		return (err);
459 	}
460 	ixl_dbg(pf, IXL_DBG_SWITCH_INFO,
461 	    "get_vsi_params: seid: %d, uplinkseid: %d, vsi_number: %d, "
462 	    "vsis_allocated: %d, vsis_unallocated: %d, flags: 0x%x, "
463 	    "pfnum: %d, vfnum: %d, stat idx: %d, enabled: %d\n", ctxt.seid,
464 	    ctxt.uplink_seid, ctxt.vsi_number,
465 	    ctxt.vsis_allocated, ctxt.vsis_unallocated,
466 	    ctxt.flags, ctxt.pf_num, ctxt.vf_num,
467 	    ctxt.info.stat_counter_idx, ctxt.info.up_enable_bits);
468 	/*
469 	** Set the queue and traffic class bits
470 	**  - when multiple traffic classes are supported
471 	**    this will need to be more robust.
472 	*/
473 	ctxt.info.valid_sections = I40E_AQ_VSI_PROP_QUEUE_MAP_VALID;
474 	ctxt.info.mapping_flags |= I40E_AQ_VSI_QUE_MAP_CONTIG;
475 	/* In contig mode, que_mapping[0] is first queue index used by this VSI */
476 	ctxt.info.queue_mapping[0] = 0;
477 	/*
478 	 * This VSI will only use traffic class 0; start traffic class 0's
479 	 * queue allocation at queue 0, and assign it 2^tc_queues queues (though
480 	 * the driver may not use all of them).
481 	 */
482 	tc_queues = fls(pf->qtag.num_allocated) - 1;
483 	ctxt.info.tc_mapping[0] = ((pf->qtag.first_qidx << I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT)
484 	    & I40E_AQ_VSI_TC_QUE_OFFSET_MASK) |
485 	    ((tc_queues << I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT)
486 	    & I40E_AQ_VSI_TC_QUE_NUMBER_MASK);
487 
488 	/* Set VLAN receive stripping mode */
489 	ctxt.info.valid_sections |= I40E_AQ_VSI_PROP_VLAN_VALID;
490 	ctxt.info.port_vlan_flags = I40E_AQ_VSI_PVLAN_MODE_ALL;
491 	if (if_getcapenable(vsi->ifp) & IFCAP_VLAN_HWTAGGING)
492 		ctxt.info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_EMOD_STR_BOTH;
493 	else
494 		ctxt.info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_EMOD_NOTHING;
495 
496 #ifdef IXL_IW
497 	/* Set TCP Enable for iWARP capable VSI */
498 	if (ixl_enable_iwarp && pf->iw_enabled) {
499 		ctxt.info.valid_sections |=
500 		    htole16(I40E_AQ_VSI_PROP_QUEUE_OPT_VALID);
501 		ctxt.info.queueing_opt_flags |= I40E_AQ_VSI_QUE_OPT_TCP_ENA;
502 	}
503 #endif
504 	/* Save VSI number and info for use later */
505 	vsi->vsi_num = ctxt.vsi_number;
506 	bcopy(&ctxt.info, &vsi->info, sizeof(vsi->info));
507 
508 	ctxt.flags = htole16(I40E_AQ_VSI_TYPE_PF);
509 
510 	err = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
511 	if (err) {
512 		device_printf(dev, "i40e_aq_update_vsi_params() failed, error %d,"
513 		    " aq_error %d\n", err, hw->aq.asq_last_status);
514 		return (err);
515 	}
516 
517 	for (int i = 0; i < vsi->num_tx_queues; i++, tx_que++) {
518 		struct tx_ring		*txr = &tx_que->txr;
519 		struct i40e_hmc_obj_txq tctx;
520 		u32			txctl;
521 
522 		/* Setup the HMC TX Context  */
523 		bzero(&tctx, sizeof(tctx));
524 		tctx.new_context = 1;
525 		tctx.base = (txr->tx_paddr/IXL_TX_CTX_BASE_UNITS);
526 		tctx.qlen = scctx->isc_ntxd[0];
527 		tctx.fc_ena = 0;	/* Disable FCoE */
528 		/*
529 		 * This value needs to pulled from the VSI that this queue
530 		 * is assigned to. Index into array is traffic class.
531 		 */
532 		tctx.rdylist = vsi->info.qs_handle[0];
533 		/*
534 		 * Set these to enable Head Writeback
535 		 * - Address is last entry in TX ring (reserved for HWB index)
536 		 * Leave these as 0 for Descriptor Writeback
537 		 */
538 		if (vsi->enable_head_writeback) {
539 			tctx.head_wb_ena = 1;
540 			tctx.head_wb_addr = txr->tx_paddr +
541 			    (scctx->isc_ntxd[0] * sizeof(struct i40e_tx_desc));
542 		} else {
543 			tctx.head_wb_ena = 0;
544 			tctx.head_wb_addr = 0;
545 		}
546 		tctx.rdylist_act = 0;
547 		err = i40e_clear_lan_tx_queue_context(hw, i);
548 		if (err) {
549 			device_printf(dev, "Unable to clear TX context\n");
550 			break;
551 		}
552 		err = i40e_set_lan_tx_queue_context(hw, i, &tctx);
553 		if (err) {
554 			device_printf(dev, "Unable to set TX context\n");
555 			break;
556 		}
557 		/* Associate the ring with this PF */
558 		txctl = I40E_QTX_CTL_PF_QUEUE;
559 		txctl |= ((hw->pf_id << I40E_QTX_CTL_PF_INDX_SHIFT) &
560 		    I40E_QTX_CTL_PF_INDX_MASK);
561 		wr32(hw, I40E_QTX_CTL(i), txctl);
562 		ixl_flush(hw);
563 
564 		/* Do ring (re)init */
565 		ixl_init_tx_ring(vsi, tx_que);
566 	}
567 	for (int i = 0; i < vsi->num_rx_queues; i++, rx_que++) {
568 		struct rx_ring 		*rxr = &rx_que->rxr;
569 		struct i40e_hmc_obj_rxq rctx;
570 
571 		/* Next setup the HMC RX Context  */
572 		rxr->mbuf_sz = iflib_get_rx_mbuf_sz(vsi->ctx);
573 
574 		u16 max_rxmax = rxr->mbuf_sz * hw->func_caps.rx_buf_chain_len;
575 
576 		/* Set up an RX context for the HMC */
577 		memset(&rctx, 0, sizeof(struct i40e_hmc_obj_rxq));
578 		rctx.dbuff = rxr->mbuf_sz >> I40E_RXQ_CTX_DBUFF_SHIFT;
579 		/* ignore header split for now */
580 		rctx.hbuff = 0 >> I40E_RXQ_CTX_HBUFF_SHIFT;
581 		rctx.rxmax = (scctx->isc_max_frame_size < max_rxmax) ?
582 		    scctx->isc_max_frame_size : max_rxmax;
583 		rctx.dtype = 0;
584 		rctx.dsize = 1;		/* do 32byte descriptors */
585 		rctx.hsplit_0 = 0;	/* no header split */
586 		rctx.base = (rxr->rx_paddr/IXL_RX_CTX_BASE_UNITS);
587 		rctx.qlen = scctx->isc_nrxd[0];
588 		rctx.tphrdesc_ena = 1;
589 		rctx.tphwdesc_ena = 1;
590 		rctx.tphdata_ena = 0;	/* Header Split related */
591 		rctx.tphhead_ena = 0;	/* Header Split related */
592 		rctx.lrxqthresh = 1;	/* Interrupt at <64 desc avail */
593 		rctx.crcstrip = 1;
594 		rctx.l2tsel = 1;
595 		rctx.showiv = 1;	/* Strip inner VLAN header */
596 		rctx.fc_ena = 0;	/* Disable FCoE */
597 		rctx.prefena = 1;	/* Prefetch descriptors */
598 
599 		err = i40e_clear_lan_rx_queue_context(hw, i);
600 		if (err) {
601 			device_printf(dev,
602 			    "Unable to clear RX context %d\n", i);
603 			break;
604 		}
605 		err = i40e_set_lan_rx_queue_context(hw, i, &rctx);
606 		if (err) {
607 			device_printf(dev, "Unable to set RX context %d\n", i);
608 			break;
609 		}
610 		wr32(vsi->hw, I40E_QRX_TAIL(i), 0);
611 	}
612 	return (err);
613 }
614 
615 
616 /*
617 ** Provide a update to the queue RX
618 ** interrupt moderation value.
619 */
620 void
621 ixl_set_queue_rx_itr(struct ixl_rx_queue *que)
622 {
623 	struct ixl_vsi	*vsi = que->vsi;
624 	struct ixl_pf	*pf = (struct ixl_pf *)vsi->back;
625 	struct i40e_hw	*hw = vsi->hw;
626 	struct rx_ring	*rxr = &que->rxr;
627 	u16		rx_itr;
628 	u16		rx_latency = 0;
629 	int		rx_bytes;
630 
631 	/* Idle, do nothing */
632 	if (rxr->bytes == 0)
633 		return;
634 
635 	if (pf->dynamic_rx_itr) {
636 		rx_bytes = rxr->bytes/rxr->itr;
637 		rx_itr = rxr->itr;
638 
639 		/* Adjust latency range */
640 		switch (rxr->latency) {
641 		case IXL_LOW_LATENCY:
642 			if (rx_bytes > 10) {
643 				rx_latency = IXL_AVE_LATENCY;
644 				rx_itr = IXL_ITR_20K;
645 			}
646 			break;
647 		case IXL_AVE_LATENCY:
648 			if (rx_bytes > 20) {
649 				rx_latency = IXL_BULK_LATENCY;
650 				rx_itr = IXL_ITR_8K;
651 			} else if (rx_bytes <= 10) {
652 				rx_latency = IXL_LOW_LATENCY;
653 				rx_itr = IXL_ITR_100K;
654 			}
655 			break;
656 		case IXL_BULK_LATENCY:
657 			if (rx_bytes <= 20) {
658 				rx_latency = IXL_AVE_LATENCY;
659 				rx_itr = IXL_ITR_20K;
660 			}
661 			break;
662 		}
663 
664 		rxr->latency = rx_latency;
665 
666 		if (rx_itr != rxr->itr) {
667 			/* do an exponential smoothing */
668 			rx_itr = (10 * rx_itr * rxr->itr) /
669 			    ((9 * rx_itr) + rxr->itr);
670 			rxr->itr = min(rx_itr, IXL_MAX_ITR);
671 			wr32(hw, I40E_PFINT_ITRN(IXL_RX_ITR,
672 			    rxr->me), rxr->itr);
673 		}
674 	} else { /* We may have have toggled to non-dynamic */
675 		if (vsi->rx_itr_setting & IXL_ITR_DYNAMIC)
676 			vsi->rx_itr_setting = pf->rx_itr;
677 		/* Update the hardware if needed */
678 		if (rxr->itr != vsi->rx_itr_setting) {
679 			rxr->itr = vsi->rx_itr_setting;
680 			wr32(hw, I40E_PFINT_ITRN(IXL_RX_ITR,
681 			    rxr->me), rxr->itr);
682 		}
683 	}
684 	rxr->bytes = 0;
685 	rxr->packets = 0;
686 }
687 
688 
689 /*
690 ** Provide a update to the queue TX
691 ** interrupt moderation value.
692 */
693 void
694 ixl_set_queue_tx_itr(struct ixl_tx_queue *que)
695 {
696 	struct ixl_vsi	*vsi = que->vsi;
697 	struct ixl_pf	*pf = (struct ixl_pf *)vsi->back;
698 	struct i40e_hw	*hw = vsi->hw;
699 	struct tx_ring	*txr = &que->txr;
700 	u16		tx_itr;
701 	u16		tx_latency = 0;
702 	int		tx_bytes;
703 
704 
705 	/* Idle, do nothing */
706 	if (txr->bytes == 0)
707 		return;
708 
709 	if (pf->dynamic_tx_itr) {
710 		tx_bytes = txr->bytes/txr->itr;
711 		tx_itr = txr->itr;
712 
713 		switch (txr->latency) {
714 		case IXL_LOW_LATENCY:
715 			if (tx_bytes > 10) {
716 				tx_latency = IXL_AVE_LATENCY;
717 				tx_itr = IXL_ITR_20K;
718 			}
719 			break;
720 		case IXL_AVE_LATENCY:
721 			if (tx_bytes > 20) {
722 				tx_latency = IXL_BULK_LATENCY;
723 				tx_itr = IXL_ITR_8K;
724 			} else if (tx_bytes <= 10) {
725 				tx_latency = IXL_LOW_LATENCY;
726 				tx_itr = IXL_ITR_100K;
727 			}
728 			break;
729 		case IXL_BULK_LATENCY:
730 			if (tx_bytes <= 20) {
731 				tx_latency = IXL_AVE_LATENCY;
732 				tx_itr = IXL_ITR_20K;
733 			}
734 			break;
735 		}
736 
737 		txr->latency = tx_latency;
738 
739 		if (tx_itr != txr->itr) {
740 			/* do an exponential smoothing */
741 			tx_itr = (10 * tx_itr * txr->itr) /
742 			    ((9 * tx_itr) + txr->itr);
743 			txr->itr = min(tx_itr, IXL_MAX_ITR);
744 			wr32(hw, I40E_PFINT_ITRN(IXL_TX_ITR,
745 			    txr->me), txr->itr);
746 		}
747 
748 	} else { /* We may have have toggled to non-dynamic */
749 		if (vsi->tx_itr_setting & IXL_ITR_DYNAMIC)
750 			vsi->tx_itr_setting = pf->tx_itr;
751 		/* Update the hardware if needed */
752 		if (txr->itr != vsi->tx_itr_setting) {
753 			txr->itr = vsi->tx_itr_setting;
754 			wr32(hw, I40E_PFINT_ITRN(IXL_TX_ITR,
755 			    txr->me), txr->itr);
756 		}
757 	}
758 	txr->bytes = 0;
759 	txr->packets = 0;
760 	return;
761 }
762 
763 #ifdef IXL_DEBUG
764 /**
765  * ixl_sysctl_qtx_tail_handler
766  * Retrieves I40E_QTX_TAIL value from hardware
767  * for a sysctl.
768  */
769 int
770 ixl_sysctl_qtx_tail_handler(SYSCTL_HANDLER_ARGS)
771 {
772 	struct ixl_tx_queue *tx_que;
773 	int error;
774 	u32 val;
775 
776 	tx_que = ((struct ixl_tx_queue *)oidp->oid_arg1);
777 	if (!tx_que) return 0;
778 
779 	val = rd32(tx_que->vsi->hw, tx_que->txr.tail);
780 	error = sysctl_handle_int(oidp, &val, 0, req);
781 	if (error || !req->newptr)
782 		return error;
783 	return (0);
784 }
785 
786 /**
787  * ixl_sysctl_qrx_tail_handler
788  * Retrieves I40E_QRX_TAIL value from hardware
789  * for a sysctl.
790  */
791 int
792 ixl_sysctl_qrx_tail_handler(SYSCTL_HANDLER_ARGS)
793 {
794 	struct ixl_rx_queue *rx_que;
795 	int error;
796 	u32 val;
797 
798 	rx_que = ((struct ixl_rx_queue *)oidp->oid_arg1);
799 	if (!rx_que) return 0;
800 
801 	val = rd32(rx_que->vsi->hw, rx_que->rxr.tail);
802 	error = sysctl_handle_int(oidp, &val, 0, req);
803 	if (error || !req->newptr)
804 		return error;
805 	return (0);
806 }
807 #endif
808 
809 void
810 ixl_add_hw_stats(struct ixl_pf *pf)
811 {
812 	struct ixl_vsi *vsi = &pf->vsi;
813 	device_t dev = iflib_get_dev(vsi->ctx);
814 	struct i40e_hw_port_stats *pf_stats = &pf->stats;
815 
816 	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev);
817 	struct sysctl_oid *tree = device_get_sysctl_tree(dev);
818 	struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
819 
820 	/* Driver statistics */
821 	SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "admin_irq",
822 			CTLFLAG_RD, &pf->admin_irq,
823 			"Admin Queue IRQs received");
824 
825 	sysctl_ctx_init(&vsi->sysctl_ctx);
826 	ixl_vsi_add_sysctls(vsi, "pf", true);
827 
828 	ixl_add_sysctls_mac_stats(ctx, child, pf_stats);
829 }
830 
831 void
832 ixl_set_rss_hlut(struct ixl_pf *pf)
833 {
834 	struct i40e_hw	*hw = &pf->hw;
835 	struct ixl_vsi *vsi = &pf->vsi;
836 	device_t	dev = iflib_get_dev(vsi->ctx);
837 	int		i, que_id;
838 	int		lut_entry_width;
839 	u32		lut = 0;
840 	enum i40e_status_code status;
841 
842 	lut_entry_width = pf->hw.func_caps.rss_table_entry_width;
843 
844 	/* Populate the LUT with max no. of queues in round robin fashion */
845 	u8 hlut_buf[512];
846 	for (i = 0; i < pf->hw.func_caps.rss_table_size; i++) {
847 #ifdef RSS
848 		/*
849 		 * Fetch the RSS bucket id for the given indirection entry.
850 		 * Cap it at the number of configured buckets (which is
851 		 * num_queues.)
852 		 */
853 		que_id = rss_get_indirection_to_bucket(i);
854 		que_id = que_id % vsi->num_rx_queues;
855 #else
856 		que_id = i % vsi->num_rx_queues;
857 #endif
858 		lut = (que_id & ((0x1 << lut_entry_width) - 1));
859 		hlut_buf[i] = lut;
860 	}
861 
862 	if (hw->mac.type == I40E_MAC_X722) {
863 		status = i40e_aq_set_rss_lut(hw, vsi->vsi_num, TRUE, hlut_buf, sizeof(hlut_buf));
864 		if (status)
865 			device_printf(dev, "i40e_aq_set_rss_lut status %s, error %s\n",
866 			    i40e_stat_str(hw, status), i40e_aq_str(hw, hw->aq.asq_last_status));
867 	} else {
868 		for (i = 0; i < pf->hw.func_caps.rss_table_size >> 2; i++)
869 			wr32(hw, I40E_PFQF_HLUT(i), ((u32 *)hlut_buf)[i]);
870 		ixl_flush(hw);
871 	}
872 }
873 
874 /* For PF VSI only */
875 int
876 ixl_enable_rings(struct ixl_vsi *vsi)
877 {
878 	struct ixl_pf	*pf = vsi->back;
879 	int		error = 0;
880 
881 	for (int i = 0; i < vsi->num_tx_queues; i++)
882 		error = ixl_enable_tx_ring(pf, &pf->qtag, i);
883 
884 	for (int i = 0; i < vsi->num_rx_queues; i++)
885 		error = ixl_enable_rx_ring(pf, &pf->qtag, i);
886 
887 	return (error);
888 }
889 
890 int
891 ixl_disable_rings(struct ixl_pf *pf, struct ixl_vsi *vsi, struct ixl_pf_qtag *qtag)
892 {
893 	int error = 0;
894 
895 	for (int i = 0; i < vsi->num_tx_queues; i++)
896 		error = ixl_disable_tx_ring(pf, qtag, i);
897 
898 	for (int i = 0; i < vsi->num_rx_queues; i++)
899 		error = ixl_disable_rx_ring(pf, qtag, i);
900 
901 	return (error);
902 }
903 
904 void
905 ixl_enable_intr(struct ixl_vsi *vsi)
906 {
907 	struct i40e_hw		*hw = vsi->hw;
908 	struct ixl_rx_queue	*que = vsi->rx_queues;
909 
910 	if (vsi->shared->isc_intr == IFLIB_INTR_MSIX) {
911 		for (int i = 0; i < vsi->num_rx_queues; i++, que++)
912 			ixl_enable_queue(hw, que->rxr.me);
913 	} else
914 		ixl_enable_intr0(hw);
915 }
916 
917 void
918 ixl_disable_rings_intr(struct ixl_vsi *vsi)
919 {
920 	struct i40e_hw		*hw = vsi->hw;
921 	struct ixl_rx_queue	*que = vsi->rx_queues;
922 
923 	for (int i = 0; i < vsi->num_rx_queues; i++, que++)
924 		ixl_disable_queue(hw, que->rxr.me);
925 }
926 
927 int
928 ixl_prepare_for_reset(struct ixl_pf *pf, bool is_up)
929 {
930 	struct i40e_hw *hw = &pf->hw;
931 	device_t dev = pf->dev;
932 	int error = 0;
933 
934 	if (is_up)
935 		ixl_if_stop(pf->vsi.ctx);
936 
937 	ixl_shutdown_hmc(pf);
938 
939 	ixl_disable_intr0(hw);
940 
941 	error = i40e_shutdown_adminq(hw);
942 	if (error)
943 		device_printf(dev,
944 		    "Shutdown Admin queue failed with code %d\n", error);
945 
946 	ixl_pf_qmgr_release(&pf->qmgr, &pf->qtag);
947 	return (error);
948 }
949 
950 int
951 ixl_rebuild_hw_structs_after_reset(struct ixl_pf *pf, bool is_up)
952 {
953 	struct i40e_hw *hw = &pf->hw;
954 	struct ixl_vsi *vsi = &pf->vsi;
955 	device_t dev = pf->dev;
956 	enum i40e_get_fw_lldp_status_resp lldp_status;
957 	int error = 0;
958 
959 	device_printf(dev, "Rebuilding driver state...\n");
960 
961 	/* Setup */
962 	error = i40e_init_adminq(hw);
963 	if (error != 0 && error != I40E_ERR_FIRMWARE_API_VERSION) {
964 		device_printf(dev, "Unable to initialize Admin Queue, error %d\n",
965 		    error);
966 		goto ixl_rebuild_hw_structs_after_reset_err;
967 	}
968 
969 	if (IXL_PF_IN_RECOVERY_MODE(pf)) {
970 		/* Keep admin queue interrupts active while driver is loaded */
971 		if (vsi->shared->isc_intr == IFLIB_INTR_MSIX) {
972 			ixl_configure_intr0_msix(pf);
973 			ixl_enable_intr0(hw);
974 		}
975 
976 		return (0);
977 	}
978 
979 	i40e_clear_pxe_mode(hw);
980 
981 	error = ixl_get_hw_capabilities(pf);
982 	if (error) {
983 		device_printf(dev, "ixl_get_hw_capabilities failed: %d\n", error);
984 		goto ixl_rebuild_hw_structs_after_reset_err;
985 	}
986 
987 	error = ixl_setup_hmc(pf);
988 	if (error)
989 		goto ixl_rebuild_hw_structs_after_reset_err;
990 
991 	/* reserve a contiguous allocation for the PF's VSI */
992 	error = ixl_pf_qmgr_alloc_contiguous(&pf->qmgr, vsi->num_tx_queues, &pf->qtag);
993 	if (error) {
994 		device_printf(dev, "Failed to reserve queues for PF LAN VSI, error %d\n",
995 		    error);
996 	}
997 
998 	error = ixl_switch_config(pf);
999 	if (error) {
1000 		device_printf(dev, "ixl_rebuild_hw_structs_after_reset: ixl_switch_config() failed: %d\n",
1001 		     error);
1002 		error = EIO;
1003 		goto ixl_rebuild_hw_structs_after_reset_err;
1004 	}
1005 
1006 	error = i40e_aq_set_phy_int_mask(hw, IXL_DEFAULT_PHY_INT_MASK,
1007 	    NULL);
1008 	if (error) {
1009 		device_printf(dev, "init: i40e_aq_set_phy_mask() failed: err %d,"
1010 		    " aq_err %d\n", error, hw->aq.asq_last_status);
1011 		error = EIO;
1012 		goto ixl_rebuild_hw_structs_after_reset_err;
1013 	}
1014 
1015 	u8 set_fc_err_mask;
1016 	error = i40e_set_fc(hw, &set_fc_err_mask, true);
1017 	if (error) {
1018 		device_printf(dev, "init: setting link flow control failed; retcode %d,"
1019 		    " fc_err_mask 0x%02x\n", error, set_fc_err_mask);
1020 		error = EIO;
1021 		goto ixl_rebuild_hw_structs_after_reset_err;
1022 	}
1023 
1024 	/* Remove default filters reinstalled by FW on reset */
1025 	ixl_del_default_hw_filters(vsi);
1026 
1027 	/* Receive broadcast Ethernet frames */
1028 	i40e_aq_set_vsi_broadcast(&pf->hw, vsi->seid, TRUE, NULL);
1029 
1030 	/* Determine link state */
1031 	if (ixl_attach_get_link_status(pf)) {
1032 		error = EINVAL;
1033 	}
1034 
1035 	i40e_aq_set_dcb_parameters(hw, TRUE, NULL);
1036 
1037 	/* Query device FW LLDP status */
1038 	if (i40e_get_fw_lldp_status(hw, &lldp_status) == I40E_SUCCESS) {
1039 		if (lldp_status == I40E_GET_FW_LLDP_STATUS_DISABLED) {
1040 			atomic_set_32(&pf->state,
1041 			    IXL_PF_STATE_FW_LLDP_DISABLED);
1042 		} else {
1043 			atomic_clear_32(&pf->state,
1044 			    IXL_PF_STATE_FW_LLDP_DISABLED);
1045 		}
1046 	}
1047 
1048 	/* Keep admin queue interrupts active while driver is loaded */
1049 	if (vsi->shared->isc_intr == IFLIB_INTR_MSIX) {
1050 		ixl_configure_intr0_msix(pf);
1051 		ixl_enable_intr0(hw);
1052 	}
1053 
1054 	if (is_up) {
1055 		iflib_request_reset(vsi->ctx);
1056 		iflib_admin_intr_deferred(vsi->ctx);
1057 	}
1058 
1059 	device_printf(dev, "Rebuilding driver state done.\n");
1060 	return (0);
1061 
1062 ixl_rebuild_hw_structs_after_reset_err:
1063 	device_printf(dev, "Reload the driver to recover\n");
1064 	return (error);
1065 }
1066 
1067 /*
1068 ** Set flow control using sysctl:
1069 ** 	0 - off
1070 **	1 - rx pause
1071 **	2 - tx pause
1072 **	3 - full
1073 */
1074 int
1075 ixl_sysctl_set_flowcntl(SYSCTL_HANDLER_ARGS)
1076 {
1077 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
1078 	struct i40e_hw *hw = &pf->hw;
1079 	device_t dev = pf->dev;
1080 	int requested_fc, error = 0;
1081 	enum i40e_status_code aq_error = 0;
1082 	u8 fc_aq_err = 0;
1083 
1084 	/* Get request */
1085 	requested_fc = pf->fc;
1086 	error = sysctl_handle_int(oidp, &requested_fc, 0, req);
1087 	if ((error) || (req->newptr == NULL))
1088 		return (error);
1089 	if (requested_fc < 0 || requested_fc > 3) {
1090 		device_printf(dev,
1091 		    "Invalid fc mode; valid modes are 0 through 3\n");
1092 		return (EINVAL);
1093 	}
1094 
1095 	/* Set fc ability for port */
1096 	hw->fc.requested_mode = requested_fc;
1097 	aq_error = i40e_set_fc(hw, &fc_aq_err, TRUE);
1098 	if (aq_error) {
1099 		device_printf(dev,
1100 		    "%s: Error setting Flow Control mode %d; fc_err %#x\n",
1101 		    __func__, aq_error, fc_aq_err);
1102 		return (EIO);
1103 	}
1104 	pf->fc = requested_fc;
1105 
1106 	return (0);
1107 }
1108