1ae06c70bSJeff Kirsher // SPDX-License-Identifier: GPL-2.0
2d5c2f395SJacob Keller /* Copyright(c) 2013 - 2019 Intel Corporation. */
3b6fec18fSAlexander Duyck 
4e383353bSJesse Brandeburg #include <linux/bitfield.h>
5b6fec18fSAlexander Duyck #include "fm10k_pf.h"
6c2653865SAlexander Duyck #include "fm10k_vf.h"
7b6fec18fSAlexander Duyck 
8b6fec18fSAlexander Duyck /**
9b6fec18fSAlexander Duyck  *  fm10k_reset_hw_pf - PF hardware reset
10b6fec18fSAlexander Duyck  *  @hw: pointer to hardware structure
11b6fec18fSAlexander Duyck  *
12b6fec18fSAlexander Duyck  *  This function should return the hardware to a state similar to the
13b6fec18fSAlexander Duyck  *  one it is in after being powered on.
14b6fec18fSAlexander Duyck  **/
fm10k_reset_hw_pf(struct fm10k_hw * hw)15b6fec18fSAlexander Duyck static s32 fm10k_reset_hw_pf(struct fm10k_hw *hw)
16b6fec18fSAlexander Duyck {
17b6fec18fSAlexander Duyck 	s32 err;
18b6fec18fSAlexander Duyck 	u32 reg;
19b6fec18fSAlexander Duyck 	u16 i;
20b6fec18fSAlexander Duyck 
21b6fec18fSAlexander Duyck 	/* Disable interrupts */
22b6fec18fSAlexander Duyck 	fm10k_write_reg(hw, FM10K_EIMR, FM10K_EIMR_DISABLE(ALL));
23b6fec18fSAlexander Duyck 
24b6fec18fSAlexander Duyck 	/* Lock ITR2 reg 0 into itself and disable interrupt moderation */
25b6fec18fSAlexander Duyck 	fm10k_write_reg(hw, FM10K_ITR2(0), 0);
26b6fec18fSAlexander Duyck 	fm10k_write_reg(hw, FM10K_INT_CTRL, 0);
27b6fec18fSAlexander Duyck 
28b6fec18fSAlexander Duyck 	/* We assume here Tx and Rx queue 0 are owned by the PF */
29b6fec18fSAlexander Duyck 
30b6fec18fSAlexander Duyck 	/* Shut off VF access to their queues forcing them to queue 0 */
31b6fec18fSAlexander Duyck 	for (i = 0; i < FM10K_TQMAP_TABLE_SIZE; i++) {
32b6fec18fSAlexander Duyck 		fm10k_write_reg(hw, FM10K_TQMAP(i), 0);
33b6fec18fSAlexander Duyck 		fm10k_write_reg(hw, FM10K_RQMAP(i), 0);
34b6fec18fSAlexander Duyck 	}
35b6fec18fSAlexander Duyck 
36b6fec18fSAlexander Duyck 	/* shut down all rings */
37b6fec18fSAlexander Duyck 	err = fm10k_disable_queues_generic(hw, FM10K_MAX_QUEUES);
38ce33624fSJacob Keller 	if (err == FM10K_ERR_REQUESTS_PENDING) {
39ce33624fSJacob Keller 		hw->mac.reset_while_pending++;
40ce33624fSJacob Keller 		goto force_reset;
41ce33624fSJacob Keller 	} else if (err) {
42b6fec18fSAlexander Duyck 		return err;
43ce33624fSJacob Keller 	}
44b6fec18fSAlexander Duyck 
45b6fec18fSAlexander Duyck 	/* Verify that DMA is no longer active */
46b6fec18fSAlexander Duyck 	reg = fm10k_read_reg(hw, FM10K_DMA_CTRL);
47b6fec18fSAlexander Duyck 	if (reg & (FM10K_DMA_CTRL_TX_ACTIVE | FM10K_DMA_CTRL_RX_ACTIVE))
48b6fec18fSAlexander Duyck 		return FM10K_ERR_DMA_PENDING;
49b6fec18fSAlexander Duyck 
50ce33624fSJacob Keller force_reset:
51b6fec18fSAlexander Duyck 	/* Inititate data path reset */
52ce33624fSJacob Keller 	reg = FM10K_DMA_CTRL_DATAPATH_RESET;
53b6fec18fSAlexander Duyck 	fm10k_write_reg(hw, FM10K_DMA_CTRL, reg);
54b6fec18fSAlexander Duyck 
55b6fec18fSAlexander Duyck 	/* Flush write and allow 100us for reset to complete */
56b6fec18fSAlexander Duyck 	fm10k_write_flush(hw);
57b6fec18fSAlexander Duyck 	udelay(FM10K_RESET_TIMEOUT);
58b6fec18fSAlexander Duyck 
59ce33624fSJacob Keller 	/* Verify we made it out of reset */
60ce33624fSJacob Keller 	reg = fm10k_read_reg(hw, FM10K_IP);
61ce33624fSJacob Keller 	if (!(reg & FM10K_IP_NOTINRESET))
62ce33624fSJacob Keller 		return FM10K_ERR_RESET_FAILED;
63ce33624fSJacob Keller 
64ce33624fSJacob Keller 	return 0;
65b6fec18fSAlexander Duyck }
66b6fec18fSAlexander Duyck 
67b6fec18fSAlexander Duyck /**
68c2653865SAlexander Duyck  *  fm10k_is_ari_hierarchy_pf - Indicate ARI hierarchy support
69c2653865SAlexander Duyck  *  @hw: pointer to hardware structure
70c2653865SAlexander Duyck  *
71c2653865SAlexander Duyck  *  Looks at the ARI hierarchy bit to determine whether ARI is supported or not.
72c2653865SAlexander Duyck  **/
fm10k_is_ari_hierarchy_pf(struct fm10k_hw * hw)73c2653865SAlexander Duyck static bool fm10k_is_ari_hierarchy_pf(struct fm10k_hw *hw)
74c2653865SAlexander Duyck {
75c2653865SAlexander Duyck 	u16 sriov_ctrl = fm10k_read_pci_cfg_word(hw, FM10K_PCIE_SRIOV_CTRL);
76c2653865SAlexander Duyck 
77c2653865SAlexander Duyck 	return !!(sriov_ctrl & FM10K_PCIE_SRIOV_CTRL_VFARI);
78c2653865SAlexander Duyck }
79c2653865SAlexander Duyck 
80c2653865SAlexander Duyck /**
81b6fec18fSAlexander Duyck  *  fm10k_init_hw_pf - PF hardware initialization
82b6fec18fSAlexander Duyck  *  @hw: pointer to hardware structure
83b6fec18fSAlexander Duyck  *
84b6fec18fSAlexander Duyck  **/
fm10k_init_hw_pf(struct fm10k_hw * hw)85b6fec18fSAlexander Duyck static s32 fm10k_init_hw_pf(struct fm10k_hw *hw)
86b6fec18fSAlexander Duyck {
87b6fec18fSAlexander Duyck 	u32 dma_ctrl, txqctl;
88b6fec18fSAlexander Duyck 	u16 i;
89b6fec18fSAlexander Duyck 
90b6fec18fSAlexander Duyck 	/* Establish default VSI as valid */
91b6fec18fSAlexander Duyck 	fm10k_write_reg(hw, FM10K_DGLORTDEC(fm10k_dglort_default), 0);
92b6fec18fSAlexander Duyck 	fm10k_write_reg(hw, FM10K_DGLORTMAP(fm10k_dglort_default),
93b6fec18fSAlexander Duyck 			FM10K_DGLORTMAP_ANY);
94b6fec18fSAlexander Duyck 
95b6fec18fSAlexander Duyck 	/* Invalidate all other GLORT entries */
96b6fec18fSAlexander Duyck 	for (i = 1; i < FM10K_DGLORT_COUNT; i++)
97b6fec18fSAlexander Duyck 		fm10k_write_reg(hw, FM10K_DGLORTMAP(i), FM10K_DGLORTMAP_NONE);
98b6fec18fSAlexander Duyck 
99b6fec18fSAlexander Duyck 	/* reset ITR2(0) to point to itself */
100b6fec18fSAlexander Duyck 	fm10k_write_reg(hw, FM10K_ITR2(0), 0);
101b6fec18fSAlexander Duyck 
102b6fec18fSAlexander Duyck 	/* reset VF ITR2(0) to point to 0 avoid PF registers */
103b6fec18fSAlexander Duyck 	fm10k_write_reg(hw, FM10K_ITR2(FM10K_ITR_REG_COUNT_PF), 0);
104b6fec18fSAlexander Duyck 
105b6fec18fSAlexander Duyck 	/* loop through all PF ITR2 registers pointing them to the previous */
106b6fec18fSAlexander Duyck 	for (i = 1; i < FM10K_ITR_REG_COUNT_PF; i++)
107b6fec18fSAlexander Duyck 		fm10k_write_reg(hw, FM10K_ITR2(i), i - 1);
108b6fec18fSAlexander Duyck 
109b6fec18fSAlexander Duyck 	/* Enable interrupt moderator if not already enabled */
110b6fec18fSAlexander Duyck 	fm10k_write_reg(hw, FM10K_INT_CTRL, FM10K_INT_CTRL_ENABLEMODERATOR);
111b6fec18fSAlexander Duyck 
112b6fec18fSAlexander Duyck 	/* compute the default txqctl configuration */
113b6fec18fSAlexander Duyck 	txqctl = FM10K_TXQCTL_PF | FM10K_TXQCTL_UNLIMITED_BW |
114b6fec18fSAlexander Duyck 		 (hw->mac.default_vid << FM10K_TXQCTL_VID_SHIFT);
115b6fec18fSAlexander Duyck 
116b6fec18fSAlexander Duyck 	for (i = 0; i < FM10K_MAX_QUEUES; i++) {
117b6fec18fSAlexander Duyck 		/* configure rings for 256 Queue / 32 Descriptor cache mode */
118b6fec18fSAlexander Duyck 		fm10k_write_reg(hw, FM10K_TQDLOC(i),
119b6fec18fSAlexander Duyck 				(i * FM10K_TQDLOC_BASE_32_DESC) |
120b6fec18fSAlexander Duyck 				FM10K_TQDLOC_SIZE_32_DESC);
121b6fec18fSAlexander Duyck 		fm10k_write_reg(hw, FM10K_TXQCTL(i), txqctl);
122b6fec18fSAlexander Duyck 
123b6fec18fSAlexander Duyck 		/* configure rings to provide TPH processing hints */
124b6fec18fSAlexander Duyck 		fm10k_write_reg(hw, FM10K_TPH_TXCTRL(i),
125b6fec18fSAlexander Duyck 				FM10K_TPH_TXCTRL_DESC_TPHEN |
126b6fec18fSAlexander Duyck 				FM10K_TPH_TXCTRL_DESC_RROEN |
127b6fec18fSAlexander Duyck 				FM10K_TPH_TXCTRL_DESC_WROEN |
128b6fec18fSAlexander Duyck 				FM10K_TPH_TXCTRL_DATA_RROEN);
129b6fec18fSAlexander Duyck 		fm10k_write_reg(hw, FM10K_TPH_RXCTRL(i),
130b6fec18fSAlexander Duyck 				FM10K_TPH_RXCTRL_DESC_TPHEN |
131b6fec18fSAlexander Duyck 				FM10K_TPH_RXCTRL_DESC_RROEN |
132b6fec18fSAlexander Duyck 				FM10K_TPH_RXCTRL_DATA_WROEN |
133b6fec18fSAlexander Duyck 				FM10K_TPH_RXCTRL_HDR_WROEN);
134b6fec18fSAlexander Duyck 	}
135b6fec18fSAlexander Duyck 
13620076fa1SJacob Keller 	/* set max hold interval to align with 1.024 usec in all modes and
13720076fa1SJacob Keller 	 * store ITR scale
13820076fa1SJacob Keller 	 */
139b6fec18fSAlexander Duyck 	switch (hw->bus.speed) {
140b6fec18fSAlexander Duyck 	case fm10k_bus_speed_2500:
141b6fec18fSAlexander Duyck 		dma_ctrl = FM10K_DMA_CTRL_MAX_HOLD_1US_GEN1;
14220076fa1SJacob Keller 		hw->mac.itr_scale = FM10K_TDLEN_ITR_SCALE_GEN1;
143b6fec18fSAlexander Duyck 		break;
144b6fec18fSAlexander Duyck 	case fm10k_bus_speed_5000:
145b6fec18fSAlexander Duyck 		dma_ctrl = FM10K_DMA_CTRL_MAX_HOLD_1US_GEN2;
14620076fa1SJacob Keller 		hw->mac.itr_scale = FM10K_TDLEN_ITR_SCALE_GEN2;
147b6fec18fSAlexander Duyck 		break;
148b6fec18fSAlexander Duyck 	case fm10k_bus_speed_8000:
149b6fec18fSAlexander Duyck 		dma_ctrl = FM10K_DMA_CTRL_MAX_HOLD_1US_GEN3;
15020076fa1SJacob Keller 		hw->mac.itr_scale = FM10K_TDLEN_ITR_SCALE_GEN3;
151b6fec18fSAlexander Duyck 		break;
152b6fec18fSAlexander Duyck 	default:
153b6fec18fSAlexander Duyck 		dma_ctrl = 0;
15420076fa1SJacob Keller 		/* just in case, assume Gen3 ITR scale */
15520076fa1SJacob Keller 		hw->mac.itr_scale = FM10K_TDLEN_ITR_SCALE_GEN3;
156b6fec18fSAlexander Duyck 		break;
157b6fec18fSAlexander Duyck 	}
158b6fec18fSAlexander Duyck 
159b6fec18fSAlexander Duyck 	/* Configure TSO flags */
160b6fec18fSAlexander Duyck 	fm10k_write_reg(hw, FM10K_DTXTCPFLGL, FM10K_TSO_FLAGS_LOW);
161b6fec18fSAlexander Duyck 	fm10k_write_reg(hw, FM10K_DTXTCPFLGH, FM10K_TSO_FLAGS_HI);
162b6fec18fSAlexander Duyck 
163b6fec18fSAlexander Duyck 	/* Enable DMA engine
164b6fec18fSAlexander Duyck 	 * Set Rx Descriptor size to 32
165b6fec18fSAlexander Duyck 	 * Set Minimum MSS to 64
166b6fec18fSAlexander Duyck 	 * Set Maximum number of Rx queues to 256 / 32 Descriptor
167b6fec18fSAlexander Duyck 	 */
168b6fec18fSAlexander Duyck 	dma_ctrl |= FM10K_DMA_CTRL_TX_ENABLE | FM10K_DMA_CTRL_RX_ENABLE |
169b6fec18fSAlexander Duyck 		    FM10K_DMA_CTRL_RX_DESC_SIZE | FM10K_DMA_CTRL_MINMSS_64 |
170b6fec18fSAlexander Duyck 		    FM10K_DMA_CTRL_32_DESC;
171b6fec18fSAlexander Duyck 
172b6fec18fSAlexander Duyck 	fm10k_write_reg(hw, FM10K_DMA_CTRL, dma_ctrl);
173b6fec18fSAlexander Duyck 
174b6fec18fSAlexander Duyck 	/* record maximum queue count, we limit ourselves to 128 */
175b6fec18fSAlexander Duyck 	hw->mac.max_queues = FM10K_MAX_QUEUES_PF;
176b6fec18fSAlexander Duyck 
177c2653865SAlexander Duyck 	/* We support either 64 VFs or 7 VFs depending on if we have ARI */
178c2653865SAlexander Duyck 	hw->iov.total_vfs = fm10k_is_ari_hierarchy_pf(hw) ? 64 : 7;
179c2653865SAlexander Duyck 
180b6fec18fSAlexander Duyck 	return 0;
181b6fec18fSAlexander Duyck }
182b6fec18fSAlexander Duyck 
183b6fec18fSAlexander Duyck /**
184401b5383SAlexander Duyck  *  fm10k_update_vlan_pf - Update status of VLAN ID in VLAN filter table
185401b5383SAlexander Duyck  *  @hw: pointer to hardware structure
186401b5383SAlexander Duyck  *  @vid: VLAN ID to add to table
187401b5383SAlexander Duyck  *  @vsi: Index indicating VF ID or PF ID in table
188401b5383SAlexander Duyck  *  @set: Indicates if this is a set or clear operation
189401b5383SAlexander Duyck  *
190401b5383SAlexander Duyck  *  This function adds or removes the corresponding VLAN ID from the VLAN
191401b5383SAlexander Duyck  *  filter table for the corresponding function.  In addition to the
192401b5383SAlexander Duyck  *  standard set/clear that supports one bit a multi-bit write is
193401b5383SAlexander Duyck  *  supported to set 64 bits at a time.
194401b5383SAlexander Duyck  **/
fm10k_update_vlan_pf(struct fm10k_hw * hw,u32 vid,u8 vsi,bool set)195401b5383SAlexander Duyck static s32 fm10k_update_vlan_pf(struct fm10k_hw *hw, u32 vid, u8 vsi, bool set)
196401b5383SAlexander Duyck {
197401b5383SAlexander Duyck 	u32 vlan_table, reg, mask, bit, len;
198401b5383SAlexander Duyck 
199401b5383SAlexander Duyck 	/* verify the VSI index is valid */
200401b5383SAlexander Duyck 	if (vsi > FM10K_VLAN_TABLE_VSI_MAX)
201401b5383SAlexander Duyck 		return FM10K_ERR_PARAM;
202401b5383SAlexander Duyck 
203401b5383SAlexander Duyck 	/* VLAN multi-bit write:
204401b5383SAlexander Duyck 	 * The multi-bit write has several parts to it.
205d057d9a9SJacob Keller 	 *               24              16               8               0
206d057d9a9SJacob Keller 	 *  7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
207401b5383SAlexander Duyck 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
208401b5383SAlexander Duyck 	 * | RSVD0 |         Length        |C|RSVD0|        VLAN ID        |
209401b5383SAlexander Duyck 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
210401b5383SAlexander Duyck 	 *
211401b5383SAlexander Duyck 	 * VLAN ID: Vlan Starting value
212401b5383SAlexander Duyck 	 * RSVD0: Reserved section, must be 0
213401b5383SAlexander Duyck 	 * C: Flag field, 0 is set, 1 is clear (Used in VF VLAN message)
214401b5383SAlexander Duyck 	 * Length: Number of times to repeat the bit being set
215401b5383SAlexander Duyck 	 */
216401b5383SAlexander Duyck 	len = vid >> 16;
217401b5383SAlexander Duyck 	vid = (vid << 17) >> 17;
218401b5383SAlexander Duyck 
219401b5383SAlexander Duyck 	/* verify the reserved 0 fields are 0 */
220eca32047SMatthew Vick 	if (len >= FM10K_VLAN_TABLE_VID_MAX || vid >= FM10K_VLAN_TABLE_VID_MAX)
221401b5383SAlexander Duyck 		return FM10K_ERR_PARAM;
222401b5383SAlexander Duyck 
223401b5383SAlexander Duyck 	/* Loop through the table updating all required VLANs */
224401b5383SAlexander Duyck 	for (reg = FM10K_VLAN_TABLE(vsi, vid / 32), bit = vid % 32;
225401b5383SAlexander Duyck 	     len < FM10K_VLAN_TABLE_VID_MAX;
226401b5383SAlexander Duyck 	     len -= 32 - bit, reg++, bit = 0) {
227401b5383SAlexander Duyck 		/* record the initial state of the register */
228401b5383SAlexander Duyck 		vlan_table = fm10k_read_reg(hw, reg);
229401b5383SAlexander Duyck 
230401b5383SAlexander Duyck 		/* truncate mask if we are at the start or end of the run */
231401b5383SAlexander Duyck 		mask = (~(u32)0 >> ((len < 31) ? 31 - len : 0)) << bit;
232401b5383SAlexander Duyck 
233401b5383SAlexander Duyck 		/* make necessary modifications to the register */
234401b5383SAlexander Duyck 		mask &= set ? ~vlan_table : vlan_table;
235401b5383SAlexander Duyck 		if (mask)
236401b5383SAlexander Duyck 			fm10k_write_reg(hw, reg, vlan_table ^ mask);
237401b5383SAlexander Duyck 	}
238401b5383SAlexander Duyck 
239401b5383SAlexander Duyck 	return 0;
240401b5383SAlexander Duyck }
241401b5383SAlexander Duyck 
242401b5383SAlexander Duyck /**
243b6fec18fSAlexander Duyck  *  fm10k_read_mac_addr_pf - Read device MAC address
244b6fec18fSAlexander Duyck  *  @hw: pointer to the HW structure
245b6fec18fSAlexander Duyck  *
246b6fec18fSAlexander Duyck  *  Reads the device MAC address from the SM_AREA and stores the value.
247b6fec18fSAlexander Duyck  **/
fm10k_read_mac_addr_pf(struct fm10k_hw * hw)248b6fec18fSAlexander Duyck static s32 fm10k_read_mac_addr_pf(struct fm10k_hw *hw)
249b6fec18fSAlexander Duyck {
250b6fec18fSAlexander Duyck 	u8 perm_addr[ETH_ALEN];
251b6fec18fSAlexander Duyck 	u32 serial_num;
252b6fec18fSAlexander Duyck 
253b6fec18fSAlexander Duyck 	serial_num = fm10k_read_reg(hw, FM10K_SM_AREA(1));
254b6fec18fSAlexander Duyck 
255b6fec18fSAlexander Duyck 	/* last byte should be all 1's */
256b6fec18fSAlexander Duyck 	if ((~serial_num) << 24)
257b6fec18fSAlexander Duyck 		return  FM10K_ERR_INVALID_MAC_ADDR;
258b6fec18fSAlexander Duyck 
259b6fec18fSAlexander Duyck 	perm_addr[0] = (u8)(serial_num >> 24);
260b6fec18fSAlexander Duyck 	perm_addr[1] = (u8)(serial_num >> 16);
261b6fec18fSAlexander Duyck 	perm_addr[2] = (u8)(serial_num >> 8);
262b6fec18fSAlexander Duyck 
263b6fec18fSAlexander Duyck 	serial_num = fm10k_read_reg(hw, FM10K_SM_AREA(0));
264b6fec18fSAlexander Duyck 
265b6fec18fSAlexander Duyck 	/* first byte should be all 1's */
266b6fec18fSAlexander Duyck 	if ((~serial_num) >> 24)
267b6fec18fSAlexander Duyck 		return  FM10K_ERR_INVALID_MAC_ADDR;
268b6fec18fSAlexander Duyck 
269b6fec18fSAlexander Duyck 	perm_addr[3] = (u8)(serial_num >> 16);
270b6fec18fSAlexander Duyck 	perm_addr[4] = (u8)(serial_num >> 8);
271b6fec18fSAlexander Duyck 	perm_addr[5] = (u8)(serial_num);
272b6fec18fSAlexander Duyck 
273f0cf5c98SJacob Keller 	ether_addr_copy(hw->mac.perm_addr, perm_addr);
274f0cf5c98SJacob Keller 	ether_addr_copy(hw->mac.addr, perm_addr);
275b6fec18fSAlexander Duyck 
276b6fec18fSAlexander Duyck 	return 0;
277b6fec18fSAlexander Duyck }
278b6fec18fSAlexander Duyck 
279b6fec18fSAlexander Duyck /**
280401b5383SAlexander Duyck  *  fm10k_glort_valid_pf - Validate that the provided glort is valid
281401b5383SAlexander Duyck  *  @hw: pointer to the HW structure
282401b5383SAlexander Duyck  *  @glort: base glort to be validated
283401b5383SAlexander Duyck  *
284401b5383SAlexander Duyck  *  This function will return an error if the provided glort is invalid
285401b5383SAlexander Duyck  **/
fm10k_glort_valid_pf(struct fm10k_hw * hw,u16 glort)286401b5383SAlexander Duyck bool fm10k_glort_valid_pf(struct fm10k_hw *hw, u16 glort)
287401b5383SAlexander Duyck {
288401b5383SAlexander Duyck 	glort &= hw->mac.dglort_map >> FM10K_DGLORTMAP_MASK_SHIFT;
289401b5383SAlexander Duyck 
290401b5383SAlexander Duyck 	return glort == (hw->mac.dglort_map & FM10K_DGLORTMAP_NONE);
291401b5383SAlexander Duyck }
292401b5383SAlexander Duyck 
293401b5383SAlexander Duyck /**
294eca32047SMatthew Vick  *  fm10k_update_xc_addr_pf - Update device addresses
295401b5383SAlexander Duyck  *  @hw: pointer to the HW structure
296401b5383SAlexander Duyck  *  @glort: base resource tag for this request
297401b5383SAlexander Duyck  *  @mac: MAC address to add/remove from table
298401b5383SAlexander Duyck  *  @vid: VLAN ID to add/remove from table
299401b5383SAlexander Duyck  *  @add: Indicates if this is an add or remove operation
300401b5383SAlexander Duyck  *  @flags: flags field to indicate add and secure
301401b5383SAlexander Duyck  *
302401b5383SAlexander Duyck  *  This function generates a message to the Switch API requesting
303401b5383SAlexander Duyck  *  that the given logical port add/remove the given L2 MAC/VLAN address.
304401b5383SAlexander Duyck  **/
fm10k_update_xc_addr_pf(struct fm10k_hw * hw,u16 glort,const u8 * mac,u16 vid,bool add,u8 flags)305401b5383SAlexander Duyck static s32 fm10k_update_xc_addr_pf(struct fm10k_hw *hw, u16 glort,
306401b5383SAlexander Duyck 				   const u8 *mac, u16 vid, bool add, u8 flags)
307401b5383SAlexander Duyck {
308401b5383SAlexander Duyck 	struct fm10k_mbx_info *mbx = &hw->mbx;
309401b5383SAlexander Duyck 	struct fm10k_mac_update mac_update;
310401b5383SAlexander Duyck 	u32 msg[5];
311401b5383SAlexander Duyck 
312b32d15b9SJeff Kirsher 	/* clear set bit from VLAN ID */
313b32d15b9SJeff Kirsher 	vid &= ~FM10K_VLAN_CLEAR;
314b32d15b9SJeff Kirsher 
315aa502b4aSJacob Keller 	/* if glort or VLAN are not valid return error */
31633a44c28SMatthew Vick 	if (!fm10k_glort_valid_pf(hw, glort) || vid >= FM10K_VLAN_TABLE_VID_MAX)
317401b5383SAlexander Duyck 		return FM10K_ERR_PARAM;
318401b5383SAlexander Duyck 
319401b5383SAlexander Duyck 	/* record fields */
320401b5383SAlexander Duyck 	mac_update.mac_lower = cpu_to_le32(((u32)mac[2] << 24) |
321401b5383SAlexander Duyck 						 ((u32)mac[3] << 16) |
322401b5383SAlexander Duyck 						 ((u32)mac[4] << 8) |
323401b5383SAlexander Duyck 						 ((u32)mac[5]));
3249d4955b4SJacob Keller 	mac_update.mac_upper = cpu_to_le16(((u16)mac[0] << 8) |
3259d4955b4SJacob Keller 					   ((u16)mac[1]));
326401b5383SAlexander Duyck 	mac_update.vlan = cpu_to_le16(vid);
327401b5383SAlexander Duyck 	mac_update.glort = cpu_to_le16(glort);
328401b5383SAlexander Duyck 	mac_update.action = add ? 0 : 1;
329401b5383SAlexander Duyck 	mac_update.flags = flags;
330401b5383SAlexander Duyck 
331401b5383SAlexander Duyck 	/* populate mac_update fields */
332401b5383SAlexander Duyck 	fm10k_tlv_msg_init(msg, FM10K_PF_MSG_ID_UPDATE_MAC_FWD_RULE);
333401b5383SAlexander Duyck 	fm10k_tlv_attr_put_le_struct(msg, FM10K_PF_ATTR_ID_MAC_UPDATE,
334401b5383SAlexander Duyck 				     &mac_update, sizeof(mac_update));
335401b5383SAlexander Duyck 
336401b5383SAlexander Duyck 	/* load onto outgoing mailbox */
337401b5383SAlexander Duyck 	return mbx->ops.enqueue_tx(hw, mbx, msg);
338401b5383SAlexander Duyck }
339401b5383SAlexander Duyck 
340401b5383SAlexander Duyck /**
341eca32047SMatthew Vick  *  fm10k_update_uc_addr_pf - Update device unicast addresses
342401b5383SAlexander Duyck  *  @hw: pointer to the HW structure
343401b5383SAlexander Duyck  *  @glort: base resource tag for this request
344401b5383SAlexander Duyck  *  @mac: MAC address to add/remove from table
345401b5383SAlexander Duyck  *  @vid: VLAN ID to add/remove from table
346401b5383SAlexander Duyck  *  @add: Indicates if this is an add or remove operation
347401b5383SAlexander Duyck  *  @flags: flags field to indicate add and secure
348401b5383SAlexander Duyck  *
349401b5383SAlexander Duyck  *  This function is used to add or remove unicast addresses for
350401b5383SAlexander Duyck  *  the PF.
351401b5383SAlexander Duyck  **/
fm10k_update_uc_addr_pf(struct fm10k_hw * hw,u16 glort,const u8 * mac,u16 vid,bool add,u8 flags)352401b5383SAlexander Duyck static s32 fm10k_update_uc_addr_pf(struct fm10k_hw *hw, u16 glort,
353401b5383SAlexander Duyck 				   const u8 *mac, u16 vid, bool add, u8 flags)
354401b5383SAlexander Duyck {
355401b5383SAlexander Duyck 	/* verify MAC address is valid */
356401b5383SAlexander Duyck 	if (!is_valid_ether_addr(mac))
357401b5383SAlexander Duyck 		return FM10K_ERR_PARAM;
358401b5383SAlexander Duyck 
359401b5383SAlexander Duyck 	return fm10k_update_xc_addr_pf(hw, glort, mac, vid, add, flags);
360401b5383SAlexander Duyck }
361401b5383SAlexander Duyck 
362401b5383SAlexander Duyck /**
363401b5383SAlexander Duyck  *  fm10k_update_mc_addr_pf - Update device multicast addresses
364401b5383SAlexander Duyck  *  @hw: pointer to the HW structure
365401b5383SAlexander Duyck  *  @glort: base resource tag for this request
366401b5383SAlexander Duyck  *  @mac: MAC address to add/remove from table
367401b5383SAlexander Duyck  *  @vid: VLAN ID to add/remove from table
368401b5383SAlexander Duyck  *  @add: Indicates if this is an add or remove operation
369401b5383SAlexander Duyck  *
370401b5383SAlexander Duyck  *  This function is used to add or remove multicast MAC addresses for
371401b5383SAlexander Duyck  *  the PF.
372401b5383SAlexander Duyck  **/
fm10k_update_mc_addr_pf(struct fm10k_hw * hw,u16 glort,const u8 * mac,u16 vid,bool add)373401b5383SAlexander Duyck static s32 fm10k_update_mc_addr_pf(struct fm10k_hw *hw, u16 glort,
374401b5383SAlexander Duyck 				   const u8 *mac, u16 vid, bool add)
375401b5383SAlexander Duyck {
376401b5383SAlexander Duyck 	/* verify multicast address is valid */
377401b5383SAlexander Duyck 	if (!is_multicast_ether_addr(mac))
378401b5383SAlexander Duyck 		return FM10K_ERR_PARAM;
379401b5383SAlexander Duyck 
380401b5383SAlexander Duyck 	return fm10k_update_xc_addr_pf(hw, glort, mac, vid, add, 0);
381401b5383SAlexander Duyck }
382401b5383SAlexander Duyck 
383401b5383SAlexander Duyck /**
384401b5383SAlexander Duyck  *  fm10k_update_xcast_mode_pf - Request update of multicast mode
385401b5383SAlexander Duyck  *  @hw: pointer to hardware structure
386401b5383SAlexander Duyck  *  @glort: base resource tag for this request
387401b5383SAlexander Duyck  *  @mode: integer value indicating mode being requested
388401b5383SAlexander Duyck  *
389401b5383SAlexander Duyck  *  This function will attempt to request a higher mode for the port
390401b5383SAlexander Duyck  *  so that it can enable either multicast, multicast promiscuous, or
391401b5383SAlexander Duyck  *  promiscuous mode of operation.
392401b5383SAlexander Duyck  **/
fm10k_update_xcast_mode_pf(struct fm10k_hw * hw,u16 glort,u8 mode)393401b5383SAlexander Duyck static s32 fm10k_update_xcast_mode_pf(struct fm10k_hw *hw, u16 glort, u8 mode)
394401b5383SAlexander Duyck {
395401b5383SAlexander Duyck 	struct fm10k_mbx_info *mbx = &hw->mbx;
396401b5383SAlexander Duyck 	u32 msg[3], xcast_mode;
397401b5383SAlexander Duyck 
398401b5383SAlexander Duyck 	if (mode > FM10K_XCAST_MODE_NONE)
399401b5383SAlexander Duyck 		return FM10K_ERR_PARAM;
400a4fcad65SBruce Allan 
401401b5383SAlexander Duyck 	/* if glort is not valid return error */
402401b5383SAlexander Duyck 	if (!fm10k_glort_valid_pf(hw, glort))
403401b5383SAlexander Duyck 		return FM10K_ERR_PARAM;
404401b5383SAlexander Duyck 
405401b5383SAlexander Duyck 	/* write xcast mode as a single u32 value,
406401b5383SAlexander Duyck 	 * lower 16 bits: glort
407401b5383SAlexander Duyck 	 * upper 16 bits: mode
408401b5383SAlexander Duyck 	 */
409401b5383SAlexander Duyck 	xcast_mode = ((u32)mode << 16) | glort;
410401b5383SAlexander Duyck 
411401b5383SAlexander Duyck 	/* generate message requesting to change xcast mode */
412401b5383SAlexander Duyck 	fm10k_tlv_msg_init(msg, FM10K_PF_MSG_ID_XCAST_MODES);
413401b5383SAlexander Duyck 	fm10k_tlv_attr_put_u32(msg, FM10K_PF_ATTR_ID_XCAST_MODE, xcast_mode);
414401b5383SAlexander Duyck 
415401b5383SAlexander Duyck 	/* load onto outgoing mailbox */
416401b5383SAlexander Duyck 	return mbx->ops.enqueue_tx(hw, mbx, msg);
417401b5383SAlexander Duyck }
418401b5383SAlexander Duyck 
419401b5383SAlexander Duyck /**
420401b5383SAlexander Duyck  *  fm10k_update_int_moderator_pf - Update interrupt moderator linked list
421401b5383SAlexander Duyck  *  @hw: pointer to hardware structure
422401b5383SAlexander Duyck  *
423401b5383SAlexander Duyck  *  This function walks through the MSI-X vector table to determine the
424401b5383SAlexander Duyck  *  number of active interrupts and based on that information updates the
425401b5383SAlexander Duyck  *  interrupt moderator linked list.
426401b5383SAlexander Duyck  **/
fm10k_update_int_moderator_pf(struct fm10k_hw * hw)427401b5383SAlexander Duyck static void fm10k_update_int_moderator_pf(struct fm10k_hw *hw)
428401b5383SAlexander Duyck {
429401b5383SAlexander Duyck 	u32 i;
430401b5383SAlexander Duyck 
431401b5383SAlexander Duyck 	/* Disable interrupt moderator */
432401b5383SAlexander Duyck 	fm10k_write_reg(hw, FM10K_INT_CTRL, 0);
433401b5383SAlexander Duyck 
434401b5383SAlexander Duyck 	/* loop through PF from last to first looking enabled vectors */
435401b5383SAlexander Duyck 	for (i = FM10K_ITR_REG_COUNT_PF - 1; i; i--) {
436401b5383SAlexander Duyck 		if (!fm10k_read_reg(hw, FM10K_MSIX_VECTOR_MASK(i)))
437401b5383SAlexander Duyck 			break;
438401b5383SAlexander Duyck 	}
439401b5383SAlexander Duyck 
440401b5383SAlexander Duyck 	/* always reset VFITR2[0] to point to last enabled PF vector */
441401b5383SAlexander Duyck 	fm10k_write_reg(hw, FM10K_ITR2(FM10K_ITR_REG_COUNT_PF), i);
442401b5383SAlexander Duyck 
443401b5383SAlexander Duyck 	/* reset ITR2[0] to point to last enabled PF vector */
444c2653865SAlexander Duyck 	if (!hw->iov.num_vfs)
445401b5383SAlexander Duyck 		fm10k_write_reg(hw, FM10K_ITR2(0), i);
446401b5383SAlexander Duyck 
447401b5383SAlexander Duyck 	/* Enable interrupt moderator */
448401b5383SAlexander Duyck 	fm10k_write_reg(hw, FM10K_INT_CTRL, FM10K_INT_CTRL_ENABLEMODERATOR);
449401b5383SAlexander Duyck }
450401b5383SAlexander Duyck 
451401b5383SAlexander Duyck /**
452401b5383SAlexander Duyck  *  fm10k_update_lport_state_pf - Notify the switch of a change in port state
453401b5383SAlexander Duyck  *  @hw: pointer to the HW structure
454401b5383SAlexander Duyck  *  @glort: base resource tag for this request
455401b5383SAlexander Duyck  *  @count: number of logical ports being updated
456401b5383SAlexander Duyck  *  @enable: boolean value indicating enable or disable
457401b5383SAlexander Duyck  *
458401b5383SAlexander Duyck  *  This function is used to add/remove a logical port from the switch.
459401b5383SAlexander Duyck  **/
fm10k_update_lport_state_pf(struct fm10k_hw * hw,u16 glort,u16 count,bool enable)460401b5383SAlexander Duyck static s32 fm10k_update_lport_state_pf(struct fm10k_hw *hw, u16 glort,
461401b5383SAlexander Duyck 				       u16 count, bool enable)
462401b5383SAlexander Duyck {
463401b5383SAlexander Duyck 	struct fm10k_mbx_info *mbx = &hw->mbx;
464401b5383SAlexander Duyck 	u32 msg[3], lport_msg;
465401b5383SAlexander Duyck 
466401b5383SAlexander Duyck 	/* do nothing if we are being asked to create or destroy 0 ports */
467401b5383SAlexander Duyck 	if (!count)
468401b5383SAlexander Duyck 		return 0;
469401b5383SAlexander Duyck 
470401b5383SAlexander Duyck 	/* if glort is not valid return error */
471401b5383SAlexander Duyck 	if (!fm10k_glort_valid_pf(hw, glort))
472401b5383SAlexander Duyck 		return FM10K_ERR_PARAM;
473401b5383SAlexander Duyck 
47411ec36a9SNgai-Mint Kwan 	/* reset multicast mode if deleting lport */
47511ec36a9SNgai-Mint Kwan 	if (!enable)
47611ec36a9SNgai-Mint Kwan 		fm10k_update_xcast_mode_pf(hw, glort, FM10K_XCAST_MODE_NONE);
47711ec36a9SNgai-Mint Kwan 
478401b5383SAlexander Duyck 	/* construct the lport message from the 2 pieces of data we have */
479401b5383SAlexander Duyck 	lport_msg = ((u32)count << 16) | glort;
480401b5383SAlexander Duyck 
481401b5383SAlexander Duyck 	/* generate lport create/delete message */
482401b5383SAlexander Duyck 	fm10k_tlv_msg_init(msg, enable ? FM10K_PF_MSG_ID_LPORT_CREATE :
483401b5383SAlexander Duyck 					 FM10K_PF_MSG_ID_LPORT_DELETE);
484401b5383SAlexander Duyck 	fm10k_tlv_attr_put_u32(msg, FM10K_PF_ATTR_ID_PORT, lport_msg);
485401b5383SAlexander Duyck 
486401b5383SAlexander Duyck 	/* load onto outgoing mailbox */
487401b5383SAlexander Duyck 	return mbx->ops.enqueue_tx(hw, mbx, msg);
488401b5383SAlexander Duyck }
489401b5383SAlexander Duyck 
490401b5383SAlexander Duyck /**
491401b5383SAlexander Duyck  *  fm10k_configure_dglort_map_pf - Configures GLORT entry and queues
492401b5383SAlexander Duyck  *  @hw: pointer to hardware structure
493401b5383SAlexander Duyck  *  @dglort: pointer to dglort configuration structure
494401b5383SAlexander Duyck  *
495401b5383SAlexander Duyck  *  Reads the configuration structure contained in dglort_cfg and uses
496401b5383SAlexander Duyck  *  that information to then populate a DGLORTMAP/DEC entry and the queues
497401b5383SAlexander Duyck  *  to which it has been assigned.
498401b5383SAlexander Duyck  **/
fm10k_configure_dglort_map_pf(struct fm10k_hw * hw,struct fm10k_dglort_cfg * dglort)499401b5383SAlexander Duyck static s32 fm10k_configure_dglort_map_pf(struct fm10k_hw *hw,
500401b5383SAlexander Duyck 					 struct fm10k_dglort_cfg *dglort)
501401b5383SAlexander Duyck {
502401b5383SAlexander Duyck 	u16 glort, queue_count, vsi_count, pc_count;
503401b5383SAlexander Duyck 	u16 vsi, queue, pc, q_idx;
504401b5383SAlexander Duyck 	u32 txqctl, dglortdec, dglortmap;
505401b5383SAlexander Duyck 
506401b5383SAlexander Duyck 	/* verify the dglort pointer */
507401b5383SAlexander Duyck 	if (!dglort)
508401b5383SAlexander Duyck 		return FM10K_ERR_PARAM;
509401b5383SAlexander Duyck 
510401b5383SAlexander Duyck 	/* verify the dglort values */
511401b5383SAlexander Duyck 	if ((dglort->idx > 7) || (dglort->rss_l > 7) || (dglort->pc_l > 3) ||
512401b5383SAlexander Duyck 	    (dglort->vsi_l > 6) || (dglort->vsi_b > 64) ||
513401b5383SAlexander Duyck 	    (dglort->queue_l > 8) || (dglort->queue_b >= 256))
514401b5383SAlexander Duyck 		return FM10K_ERR_PARAM;
515401b5383SAlexander Duyck 
516401b5383SAlexander Duyck 	/* determine count of VSIs and queues */
517fcdb0a99SBruce Allan 	queue_count = BIT(dglort->rss_l + dglort->pc_l);
518fcdb0a99SBruce Allan 	vsi_count = BIT(dglort->vsi_l + dglort->queue_l);
519401b5383SAlexander Duyck 	glort = dglort->glort;
520401b5383SAlexander Duyck 	q_idx = dglort->queue_b;
521401b5383SAlexander Duyck 
522401b5383SAlexander Duyck 	/* configure SGLORT for queues */
523401b5383SAlexander Duyck 	for (vsi = 0; vsi < vsi_count; vsi++, glort++) {
524401b5383SAlexander Duyck 		for (queue = 0; queue < queue_count; queue++, q_idx++) {
525401b5383SAlexander Duyck 			if (q_idx >= FM10K_MAX_QUEUES)
526401b5383SAlexander Duyck 				break;
527401b5383SAlexander Duyck 
528401b5383SAlexander Duyck 			fm10k_write_reg(hw, FM10K_TX_SGLORT(q_idx), glort);
529401b5383SAlexander Duyck 			fm10k_write_reg(hw, FM10K_RX_SGLORT(q_idx), glort);
530401b5383SAlexander Duyck 		}
531401b5383SAlexander Duyck 	}
532401b5383SAlexander Duyck 
533401b5383SAlexander Duyck 	/* determine count of PCs and queues */
534fcdb0a99SBruce Allan 	queue_count = BIT(dglort->queue_l + dglort->rss_l + dglort->vsi_l);
535fcdb0a99SBruce Allan 	pc_count = BIT(dglort->pc_l);
536401b5383SAlexander Duyck 
537401b5383SAlexander Duyck 	/* configure PC for Tx queues */
538401b5383SAlexander Duyck 	for (pc = 0; pc < pc_count; pc++) {
539401b5383SAlexander Duyck 		q_idx = pc + dglort->queue_b;
540401b5383SAlexander Duyck 		for (queue = 0; queue < queue_count; queue++) {
541401b5383SAlexander Duyck 			if (q_idx >= FM10K_MAX_QUEUES)
542401b5383SAlexander Duyck 				break;
543401b5383SAlexander Duyck 
544401b5383SAlexander Duyck 			txqctl = fm10k_read_reg(hw, FM10K_TXQCTL(q_idx));
545401b5383SAlexander Duyck 			txqctl &= ~FM10K_TXQCTL_PC_MASK;
546401b5383SAlexander Duyck 			txqctl |= pc << FM10K_TXQCTL_PC_SHIFT;
547401b5383SAlexander Duyck 			fm10k_write_reg(hw, FM10K_TXQCTL(q_idx), txqctl);
548401b5383SAlexander Duyck 
549401b5383SAlexander Duyck 			q_idx += pc_count;
550401b5383SAlexander Duyck 		}
551401b5383SAlexander Duyck 	}
552401b5383SAlexander Duyck 
553401b5383SAlexander Duyck 	/* configure DGLORTDEC */
554401b5383SAlexander Duyck 	dglortdec = ((u32)(dglort->rss_l) << FM10K_DGLORTDEC_RSSLENGTH_SHIFT) |
555401b5383SAlexander Duyck 		    ((u32)(dglort->queue_b) << FM10K_DGLORTDEC_QBASE_SHIFT) |
556401b5383SAlexander Duyck 		    ((u32)(dglort->pc_l) << FM10K_DGLORTDEC_PCLENGTH_SHIFT) |
557401b5383SAlexander Duyck 		    ((u32)(dglort->vsi_b) << FM10K_DGLORTDEC_VSIBASE_SHIFT) |
558401b5383SAlexander Duyck 		    ((u32)(dglort->vsi_l) << FM10K_DGLORTDEC_VSILENGTH_SHIFT) |
559401b5383SAlexander Duyck 		    ((u32)(dglort->queue_l));
560401b5383SAlexander Duyck 	if (dglort->inner_rss)
561401b5383SAlexander Duyck 		dglortdec |=  FM10K_DGLORTDEC_INNERRSS_ENABLE;
562401b5383SAlexander Duyck 
563401b5383SAlexander Duyck 	/* configure DGLORTMAP */
564401b5383SAlexander Duyck 	dglortmap = (dglort->idx == fm10k_dglort_default) ?
565401b5383SAlexander Duyck 			FM10K_DGLORTMAP_ANY : FM10K_DGLORTMAP_ZERO;
566401b5383SAlexander Duyck 	dglortmap <<= dglort->vsi_l + dglort->queue_l + dglort->shared_l;
567401b5383SAlexander Duyck 	dglortmap |= dglort->glort;
568401b5383SAlexander Duyck 
569401b5383SAlexander Duyck 	/* write values to hardware */
570401b5383SAlexander Duyck 	fm10k_write_reg(hw, FM10K_DGLORTDEC(dglort->idx), dglortdec);
571401b5383SAlexander Duyck 	fm10k_write_reg(hw, FM10K_DGLORTMAP(dglort->idx), dglortmap);
572401b5383SAlexander Duyck 
573401b5383SAlexander Duyck 	return 0;
574401b5383SAlexander Duyck }
575401b5383SAlexander Duyck 
fm10k_queues_per_pool(struct fm10k_hw * hw)576c2653865SAlexander Duyck u16 fm10k_queues_per_pool(struct fm10k_hw *hw)
577c2653865SAlexander Duyck {
578c2653865SAlexander Duyck 	u16 num_pools = hw->iov.num_pools;
579c2653865SAlexander Duyck 
580c2653865SAlexander Duyck 	return (num_pools > 32) ? 2 : (num_pools > 16) ? 4 : (num_pools > 8) ?
581c2653865SAlexander Duyck 	       8 : FM10K_MAX_QUEUES_POOL;
582c2653865SAlexander Duyck }
583c2653865SAlexander Duyck 
fm10k_vf_queue_index(struct fm10k_hw * hw,u16 vf_idx)584c2653865SAlexander Duyck u16 fm10k_vf_queue_index(struct fm10k_hw *hw, u16 vf_idx)
585c2653865SAlexander Duyck {
586c2653865SAlexander Duyck 	u16 num_vfs = hw->iov.num_vfs;
587c2653865SAlexander Duyck 	u16 vf_q_idx = FM10K_MAX_QUEUES;
588c2653865SAlexander Duyck 
589c2653865SAlexander Duyck 	vf_q_idx -= fm10k_queues_per_pool(hw) * (num_vfs - vf_idx);
590c2653865SAlexander Duyck 
591c2653865SAlexander Duyck 	return vf_q_idx;
592c2653865SAlexander Duyck }
593c2653865SAlexander Duyck 
fm10k_vectors_per_pool(struct fm10k_hw * hw)594c2653865SAlexander Duyck static u16 fm10k_vectors_per_pool(struct fm10k_hw *hw)
595c2653865SAlexander Duyck {
596c2653865SAlexander Duyck 	u16 num_pools = hw->iov.num_pools;
597c2653865SAlexander Duyck 
598c2653865SAlexander Duyck 	return (num_pools > 32) ? 8 : (num_pools > 16) ? 16 :
599c2653865SAlexander Duyck 	       FM10K_MAX_VECTORS_POOL;
600c2653865SAlexander Duyck }
601c2653865SAlexander Duyck 
fm10k_vf_vector_index(struct fm10k_hw * hw,u16 vf_idx)602c2653865SAlexander Duyck static u16 fm10k_vf_vector_index(struct fm10k_hw *hw, u16 vf_idx)
603c2653865SAlexander Duyck {
604c2653865SAlexander Duyck 	u16 vf_v_idx = FM10K_MAX_VECTORS_PF;
605c2653865SAlexander Duyck 
606c2653865SAlexander Duyck 	vf_v_idx += fm10k_vectors_per_pool(hw) * vf_idx;
607c2653865SAlexander Duyck 
608c2653865SAlexander Duyck 	return vf_v_idx;
609c2653865SAlexander Duyck }
610c2653865SAlexander Duyck 
611c2653865SAlexander Duyck /**
612c2653865SAlexander Duyck  *  fm10k_iov_assign_resources_pf - Assign pool resources for virtualization
613c2653865SAlexander Duyck  *  @hw: pointer to the HW structure
614c2653865SAlexander Duyck  *  @num_vfs: number of VFs to be allocated
615c2653865SAlexander Duyck  *  @num_pools: number of virtualization pools to be allocated
616c2653865SAlexander Duyck  *
617c2653865SAlexander Duyck  *  Allocates queues and traffic classes to virtualization entities to prepare
618c2653865SAlexander Duyck  *  the PF for SR-IOV and VMDq
619c2653865SAlexander Duyck  **/
fm10k_iov_assign_resources_pf(struct fm10k_hw * hw,u16 num_vfs,u16 num_pools)620c2653865SAlexander Duyck static s32 fm10k_iov_assign_resources_pf(struct fm10k_hw *hw, u16 num_vfs,
621c2653865SAlexander Duyck 					 u16 num_pools)
622c2653865SAlexander Duyck {
623c2653865SAlexander Duyck 	u16 qmap_stride, qpp, vpp, vf_q_idx, vf_q_idx0, qmap_idx;
624c2653865SAlexander Duyck 	u32 vid = hw->mac.default_vid << FM10K_TXQCTL_VID_SHIFT;
625c2653865SAlexander Duyck 	int i, j;
626c2653865SAlexander Duyck 
627c2653865SAlexander Duyck 	/* hardware only supports up to 64 pools */
628c2653865SAlexander Duyck 	if (num_pools > 64)
629c2653865SAlexander Duyck 		return FM10K_ERR_PARAM;
630c2653865SAlexander Duyck 
631c2653865SAlexander Duyck 	/* the number of VFs cannot exceed the number of pools */
632c2653865SAlexander Duyck 	if ((num_vfs > num_pools) || (num_vfs > hw->iov.total_vfs))
633c2653865SAlexander Duyck 		return FM10K_ERR_PARAM;
634c2653865SAlexander Duyck 
635c2653865SAlexander Duyck 	/* record number of virtualization entities */
636c2653865SAlexander Duyck 	hw->iov.num_vfs = num_vfs;
637c2653865SAlexander Duyck 	hw->iov.num_pools = num_pools;
638c2653865SAlexander Duyck 
639c2653865SAlexander Duyck 	/* determine qmap offsets and counts */
640c2653865SAlexander Duyck 	qmap_stride = (num_vfs > 8) ? 32 : 256;
641c2653865SAlexander Duyck 	qpp = fm10k_queues_per_pool(hw);
642c2653865SAlexander Duyck 	vpp = fm10k_vectors_per_pool(hw);
643c2653865SAlexander Duyck 
644c2653865SAlexander Duyck 	/* calculate starting index for queues */
645c2653865SAlexander Duyck 	vf_q_idx = fm10k_vf_queue_index(hw, 0);
646c2653865SAlexander Duyck 	qmap_idx = 0;
647c2653865SAlexander Duyck 
648c2653865SAlexander Duyck 	/* establish TCs with -1 credits and no quanta to prevent transmit */
649c2653865SAlexander Duyck 	for (i = 0; i < num_vfs; i++) {
650c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_TC_MAXCREDIT(i), 0);
651c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_TC_RATE(i), 0);
652c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_TC_CREDIT(i),
653c2653865SAlexander Duyck 				FM10K_TC_CREDIT_CREDIT_MASK);
654c2653865SAlexander Duyck 	}
655c2653865SAlexander Duyck 
656c2653865SAlexander Duyck 	/* zero out all mbmem registers */
657c2653865SAlexander Duyck 	for (i = FM10K_VFMBMEM_LEN * num_vfs; i--;)
658c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_MBMEM(i), 0);
659c2653865SAlexander Duyck 
660c2653865SAlexander Duyck 	/* clear event notification of VF FLR */
661c2653865SAlexander Duyck 	fm10k_write_reg(hw, FM10K_PFVFLREC(0), ~0);
662c2653865SAlexander Duyck 	fm10k_write_reg(hw, FM10K_PFVFLREC(1), ~0);
663c2653865SAlexander Duyck 
664c2653865SAlexander Duyck 	/* loop through unallocated rings assigning them back to PF */
665c2653865SAlexander Duyck 	for (i = FM10K_MAX_QUEUES_PF; i < vf_q_idx; i++) {
666c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_TXDCTL(i), 0);
667ded8b20dSJeff Kirsher 		fm10k_write_reg(hw, FM10K_TXQCTL(i), FM10K_TXQCTL_PF |
668ded8b20dSJeff Kirsher 				FM10K_TXQCTL_UNLIMITED_BW | vid);
669c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_RXQCTL(i), FM10K_RXQCTL_PF);
670c2653865SAlexander Duyck 	}
671c2653865SAlexander Duyck 
672c2653865SAlexander Duyck 	/* PF should have already updated VFITR2[0] */
673c2653865SAlexander Duyck 
674c2653865SAlexander Duyck 	/* update all ITR registers to flow to VFITR2[0] */
675c2653865SAlexander Duyck 	for (i = FM10K_ITR_REG_COUNT_PF + 1; i < FM10K_ITR_REG_COUNT; i++) {
676c2653865SAlexander Duyck 		if (!(i & (vpp - 1)))
677c2653865SAlexander Duyck 			fm10k_write_reg(hw, FM10K_ITR2(i), i - vpp);
678c2653865SAlexander Duyck 		else
679c2653865SAlexander Duyck 			fm10k_write_reg(hw, FM10K_ITR2(i), i - 1);
680c2653865SAlexander Duyck 	}
681c2653865SAlexander Duyck 
682c2653865SAlexander Duyck 	/* update PF ITR2[0] to reference the last vector */
683c2653865SAlexander Duyck 	fm10k_write_reg(hw, FM10K_ITR2(0),
684c2653865SAlexander Duyck 			fm10k_vf_vector_index(hw, num_vfs - 1));
685c2653865SAlexander Duyck 
686c2653865SAlexander Duyck 	/* loop through rings populating rings and TCs */
687c2653865SAlexander Duyck 	for (i = 0; i < num_vfs; i++) {
688c2653865SAlexander Duyck 		/* record index for VF queue 0 for use in end of loop */
689c2653865SAlexander Duyck 		vf_q_idx0 = vf_q_idx;
690c2653865SAlexander Duyck 
691c2653865SAlexander Duyck 		for (j = 0; j < qpp; j++, qmap_idx++, vf_q_idx++) {
692c2653865SAlexander Duyck 			/* assign VF and locked TC to queues */
693c2653865SAlexander Duyck 			fm10k_write_reg(hw, FM10K_TXDCTL(vf_q_idx), 0);
694c2653865SAlexander Duyck 			fm10k_write_reg(hw, FM10K_TXQCTL(vf_q_idx),
695c2653865SAlexander Duyck 					(i << FM10K_TXQCTL_TC_SHIFT) | i |
696c2653865SAlexander Duyck 					FM10K_TXQCTL_VF | vid);
697c2653865SAlexander Duyck 			fm10k_write_reg(hw, FM10K_RXDCTL(vf_q_idx),
698c2653865SAlexander Duyck 					FM10K_RXDCTL_WRITE_BACK_MIN_DELAY |
699c2653865SAlexander Duyck 					FM10K_RXDCTL_DROP_ON_EMPTY);
700c2653865SAlexander Duyck 			fm10k_write_reg(hw, FM10K_RXQCTL(vf_q_idx),
7011aab144cSBruce Allan 					(i << FM10K_RXQCTL_VF_SHIFT) |
7021aab144cSBruce Allan 					FM10K_RXQCTL_VF);
703c2653865SAlexander Duyck 
704c2653865SAlexander Duyck 			/* map queue pair to VF */
705c2653865SAlexander Duyck 			fm10k_write_reg(hw, FM10K_TQMAP(qmap_idx), vf_q_idx);
706c2653865SAlexander Duyck 			fm10k_write_reg(hw, FM10K_RQMAP(qmap_idx), vf_q_idx);
707c2653865SAlexander Duyck 		}
708c2653865SAlexander Duyck 
709c2653865SAlexander Duyck 		/* repeat the first ring for all of the remaining VF rings */
710c2653865SAlexander Duyck 		for (; j < qmap_stride; j++, qmap_idx++) {
711c2653865SAlexander Duyck 			fm10k_write_reg(hw, FM10K_TQMAP(qmap_idx), vf_q_idx0);
712c2653865SAlexander Duyck 			fm10k_write_reg(hw, FM10K_RQMAP(qmap_idx), vf_q_idx0);
713c2653865SAlexander Duyck 		}
714c2653865SAlexander Duyck 	}
715c2653865SAlexander Duyck 
716c2653865SAlexander Duyck 	/* loop through remaining indexes assigning all to queue 0 */
717c2653865SAlexander Duyck 	while (qmap_idx < FM10K_TQMAP_TABLE_SIZE) {
718c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_TQMAP(qmap_idx), 0);
719c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_RQMAP(qmap_idx), 0);
720c2653865SAlexander Duyck 		qmap_idx++;
721c2653865SAlexander Duyck 	}
722c2653865SAlexander Duyck 
723c2653865SAlexander Duyck 	return 0;
724c2653865SAlexander Duyck }
725c2653865SAlexander Duyck 
726c2653865SAlexander Duyck /**
727c2653865SAlexander Duyck  *  fm10k_iov_configure_tc_pf - Configure the shaping group for VF
728c2653865SAlexander Duyck  *  @hw: pointer to the HW structure
729c2653865SAlexander Duyck  *  @vf_idx: index of VF receiving GLORT
730c2653865SAlexander Duyck  *  @rate: Rate indicated in Mb/s
731c2653865SAlexander Duyck  *
732c2653865SAlexander Duyck  *  Configured the TC for a given VF to allow only up to a given number
733c2653865SAlexander Duyck  *  of Mb/s of outgoing Tx throughput.
734c2653865SAlexander Duyck  **/
fm10k_iov_configure_tc_pf(struct fm10k_hw * hw,u16 vf_idx,int rate)735c2653865SAlexander Duyck static s32 fm10k_iov_configure_tc_pf(struct fm10k_hw *hw, u16 vf_idx, int rate)
736c2653865SAlexander Duyck {
737c2653865SAlexander Duyck 	/* configure defaults */
738c2653865SAlexander Duyck 	u32 interval = FM10K_TC_RATE_INTERVAL_4US_GEN3;
739c2653865SAlexander Duyck 	u32 tc_rate = FM10K_TC_RATE_QUANTA_MASK;
740c2653865SAlexander Duyck 
741c2653865SAlexander Duyck 	/* verify vf is in range */
742c2653865SAlexander Duyck 	if (vf_idx >= hw->iov.num_vfs)
743c2653865SAlexander Duyck 		return FM10K_ERR_PARAM;
744c2653865SAlexander Duyck 
745c2653865SAlexander Duyck 	/* set interval to align with 4.096 usec in all modes */
746c2653865SAlexander Duyck 	switch (hw->bus.speed) {
747c2653865SAlexander Duyck 	case fm10k_bus_speed_2500:
748c2653865SAlexander Duyck 		interval = FM10K_TC_RATE_INTERVAL_4US_GEN1;
749c2653865SAlexander Duyck 		break;
750c2653865SAlexander Duyck 	case fm10k_bus_speed_5000:
751c2653865SAlexander Duyck 		interval = FM10K_TC_RATE_INTERVAL_4US_GEN2;
752c2653865SAlexander Duyck 		break;
753c2653865SAlexander Duyck 	default:
754c2653865SAlexander Duyck 		break;
755c2653865SAlexander Duyck 	}
756c2653865SAlexander Duyck 
757c2653865SAlexander Duyck 	if (rate) {
758c2653865SAlexander Duyck 		if (rate > FM10K_VF_TC_MAX || rate < FM10K_VF_TC_MIN)
759c2653865SAlexander Duyck 			return FM10K_ERR_PARAM;
760c2653865SAlexander Duyck 
761c2653865SAlexander Duyck 		/* The quanta is measured in Bytes per 4.096 or 8.192 usec
762c2653865SAlexander Duyck 		 * The rate is provided in Mbits per second
763c2653865SAlexander Duyck 		 * To tralslate from rate to quanta we need to multiply the
764c2653865SAlexander Duyck 		 * rate by 8.192 usec and divide by 8 bits/byte.  To avoid
765c2653865SAlexander Duyck 		 * dealing with floating point we can round the values up
766c2653865SAlexander Duyck 		 * to the nearest whole number ratio which gives us 128 / 125.
767c2653865SAlexander Duyck 		 */
768c2653865SAlexander Duyck 		tc_rate = (rate * 128) / 125;
769c2653865SAlexander Duyck 
770c2653865SAlexander Duyck 		/* try to keep the rate limiting accurate by increasing
771c2653865SAlexander Duyck 		 * the number of credits and interval for rates less than 4Gb/s
772c2653865SAlexander Duyck 		 */
773c2653865SAlexander Duyck 		if (rate < 4000)
774c2653865SAlexander Duyck 			interval <<= 1;
775c2653865SAlexander Duyck 		else
776c2653865SAlexander Duyck 			tc_rate >>= 1;
777c2653865SAlexander Duyck 	}
778c2653865SAlexander Duyck 
779c2653865SAlexander Duyck 	/* update rate limiter with new values */
780c2653865SAlexander Duyck 	fm10k_write_reg(hw, FM10K_TC_RATE(vf_idx), tc_rate | interval);
781c2653865SAlexander Duyck 	fm10k_write_reg(hw, FM10K_TC_MAXCREDIT(vf_idx), FM10K_TC_MAXCREDIT_64K);
782c2653865SAlexander Duyck 	fm10k_write_reg(hw, FM10K_TC_CREDIT(vf_idx), FM10K_TC_MAXCREDIT_64K);
783c2653865SAlexander Duyck 
784c2653865SAlexander Duyck 	return 0;
785c2653865SAlexander Duyck }
786c2653865SAlexander Duyck 
787c2653865SAlexander Duyck /**
788c2653865SAlexander Duyck  *  fm10k_iov_assign_int_moderator_pf - Add VF interrupts to moderator list
789c2653865SAlexander Duyck  *  @hw: pointer to the HW structure
790c2653865SAlexander Duyck  *  @vf_idx: index of VF receiving GLORT
791c2653865SAlexander Duyck  *
792c2653865SAlexander Duyck  *  Update the interrupt moderator linked list to include any MSI-X
793c2653865SAlexander Duyck  *  interrupts which the VF has enabled in the MSI-X vector table.
794c2653865SAlexander Duyck  **/
fm10k_iov_assign_int_moderator_pf(struct fm10k_hw * hw,u16 vf_idx)795c2653865SAlexander Duyck static s32 fm10k_iov_assign_int_moderator_pf(struct fm10k_hw *hw, u16 vf_idx)
796c2653865SAlexander Duyck {
797c2653865SAlexander Duyck 	u16 vf_v_idx, vf_v_limit, i;
798c2653865SAlexander Duyck 
799c2653865SAlexander Duyck 	/* verify vf is in range */
800c2653865SAlexander Duyck 	if (vf_idx >= hw->iov.num_vfs)
801c2653865SAlexander Duyck 		return FM10K_ERR_PARAM;
802c2653865SAlexander Duyck 
803c2653865SAlexander Duyck 	/* determine vector offset and count */
804c2653865SAlexander Duyck 	vf_v_idx = fm10k_vf_vector_index(hw, vf_idx);
805c2653865SAlexander Duyck 	vf_v_limit = vf_v_idx + fm10k_vectors_per_pool(hw);
806c2653865SAlexander Duyck 
807c2653865SAlexander Duyck 	/* search for first vector that is not masked */
808c2653865SAlexander Duyck 	for (i = vf_v_limit - 1; i > vf_v_idx; i--) {
809c2653865SAlexander Duyck 		if (!fm10k_read_reg(hw, FM10K_MSIX_VECTOR_MASK(i)))
810c2653865SAlexander Duyck 			break;
811c2653865SAlexander Duyck 	}
812c2653865SAlexander Duyck 
813c2653865SAlexander Duyck 	/* reset linked list so it now includes our active vectors */
814c2653865SAlexander Duyck 	if (vf_idx == (hw->iov.num_vfs - 1))
815c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_ITR2(0), i);
816c2653865SAlexander Duyck 	else
817c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_ITR2(vf_v_limit), i);
818c2653865SAlexander Duyck 
819c2653865SAlexander Duyck 	return 0;
820c2653865SAlexander Duyck }
821c2653865SAlexander Duyck 
822c2653865SAlexander Duyck /**
823c2653865SAlexander Duyck  *  fm10k_iov_assign_default_mac_vlan_pf - Assign a MAC and VLAN to VF
824c2653865SAlexander Duyck  *  @hw: pointer to the HW structure
825c2653865SAlexander Duyck  *  @vf_info: pointer to VF information structure
826c2653865SAlexander Duyck  *
827c2653865SAlexander Duyck  *  Assign a MAC address and default VLAN to a VF and notify it of the update
828c2653865SAlexander Duyck  **/
fm10k_iov_assign_default_mac_vlan_pf(struct fm10k_hw * hw,struct fm10k_vf_info * vf_info)829c2653865SAlexander Duyck static s32 fm10k_iov_assign_default_mac_vlan_pf(struct fm10k_hw *hw,
830c2653865SAlexander Duyck 						struct fm10k_vf_info *vf_info)
831c2653865SAlexander Duyck {
832c2653865SAlexander Duyck 	u16 qmap_stride, queues_per_pool, vf_q_idx, timeout, qmap_idx, i;
833c2653865SAlexander Duyck 	u32 msg[4], txdctl, txqctl, tdbal = 0, tdbah = 0;
834c2653865SAlexander Duyck 	s32 err = 0;
835c2653865SAlexander Duyck 	u16 vf_idx, vf_vid;
836c2653865SAlexander Duyck 
837c2653865SAlexander Duyck 	/* verify vf is in range */
838c2653865SAlexander Duyck 	if (!vf_info || vf_info->vf_idx >= hw->iov.num_vfs)
839c2653865SAlexander Duyck 		return FM10K_ERR_PARAM;
840c2653865SAlexander Duyck 
841c2653865SAlexander Duyck 	/* determine qmap offsets and counts */
842c2653865SAlexander Duyck 	qmap_stride = (hw->iov.num_vfs > 8) ? 32 : 256;
843c2653865SAlexander Duyck 	queues_per_pool = fm10k_queues_per_pool(hw);
844c2653865SAlexander Duyck 
845c2653865SAlexander Duyck 	/* calculate starting index for queues */
846c2653865SAlexander Duyck 	vf_idx = vf_info->vf_idx;
847c2653865SAlexander Duyck 	vf_q_idx = fm10k_vf_queue_index(hw, vf_idx);
848c2653865SAlexander Duyck 	qmap_idx = qmap_stride * vf_idx;
849c2653865SAlexander Duyck 
8505c69df8aSJacob Keller 	/* Determine correct default VLAN ID. The FM10K_VLAN_OVERRIDE bit is
8515c69df8aSJacob Keller 	 * used here to indicate to the VF that it will not have privilege to
8525c69df8aSJacob Keller 	 * write VLAN_TABLE. All policy is enforced on the PF but this allows
8536ee98686SNgai-Mint Kwan 	 * the VF to correctly report errors to userspace requests.
8545c69df8aSJacob Keller 	 */
855c2653865SAlexander Duyck 	if (vf_info->pf_vid)
8565c69df8aSJacob Keller 		vf_vid = vf_info->pf_vid | FM10K_VLAN_OVERRIDE;
857c2653865SAlexander Duyck 	else
858c2653865SAlexander Duyck 		vf_vid = vf_info->sw_vid;
859c2653865SAlexander Duyck 
860c2653865SAlexander Duyck 	/* generate MAC_ADDR request */
861c2653865SAlexander Duyck 	fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_MAC_VLAN);
862c2653865SAlexander Duyck 	fm10k_tlv_attr_put_mac_vlan(msg, FM10K_MAC_VLAN_MSG_DEFAULT_MAC,
863c2653865SAlexander Duyck 				    vf_info->mac, vf_vid);
864c2653865SAlexander Duyck 
865325782a1SJacob Keller 	/* Configure Queue control register with new VLAN ID. The TXQCTL
866325782a1SJacob Keller 	 * register is RO from the VF, so the PF must do this even in the
867325782a1SJacob Keller 	 * case of notifying the VF of a new VID via the mailbox.
868325782a1SJacob Keller 	 */
869325782a1SJacob Keller 	txqctl = ((u32)vf_vid << FM10K_TXQCTL_VID_SHIFT) &
870325782a1SJacob Keller 		 FM10K_TXQCTL_VID_MASK;
871325782a1SJacob Keller 	txqctl |= (vf_idx << FM10K_TXQCTL_TC_SHIFT) |
872325782a1SJacob Keller 		  FM10K_TXQCTL_VF | vf_idx;
873325782a1SJacob Keller 
874325782a1SJacob Keller 	for (i = 0; i < queues_per_pool; i++)
875325782a1SJacob Keller 		fm10k_write_reg(hw, FM10K_TXQCTL(vf_q_idx + i), txqctl);
876325782a1SJacob Keller 
877325782a1SJacob Keller 	/* try loading a message onto outgoing mailbox first */
878325782a1SJacob Keller 	if (vf_info->mbx.ops.enqueue_tx) {
879325782a1SJacob Keller 		err = vf_info->mbx.ops.enqueue_tx(hw, &vf_info->mbx, msg);
880325782a1SJacob Keller 		if (err != FM10K_MBX_ERR_NO_MBX)
881325782a1SJacob Keller 			return err;
882325782a1SJacob Keller 		err = 0;
883325782a1SJacob Keller 	}
884325782a1SJacob Keller 
885325782a1SJacob Keller 	/* If we aren't connected to a mailbox, this is most likely because
886325782a1SJacob Keller 	 * the VF driver is not running. It should thus be safe to re-map
887325782a1SJacob Keller 	 * queues and use the registers to pass the MAC address so that the VF
888325782a1SJacob Keller 	 * driver gets correct information during its initialization.
889325782a1SJacob Keller 	 */
890325782a1SJacob Keller 
891325782a1SJacob Keller 	/* MAP Tx queue back to 0 temporarily, and disable it */
892325782a1SJacob Keller 	fm10k_write_reg(hw, FM10K_TQMAP(qmap_idx), 0);
893325782a1SJacob Keller 	fm10k_write_reg(hw, FM10K_TXDCTL(vf_q_idx), 0);
894c2653865SAlexander Duyck 
895c2653865SAlexander Duyck 	/* verify ring has disabled before modifying base address registers */
896c2653865SAlexander Duyck 	txdctl = fm10k_read_reg(hw, FM10K_TXDCTL(vf_q_idx));
897c2653865SAlexander Duyck 	for (timeout = 0; txdctl & FM10K_TXDCTL_ENABLE; timeout++) {
898c2653865SAlexander Duyck 		/* limit ourselves to a 1ms timeout */
899c2653865SAlexander Duyck 		if (timeout == 10) {
900c2653865SAlexander Duyck 			err = FM10K_ERR_DMA_PENDING;
901c2653865SAlexander Duyck 			goto err_out;
902c2653865SAlexander Duyck 		}
903c2653865SAlexander Duyck 
904c2653865SAlexander Duyck 		usleep_range(100, 200);
905c2653865SAlexander Duyck 		txdctl = fm10k_read_reg(hw, FM10K_TXDCTL(vf_q_idx));
906c2653865SAlexander Duyck 	}
907c2653865SAlexander Duyck 
908c2653865SAlexander Duyck 	/* Update base address registers to contain MAC address */
909c2653865SAlexander Duyck 	if (is_valid_ether_addr(vf_info->mac)) {
910c2653865SAlexander Duyck 		tdbal = (((u32)vf_info->mac[3]) << 24) |
911c2653865SAlexander Duyck 			(((u32)vf_info->mac[4]) << 16) |
912c2653865SAlexander Duyck 			(((u32)vf_info->mac[5]) << 8);
913c2653865SAlexander Duyck 
914c2653865SAlexander Duyck 		tdbah = (((u32)0xFF)	        << 24) |
915c2653865SAlexander Duyck 			(((u32)vf_info->mac[0]) << 16) |
916c2653865SAlexander Duyck 			(((u32)vf_info->mac[1]) << 8) |
917c2653865SAlexander Duyck 			((u32)vf_info->mac[2]);
918c2653865SAlexander Duyck 	}
919c2653865SAlexander Duyck 
920c2653865SAlexander Duyck 	/* Record the base address into queue 0 */
921c2653865SAlexander Duyck 	fm10k_write_reg(hw, FM10K_TDBAL(vf_q_idx), tdbal);
922c2653865SAlexander Duyck 	fm10k_write_reg(hw, FM10K_TDBAH(vf_q_idx), tdbah);
923c2653865SAlexander Duyck 
92420076fa1SJacob Keller 	/* Provide the VF the ITR scale, using software-defined fields in TDLEN
92520076fa1SJacob Keller 	 * to pass the information during VF initialization. See definition of
92620076fa1SJacob Keller 	 * FM10K_TDLEN_ITR_SCALE_SHIFT for more details.
92720076fa1SJacob Keller 	 */
92820076fa1SJacob Keller 	fm10k_write_reg(hw, FM10K_TDLEN(vf_q_idx), hw->mac.itr_scale <<
92920076fa1SJacob Keller 						   FM10K_TDLEN_ITR_SCALE_SHIFT);
93020076fa1SJacob Keller 
931c2653865SAlexander Duyck err_out:
932c2653865SAlexander Duyck 	/* restore the queue back to VF ownership */
933c2653865SAlexander Duyck 	fm10k_write_reg(hw, FM10K_TQMAP(qmap_idx), vf_q_idx);
934c2653865SAlexander Duyck 	return err;
935c2653865SAlexander Duyck }
936c2653865SAlexander Duyck 
937c2653865SAlexander Duyck /**
938c2653865SAlexander Duyck  *  fm10k_iov_reset_resources_pf - Reassign queues and interrupts to a VF
939c2653865SAlexander Duyck  *  @hw: pointer to the HW structure
940c2653865SAlexander Duyck  *  @vf_info: pointer to VF information structure
941c2653865SAlexander Duyck  *
942c2653865SAlexander Duyck  *  Reassign the interrupts and queues to a VF following an FLR
943c2653865SAlexander Duyck  **/
fm10k_iov_reset_resources_pf(struct fm10k_hw * hw,struct fm10k_vf_info * vf_info)944c2653865SAlexander Duyck static s32 fm10k_iov_reset_resources_pf(struct fm10k_hw *hw,
945c2653865SAlexander Duyck 					struct fm10k_vf_info *vf_info)
946c2653865SAlexander Duyck {
947c2653865SAlexander Duyck 	u16 qmap_stride, queues_per_pool, vf_q_idx, qmap_idx;
948c2653865SAlexander Duyck 	u32 tdbal = 0, tdbah = 0, txqctl, rxqctl;
949c2653865SAlexander Duyck 	u16 vf_v_idx, vf_v_limit, vf_vid;
950c2653865SAlexander Duyck 	u8 vf_idx = vf_info->vf_idx;
951c2653865SAlexander Duyck 	int i;
952c2653865SAlexander Duyck 
953c2653865SAlexander Duyck 	/* verify vf is in range */
954c2653865SAlexander Duyck 	if (vf_idx >= hw->iov.num_vfs)
955c2653865SAlexander Duyck 		return FM10K_ERR_PARAM;
956c2653865SAlexander Duyck 
957c2653865SAlexander Duyck 	/* clear event notification of VF FLR */
958fcdb0a99SBruce Allan 	fm10k_write_reg(hw, FM10K_PFVFLREC(vf_idx / 32), BIT(vf_idx % 32));
959c2653865SAlexander Duyck 
960c2653865SAlexander Duyck 	/* force timeout and then disconnect the mailbox */
961c2653865SAlexander Duyck 	vf_info->mbx.timeout = 0;
962c2653865SAlexander Duyck 	if (vf_info->mbx.ops.disconnect)
963c2653865SAlexander Duyck 		vf_info->mbx.ops.disconnect(hw, &vf_info->mbx);
964c2653865SAlexander Duyck 
965c2653865SAlexander Duyck 	/* determine vector offset and count */
966c2653865SAlexander Duyck 	vf_v_idx = fm10k_vf_vector_index(hw, vf_idx);
967c2653865SAlexander Duyck 	vf_v_limit = vf_v_idx + fm10k_vectors_per_pool(hw);
968c2653865SAlexander Duyck 
969c2653865SAlexander Duyck 	/* determine qmap offsets and counts */
970c2653865SAlexander Duyck 	qmap_stride = (hw->iov.num_vfs > 8) ? 32 : 256;
971c2653865SAlexander Duyck 	queues_per_pool = fm10k_queues_per_pool(hw);
972c2653865SAlexander Duyck 	qmap_idx = qmap_stride * vf_idx;
973c2653865SAlexander Duyck 
974c2653865SAlexander Duyck 	/* make all the queues inaccessible to the VF */
975c2653865SAlexander Duyck 	for (i = qmap_idx; i < (qmap_idx + qmap_stride); i++) {
976c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_TQMAP(i), 0);
977c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_RQMAP(i), 0);
978c2653865SAlexander Duyck 	}
979c2653865SAlexander Duyck 
980c2653865SAlexander Duyck 	/* calculate starting index for queues */
981c2653865SAlexander Duyck 	vf_q_idx = fm10k_vf_queue_index(hw, vf_idx);
982c2653865SAlexander Duyck 
983c2653865SAlexander Duyck 	/* determine correct default VLAN ID */
984c2653865SAlexander Duyck 	if (vf_info->pf_vid)
985c2653865SAlexander Duyck 		vf_vid = vf_info->pf_vid;
986c2653865SAlexander Duyck 	else
987c2653865SAlexander Duyck 		vf_vid = vf_info->sw_vid;
988c2653865SAlexander Duyck 
989c2653865SAlexander Duyck 	/* configure Queue control register */
990c2653865SAlexander Duyck 	txqctl = ((u32)vf_vid << FM10K_TXQCTL_VID_SHIFT) |
991c2653865SAlexander Duyck 		 (vf_idx << FM10K_TXQCTL_TC_SHIFT) |
992c2653865SAlexander Duyck 		 FM10K_TXQCTL_VF | vf_idx;
9931aab144cSBruce Allan 	rxqctl = (vf_idx << FM10K_RXQCTL_VF_SHIFT) | FM10K_RXQCTL_VF;
994c2653865SAlexander Duyck 
995c2653865SAlexander Duyck 	/* stop further DMA and reset queue ownership back to VF */
996c2653865SAlexander Duyck 	for (i = vf_q_idx; i < (queues_per_pool + vf_q_idx); i++) {
997c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_TXDCTL(i), 0);
998c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_TXQCTL(i), txqctl);
999c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_RXDCTL(i),
1000c2653865SAlexander Duyck 				FM10K_RXDCTL_WRITE_BACK_MIN_DELAY |
1001c2653865SAlexander Duyck 				FM10K_RXDCTL_DROP_ON_EMPTY);
1002c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_RXQCTL(i), rxqctl);
1003c2653865SAlexander Duyck 	}
1004c2653865SAlexander Duyck 
1005c2653865SAlexander Duyck 	/* reset TC with -1 credits and no quanta to prevent transmit */
1006c2653865SAlexander Duyck 	fm10k_write_reg(hw, FM10K_TC_MAXCREDIT(vf_idx), 0);
1007c2653865SAlexander Duyck 	fm10k_write_reg(hw, FM10K_TC_RATE(vf_idx), 0);
1008c2653865SAlexander Duyck 	fm10k_write_reg(hw, FM10K_TC_CREDIT(vf_idx),
1009c2653865SAlexander Duyck 			FM10K_TC_CREDIT_CREDIT_MASK);
1010c2653865SAlexander Duyck 
1011c2653865SAlexander Duyck 	/* update our first entry in the table based on previous VF */
1012c2653865SAlexander Duyck 	if (!vf_idx)
1013c2653865SAlexander Duyck 		hw->mac.ops.update_int_moderator(hw);
1014c2653865SAlexander Duyck 	else
1015c2653865SAlexander Duyck 		hw->iov.ops.assign_int_moderator(hw, vf_idx - 1);
1016c2653865SAlexander Duyck 
1017c2653865SAlexander Duyck 	/* reset linked list so it now includes our active vectors */
1018c2653865SAlexander Duyck 	if (vf_idx == (hw->iov.num_vfs - 1))
1019c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_ITR2(0), vf_v_idx);
1020c2653865SAlexander Duyck 	else
1021c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_ITR2(vf_v_limit), vf_v_idx);
1022c2653865SAlexander Duyck 
1023c2653865SAlexander Duyck 	/* link remaining vectors so that next points to previous */
1024c2653865SAlexander Duyck 	for (vf_v_idx++; vf_v_idx < vf_v_limit; vf_v_idx++)
1025c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_ITR2(vf_v_idx), vf_v_idx - 1);
1026c2653865SAlexander Duyck 
1027c2653865SAlexander Duyck 	/* zero out MBMEM, VLAN_TABLE, RETA, RSSRK, and MRQC registers */
1028c2653865SAlexander Duyck 	for (i = FM10K_VFMBMEM_LEN; i--;)
1029c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_MBMEM_VF(vf_idx, i), 0);
1030c2653865SAlexander Duyck 	for (i = FM10K_VLAN_TABLE_SIZE; i--;)
1031c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_VLAN_TABLE(vf_info->vsi, i), 0);
1032c2653865SAlexander Duyck 	for (i = FM10K_RETA_SIZE; i--;)
1033c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_RETA(vf_info->vsi, i), 0);
1034c2653865SAlexander Duyck 	for (i = FM10K_RSSRK_SIZE; i--;)
1035c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_RSSRK(vf_info->vsi, i), 0);
1036c2653865SAlexander Duyck 	fm10k_write_reg(hw, FM10K_MRQC(vf_info->vsi), 0);
1037c2653865SAlexander Duyck 
1038c2653865SAlexander Duyck 	/* Update base address registers to contain MAC address */
1039c2653865SAlexander Duyck 	if (is_valid_ether_addr(vf_info->mac)) {
1040c2653865SAlexander Duyck 		tdbal = (((u32)vf_info->mac[3]) << 24) |
1041c2653865SAlexander Duyck 			(((u32)vf_info->mac[4]) << 16) |
1042c2653865SAlexander Duyck 			(((u32)vf_info->mac[5]) << 8);
1043c2653865SAlexander Duyck 		tdbah = (((u32)0xFF)	   << 24) |
1044c2653865SAlexander Duyck 			(((u32)vf_info->mac[0]) << 16) |
1045c2653865SAlexander Duyck 			(((u32)vf_info->mac[1]) << 8) |
1046c2653865SAlexander Duyck 			((u32)vf_info->mac[2]);
1047c2653865SAlexander Duyck 	}
1048c2653865SAlexander Duyck 
1049c2653865SAlexander Duyck 	/* map queue pairs back to VF from last to first */
1050c2653865SAlexander Duyck 	for (i = queues_per_pool; i--;) {
1051c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_TDBAL(vf_q_idx + i), tdbal);
1052c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_TDBAH(vf_q_idx + i), tdbah);
105320076fa1SJacob Keller 		/* See definition of FM10K_TDLEN_ITR_SCALE_SHIFT for an
105420076fa1SJacob Keller 		 * explanation of how TDLEN is used.
105520076fa1SJacob Keller 		 */
105620076fa1SJacob Keller 		fm10k_write_reg(hw, FM10K_TDLEN(vf_q_idx + i),
105720076fa1SJacob Keller 				hw->mac.itr_scale <<
105820076fa1SJacob Keller 				FM10K_TDLEN_ITR_SCALE_SHIFT);
1059c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_TQMAP(qmap_idx + i), vf_q_idx + i);
1060c2653865SAlexander Duyck 		fm10k_write_reg(hw, FM10K_RQMAP(qmap_idx + i), vf_q_idx + i);
1061c2653865SAlexander Duyck 	}
1062c2653865SAlexander Duyck 
1063fba341d5SJacob Keller 	/* repeat the first ring for all the remaining VF rings */
1064fba341d5SJacob Keller 	for (i = queues_per_pool; i < qmap_stride; i++) {
1065fba341d5SJacob Keller 		fm10k_write_reg(hw, FM10K_TQMAP(qmap_idx + i), vf_q_idx);
1066fba341d5SJacob Keller 		fm10k_write_reg(hw, FM10K_RQMAP(qmap_idx + i), vf_q_idx);
1067fba341d5SJacob Keller 	}
1068fba341d5SJacob Keller 
1069c2653865SAlexander Duyck 	return 0;
1070c2653865SAlexander Duyck }
1071c2653865SAlexander Duyck 
1072c2653865SAlexander Duyck /**
1073c2653865SAlexander Duyck  *  fm10k_iov_set_lport_pf - Assign and enable a logical port for a given VF
1074c2653865SAlexander Duyck  *  @hw: pointer to hardware structure
1075c2653865SAlexander Duyck  *  @vf_info: pointer to VF information structure
1076c2653865SAlexander Duyck  *  @lport_idx: Logical port offset from the hardware glort
1077c2653865SAlexander Duyck  *  @flags: Set of capability flags to extend port beyond basic functionality
1078c2653865SAlexander Duyck  *
1079c2653865SAlexander Duyck  *  This function allows enabling a VF port by assigning it a GLORT and
1080c2653865SAlexander Duyck  *  setting the flags so that it can enable an Rx mode.
1081c2653865SAlexander Duyck  **/
fm10k_iov_set_lport_pf(struct fm10k_hw * hw,struct fm10k_vf_info * vf_info,u16 lport_idx,u8 flags)1082c2653865SAlexander Duyck static s32 fm10k_iov_set_lport_pf(struct fm10k_hw *hw,
1083c2653865SAlexander Duyck 				  struct fm10k_vf_info *vf_info,
1084c2653865SAlexander Duyck 				  u16 lport_idx, u8 flags)
1085c2653865SAlexander Duyck {
1086c2653865SAlexander Duyck 	u16 glort = (hw->mac.dglort_map + lport_idx) & FM10K_DGLORTMAP_NONE;
1087c2653865SAlexander Duyck 
1088c2653865SAlexander Duyck 	/* if glort is not valid return error */
1089c2653865SAlexander Duyck 	if (!fm10k_glort_valid_pf(hw, glort))
1090c2653865SAlexander Duyck 		return FM10K_ERR_PARAM;
1091c2653865SAlexander Duyck 
1092c2653865SAlexander Duyck 	vf_info->vf_flags = flags | FM10K_VF_FLAG_NONE_CAPABLE;
1093c2653865SAlexander Duyck 	vf_info->glort = glort;
1094c2653865SAlexander Duyck 
1095c2653865SAlexander Duyck 	return 0;
1096c2653865SAlexander Duyck }
1097c2653865SAlexander Duyck 
1098c2653865SAlexander Duyck /**
1099c2653865SAlexander Duyck  *  fm10k_iov_reset_lport_pf - Disable a logical port for a given VF
1100c2653865SAlexander Duyck  *  @hw: pointer to hardware structure
1101c2653865SAlexander Duyck  *  @vf_info: pointer to VF information structure
1102c2653865SAlexander Duyck  *
1103c2653865SAlexander Duyck  *  This function disables a VF port by stripping it of a GLORT and
1104c2653865SAlexander Duyck  *  setting the flags so that it cannot enable any Rx mode.
1105c2653865SAlexander Duyck  **/
fm10k_iov_reset_lport_pf(struct fm10k_hw * hw,struct fm10k_vf_info * vf_info)1106c2653865SAlexander Duyck static void fm10k_iov_reset_lport_pf(struct fm10k_hw *hw,
1107c2653865SAlexander Duyck 				     struct fm10k_vf_info *vf_info)
1108c2653865SAlexander Duyck {
1109c2653865SAlexander Duyck 	u32 msg[1];
1110c2653865SAlexander Duyck 
1111c2653865SAlexander Duyck 	/* need to disable the port if it is already enabled */
1112c2653865SAlexander Duyck 	if (FM10K_VF_FLAG_ENABLED(vf_info)) {
1113c2653865SAlexander Duyck 		/* notify switch that this port has been disabled */
1114c2653865SAlexander Duyck 		fm10k_update_lport_state_pf(hw, vf_info->glort, 1, false);
1115c2653865SAlexander Duyck 
1116c2653865SAlexander Duyck 		/* generate port state response to notify VF it is not ready */
1117c2653865SAlexander Duyck 		fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_LPORT_STATE);
1118c2653865SAlexander Duyck 		vf_info->mbx.ops.enqueue_tx(hw, &vf_info->mbx, msg);
1119c2653865SAlexander Duyck 	}
1120c2653865SAlexander Duyck 
1121c2653865SAlexander Duyck 	/* clear flags and glort if it exists */
1122c2653865SAlexander Duyck 	vf_info->vf_flags = 0;
1123c2653865SAlexander Duyck 	vf_info->glort = 0;
1124c2653865SAlexander Duyck }
1125c2653865SAlexander Duyck 
1126c2653865SAlexander Duyck /**
1127c2653865SAlexander Duyck  *  fm10k_iov_update_stats_pf - Updates hardware related statistics for VFs
1128c2653865SAlexander Duyck  *  @hw: pointer to hardware structure
1129c2653865SAlexander Duyck  *  @q: stats for all queues of a VF
1130c2653865SAlexander Duyck  *  @vf_idx: index of VF
1131c2653865SAlexander Duyck  *
1132c2653865SAlexander Duyck  *  This function collects queue stats for VFs.
1133c2653865SAlexander Duyck  **/
fm10k_iov_update_stats_pf(struct fm10k_hw * hw,struct fm10k_hw_stats_q * q,u16 vf_idx)1134c2653865SAlexander Duyck static void fm10k_iov_update_stats_pf(struct fm10k_hw *hw,
1135c2653865SAlexander Duyck 				      struct fm10k_hw_stats_q *q,
1136c2653865SAlexander Duyck 				      u16 vf_idx)
1137c2653865SAlexander Duyck {
1138c2653865SAlexander Duyck 	u32 idx, qpp;
1139c2653865SAlexander Duyck 
1140c2653865SAlexander Duyck 	/* get stats for all of the queues */
1141c2653865SAlexander Duyck 	qpp = fm10k_queues_per_pool(hw);
1142c2653865SAlexander Duyck 	idx = fm10k_vf_queue_index(hw, vf_idx);
1143c2653865SAlexander Duyck 	fm10k_update_hw_stats_q(hw, q, idx, qpp);
1144c2653865SAlexander Duyck }
1145c2653865SAlexander Duyck 
1146c2653865SAlexander Duyck /**
1147c2653865SAlexander Duyck  *  fm10k_iov_msg_msix_pf - Message handler for MSI-X request from VF
1148c2653865SAlexander Duyck  *  @hw: Pointer to hardware structure
1149c2653865SAlexander Duyck  *  @results: Pointer array to message, results[0] is pointer to message
1150c2653865SAlexander Duyck  *  @mbx: Pointer to mailbox information structure
1151c2653865SAlexander Duyck  *
1152c2653865SAlexander Duyck  *  This function is a default handler for MSI-X requests from the VF. The
1153c2653865SAlexander Duyck  *  assumption is that in this case it is acceptable to just directly
1154eca32047SMatthew Vick  *  hand off the message from the VF to the underlying shared code.
1155c2653865SAlexander Duyck  **/
fm10k_iov_msg_msix_pf(struct fm10k_hw * hw,u32 __always_unused ** results,struct fm10k_mbx_info * mbx)1156d5c2f395SJacob Keller s32 fm10k_iov_msg_msix_pf(struct fm10k_hw *hw, u32 __always_unused **results,
1157c2653865SAlexander Duyck 			  struct fm10k_mbx_info *mbx)
1158c2653865SAlexander Duyck {
1159c2653865SAlexander Duyck 	struct fm10k_vf_info *vf_info = (struct fm10k_vf_info *)mbx;
1160c2653865SAlexander Duyck 	u8 vf_idx = vf_info->vf_idx;
1161c2653865SAlexander Duyck 
1162c2653865SAlexander Duyck 	return hw->iov.ops.assign_int_moderator(hw, vf_idx);
1163c2653865SAlexander Duyck }
1164c2653865SAlexander Duyck 
1165c2653865SAlexander Duyck /**
1166aa502b4aSJacob Keller  * fm10k_iov_select_vid - Select correct default VLAN ID
1167363656ebSJacob Keller  * @vf_info: pointer to VF information structure
1168aa502b4aSJacob Keller  * @vid: VLAN ID to correct
11699adbac59SJacob Keller  *
1170aa502b4aSJacob Keller  * Will report an error if the VLAN ID is out of range. For VID = 0, it will
1171aa502b4aSJacob Keller  * return either the pf_vid or sw_vid depending on which one is set.
11729adbac59SJacob Keller  */
fm10k_iov_select_vid(struct fm10k_vf_info * vf_info,u16 vid)11731f5c27e5SJacob Keller s32 fm10k_iov_select_vid(struct fm10k_vf_info *vf_info, u16 vid)
11749adbac59SJacob Keller {
11759adbac59SJacob Keller 	if (!vid)
11769adbac59SJacob Keller 		return vf_info->pf_vid ? vf_info->pf_vid : vf_info->sw_vid;
11779adbac59SJacob Keller 	else if (vf_info->pf_vid && vid != vf_info->pf_vid)
11789adbac59SJacob Keller 		return FM10K_ERR_PARAM;
11799adbac59SJacob Keller 	else
11809adbac59SJacob Keller 		return vid;
11819adbac59SJacob Keller }
11829adbac59SJacob Keller 
11839adbac59SJacob Keller /**
1184c2653865SAlexander Duyck  *  fm10k_iov_msg_mac_vlan_pf - Message handler for MAC/VLAN request from VF
1185c2653865SAlexander Duyck  *  @hw: Pointer to hardware structure
1186c2653865SAlexander Duyck  *  @results: Pointer array to message, results[0] is pointer to message
1187c2653865SAlexander Duyck  *  @mbx: Pointer to mailbox information structure
1188c2653865SAlexander Duyck  *
1189c2653865SAlexander Duyck  *  This function is a default handler for MAC/VLAN requests from the VF.
1190c2653865SAlexander Duyck  *  The assumption is that in this case it is acceptable to just directly
1191eca32047SMatthew Vick  *  hand off the message from the VF to the underlying shared code.
1192c2653865SAlexander Duyck  **/
fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw * hw,u32 ** results,struct fm10k_mbx_info * mbx)1193c2653865SAlexander Duyck s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results,
1194c2653865SAlexander Duyck 			      struct fm10k_mbx_info *mbx)
1195c2653865SAlexander Duyck {
1196c2653865SAlexander Duyck 	struct fm10k_vf_info *vf_info = (struct fm10k_vf_info *)mbx;
1197c2653865SAlexander Duyck 	u8 mac[ETH_ALEN];
1198c2653865SAlexander Duyck 	u32 *result;
11999adbac59SJacob Keller 	int err = 0;
12009adbac59SJacob Keller 	bool set;
1201c2653865SAlexander Duyck 	u16 vlan;
1202c2653865SAlexander Duyck 	u32 vid;
1203c2653865SAlexander Duyck 
1204c2653865SAlexander Duyck 	/* we shouldn't be updating rules on a disabled interface */
1205c2653865SAlexander Duyck 	if (!FM10K_VF_FLAG_ENABLED(vf_info))
1206c2653865SAlexander Duyck 		err = FM10K_ERR_PARAM;
1207c2653865SAlexander Duyck 
1208c2653865SAlexander Duyck 	if (!err && !!results[FM10K_MAC_VLAN_MSG_VLAN]) {
1209c2653865SAlexander Duyck 		result = results[FM10K_MAC_VLAN_MSG_VLAN];
1210c2653865SAlexander Duyck 
1211c2653865SAlexander Duyck 		/* record VLAN id requested */
1212c2653865SAlexander Duyck 		err = fm10k_tlv_attr_get_u32(result, &vid);
1213c2653865SAlexander Duyck 		if (err)
1214c2653865SAlexander Duyck 			return err;
1215c2653865SAlexander Duyck 
12169adbac59SJacob Keller 		set = !(vid & FM10K_VLAN_CLEAR);
12179adbac59SJacob Keller 		vid &= ~FM10K_VLAN_CLEAR;
12189adbac59SJacob Keller 
1219f808c5dbSJacob Keller 		/* if the length field has been set, this is a multi-bit
1220f808c5dbSJacob Keller 		 * update request. For multi-bit requests, simply disallow
1221f808c5dbSJacob Keller 		 * them when the pf_vid has been set. In this case, the PF
1222f808c5dbSJacob Keller 		 * should have already cleared the VLAN_TABLE, and if we
1223f808c5dbSJacob Keller 		 * allowed them, it could allow a rogue VF to receive traffic
1224f808c5dbSJacob Keller 		 * on a VLAN it was not assigned. In the single-bit case, we
1225f808c5dbSJacob Keller 		 * need to modify requests for VLAN 0 to use the default PF or
1226f808c5dbSJacob Keller 		 * SW vid when assigned.
1227f808c5dbSJacob Keller 		 */
1228f808c5dbSJacob Keller 
1229f808c5dbSJacob Keller 		if (vid >> 16) {
1230f808c5dbSJacob Keller 			/* prevent multi-bit requests when PF has
1231f808c5dbSJacob Keller 			 * administratively set the VLAN for this VF
1232f808c5dbSJacob Keller 			 */
1233f808c5dbSJacob Keller 			if (vf_info->pf_vid)
1234f808c5dbSJacob Keller 				return FM10K_ERR_PARAM;
1235f808c5dbSJacob Keller 		} else {
1236cdf32c94SJacob Keller 			err = fm10k_iov_select_vid(vf_info, (u16)vid);
12379adbac59SJacob Keller 			if (err < 0)
12389adbac59SJacob Keller 				return err;
12394ab0f79bSJacob Keller 
12409adbac59SJacob Keller 			vid = err;
1241f808c5dbSJacob Keller 		}
1242c2653865SAlexander Duyck 
1243c2653865SAlexander Duyck 		/* update VSI info for VF in regards to VLAN table */
12449adbac59SJacob Keller 		err = hw->mac.ops.update_vlan(hw, vid, vf_info->vsi, set);
1245c2653865SAlexander Duyck 	}
1246c2653865SAlexander Duyck 
1247c2653865SAlexander Duyck 	if (!err && !!results[FM10K_MAC_VLAN_MSG_MAC]) {
1248c2653865SAlexander Duyck 		result = results[FM10K_MAC_VLAN_MSG_MAC];
1249c2653865SAlexander Duyck 
1250c2653865SAlexander Duyck 		/* record unicast MAC address requested */
1251c2653865SAlexander Duyck 		err = fm10k_tlv_attr_get_mac_vlan(result, mac, &vlan);
1252c2653865SAlexander Duyck 		if (err)
1253c2653865SAlexander Duyck 			return err;
1254c2653865SAlexander Duyck 
1255c2653865SAlexander Duyck 		/* block attempts to set MAC for a locked device */
1256c2653865SAlexander Duyck 		if (is_valid_ether_addr(vf_info->mac) &&
12576186ddf0SJacob Keller 		    !ether_addr_equal(mac, vf_info->mac))
1258c2653865SAlexander Duyck 			return FM10K_ERR_PARAM;
1259c2653865SAlexander Duyck 
12609adbac59SJacob Keller 		set = !(vlan & FM10K_VLAN_CLEAR);
12619adbac59SJacob Keller 		vlan &= ~FM10K_VLAN_CLEAR;
12629adbac59SJacob Keller 
12639adbac59SJacob Keller 		err = fm10k_iov_select_vid(vf_info, vlan);
12649adbac59SJacob Keller 		if (err < 0)
12659adbac59SJacob Keller 			return err;
12664ab0f79bSJacob Keller 
1267cdf32c94SJacob Keller 		vlan = (u16)err;
1268c2653865SAlexander Duyck 
1269c2653865SAlexander Duyck 		/* notify switch of request for new unicast address */
12709adbac59SJacob Keller 		err = hw->mac.ops.update_uc_addr(hw, vf_info->glort,
12719adbac59SJacob Keller 						 mac, vlan, set, 0);
1272c2653865SAlexander Duyck 	}
1273c2653865SAlexander Duyck 
1274c2653865SAlexander Duyck 	if (!err && !!results[FM10K_MAC_VLAN_MSG_MULTICAST]) {
1275c2653865SAlexander Duyck 		result = results[FM10K_MAC_VLAN_MSG_MULTICAST];
1276c2653865SAlexander Duyck 
1277c2653865SAlexander Duyck 		/* record multicast MAC address requested */
1278c2653865SAlexander Duyck 		err = fm10k_tlv_attr_get_mac_vlan(result, mac, &vlan);
1279c2653865SAlexander Duyck 		if (err)
1280c2653865SAlexander Duyck 			return err;
1281c2653865SAlexander Duyck 
1282c2653865SAlexander Duyck 		/* verify that the VF is allowed to request multicast */
1283c2653865SAlexander Duyck 		if (!(vf_info->vf_flags & FM10K_VF_FLAG_MULTI_ENABLED))
1284c2653865SAlexander Duyck 			return FM10K_ERR_PARAM;
1285c2653865SAlexander Duyck 
12869adbac59SJacob Keller 		set = !(vlan & FM10K_VLAN_CLEAR);
12879adbac59SJacob Keller 		vlan &= ~FM10K_VLAN_CLEAR;
12889adbac59SJacob Keller 
12899adbac59SJacob Keller 		err = fm10k_iov_select_vid(vf_info, vlan);
12909adbac59SJacob Keller 		if (err < 0)
12919adbac59SJacob Keller 			return err;
12924ab0f79bSJacob Keller 
1293cdf32c94SJacob Keller 		vlan = (u16)err;
1294c2653865SAlexander Duyck 
1295c2653865SAlexander Duyck 		/* notify switch of request for new multicast address */
12969adbac59SJacob Keller 		err = hw->mac.ops.update_mc_addr(hw, vf_info->glort,
12979adbac59SJacob Keller 						 mac, vlan, set);
1298c2653865SAlexander Duyck 	}
1299c2653865SAlexander Duyck 
1300c2653865SAlexander Duyck 	return err;
1301c2653865SAlexander Duyck }
1302c2653865SAlexander Duyck 
1303c2653865SAlexander Duyck /**
1304c2653865SAlexander Duyck  *  fm10k_iov_supported_xcast_mode_pf - Determine best match for xcast mode
1305c2653865SAlexander Duyck  *  @vf_info: VF info structure containing capability flags
1306c2653865SAlexander Duyck  *  @mode: Requested xcast mode
1307c2653865SAlexander Duyck  *
1308c2653865SAlexander Duyck  *  This function outputs the mode that most closely matches the requested
1309c2653865SAlexander Duyck  *  mode.  If not modes match it will request we disable the port
1310c2653865SAlexander Duyck  **/
fm10k_iov_supported_xcast_mode_pf(struct fm10k_vf_info * vf_info,u8 mode)1311c2653865SAlexander Duyck static u8 fm10k_iov_supported_xcast_mode_pf(struct fm10k_vf_info *vf_info,
1312c2653865SAlexander Duyck 					    u8 mode)
1313c2653865SAlexander Duyck {
1314c2653865SAlexander Duyck 	u8 vf_flags = vf_info->vf_flags;
1315c2653865SAlexander Duyck 
1316c2653865SAlexander Duyck 	/* match up mode to capabilities as best as possible */
1317c2653865SAlexander Duyck 	switch (mode) {
1318c2653865SAlexander Duyck 	case FM10K_XCAST_MODE_PROMISC:
1319c2653865SAlexander Duyck 		if (vf_flags & FM10K_VF_FLAG_PROMISC_CAPABLE)
1320c2653865SAlexander Duyck 			return FM10K_XCAST_MODE_PROMISC;
13215463fce6SJeff Kirsher 		fallthrough;
1322c2653865SAlexander Duyck 	case FM10K_XCAST_MODE_ALLMULTI:
1323c2653865SAlexander Duyck 		if (vf_flags & FM10K_VF_FLAG_ALLMULTI_CAPABLE)
1324c2653865SAlexander Duyck 			return FM10K_XCAST_MODE_ALLMULTI;
13255463fce6SJeff Kirsher 		fallthrough;
1326c2653865SAlexander Duyck 	case FM10K_XCAST_MODE_MULTI:
1327c2653865SAlexander Duyck 		if (vf_flags & FM10K_VF_FLAG_MULTI_CAPABLE)
1328c2653865SAlexander Duyck 			return FM10K_XCAST_MODE_MULTI;
13295463fce6SJeff Kirsher 		fallthrough;
1330c2653865SAlexander Duyck 	case FM10K_XCAST_MODE_NONE:
1331c2653865SAlexander Duyck 		if (vf_flags & FM10K_VF_FLAG_NONE_CAPABLE)
1332c2653865SAlexander Duyck 			return FM10K_XCAST_MODE_NONE;
13335463fce6SJeff Kirsher 		fallthrough;
1334c2653865SAlexander Duyck 	default:
1335c2653865SAlexander Duyck 		break;
1336c2653865SAlexander Duyck 	}
1337c2653865SAlexander Duyck 
1338c2653865SAlexander Duyck 	/* disable interface as it should not be able to request any */
1339c2653865SAlexander Duyck 	return FM10K_XCAST_MODE_DISABLE;
1340c2653865SAlexander Duyck }
1341c2653865SAlexander Duyck 
1342c2653865SAlexander Duyck /**
1343c2653865SAlexander Duyck  *  fm10k_iov_msg_lport_state_pf - Message handler for port state requests
1344c2653865SAlexander Duyck  *  @hw: Pointer to hardware structure
1345c2653865SAlexander Duyck  *  @results: Pointer array to message, results[0] is pointer to message
1346c2653865SAlexander Duyck  *  @mbx: Pointer to mailbox information structure
1347c2653865SAlexander Duyck  *
1348c2653865SAlexander Duyck  *  This function is a default handler for port state requests.  The port
1349c2653865SAlexander Duyck  *  state requests for now are basic and consist of enabling or disabling
1350c2653865SAlexander Duyck  *  the port.
1351c2653865SAlexander Duyck  **/
fm10k_iov_msg_lport_state_pf(struct fm10k_hw * hw,u32 ** results,struct fm10k_mbx_info * mbx)1352c2653865SAlexander Duyck s32 fm10k_iov_msg_lport_state_pf(struct fm10k_hw *hw, u32 **results,
1353c2653865SAlexander Duyck 				 struct fm10k_mbx_info *mbx)
1354c2653865SAlexander Duyck {
1355c2653865SAlexander Duyck 	struct fm10k_vf_info *vf_info = (struct fm10k_vf_info *)mbx;
1356c2653865SAlexander Duyck 	s32 err = 0;
1357c2653865SAlexander Duyck 	u32 msg[2];
1358c2653865SAlexander Duyck 	u8 mode = 0;
1359c2653865SAlexander Duyck 
1360c2653865SAlexander Duyck 	/* verify VF is allowed to enable even minimal mode */
1361c2653865SAlexander Duyck 	if (!(vf_info->vf_flags & FM10K_VF_FLAG_NONE_CAPABLE))
1362c2653865SAlexander Duyck 		return FM10K_ERR_PARAM;
1363c2653865SAlexander Duyck 
1364c2653865SAlexander Duyck 	if (!!results[FM10K_LPORT_STATE_MSG_XCAST_MODE]) {
13658e03f26bSJacob Keller 		u32 *result = results[FM10K_LPORT_STATE_MSG_XCAST_MODE];
1366c2653865SAlexander Duyck 
1367c2653865SAlexander Duyck 		/* XCAST mode update requested */
1368c2653865SAlexander Duyck 		err = fm10k_tlv_attr_get_u8(result, &mode);
1369c2653865SAlexander Duyck 		if (err)
1370c2653865SAlexander Duyck 			return FM10K_ERR_PARAM;
1371c2653865SAlexander Duyck 
1372c2653865SAlexander Duyck 		/* prep for possible demotion depending on capabilities */
1373c2653865SAlexander Duyck 		mode = fm10k_iov_supported_xcast_mode_pf(vf_info, mode);
1374c2653865SAlexander Duyck 
1375c2653865SAlexander Duyck 		/* if mode is not currently enabled, enable it */
1376fcdb0a99SBruce Allan 		if (!(FM10K_VF_FLAG_ENABLED(vf_info) & BIT(mode)))
1377c2653865SAlexander Duyck 			fm10k_update_xcast_mode_pf(hw, vf_info->glort, mode);
1378c2653865SAlexander Duyck 
1379c2653865SAlexander Duyck 		/* swap mode back to a bit flag */
1380c2653865SAlexander Duyck 		mode = FM10K_VF_FLAG_SET_MODE(mode);
1381c2653865SAlexander Duyck 	} else if (!results[FM10K_LPORT_STATE_MSG_DISABLE]) {
1382c2653865SAlexander Duyck 		/* need to disable the port if it is already enabled */
1383c2653865SAlexander Duyck 		if (FM10K_VF_FLAG_ENABLED(vf_info))
1384c2653865SAlexander Duyck 			err = fm10k_update_lport_state_pf(hw, vf_info->glort,
1385c2653865SAlexander Duyck 							  1, false);
1386c2653865SAlexander Duyck 
1387ee4373e7SJacob Keller 		/* we need to clear VF_FLAG_ENABLED flags in order to ensure
1388ee4373e7SJacob Keller 		 * that we actually re-enable the LPORT state below. Note that
1389ee4373e7SJacob Keller 		 * this has no impact if the VF is already disabled, as the
1390ee4373e7SJacob Keller 		 * flags are already cleared.
1391ee4373e7SJacob Keller 		 */
1392ee4373e7SJacob Keller 		if (!err)
1393ee4373e7SJacob Keller 			vf_info->vf_flags = FM10K_VF_FLAG_CAPABLE(vf_info);
1394ee4373e7SJacob Keller 
1395c2653865SAlexander Duyck 		/* when enabling the port we should reset the rate limiters */
1396c2653865SAlexander Duyck 		hw->iov.ops.configure_tc(hw, vf_info->vf_idx, vf_info->rate);
1397c2653865SAlexander Duyck 
1398c2653865SAlexander Duyck 		/* set mode for minimal functionality */
1399c2653865SAlexander Duyck 		mode = FM10K_VF_FLAG_SET_MODE_NONE;
1400c2653865SAlexander Duyck 
1401c2653865SAlexander Duyck 		/* generate port state response to notify VF it is ready */
1402c2653865SAlexander Duyck 		fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_LPORT_STATE);
1403c2653865SAlexander Duyck 		fm10k_tlv_attr_put_bool(msg, FM10K_LPORT_STATE_MSG_READY);
1404c2653865SAlexander Duyck 		mbx->ops.enqueue_tx(hw, mbx, msg);
1405c2653865SAlexander Duyck 	}
1406c2653865SAlexander Duyck 
1407c2653865SAlexander Duyck 	/* if enable state toggled note the update */
1408c2653865SAlexander Duyck 	if (!err && (!FM10K_VF_FLAG_ENABLED(vf_info) != !mode))
1409c2653865SAlexander Duyck 		err = fm10k_update_lport_state_pf(hw, vf_info->glort, 1,
1410c2653865SAlexander Duyck 						  !!mode);
1411c2653865SAlexander Duyck 
1412c2653865SAlexander Duyck 	/* if state change succeeded, then update our stored state */
1413c2653865SAlexander Duyck 	mode |= FM10K_VF_FLAG_CAPABLE(vf_info);
1414c2653865SAlexander Duyck 	if (!err)
1415c2653865SAlexander Duyck 		vf_info->vf_flags = mode;
1416c2653865SAlexander Duyck 
1417c2653865SAlexander Duyck 	return err;
1418c2653865SAlexander Duyck }
1419c2653865SAlexander Duyck 
1420401b5383SAlexander Duyck /**
1421262de08fSJesse Brandeburg  *  fm10k_update_hw_stats_pf - Updates hardware related statistics of PF
1422b6fec18fSAlexander Duyck  *  @hw: pointer to hardware structure
1423b6fec18fSAlexander Duyck  *  @stats: pointer to the stats structure to update
1424b6fec18fSAlexander Duyck  *
1425b6fec18fSAlexander Duyck  *  This function collects and aggregates global and per queue hardware
1426b6fec18fSAlexander Duyck  *  statistics.
1427b6fec18fSAlexander Duyck  **/
fm10k_update_hw_stats_pf(struct fm10k_hw * hw,struct fm10k_hw_stats * stats)1428b6fec18fSAlexander Duyck static void fm10k_update_hw_stats_pf(struct fm10k_hw *hw,
1429b6fec18fSAlexander Duyck 				     struct fm10k_hw_stats *stats)
1430b6fec18fSAlexander Duyck {
1431b6fec18fSAlexander Duyck 	u32 timeout, ur, ca, um, xec, vlan_drop, loopback_drop, nodesc_drop;
1432b6fec18fSAlexander Duyck 	u32 id, id_prev;
1433b6fec18fSAlexander Duyck 
1434b6fec18fSAlexander Duyck 	/* Use Tx queue 0 as a canary to detect a reset */
1435b6fec18fSAlexander Duyck 	id = fm10k_read_reg(hw, FM10K_TXQCTL(0));
1436b6fec18fSAlexander Duyck 
1437b6fec18fSAlexander Duyck 	/* Read Global Statistics */
1438b6fec18fSAlexander Duyck 	do {
1439b6fec18fSAlexander Duyck 		timeout = fm10k_read_hw_stats_32b(hw, FM10K_STATS_TIMEOUT,
1440b6fec18fSAlexander Duyck 						  &stats->timeout);
1441b6fec18fSAlexander Duyck 		ur = fm10k_read_hw_stats_32b(hw, FM10K_STATS_UR, &stats->ur);
1442b6fec18fSAlexander Duyck 		ca = fm10k_read_hw_stats_32b(hw, FM10K_STATS_CA, &stats->ca);
1443b6fec18fSAlexander Duyck 		um = fm10k_read_hw_stats_32b(hw, FM10K_STATS_UM, &stats->um);
1444b6fec18fSAlexander Duyck 		xec = fm10k_read_hw_stats_32b(hw, FM10K_STATS_XEC, &stats->xec);
1445b6fec18fSAlexander Duyck 		vlan_drop = fm10k_read_hw_stats_32b(hw, FM10K_STATS_VLAN_DROP,
1446b6fec18fSAlexander Duyck 						    &stats->vlan_drop);
14473d02b3dfSBruce Allan 		loopback_drop =
14483d02b3dfSBruce Allan 			fm10k_read_hw_stats_32b(hw,
1449b6fec18fSAlexander Duyck 						FM10K_STATS_LOOPBACK_DROP,
1450b6fec18fSAlexander Duyck 						&stats->loopback_drop);
1451b6fec18fSAlexander Duyck 		nodesc_drop = fm10k_read_hw_stats_32b(hw,
1452b6fec18fSAlexander Duyck 						      FM10K_STATS_NODESC_DROP,
1453b6fec18fSAlexander Duyck 						      &stats->nodesc_drop);
1454b6fec18fSAlexander Duyck 
1455b6fec18fSAlexander Duyck 		/* if value has not changed then we have consistent data */
1456b6fec18fSAlexander Duyck 		id_prev = id;
1457b6fec18fSAlexander Duyck 		id = fm10k_read_reg(hw, FM10K_TXQCTL(0));
1458b6fec18fSAlexander Duyck 	} while ((id ^ id_prev) & FM10K_TXQCTL_ID_MASK);
1459b6fec18fSAlexander Duyck 
1460b6fec18fSAlexander Duyck 	/* drop non-ID bits and set VALID ID bit */
1461b6fec18fSAlexander Duyck 	id &= FM10K_TXQCTL_ID_MASK;
1462b6fec18fSAlexander Duyck 	id |= FM10K_STAT_VALID;
1463b6fec18fSAlexander Duyck 
1464b6fec18fSAlexander Duyck 	/* Update Global Statistics */
1465b6fec18fSAlexander Duyck 	if (stats->stats_idx == id) {
1466b6fec18fSAlexander Duyck 		stats->timeout.count += timeout;
1467b6fec18fSAlexander Duyck 		stats->ur.count += ur;
1468b6fec18fSAlexander Duyck 		stats->ca.count += ca;
1469b6fec18fSAlexander Duyck 		stats->um.count += um;
1470b6fec18fSAlexander Duyck 		stats->xec.count += xec;
1471b6fec18fSAlexander Duyck 		stats->vlan_drop.count += vlan_drop;
1472b6fec18fSAlexander Duyck 		stats->loopback_drop.count += loopback_drop;
1473b6fec18fSAlexander Duyck 		stats->nodesc_drop.count += nodesc_drop;
1474b6fec18fSAlexander Duyck 	}
1475b6fec18fSAlexander Duyck 
1476b6fec18fSAlexander Duyck 	/* Update bases and record current PF id */
1477b6fec18fSAlexander Duyck 	fm10k_update_hw_base_32b(&stats->timeout, timeout);
1478b6fec18fSAlexander Duyck 	fm10k_update_hw_base_32b(&stats->ur, ur);
1479b6fec18fSAlexander Duyck 	fm10k_update_hw_base_32b(&stats->ca, ca);
1480b6fec18fSAlexander Duyck 	fm10k_update_hw_base_32b(&stats->um, um);
1481b6fec18fSAlexander Duyck 	fm10k_update_hw_base_32b(&stats->xec, xec);
1482b6fec18fSAlexander Duyck 	fm10k_update_hw_base_32b(&stats->vlan_drop, vlan_drop);
1483b6fec18fSAlexander Duyck 	fm10k_update_hw_base_32b(&stats->loopback_drop, loopback_drop);
1484b6fec18fSAlexander Duyck 	fm10k_update_hw_base_32b(&stats->nodesc_drop, nodesc_drop);
1485b6fec18fSAlexander Duyck 	stats->stats_idx = id;
1486b6fec18fSAlexander Duyck 
1487b6fec18fSAlexander Duyck 	/* Update Queue Statistics */
1488b6fec18fSAlexander Duyck 	fm10k_update_hw_stats_q(hw, stats->q, 0, hw->mac.max_queues);
1489b6fec18fSAlexander Duyck }
1490b6fec18fSAlexander Duyck 
1491b6fec18fSAlexander Duyck /**
1492b6fec18fSAlexander Duyck  *  fm10k_rebind_hw_stats_pf - Resets base for hardware statistics of PF
1493b6fec18fSAlexander Duyck  *  @hw: pointer to hardware structure
1494b6fec18fSAlexander Duyck  *  @stats: pointer to the stats structure to update
1495b6fec18fSAlexander Duyck  *
1496b6fec18fSAlexander Duyck  *  This function resets the base for global and per queue hardware
1497b6fec18fSAlexander Duyck  *  statistics.
1498b6fec18fSAlexander Duyck  **/
fm10k_rebind_hw_stats_pf(struct fm10k_hw * hw,struct fm10k_hw_stats * stats)1499b6fec18fSAlexander Duyck static void fm10k_rebind_hw_stats_pf(struct fm10k_hw *hw,
1500b6fec18fSAlexander Duyck 				     struct fm10k_hw_stats *stats)
1501b6fec18fSAlexander Duyck {
1502b6fec18fSAlexander Duyck 	/* Unbind Global Statistics */
1503b6fec18fSAlexander Duyck 	fm10k_unbind_hw_stats_32b(&stats->timeout);
1504b6fec18fSAlexander Duyck 	fm10k_unbind_hw_stats_32b(&stats->ur);
1505b6fec18fSAlexander Duyck 	fm10k_unbind_hw_stats_32b(&stats->ca);
1506b6fec18fSAlexander Duyck 	fm10k_unbind_hw_stats_32b(&stats->um);
1507b6fec18fSAlexander Duyck 	fm10k_unbind_hw_stats_32b(&stats->xec);
1508b6fec18fSAlexander Duyck 	fm10k_unbind_hw_stats_32b(&stats->vlan_drop);
1509b6fec18fSAlexander Duyck 	fm10k_unbind_hw_stats_32b(&stats->loopback_drop);
1510b6fec18fSAlexander Duyck 	fm10k_unbind_hw_stats_32b(&stats->nodesc_drop);
1511b6fec18fSAlexander Duyck 
1512b6fec18fSAlexander Duyck 	/* Unbind Queue Statistics */
1513b6fec18fSAlexander Duyck 	fm10k_unbind_hw_stats_q(stats->q, 0, hw->mac.max_queues);
1514b6fec18fSAlexander Duyck 
1515b6fec18fSAlexander Duyck 	/* Reinitialize bases for all stats */
1516b6fec18fSAlexander Duyck 	fm10k_update_hw_stats_pf(hw, stats);
1517b6fec18fSAlexander Duyck }
1518b6fec18fSAlexander Duyck 
1519b6fec18fSAlexander Duyck /**
1520401b5383SAlexander Duyck  *  fm10k_set_dma_mask_pf - Configures PhyAddrSpace to limit DMA to system
1521401b5383SAlexander Duyck  *  @hw: pointer to hardware structure
1522401b5383SAlexander Duyck  *  @dma_mask: 64 bit DMA mask required for platform
1523401b5383SAlexander Duyck  *
1524401b5383SAlexander Duyck  *  This function sets the PHYADDR.PhyAddrSpace bits for the endpoint in order
1525401b5383SAlexander Duyck  *  to limit the access to memory beyond what is physically in the system.
1526401b5383SAlexander Duyck  **/
fm10k_set_dma_mask_pf(struct fm10k_hw * hw,u64 dma_mask)1527401b5383SAlexander Duyck static void fm10k_set_dma_mask_pf(struct fm10k_hw *hw, u64 dma_mask)
1528401b5383SAlexander Duyck {
1529401b5383SAlexander Duyck 	/* we need to write the upper 32 bits of DMA mask to PhyAddrSpace */
1530401b5383SAlexander Duyck 	u32 phyaddr = (u32)(dma_mask >> 32);
1531401b5383SAlexander Duyck 
1532401b5383SAlexander Duyck 	fm10k_write_reg(hw, FM10K_PHYADDR, phyaddr);
1533401b5383SAlexander Duyck }
1534401b5383SAlexander Duyck 
1535401b5383SAlexander Duyck /**
1536b6fec18fSAlexander Duyck  *  fm10k_get_fault_pf - Record a fault in one of the interface units
1537b6fec18fSAlexander Duyck  *  @hw: pointer to hardware structure
1538b6fec18fSAlexander Duyck  *  @type: pointer to fault type register offset
1539b6fec18fSAlexander Duyck  *  @fault: pointer to memory location to record the fault
1540b6fec18fSAlexander Duyck  *
1541b6fec18fSAlexander Duyck  *  Record the fault register contents to the fault data structure and
1542b6fec18fSAlexander Duyck  *  clear the entry from the register.
1543b6fec18fSAlexander Duyck  *
1544b6fec18fSAlexander Duyck  *  Returns ERR_PARAM if invalid register is specified or no error is present.
1545b6fec18fSAlexander Duyck  **/
fm10k_get_fault_pf(struct fm10k_hw * hw,int type,struct fm10k_fault * fault)1546b6fec18fSAlexander Duyck static s32 fm10k_get_fault_pf(struct fm10k_hw *hw, int type,
1547b6fec18fSAlexander Duyck 			      struct fm10k_fault *fault)
1548b6fec18fSAlexander Duyck {
1549b6fec18fSAlexander Duyck 	u32 func;
1550b6fec18fSAlexander Duyck 
1551b6fec18fSAlexander Duyck 	/* verify the fault register is in range and is aligned */
1552b6fec18fSAlexander Duyck 	switch (type) {
1553b6fec18fSAlexander Duyck 	case FM10K_PCA_FAULT:
1554b6fec18fSAlexander Duyck 	case FM10K_THI_FAULT:
1555b6fec18fSAlexander Duyck 	case FM10K_FUM_FAULT:
1556b6fec18fSAlexander Duyck 		break;
1557b6fec18fSAlexander Duyck 	default:
1558b6fec18fSAlexander Duyck 		return FM10K_ERR_PARAM;
1559b6fec18fSAlexander Duyck 	}
1560b6fec18fSAlexander Duyck 
1561b6fec18fSAlexander Duyck 	/* only service faults that are valid */
1562b6fec18fSAlexander Duyck 	func = fm10k_read_reg(hw, type + FM10K_FAULT_FUNC);
1563b6fec18fSAlexander Duyck 	if (!(func & FM10K_FAULT_FUNC_VALID))
1564b6fec18fSAlexander Duyck 		return FM10K_ERR_PARAM;
1565b6fec18fSAlexander Duyck 
1566b6fec18fSAlexander Duyck 	/* read remaining fields */
1567b6fec18fSAlexander Duyck 	fault->address = fm10k_read_reg(hw, type + FM10K_FAULT_ADDR_HI);
1568b6fec18fSAlexander Duyck 	fault->address <<= 32;
15691fa475feSJacob Keller 	fault->address |= fm10k_read_reg(hw, type + FM10K_FAULT_ADDR_LO);
1570b6fec18fSAlexander Duyck 	fault->specinfo = fm10k_read_reg(hw, type + FM10K_FAULT_SPECINFO);
1571b6fec18fSAlexander Duyck 
1572b6fec18fSAlexander Duyck 	/* clear valid bit to allow for next error */
1573b6fec18fSAlexander Duyck 	fm10k_write_reg(hw, type + FM10K_FAULT_FUNC, FM10K_FAULT_FUNC_VALID);
1574b6fec18fSAlexander Duyck 
1575b6fec18fSAlexander Duyck 	/* Record which function triggered the error */
1576b6fec18fSAlexander Duyck 	if (func & FM10K_FAULT_FUNC_PF)
1577b6fec18fSAlexander Duyck 		fault->func = 0;
1578b6fec18fSAlexander Duyck 	else
1579*d5752c7bSJesse Brandeburg 		fault->func = 1 + FIELD_GET(FM10K_FAULT_FUNC_VF_MASK, func);
1580b6fec18fSAlexander Duyck 
1581b6fec18fSAlexander Duyck 	/* record fault type */
1582b6fec18fSAlexander Duyck 	fault->type = func & FM10K_FAULT_FUNC_TYPE_MASK;
1583b6fec18fSAlexander Duyck 
1584b6fec18fSAlexander Duyck 	return 0;
1585b6fec18fSAlexander Duyck }
1586b6fec18fSAlexander Duyck 
1587401b5383SAlexander Duyck /**
1588401b5383SAlexander Duyck  *  fm10k_request_lport_map_pf - Request LPORT map from the switch API
1589401b5383SAlexander Duyck  *  @hw: pointer to hardware structure
1590401b5383SAlexander Duyck  *
1591401b5383SAlexander Duyck  **/
fm10k_request_lport_map_pf(struct fm10k_hw * hw)1592401b5383SAlexander Duyck static s32 fm10k_request_lport_map_pf(struct fm10k_hw *hw)
1593401b5383SAlexander Duyck {
1594401b5383SAlexander Duyck 	struct fm10k_mbx_info *mbx = &hw->mbx;
1595401b5383SAlexander Duyck 	u32 msg[1];
1596401b5383SAlexander Duyck 
1597401b5383SAlexander Duyck 	/* issue request asking for LPORT map */
1598401b5383SAlexander Duyck 	fm10k_tlv_msg_init(msg, FM10K_PF_MSG_ID_LPORT_MAP);
1599401b5383SAlexander Duyck 
1600401b5383SAlexander Duyck 	/* load onto outgoing mailbox */
1601401b5383SAlexander Duyck 	return mbx->ops.enqueue_tx(hw, mbx, msg);
1602401b5383SAlexander Duyck }
1603401b5383SAlexander Duyck 
1604401b5383SAlexander Duyck /**
1605401b5383SAlexander Duyck  *  fm10k_get_host_state_pf - Returns the state of the switch and mailbox
1606401b5383SAlexander Duyck  *  @hw: pointer to hardware structure
1607401b5383SAlexander Duyck  *  @switch_ready: pointer to boolean value that will record switch state
1608401b5383SAlexander Duyck  *
1609d8ec92f2SJacob Keller  *  This function will check the DMA_CTRL2 register and mailbox in order
1610401b5383SAlexander Duyck  *  to determine if the switch is ready for the PF to begin requesting
1611401b5383SAlexander Duyck  *  addresses and mapping traffic to the local interface.
1612401b5383SAlexander Duyck  **/
fm10k_get_host_state_pf(struct fm10k_hw * hw,bool * switch_ready)1613401b5383SAlexander Duyck static s32 fm10k_get_host_state_pf(struct fm10k_hw *hw, bool *switch_ready)
1614401b5383SAlexander Duyck {
1615401b5383SAlexander Duyck 	u32 dma_ctrl2;
1616401b5383SAlexander Duyck 
1617eca32047SMatthew Vick 	/* verify the switch is ready for interaction */
1618401b5383SAlexander Duyck 	dma_ctrl2 = fm10k_read_reg(hw, FM10K_DMA_CTRL2);
1619401b5383SAlexander Duyck 	if (!(dma_ctrl2 & FM10K_DMA_CTRL2_SWITCH_READY))
16200afd20e5SJacob Keller 		return 0;
1621401b5383SAlexander Duyck 
1622401b5383SAlexander Duyck 	/* retrieve generic host state info */
16230afd20e5SJacob Keller 	return fm10k_get_host_state_generic(hw, switch_ready);
1624401b5383SAlexander Duyck }
1625401b5383SAlexander Duyck 
1626401b5383SAlexander Duyck /* This structure defines the attibutes to be parsed below */
1627401b5383SAlexander Duyck const struct fm10k_tlv_attr fm10k_lport_map_msg_attr[] = {
1628a7a7783aSJacob Keller 	FM10K_TLV_ATTR_LE_STRUCT(FM10K_PF_ATTR_ID_ERR,
1629a7a7783aSJacob Keller 				 sizeof(struct fm10k_swapi_error)),
1630401b5383SAlexander Duyck 	FM10K_TLV_ATTR_U32(FM10K_PF_ATTR_ID_LPORT_MAP),
1631401b5383SAlexander Duyck 	FM10K_TLV_ATTR_LAST
1632401b5383SAlexander Duyck };
1633401b5383SAlexander Duyck 
1634401b5383SAlexander Duyck /**
1635401b5383SAlexander Duyck  *  fm10k_msg_lport_map_pf - Message handler for lport_map message from SM
1636401b5383SAlexander Duyck  *  @hw: Pointer to hardware structure
1637401b5383SAlexander Duyck  *  @results: pointer array containing parsed data
1638401b5383SAlexander Duyck  *  @mbx: Pointer to mailbox information structure
1639401b5383SAlexander Duyck  *
1640401b5383SAlexander Duyck  *  This handler configures the lport mapping based on the reply from the
1641401b5383SAlexander Duyck  *  switch API.
1642401b5383SAlexander Duyck  **/
fm10k_msg_lport_map_pf(struct fm10k_hw * hw,u32 ** results,struct fm10k_mbx_info __always_unused * mbx)1643401b5383SAlexander Duyck s32 fm10k_msg_lport_map_pf(struct fm10k_hw *hw, u32 **results,
1644d5c2f395SJacob Keller 			   struct fm10k_mbx_info __always_unused *mbx)
1645401b5383SAlexander Duyck {
1646401b5383SAlexander Duyck 	u16 glort, mask;
1647401b5383SAlexander Duyck 	u32 dglort_map;
1648401b5383SAlexander Duyck 	s32 err;
1649401b5383SAlexander Duyck 
1650401b5383SAlexander Duyck 	err = fm10k_tlv_attr_get_u32(results[FM10K_PF_ATTR_ID_LPORT_MAP],
1651401b5383SAlexander Duyck 				     &dglort_map);
1652401b5383SAlexander Duyck 	if (err)
1653401b5383SAlexander Duyck 		return err;
1654401b5383SAlexander Duyck 
1655401b5383SAlexander Duyck 	/* extract values out of the header */
1656401b5383SAlexander Duyck 	glort = FM10K_MSG_HDR_FIELD_GET(dglort_map, LPORT_MAP_GLORT);
1657401b5383SAlexander Duyck 	mask = FM10K_MSG_HDR_FIELD_GET(dglort_map, LPORT_MAP_MASK);
1658401b5383SAlexander Duyck 
1659401b5383SAlexander Duyck 	/* verify mask is set and none of the masked bits in glort are set */
1660401b5383SAlexander Duyck 	if (!mask || (glort & ~mask))
1661401b5383SAlexander Duyck 		return FM10K_ERR_PARAM;
1662401b5383SAlexander Duyck 
1663401b5383SAlexander Duyck 	/* verify the mask is contiguous, and that it is 1's followed by 0's */
1664401b5383SAlexander Duyck 	if (((~(mask - 1) & mask) + mask) & FM10K_DGLORTMAP_NONE)
1665401b5383SAlexander Duyck 		return FM10K_ERR_PARAM;
1666401b5383SAlexander Duyck 
1667401b5383SAlexander Duyck 	/* record the glort, mask, and port count */
1668401b5383SAlexander Duyck 	hw->mac.dglort_map = dglort_map;
1669401b5383SAlexander Duyck 
1670401b5383SAlexander Duyck 	return 0;
1671401b5383SAlexander Duyck }
1672401b5383SAlexander Duyck 
1673401b5383SAlexander Duyck const struct fm10k_tlv_attr fm10k_update_pvid_msg_attr[] = {
1674401b5383SAlexander Duyck 	FM10K_TLV_ATTR_U32(FM10K_PF_ATTR_ID_UPDATE_PVID),
1675401b5383SAlexander Duyck 	FM10K_TLV_ATTR_LAST
1676401b5383SAlexander Duyck };
1677401b5383SAlexander Duyck 
1678401b5383SAlexander Duyck /**
1679401b5383SAlexander Duyck  *  fm10k_msg_update_pvid_pf - Message handler for port VLAN message from SM
1680401b5383SAlexander Duyck  *  @hw: Pointer to hardware structure
1681401b5383SAlexander Duyck  *  @results: pointer array containing parsed data
1682401b5383SAlexander Duyck  *  @mbx: Pointer to mailbox information structure
1683401b5383SAlexander Duyck  *
1684401b5383SAlexander Duyck  *  This handler configures the default VLAN for the PF
1685401b5383SAlexander Duyck  **/
fm10k_msg_update_pvid_pf(struct fm10k_hw * hw,u32 ** results,struct fm10k_mbx_info __always_unused * mbx)1686bb269e8bSBruce Allan static s32 fm10k_msg_update_pvid_pf(struct fm10k_hw *hw, u32 **results,
1687d5c2f395SJacob Keller 				    struct fm10k_mbx_info __always_unused *mbx)
1688401b5383SAlexander Duyck {
1689401b5383SAlexander Duyck 	u16 glort, pvid;
1690401b5383SAlexander Duyck 	u32 pvid_update;
1691401b5383SAlexander Duyck 	s32 err;
1692401b5383SAlexander Duyck 
1693401b5383SAlexander Duyck 	err = fm10k_tlv_attr_get_u32(results[FM10K_PF_ATTR_ID_UPDATE_PVID],
1694401b5383SAlexander Duyck 				     &pvid_update);
1695401b5383SAlexander Duyck 	if (err)
1696401b5383SAlexander Duyck 		return err;
1697401b5383SAlexander Duyck 
1698401b5383SAlexander Duyck 	/* extract values from the pvid update */
1699401b5383SAlexander Duyck 	glort = FM10K_MSG_HDR_FIELD_GET(pvid_update, UPDATE_PVID_GLORT);
1700401b5383SAlexander Duyck 	pvid = FM10K_MSG_HDR_FIELD_GET(pvid_update, UPDATE_PVID_PVID);
1701401b5383SAlexander Duyck 
1702401b5383SAlexander Duyck 	/* if glort is not valid return error */
1703401b5383SAlexander Duyck 	if (!fm10k_glort_valid_pf(hw, glort))
1704401b5383SAlexander Duyck 		return FM10K_ERR_PARAM;
1705401b5383SAlexander Duyck 
1706aa502b4aSJacob Keller 	/* verify VLAN ID is valid */
1707401b5383SAlexander Duyck 	if (pvid >= FM10K_VLAN_TABLE_VID_MAX)
1708401b5383SAlexander Duyck 		return FM10K_ERR_PARAM;
1709401b5383SAlexander Duyck 
1710401b5383SAlexander Duyck 	/* record the port VLAN ID value */
1711401b5383SAlexander Duyck 	hw->mac.default_vid = pvid;
1712401b5383SAlexander Duyck 
1713401b5383SAlexander Duyck 	return 0;
1714401b5383SAlexander Duyck }
1715401b5383SAlexander Duyck 
1716401b5383SAlexander Duyck /**
1717401b5383SAlexander Duyck  *  fm10k_record_global_table_data - Move global table data to swapi table info
1718401b5383SAlexander Duyck  *  @from: pointer to source table data structure
1719401b5383SAlexander Duyck  *  @to: pointer to destination table info structure
1720401b5383SAlexander Duyck  *
1721401b5383SAlexander Duyck  *  This function is will copy table_data to the table_info contained in
1722401b5383SAlexander Duyck  *  the hw struct.
1723401b5383SAlexander Duyck  **/
fm10k_record_global_table_data(struct fm10k_global_table_data * from,struct fm10k_swapi_table_info * to)1724401b5383SAlexander Duyck static void fm10k_record_global_table_data(struct fm10k_global_table_data *from,
1725401b5383SAlexander Duyck 					   struct fm10k_swapi_table_info *to)
1726401b5383SAlexander Duyck {
1727401b5383SAlexander Duyck 	/* convert from le32 struct to CPU byte ordered values */
1728401b5383SAlexander Duyck 	to->used = le32_to_cpu(from->used);
1729401b5383SAlexander Duyck 	to->avail = le32_to_cpu(from->avail);
1730401b5383SAlexander Duyck }
1731401b5383SAlexander Duyck 
1732401b5383SAlexander Duyck const struct fm10k_tlv_attr fm10k_err_msg_attr[] = {
1733401b5383SAlexander Duyck 	FM10K_TLV_ATTR_LE_STRUCT(FM10K_PF_ATTR_ID_ERR,
1734401b5383SAlexander Duyck 				 sizeof(struct fm10k_swapi_error)),
1735401b5383SAlexander Duyck 	FM10K_TLV_ATTR_LAST
1736401b5383SAlexander Duyck };
1737401b5383SAlexander Duyck 
1738401b5383SAlexander Duyck /**
1739401b5383SAlexander Duyck  *  fm10k_msg_err_pf - Message handler for error reply
1740401b5383SAlexander Duyck  *  @hw: Pointer to hardware structure
1741401b5383SAlexander Duyck  *  @results: pointer array containing parsed data
1742401b5383SAlexander Duyck  *  @mbx: Pointer to mailbox information structure
1743401b5383SAlexander Duyck  *
1744401b5383SAlexander Duyck  *  This handler will capture the data for any error replies to previous
1745401b5383SAlexander Duyck  *  messages that the PF has sent.
1746401b5383SAlexander Duyck  **/
fm10k_msg_err_pf(struct fm10k_hw * hw,u32 ** results,struct fm10k_mbx_info __always_unused * mbx)1747401b5383SAlexander Duyck s32 fm10k_msg_err_pf(struct fm10k_hw *hw, u32 **results,
1748d5c2f395SJacob Keller 		     struct fm10k_mbx_info __always_unused *mbx)
1749401b5383SAlexander Duyck {
1750401b5383SAlexander Duyck 	struct fm10k_swapi_error err_msg;
1751401b5383SAlexander Duyck 	s32 err;
1752401b5383SAlexander Duyck 
1753401b5383SAlexander Duyck 	/* extract structure from message */
1754401b5383SAlexander Duyck 	err = fm10k_tlv_attr_get_le_struct(results[FM10K_PF_ATTR_ID_ERR],
1755401b5383SAlexander Duyck 					   &err_msg, sizeof(err_msg));
1756401b5383SAlexander Duyck 	if (err)
1757401b5383SAlexander Duyck 		return err;
1758401b5383SAlexander Duyck 
1759401b5383SAlexander Duyck 	/* record table status */
1760401b5383SAlexander Duyck 	fm10k_record_global_table_data(&err_msg.mac, &hw->swapi.mac);
1761401b5383SAlexander Duyck 	fm10k_record_global_table_data(&err_msg.nexthop, &hw->swapi.nexthop);
1762401b5383SAlexander Duyck 	fm10k_record_global_table_data(&err_msg.ffu, &hw->swapi.ffu);
1763401b5383SAlexander Duyck 
1764401b5383SAlexander Duyck 	/* record SW API status value */
1765401b5383SAlexander Duyck 	hw->swapi.status = le32_to_cpu(err_msg.status);
1766401b5383SAlexander Duyck 
1767401b5383SAlexander Duyck 	return 0;
1768401b5383SAlexander Duyck }
1769401b5383SAlexander Duyck 
1770401b5383SAlexander Duyck static const struct fm10k_msg_data fm10k_msg_data_pf[] = {
1771401b5383SAlexander Duyck 	FM10K_PF_MSG_ERR_HANDLER(XCAST_MODES, fm10k_msg_err_pf),
1772401b5383SAlexander Duyck 	FM10K_PF_MSG_ERR_HANDLER(UPDATE_MAC_FWD_RULE, fm10k_msg_err_pf),
1773401b5383SAlexander Duyck 	FM10K_PF_MSG_LPORT_MAP_HANDLER(fm10k_msg_lport_map_pf),
1774401b5383SAlexander Duyck 	FM10K_PF_MSG_ERR_HANDLER(LPORT_CREATE, fm10k_msg_err_pf),
1775401b5383SAlexander Duyck 	FM10K_PF_MSG_ERR_HANDLER(LPORT_DELETE, fm10k_msg_err_pf),
1776401b5383SAlexander Duyck 	FM10K_PF_MSG_UPDATE_PVID_HANDLER(fm10k_msg_update_pvid_pf),
1777401b5383SAlexander Duyck 	FM10K_TLV_MSG_ERROR_HANDLER(fm10k_tlv_msg_error),
1778401b5383SAlexander Duyck };
1779401b5383SAlexander Duyck 
1780f329ad73SBruce Allan static const struct fm10k_mac_ops mac_ops_pf = {
17814e458cfbSBruce Allan 	.get_bus_info		= fm10k_get_bus_info_generic,
17824e458cfbSBruce Allan 	.reset_hw		= fm10k_reset_hw_pf,
17834e458cfbSBruce Allan 	.init_hw		= fm10k_init_hw_pf,
17844e458cfbSBruce Allan 	.start_hw		= fm10k_start_hw_generic,
17854e458cfbSBruce Allan 	.stop_hw		= fm10k_stop_hw_generic,
17864e458cfbSBruce Allan 	.update_vlan		= fm10k_update_vlan_pf,
17874e458cfbSBruce Allan 	.read_mac_addr		= fm10k_read_mac_addr_pf,
17884e458cfbSBruce Allan 	.update_uc_addr		= fm10k_update_uc_addr_pf,
17894e458cfbSBruce Allan 	.update_mc_addr		= fm10k_update_mc_addr_pf,
17904e458cfbSBruce Allan 	.update_xcast_mode	= fm10k_update_xcast_mode_pf,
17914e458cfbSBruce Allan 	.update_int_moderator	= fm10k_update_int_moderator_pf,
17924e458cfbSBruce Allan 	.update_lport_state	= fm10k_update_lport_state_pf,
17934e458cfbSBruce Allan 	.update_hw_stats	= fm10k_update_hw_stats_pf,
17944e458cfbSBruce Allan 	.rebind_hw_stats	= fm10k_rebind_hw_stats_pf,
17954e458cfbSBruce Allan 	.configure_dglort_map	= fm10k_configure_dglort_map_pf,
17964e458cfbSBruce Allan 	.set_dma_mask		= fm10k_set_dma_mask_pf,
17974e458cfbSBruce Allan 	.get_fault		= fm10k_get_fault_pf,
17984e458cfbSBruce Allan 	.get_host_state		= fm10k_get_host_state_pf,
17990afd20e5SJacob Keller 	.request_lport_map	= fm10k_request_lport_map_pf,
1800b6fec18fSAlexander Duyck };
1801b6fec18fSAlexander Duyck 
1802f329ad73SBruce Allan static const struct fm10k_iov_ops iov_ops_pf = {
18034e458cfbSBruce Allan 	.assign_resources		= fm10k_iov_assign_resources_pf,
18044e458cfbSBruce Allan 	.configure_tc			= fm10k_iov_configure_tc_pf,
18054e458cfbSBruce Allan 	.assign_int_moderator		= fm10k_iov_assign_int_moderator_pf,
1806c2653865SAlexander Duyck 	.assign_default_mac_vlan	= fm10k_iov_assign_default_mac_vlan_pf,
18074e458cfbSBruce Allan 	.reset_resources		= fm10k_iov_reset_resources_pf,
18084e458cfbSBruce Allan 	.set_lport			= fm10k_iov_set_lport_pf,
18094e458cfbSBruce Allan 	.reset_lport			= fm10k_iov_reset_lport_pf,
18104e458cfbSBruce Allan 	.update_stats			= fm10k_iov_update_stats_pf,
1811c2653865SAlexander Duyck };
1812c2653865SAlexander Duyck 
fm10k_get_invariants_pf(struct fm10k_hw * hw)1813401b5383SAlexander Duyck static s32 fm10k_get_invariants_pf(struct fm10k_hw *hw)
1814401b5383SAlexander Duyck {
1815401b5383SAlexander Duyck 	fm10k_get_invariants_generic(hw);
1816401b5383SAlexander Duyck 
1817401b5383SAlexander Duyck 	return fm10k_sm_mbx_init(hw, &hw->mbx, fm10k_msg_data_pf);
1818401b5383SAlexander Duyck }
1819401b5383SAlexander Duyck 
1820f329ad73SBruce Allan const struct fm10k_info fm10k_pf_info = {
1821b6fec18fSAlexander Duyck 	.mac		= fm10k_mac_pf,
18224e458cfbSBruce Allan 	.get_invariants	= fm10k_get_invariants_pf,
1823b6fec18fSAlexander Duyck 	.mac_ops	= &mac_ops_pf,
1824c2653865SAlexander Duyck 	.iov_ops	= &iov_ops_pf,
1825b6fec18fSAlexander Duyck };
1826