1837f08fdSAnirudh Venkataramanan // SPDX-License-Identifier: GPL-2.0
2837f08fdSAnirudh Venkataramanan /* Copyright (c) 2018, Intel Corporation. */
3837f08fdSAnirudh Venkataramanan 
4837f08fdSAnirudh Venkataramanan /* Intel(R) Ethernet Connection E800 Series Linux Driver */
5837f08fdSAnirudh Venkataramanan 
6837f08fdSAnirudh Venkataramanan #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7837f08fdSAnirudh Venkataramanan 
8837f08fdSAnirudh Venkataramanan #include "ice.h"
945d3d428SAnirudh Venkataramanan #include "ice_lib.h"
10837f08fdSAnirudh Venkataramanan 
119ea47d81SAnirudh Venkataramanan #define DRV_VERSION	"0.7.1-k"
12837f08fdSAnirudh Venkataramanan #define DRV_SUMMARY	"Intel(R) Ethernet Connection E800 Series Linux Driver"
13fcea6f3dSAnirudh Venkataramanan const char ice_drv_ver[] = DRV_VERSION;
14837f08fdSAnirudh Venkataramanan static const char ice_driver_string[] = DRV_SUMMARY;
15837f08fdSAnirudh Venkataramanan static const char ice_copyright[] = "Copyright (c) 2018, Intel Corporation.";
16837f08fdSAnirudh Venkataramanan 
17837f08fdSAnirudh Venkataramanan MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
18837f08fdSAnirudh Venkataramanan MODULE_DESCRIPTION(DRV_SUMMARY);
1998674ebeSJesse Brandeburg MODULE_LICENSE("GPL v2");
20837f08fdSAnirudh Venkataramanan MODULE_VERSION(DRV_VERSION);
21837f08fdSAnirudh Venkataramanan 
22837f08fdSAnirudh Venkataramanan static int debug = -1;
23837f08fdSAnirudh Venkataramanan module_param(debug, int, 0644);
247ec59eeaSAnirudh Venkataramanan #ifndef CONFIG_DYNAMIC_DEBUG
257ec59eeaSAnirudh Venkataramanan MODULE_PARM_DESC(debug, "netif level (0=none,...,16=all), hw debug_mask (0x8XXXXXXX)");
267ec59eeaSAnirudh Venkataramanan #else
277ec59eeaSAnirudh Venkataramanan MODULE_PARM_DESC(debug, "netif level (0=none,...,16=all)");
287ec59eeaSAnirudh Venkataramanan #endif /* !CONFIG_DYNAMIC_DEBUG */
29837f08fdSAnirudh Venkataramanan 
30940b61afSAnirudh Venkataramanan static struct workqueue_struct *ice_wq;
31cdedef59SAnirudh Venkataramanan static const struct net_device_ops ice_netdev_ops;
32940b61afSAnirudh Venkataramanan 
330b28b702SAnirudh Venkataramanan static void ice_pf_dis_all_vsi(struct ice_pf *pf);
340b28b702SAnirudh Venkataramanan static void ice_rebuild(struct ice_pf *pf);
3528c2a645SAnirudh Venkataramanan 
360f9d5027SAnirudh Venkataramanan static void ice_vsi_release_all(struct ice_pf *pf);
37fcea6f3dSAnirudh Venkataramanan static void ice_update_vsi_stats(struct ice_vsi *vsi);
38fcea6f3dSAnirudh Venkataramanan static void ice_update_pf_stats(struct ice_pf *pf);
393a858ba3SAnirudh Venkataramanan 
403a858ba3SAnirudh Venkataramanan /**
41b3969fd7SSudheer Mogilappagari  * ice_get_tx_pending - returns number of Tx descriptors not processed
42b3969fd7SSudheer Mogilappagari  * @ring: the ring of descriptors
43b3969fd7SSudheer Mogilappagari  */
44b3969fd7SSudheer Mogilappagari static u32 ice_get_tx_pending(struct ice_ring *ring)
45b3969fd7SSudheer Mogilappagari {
46b3969fd7SSudheer Mogilappagari 	u32 head, tail;
47b3969fd7SSudheer Mogilappagari 
48b3969fd7SSudheer Mogilappagari 	head = ring->next_to_clean;
49b3969fd7SSudheer Mogilappagari 	tail = readl(ring->tail);
50b3969fd7SSudheer Mogilappagari 
51b3969fd7SSudheer Mogilappagari 	if (head != tail)
52b3969fd7SSudheer Mogilappagari 		return (head < tail) ?
53b3969fd7SSudheer Mogilappagari 			tail - head : (tail + ring->count - head);
54b3969fd7SSudheer Mogilappagari 	return 0;
55b3969fd7SSudheer Mogilappagari }
56b3969fd7SSudheer Mogilappagari 
57b3969fd7SSudheer Mogilappagari /**
58b3969fd7SSudheer Mogilappagari  * ice_check_for_hang_subtask - check for and recover hung queues
59b3969fd7SSudheer Mogilappagari  * @pf: pointer to PF struct
60b3969fd7SSudheer Mogilappagari  */
61b3969fd7SSudheer Mogilappagari static void ice_check_for_hang_subtask(struct ice_pf *pf)
62b3969fd7SSudheer Mogilappagari {
63b3969fd7SSudheer Mogilappagari 	struct ice_vsi *vsi = NULL;
64b3969fd7SSudheer Mogilappagari 	unsigned int i;
65b3969fd7SSudheer Mogilappagari 	u32 v, v_idx;
66b3969fd7SSudheer Mogilappagari 	int packets;
67b3969fd7SSudheer Mogilappagari 
68b3969fd7SSudheer Mogilappagari 	ice_for_each_vsi(pf, v)
69b3969fd7SSudheer Mogilappagari 		if (pf->vsi[v] && pf->vsi[v]->type == ICE_VSI_PF) {
70b3969fd7SSudheer Mogilappagari 			vsi = pf->vsi[v];
71b3969fd7SSudheer Mogilappagari 			break;
72b3969fd7SSudheer Mogilappagari 		}
73b3969fd7SSudheer Mogilappagari 
74b3969fd7SSudheer Mogilappagari 	if (!vsi || test_bit(__ICE_DOWN, vsi->state))
75b3969fd7SSudheer Mogilappagari 		return;
76b3969fd7SSudheer Mogilappagari 
77b3969fd7SSudheer Mogilappagari 	if (!(vsi->netdev && netif_carrier_ok(vsi->netdev)))
78b3969fd7SSudheer Mogilappagari 		return;
79b3969fd7SSudheer Mogilappagari 
80b3969fd7SSudheer Mogilappagari 	for (i = 0; i < vsi->num_txq; i++) {
81b3969fd7SSudheer Mogilappagari 		struct ice_ring *tx_ring = vsi->tx_rings[i];
82b3969fd7SSudheer Mogilappagari 
83b3969fd7SSudheer Mogilappagari 		if (tx_ring && tx_ring->desc) {
84b3969fd7SSudheer Mogilappagari 			int itr = ICE_ITR_NONE;
85b3969fd7SSudheer Mogilappagari 
86b3969fd7SSudheer Mogilappagari 			/* If packet counter has not changed the queue is
87b3969fd7SSudheer Mogilappagari 			 * likely stalled, so force an interrupt for this
88b3969fd7SSudheer Mogilappagari 			 * queue.
89b3969fd7SSudheer Mogilappagari 			 *
90b3969fd7SSudheer Mogilappagari 			 * prev_pkt would be negative if there was no
91b3969fd7SSudheer Mogilappagari 			 * pending work.
92b3969fd7SSudheer Mogilappagari 			 */
93b3969fd7SSudheer Mogilappagari 			packets = tx_ring->stats.pkts & INT_MAX;
94b3969fd7SSudheer Mogilappagari 			if (tx_ring->tx_stats.prev_pkt == packets) {
95b3969fd7SSudheer Mogilappagari 				/* Trigger sw interrupt to revive the queue */
96b3969fd7SSudheer Mogilappagari 				v_idx = tx_ring->q_vector->v_idx;
97b3969fd7SSudheer Mogilappagari 				wr32(&vsi->back->hw,
98eb0208ecSPreethi Banala 				     GLINT_DYN_CTL(vsi->hw_base_vector + v_idx),
99b3969fd7SSudheer Mogilappagari 				     (itr << GLINT_DYN_CTL_ITR_INDX_S) |
100b3969fd7SSudheer Mogilappagari 				     GLINT_DYN_CTL_SWINT_TRIG_M |
101b3969fd7SSudheer Mogilappagari 				     GLINT_DYN_CTL_INTENA_MSK_M);
102b3969fd7SSudheer Mogilappagari 				continue;
103b3969fd7SSudheer Mogilappagari 			}
104b3969fd7SSudheer Mogilappagari 
105b3969fd7SSudheer Mogilappagari 			/* Memory barrier between read of packet count and call
106b3969fd7SSudheer Mogilappagari 			 * to ice_get_tx_pending()
107b3969fd7SSudheer Mogilappagari 			 */
108b3969fd7SSudheer Mogilappagari 			smp_rmb();
109b3969fd7SSudheer Mogilappagari 			tx_ring->tx_stats.prev_pkt =
110b3969fd7SSudheer Mogilappagari 			    ice_get_tx_pending(tx_ring) ? packets : -1;
111b3969fd7SSudheer Mogilappagari 		}
112b3969fd7SSudheer Mogilappagari 	}
113b3969fd7SSudheer Mogilappagari }
114b3969fd7SSudheer Mogilappagari 
115b3969fd7SSudheer Mogilappagari /**
116e94d4478SAnirudh Venkataramanan  * ice_add_mac_to_sync_list - creates list of mac addresses to be synced
117e94d4478SAnirudh Venkataramanan  * @netdev: the net device on which the sync is happening
118e94d4478SAnirudh Venkataramanan  * @addr: mac address to sync
119e94d4478SAnirudh Venkataramanan  *
120e94d4478SAnirudh Venkataramanan  * This is a callback function which is called by the in kernel device sync
121e94d4478SAnirudh Venkataramanan  * functions (like __dev_uc_sync, __dev_mc_sync, etc). This function only
122e94d4478SAnirudh Venkataramanan  * populates the tmp_sync_list, which is later used by ice_add_mac to add the
123e94d4478SAnirudh Venkataramanan  * mac filters from the hardware.
124e94d4478SAnirudh Venkataramanan  */
125e94d4478SAnirudh Venkataramanan static int ice_add_mac_to_sync_list(struct net_device *netdev, const u8 *addr)
126e94d4478SAnirudh Venkataramanan {
127e94d4478SAnirudh Venkataramanan 	struct ice_netdev_priv *np = netdev_priv(netdev);
128e94d4478SAnirudh Venkataramanan 	struct ice_vsi *vsi = np->vsi;
129e94d4478SAnirudh Venkataramanan 
130e94d4478SAnirudh Venkataramanan 	if (ice_add_mac_to_list(vsi, &vsi->tmp_sync_list, addr))
131e94d4478SAnirudh Venkataramanan 		return -EINVAL;
132e94d4478SAnirudh Venkataramanan 
133e94d4478SAnirudh Venkataramanan 	return 0;
134e94d4478SAnirudh Venkataramanan }
135e94d4478SAnirudh Venkataramanan 
136e94d4478SAnirudh Venkataramanan /**
137e94d4478SAnirudh Venkataramanan  * ice_add_mac_to_unsync_list - creates list of mac addresses to be unsynced
138e94d4478SAnirudh Venkataramanan  * @netdev: the net device on which the unsync is happening
139e94d4478SAnirudh Venkataramanan  * @addr: mac address to unsync
140e94d4478SAnirudh Venkataramanan  *
141e94d4478SAnirudh Venkataramanan  * This is a callback function which is called by the in kernel device unsync
142e94d4478SAnirudh Venkataramanan  * functions (like __dev_uc_unsync, __dev_mc_unsync, etc). This function only
143e94d4478SAnirudh Venkataramanan  * populates the tmp_unsync_list, which is later used by ice_remove_mac to
144e94d4478SAnirudh Venkataramanan  * delete the mac filters from the hardware.
145e94d4478SAnirudh Venkataramanan  */
146e94d4478SAnirudh Venkataramanan static int ice_add_mac_to_unsync_list(struct net_device *netdev, const u8 *addr)
147e94d4478SAnirudh Venkataramanan {
148e94d4478SAnirudh Venkataramanan 	struct ice_netdev_priv *np = netdev_priv(netdev);
149e94d4478SAnirudh Venkataramanan 	struct ice_vsi *vsi = np->vsi;
150e94d4478SAnirudh Venkataramanan 
151e94d4478SAnirudh Venkataramanan 	if (ice_add_mac_to_list(vsi, &vsi->tmp_unsync_list, addr))
152e94d4478SAnirudh Venkataramanan 		return -EINVAL;
153e94d4478SAnirudh Venkataramanan 
154e94d4478SAnirudh Venkataramanan 	return 0;
155e94d4478SAnirudh Venkataramanan }
156e94d4478SAnirudh Venkataramanan 
157e94d4478SAnirudh Venkataramanan /**
158e94d4478SAnirudh Venkataramanan  * ice_vsi_fltr_changed - check if filter state changed
159e94d4478SAnirudh Venkataramanan  * @vsi: VSI to be checked
160e94d4478SAnirudh Venkataramanan  *
161e94d4478SAnirudh Venkataramanan  * returns true if filter state has changed, false otherwise.
162e94d4478SAnirudh Venkataramanan  */
163e94d4478SAnirudh Venkataramanan static bool ice_vsi_fltr_changed(struct ice_vsi *vsi)
164e94d4478SAnirudh Venkataramanan {
165e94d4478SAnirudh Venkataramanan 	return test_bit(ICE_VSI_FLAG_UMAC_FLTR_CHANGED, vsi->flags) ||
166e94d4478SAnirudh Venkataramanan 	       test_bit(ICE_VSI_FLAG_MMAC_FLTR_CHANGED, vsi->flags) ||
167e94d4478SAnirudh Venkataramanan 	       test_bit(ICE_VSI_FLAG_VLAN_FLTR_CHANGED, vsi->flags);
168e94d4478SAnirudh Venkataramanan }
169e94d4478SAnirudh Venkataramanan 
170e94d4478SAnirudh Venkataramanan /**
171e94d4478SAnirudh Venkataramanan  * ice_vsi_sync_fltr - Update the VSI filter list to the HW
172e94d4478SAnirudh Venkataramanan  * @vsi: ptr to the VSI
173e94d4478SAnirudh Venkataramanan  *
174e94d4478SAnirudh Venkataramanan  * Push any outstanding VSI filter changes through the AdminQ.
175e94d4478SAnirudh Venkataramanan  */
176e94d4478SAnirudh Venkataramanan static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
177e94d4478SAnirudh Venkataramanan {
178e94d4478SAnirudh Venkataramanan 	struct device *dev = &vsi->back->pdev->dev;
179e94d4478SAnirudh Venkataramanan 	struct net_device *netdev = vsi->netdev;
180e94d4478SAnirudh Venkataramanan 	bool promisc_forced_on = false;
181e94d4478SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
182e94d4478SAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
183e94d4478SAnirudh Venkataramanan 	enum ice_status status = 0;
184e94d4478SAnirudh Venkataramanan 	u32 changed_flags = 0;
185e94d4478SAnirudh Venkataramanan 	int err = 0;
186e94d4478SAnirudh Venkataramanan 
187e94d4478SAnirudh Venkataramanan 	if (!vsi->netdev)
188e94d4478SAnirudh Venkataramanan 		return -EINVAL;
189e94d4478SAnirudh Venkataramanan 
190e94d4478SAnirudh Venkataramanan 	while (test_and_set_bit(__ICE_CFG_BUSY, vsi->state))
191e94d4478SAnirudh Venkataramanan 		usleep_range(1000, 2000);
192e94d4478SAnirudh Venkataramanan 
193e94d4478SAnirudh Venkataramanan 	changed_flags = vsi->current_netdev_flags ^ vsi->netdev->flags;
194e94d4478SAnirudh Venkataramanan 	vsi->current_netdev_flags = vsi->netdev->flags;
195e94d4478SAnirudh Venkataramanan 
196e94d4478SAnirudh Venkataramanan 	INIT_LIST_HEAD(&vsi->tmp_sync_list);
197e94d4478SAnirudh Venkataramanan 	INIT_LIST_HEAD(&vsi->tmp_unsync_list);
198e94d4478SAnirudh Venkataramanan 
199e94d4478SAnirudh Venkataramanan 	if (ice_vsi_fltr_changed(vsi)) {
200e94d4478SAnirudh Venkataramanan 		clear_bit(ICE_VSI_FLAG_UMAC_FLTR_CHANGED, vsi->flags);
201e94d4478SAnirudh Venkataramanan 		clear_bit(ICE_VSI_FLAG_MMAC_FLTR_CHANGED, vsi->flags);
202e94d4478SAnirudh Venkataramanan 		clear_bit(ICE_VSI_FLAG_VLAN_FLTR_CHANGED, vsi->flags);
203e94d4478SAnirudh Venkataramanan 
204e94d4478SAnirudh Venkataramanan 		/* grab the netdev's addr_list_lock */
205e94d4478SAnirudh Venkataramanan 		netif_addr_lock_bh(netdev);
206e94d4478SAnirudh Venkataramanan 		__dev_uc_sync(netdev, ice_add_mac_to_sync_list,
207e94d4478SAnirudh Venkataramanan 			      ice_add_mac_to_unsync_list);
208e94d4478SAnirudh Venkataramanan 		__dev_mc_sync(netdev, ice_add_mac_to_sync_list,
209e94d4478SAnirudh Venkataramanan 			      ice_add_mac_to_unsync_list);
210e94d4478SAnirudh Venkataramanan 		/* our temp lists are populated. release lock */
211e94d4478SAnirudh Venkataramanan 		netif_addr_unlock_bh(netdev);
212e94d4478SAnirudh Venkataramanan 	}
213e94d4478SAnirudh Venkataramanan 
214e94d4478SAnirudh Venkataramanan 	/* Remove mac addresses in the unsync list */
215e94d4478SAnirudh Venkataramanan 	status = ice_remove_mac(hw, &vsi->tmp_unsync_list);
216e94d4478SAnirudh Venkataramanan 	ice_free_fltr_list(dev, &vsi->tmp_unsync_list);
217e94d4478SAnirudh Venkataramanan 	if (status) {
218e94d4478SAnirudh Venkataramanan 		netdev_err(netdev, "Failed to delete MAC filters\n");
219e94d4478SAnirudh Venkataramanan 		/* if we failed because of alloc failures, just bail */
220e94d4478SAnirudh Venkataramanan 		if (status == ICE_ERR_NO_MEMORY) {
221e94d4478SAnirudh Venkataramanan 			err = -ENOMEM;
222e94d4478SAnirudh Venkataramanan 			goto out;
223e94d4478SAnirudh Venkataramanan 		}
224e94d4478SAnirudh Venkataramanan 	}
225e94d4478SAnirudh Venkataramanan 
226e94d4478SAnirudh Venkataramanan 	/* Add mac addresses in the sync list */
227e94d4478SAnirudh Venkataramanan 	status = ice_add_mac(hw, &vsi->tmp_sync_list);
228e94d4478SAnirudh Venkataramanan 	ice_free_fltr_list(dev, &vsi->tmp_sync_list);
229e94d4478SAnirudh Venkataramanan 	if (status) {
230e94d4478SAnirudh Venkataramanan 		netdev_err(netdev, "Failed to add MAC filters\n");
231e94d4478SAnirudh Venkataramanan 		/* If there is no more space for new umac filters, vsi
232e94d4478SAnirudh Venkataramanan 		 * should go into promiscuous mode. There should be some
233e94d4478SAnirudh Venkataramanan 		 * space reserved for promiscuous filters.
234e94d4478SAnirudh Venkataramanan 		 */
235e94d4478SAnirudh Venkataramanan 		if (hw->adminq.sq_last_status == ICE_AQ_RC_ENOSPC &&
236e94d4478SAnirudh Venkataramanan 		    !test_and_set_bit(__ICE_FLTR_OVERFLOW_PROMISC,
237e94d4478SAnirudh Venkataramanan 				      vsi->state)) {
238e94d4478SAnirudh Venkataramanan 			promisc_forced_on = true;
239e94d4478SAnirudh Venkataramanan 			netdev_warn(netdev,
240e94d4478SAnirudh Venkataramanan 				    "Reached MAC filter limit, forcing promisc mode on VSI %d\n",
241e94d4478SAnirudh Venkataramanan 				    vsi->vsi_num);
242e94d4478SAnirudh Venkataramanan 		} else {
243e94d4478SAnirudh Venkataramanan 			err = -EIO;
244e94d4478SAnirudh Venkataramanan 			goto out;
245e94d4478SAnirudh Venkataramanan 		}
246e94d4478SAnirudh Venkataramanan 	}
247e94d4478SAnirudh Venkataramanan 	/* check for changes in promiscuous modes */
248e94d4478SAnirudh Venkataramanan 	if (changed_flags & IFF_ALLMULTI)
249e94d4478SAnirudh Venkataramanan 		netdev_warn(netdev, "Unsupported configuration\n");
250e94d4478SAnirudh Venkataramanan 
251e94d4478SAnirudh Venkataramanan 	if (((changed_flags & IFF_PROMISC) || promisc_forced_on) ||
252e94d4478SAnirudh Venkataramanan 	    test_bit(ICE_VSI_FLAG_PROMISC_CHANGED, vsi->flags)) {
253e94d4478SAnirudh Venkataramanan 		clear_bit(ICE_VSI_FLAG_PROMISC_CHANGED, vsi->flags);
254e94d4478SAnirudh Venkataramanan 		if (vsi->current_netdev_flags & IFF_PROMISC) {
255e94d4478SAnirudh Venkataramanan 			/* Apply TX filter rule to get traffic from VMs */
2564fb33f31SAnirudh Venkataramanan 			status = ice_cfg_dflt_vsi(hw, vsi->idx, true,
257e94d4478SAnirudh Venkataramanan 						  ICE_FLTR_TX);
258e94d4478SAnirudh Venkataramanan 			if (status) {
259e94d4478SAnirudh Venkataramanan 				netdev_err(netdev, "Error setting default VSI %i tx rule\n",
260e94d4478SAnirudh Venkataramanan 					   vsi->vsi_num);
261e94d4478SAnirudh Venkataramanan 				vsi->current_netdev_flags &= ~IFF_PROMISC;
262e94d4478SAnirudh Venkataramanan 				err = -EIO;
263e94d4478SAnirudh Venkataramanan 				goto out_promisc;
264e94d4478SAnirudh Venkataramanan 			}
265e94d4478SAnirudh Venkataramanan 			/* Apply RX filter rule to get traffic from wire */
2664fb33f31SAnirudh Venkataramanan 			status = ice_cfg_dflt_vsi(hw, vsi->idx, true,
267e94d4478SAnirudh Venkataramanan 						  ICE_FLTR_RX);
268e94d4478SAnirudh Venkataramanan 			if (status) {
269e94d4478SAnirudh Venkataramanan 				netdev_err(netdev, "Error setting default VSI %i rx rule\n",
270e94d4478SAnirudh Venkataramanan 					   vsi->vsi_num);
271e94d4478SAnirudh Venkataramanan 				vsi->current_netdev_flags &= ~IFF_PROMISC;
272e94d4478SAnirudh Venkataramanan 				err = -EIO;
273e94d4478SAnirudh Venkataramanan 				goto out_promisc;
274e94d4478SAnirudh Venkataramanan 			}
275e94d4478SAnirudh Venkataramanan 		} else {
276e94d4478SAnirudh Venkataramanan 			/* Clear TX filter rule to stop traffic from VMs */
2774fb33f31SAnirudh Venkataramanan 			status = ice_cfg_dflt_vsi(hw, vsi->idx, false,
278e94d4478SAnirudh Venkataramanan 						  ICE_FLTR_TX);
279e94d4478SAnirudh Venkataramanan 			if (status) {
280e94d4478SAnirudh Venkataramanan 				netdev_err(netdev, "Error clearing default VSI %i tx rule\n",
281e94d4478SAnirudh Venkataramanan 					   vsi->vsi_num);
282e94d4478SAnirudh Venkataramanan 				vsi->current_netdev_flags |= IFF_PROMISC;
283e94d4478SAnirudh Venkataramanan 				err = -EIO;
284e94d4478SAnirudh Venkataramanan 				goto out_promisc;
285e94d4478SAnirudh Venkataramanan 			}
2864fb33f31SAnirudh Venkataramanan 			/* Clear RX filter to remove traffic from wire */
2874fb33f31SAnirudh Venkataramanan 			status = ice_cfg_dflt_vsi(hw, vsi->idx, false,
288e94d4478SAnirudh Venkataramanan 						  ICE_FLTR_RX);
289e94d4478SAnirudh Venkataramanan 			if (status) {
290e94d4478SAnirudh Venkataramanan 				netdev_err(netdev, "Error clearing default VSI %i rx rule\n",
291e94d4478SAnirudh Venkataramanan 					   vsi->vsi_num);
292e94d4478SAnirudh Venkataramanan 				vsi->current_netdev_flags |= IFF_PROMISC;
293e94d4478SAnirudh Venkataramanan 				err = -EIO;
294e94d4478SAnirudh Venkataramanan 				goto out_promisc;
295e94d4478SAnirudh Venkataramanan 			}
296e94d4478SAnirudh Venkataramanan 		}
297e94d4478SAnirudh Venkataramanan 	}
298e94d4478SAnirudh Venkataramanan 	goto exit;
299e94d4478SAnirudh Venkataramanan 
300e94d4478SAnirudh Venkataramanan out_promisc:
301e94d4478SAnirudh Venkataramanan 	set_bit(ICE_VSI_FLAG_PROMISC_CHANGED, vsi->flags);
302e94d4478SAnirudh Venkataramanan 	goto exit;
303e94d4478SAnirudh Venkataramanan out:
304e94d4478SAnirudh Venkataramanan 	/* if something went wrong then set the changed flag so we try again */
305e94d4478SAnirudh Venkataramanan 	set_bit(ICE_VSI_FLAG_UMAC_FLTR_CHANGED, vsi->flags);
306e94d4478SAnirudh Venkataramanan 	set_bit(ICE_VSI_FLAG_MMAC_FLTR_CHANGED, vsi->flags);
307e94d4478SAnirudh Venkataramanan exit:
308e94d4478SAnirudh Venkataramanan 	clear_bit(__ICE_CFG_BUSY, vsi->state);
309e94d4478SAnirudh Venkataramanan 	return err;
310e94d4478SAnirudh Venkataramanan }
311e94d4478SAnirudh Venkataramanan 
312e94d4478SAnirudh Venkataramanan /**
313e94d4478SAnirudh Venkataramanan  * ice_sync_fltr_subtask - Sync the VSI filter list with HW
314e94d4478SAnirudh Venkataramanan  * @pf: board private structure
315e94d4478SAnirudh Venkataramanan  */
316e94d4478SAnirudh Venkataramanan static void ice_sync_fltr_subtask(struct ice_pf *pf)
317e94d4478SAnirudh Venkataramanan {
318e94d4478SAnirudh Venkataramanan 	int v;
319e94d4478SAnirudh Venkataramanan 
320e94d4478SAnirudh Venkataramanan 	if (!pf || !(test_bit(ICE_FLAG_FLTR_SYNC, pf->flags)))
321e94d4478SAnirudh Venkataramanan 		return;
322e94d4478SAnirudh Venkataramanan 
323e94d4478SAnirudh Venkataramanan 	clear_bit(ICE_FLAG_FLTR_SYNC, pf->flags);
324e94d4478SAnirudh Venkataramanan 
325e94d4478SAnirudh Venkataramanan 	for (v = 0; v < pf->num_alloc_vsi; v++)
326e94d4478SAnirudh Venkataramanan 		if (pf->vsi[v] && ice_vsi_fltr_changed(pf->vsi[v]) &&
327e94d4478SAnirudh Venkataramanan 		    ice_vsi_sync_fltr(pf->vsi[v])) {
328e94d4478SAnirudh Venkataramanan 			/* come back and try again later */
329e94d4478SAnirudh Venkataramanan 			set_bit(ICE_FLAG_FLTR_SYNC, pf->flags);
330e94d4478SAnirudh Venkataramanan 			break;
331e94d4478SAnirudh Venkataramanan 		}
332e94d4478SAnirudh Venkataramanan }
333e94d4478SAnirudh Venkataramanan 
334e94d4478SAnirudh Venkataramanan /**
3350b28b702SAnirudh Venkataramanan  * ice_prepare_for_reset - prep for the core to reset
3360b28b702SAnirudh Venkataramanan  * @pf: board private structure
3370b28b702SAnirudh Venkataramanan  *
3380b28b702SAnirudh Venkataramanan  * Inform or close all dependent features in prep for reset.
3390b28b702SAnirudh Venkataramanan  */
3400b28b702SAnirudh Venkataramanan static void
3410b28b702SAnirudh Venkataramanan ice_prepare_for_reset(struct ice_pf *pf)
3420b28b702SAnirudh Venkataramanan {
3430b28b702SAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
3440b28b702SAnirudh Venkataramanan 
3450b28b702SAnirudh Venkataramanan 	/* disable the VSIs and their queues that are not already DOWN */
3460b28b702SAnirudh Venkataramanan 	ice_pf_dis_all_vsi(pf);
3470b28b702SAnirudh Venkataramanan 
3480b28b702SAnirudh Venkataramanan 	ice_shutdown_all_ctrlq(hw);
3490f9d5027SAnirudh Venkataramanan 
3500f9d5027SAnirudh Venkataramanan 	set_bit(__ICE_PREPARED_FOR_RESET, pf->state);
3510b28b702SAnirudh Venkataramanan }
3520b28b702SAnirudh Venkataramanan 
3530b28b702SAnirudh Venkataramanan /**
3540b28b702SAnirudh Venkataramanan  * ice_do_reset - Initiate one of many types of resets
3550b28b702SAnirudh Venkataramanan  * @pf: board private structure
3560b28b702SAnirudh Venkataramanan  * @reset_type: reset type requested
3570b28b702SAnirudh Venkataramanan  * before this function was called.
3580b28b702SAnirudh Venkataramanan  */
3590b28b702SAnirudh Venkataramanan static void ice_do_reset(struct ice_pf *pf, enum ice_reset_req reset_type)
3600b28b702SAnirudh Venkataramanan {
3610b28b702SAnirudh Venkataramanan 	struct device *dev = &pf->pdev->dev;
3620b28b702SAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
3630b28b702SAnirudh Venkataramanan 
3640b28b702SAnirudh Venkataramanan 	dev_dbg(dev, "reset_type 0x%x requested\n", reset_type);
3650b28b702SAnirudh Venkataramanan 	WARN_ON(in_interrupt());
3660b28b702SAnirudh Venkataramanan 
3670b28b702SAnirudh Venkataramanan 	ice_prepare_for_reset(pf);
3680b28b702SAnirudh Venkataramanan 
3690b28b702SAnirudh Venkataramanan 	/* trigger the reset */
3700b28b702SAnirudh Venkataramanan 	if (ice_reset(hw, reset_type)) {
3710b28b702SAnirudh Venkataramanan 		dev_err(dev, "reset %d failed\n", reset_type);
3720b28b702SAnirudh Venkataramanan 		set_bit(__ICE_RESET_FAILED, pf->state);
3735df7e45dSDave Ertman 		clear_bit(__ICE_RESET_OICR_RECV, pf->state);
3740f9d5027SAnirudh Venkataramanan 		clear_bit(__ICE_PREPARED_FOR_RESET, pf->state);
3755df7e45dSDave Ertman 		clear_bit(__ICE_PFR_REQ, pf->state);
3765df7e45dSDave Ertman 		clear_bit(__ICE_CORER_REQ, pf->state);
3775df7e45dSDave Ertman 		clear_bit(__ICE_GLOBR_REQ, pf->state);
3780b28b702SAnirudh Venkataramanan 		return;
3790b28b702SAnirudh Venkataramanan 	}
3800b28b702SAnirudh Venkataramanan 
3810f9d5027SAnirudh Venkataramanan 	/* PFR is a bit of a special case because it doesn't result in an OICR
3820f9d5027SAnirudh Venkataramanan 	 * interrupt. So for PFR, rebuild after the reset and clear the reset-
3830f9d5027SAnirudh Venkataramanan 	 * associated state bits.
3840f9d5027SAnirudh Venkataramanan 	 */
3850b28b702SAnirudh Venkataramanan 	if (reset_type == ICE_RESET_PFR) {
3860b28b702SAnirudh Venkataramanan 		pf->pfr_count++;
3870b28b702SAnirudh Venkataramanan 		ice_rebuild(pf);
3880f9d5027SAnirudh Venkataramanan 		clear_bit(__ICE_PREPARED_FOR_RESET, pf->state);
3895df7e45dSDave Ertman 		clear_bit(__ICE_PFR_REQ, pf->state);
3900b28b702SAnirudh Venkataramanan 	}
3910b28b702SAnirudh Venkataramanan }
3920b28b702SAnirudh Venkataramanan 
3930b28b702SAnirudh Venkataramanan /**
3940b28b702SAnirudh Venkataramanan  * ice_reset_subtask - Set up for resetting the device and driver
3950b28b702SAnirudh Venkataramanan  * @pf: board private structure
3960b28b702SAnirudh Venkataramanan  */
3970b28b702SAnirudh Venkataramanan static void ice_reset_subtask(struct ice_pf *pf)
3980b28b702SAnirudh Venkataramanan {
3990f9d5027SAnirudh Venkataramanan 	enum ice_reset_req reset_type = ICE_RESET_INVAL;
4000b28b702SAnirudh Venkataramanan 
4010b28b702SAnirudh Venkataramanan 	/* When a CORER/GLOBR/EMPR is about to happen, the hardware triggers an
4020f9d5027SAnirudh Venkataramanan 	 * OICR interrupt. The OICR handler (ice_misc_intr) determines what type
4030f9d5027SAnirudh Venkataramanan 	 * of reset is pending and sets bits in pf->state indicating the reset
4045df7e45dSDave Ertman 	 * type and __ICE_RESET_OICR_RECV.  So, if the latter bit is set
4050f9d5027SAnirudh Venkataramanan 	 * prepare for pending reset if not already (for PF software-initiated
4060f9d5027SAnirudh Venkataramanan 	 * global resets the software should already be prepared for it as
4070f9d5027SAnirudh Venkataramanan 	 * indicated by __ICE_PREPARED_FOR_RESET; for global resets initiated
4080f9d5027SAnirudh Venkataramanan 	 * by firmware or software on other PFs, that bit is not set so prepare
4090f9d5027SAnirudh Venkataramanan 	 * for the reset now), poll for reset done, rebuild and return.
4100b28b702SAnirudh Venkataramanan 	 */
4115df7e45dSDave Ertman 	if (test_bit(__ICE_RESET_OICR_RECV, pf->state)) {
4120b28b702SAnirudh Venkataramanan 		clear_bit(__ICE_GLOBR_RECV, pf->state);
4130b28b702SAnirudh Venkataramanan 		clear_bit(__ICE_CORER_RECV, pf->state);
4140f9d5027SAnirudh Venkataramanan 		if (!test_bit(__ICE_PREPARED_FOR_RESET, pf->state))
4150b28b702SAnirudh Venkataramanan 			ice_prepare_for_reset(pf);
4160b28b702SAnirudh Venkataramanan 
4170b28b702SAnirudh Venkataramanan 		/* make sure we are ready to rebuild */
418fd2a9817SAnirudh Venkataramanan 		if (ice_check_reset(&pf->hw)) {
4190b28b702SAnirudh Venkataramanan 			set_bit(__ICE_RESET_FAILED, pf->state);
420fd2a9817SAnirudh Venkataramanan 		} else {
421fd2a9817SAnirudh Venkataramanan 			/* done with reset. start rebuild */
422fd2a9817SAnirudh Venkataramanan 			pf->hw.reset_ongoing = false;
4230b28b702SAnirudh Venkataramanan 			ice_rebuild(pf);
4240f9d5027SAnirudh Venkataramanan 			/* clear bit to resume normal operations, but
4250f9d5027SAnirudh Venkataramanan 			 * ICE_NEEDS_RESTART bit is set incase rebuild failed
4260f9d5027SAnirudh Venkataramanan 			 */
4275df7e45dSDave Ertman 			clear_bit(__ICE_RESET_OICR_RECV, pf->state);
4280f9d5027SAnirudh Venkataramanan 			clear_bit(__ICE_PREPARED_FOR_RESET, pf->state);
4295df7e45dSDave Ertman 			clear_bit(__ICE_PFR_REQ, pf->state);
4305df7e45dSDave Ertman 			clear_bit(__ICE_CORER_REQ, pf->state);
4315df7e45dSDave Ertman 			clear_bit(__ICE_GLOBR_REQ, pf->state);
4320f9d5027SAnirudh Venkataramanan 		}
4330f9d5027SAnirudh Venkataramanan 
4340f9d5027SAnirudh Venkataramanan 		return;
4350b28b702SAnirudh Venkataramanan 	}
4360b28b702SAnirudh Venkataramanan 
4370b28b702SAnirudh Venkataramanan 	/* No pending resets to finish processing. Check for new resets */
4385df7e45dSDave Ertman 	if (test_bit(__ICE_PFR_REQ, pf->state))
4390f9d5027SAnirudh Venkataramanan 		reset_type = ICE_RESET_PFR;
4405df7e45dSDave Ertman 	if (test_bit(__ICE_CORER_REQ, pf->state))
4410f9d5027SAnirudh Venkataramanan 		reset_type = ICE_RESET_CORER;
4425df7e45dSDave Ertman 	if (test_bit(__ICE_GLOBR_REQ, pf->state))
4430b28b702SAnirudh Venkataramanan 		reset_type = ICE_RESET_GLOBR;
4440f9d5027SAnirudh Venkataramanan 	/* If no valid reset type requested just return */
4450f9d5027SAnirudh Venkataramanan 	if (reset_type == ICE_RESET_INVAL)
4460f9d5027SAnirudh Venkataramanan 		return;
4470b28b702SAnirudh Venkataramanan 
4480f9d5027SAnirudh Venkataramanan 	/* reset if not already down or busy */
4490b28b702SAnirudh Venkataramanan 	if (!test_bit(__ICE_DOWN, pf->state) &&
4500b28b702SAnirudh Venkataramanan 	    !test_bit(__ICE_CFG_BUSY, pf->state)) {
4510b28b702SAnirudh Venkataramanan 		ice_do_reset(pf, reset_type);
4520b28b702SAnirudh Venkataramanan 	}
4530b28b702SAnirudh Venkataramanan }
4540b28b702SAnirudh Venkataramanan 
4550b28b702SAnirudh Venkataramanan /**
456fcea6f3dSAnirudh Venkataramanan  * ice_watchdog_subtask - periodic tasks not using event driven scheduling
457fcea6f3dSAnirudh Venkataramanan  * @pf: board private structure
458fcea6f3dSAnirudh Venkataramanan  */
459fcea6f3dSAnirudh Venkataramanan static void ice_watchdog_subtask(struct ice_pf *pf)
460fcea6f3dSAnirudh Venkataramanan {
461fcea6f3dSAnirudh Venkataramanan 	int i;
462fcea6f3dSAnirudh Venkataramanan 
463fcea6f3dSAnirudh Venkataramanan 	/* if interface is down do nothing */
464fcea6f3dSAnirudh Venkataramanan 	if (test_bit(__ICE_DOWN, pf->state) ||
465fcea6f3dSAnirudh Venkataramanan 	    test_bit(__ICE_CFG_BUSY, pf->state))
466fcea6f3dSAnirudh Venkataramanan 		return;
467fcea6f3dSAnirudh Venkataramanan 
468fcea6f3dSAnirudh Venkataramanan 	/* make sure we don't do these things too often */
469fcea6f3dSAnirudh Venkataramanan 	if (time_before(jiffies,
470fcea6f3dSAnirudh Venkataramanan 			pf->serv_tmr_prev + pf->serv_tmr_period))
471fcea6f3dSAnirudh Venkataramanan 		return;
472fcea6f3dSAnirudh Venkataramanan 
473fcea6f3dSAnirudh Venkataramanan 	pf->serv_tmr_prev = jiffies;
474fcea6f3dSAnirudh Venkataramanan 
475fcea6f3dSAnirudh Venkataramanan 	/* Update the stats for active netdevs so the network stack
476fcea6f3dSAnirudh Venkataramanan 	 * can look at updated numbers whenever it cares to
477fcea6f3dSAnirudh Venkataramanan 	 */
478fcea6f3dSAnirudh Venkataramanan 	ice_update_pf_stats(pf);
479fcea6f3dSAnirudh Venkataramanan 	for (i = 0; i < pf->num_alloc_vsi; i++)
480fcea6f3dSAnirudh Venkataramanan 		if (pf->vsi[i] && pf->vsi[i]->netdev)
481fcea6f3dSAnirudh Venkataramanan 			ice_update_vsi_stats(pf->vsi[i]);
482fcea6f3dSAnirudh Venkataramanan }
483fcea6f3dSAnirudh Venkataramanan 
484fcea6f3dSAnirudh Venkataramanan /**
485cdedef59SAnirudh Venkataramanan  * ice_print_link_msg - print link up or down message
486cdedef59SAnirudh Venkataramanan  * @vsi: the VSI whose link status is being queried
487cdedef59SAnirudh Venkataramanan  * @isup: boolean for if the link is now up or down
488cdedef59SAnirudh Venkataramanan  */
489fcea6f3dSAnirudh Venkataramanan void ice_print_link_msg(struct ice_vsi *vsi, bool isup)
490cdedef59SAnirudh Venkataramanan {
491cdedef59SAnirudh Venkataramanan 	const char *speed;
492cdedef59SAnirudh Venkataramanan 	const char *fc;
493cdedef59SAnirudh Venkataramanan 
494cdedef59SAnirudh Venkataramanan 	if (vsi->current_isup == isup)
495cdedef59SAnirudh Venkataramanan 		return;
496cdedef59SAnirudh Venkataramanan 
497cdedef59SAnirudh Venkataramanan 	vsi->current_isup = isup;
498cdedef59SAnirudh Venkataramanan 
499cdedef59SAnirudh Venkataramanan 	if (!isup) {
500cdedef59SAnirudh Venkataramanan 		netdev_info(vsi->netdev, "NIC Link is Down\n");
501cdedef59SAnirudh Venkataramanan 		return;
502cdedef59SAnirudh Venkataramanan 	}
503cdedef59SAnirudh Venkataramanan 
504cdedef59SAnirudh Venkataramanan 	switch (vsi->port_info->phy.link_info.link_speed) {
505cdedef59SAnirudh Venkataramanan 	case ICE_AQ_LINK_SPEED_40GB:
506cdedef59SAnirudh Venkataramanan 		speed = "40 G";
507cdedef59SAnirudh Venkataramanan 		break;
508cdedef59SAnirudh Venkataramanan 	case ICE_AQ_LINK_SPEED_25GB:
509cdedef59SAnirudh Venkataramanan 		speed = "25 G";
510cdedef59SAnirudh Venkataramanan 		break;
511cdedef59SAnirudh Venkataramanan 	case ICE_AQ_LINK_SPEED_20GB:
512cdedef59SAnirudh Venkataramanan 		speed = "20 G";
513cdedef59SAnirudh Venkataramanan 		break;
514cdedef59SAnirudh Venkataramanan 	case ICE_AQ_LINK_SPEED_10GB:
515cdedef59SAnirudh Venkataramanan 		speed = "10 G";
516cdedef59SAnirudh Venkataramanan 		break;
517cdedef59SAnirudh Venkataramanan 	case ICE_AQ_LINK_SPEED_5GB:
518cdedef59SAnirudh Venkataramanan 		speed = "5 G";
519cdedef59SAnirudh Venkataramanan 		break;
520cdedef59SAnirudh Venkataramanan 	case ICE_AQ_LINK_SPEED_2500MB:
521cdedef59SAnirudh Venkataramanan 		speed = "2.5 G";
522cdedef59SAnirudh Venkataramanan 		break;
523cdedef59SAnirudh Venkataramanan 	case ICE_AQ_LINK_SPEED_1000MB:
524cdedef59SAnirudh Venkataramanan 		speed = "1 G";
525cdedef59SAnirudh Venkataramanan 		break;
526cdedef59SAnirudh Venkataramanan 	case ICE_AQ_LINK_SPEED_100MB:
527cdedef59SAnirudh Venkataramanan 		speed = "100 M";
528cdedef59SAnirudh Venkataramanan 		break;
529cdedef59SAnirudh Venkataramanan 	default:
530cdedef59SAnirudh Venkataramanan 		speed = "Unknown";
531cdedef59SAnirudh Venkataramanan 		break;
532cdedef59SAnirudh Venkataramanan 	}
533cdedef59SAnirudh Venkataramanan 
534cdedef59SAnirudh Venkataramanan 	switch (vsi->port_info->fc.current_mode) {
535cdedef59SAnirudh Venkataramanan 	case ICE_FC_FULL:
536cdedef59SAnirudh Venkataramanan 		fc = "RX/TX";
537cdedef59SAnirudh Venkataramanan 		break;
538cdedef59SAnirudh Venkataramanan 	case ICE_FC_TX_PAUSE:
539cdedef59SAnirudh Venkataramanan 		fc = "TX";
540cdedef59SAnirudh Venkataramanan 		break;
541cdedef59SAnirudh Venkataramanan 	case ICE_FC_RX_PAUSE:
542cdedef59SAnirudh Venkataramanan 		fc = "RX";
543cdedef59SAnirudh Venkataramanan 		break;
544cdedef59SAnirudh Venkataramanan 	default:
545cdedef59SAnirudh Venkataramanan 		fc = "Unknown";
546cdedef59SAnirudh Venkataramanan 		break;
547cdedef59SAnirudh Venkataramanan 	}
548cdedef59SAnirudh Venkataramanan 
549cdedef59SAnirudh Venkataramanan 	netdev_info(vsi->netdev, "NIC Link is up %sbps, Flow Control: %s\n",
550cdedef59SAnirudh Venkataramanan 		    speed, fc);
551cdedef59SAnirudh Venkataramanan }
552cdedef59SAnirudh Venkataramanan 
553cdedef59SAnirudh Venkataramanan /**
5540b28b702SAnirudh Venkataramanan  * ice_init_link_events - enable/initialize link events
5550b28b702SAnirudh Venkataramanan  * @pi: pointer to the port_info instance
5560b28b702SAnirudh Venkataramanan  *
5570b28b702SAnirudh Venkataramanan  * Returns -EIO on failure, 0 on success
5580b28b702SAnirudh Venkataramanan  */
5590b28b702SAnirudh Venkataramanan static int ice_init_link_events(struct ice_port_info *pi)
5600b28b702SAnirudh Venkataramanan {
5610b28b702SAnirudh Venkataramanan 	u16 mask;
5620b28b702SAnirudh Venkataramanan 
5630b28b702SAnirudh Venkataramanan 	mask = ~((u16)(ICE_AQ_LINK_EVENT_UPDOWN | ICE_AQ_LINK_EVENT_MEDIA_NA |
5640b28b702SAnirudh Venkataramanan 		       ICE_AQ_LINK_EVENT_MODULE_QUAL_FAIL));
5650b28b702SAnirudh Venkataramanan 
5660b28b702SAnirudh Venkataramanan 	if (ice_aq_set_event_mask(pi->hw, pi->lport, mask, NULL)) {
5670b28b702SAnirudh Venkataramanan 		dev_dbg(ice_hw_to_dev(pi->hw),
5680b28b702SAnirudh Venkataramanan 			"Failed to set link event mask for port %d\n",
5690b28b702SAnirudh Venkataramanan 			pi->lport);
5700b28b702SAnirudh Venkataramanan 		return -EIO;
5710b28b702SAnirudh Venkataramanan 	}
5720b28b702SAnirudh Venkataramanan 
5730b28b702SAnirudh Venkataramanan 	if (ice_aq_get_link_info(pi, true, NULL, NULL)) {
5740b28b702SAnirudh Venkataramanan 		dev_dbg(ice_hw_to_dev(pi->hw),
5750b28b702SAnirudh Venkataramanan 			"Failed to enable link events for port %d\n",
5760b28b702SAnirudh Venkataramanan 			pi->lport);
5770b28b702SAnirudh Venkataramanan 		return -EIO;
5780b28b702SAnirudh Venkataramanan 	}
5790b28b702SAnirudh Venkataramanan 
5800b28b702SAnirudh Venkataramanan 	return 0;
5810b28b702SAnirudh Venkataramanan }
5820b28b702SAnirudh Venkataramanan 
5830b28b702SAnirudh Venkataramanan /**
5840b28b702SAnirudh Venkataramanan  * ice_vsi_link_event - update the vsi's netdev
5850b28b702SAnirudh Venkataramanan  * @vsi: the vsi on which the link event occurred
5860b28b702SAnirudh Venkataramanan  * @link_up: whether or not the vsi needs to be set up or down
5870b28b702SAnirudh Venkataramanan  */
5880b28b702SAnirudh Venkataramanan static void ice_vsi_link_event(struct ice_vsi *vsi, bool link_up)
5890b28b702SAnirudh Venkataramanan {
5900b28b702SAnirudh Venkataramanan 	if (!vsi || test_bit(__ICE_DOWN, vsi->state))
5910b28b702SAnirudh Venkataramanan 		return;
5920b28b702SAnirudh Venkataramanan 
5930b28b702SAnirudh Venkataramanan 	if (vsi->type == ICE_VSI_PF) {
5940b28b702SAnirudh Venkataramanan 		if (!vsi->netdev) {
5950b28b702SAnirudh Venkataramanan 			dev_dbg(&vsi->back->pdev->dev,
5960b28b702SAnirudh Venkataramanan 				"vsi->netdev is not initialized!\n");
5970b28b702SAnirudh Venkataramanan 			return;
5980b28b702SAnirudh Venkataramanan 		}
5990b28b702SAnirudh Venkataramanan 		if (link_up) {
6000b28b702SAnirudh Venkataramanan 			netif_carrier_on(vsi->netdev);
6010b28b702SAnirudh Venkataramanan 			netif_tx_wake_all_queues(vsi->netdev);
6020b28b702SAnirudh Venkataramanan 		} else {
6030b28b702SAnirudh Venkataramanan 			netif_carrier_off(vsi->netdev);
6040b28b702SAnirudh Venkataramanan 			netif_tx_stop_all_queues(vsi->netdev);
6050b28b702SAnirudh Venkataramanan 		}
6060b28b702SAnirudh Venkataramanan 	}
6070b28b702SAnirudh Venkataramanan }
6080b28b702SAnirudh Venkataramanan 
6090b28b702SAnirudh Venkataramanan /**
6100b28b702SAnirudh Venkataramanan  * ice_link_event - process the link event
6110b28b702SAnirudh Venkataramanan  * @pf: pf that the link event is associated with
6120b28b702SAnirudh Venkataramanan  * @pi: port_info for the port that the link event is associated with
6130b28b702SAnirudh Venkataramanan  *
6140b28b702SAnirudh Venkataramanan  * Returns -EIO if ice_get_link_status() fails
6150b28b702SAnirudh Venkataramanan  * Returns 0 on success
6160b28b702SAnirudh Venkataramanan  */
6170b28b702SAnirudh Venkataramanan static int
6180b28b702SAnirudh Venkataramanan ice_link_event(struct ice_pf *pf, struct ice_port_info *pi)
6190b28b702SAnirudh Venkataramanan {
6200b28b702SAnirudh Venkataramanan 	u8 new_link_speed, old_link_speed;
6210b28b702SAnirudh Venkataramanan 	struct ice_phy_info *phy_info;
6220b28b702SAnirudh Venkataramanan 	bool new_link_same_as_old;
6230b28b702SAnirudh Venkataramanan 	bool new_link, old_link;
6240b28b702SAnirudh Venkataramanan 	u8 lport;
6250b28b702SAnirudh Venkataramanan 	u16 v;
6260b28b702SAnirudh Venkataramanan 
6270b28b702SAnirudh Venkataramanan 	phy_info = &pi->phy;
6280b28b702SAnirudh Venkataramanan 	phy_info->link_info_old = phy_info->link_info;
6290b28b702SAnirudh Venkataramanan 	/* Force ice_get_link_status() to update link info */
6300b28b702SAnirudh Venkataramanan 	phy_info->get_link_info = true;
6310b28b702SAnirudh Venkataramanan 
6320b28b702SAnirudh Venkataramanan 	old_link = (phy_info->link_info_old.link_info & ICE_AQ_LINK_UP);
6330b28b702SAnirudh Venkataramanan 	old_link_speed = phy_info->link_info_old.link_speed;
6340b28b702SAnirudh Venkataramanan 
6350b28b702SAnirudh Venkataramanan 	lport = pi->lport;
6360b28b702SAnirudh Venkataramanan 	if (ice_get_link_status(pi, &new_link)) {
6370b28b702SAnirudh Venkataramanan 		dev_dbg(&pf->pdev->dev,
6380b28b702SAnirudh Venkataramanan 			"Could not get link status for port %d\n", lport);
6390b28b702SAnirudh Venkataramanan 		return -EIO;
6400b28b702SAnirudh Venkataramanan 	}
6410b28b702SAnirudh Venkataramanan 
6420b28b702SAnirudh Venkataramanan 	new_link_speed = phy_info->link_info.link_speed;
6430b28b702SAnirudh Venkataramanan 
6440b28b702SAnirudh Venkataramanan 	new_link_same_as_old = (new_link == old_link &&
6450b28b702SAnirudh Venkataramanan 				new_link_speed == old_link_speed);
6460b28b702SAnirudh Venkataramanan 
6470b28b702SAnirudh Venkataramanan 	ice_for_each_vsi(pf, v) {
6480b28b702SAnirudh Venkataramanan 		struct ice_vsi *vsi = pf->vsi[v];
6490b28b702SAnirudh Venkataramanan 
6500b28b702SAnirudh Venkataramanan 		if (!vsi || !vsi->port_info)
6510b28b702SAnirudh Venkataramanan 			continue;
6520b28b702SAnirudh Venkataramanan 
6530b28b702SAnirudh Venkataramanan 		if (new_link_same_as_old &&
6540b28b702SAnirudh Venkataramanan 		    (test_bit(__ICE_DOWN, vsi->state) ||
6550b28b702SAnirudh Venkataramanan 		    new_link == netif_carrier_ok(vsi->netdev)))
6560b28b702SAnirudh Venkataramanan 			continue;
6570b28b702SAnirudh Venkataramanan 
6580b28b702SAnirudh Venkataramanan 		if (vsi->port_info->lport == lport) {
6590b28b702SAnirudh Venkataramanan 			ice_print_link_msg(vsi, new_link);
6600b28b702SAnirudh Venkataramanan 			ice_vsi_link_event(vsi, new_link);
6610b28b702SAnirudh Venkataramanan 		}
6620b28b702SAnirudh Venkataramanan 	}
6630b28b702SAnirudh Venkataramanan 
6640b28b702SAnirudh Venkataramanan 	return 0;
6650b28b702SAnirudh Venkataramanan }
6660b28b702SAnirudh Venkataramanan 
6670b28b702SAnirudh Venkataramanan /**
6680b28b702SAnirudh Venkataramanan  * ice_handle_link_event - handle link event via ARQ
6690b28b702SAnirudh Venkataramanan  * @pf: pf that the link event is associated with
6700b28b702SAnirudh Venkataramanan  *
6710b28b702SAnirudh Venkataramanan  * Return -EINVAL if port_info is null
6720b28b702SAnirudh Venkataramanan  * Return status on succes
6730b28b702SAnirudh Venkataramanan  */
6740b28b702SAnirudh Venkataramanan static int ice_handle_link_event(struct ice_pf *pf)
6750b28b702SAnirudh Venkataramanan {
6760b28b702SAnirudh Venkataramanan 	struct ice_port_info *port_info;
6770b28b702SAnirudh Venkataramanan 	int status;
6780b28b702SAnirudh Venkataramanan 
6790b28b702SAnirudh Venkataramanan 	port_info = pf->hw.port_info;
6800b28b702SAnirudh Venkataramanan 	if (!port_info)
6810b28b702SAnirudh Venkataramanan 		return -EINVAL;
6820b28b702SAnirudh Venkataramanan 
6830b28b702SAnirudh Venkataramanan 	status = ice_link_event(pf, port_info);
6840b28b702SAnirudh Venkataramanan 	if (status)
6850b28b702SAnirudh Venkataramanan 		dev_dbg(&pf->pdev->dev,
6860b28b702SAnirudh Venkataramanan 			"Could not process link event, error %d\n", status);
6870b28b702SAnirudh Venkataramanan 
6880b28b702SAnirudh Venkataramanan 	return status;
6890b28b702SAnirudh Venkataramanan }
6900b28b702SAnirudh Venkataramanan 
6910b28b702SAnirudh Venkataramanan /**
692940b61afSAnirudh Venkataramanan  * __ice_clean_ctrlq - helper function to clean controlq rings
693940b61afSAnirudh Venkataramanan  * @pf: ptr to struct ice_pf
694940b61afSAnirudh Venkataramanan  * @q_type: specific Control queue type
695940b61afSAnirudh Venkataramanan  */
696940b61afSAnirudh Venkataramanan static int __ice_clean_ctrlq(struct ice_pf *pf, enum ice_ctl_q q_type)
697940b61afSAnirudh Venkataramanan {
698940b61afSAnirudh Venkataramanan 	struct ice_rq_event_info event;
699940b61afSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
700940b61afSAnirudh Venkataramanan 	struct ice_ctl_q_info *cq;
701940b61afSAnirudh Venkataramanan 	u16 pending, i = 0;
702940b61afSAnirudh Venkataramanan 	const char *qtype;
703940b61afSAnirudh Venkataramanan 	u32 oldval, val;
704940b61afSAnirudh Venkataramanan 
7050b28b702SAnirudh Venkataramanan 	/* Do not clean control queue if/when PF reset fails */
7060b28b702SAnirudh Venkataramanan 	if (test_bit(__ICE_RESET_FAILED, pf->state))
7070b28b702SAnirudh Venkataramanan 		return 0;
7080b28b702SAnirudh Venkataramanan 
709940b61afSAnirudh Venkataramanan 	switch (q_type) {
710940b61afSAnirudh Venkataramanan 	case ICE_CTL_Q_ADMIN:
711940b61afSAnirudh Venkataramanan 		cq = &hw->adminq;
712940b61afSAnirudh Venkataramanan 		qtype = "Admin";
713940b61afSAnirudh Venkataramanan 		break;
71475d2b253SAnirudh Venkataramanan 	case ICE_CTL_Q_MAILBOX:
71575d2b253SAnirudh Venkataramanan 		cq = &hw->mailboxq;
71675d2b253SAnirudh Venkataramanan 		qtype = "Mailbox";
71775d2b253SAnirudh Venkataramanan 		break;
718940b61afSAnirudh Venkataramanan 	default:
719940b61afSAnirudh Venkataramanan 		dev_warn(&pf->pdev->dev, "Unknown control queue type 0x%x\n",
720940b61afSAnirudh Venkataramanan 			 q_type);
721940b61afSAnirudh Venkataramanan 		return 0;
722940b61afSAnirudh Venkataramanan 	}
723940b61afSAnirudh Venkataramanan 
724940b61afSAnirudh Venkataramanan 	/* check for error indications - PF_xx_AxQLEN register layout for
725940b61afSAnirudh Venkataramanan 	 * FW/MBX/SB are identical so just use defines for PF_FW_AxQLEN.
726940b61afSAnirudh Venkataramanan 	 */
727940b61afSAnirudh Venkataramanan 	val = rd32(hw, cq->rq.len);
728940b61afSAnirudh Venkataramanan 	if (val & (PF_FW_ARQLEN_ARQVFE_M | PF_FW_ARQLEN_ARQOVFL_M |
729940b61afSAnirudh Venkataramanan 		   PF_FW_ARQLEN_ARQCRIT_M)) {
730940b61afSAnirudh Venkataramanan 		oldval = val;
731940b61afSAnirudh Venkataramanan 		if (val & PF_FW_ARQLEN_ARQVFE_M)
732940b61afSAnirudh Venkataramanan 			dev_dbg(&pf->pdev->dev,
733940b61afSAnirudh Venkataramanan 				"%s Receive Queue VF Error detected\n", qtype);
734940b61afSAnirudh Venkataramanan 		if (val & PF_FW_ARQLEN_ARQOVFL_M) {
735940b61afSAnirudh Venkataramanan 			dev_dbg(&pf->pdev->dev,
736940b61afSAnirudh Venkataramanan 				"%s Receive Queue Overflow Error detected\n",
737940b61afSAnirudh Venkataramanan 				qtype);
738940b61afSAnirudh Venkataramanan 		}
739940b61afSAnirudh Venkataramanan 		if (val & PF_FW_ARQLEN_ARQCRIT_M)
740940b61afSAnirudh Venkataramanan 			dev_dbg(&pf->pdev->dev,
741940b61afSAnirudh Venkataramanan 				"%s Receive Queue Critical Error detected\n",
742940b61afSAnirudh Venkataramanan 				qtype);
743940b61afSAnirudh Venkataramanan 		val &= ~(PF_FW_ARQLEN_ARQVFE_M | PF_FW_ARQLEN_ARQOVFL_M |
744940b61afSAnirudh Venkataramanan 			 PF_FW_ARQLEN_ARQCRIT_M);
745940b61afSAnirudh Venkataramanan 		if (oldval != val)
746940b61afSAnirudh Venkataramanan 			wr32(hw, cq->rq.len, val);
747940b61afSAnirudh Venkataramanan 	}
748940b61afSAnirudh Venkataramanan 
749940b61afSAnirudh Venkataramanan 	val = rd32(hw, cq->sq.len);
750940b61afSAnirudh Venkataramanan 	if (val & (PF_FW_ATQLEN_ATQVFE_M | PF_FW_ATQLEN_ATQOVFL_M |
751940b61afSAnirudh Venkataramanan 		   PF_FW_ATQLEN_ATQCRIT_M)) {
752940b61afSAnirudh Venkataramanan 		oldval = val;
753940b61afSAnirudh Venkataramanan 		if (val & PF_FW_ATQLEN_ATQVFE_M)
754940b61afSAnirudh Venkataramanan 			dev_dbg(&pf->pdev->dev,
755940b61afSAnirudh Venkataramanan 				"%s Send Queue VF Error detected\n", qtype);
756940b61afSAnirudh Venkataramanan 		if (val & PF_FW_ATQLEN_ATQOVFL_M) {
757940b61afSAnirudh Venkataramanan 			dev_dbg(&pf->pdev->dev,
758940b61afSAnirudh Venkataramanan 				"%s Send Queue Overflow Error detected\n",
759940b61afSAnirudh Venkataramanan 				qtype);
760940b61afSAnirudh Venkataramanan 		}
761940b61afSAnirudh Venkataramanan 		if (val & PF_FW_ATQLEN_ATQCRIT_M)
762940b61afSAnirudh Venkataramanan 			dev_dbg(&pf->pdev->dev,
763940b61afSAnirudh Venkataramanan 				"%s Send Queue Critical Error detected\n",
764940b61afSAnirudh Venkataramanan 				qtype);
765940b61afSAnirudh Venkataramanan 		val &= ~(PF_FW_ATQLEN_ATQVFE_M | PF_FW_ATQLEN_ATQOVFL_M |
766940b61afSAnirudh Venkataramanan 			 PF_FW_ATQLEN_ATQCRIT_M);
767940b61afSAnirudh Venkataramanan 		if (oldval != val)
768940b61afSAnirudh Venkataramanan 			wr32(hw, cq->sq.len, val);
769940b61afSAnirudh Venkataramanan 	}
770940b61afSAnirudh Venkataramanan 
771940b61afSAnirudh Venkataramanan 	event.buf_len = cq->rq_buf_size;
772940b61afSAnirudh Venkataramanan 	event.msg_buf = devm_kzalloc(&pf->pdev->dev, event.buf_len,
773940b61afSAnirudh Venkataramanan 				     GFP_KERNEL);
774940b61afSAnirudh Venkataramanan 	if (!event.msg_buf)
775940b61afSAnirudh Venkataramanan 		return 0;
776940b61afSAnirudh Venkataramanan 
777940b61afSAnirudh Venkataramanan 	do {
778940b61afSAnirudh Venkataramanan 		enum ice_status ret;
7790b28b702SAnirudh Venkataramanan 		u16 opcode;
780940b61afSAnirudh Venkataramanan 
781940b61afSAnirudh Venkataramanan 		ret = ice_clean_rq_elem(hw, cq, &event, &pending);
782940b61afSAnirudh Venkataramanan 		if (ret == ICE_ERR_AQ_NO_WORK)
783940b61afSAnirudh Venkataramanan 			break;
784940b61afSAnirudh Venkataramanan 		if (ret) {
785940b61afSAnirudh Venkataramanan 			dev_err(&pf->pdev->dev,
786940b61afSAnirudh Venkataramanan 				"%s Receive Queue event error %d\n", qtype,
787940b61afSAnirudh Venkataramanan 				ret);
788940b61afSAnirudh Venkataramanan 			break;
789940b61afSAnirudh Venkataramanan 		}
7900b28b702SAnirudh Venkataramanan 
7910b28b702SAnirudh Venkataramanan 		opcode = le16_to_cpu(event.desc.opcode);
7920b28b702SAnirudh Venkataramanan 
7930b28b702SAnirudh Venkataramanan 		switch (opcode) {
7940b28b702SAnirudh Venkataramanan 		case ice_aqc_opc_get_link_status:
7950b28b702SAnirudh Venkataramanan 			if (ice_handle_link_event(pf))
7960b28b702SAnirudh Venkataramanan 				dev_err(&pf->pdev->dev,
7973968540bSAnirudh Venkataramanan 					"Could not handle link event\n");
7980b28b702SAnirudh Venkataramanan 			break;
7998b97ceb1SHieu Tran 		case ice_aqc_opc_fw_logging:
8008b97ceb1SHieu Tran 			ice_output_fw_log(hw, &event.desc, event.msg_buf);
8018b97ceb1SHieu Tran 			break;
8020b28b702SAnirudh Venkataramanan 		default:
8030b28b702SAnirudh Venkataramanan 			dev_dbg(&pf->pdev->dev,
8040b28b702SAnirudh Venkataramanan 				"%s Receive Queue unknown event 0x%04x ignored\n",
8050b28b702SAnirudh Venkataramanan 				qtype, opcode);
8060b28b702SAnirudh Venkataramanan 			break;
8070b28b702SAnirudh Venkataramanan 		}
808940b61afSAnirudh Venkataramanan 	} while (pending && (i++ < ICE_DFLT_IRQ_WORK));
809940b61afSAnirudh Venkataramanan 
810940b61afSAnirudh Venkataramanan 	devm_kfree(&pf->pdev->dev, event.msg_buf);
811940b61afSAnirudh Venkataramanan 
812940b61afSAnirudh Venkataramanan 	return pending && (i == ICE_DFLT_IRQ_WORK);
813940b61afSAnirudh Venkataramanan }
814940b61afSAnirudh Venkataramanan 
815940b61afSAnirudh Venkataramanan /**
8163d6b640eSAnirudh Venkataramanan  * ice_ctrlq_pending - check if there is a difference between ntc and ntu
8173d6b640eSAnirudh Venkataramanan  * @hw: pointer to hardware info
8183d6b640eSAnirudh Venkataramanan  * @cq: control queue information
8193d6b640eSAnirudh Venkataramanan  *
8203d6b640eSAnirudh Venkataramanan  * returns true if there are pending messages in a queue, false if there aren't
8213d6b640eSAnirudh Venkataramanan  */
8223d6b640eSAnirudh Venkataramanan static bool ice_ctrlq_pending(struct ice_hw *hw, struct ice_ctl_q_info *cq)
8233d6b640eSAnirudh Venkataramanan {
8243d6b640eSAnirudh Venkataramanan 	u16 ntu;
8253d6b640eSAnirudh Venkataramanan 
8263d6b640eSAnirudh Venkataramanan 	ntu = (u16)(rd32(hw, cq->rq.head) & cq->rq.head_mask);
8273d6b640eSAnirudh Venkataramanan 	return cq->rq.next_to_clean != ntu;
8283d6b640eSAnirudh Venkataramanan }
8293d6b640eSAnirudh Venkataramanan 
8303d6b640eSAnirudh Venkataramanan /**
831940b61afSAnirudh Venkataramanan  * ice_clean_adminq_subtask - clean the AdminQ rings
832940b61afSAnirudh Venkataramanan  * @pf: board private structure
833940b61afSAnirudh Venkataramanan  */
834940b61afSAnirudh Venkataramanan static void ice_clean_adminq_subtask(struct ice_pf *pf)
835940b61afSAnirudh Venkataramanan {
836940b61afSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
837940b61afSAnirudh Venkataramanan 
838940b61afSAnirudh Venkataramanan 	if (!test_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state))
839940b61afSAnirudh Venkataramanan 		return;
840940b61afSAnirudh Venkataramanan 
841940b61afSAnirudh Venkataramanan 	if (__ice_clean_ctrlq(pf, ICE_CTL_Q_ADMIN))
842940b61afSAnirudh Venkataramanan 		return;
843940b61afSAnirudh Venkataramanan 
844940b61afSAnirudh Venkataramanan 	clear_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state);
845940b61afSAnirudh Venkataramanan 
8463d6b640eSAnirudh Venkataramanan 	/* There might be a situation where new messages arrive to a control
8473d6b640eSAnirudh Venkataramanan 	 * queue between processing the last message and clearing the
8483d6b640eSAnirudh Venkataramanan 	 * EVENT_PENDING bit. So before exiting, check queue head again (using
8493d6b640eSAnirudh Venkataramanan 	 * ice_ctrlq_pending) and process new messages if any.
8503d6b640eSAnirudh Venkataramanan 	 */
8513d6b640eSAnirudh Venkataramanan 	if (ice_ctrlq_pending(hw, &hw->adminq))
8523d6b640eSAnirudh Venkataramanan 		__ice_clean_ctrlq(pf, ICE_CTL_Q_ADMIN);
853940b61afSAnirudh Venkataramanan 
854940b61afSAnirudh Venkataramanan 	ice_flush(hw);
855940b61afSAnirudh Venkataramanan }
856940b61afSAnirudh Venkataramanan 
857940b61afSAnirudh Venkataramanan /**
85875d2b253SAnirudh Venkataramanan  * ice_clean_mailboxq_subtask - clean the MailboxQ rings
85975d2b253SAnirudh Venkataramanan  * @pf: board private structure
86075d2b253SAnirudh Venkataramanan  */
86175d2b253SAnirudh Venkataramanan static void ice_clean_mailboxq_subtask(struct ice_pf *pf)
86275d2b253SAnirudh Venkataramanan {
86375d2b253SAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
86475d2b253SAnirudh Venkataramanan 
86575d2b253SAnirudh Venkataramanan 	if (!test_bit(__ICE_MAILBOXQ_EVENT_PENDING, pf->state))
86675d2b253SAnirudh Venkataramanan 		return;
86775d2b253SAnirudh Venkataramanan 
86875d2b253SAnirudh Venkataramanan 	if (__ice_clean_ctrlq(pf, ICE_CTL_Q_MAILBOX))
86975d2b253SAnirudh Venkataramanan 		return;
87075d2b253SAnirudh Venkataramanan 
87175d2b253SAnirudh Venkataramanan 	clear_bit(__ICE_MAILBOXQ_EVENT_PENDING, pf->state);
87275d2b253SAnirudh Venkataramanan 
87375d2b253SAnirudh Venkataramanan 	if (ice_ctrlq_pending(hw, &hw->mailboxq))
87475d2b253SAnirudh Venkataramanan 		__ice_clean_ctrlq(pf, ICE_CTL_Q_MAILBOX);
87575d2b253SAnirudh Venkataramanan 
87675d2b253SAnirudh Venkataramanan 	ice_flush(hw);
87775d2b253SAnirudh Venkataramanan }
87875d2b253SAnirudh Venkataramanan 
87975d2b253SAnirudh Venkataramanan /**
880940b61afSAnirudh Venkataramanan  * ice_service_task_schedule - schedule the service task to wake up
881940b61afSAnirudh Venkataramanan  * @pf: board private structure
882940b61afSAnirudh Venkataramanan  *
883940b61afSAnirudh Venkataramanan  * If not already scheduled, this puts the task into the work queue.
884940b61afSAnirudh Venkataramanan  */
885940b61afSAnirudh Venkataramanan static void ice_service_task_schedule(struct ice_pf *pf)
886940b61afSAnirudh Venkataramanan {
8878d81fa55SAkeem G Abodunrin 	if (!test_bit(__ICE_SERVICE_DIS, pf->state) &&
8880f9d5027SAnirudh Venkataramanan 	    !test_and_set_bit(__ICE_SERVICE_SCHED, pf->state) &&
8890f9d5027SAnirudh Venkataramanan 	    !test_bit(__ICE_NEEDS_RESTART, pf->state))
890940b61afSAnirudh Venkataramanan 		queue_work(ice_wq, &pf->serv_task);
891940b61afSAnirudh Venkataramanan }
892940b61afSAnirudh Venkataramanan 
893940b61afSAnirudh Venkataramanan /**
894940b61afSAnirudh Venkataramanan  * ice_service_task_complete - finish up the service task
895940b61afSAnirudh Venkataramanan  * @pf: board private structure
896940b61afSAnirudh Venkataramanan  */
897940b61afSAnirudh Venkataramanan static void ice_service_task_complete(struct ice_pf *pf)
898940b61afSAnirudh Venkataramanan {
899940b61afSAnirudh Venkataramanan 	WARN_ON(!test_bit(__ICE_SERVICE_SCHED, pf->state));
900940b61afSAnirudh Venkataramanan 
901940b61afSAnirudh Venkataramanan 	/* force memory (pf->state) to sync before next service task */
902940b61afSAnirudh Venkataramanan 	smp_mb__before_atomic();
903940b61afSAnirudh Venkataramanan 	clear_bit(__ICE_SERVICE_SCHED, pf->state);
904940b61afSAnirudh Venkataramanan }
905940b61afSAnirudh Venkataramanan 
906940b61afSAnirudh Venkataramanan /**
9078d81fa55SAkeem G Abodunrin  * ice_service_task_stop - stop service task and cancel works
9088d81fa55SAkeem G Abodunrin  * @pf: board private structure
9098d81fa55SAkeem G Abodunrin  */
9108d81fa55SAkeem G Abodunrin static void ice_service_task_stop(struct ice_pf *pf)
9118d81fa55SAkeem G Abodunrin {
9128d81fa55SAkeem G Abodunrin 	set_bit(__ICE_SERVICE_DIS, pf->state);
9138d81fa55SAkeem G Abodunrin 
9148d81fa55SAkeem G Abodunrin 	if (pf->serv_tmr.function)
9158d81fa55SAkeem G Abodunrin 		del_timer_sync(&pf->serv_tmr);
9168d81fa55SAkeem G Abodunrin 	if (pf->serv_task.func)
9178d81fa55SAkeem G Abodunrin 		cancel_work_sync(&pf->serv_task);
9188d81fa55SAkeem G Abodunrin 
9198d81fa55SAkeem G Abodunrin 	clear_bit(__ICE_SERVICE_SCHED, pf->state);
9208d81fa55SAkeem G Abodunrin }
9218d81fa55SAkeem G Abodunrin 
9228d81fa55SAkeem G Abodunrin /**
923940b61afSAnirudh Venkataramanan  * ice_service_timer - timer callback to schedule service task
924940b61afSAnirudh Venkataramanan  * @t: pointer to timer_list
925940b61afSAnirudh Venkataramanan  */
926940b61afSAnirudh Venkataramanan static void ice_service_timer(struct timer_list *t)
927940b61afSAnirudh Venkataramanan {
928940b61afSAnirudh Venkataramanan 	struct ice_pf *pf = from_timer(pf, t, serv_tmr);
929940b61afSAnirudh Venkataramanan 
930940b61afSAnirudh Venkataramanan 	mod_timer(&pf->serv_tmr, round_jiffies(pf->serv_tmr_period + jiffies));
931940b61afSAnirudh Venkataramanan 	ice_service_task_schedule(pf);
932940b61afSAnirudh Venkataramanan }
933940b61afSAnirudh Venkataramanan 
934940b61afSAnirudh Venkataramanan /**
935b3969fd7SSudheer Mogilappagari  * ice_handle_mdd_event - handle malicious driver detect event
936b3969fd7SSudheer Mogilappagari  * @pf: pointer to the PF structure
937b3969fd7SSudheer Mogilappagari  *
938b3969fd7SSudheer Mogilappagari  * Called from service task. OICR interrupt handler indicates MDD event
939b3969fd7SSudheer Mogilappagari  */
940b3969fd7SSudheer Mogilappagari static void ice_handle_mdd_event(struct ice_pf *pf)
941b3969fd7SSudheer Mogilappagari {
942b3969fd7SSudheer Mogilappagari 	struct ice_hw *hw = &pf->hw;
943b3969fd7SSudheer Mogilappagari 	bool mdd_detected = false;
944b3969fd7SSudheer Mogilappagari 	u32 reg;
945b3969fd7SSudheer Mogilappagari 
946b3969fd7SSudheer Mogilappagari 	if (!test_bit(__ICE_MDD_EVENT_PENDING, pf->state))
947b3969fd7SSudheer Mogilappagari 		return;
948b3969fd7SSudheer Mogilappagari 
949b3969fd7SSudheer Mogilappagari 	/* find what triggered the MDD event */
950b3969fd7SSudheer Mogilappagari 	reg = rd32(hw, GL_MDET_TX_PQM);
951b3969fd7SSudheer Mogilappagari 	if (reg & GL_MDET_TX_PQM_VALID_M) {
952b3969fd7SSudheer Mogilappagari 		u8 pf_num = (reg & GL_MDET_TX_PQM_PF_NUM_M) >>
953b3969fd7SSudheer Mogilappagari 				GL_MDET_TX_PQM_PF_NUM_S;
954b3969fd7SSudheer Mogilappagari 		u16 vf_num = (reg & GL_MDET_TX_PQM_VF_NUM_M) >>
955b3969fd7SSudheer Mogilappagari 				GL_MDET_TX_PQM_VF_NUM_S;
956b3969fd7SSudheer Mogilappagari 		u8 event = (reg & GL_MDET_TX_PQM_MAL_TYPE_M) >>
957b3969fd7SSudheer Mogilappagari 				GL_MDET_TX_PQM_MAL_TYPE_S;
958b3969fd7SSudheer Mogilappagari 		u16 queue = ((reg & GL_MDET_TX_PQM_QNUM_M) >>
959b3969fd7SSudheer Mogilappagari 				GL_MDET_TX_PQM_QNUM_S);
960b3969fd7SSudheer Mogilappagari 
961b3969fd7SSudheer Mogilappagari 		if (netif_msg_tx_err(pf))
962b3969fd7SSudheer Mogilappagari 			dev_info(&pf->pdev->dev, "Malicious Driver Detection event %d on TX queue %d PF# %d VF# %d\n",
963b3969fd7SSudheer Mogilappagari 				 event, queue, pf_num, vf_num);
964b3969fd7SSudheer Mogilappagari 		wr32(hw, GL_MDET_TX_PQM, 0xffffffff);
965b3969fd7SSudheer Mogilappagari 		mdd_detected = true;
966b3969fd7SSudheer Mogilappagari 	}
967b3969fd7SSudheer Mogilappagari 
968b3969fd7SSudheer Mogilappagari 	reg = rd32(hw, GL_MDET_TX_TCLAN);
969b3969fd7SSudheer Mogilappagari 	if (reg & GL_MDET_TX_TCLAN_VALID_M) {
970b3969fd7SSudheer Mogilappagari 		u8 pf_num = (reg & GL_MDET_TX_TCLAN_PF_NUM_M) >>
971b3969fd7SSudheer Mogilappagari 				GL_MDET_TX_TCLAN_PF_NUM_S;
972b3969fd7SSudheer Mogilappagari 		u16 vf_num = (reg & GL_MDET_TX_TCLAN_VF_NUM_M) >>
973b3969fd7SSudheer Mogilappagari 				GL_MDET_TX_TCLAN_VF_NUM_S;
974b3969fd7SSudheer Mogilappagari 		u8 event = (reg & GL_MDET_TX_TCLAN_MAL_TYPE_M) >>
975b3969fd7SSudheer Mogilappagari 				GL_MDET_TX_TCLAN_MAL_TYPE_S;
976b3969fd7SSudheer Mogilappagari 		u16 queue = ((reg & GL_MDET_TX_TCLAN_QNUM_M) >>
977b3969fd7SSudheer Mogilappagari 				GL_MDET_TX_TCLAN_QNUM_S);
978b3969fd7SSudheer Mogilappagari 
979b3969fd7SSudheer Mogilappagari 		if (netif_msg_rx_err(pf))
980b3969fd7SSudheer Mogilappagari 			dev_info(&pf->pdev->dev, "Malicious Driver Detection event %d on TX queue %d PF# %d VF# %d\n",
981b3969fd7SSudheer Mogilappagari 				 event, queue, pf_num, vf_num);
982b3969fd7SSudheer Mogilappagari 		wr32(hw, GL_MDET_TX_TCLAN, 0xffffffff);
983b3969fd7SSudheer Mogilappagari 		mdd_detected = true;
984b3969fd7SSudheer Mogilappagari 	}
985b3969fd7SSudheer Mogilappagari 
986b3969fd7SSudheer Mogilappagari 	reg = rd32(hw, GL_MDET_RX);
987b3969fd7SSudheer Mogilappagari 	if (reg & GL_MDET_RX_VALID_M) {
988b3969fd7SSudheer Mogilappagari 		u8 pf_num = (reg & GL_MDET_RX_PF_NUM_M) >>
989b3969fd7SSudheer Mogilappagari 				GL_MDET_RX_PF_NUM_S;
990b3969fd7SSudheer Mogilappagari 		u16 vf_num = (reg & GL_MDET_RX_VF_NUM_M) >>
991b3969fd7SSudheer Mogilappagari 				GL_MDET_RX_VF_NUM_S;
992b3969fd7SSudheer Mogilappagari 		u8 event = (reg & GL_MDET_RX_MAL_TYPE_M) >>
993b3969fd7SSudheer Mogilappagari 				GL_MDET_RX_MAL_TYPE_S;
994b3969fd7SSudheer Mogilappagari 		u16 queue = ((reg & GL_MDET_RX_QNUM_M) >>
995b3969fd7SSudheer Mogilappagari 				GL_MDET_RX_QNUM_S);
996b3969fd7SSudheer Mogilappagari 
997b3969fd7SSudheer Mogilappagari 		if (netif_msg_rx_err(pf))
998b3969fd7SSudheer Mogilappagari 			dev_info(&pf->pdev->dev, "Malicious Driver Detection event %d on RX queue %d PF# %d VF# %d\n",
999b3969fd7SSudheer Mogilappagari 				 event, queue, pf_num, vf_num);
1000b3969fd7SSudheer Mogilappagari 		wr32(hw, GL_MDET_RX, 0xffffffff);
1001b3969fd7SSudheer Mogilappagari 		mdd_detected = true;
1002b3969fd7SSudheer Mogilappagari 	}
1003b3969fd7SSudheer Mogilappagari 
1004b3969fd7SSudheer Mogilappagari 	if (mdd_detected) {
1005b3969fd7SSudheer Mogilappagari 		bool pf_mdd_detected = false;
1006b3969fd7SSudheer Mogilappagari 
1007b3969fd7SSudheer Mogilappagari 		reg = rd32(hw, PF_MDET_TX_PQM);
1008b3969fd7SSudheer Mogilappagari 		if (reg & PF_MDET_TX_PQM_VALID_M) {
1009b3969fd7SSudheer Mogilappagari 			wr32(hw, PF_MDET_TX_PQM, 0xFFFF);
1010b3969fd7SSudheer Mogilappagari 			dev_info(&pf->pdev->dev, "TX driver issue detected, PF reset issued\n");
1011b3969fd7SSudheer Mogilappagari 			pf_mdd_detected = true;
1012b3969fd7SSudheer Mogilappagari 		}
1013b3969fd7SSudheer Mogilappagari 
1014b3969fd7SSudheer Mogilappagari 		reg = rd32(hw, PF_MDET_TX_TCLAN);
1015b3969fd7SSudheer Mogilappagari 		if (reg & PF_MDET_TX_TCLAN_VALID_M) {
1016b3969fd7SSudheer Mogilappagari 			wr32(hw, PF_MDET_TX_TCLAN, 0xFFFF);
1017b3969fd7SSudheer Mogilappagari 			dev_info(&pf->pdev->dev, "TX driver issue detected, PF reset issued\n");
1018b3969fd7SSudheer Mogilappagari 			pf_mdd_detected = true;
1019b3969fd7SSudheer Mogilappagari 		}
1020b3969fd7SSudheer Mogilappagari 
1021b3969fd7SSudheer Mogilappagari 		reg = rd32(hw, PF_MDET_RX);
1022b3969fd7SSudheer Mogilappagari 		if (reg & PF_MDET_RX_VALID_M) {
1023b3969fd7SSudheer Mogilappagari 			wr32(hw, PF_MDET_RX, 0xFFFF);
1024b3969fd7SSudheer Mogilappagari 			dev_info(&pf->pdev->dev, "RX driver issue detected, PF reset issued\n");
1025b3969fd7SSudheer Mogilappagari 			pf_mdd_detected = true;
1026b3969fd7SSudheer Mogilappagari 		}
1027b3969fd7SSudheer Mogilappagari 		/* Queue belongs to the PF initiate a reset */
1028b3969fd7SSudheer Mogilappagari 		if (pf_mdd_detected) {
1029b3969fd7SSudheer Mogilappagari 			set_bit(__ICE_NEEDS_RESTART, pf->state);
1030b3969fd7SSudheer Mogilappagari 			ice_service_task_schedule(pf);
1031b3969fd7SSudheer Mogilappagari 		}
1032b3969fd7SSudheer Mogilappagari 	}
1033b3969fd7SSudheer Mogilappagari 
1034b3969fd7SSudheer Mogilappagari 	/* re-enable MDD interrupt cause */
1035b3969fd7SSudheer Mogilappagari 	clear_bit(__ICE_MDD_EVENT_PENDING, pf->state);
1036b3969fd7SSudheer Mogilappagari 	reg = rd32(hw, PFINT_OICR_ENA);
1037b3969fd7SSudheer Mogilappagari 	reg |= PFINT_OICR_MAL_DETECT_M;
1038b3969fd7SSudheer Mogilappagari 	wr32(hw, PFINT_OICR_ENA, reg);
1039b3969fd7SSudheer Mogilappagari 	ice_flush(hw);
1040b3969fd7SSudheer Mogilappagari }
1041b3969fd7SSudheer Mogilappagari 
1042b3969fd7SSudheer Mogilappagari /**
1043940b61afSAnirudh Venkataramanan  * ice_service_task - manage and run subtasks
1044940b61afSAnirudh Venkataramanan  * @work: pointer to work_struct contained by the PF struct
1045940b61afSAnirudh Venkataramanan  */
1046940b61afSAnirudh Venkataramanan static void ice_service_task(struct work_struct *work)
1047940b61afSAnirudh Venkataramanan {
1048940b61afSAnirudh Venkataramanan 	struct ice_pf *pf = container_of(work, struct ice_pf, serv_task);
1049940b61afSAnirudh Venkataramanan 	unsigned long start_time = jiffies;
1050940b61afSAnirudh Venkataramanan 
1051940b61afSAnirudh Venkataramanan 	/* subtasks */
10520b28b702SAnirudh Venkataramanan 
10530b28b702SAnirudh Venkataramanan 	/* process reset requests first */
10540b28b702SAnirudh Venkataramanan 	ice_reset_subtask(pf);
10550b28b702SAnirudh Venkataramanan 
10560f9d5027SAnirudh Venkataramanan 	/* bail if a reset/recovery cycle is pending or rebuild failed */
10575df7e45dSDave Ertman 	if (ice_is_reset_in_progress(pf->state) ||
10580f9d5027SAnirudh Venkataramanan 	    test_bit(__ICE_SUSPENDED, pf->state) ||
10590f9d5027SAnirudh Venkataramanan 	    test_bit(__ICE_NEEDS_RESTART, pf->state)) {
10600b28b702SAnirudh Venkataramanan 		ice_service_task_complete(pf);
10610b28b702SAnirudh Venkataramanan 		return;
10620b28b702SAnirudh Venkataramanan 	}
10630b28b702SAnirudh Venkataramanan 
1064b3969fd7SSudheer Mogilappagari 	ice_check_for_hang_subtask(pf);
1065e94d4478SAnirudh Venkataramanan 	ice_sync_fltr_subtask(pf);
1066b3969fd7SSudheer Mogilappagari 	ice_handle_mdd_event(pf);
1067fcea6f3dSAnirudh Venkataramanan 	ice_watchdog_subtask(pf);
1068940b61afSAnirudh Venkataramanan 	ice_clean_adminq_subtask(pf);
106975d2b253SAnirudh Venkataramanan 	ice_clean_mailboxq_subtask(pf);
1070940b61afSAnirudh Venkataramanan 
1071940b61afSAnirudh Venkataramanan 	/* Clear __ICE_SERVICE_SCHED flag to allow scheduling next event */
1072940b61afSAnirudh Venkataramanan 	ice_service_task_complete(pf);
1073940b61afSAnirudh Venkataramanan 
1074940b61afSAnirudh Venkataramanan 	/* If the tasks have taken longer than one service timer period
1075940b61afSAnirudh Venkataramanan 	 * or there is more work to be done, reset the service timer to
1076940b61afSAnirudh Venkataramanan 	 * schedule the service task now.
1077940b61afSAnirudh Venkataramanan 	 */
1078940b61afSAnirudh Venkataramanan 	if (time_after(jiffies, (start_time + pf->serv_tmr_period)) ||
1079b3969fd7SSudheer Mogilappagari 	    test_bit(__ICE_MDD_EVENT_PENDING, pf->state) ||
108075d2b253SAnirudh Venkataramanan 	    test_bit(__ICE_MAILBOXQ_EVENT_PENDING, pf->state) ||
1081940b61afSAnirudh Venkataramanan 	    test_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state))
1082940b61afSAnirudh Venkataramanan 		mod_timer(&pf->serv_tmr, jiffies);
1083940b61afSAnirudh Venkataramanan }
1084940b61afSAnirudh Venkataramanan 
1085837f08fdSAnirudh Venkataramanan /**
1086f31e4b6fSAnirudh Venkataramanan  * ice_set_ctrlq_len - helper function to set controlq length
1087f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hw instance
1088f31e4b6fSAnirudh Venkataramanan  */
1089f31e4b6fSAnirudh Venkataramanan static void ice_set_ctrlq_len(struct ice_hw *hw)
1090f31e4b6fSAnirudh Venkataramanan {
1091f31e4b6fSAnirudh Venkataramanan 	hw->adminq.num_rq_entries = ICE_AQ_LEN;
1092f31e4b6fSAnirudh Venkataramanan 	hw->adminq.num_sq_entries = ICE_AQ_LEN;
1093f31e4b6fSAnirudh Venkataramanan 	hw->adminq.rq_buf_size = ICE_AQ_MAX_BUF_LEN;
1094f31e4b6fSAnirudh Venkataramanan 	hw->adminq.sq_buf_size = ICE_AQ_MAX_BUF_LEN;
109575d2b253SAnirudh Venkataramanan 	hw->mailboxq.num_rq_entries = ICE_MBXQ_LEN;
109675d2b253SAnirudh Venkataramanan 	hw->mailboxq.num_sq_entries = ICE_MBXQ_LEN;
109775d2b253SAnirudh Venkataramanan 	hw->mailboxq.rq_buf_size = ICE_MBXQ_MAX_BUF_LEN;
109875d2b253SAnirudh Venkataramanan 	hw->mailboxq.sq_buf_size = ICE_MBXQ_MAX_BUF_LEN;
1099f31e4b6fSAnirudh Venkataramanan }
1100f31e4b6fSAnirudh Venkataramanan 
1101f31e4b6fSAnirudh Venkataramanan /**
1102cdedef59SAnirudh Venkataramanan  * ice_irq_affinity_notify - Callback for affinity changes
1103cdedef59SAnirudh Venkataramanan  * @notify: context as to what irq was changed
1104cdedef59SAnirudh Venkataramanan  * @mask: the new affinity mask
1105cdedef59SAnirudh Venkataramanan  *
1106cdedef59SAnirudh Venkataramanan  * This is a callback function used by the irq_set_affinity_notifier function
1107cdedef59SAnirudh Venkataramanan  * so that we may register to receive changes to the irq affinity masks.
1108cdedef59SAnirudh Venkataramanan  */
1109cdedef59SAnirudh Venkataramanan static void ice_irq_affinity_notify(struct irq_affinity_notify *notify,
1110cdedef59SAnirudh Venkataramanan 				    const cpumask_t *mask)
1111cdedef59SAnirudh Venkataramanan {
1112cdedef59SAnirudh Venkataramanan 	struct ice_q_vector *q_vector =
1113cdedef59SAnirudh Venkataramanan 		container_of(notify, struct ice_q_vector, affinity_notify);
1114cdedef59SAnirudh Venkataramanan 
1115cdedef59SAnirudh Venkataramanan 	cpumask_copy(&q_vector->affinity_mask, mask);
1116cdedef59SAnirudh Venkataramanan }
1117cdedef59SAnirudh Venkataramanan 
1118cdedef59SAnirudh Venkataramanan /**
1119cdedef59SAnirudh Venkataramanan  * ice_irq_affinity_release - Callback for affinity notifier release
1120cdedef59SAnirudh Venkataramanan  * @ref: internal core kernel usage
1121cdedef59SAnirudh Venkataramanan  *
1122cdedef59SAnirudh Venkataramanan  * This is a callback function used by the irq_set_affinity_notifier function
1123cdedef59SAnirudh Venkataramanan  * to inform the current notification subscriber that they will no longer
1124cdedef59SAnirudh Venkataramanan  * receive notifications.
1125cdedef59SAnirudh Venkataramanan  */
1126cdedef59SAnirudh Venkataramanan static void ice_irq_affinity_release(struct kref __always_unused *ref) {}
1127cdedef59SAnirudh Venkataramanan 
1128cdedef59SAnirudh Venkataramanan /**
1129cdedef59SAnirudh Venkataramanan  * ice_vsi_ena_irq - Enable IRQ for the given VSI
1130cdedef59SAnirudh Venkataramanan  * @vsi: the VSI being configured
1131cdedef59SAnirudh Venkataramanan  */
1132cdedef59SAnirudh Venkataramanan static int ice_vsi_ena_irq(struct ice_vsi *vsi)
1133cdedef59SAnirudh Venkataramanan {
1134cdedef59SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
1135cdedef59SAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
1136cdedef59SAnirudh Venkataramanan 
1137cdedef59SAnirudh Venkataramanan 	if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) {
1138cdedef59SAnirudh Venkataramanan 		int i;
1139cdedef59SAnirudh Venkataramanan 
1140cdedef59SAnirudh Venkataramanan 		for (i = 0; i < vsi->num_q_vectors; i++)
1141cdedef59SAnirudh Venkataramanan 			ice_irq_dynamic_ena(hw, vsi, vsi->q_vectors[i]);
1142cdedef59SAnirudh Venkataramanan 	}
1143cdedef59SAnirudh Venkataramanan 
1144cdedef59SAnirudh Venkataramanan 	ice_flush(hw);
1145cdedef59SAnirudh Venkataramanan 	return 0;
1146cdedef59SAnirudh Venkataramanan }
1147cdedef59SAnirudh Venkataramanan 
1148cdedef59SAnirudh Venkataramanan /**
1149cdedef59SAnirudh Venkataramanan  * ice_vsi_req_irq_msix - get MSI-X vectors from the OS for the VSI
1150cdedef59SAnirudh Venkataramanan  * @vsi: the VSI being configured
1151cdedef59SAnirudh Venkataramanan  * @basename: name for the vector
1152cdedef59SAnirudh Venkataramanan  */
1153cdedef59SAnirudh Venkataramanan static int ice_vsi_req_irq_msix(struct ice_vsi *vsi, char *basename)
1154cdedef59SAnirudh Venkataramanan {
1155cdedef59SAnirudh Venkataramanan 	int q_vectors = vsi->num_q_vectors;
1156cdedef59SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
1157eb0208ecSPreethi Banala 	int base = vsi->sw_base_vector;
1158cdedef59SAnirudh Venkataramanan 	int rx_int_idx = 0;
1159cdedef59SAnirudh Venkataramanan 	int tx_int_idx = 0;
1160cdedef59SAnirudh Venkataramanan 	int vector, err;
1161cdedef59SAnirudh Venkataramanan 	int irq_num;
1162cdedef59SAnirudh Venkataramanan 
1163cdedef59SAnirudh Venkataramanan 	for (vector = 0; vector < q_vectors; vector++) {
1164cdedef59SAnirudh Venkataramanan 		struct ice_q_vector *q_vector = vsi->q_vectors[vector];
1165cdedef59SAnirudh Venkataramanan 
1166cdedef59SAnirudh Venkataramanan 		irq_num = pf->msix_entries[base + vector].vector;
1167cdedef59SAnirudh Venkataramanan 
1168cdedef59SAnirudh Venkataramanan 		if (q_vector->tx.ring && q_vector->rx.ring) {
1169cdedef59SAnirudh Venkataramanan 			snprintf(q_vector->name, sizeof(q_vector->name) - 1,
1170cdedef59SAnirudh Venkataramanan 				 "%s-%s-%d", basename, "TxRx", rx_int_idx++);
1171cdedef59SAnirudh Venkataramanan 			tx_int_idx++;
1172cdedef59SAnirudh Venkataramanan 		} else if (q_vector->rx.ring) {
1173cdedef59SAnirudh Venkataramanan 			snprintf(q_vector->name, sizeof(q_vector->name) - 1,
1174cdedef59SAnirudh Venkataramanan 				 "%s-%s-%d", basename, "rx", rx_int_idx++);
1175cdedef59SAnirudh Venkataramanan 		} else if (q_vector->tx.ring) {
1176cdedef59SAnirudh Venkataramanan 			snprintf(q_vector->name, sizeof(q_vector->name) - 1,
1177cdedef59SAnirudh Venkataramanan 				 "%s-%s-%d", basename, "tx", tx_int_idx++);
1178cdedef59SAnirudh Venkataramanan 		} else {
1179cdedef59SAnirudh Venkataramanan 			/* skip this unused q_vector */
1180cdedef59SAnirudh Venkataramanan 			continue;
1181cdedef59SAnirudh Venkataramanan 		}
1182cdedef59SAnirudh Venkataramanan 		err = devm_request_irq(&pf->pdev->dev,
1183cdedef59SAnirudh Venkataramanan 				       pf->msix_entries[base + vector].vector,
1184cdedef59SAnirudh Venkataramanan 				       vsi->irq_handler, 0, q_vector->name,
1185cdedef59SAnirudh Venkataramanan 				       q_vector);
1186cdedef59SAnirudh Venkataramanan 		if (err) {
1187cdedef59SAnirudh Venkataramanan 			netdev_err(vsi->netdev,
1188cdedef59SAnirudh Venkataramanan 				   "MSIX request_irq failed, error: %d\n", err);
1189cdedef59SAnirudh Venkataramanan 			goto free_q_irqs;
1190cdedef59SAnirudh Venkataramanan 		}
1191cdedef59SAnirudh Venkataramanan 
1192cdedef59SAnirudh Venkataramanan 		/* register for affinity change notifications */
1193cdedef59SAnirudh Venkataramanan 		q_vector->affinity_notify.notify = ice_irq_affinity_notify;
1194cdedef59SAnirudh Venkataramanan 		q_vector->affinity_notify.release = ice_irq_affinity_release;
1195cdedef59SAnirudh Venkataramanan 		irq_set_affinity_notifier(irq_num, &q_vector->affinity_notify);
1196cdedef59SAnirudh Venkataramanan 
1197cdedef59SAnirudh Venkataramanan 		/* assign the mask for this irq */
1198cdedef59SAnirudh Venkataramanan 		irq_set_affinity_hint(irq_num, &q_vector->affinity_mask);
1199cdedef59SAnirudh Venkataramanan 	}
1200cdedef59SAnirudh Venkataramanan 
1201cdedef59SAnirudh Venkataramanan 	vsi->irqs_ready = true;
1202cdedef59SAnirudh Venkataramanan 	return 0;
1203cdedef59SAnirudh Venkataramanan 
1204cdedef59SAnirudh Venkataramanan free_q_irqs:
1205cdedef59SAnirudh Venkataramanan 	while (vector) {
1206cdedef59SAnirudh Venkataramanan 		vector--;
1207cdedef59SAnirudh Venkataramanan 		irq_num = pf->msix_entries[base + vector].vector,
1208cdedef59SAnirudh Venkataramanan 		irq_set_affinity_notifier(irq_num, NULL);
1209cdedef59SAnirudh Venkataramanan 		irq_set_affinity_hint(irq_num, NULL);
1210cdedef59SAnirudh Venkataramanan 		devm_free_irq(&pf->pdev->dev, irq_num, &vsi->q_vectors[vector]);
1211cdedef59SAnirudh Venkataramanan 	}
1212cdedef59SAnirudh Venkataramanan 	return err;
1213cdedef59SAnirudh Venkataramanan }
1214cdedef59SAnirudh Venkataramanan 
1215cdedef59SAnirudh Venkataramanan /**
1216940b61afSAnirudh Venkataramanan  * ice_ena_misc_vector - enable the non-queue interrupts
1217940b61afSAnirudh Venkataramanan  * @pf: board private structure
1218940b61afSAnirudh Venkataramanan  */
1219940b61afSAnirudh Venkataramanan static void ice_ena_misc_vector(struct ice_pf *pf)
1220940b61afSAnirudh Venkataramanan {
1221940b61afSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
1222940b61afSAnirudh Venkataramanan 	u32 val;
1223940b61afSAnirudh Venkataramanan 
1224940b61afSAnirudh Venkataramanan 	/* clear things first */
1225940b61afSAnirudh Venkataramanan 	wr32(hw, PFINT_OICR_ENA, 0);	/* disable all */
1226940b61afSAnirudh Venkataramanan 	rd32(hw, PFINT_OICR);		/* read to clear */
1227940b61afSAnirudh Venkataramanan 
12283bcd7fa3SBruce Allan 	val = (PFINT_OICR_ECC_ERR_M |
1229940b61afSAnirudh Venkataramanan 	       PFINT_OICR_MAL_DETECT_M |
1230940b61afSAnirudh Venkataramanan 	       PFINT_OICR_GRST_M |
1231940b61afSAnirudh Venkataramanan 	       PFINT_OICR_PCI_EXCEPTION_M |
12323bcd7fa3SBruce Allan 	       PFINT_OICR_HMC_ERR_M |
12333bcd7fa3SBruce Allan 	       PFINT_OICR_PE_CRITERR_M);
1234940b61afSAnirudh Venkataramanan 
1235940b61afSAnirudh Venkataramanan 	wr32(hw, PFINT_OICR_ENA, val);
1236940b61afSAnirudh Venkataramanan 
1237940b61afSAnirudh Venkataramanan 	/* SW_ITR_IDX = 0, but don't change INTENA */
1238eb0208ecSPreethi Banala 	wr32(hw, GLINT_DYN_CTL(pf->hw_oicr_idx),
1239940b61afSAnirudh Venkataramanan 	     GLINT_DYN_CTL_SW_ITR_INDX_M | GLINT_DYN_CTL_INTENA_MSK_M);
1240940b61afSAnirudh Venkataramanan }
1241940b61afSAnirudh Venkataramanan 
1242940b61afSAnirudh Venkataramanan /**
1243940b61afSAnirudh Venkataramanan  * ice_misc_intr - misc interrupt handler
1244940b61afSAnirudh Venkataramanan  * @irq: interrupt number
1245940b61afSAnirudh Venkataramanan  * @data: pointer to a q_vector
1246940b61afSAnirudh Venkataramanan  */
1247940b61afSAnirudh Venkataramanan static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
1248940b61afSAnirudh Venkataramanan {
1249940b61afSAnirudh Venkataramanan 	struct ice_pf *pf = (struct ice_pf *)data;
1250940b61afSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
1251940b61afSAnirudh Venkataramanan 	irqreturn_t ret = IRQ_NONE;
1252940b61afSAnirudh Venkataramanan 	u32 oicr, ena_mask;
1253940b61afSAnirudh Venkataramanan 
1254940b61afSAnirudh Venkataramanan 	set_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state);
125575d2b253SAnirudh Venkataramanan 	set_bit(__ICE_MAILBOXQ_EVENT_PENDING, pf->state);
1256940b61afSAnirudh Venkataramanan 
1257940b61afSAnirudh Venkataramanan 	oicr = rd32(hw, PFINT_OICR);
1258940b61afSAnirudh Venkataramanan 	ena_mask = rd32(hw, PFINT_OICR_ENA);
1259940b61afSAnirudh Venkataramanan 
1260b3969fd7SSudheer Mogilappagari 	if (oicr & PFINT_OICR_MAL_DETECT_M) {
1261b3969fd7SSudheer Mogilappagari 		ena_mask &= ~PFINT_OICR_MAL_DETECT_M;
1262b3969fd7SSudheer Mogilappagari 		set_bit(__ICE_MDD_EVENT_PENDING, pf->state);
1263b3969fd7SSudheer Mogilappagari 	}
1264b3969fd7SSudheer Mogilappagari 
12650b28b702SAnirudh Venkataramanan 	if (oicr & PFINT_OICR_GRST_M) {
12660b28b702SAnirudh Venkataramanan 		u32 reset;
1267b3969fd7SSudheer Mogilappagari 
12680b28b702SAnirudh Venkataramanan 		/* we have a reset warning */
12690b28b702SAnirudh Venkataramanan 		ena_mask &= ~PFINT_OICR_GRST_M;
12700b28b702SAnirudh Venkataramanan 		reset = (rd32(hw, GLGEN_RSTAT) & GLGEN_RSTAT_RESET_TYPE_M) >>
12710b28b702SAnirudh Venkataramanan 			GLGEN_RSTAT_RESET_TYPE_S;
12720b28b702SAnirudh Venkataramanan 
12730b28b702SAnirudh Venkataramanan 		if (reset == ICE_RESET_CORER)
12740b28b702SAnirudh Venkataramanan 			pf->corer_count++;
12750b28b702SAnirudh Venkataramanan 		else if (reset == ICE_RESET_GLOBR)
12760b28b702SAnirudh Venkataramanan 			pf->globr_count++;
1277ca4929b6SBrett Creeley 		else if (reset == ICE_RESET_EMPR)
12780b28b702SAnirudh Venkataramanan 			pf->empr_count++;
1279ca4929b6SBrett Creeley 		else
1280ca4929b6SBrett Creeley 			dev_dbg(&pf->pdev->dev, "Invalid reset type %d\n",
1281ca4929b6SBrett Creeley 				reset);
12820b28b702SAnirudh Venkataramanan 
12830b28b702SAnirudh Venkataramanan 		/* If a reset cycle isn't already in progress, we set a bit in
12840b28b702SAnirudh Venkataramanan 		 * pf->state so that the service task can start a reset/rebuild.
12850b28b702SAnirudh Venkataramanan 		 * We also make note of which reset happened so that peer
12860b28b702SAnirudh Venkataramanan 		 * devices/drivers can be informed.
12870b28b702SAnirudh Venkataramanan 		 */
12885df7e45dSDave Ertman 		if (!test_and_set_bit(__ICE_RESET_OICR_RECV, pf->state)) {
12890b28b702SAnirudh Venkataramanan 			if (reset == ICE_RESET_CORER)
12900b28b702SAnirudh Venkataramanan 				set_bit(__ICE_CORER_RECV, pf->state);
12910b28b702SAnirudh Venkataramanan 			else if (reset == ICE_RESET_GLOBR)
12920b28b702SAnirudh Venkataramanan 				set_bit(__ICE_GLOBR_RECV, pf->state);
12930b28b702SAnirudh Venkataramanan 			else
12940b28b702SAnirudh Venkataramanan 				set_bit(__ICE_EMPR_RECV, pf->state);
12950b28b702SAnirudh Venkataramanan 
1296fd2a9817SAnirudh Venkataramanan 			/* There are couple of different bits at play here.
1297fd2a9817SAnirudh Venkataramanan 			 * hw->reset_ongoing indicates whether the hardware is
1298fd2a9817SAnirudh Venkataramanan 			 * in reset. This is set to true when a reset interrupt
1299fd2a9817SAnirudh Venkataramanan 			 * is received and set back to false after the driver
1300fd2a9817SAnirudh Venkataramanan 			 * has determined that the hardware is out of reset.
1301fd2a9817SAnirudh Venkataramanan 			 *
13025df7e45dSDave Ertman 			 * __ICE_RESET_OICR_RECV in pf->state indicates
1303fd2a9817SAnirudh Venkataramanan 			 * that a post reset rebuild is required before the
1304fd2a9817SAnirudh Venkataramanan 			 * driver is operational again. This is set above.
1305fd2a9817SAnirudh Venkataramanan 			 *
1306fd2a9817SAnirudh Venkataramanan 			 * As this is the start of the reset/rebuild cycle, set
1307fd2a9817SAnirudh Venkataramanan 			 * both to indicate that.
1308fd2a9817SAnirudh Venkataramanan 			 */
1309fd2a9817SAnirudh Venkataramanan 			hw->reset_ongoing = true;
13100b28b702SAnirudh Venkataramanan 		}
13110b28b702SAnirudh Venkataramanan 	}
13120b28b702SAnirudh Venkataramanan 
1313940b61afSAnirudh Venkataramanan 	if (oicr & PFINT_OICR_HMC_ERR_M) {
1314940b61afSAnirudh Venkataramanan 		ena_mask &= ~PFINT_OICR_HMC_ERR_M;
1315940b61afSAnirudh Venkataramanan 		dev_dbg(&pf->pdev->dev,
1316940b61afSAnirudh Venkataramanan 			"HMC Error interrupt - info 0x%x, data 0x%x\n",
1317940b61afSAnirudh Venkataramanan 			rd32(hw, PFHMC_ERRORINFO),
1318940b61afSAnirudh Venkataramanan 			rd32(hw, PFHMC_ERRORDATA));
1319940b61afSAnirudh Venkataramanan 	}
1320940b61afSAnirudh Venkataramanan 
1321940b61afSAnirudh Venkataramanan 	/* Report and mask off any remaining unexpected interrupts */
1322940b61afSAnirudh Venkataramanan 	oicr &= ena_mask;
1323940b61afSAnirudh Venkataramanan 	if (oicr) {
1324940b61afSAnirudh Venkataramanan 		dev_dbg(&pf->pdev->dev, "unhandled interrupt oicr=0x%08x\n",
1325940b61afSAnirudh Venkataramanan 			oicr);
1326940b61afSAnirudh Venkataramanan 		/* If a critical error is pending there is no choice but to
1327940b61afSAnirudh Venkataramanan 		 * reset the device.
1328940b61afSAnirudh Venkataramanan 		 */
1329940b61afSAnirudh Venkataramanan 		if (oicr & (PFINT_OICR_PE_CRITERR_M |
1330940b61afSAnirudh Venkataramanan 			    PFINT_OICR_PCI_EXCEPTION_M |
13310b28b702SAnirudh Venkataramanan 			    PFINT_OICR_ECC_ERR_M)) {
1332940b61afSAnirudh Venkataramanan 			set_bit(__ICE_PFR_REQ, pf->state);
13330b28b702SAnirudh Venkataramanan 			ice_service_task_schedule(pf);
13340b28b702SAnirudh Venkataramanan 		}
1335940b61afSAnirudh Venkataramanan 		ena_mask &= ~oicr;
1336940b61afSAnirudh Venkataramanan 	}
1337940b61afSAnirudh Venkataramanan 	ret = IRQ_HANDLED;
1338940b61afSAnirudh Venkataramanan 
1339940b61afSAnirudh Venkataramanan 	/* re-enable interrupt causes that are not handled during this pass */
1340940b61afSAnirudh Venkataramanan 	wr32(hw, PFINT_OICR_ENA, ena_mask);
1341940b61afSAnirudh Venkataramanan 	if (!test_bit(__ICE_DOWN, pf->state)) {
1342940b61afSAnirudh Venkataramanan 		ice_service_task_schedule(pf);
1343cdedef59SAnirudh Venkataramanan 		ice_irq_dynamic_ena(hw, NULL, NULL);
1344940b61afSAnirudh Venkataramanan 	}
1345940b61afSAnirudh Venkataramanan 
1346940b61afSAnirudh Venkataramanan 	return ret;
1347940b61afSAnirudh Venkataramanan }
1348940b61afSAnirudh Venkataramanan 
1349940b61afSAnirudh Venkataramanan /**
1350940b61afSAnirudh Venkataramanan  * ice_free_irq_msix_misc - Unroll misc vector setup
1351940b61afSAnirudh Venkataramanan  * @pf: board private structure
1352940b61afSAnirudh Venkataramanan  */
1353940b61afSAnirudh Venkataramanan static void ice_free_irq_msix_misc(struct ice_pf *pf)
1354940b61afSAnirudh Venkataramanan {
1355940b61afSAnirudh Venkataramanan 	/* disable OICR interrupt */
1356940b61afSAnirudh Venkataramanan 	wr32(&pf->hw, PFINT_OICR_ENA, 0);
1357940b61afSAnirudh Venkataramanan 	ice_flush(&pf->hw);
1358940b61afSAnirudh Venkataramanan 
1359940b61afSAnirudh Venkataramanan 	if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags) && pf->msix_entries) {
1360eb0208ecSPreethi Banala 		synchronize_irq(pf->msix_entries[pf->sw_oicr_idx].vector);
1361940b61afSAnirudh Venkataramanan 		devm_free_irq(&pf->pdev->dev,
1362eb0208ecSPreethi Banala 			      pf->msix_entries[pf->sw_oicr_idx].vector, pf);
1363940b61afSAnirudh Venkataramanan 	}
1364940b61afSAnirudh Venkataramanan 
1365eb0208ecSPreethi Banala 	pf->num_avail_sw_msix += 1;
1366eb0208ecSPreethi Banala 	ice_free_res(pf->sw_irq_tracker, pf->sw_oicr_idx, ICE_RES_MISC_VEC_ID);
1367eb0208ecSPreethi Banala 	pf->num_avail_hw_msix += 1;
1368eb0208ecSPreethi Banala 	ice_free_res(pf->hw_irq_tracker, pf->hw_oicr_idx, ICE_RES_MISC_VEC_ID);
1369940b61afSAnirudh Venkataramanan }
1370940b61afSAnirudh Venkataramanan 
1371940b61afSAnirudh Venkataramanan /**
1372940b61afSAnirudh Venkataramanan  * ice_req_irq_msix_misc - Setup the misc vector to handle non queue events
1373940b61afSAnirudh Venkataramanan  * @pf: board private structure
1374940b61afSAnirudh Venkataramanan  *
1375940b61afSAnirudh Venkataramanan  * This sets up the handler for MSIX 0, which is used to manage the
1376940b61afSAnirudh Venkataramanan  * non-queue interrupts, e.g. AdminQ and errors.  This is not used
1377940b61afSAnirudh Venkataramanan  * when in MSI or Legacy interrupt mode.
1378940b61afSAnirudh Venkataramanan  */
1379940b61afSAnirudh Venkataramanan static int ice_req_irq_msix_misc(struct ice_pf *pf)
1380940b61afSAnirudh Venkataramanan {
1381940b61afSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
1382940b61afSAnirudh Venkataramanan 	int oicr_idx, err = 0;
1383940b61afSAnirudh Venkataramanan 	u8 itr_gran;
1384940b61afSAnirudh Venkataramanan 	u32 val;
1385940b61afSAnirudh Venkataramanan 
1386940b61afSAnirudh Venkataramanan 	if (!pf->int_name[0])
1387940b61afSAnirudh Venkataramanan 		snprintf(pf->int_name, sizeof(pf->int_name) - 1, "%s-%s:misc",
1388940b61afSAnirudh Venkataramanan 			 dev_driver_string(&pf->pdev->dev),
1389940b61afSAnirudh Venkataramanan 			 dev_name(&pf->pdev->dev));
1390940b61afSAnirudh Venkataramanan 
13910b28b702SAnirudh Venkataramanan 	/* Do not request IRQ but do enable OICR interrupt since settings are
13920b28b702SAnirudh Venkataramanan 	 * lost during reset. Note that this function is called only during
13930b28b702SAnirudh Venkataramanan 	 * rebuild path and not while reset is in progress.
13940b28b702SAnirudh Venkataramanan 	 */
13955df7e45dSDave Ertman 	if (ice_is_reset_in_progress(pf->state))
13960b28b702SAnirudh Venkataramanan 		goto skip_req_irq;
13970b28b702SAnirudh Venkataramanan 
1398eb0208ecSPreethi Banala 	/* reserve one vector in sw_irq_tracker for misc interrupts */
1399eb0208ecSPreethi Banala 	oicr_idx = ice_get_res(pf, pf->sw_irq_tracker, 1, ICE_RES_MISC_VEC_ID);
1400940b61afSAnirudh Venkataramanan 	if (oicr_idx < 0)
1401940b61afSAnirudh Venkataramanan 		return oicr_idx;
1402940b61afSAnirudh Venkataramanan 
1403eb0208ecSPreethi Banala 	pf->num_avail_sw_msix -= 1;
1404eb0208ecSPreethi Banala 	pf->sw_oicr_idx = oicr_idx;
1405eb0208ecSPreethi Banala 
1406eb0208ecSPreethi Banala 	/* reserve one vector in hw_irq_tracker for misc interrupts */
1407eb0208ecSPreethi Banala 	oicr_idx = ice_get_res(pf, pf->hw_irq_tracker, 1, ICE_RES_MISC_VEC_ID);
1408eb0208ecSPreethi Banala 	if (oicr_idx < 0) {
1409eb0208ecSPreethi Banala 		ice_free_res(pf->sw_irq_tracker, 1, ICE_RES_MISC_VEC_ID);
1410eb0208ecSPreethi Banala 		pf->num_avail_sw_msix += 1;
1411eb0208ecSPreethi Banala 		return oicr_idx;
1412eb0208ecSPreethi Banala 	}
1413eb0208ecSPreethi Banala 	pf->num_avail_hw_msix -= 1;
1414eb0208ecSPreethi Banala 	pf->hw_oicr_idx = oicr_idx;
1415940b61afSAnirudh Venkataramanan 
1416940b61afSAnirudh Venkataramanan 	err = devm_request_irq(&pf->pdev->dev,
1417eb0208ecSPreethi Banala 			       pf->msix_entries[pf->sw_oicr_idx].vector,
1418940b61afSAnirudh Venkataramanan 			       ice_misc_intr, 0, pf->int_name, pf);
1419940b61afSAnirudh Venkataramanan 	if (err) {
1420940b61afSAnirudh Venkataramanan 		dev_err(&pf->pdev->dev,
1421940b61afSAnirudh Venkataramanan 			"devm_request_irq for %s failed: %d\n",
1422940b61afSAnirudh Venkataramanan 			pf->int_name, err);
1423eb0208ecSPreethi Banala 		ice_free_res(pf->sw_irq_tracker, 1, ICE_RES_MISC_VEC_ID);
1424eb0208ecSPreethi Banala 		pf->num_avail_sw_msix += 1;
1425eb0208ecSPreethi Banala 		ice_free_res(pf->hw_irq_tracker, 1, ICE_RES_MISC_VEC_ID);
1426eb0208ecSPreethi Banala 		pf->num_avail_hw_msix += 1;
1427940b61afSAnirudh Venkataramanan 		return err;
1428940b61afSAnirudh Venkataramanan 	}
1429940b61afSAnirudh Venkataramanan 
14300b28b702SAnirudh Venkataramanan skip_req_irq:
1431940b61afSAnirudh Venkataramanan 	ice_ena_misc_vector(pf);
1432940b61afSAnirudh Venkataramanan 
1433eb0208ecSPreethi Banala 	val = ((pf->hw_oicr_idx & PFINT_OICR_CTL_MSIX_INDX_M) |
14344381147dSAnirudh Venkataramanan 	       PFINT_OICR_CTL_CAUSE_ENA_M);
1435940b61afSAnirudh Venkataramanan 	wr32(hw, PFINT_OICR_CTL, val);
1436940b61afSAnirudh Venkataramanan 
1437940b61afSAnirudh Venkataramanan 	/* This enables Admin queue Interrupt causes */
1438eb0208ecSPreethi Banala 	val = ((pf->hw_oicr_idx & PFINT_FW_CTL_MSIX_INDX_M) |
14394381147dSAnirudh Venkataramanan 	       PFINT_FW_CTL_CAUSE_ENA_M);
1440940b61afSAnirudh Venkataramanan 	wr32(hw, PFINT_FW_CTL, val);
1441940b61afSAnirudh Venkataramanan 
144275d2b253SAnirudh Venkataramanan 	/* This enables Mailbox queue Interrupt causes */
144375d2b253SAnirudh Venkataramanan 	val = ((pf->hw_oicr_idx & PFINT_MBX_CTL_MSIX_INDX_M) |
144475d2b253SAnirudh Venkataramanan 	       PFINT_MBX_CTL_CAUSE_ENA_M);
144575d2b253SAnirudh Venkataramanan 	wr32(hw, PFINT_MBX_CTL, val);
144675d2b253SAnirudh Venkataramanan 
14479e4ab4c2SBrett Creeley 	itr_gran = hw->itr_gran;
1448940b61afSAnirudh Venkataramanan 
1449eb0208ecSPreethi Banala 	wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->hw_oicr_idx),
1450940b61afSAnirudh Venkataramanan 	     ITR_TO_REG(ICE_ITR_8K, itr_gran));
1451940b61afSAnirudh Venkataramanan 
1452940b61afSAnirudh Venkataramanan 	ice_flush(hw);
1453cdedef59SAnirudh Venkataramanan 	ice_irq_dynamic_ena(hw, NULL, NULL);
1454940b61afSAnirudh Venkataramanan 
1455940b61afSAnirudh Venkataramanan 	return 0;
1456940b61afSAnirudh Venkataramanan }
1457940b61afSAnirudh Venkataramanan 
1458940b61afSAnirudh Venkataramanan /**
1459df0f8479SAnirudh Venkataramanan  * ice_napi_del - Remove NAPI handler for the VSI
1460df0f8479SAnirudh Venkataramanan  * @vsi: VSI for which NAPI handler is to be removed
14613a858ba3SAnirudh Venkataramanan  */
1462df0f8479SAnirudh Venkataramanan static void ice_napi_del(struct ice_vsi *vsi)
14633a858ba3SAnirudh Venkataramanan {
14643a858ba3SAnirudh Venkataramanan 	int v_idx;
14653a858ba3SAnirudh Venkataramanan 
1466df0f8479SAnirudh Venkataramanan 	if (!vsi->netdev)
1467df0f8479SAnirudh Venkataramanan 		return;
1468df0f8479SAnirudh Venkataramanan 
14693a858ba3SAnirudh Venkataramanan 	for (v_idx = 0; v_idx < vsi->num_q_vectors; v_idx++)
1470df0f8479SAnirudh Venkataramanan 		netif_napi_del(&vsi->q_vectors[v_idx]->napi);
14713a858ba3SAnirudh Venkataramanan }
14723a858ba3SAnirudh Venkataramanan 
14733a858ba3SAnirudh Venkataramanan /**
1474df0f8479SAnirudh Venkataramanan  * ice_napi_add - register NAPI handler for the VSI
1475df0f8479SAnirudh Venkataramanan  * @vsi: VSI for which NAPI handler is to be registered
1476df0f8479SAnirudh Venkataramanan  *
1477df0f8479SAnirudh Venkataramanan  * This function is only called in the driver's load path. Registering the NAPI
1478df0f8479SAnirudh Venkataramanan  * handler is done in ice_vsi_alloc_q_vector() for all other cases (i.e. resume,
1479df0f8479SAnirudh Venkataramanan  * reset/rebuild, etc.)
1480df0f8479SAnirudh Venkataramanan  */
1481df0f8479SAnirudh Venkataramanan static void ice_napi_add(struct ice_vsi *vsi)
1482df0f8479SAnirudh Venkataramanan {
1483df0f8479SAnirudh Venkataramanan 	int v_idx;
1484df0f8479SAnirudh Venkataramanan 
1485df0f8479SAnirudh Venkataramanan 	if (!vsi->netdev)
1486df0f8479SAnirudh Venkataramanan 		return;
1487df0f8479SAnirudh Venkataramanan 
1488df0f8479SAnirudh Venkataramanan 	for (v_idx = 0; v_idx < vsi->num_q_vectors; v_idx++)
1489df0f8479SAnirudh Venkataramanan 		netif_napi_add(vsi->netdev, &vsi->q_vectors[v_idx]->napi,
1490df0f8479SAnirudh Venkataramanan 			       ice_napi_poll, NAPI_POLL_WEIGHT);
1491df0f8479SAnirudh Venkataramanan }
1492df0f8479SAnirudh Venkataramanan 
1493df0f8479SAnirudh Venkataramanan /**
1494df0f8479SAnirudh Venkataramanan  * ice_cfg_netdev - Allocate, configure and register a netdev
1495df0f8479SAnirudh Venkataramanan  * @vsi: the VSI associated with the new netdev
14963a858ba3SAnirudh Venkataramanan  *
14973a858ba3SAnirudh Venkataramanan  * Returns 0 on success, negative value on failure
14983a858ba3SAnirudh Venkataramanan  */
14993a858ba3SAnirudh Venkataramanan static int ice_cfg_netdev(struct ice_vsi *vsi)
15003a858ba3SAnirudh Venkataramanan {
1501d76a60baSAnirudh Venkataramanan 	netdev_features_t csumo_features;
1502d76a60baSAnirudh Venkataramanan 	netdev_features_t vlano_features;
1503d76a60baSAnirudh Venkataramanan 	netdev_features_t dflt_features;
1504d76a60baSAnirudh Venkataramanan 	netdev_features_t tso_features;
15053a858ba3SAnirudh Venkataramanan 	struct ice_netdev_priv *np;
15063a858ba3SAnirudh Venkataramanan 	struct net_device *netdev;
15073a858ba3SAnirudh Venkataramanan 	u8 mac_addr[ETH_ALEN];
1508df0f8479SAnirudh Venkataramanan 	int err;
15093a858ba3SAnirudh Venkataramanan 
15103a858ba3SAnirudh Venkataramanan 	netdev = alloc_etherdev_mqs(sizeof(struct ice_netdev_priv),
15113a858ba3SAnirudh Venkataramanan 				    vsi->alloc_txq, vsi->alloc_rxq);
15123a858ba3SAnirudh Venkataramanan 	if (!netdev)
15133a858ba3SAnirudh Venkataramanan 		return -ENOMEM;
15143a858ba3SAnirudh Venkataramanan 
15153a858ba3SAnirudh Venkataramanan 	vsi->netdev = netdev;
15163a858ba3SAnirudh Venkataramanan 	np = netdev_priv(netdev);
15173a858ba3SAnirudh Venkataramanan 	np->vsi = vsi;
15183a858ba3SAnirudh Venkataramanan 
1519d76a60baSAnirudh Venkataramanan 	dflt_features = NETIF_F_SG	|
15203a858ba3SAnirudh Venkataramanan 			NETIF_F_HIGHDMA	|
15213a858ba3SAnirudh Venkataramanan 			NETIF_F_RXHASH;
15223a858ba3SAnirudh Venkataramanan 
1523d76a60baSAnirudh Venkataramanan 	csumo_features = NETIF_F_RXCSUM	  |
1524d76a60baSAnirudh Venkataramanan 			 NETIF_F_IP_CSUM  |
1525d76a60baSAnirudh Venkataramanan 			 NETIF_F_IPV6_CSUM;
1526d76a60baSAnirudh Venkataramanan 
1527d76a60baSAnirudh Venkataramanan 	vlano_features = NETIF_F_HW_VLAN_CTAG_FILTER |
1528d76a60baSAnirudh Venkataramanan 			 NETIF_F_HW_VLAN_CTAG_TX     |
1529d76a60baSAnirudh Venkataramanan 			 NETIF_F_HW_VLAN_CTAG_RX;
1530d76a60baSAnirudh Venkataramanan 
1531d76a60baSAnirudh Venkataramanan 	tso_features = NETIF_F_TSO;
1532d76a60baSAnirudh Venkataramanan 
1533d76a60baSAnirudh Venkataramanan 	/* set features that user can change */
1534d76a60baSAnirudh Venkataramanan 	netdev->hw_features = dflt_features | csumo_features |
1535d76a60baSAnirudh Venkataramanan 			      vlano_features | tso_features;
1536d76a60baSAnirudh Venkataramanan 
15373a858ba3SAnirudh Venkataramanan 	/* enable features */
15383a858ba3SAnirudh Venkataramanan 	netdev->features |= netdev->hw_features;
1539d76a60baSAnirudh Venkataramanan 	/* encap and VLAN devices inherit default, csumo and tso features */
1540d76a60baSAnirudh Venkataramanan 	netdev->hw_enc_features |= dflt_features | csumo_features |
1541d76a60baSAnirudh Venkataramanan 				   tso_features;
1542d76a60baSAnirudh Venkataramanan 	netdev->vlan_features |= dflt_features | csumo_features |
1543d76a60baSAnirudh Venkataramanan 				 tso_features;
15443a858ba3SAnirudh Venkataramanan 
15453a858ba3SAnirudh Venkataramanan 	if (vsi->type == ICE_VSI_PF) {
15463a858ba3SAnirudh Venkataramanan 		SET_NETDEV_DEV(netdev, &vsi->back->pdev->dev);
15473a858ba3SAnirudh Venkataramanan 		ether_addr_copy(mac_addr, vsi->port_info->mac.perm_addr);
15483a858ba3SAnirudh Venkataramanan 
15493a858ba3SAnirudh Venkataramanan 		ether_addr_copy(netdev->dev_addr, mac_addr);
15503a858ba3SAnirudh Venkataramanan 		ether_addr_copy(netdev->perm_addr, mac_addr);
15513a858ba3SAnirudh Venkataramanan 	}
15523a858ba3SAnirudh Venkataramanan 
15533a858ba3SAnirudh Venkataramanan 	netdev->priv_flags |= IFF_UNICAST_FLT;
15543a858ba3SAnirudh Venkataramanan 
1555cdedef59SAnirudh Venkataramanan 	/* assign netdev_ops */
1556cdedef59SAnirudh Venkataramanan 	netdev->netdev_ops = &ice_netdev_ops;
1557cdedef59SAnirudh Venkataramanan 
15583a858ba3SAnirudh Venkataramanan 	/* setup watchdog timeout value to be 5 second */
15593a858ba3SAnirudh Venkataramanan 	netdev->watchdog_timeo = 5 * HZ;
15603a858ba3SAnirudh Venkataramanan 
1561fcea6f3dSAnirudh Venkataramanan 	ice_set_ethtool_ops(netdev);
1562fcea6f3dSAnirudh Venkataramanan 
15633a858ba3SAnirudh Venkataramanan 	netdev->min_mtu = ETH_MIN_MTU;
15643a858ba3SAnirudh Venkataramanan 	netdev->max_mtu = ICE_MAX_MTU;
15653a858ba3SAnirudh Venkataramanan 
1566df0f8479SAnirudh Venkataramanan 	err = register_netdev(vsi->netdev);
15673a858ba3SAnirudh Venkataramanan 	if (err)
15683a858ba3SAnirudh Venkataramanan 		return err;
15693a858ba3SAnirudh Venkataramanan 
1570df0f8479SAnirudh Venkataramanan 	netif_carrier_off(vsi->netdev);
15713a858ba3SAnirudh Venkataramanan 
1572df0f8479SAnirudh Venkataramanan 	/* make sure transmit queues start off as stopped */
1573df0f8479SAnirudh Venkataramanan 	netif_tx_stop_all_queues(vsi->netdev);
15743a858ba3SAnirudh Venkataramanan 
15753a858ba3SAnirudh Venkataramanan 	return 0;
15763a858ba3SAnirudh Venkataramanan }
15773a858ba3SAnirudh Venkataramanan 
15783a858ba3SAnirudh Venkataramanan /**
1579d76a60baSAnirudh Venkataramanan  * ice_fill_rss_lut - Fill the RSS lookup table with default values
1580d76a60baSAnirudh Venkataramanan  * @lut: Lookup table
1581d76a60baSAnirudh Venkataramanan  * @rss_table_size: Lookup table size
1582d76a60baSAnirudh Venkataramanan  * @rss_size: Range of queue number for hashing
1583d76a60baSAnirudh Venkataramanan  */
1584d76a60baSAnirudh Venkataramanan void ice_fill_rss_lut(u8 *lut, u16 rss_table_size, u16 rss_size)
1585d76a60baSAnirudh Venkataramanan {
1586d76a60baSAnirudh Venkataramanan 	u16 i;
1587d76a60baSAnirudh Venkataramanan 
1588d76a60baSAnirudh Venkataramanan 	for (i = 0; i < rss_table_size; i++)
1589d76a60baSAnirudh Venkataramanan 		lut[i] = i % rss_size;
1590d76a60baSAnirudh Venkataramanan }
1591d76a60baSAnirudh Venkataramanan 
1592d76a60baSAnirudh Venkataramanan /**
15930f9d5027SAnirudh Venkataramanan  * ice_pf_vsi_setup - Set up a PF VSI
15940f9d5027SAnirudh Venkataramanan  * @pf: board private structure
15950f9d5027SAnirudh Venkataramanan  * @pi: pointer to the port_info instance
15960f9d5027SAnirudh Venkataramanan  *
15970f9d5027SAnirudh Venkataramanan  * Returns pointer to the successfully allocated VSI sw struct on success,
15980f9d5027SAnirudh Venkataramanan  * otherwise returns NULL on failure.
15990f9d5027SAnirudh Venkataramanan  */
16000f9d5027SAnirudh Venkataramanan static struct ice_vsi *
16010f9d5027SAnirudh Venkataramanan ice_pf_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi)
16020f9d5027SAnirudh Venkataramanan {
16030f9d5027SAnirudh Venkataramanan 	return ice_vsi_setup(pf, pi, ICE_VSI_PF, ICE_INVAL_VFID);
16040f9d5027SAnirudh Venkataramanan }
16050f9d5027SAnirudh Venkataramanan 
16060f9d5027SAnirudh Venkataramanan /**
1607d76a60baSAnirudh Venkataramanan  * ice_vlan_rx_add_vid - Add a vlan id filter to HW offload
1608d76a60baSAnirudh Venkataramanan  * @netdev: network interface to be adjusted
1609d76a60baSAnirudh Venkataramanan  * @proto: unused protocol
1610d76a60baSAnirudh Venkataramanan  * @vid: vlan id to be added
1611d76a60baSAnirudh Venkataramanan  *
1612d76a60baSAnirudh Venkataramanan  * net_device_ops implementation for adding vlan ids
1613d76a60baSAnirudh Venkataramanan  */
1614d76a60baSAnirudh Venkataramanan static int ice_vlan_rx_add_vid(struct net_device *netdev,
1615d76a60baSAnirudh Venkataramanan 			       __always_unused __be16 proto, u16 vid)
1616d76a60baSAnirudh Venkataramanan {
1617d76a60baSAnirudh Venkataramanan 	struct ice_netdev_priv *np = netdev_priv(netdev);
1618d76a60baSAnirudh Venkataramanan 	struct ice_vsi *vsi = np->vsi;
16194f74dcc1SBrett Creeley 	int ret;
1620d76a60baSAnirudh Venkataramanan 
1621d76a60baSAnirudh Venkataramanan 	if (vid >= VLAN_N_VID) {
1622d76a60baSAnirudh Venkataramanan 		netdev_err(netdev, "VLAN id requested %d is out of range %d\n",
1623d76a60baSAnirudh Venkataramanan 			   vid, VLAN_N_VID);
1624d76a60baSAnirudh Venkataramanan 		return -EINVAL;
1625d76a60baSAnirudh Venkataramanan 	}
1626d76a60baSAnirudh Venkataramanan 
1627d76a60baSAnirudh Venkataramanan 	if (vsi->info.pvid)
1628d76a60baSAnirudh Venkataramanan 		return -EINVAL;
1629d76a60baSAnirudh Venkataramanan 
16304f74dcc1SBrett Creeley 	/* Enable VLAN pruning when VLAN 0 is added */
16314f74dcc1SBrett Creeley 	if (unlikely(!vid)) {
16324f74dcc1SBrett Creeley 		ret = ice_cfg_vlan_pruning(vsi, true);
16334f74dcc1SBrett Creeley 		if (ret)
16344f74dcc1SBrett Creeley 			return ret;
16354f74dcc1SBrett Creeley 	}
16364f74dcc1SBrett Creeley 
1637d76a60baSAnirudh Venkataramanan 	/* Add all VLAN ids including 0 to the switch filter. VLAN id 0 is
1638d76a60baSAnirudh Venkataramanan 	 * needed to continue allowing all untagged packets since VLAN prune
1639d76a60baSAnirudh Venkataramanan 	 * list is applied to all packets by the switch
1640d76a60baSAnirudh Venkataramanan 	 */
1641d76a60baSAnirudh Venkataramanan 	ret = ice_vsi_add_vlan(vsi, vid);
1642d76a60baSAnirudh Venkataramanan 
1643d76a60baSAnirudh Venkataramanan 	if (!ret)
1644d76a60baSAnirudh Venkataramanan 		set_bit(vid, vsi->active_vlans);
1645d76a60baSAnirudh Venkataramanan 
1646d76a60baSAnirudh Venkataramanan 	return ret;
1647d76a60baSAnirudh Venkataramanan }
1648d76a60baSAnirudh Venkataramanan 
1649d76a60baSAnirudh Venkataramanan /**
1650d76a60baSAnirudh Venkataramanan  * ice_vlan_rx_kill_vid - Remove a vlan id filter from HW offload
1651d76a60baSAnirudh Venkataramanan  * @netdev: network interface to be adjusted
1652d76a60baSAnirudh Venkataramanan  * @proto: unused protocol
1653d76a60baSAnirudh Venkataramanan  * @vid: vlan id to be removed
1654d76a60baSAnirudh Venkataramanan  *
1655d76a60baSAnirudh Venkataramanan  * net_device_ops implementation for removing vlan ids
1656d76a60baSAnirudh Venkataramanan  */
1657d76a60baSAnirudh Venkataramanan static int ice_vlan_rx_kill_vid(struct net_device *netdev,
1658d76a60baSAnirudh Venkataramanan 				__always_unused __be16 proto, u16 vid)
1659d76a60baSAnirudh Venkataramanan {
1660d76a60baSAnirudh Venkataramanan 	struct ice_netdev_priv *np = netdev_priv(netdev);
1661d76a60baSAnirudh Venkataramanan 	struct ice_vsi *vsi = np->vsi;
16624f74dcc1SBrett Creeley 	int status;
1663d76a60baSAnirudh Venkataramanan 
1664d76a60baSAnirudh Venkataramanan 	if (vsi->info.pvid)
1665d76a60baSAnirudh Venkataramanan 		return -EINVAL;
1666d76a60baSAnirudh Venkataramanan 
16674f74dcc1SBrett Creeley 	/* Make sure ice_vsi_kill_vlan is successful before updating VLAN
16684f74dcc1SBrett Creeley 	 * information
1669d76a60baSAnirudh Venkataramanan 	 */
16704f74dcc1SBrett Creeley 	status = ice_vsi_kill_vlan(vsi, vid);
16714f74dcc1SBrett Creeley 	if (status)
16724f74dcc1SBrett Creeley 		return status;
1673d76a60baSAnirudh Venkataramanan 
1674d76a60baSAnirudh Venkataramanan 	clear_bit(vid, vsi->active_vlans);
1675d76a60baSAnirudh Venkataramanan 
16764f74dcc1SBrett Creeley 	/* Disable VLAN pruning when VLAN 0 is removed */
16774f74dcc1SBrett Creeley 	if (unlikely(!vid))
16784f74dcc1SBrett Creeley 		status = ice_cfg_vlan_pruning(vsi, false);
16794f74dcc1SBrett Creeley 
16804f74dcc1SBrett Creeley 	return status;
1681d76a60baSAnirudh Venkataramanan }
1682d76a60baSAnirudh Venkataramanan 
1683d76a60baSAnirudh Venkataramanan /**
16843a858ba3SAnirudh Venkataramanan  * ice_setup_pf_sw - Setup the HW switch on startup or after reset
16853a858ba3SAnirudh Venkataramanan  * @pf: board private structure
16863a858ba3SAnirudh Venkataramanan  *
16873a858ba3SAnirudh Venkataramanan  * Returns 0 on success, negative value on failure
16883a858ba3SAnirudh Venkataramanan  */
16893a858ba3SAnirudh Venkataramanan static int ice_setup_pf_sw(struct ice_pf *pf)
16903a858ba3SAnirudh Venkataramanan {
16919daf8208SAnirudh Venkataramanan 	LIST_HEAD(tmp_add_list);
16929daf8208SAnirudh Venkataramanan 	u8 broadcast[ETH_ALEN];
16933a858ba3SAnirudh Venkataramanan 	struct ice_vsi *vsi;
16943a858ba3SAnirudh Venkataramanan 	int status = 0;
16953a858ba3SAnirudh Venkataramanan 
16965df7e45dSDave Ertman 	if (ice_is_reset_in_progress(pf->state))
16970f9d5027SAnirudh Venkataramanan 		return -EBUSY;
16980f9d5027SAnirudh Venkataramanan 
16990f9d5027SAnirudh Venkataramanan 	vsi = ice_pf_vsi_setup(pf, pf->hw.port_info);
17003a858ba3SAnirudh Venkataramanan 	if (!vsi) {
17013a858ba3SAnirudh Venkataramanan 		status = -ENOMEM;
17020f9d5027SAnirudh Venkataramanan 		goto unroll_vsi_setup;
17030b28b702SAnirudh Venkataramanan 	}
17043a858ba3SAnirudh Venkataramanan 
1705df0f8479SAnirudh Venkataramanan 	status = ice_cfg_netdev(vsi);
1706df0f8479SAnirudh Venkataramanan 	if (status) {
1707df0f8479SAnirudh Venkataramanan 		status = -ENODEV;
1708df0f8479SAnirudh Venkataramanan 		goto unroll_vsi_setup;
1709df0f8479SAnirudh Venkataramanan 	}
1710df0f8479SAnirudh Venkataramanan 
1711df0f8479SAnirudh Venkataramanan 	/* registering the NAPI handler requires both the queues and
1712df0f8479SAnirudh Venkataramanan 	 * netdev to be created, which are done in ice_pf_vsi_setup()
1713df0f8479SAnirudh Venkataramanan 	 * and ice_cfg_netdev() respectively
1714df0f8479SAnirudh Venkataramanan 	 */
1715df0f8479SAnirudh Venkataramanan 	ice_napi_add(vsi);
1716df0f8479SAnirudh Venkataramanan 
17170f9d5027SAnirudh Venkataramanan 	/* To add a MAC filter, first add the MAC to a list and then
17180f9d5027SAnirudh Venkataramanan 	 * pass the list to ice_add_mac.
17199daf8208SAnirudh Venkataramanan 	 */
17200f9d5027SAnirudh Venkataramanan 
17210f9d5027SAnirudh Venkataramanan 	 /* Add a unicast MAC filter so the VSI can get its packets */
17229daf8208SAnirudh Venkataramanan 	status = ice_add_mac_to_list(vsi, &tmp_add_list,
17239daf8208SAnirudh Venkataramanan 				     vsi->port_info->mac.perm_addr);
17249daf8208SAnirudh Venkataramanan 	if (status)
1725df0f8479SAnirudh Venkataramanan 		goto unroll_napi_add;
17269daf8208SAnirudh Venkataramanan 
17279daf8208SAnirudh Venkataramanan 	/* VSI needs to receive broadcast traffic, so add the broadcast
17280f9d5027SAnirudh Venkataramanan 	 * MAC address to the list as well.
17299daf8208SAnirudh Venkataramanan 	 */
17309daf8208SAnirudh Venkataramanan 	eth_broadcast_addr(broadcast);
17319daf8208SAnirudh Venkataramanan 	status = ice_add_mac_to_list(vsi, &tmp_add_list, broadcast);
17329daf8208SAnirudh Venkataramanan 	if (status)
17330f9d5027SAnirudh Venkataramanan 		goto free_mac_list;
17349daf8208SAnirudh Venkataramanan 
17359daf8208SAnirudh Venkataramanan 	/* program MAC filters for entries in tmp_add_list */
17369daf8208SAnirudh Venkataramanan 	status = ice_add_mac(&pf->hw, &tmp_add_list);
17379daf8208SAnirudh Venkataramanan 	if (status) {
17389daf8208SAnirudh Venkataramanan 		dev_err(&pf->pdev->dev, "Could not add MAC filters\n");
17399daf8208SAnirudh Venkataramanan 		status = -ENOMEM;
17400f9d5027SAnirudh Venkataramanan 		goto free_mac_list;
17419daf8208SAnirudh Venkataramanan 	}
17429daf8208SAnirudh Venkataramanan 
17439daf8208SAnirudh Venkataramanan 	ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list);
17449daf8208SAnirudh Venkataramanan 	return status;
17459daf8208SAnirudh Venkataramanan 
17460f9d5027SAnirudh Venkataramanan free_mac_list:
17479daf8208SAnirudh Venkataramanan 	ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list);
17489daf8208SAnirudh Venkataramanan 
1749df0f8479SAnirudh Venkataramanan unroll_napi_add:
17503a858ba3SAnirudh Venkataramanan 	if (vsi) {
1751df0f8479SAnirudh Venkataramanan 		ice_napi_del(vsi);
17523a858ba3SAnirudh Venkataramanan 		if (vsi->netdev) {
1753df0f8479SAnirudh Venkataramanan 			if (vsi->netdev->reg_state == NETREG_REGISTERED)
1754df0f8479SAnirudh Venkataramanan 				unregister_netdev(vsi->netdev);
17553a858ba3SAnirudh Venkataramanan 			free_netdev(vsi->netdev);
17563a858ba3SAnirudh Venkataramanan 			vsi->netdev = NULL;
17573a858ba3SAnirudh Venkataramanan 		}
1758df0f8479SAnirudh Venkataramanan 	}
17599daf8208SAnirudh Venkataramanan 
1760df0f8479SAnirudh Venkataramanan unroll_vsi_setup:
1761df0f8479SAnirudh Venkataramanan 	if (vsi) {
1762df0f8479SAnirudh Venkataramanan 		ice_vsi_free_q_vectors(vsi);
17633a858ba3SAnirudh Venkataramanan 		ice_vsi_delete(vsi);
17643a858ba3SAnirudh Venkataramanan 		ice_vsi_put_qs(vsi);
17653a858ba3SAnirudh Venkataramanan 		pf->q_left_tx += vsi->alloc_txq;
17663a858ba3SAnirudh Venkataramanan 		pf->q_left_rx += vsi->alloc_rxq;
17673a858ba3SAnirudh Venkataramanan 		ice_vsi_clear(vsi);
17683a858ba3SAnirudh Venkataramanan 	}
17693a858ba3SAnirudh Venkataramanan 	return status;
17703a858ba3SAnirudh Venkataramanan }
17713a858ba3SAnirudh Venkataramanan 
17723a858ba3SAnirudh Venkataramanan /**
1773940b61afSAnirudh Venkataramanan  * ice_determine_q_usage - Calculate queue distribution
1774940b61afSAnirudh Venkataramanan  * @pf: board private structure
1775940b61afSAnirudh Venkataramanan  *
1776940b61afSAnirudh Venkataramanan  * Return -ENOMEM if we don't get enough queues for all ports
1777940b61afSAnirudh Venkataramanan  */
1778940b61afSAnirudh Venkataramanan static void ice_determine_q_usage(struct ice_pf *pf)
1779940b61afSAnirudh Venkataramanan {
1780940b61afSAnirudh Venkataramanan 	u16 q_left_tx, q_left_rx;
1781940b61afSAnirudh Venkataramanan 
1782940b61afSAnirudh Venkataramanan 	q_left_tx = pf->hw.func_caps.common_cap.num_txq;
1783940b61afSAnirudh Venkataramanan 	q_left_rx = pf->hw.func_caps.common_cap.num_rxq;
1784940b61afSAnirudh Venkataramanan 
17855513b920SAnirudh Venkataramanan 	pf->num_lan_tx = min_t(int, q_left_tx, num_online_cpus());
1786d76a60baSAnirudh Venkataramanan 
1787d76a60baSAnirudh Venkataramanan 	/* only 1 rx queue unless RSS is enabled */
1788d76a60baSAnirudh Venkataramanan 	if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags))
1789940b61afSAnirudh Venkataramanan 		pf->num_lan_rx = 1;
1790d76a60baSAnirudh Venkataramanan 	else
1791d76a60baSAnirudh Venkataramanan 		pf->num_lan_rx = min_t(int, q_left_rx, num_online_cpus());
1792940b61afSAnirudh Venkataramanan 
1793940b61afSAnirudh Venkataramanan 	pf->q_left_tx = q_left_tx - pf->num_lan_tx;
1794940b61afSAnirudh Venkataramanan 	pf->q_left_rx = q_left_rx - pf->num_lan_rx;
1795940b61afSAnirudh Venkataramanan }
1796940b61afSAnirudh Venkataramanan 
1797940b61afSAnirudh Venkataramanan /**
1798940b61afSAnirudh Venkataramanan  * ice_deinit_pf - Unrolls initialziations done by ice_init_pf
1799940b61afSAnirudh Venkataramanan  * @pf: board private structure to initialize
1800940b61afSAnirudh Venkataramanan  */
1801940b61afSAnirudh Venkataramanan static void ice_deinit_pf(struct ice_pf *pf)
1802940b61afSAnirudh Venkataramanan {
18038d81fa55SAkeem G Abodunrin 	ice_service_task_stop(pf);
1804940b61afSAnirudh Venkataramanan 	mutex_destroy(&pf->sw_mutex);
1805940b61afSAnirudh Venkataramanan 	mutex_destroy(&pf->avail_q_mutex);
1806940b61afSAnirudh Venkataramanan }
1807940b61afSAnirudh Venkataramanan 
1808940b61afSAnirudh Venkataramanan /**
1809940b61afSAnirudh Venkataramanan  * ice_init_pf - Initialize general software structures (struct ice_pf)
1810940b61afSAnirudh Venkataramanan  * @pf: board private structure to initialize
1811940b61afSAnirudh Venkataramanan  */
1812940b61afSAnirudh Venkataramanan static void ice_init_pf(struct ice_pf *pf)
1813940b61afSAnirudh Venkataramanan {
1814940b61afSAnirudh Venkataramanan 	bitmap_zero(pf->flags, ICE_PF_FLAGS_NBITS);
1815940b61afSAnirudh Venkataramanan 	set_bit(ICE_FLAG_MSIX_ENA, pf->flags);
181675d2b253SAnirudh Venkataramanan #ifdef CONFIG_PCI_IOV
181775d2b253SAnirudh Venkataramanan 	if (pf->hw.func_caps.common_cap.sr_iov_1_1) {
181875d2b253SAnirudh Venkataramanan 		struct ice_hw *hw = &pf->hw;
181975d2b253SAnirudh Venkataramanan 
182075d2b253SAnirudh Venkataramanan 		set_bit(ICE_FLAG_SRIOV_CAPABLE, pf->flags);
182175d2b253SAnirudh Venkataramanan 		pf->num_vfs_supported = min_t(int, hw->func_caps.num_allocd_vfs,
182275d2b253SAnirudh Venkataramanan 					      ICE_MAX_VF_COUNT);
182375d2b253SAnirudh Venkataramanan 	}
182475d2b253SAnirudh Venkataramanan #endif /* CONFIG_PCI_IOV */
1825940b61afSAnirudh Venkataramanan 
1826940b61afSAnirudh Venkataramanan 	mutex_init(&pf->sw_mutex);
1827940b61afSAnirudh Venkataramanan 	mutex_init(&pf->avail_q_mutex);
1828940b61afSAnirudh Venkataramanan 
1829940b61afSAnirudh Venkataramanan 	/* Clear avail_[t|r]x_qs bitmaps (set all to avail) */
1830940b61afSAnirudh Venkataramanan 	mutex_lock(&pf->avail_q_mutex);
1831940b61afSAnirudh Venkataramanan 	bitmap_zero(pf->avail_txqs, ICE_MAX_TXQS);
1832940b61afSAnirudh Venkataramanan 	bitmap_zero(pf->avail_rxqs, ICE_MAX_RXQS);
1833940b61afSAnirudh Venkataramanan 	mutex_unlock(&pf->avail_q_mutex);
1834940b61afSAnirudh Venkataramanan 
1835d76a60baSAnirudh Venkataramanan 	if (pf->hw.func_caps.common_cap.rss_table_size)
1836d76a60baSAnirudh Venkataramanan 		set_bit(ICE_FLAG_RSS_ENA, pf->flags);
1837d76a60baSAnirudh Venkataramanan 
1838940b61afSAnirudh Venkataramanan 	/* setup service timer and periodic service task */
1839940b61afSAnirudh Venkataramanan 	timer_setup(&pf->serv_tmr, ice_service_timer, 0);
1840940b61afSAnirudh Venkataramanan 	pf->serv_tmr_period = HZ;
1841940b61afSAnirudh Venkataramanan 	INIT_WORK(&pf->serv_task, ice_service_task);
1842940b61afSAnirudh Venkataramanan 	clear_bit(__ICE_SERVICE_SCHED, pf->state);
1843940b61afSAnirudh Venkataramanan }
1844940b61afSAnirudh Venkataramanan 
1845940b61afSAnirudh Venkataramanan /**
1846940b61afSAnirudh Venkataramanan  * ice_ena_msix_range - Request a range of MSIX vectors from the OS
1847940b61afSAnirudh Venkataramanan  * @pf: board private structure
1848940b61afSAnirudh Venkataramanan  *
1849940b61afSAnirudh Venkataramanan  * compute the number of MSIX vectors required (v_budget) and request from
1850940b61afSAnirudh Venkataramanan  * the OS. Return the number of vectors reserved or negative on failure
1851940b61afSAnirudh Venkataramanan  */
1852940b61afSAnirudh Venkataramanan static int ice_ena_msix_range(struct ice_pf *pf)
1853940b61afSAnirudh Venkataramanan {
1854940b61afSAnirudh Venkataramanan 	int v_left, v_actual, v_budget = 0;
1855940b61afSAnirudh Venkataramanan 	int needed, err, i;
1856940b61afSAnirudh Venkataramanan 
1857940b61afSAnirudh Venkataramanan 	v_left = pf->hw.func_caps.common_cap.num_msix_vectors;
1858940b61afSAnirudh Venkataramanan 
1859940b61afSAnirudh Venkataramanan 	/* reserve one vector for miscellaneous handler */
1860940b61afSAnirudh Venkataramanan 	needed = 1;
1861940b61afSAnirudh Venkataramanan 	v_budget += needed;
1862940b61afSAnirudh Venkataramanan 	v_left -= needed;
1863940b61afSAnirudh Venkataramanan 
1864940b61afSAnirudh Venkataramanan 	/* reserve vectors for LAN traffic */
1865940b61afSAnirudh Venkataramanan 	pf->num_lan_msix = min_t(int, num_online_cpus(), v_left);
1866940b61afSAnirudh Venkataramanan 	v_budget += pf->num_lan_msix;
1867eb0208ecSPreethi Banala 	v_left -= pf->num_lan_msix;
1868940b61afSAnirudh Venkataramanan 
1869940b61afSAnirudh Venkataramanan 	pf->msix_entries = devm_kcalloc(&pf->pdev->dev, v_budget,
1870940b61afSAnirudh Venkataramanan 					sizeof(struct msix_entry), GFP_KERNEL);
1871940b61afSAnirudh Venkataramanan 
1872940b61afSAnirudh Venkataramanan 	if (!pf->msix_entries) {
1873940b61afSAnirudh Venkataramanan 		err = -ENOMEM;
1874940b61afSAnirudh Venkataramanan 		goto exit_err;
1875940b61afSAnirudh Venkataramanan 	}
1876940b61afSAnirudh Venkataramanan 
1877940b61afSAnirudh Venkataramanan 	for (i = 0; i < v_budget; i++)
1878940b61afSAnirudh Venkataramanan 		pf->msix_entries[i].entry = i;
1879940b61afSAnirudh Venkataramanan 
1880940b61afSAnirudh Venkataramanan 	/* actually reserve the vectors */
1881940b61afSAnirudh Venkataramanan 	v_actual = pci_enable_msix_range(pf->pdev, pf->msix_entries,
1882940b61afSAnirudh Venkataramanan 					 ICE_MIN_MSIX, v_budget);
1883940b61afSAnirudh Venkataramanan 
1884940b61afSAnirudh Venkataramanan 	if (v_actual < 0) {
1885940b61afSAnirudh Venkataramanan 		dev_err(&pf->pdev->dev, "unable to reserve MSI-X vectors\n");
1886940b61afSAnirudh Venkataramanan 		err = v_actual;
1887940b61afSAnirudh Venkataramanan 		goto msix_err;
1888940b61afSAnirudh Venkataramanan 	}
1889940b61afSAnirudh Venkataramanan 
1890940b61afSAnirudh Venkataramanan 	if (v_actual < v_budget) {
1891940b61afSAnirudh Venkataramanan 		dev_warn(&pf->pdev->dev,
1892940b61afSAnirudh Venkataramanan 			 "not enough vectors. requested = %d, obtained = %d\n",
1893940b61afSAnirudh Venkataramanan 			 v_budget, v_actual);
1894940b61afSAnirudh Venkataramanan 		if (v_actual >= (pf->num_lan_msix + 1)) {
1895eb0208ecSPreethi Banala 			pf->num_avail_sw_msix = v_actual -
1896eb0208ecSPreethi Banala 						(pf->num_lan_msix + 1);
1897940b61afSAnirudh Venkataramanan 		} else if (v_actual >= 2) {
1898940b61afSAnirudh Venkataramanan 			pf->num_lan_msix = 1;
1899eb0208ecSPreethi Banala 			pf->num_avail_sw_msix = v_actual - 2;
1900940b61afSAnirudh Venkataramanan 		} else {
1901940b61afSAnirudh Venkataramanan 			pci_disable_msix(pf->pdev);
1902940b61afSAnirudh Venkataramanan 			err = -ERANGE;
1903940b61afSAnirudh Venkataramanan 			goto msix_err;
1904940b61afSAnirudh Venkataramanan 		}
1905940b61afSAnirudh Venkataramanan 	}
1906940b61afSAnirudh Venkataramanan 
1907940b61afSAnirudh Venkataramanan 	return v_actual;
1908940b61afSAnirudh Venkataramanan 
1909940b61afSAnirudh Venkataramanan msix_err:
1910940b61afSAnirudh Venkataramanan 	devm_kfree(&pf->pdev->dev, pf->msix_entries);
1911940b61afSAnirudh Venkataramanan 	goto exit_err;
1912940b61afSAnirudh Venkataramanan 
1913940b61afSAnirudh Venkataramanan exit_err:
1914940b61afSAnirudh Venkataramanan 	pf->num_lan_msix = 0;
1915940b61afSAnirudh Venkataramanan 	clear_bit(ICE_FLAG_MSIX_ENA, pf->flags);
1916940b61afSAnirudh Venkataramanan 	return err;
1917940b61afSAnirudh Venkataramanan }
1918940b61afSAnirudh Venkataramanan 
1919940b61afSAnirudh Venkataramanan /**
1920940b61afSAnirudh Venkataramanan  * ice_dis_msix - Disable MSI-X interrupt setup in OS
1921940b61afSAnirudh Venkataramanan  * @pf: board private structure
1922940b61afSAnirudh Venkataramanan  */
1923940b61afSAnirudh Venkataramanan static void ice_dis_msix(struct ice_pf *pf)
1924940b61afSAnirudh Venkataramanan {
1925940b61afSAnirudh Venkataramanan 	pci_disable_msix(pf->pdev);
1926940b61afSAnirudh Venkataramanan 	devm_kfree(&pf->pdev->dev, pf->msix_entries);
1927940b61afSAnirudh Venkataramanan 	pf->msix_entries = NULL;
1928940b61afSAnirudh Venkataramanan 	clear_bit(ICE_FLAG_MSIX_ENA, pf->flags);
1929940b61afSAnirudh Venkataramanan }
1930940b61afSAnirudh Venkataramanan 
1931940b61afSAnirudh Venkataramanan /**
1932eb0208ecSPreethi Banala  * ice_clear_interrupt_scheme - Undo things done by ice_init_interrupt_scheme
1933eb0208ecSPreethi Banala  * @pf: board private structure
1934eb0208ecSPreethi Banala  */
1935eb0208ecSPreethi Banala static void ice_clear_interrupt_scheme(struct ice_pf *pf)
1936eb0208ecSPreethi Banala {
1937eb0208ecSPreethi Banala 	if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags))
1938eb0208ecSPreethi Banala 		ice_dis_msix(pf);
1939eb0208ecSPreethi Banala 
1940eb0208ecSPreethi Banala 	if (pf->sw_irq_tracker) {
1941eb0208ecSPreethi Banala 		devm_kfree(&pf->pdev->dev, pf->sw_irq_tracker);
1942eb0208ecSPreethi Banala 		pf->sw_irq_tracker = NULL;
1943eb0208ecSPreethi Banala 	}
1944eb0208ecSPreethi Banala 
1945eb0208ecSPreethi Banala 	if (pf->hw_irq_tracker) {
1946eb0208ecSPreethi Banala 		devm_kfree(&pf->pdev->dev, pf->hw_irq_tracker);
1947eb0208ecSPreethi Banala 		pf->hw_irq_tracker = NULL;
1948eb0208ecSPreethi Banala 	}
1949eb0208ecSPreethi Banala }
1950eb0208ecSPreethi Banala 
1951eb0208ecSPreethi Banala /**
1952940b61afSAnirudh Venkataramanan  * ice_init_interrupt_scheme - Determine proper interrupt scheme
1953940b61afSAnirudh Venkataramanan  * @pf: board private structure to initialize
1954940b61afSAnirudh Venkataramanan  */
1955940b61afSAnirudh Venkataramanan static int ice_init_interrupt_scheme(struct ice_pf *pf)
1956940b61afSAnirudh Venkataramanan {
1957eb0208ecSPreethi Banala 	int vectors = 0, hw_vectors = 0;
1958940b61afSAnirudh Venkataramanan 	ssize_t size;
1959940b61afSAnirudh Venkataramanan 
1960940b61afSAnirudh Venkataramanan 	if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags))
1961940b61afSAnirudh Venkataramanan 		vectors = ice_ena_msix_range(pf);
1962940b61afSAnirudh Venkataramanan 	else
1963940b61afSAnirudh Venkataramanan 		return -ENODEV;
1964940b61afSAnirudh Venkataramanan 
1965940b61afSAnirudh Venkataramanan 	if (vectors < 0)
1966940b61afSAnirudh Venkataramanan 		return vectors;
1967940b61afSAnirudh Venkataramanan 
1968940b61afSAnirudh Venkataramanan 	/* set up vector assignment tracking */
1969940b61afSAnirudh Venkataramanan 	size = sizeof(struct ice_res_tracker) + (sizeof(u16) * vectors);
1970940b61afSAnirudh Venkataramanan 
1971eb0208ecSPreethi Banala 	pf->sw_irq_tracker = devm_kzalloc(&pf->pdev->dev, size, GFP_KERNEL);
1972eb0208ecSPreethi Banala 	if (!pf->sw_irq_tracker) {
1973940b61afSAnirudh Venkataramanan 		ice_dis_msix(pf);
1974940b61afSAnirudh Venkataramanan 		return -ENOMEM;
1975940b61afSAnirudh Venkataramanan 	}
1976940b61afSAnirudh Venkataramanan 
1977eb0208ecSPreethi Banala 	/* populate SW interrupts pool with number of OS granted IRQs. */
1978eb0208ecSPreethi Banala 	pf->num_avail_sw_msix = vectors;
1979eb0208ecSPreethi Banala 	pf->sw_irq_tracker->num_entries = vectors;
1980eb0208ecSPreethi Banala 
1981eb0208ecSPreethi Banala 	/* set up HW vector assignment tracking */
1982eb0208ecSPreethi Banala 	hw_vectors = pf->hw.func_caps.common_cap.num_msix_vectors;
1983eb0208ecSPreethi Banala 	size = sizeof(struct ice_res_tracker) + (sizeof(u16) * hw_vectors);
1984eb0208ecSPreethi Banala 
1985eb0208ecSPreethi Banala 	pf->hw_irq_tracker = devm_kzalloc(&pf->pdev->dev, size, GFP_KERNEL);
1986eb0208ecSPreethi Banala 	if (!pf->hw_irq_tracker) {
1987eb0208ecSPreethi Banala 		ice_clear_interrupt_scheme(pf);
1988eb0208ecSPreethi Banala 		return -ENOMEM;
1989eb0208ecSPreethi Banala 	}
1990eb0208ecSPreethi Banala 
1991eb0208ecSPreethi Banala 	/* populate HW interrupts pool with number of HW supported irqs. */
1992eb0208ecSPreethi Banala 	pf->num_avail_hw_msix = hw_vectors;
1993eb0208ecSPreethi Banala 	pf->hw_irq_tracker->num_entries = hw_vectors;
1994940b61afSAnirudh Venkataramanan 
1995940b61afSAnirudh Venkataramanan 	return 0;
1996940b61afSAnirudh Venkataramanan }
1997940b61afSAnirudh Venkataramanan 
1998940b61afSAnirudh Venkataramanan /**
1999837f08fdSAnirudh Venkataramanan  * ice_probe - Device initialization routine
2000837f08fdSAnirudh Venkataramanan  * @pdev: PCI device information struct
2001837f08fdSAnirudh Venkataramanan  * @ent: entry in ice_pci_tbl
2002837f08fdSAnirudh Venkataramanan  *
2003837f08fdSAnirudh Venkataramanan  * Returns 0 on success, negative on failure
2004837f08fdSAnirudh Venkataramanan  */
2005837f08fdSAnirudh Venkataramanan static int ice_probe(struct pci_dev *pdev,
2006837f08fdSAnirudh Venkataramanan 		     const struct pci_device_id __always_unused *ent)
2007837f08fdSAnirudh Venkataramanan {
2008837f08fdSAnirudh Venkataramanan 	struct ice_pf *pf;
2009837f08fdSAnirudh Venkataramanan 	struct ice_hw *hw;
2010837f08fdSAnirudh Venkataramanan 	int err;
2011837f08fdSAnirudh Venkataramanan 
2012837f08fdSAnirudh Venkataramanan 	/* this driver uses devres, see Documentation/driver-model/devres.txt */
2013837f08fdSAnirudh Venkataramanan 	err = pcim_enable_device(pdev);
2014837f08fdSAnirudh Venkataramanan 	if (err)
2015837f08fdSAnirudh Venkataramanan 		return err;
2016837f08fdSAnirudh Venkataramanan 
2017837f08fdSAnirudh Venkataramanan 	err = pcim_iomap_regions(pdev, BIT(ICE_BAR0), pci_name(pdev));
2018837f08fdSAnirudh Venkataramanan 	if (err) {
20193968540bSAnirudh Venkataramanan 		dev_err(&pdev->dev, "BAR0 I/O map error %d\n", err);
2020837f08fdSAnirudh Venkataramanan 		return err;
2021837f08fdSAnirudh Venkataramanan 	}
2022837f08fdSAnirudh Venkataramanan 
2023837f08fdSAnirudh Venkataramanan 	pf = devm_kzalloc(&pdev->dev, sizeof(*pf), GFP_KERNEL);
2024837f08fdSAnirudh Venkataramanan 	if (!pf)
2025837f08fdSAnirudh Venkataramanan 		return -ENOMEM;
2026837f08fdSAnirudh Venkataramanan 
2027837f08fdSAnirudh Venkataramanan 	/* set up for high or low dma */
2028837f08fdSAnirudh Venkataramanan 	err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
2029837f08fdSAnirudh Venkataramanan 	if (err)
2030837f08fdSAnirudh Venkataramanan 		err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
2031837f08fdSAnirudh Venkataramanan 	if (err) {
2032837f08fdSAnirudh Venkataramanan 		dev_err(&pdev->dev, "DMA configuration failed: 0x%x\n", err);
2033837f08fdSAnirudh Venkataramanan 		return err;
2034837f08fdSAnirudh Venkataramanan 	}
2035837f08fdSAnirudh Venkataramanan 
2036837f08fdSAnirudh Venkataramanan 	pci_enable_pcie_error_reporting(pdev);
2037837f08fdSAnirudh Venkataramanan 	pci_set_master(pdev);
2038837f08fdSAnirudh Venkataramanan 
2039837f08fdSAnirudh Venkataramanan 	pf->pdev = pdev;
2040837f08fdSAnirudh Venkataramanan 	pci_set_drvdata(pdev, pf);
2041837f08fdSAnirudh Venkataramanan 	set_bit(__ICE_DOWN, pf->state);
20428d81fa55SAkeem G Abodunrin 	/* Disable service task until DOWN bit is cleared */
20438d81fa55SAkeem G Abodunrin 	set_bit(__ICE_SERVICE_DIS, pf->state);
2044837f08fdSAnirudh Venkataramanan 
2045837f08fdSAnirudh Venkataramanan 	hw = &pf->hw;
2046837f08fdSAnirudh Venkataramanan 	hw->hw_addr = pcim_iomap_table(pdev)[ICE_BAR0];
2047837f08fdSAnirudh Venkataramanan 	hw->back = pf;
2048837f08fdSAnirudh Venkataramanan 	hw->vendor_id = pdev->vendor;
2049837f08fdSAnirudh Venkataramanan 	hw->device_id = pdev->device;
2050837f08fdSAnirudh Venkataramanan 	pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
2051837f08fdSAnirudh Venkataramanan 	hw->subsystem_vendor_id = pdev->subsystem_vendor;
2052837f08fdSAnirudh Venkataramanan 	hw->subsystem_device_id = pdev->subsystem_device;
2053837f08fdSAnirudh Venkataramanan 	hw->bus.device = PCI_SLOT(pdev->devfn);
2054837f08fdSAnirudh Venkataramanan 	hw->bus.func = PCI_FUNC(pdev->devfn);
2055f31e4b6fSAnirudh Venkataramanan 	ice_set_ctrlq_len(hw);
2056f31e4b6fSAnirudh Venkataramanan 
2057837f08fdSAnirudh Venkataramanan 	pf->msg_enable = netif_msg_init(debug, ICE_DFLT_NETIF_M);
2058837f08fdSAnirudh Venkataramanan 
20597ec59eeaSAnirudh Venkataramanan #ifndef CONFIG_DYNAMIC_DEBUG
20607ec59eeaSAnirudh Venkataramanan 	if (debug < -1)
20617ec59eeaSAnirudh Venkataramanan 		hw->debug_mask = debug;
20627ec59eeaSAnirudh Venkataramanan #endif
20637ec59eeaSAnirudh Venkataramanan 
2064f31e4b6fSAnirudh Venkataramanan 	err = ice_init_hw(hw);
2065f31e4b6fSAnirudh Venkataramanan 	if (err) {
2066f31e4b6fSAnirudh Venkataramanan 		dev_err(&pdev->dev, "ice_init_hw failed: %d\n", err);
2067f31e4b6fSAnirudh Venkataramanan 		err = -EIO;
2068f31e4b6fSAnirudh Venkataramanan 		goto err_exit_unroll;
2069f31e4b6fSAnirudh Venkataramanan 	}
2070f31e4b6fSAnirudh Venkataramanan 
2071f31e4b6fSAnirudh Venkataramanan 	dev_info(&pdev->dev, "firmware %d.%d.%05d api %d.%d\n",
2072f31e4b6fSAnirudh Venkataramanan 		 hw->fw_maj_ver, hw->fw_min_ver, hw->fw_build,
2073f31e4b6fSAnirudh Venkataramanan 		 hw->api_maj_ver, hw->api_min_ver);
2074f31e4b6fSAnirudh Venkataramanan 
2075940b61afSAnirudh Venkataramanan 	ice_init_pf(pf);
2076940b61afSAnirudh Venkataramanan 
2077940b61afSAnirudh Venkataramanan 	ice_determine_q_usage(pf);
2078940b61afSAnirudh Venkataramanan 
2079940b61afSAnirudh Venkataramanan 	pf->num_alloc_vsi = min_t(u16, ICE_MAX_VSI_ALLOC,
2080940b61afSAnirudh Venkataramanan 				  hw->func_caps.guaranteed_num_vsi);
2081940b61afSAnirudh Venkataramanan 	if (!pf->num_alloc_vsi) {
2082940b61afSAnirudh Venkataramanan 		err = -EIO;
2083940b61afSAnirudh Venkataramanan 		goto err_init_pf_unroll;
2084940b61afSAnirudh Venkataramanan 	}
2085940b61afSAnirudh Venkataramanan 
2086940b61afSAnirudh Venkataramanan 	pf->vsi = devm_kcalloc(&pdev->dev, pf->num_alloc_vsi,
2087940b61afSAnirudh Venkataramanan 			       sizeof(struct ice_vsi *), GFP_KERNEL);
2088940b61afSAnirudh Venkataramanan 	if (!pf->vsi) {
2089940b61afSAnirudh Venkataramanan 		err = -ENOMEM;
2090940b61afSAnirudh Venkataramanan 		goto err_init_pf_unroll;
2091940b61afSAnirudh Venkataramanan 	}
2092940b61afSAnirudh Venkataramanan 
2093940b61afSAnirudh Venkataramanan 	err = ice_init_interrupt_scheme(pf);
2094940b61afSAnirudh Venkataramanan 	if (err) {
2095940b61afSAnirudh Venkataramanan 		dev_err(&pdev->dev,
2096940b61afSAnirudh Venkataramanan 			"ice_init_interrupt_scheme failed: %d\n", err);
2097940b61afSAnirudh Venkataramanan 		err = -EIO;
2098940b61afSAnirudh Venkataramanan 		goto err_init_interrupt_unroll;
2099940b61afSAnirudh Venkataramanan 	}
2100940b61afSAnirudh Venkataramanan 
21018d81fa55SAkeem G Abodunrin 	/* Driver is mostly up */
21028d81fa55SAkeem G Abodunrin 	clear_bit(__ICE_DOWN, pf->state);
21038d81fa55SAkeem G Abodunrin 
2104940b61afSAnirudh Venkataramanan 	/* In case of MSIX we are going to setup the misc vector right here
2105940b61afSAnirudh Venkataramanan 	 * to handle admin queue events etc. In case of legacy and MSI
2106940b61afSAnirudh Venkataramanan 	 * the misc functionality and queue processing is combined in
2107940b61afSAnirudh Venkataramanan 	 * the same vector and that gets setup at open.
2108940b61afSAnirudh Venkataramanan 	 */
2109940b61afSAnirudh Venkataramanan 	if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) {
2110940b61afSAnirudh Venkataramanan 		err = ice_req_irq_msix_misc(pf);
2111940b61afSAnirudh Venkataramanan 		if (err) {
2112940b61afSAnirudh Venkataramanan 			dev_err(&pdev->dev,
2113940b61afSAnirudh Venkataramanan 				"setup of misc vector failed: %d\n", err);
2114940b61afSAnirudh Venkataramanan 			goto err_init_interrupt_unroll;
2115940b61afSAnirudh Venkataramanan 		}
2116940b61afSAnirudh Venkataramanan 	}
2117940b61afSAnirudh Venkataramanan 
2118940b61afSAnirudh Venkataramanan 	/* create switch struct for the switch element created by FW on boot */
2119940b61afSAnirudh Venkataramanan 	pf->first_sw = devm_kzalloc(&pdev->dev, sizeof(struct ice_sw),
2120940b61afSAnirudh Venkataramanan 				    GFP_KERNEL);
2121940b61afSAnirudh Venkataramanan 	if (!pf->first_sw) {
2122940b61afSAnirudh Venkataramanan 		err = -ENOMEM;
2123940b61afSAnirudh Venkataramanan 		goto err_msix_misc_unroll;
2124940b61afSAnirudh Venkataramanan 	}
2125940b61afSAnirudh Venkataramanan 
2126b1edc14aSMd Fahad Iqbal Polash 	if (hw->evb_veb)
2127940b61afSAnirudh Venkataramanan 		pf->first_sw->bridge_mode = BRIDGE_MODE_VEB;
2128b1edc14aSMd Fahad Iqbal Polash 	else
2129b1edc14aSMd Fahad Iqbal Polash 		pf->first_sw->bridge_mode = BRIDGE_MODE_VEPA;
2130b1edc14aSMd Fahad Iqbal Polash 
2131940b61afSAnirudh Venkataramanan 	pf->first_sw->pf = pf;
2132940b61afSAnirudh Venkataramanan 
2133940b61afSAnirudh Venkataramanan 	/* record the sw_id available for later use */
2134940b61afSAnirudh Venkataramanan 	pf->first_sw->sw_id = hw->port_info->sw_id;
2135940b61afSAnirudh Venkataramanan 
21363a858ba3SAnirudh Venkataramanan 	err = ice_setup_pf_sw(pf);
21373a858ba3SAnirudh Venkataramanan 	if (err) {
21383a858ba3SAnirudh Venkataramanan 		dev_err(&pdev->dev,
21393a858ba3SAnirudh Venkataramanan 			"probe failed due to setup pf switch:%d\n", err);
21403a858ba3SAnirudh Venkataramanan 		goto err_alloc_sw_unroll;
21413a858ba3SAnirudh Venkataramanan 	}
21429daf8208SAnirudh Venkataramanan 
21438d81fa55SAkeem G Abodunrin 	clear_bit(__ICE_SERVICE_DIS, pf->state);
21449daf8208SAnirudh Venkataramanan 
21459daf8208SAnirudh Venkataramanan 	/* since everything is good, start the service timer */
21469daf8208SAnirudh Venkataramanan 	mod_timer(&pf->serv_tmr, round_jiffies(jiffies + pf->serv_tmr_period));
21479daf8208SAnirudh Venkataramanan 
21480b28b702SAnirudh Venkataramanan 	err = ice_init_link_events(pf->hw.port_info);
21490b28b702SAnirudh Venkataramanan 	if (err) {
21500b28b702SAnirudh Venkataramanan 		dev_err(&pdev->dev, "ice_init_link_events failed: %d\n", err);
21510b28b702SAnirudh Venkataramanan 		goto err_alloc_sw_unroll;
21520b28b702SAnirudh Venkataramanan 	}
21530b28b702SAnirudh Venkataramanan 
2154837f08fdSAnirudh Venkataramanan 	return 0;
2155f31e4b6fSAnirudh Venkataramanan 
21563a858ba3SAnirudh Venkataramanan err_alloc_sw_unroll:
21578d81fa55SAkeem G Abodunrin 	set_bit(__ICE_SERVICE_DIS, pf->state);
21583a858ba3SAnirudh Venkataramanan 	set_bit(__ICE_DOWN, pf->state);
21593a858ba3SAnirudh Venkataramanan 	devm_kfree(&pf->pdev->dev, pf->first_sw);
2160940b61afSAnirudh Venkataramanan err_msix_misc_unroll:
2161940b61afSAnirudh Venkataramanan 	ice_free_irq_msix_misc(pf);
2162940b61afSAnirudh Venkataramanan err_init_interrupt_unroll:
2163940b61afSAnirudh Venkataramanan 	ice_clear_interrupt_scheme(pf);
2164940b61afSAnirudh Venkataramanan 	devm_kfree(&pdev->dev, pf->vsi);
2165940b61afSAnirudh Venkataramanan err_init_pf_unroll:
2166940b61afSAnirudh Venkataramanan 	ice_deinit_pf(pf);
2167940b61afSAnirudh Venkataramanan 	ice_deinit_hw(hw);
2168f31e4b6fSAnirudh Venkataramanan err_exit_unroll:
2169f31e4b6fSAnirudh Venkataramanan 	pci_disable_pcie_error_reporting(pdev);
2170f31e4b6fSAnirudh Venkataramanan 	return err;
2171837f08fdSAnirudh Venkataramanan }
2172837f08fdSAnirudh Venkataramanan 
2173837f08fdSAnirudh Venkataramanan /**
2174837f08fdSAnirudh Venkataramanan  * ice_remove - Device removal routine
2175837f08fdSAnirudh Venkataramanan  * @pdev: PCI device information struct
2176837f08fdSAnirudh Venkataramanan  */
2177837f08fdSAnirudh Venkataramanan static void ice_remove(struct pci_dev *pdev)
2178837f08fdSAnirudh Venkataramanan {
2179837f08fdSAnirudh Venkataramanan 	struct ice_pf *pf = pci_get_drvdata(pdev);
218081b23589SDave Ertman 	int i;
2181837f08fdSAnirudh Venkataramanan 
2182837f08fdSAnirudh Venkataramanan 	if (!pf)
2183837f08fdSAnirudh Venkataramanan 		return;
2184837f08fdSAnirudh Venkataramanan 
2185837f08fdSAnirudh Venkataramanan 	set_bit(__ICE_DOWN, pf->state);
21868d81fa55SAkeem G Abodunrin 	ice_service_task_stop(pf);
2187f31e4b6fSAnirudh Venkataramanan 
21880f9d5027SAnirudh Venkataramanan 	ice_vsi_release_all(pf);
2189940b61afSAnirudh Venkataramanan 	ice_free_irq_msix_misc(pf);
219081b23589SDave Ertman 	ice_for_each_vsi(pf, i) {
219181b23589SDave Ertman 		if (!pf->vsi[i])
219281b23589SDave Ertman 			continue;
219381b23589SDave Ertman 		ice_vsi_free_q_vectors(pf->vsi[i]);
219481b23589SDave Ertman 	}
2195940b61afSAnirudh Venkataramanan 	ice_clear_interrupt_scheme(pf);
2196940b61afSAnirudh Venkataramanan 	ice_deinit_pf(pf);
2197f31e4b6fSAnirudh Venkataramanan 	ice_deinit_hw(&pf->hw);
2198837f08fdSAnirudh Venkataramanan 	pci_disable_pcie_error_reporting(pdev);
2199837f08fdSAnirudh Venkataramanan }
2200837f08fdSAnirudh Venkataramanan 
2201837f08fdSAnirudh Venkataramanan /* ice_pci_tbl - PCI Device ID Table
2202837f08fdSAnirudh Venkataramanan  *
2203837f08fdSAnirudh Venkataramanan  * Wildcard entries (PCI_ANY_ID) should come last
2204837f08fdSAnirudh Venkataramanan  * Last entry must be all 0s
2205837f08fdSAnirudh Venkataramanan  *
2206837f08fdSAnirudh Venkataramanan  * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
2207837f08fdSAnirudh Venkataramanan  *   Class, Class Mask, private data (not used) }
2208837f08fdSAnirudh Venkataramanan  */
2209837f08fdSAnirudh Venkataramanan static const struct pci_device_id ice_pci_tbl[] = {
2210837f08fdSAnirudh Venkataramanan 	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_C810_BACKPLANE), 0 },
2211837f08fdSAnirudh Venkataramanan 	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_C810_QSFP), 0 },
2212837f08fdSAnirudh Venkataramanan 	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_C810_SFP), 0 },
2213837f08fdSAnirudh Venkataramanan 	/* required last entry */
2214837f08fdSAnirudh Venkataramanan 	{ 0, }
2215837f08fdSAnirudh Venkataramanan };
2216837f08fdSAnirudh Venkataramanan MODULE_DEVICE_TABLE(pci, ice_pci_tbl);
2217837f08fdSAnirudh Venkataramanan 
2218837f08fdSAnirudh Venkataramanan static struct pci_driver ice_driver = {
2219837f08fdSAnirudh Venkataramanan 	.name = KBUILD_MODNAME,
2220837f08fdSAnirudh Venkataramanan 	.id_table = ice_pci_tbl,
2221837f08fdSAnirudh Venkataramanan 	.probe = ice_probe,
2222837f08fdSAnirudh Venkataramanan 	.remove = ice_remove,
2223837f08fdSAnirudh Venkataramanan };
2224837f08fdSAnirudh Venkataramanan 
2225837f08fdSAnirudh Venkataramanan /**
2226837f08fdSAnirudh Venkataramanan  * ice_module_init - Driver registration routine
2227837f08fdSAnirudh Venkataramanan  *
2228837f08fdSAnirudh Venkataramanan  * ice_module_init is the first routine called when the driver is
2229837f08fdSAnirudh Venkataramanan  * loaded. All it does is register with the PCI subsystem.
2230837f08fdSAnirudh Venkataramanan  */
2231837f08fdSAnirudh Venkataramanan static int __init ice_module_init(void)
2232837f08fdSAnirudh Venkataramanan {
2233837f08fdSAnirudh Venkataramanan 	int status;
2234837f08fdSAnirudh Venkataramanan 
2235837f08fdSAnirudh Venkataramanan 	pr_info("%s - version %s\n", ice_driver_string, ice_drv_ver);
2236837f08fdSAnirudh Venkataramanan 	pr_info("%s\n", ice_copyright);
2237837f08fdSAnirudh Venkataramanan 
22380f9d5027SAnirudh Venkataramanan 	ice_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 0, KBUILD_MODNAME);
2239940b61afSAnirudh Venkataramanan 	if (!ice_wq) {
2240940b61afSAnirudh Venkataramanan 		pr_err("Failed to create workqueue\n");
2241940b61afSAnirudh Venkataramanan 		return -ENOMEM;
2242940b61afSAnirudh Venkataramanan 	}
2243940b61afSAnirudh Venkataramanan 
2244837f08fdSAnirudh Venkataramanan 	status = pci_register_driver(&ice_driver);
2245940b61afSAnirudh Venkataramanan 	if (status) {
2246837f08fdSAnirudh Venkataramanan 		pr_err("failed to register pci driver, err %d\n", status);
2247940b61afSAnirudh Venkataramanan 		destroy_workqueue(ice_wq);
2248940b61afSAnirudh Venkataramanan 	}
2249837f08fdSAnirudh Venkataramanan 
2250837f08fdSAnirudh Venkataramanan 	return status;
2251837f08fdSAnirudh Venkataramanan }
2252837f08fdSAnirudh Venkataramanan module_init(ice_module_init);
2253837f08fdSAnirudh Venkataramanan 
2254837f08fdSAnirudh Venkataramanan /**
2255837f08fdSAnirudh Venkataramanan  * ice_module_exit - Driver exit cleanup routine
2256837f08fdSAnirudh Venkataramanan  *
2257837f08fdSAnirudh Venkataramanan  * ice_module_exit is called just before the driver is removed
2258837f08fdSAnirudh Venkataramanan  * from memory.
2259837f08fdSAnirudh Venkataramanan  */
2260837f08fdSAnirudh Venkataramanan static void __exit ice_module_exit(void)
2261837f08fdSAnirudh Venkataramanan {
2262837f08fdSAnirudh Venkataramanan 	pci_unregister_driver(&ice_driver);
2263940b61afSAnirudh Venkataramanan 	destroy_workqueue(ice_wq);
2264837f08fdSAnirudh Venkataramanan 	pr_info("module unloaded\n");
2265837f08fdSAnirudh Venkataramanan }
2266837f08fdSAnirudh Venkataramanan module_exit(ice_module_exit);
22673a858ba3SAnirudh Venkataramanan 
22683a858ba3SAnirudh Venkataramanan /**
2269e94d4478SAnirudh Venkataramanan  * ice_set_mac_address - NDO callback to set mac address
2270e94d4478SAnirudh Venkataramanan  * @netdev: network interface device structure
2271e94d4478SAnirudh Venkataramanan  * @pi: pointer to an address structure
2272e94d4478SAnirudh Venkataramanan  *
2273e94d4478SAnirudh Venkataramanan  * Returns 0 on success, negative on failure
2274e94d4478SAnirudh Venkataramanan  */
2275e94d4478SAnirudh Venkataramanan static int ice_set_mac_address(struct net_device *netdev, void *pi)
2276e94d4478SAnirudh Venkataramanan {
2277e94d4478SAnirudh Venkataramanan 	struct ice_netdev_priv *np = netdev_priv(netdev);
2278e94d4478SAnirudh Venkataramanan 	struct ice_vsi *vsi = np->vsi;
2279e94d4478SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
2280e94d4478SAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
2281e94d4478SAnirudh Venkataramanan 	struct sockaddr *addr = pi;
2282e94d4478SAnirudh Venkataramanan 	enum ice_status status;
2283e94d4478SAnirudh Venkataramanan 	LIST_HEAD(a_mac_list);
2284e94d4478SAnirudh Venkataramanan 	LIST_HEAD(r_mac_list);
2285e94d4478SAnirudh Venkataramanan 	u8 flags = 0;
2286e94d4478SAnirudh Venkataramanan 	int err;
2287e94d4478SAnirudh Venkataramanan 	u8 *mac;
2288e94d4478SAnirudh Venkataramanan 
2289e94d4478SAnirudh Venkataramanan 	mac = (u8 *)addr->sa_data;
2290e94d4478SAnirudh Venkataramanan 
2291e94d4478SAnirudh Venkataramanan 	if (!is_valid_ether_addr(mac))
2292e94d4478SAnirudh Venkataramanan 		return -EADDRNOTAVAIL;
2293e94d4478SAnirudh Venkataramanan 
2294e94d4478SAnirudh Venkataramanan 	if (ether_addr_equal(netdev->dev_addr, mac)) {
2295e94d4478SAnirudh Venkataramanan 		netdev_warn(netdev, "already using mac %pM\n", mac);
2296e94d4478SAnirudh Venkataramanan 		return 0;
2297e94d4478SAnirudh Venkataramanan 	}
2298e94d4478SAnirudh Venkataramanan 
2299e94d4478SAnirudh Venkataramanan 	if (test_bit(__ICE_DOWN, pf->state) ||
23005df7e45dSDave Ertman 	    ice_is_reset_in_progress(pf->state)) {
2301e94d4478SAnirudh Venkataramanan 		netdev_err(netdev, "can't set mac %pM. device not ready\n",
2302e94d4478SAnirudh Venkataramanan 			   mac);
2303e94d4478SAnirudh Venkataramanan 		return -EBUSY;
2304e94d4478SAnirudh Venkataramanan 	}
2305e94d4478SAnirudh Venkataramanan 
2306e94d4478SAnirudh Venkataramanan 	/* When we change the mac address we also have to change the mac address
2307e94d4478SAnirudh Venkataramanan 	 * based filter rules that were created previously for the old mac
2308e94d4478SAnirudh Venkataramanan 	 * address. So first, we remove the old filter rule using ice_remove_mac
2309e94d4478SAnirudh Venkataramanan 	 * and then create a new filter rule using ice_add_mac. Note that for
2310e94d4478SAnirudh Venkataramanan 	 * both these operations, we first need to form a "list" of mac
2311e94d4478SAnirudh Venkataramanan 	 * addresses (even though in this case, we have only 1 mac address to be
2312e94d4478SAnirudh Venkataramanan 	 * added/removed) and this done using ice_add_mac_to_list. Depending on
2313e94d4478SAnirudh Venkataramanan 	 * the ensuing operation this "list" of mac addresses is either to be
2314e94d4478SAnirudh Venkataramanan 	 * added or removed from the filter.
2315e94d4478SAnirudh Venkataramanan 	 */
2316e94d4478SAnirudh Venkataramanan 	err = ice_add_mac_to_list(vsi, &r_mac_list, netdev->dev_addr);
2317e94d4478SAnirudh Venkataramanan 	if (err) {
2318e94d4478SAnirudh Venkataramanan 		err = -EADDRNOTAVAIL;
2319e94d4478SAnirudh Venkataramanan 		goto free_lists;
2320e94d4478SAnirudh Venkataramanan 	}
2321e94d4478SAnirudh Venkataramanan 
2322e94d4478SAnirudh Venkataramanan 	status = ice_remove_mac(hw, &r_mac_list);
2323e94d4478SAnirudh Venkataramanan 	if (status) {
2324e94d4478SAnirudh Venkataramanan 		err = -EADDRNOTAVAIL;
2325e94d4478SAnirudh Venkataramanan 		goto free_lists;
2326e94d4478SAnirudh Venkataramanan 	}
2327e94d4478SAnirudh Venkataramanan 
2328e94d4478SAnirudh Venkataramanan 	err = ice_add_mac_to_list(vsi, &a_mac_list, mac);
2329e94d4478SAnirudh Venkataramanan 	if (err) {
2330e94d4478SAnirudh Venkataramanan 		err = -EADDRNOTAVAIL;
2331e94d4478SAnirudh Venkataramanan 		goto free_lists;
2332e94d4478SAnirudh Venkataramanan 	}
2333e94d4478SAnirudh Venkataramanan 
2334e94d4478SAnirudh Venkataramanan 	status = ice_add_mac(hw, &a_mac_list);
2335e94d4478SAnirudh Venkataramanan 	if (status) {
2336e94d4478SAnirudh Venkataramanan 		err = -EADDRNOTAVAIL;
2337e94d4478SAnirudh Venkataramanan 		goto free_lists;
2338e94d4478SAnirudh Venkataramanan 	}
2339e94d4478SAnirudh Venkataramanan 
2340e94d4478SAnirudh Venkataramanan free_lists:
2341e94d4478SAnirudh Venkataramanan 	/* free list entries */
2342e94d4478SAnirudh Venkataramanan 	ice_free_fltr_list(&pf->pdev->dev, &r_mac_list);
2343e94d4478SAnirudh Venkataramanan 	ice_free_fltr_list(&pf->pdev->dev, &a_mac_list);
2344e94d4478SAnirudh Venkataramanan 
2345e94d4478SAnirudh Venkataramanan 	if (err) {
2346e94d4478SAnirudh Venkataramanan 		netdev_err(netdev, "can't set mac %pM. filter update failed\n",
2347e94d4478SAnirudh Venkataramanan 			   mac);
2348e94d4478SAnirudh Venkataramanan 		return err;
2349e94d4478SAnirudh Venkataramanan 	}
2350e94d4478SAnirudh Venkataramanan 
2351e94d4478SAnirudh Venkataramanan 	/* change the netdev's mac address */
2352e94d4478SAnirudh Venkataramanan 	memcpy(netdev->dev_addr, mac, netdev->addr_len);
2353e94d4478SAnirudh Venkataramanan 	netdev_dbg(vsi->netdev, "updated mac address to %pM\n",
2354e94d4478SAnirudh Venkataramanan 		   netdev->dev_addr);
2355e94d4478SAnirudh Venkataramanan 
2356e94d4478SAnirudh Venkataramanan 	/* write new mac address to the firmware */
2357e94d4478SAnirudh Venkataramanan 	flags = ICE_AQC_MAN_MAC_UPDATE_LAA_WOL;
2358e94d4478SAnirudh Venkataramanan 	status = ice_aq_manage_mac_write(hw, mac, flags, NULL);
2359e94d4478SAnirudh Venkataramanan 	if (status) {
2360e94d4478SAnirudh Venkataramanan 		netdev_err(netdev, "can't set mac %pM. write to firmware failed.\n",
2361e94d4478SAnirudh Venkataramanan 			   mac);
2362e94d4478SAnirudh Venkataramanan 	}
2363e94d4478SAnirudh Venkataramanan 	return 0;
2364e94d4478SAnirudh Venkataramanan }
2365e94d4478SAnirudh Venkataramanan 
2366e94d4478SAnirudh Venkataramanan /**
2367e94d4478SAnirudh Venkataramanan  * ice_set_rx_mode - NDO callback to set the netdev filters
2368e94d4478SAnirudh Venkataramanan  * @netdev: network interface device structure
2369e94d4478SAnirudh Venkataramanan  */
2370e94d4478SAnirudh Venkataramanan static void ice_set_rx_mode(struct net_device *netdev)
2371e94d4478SAnirudh Venkataramanan {
2372e94d4478SAnirudh Venkataramanan 	struct ice_netdev_priv *np = netdev_priv(netdev);
2373e94d4478SAnirudh Venkataramanan 	struct ice_vsi *vsi = np->vsi;
2374e94d4478SAnirudh Venkataramanan 
2375e94d4478SAnirudh Venkataramanan 	if (!vsi)
2376e94d4478SAnirudh Venkataramanan 		return;
2377e94d4478SAnirudh Venkataramanan 
2378e94d4478SAnirudh Venkataramanan 	/* Set the flags to synchronize filters
2379e94d4478SAnirudh Venkataramanan 	 * ndo_set_rx_mode may be triggered even without a change in netdev
2380e94d4478SAnirudh Venkataramanan 	 * flags
2381e94d4478SAnirudh Venkataramanan 	 */
2382e94d4478SAnirudh Venkataramanan 	set_bit(ICE_VSI_FLAG_UMAC_FLTR_CHANGED, vsi->flags);
2383e94d4478SAnirudh Venkataramanan 	set_bit(ICE_VSI_FLAG_MMAC_FLTR_CHANGED, vsi->flags);
2384e94d4478SAnirudh Venkataramanan 	set_bit(ICE_FLAG_FLTR_SYNC, vsi->back->flags);
2385e94d4478SAnirudh Venkataramanan 
2386e94d4478SAnirudh Venkataramanan 	/* schedule our worker thread which will take care of
2387e94d4478SAnirudh Venkataramanan 	 * applying the new filter changes
2388e94d4478SAnirudh Venkataramanan 	 */
2389e94d4478SAnirudh Venkataramanan 	ice_service_task_schedule(vsi->back);
2390e94d4478SAnirudh Venkataramanan }
2391e94d4478SAnirudh Venkataramanan 
2392e94d4478SAnirudh Venkataramanan /**
2393e94d4478SAnirudh Venkataramanan  * ice_fdb_add - add an entry to the hardware database
2394e94d4478SAnirudh Venkataramanan  * @ndm: the input from the stack
2395e94d4478SAnirudh Venkataramanan  * @tb: pointer to array of nladdr (unused)
2396e94d4478SAnirudh Venkataramanan  * @dev: the net device pointer
2397e94d4478SAnirudh Venkataramanan  * @addr: the MAC address entry being added
2398e94d4478SAnirudh Venkataramanan  * @vid: VLAN id
2399e94d4478SAnirudh Venkataramanan  * @flags: instructions from stack about fdb operation
2400e94d4478SAnirudh Venkataramanan  */
2401e94d4478SAnirudh Venkataramanan static int ice_fdb_add(struct ndmsg *ndm, struct nlattr __always_unused *tb[],
2402e94d4478SAnirudh Venkataramanan 		       struct net_device *dev, const unsigned char *addr,
2403e94d4478SAnirudh Venkataramanan 		       u16 vid, u16 flags)
2404e94d4478SAnirudh Venkataramanan {
2405e94d4478SAnirudh Venkataramanan 	int err;
2406e94d4478SAnirudh Venkataramanan 
2407e94d4478SAnirudh Venkataramanan 	if (vid) {
2408e94d4478SAnirudh Venkataramanan 		netdev_err(dev, "VLANs aren't supported yet for dev_uc|mc_add()\n");
2409e94d4478SAnirudh Venkataramanan 		return -EINVAL;
2410e94d4478SAnirudh Venkataramanan 	}
2411e94d4478SAnirudh Venkataramanan 	if (ndm->ndm_state && !(ndm->ndm_state & NUD_PERMANENT)) {
2412e94d4478SAnirudh Venkataramanan 		netdev_err(dev, "FDB only supports static addresses\n");
2413e94d4478SAnirudh Venkataramanan 		return -EINVAL;
2414e94d4478SAnirudh Venkataramanan 	}
2415e94d4478SAnirudh Venkataramanan 
2416e94d4478SAnirudh Venkataramanan 	if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr))
2417e94d4478SAnirudh Venkataramanan 		err = dev_uc_add_excl(dev, addr);
2418e94d4478SAnirudh Venkataramanan 	else if (is_multicast_ether_addr(addr))
2419e94d4478SAnirudh Venkataramanan 		err = dev_mc_add_excl(dev, addr);
2420e94d4478SAnirudh Venkataramanan 	else
2421e94d4478SAnirudh Venkataramanan 		err = -EINVAL;
2422e94d4478SAnirudh Venkataramanan 
2423e94d4478SAnirudh Venkataramanan 	/* Only return duplicate errors if NLM_F_EXCL is set */
2424e94d4478SAnirudh Venkataramanan 	if (err == -EEXIST && !(flags & NLM_F_EXCL))
2425e94d4478SAnirudh Venkataramanan 		err = 0;
2426e94d4478SAnirudh Venkataramanan 
2427e94d4478SAnirudh Venkataramanan 	return err;
2428e94d4478SAnirudh Venkataramanan }
2429e94d4478SAnirudh Venkataramanan 
2430e94d4478SAnirudh Venkataramanan /**
2431e94d4478SAnirudh Venkataramanan  * ice_fdb_del - delete an entry from the hardware database
2432e94d4478SAnirudh Venkataramanan  * @ndm: the input from the stack
2433e94d4478SAnirudh Venkataramanan  * @tb: pointer to array of nladdr (unused)
2434e94d4478SAnirudh Venkataramanan  * @dev: the net device pointer
2435e94d4478SAnirudh Venkataramanan  * @addr: the MAC address entry being added
2436e94d4478SAnirudh Venkataramanan  * @vid: VLAN id
2437e94d4478SAnirudh Venkataramanan  */
2438e94d4478SAnirudh Venkataramanan static int ice_fdb_del(struct ndmsg *ndm, __always_unused struct nlattr *tb[],
2439e94d4478SAnirudh Venkataramanan 		       struct net_device *dev, const unsigned char *addr,
2440e94d4478SAnirudh Venkataramanan 		       __always_unused u16 vid)
2441e94d4478SAnirudh Venkataramanan {
2442e94d4478SAnirudh Venkataramanan 	int err;
2443e94d4478SAnirudh Venkataramanan 
2444e94d4478SAnirudh Venkataramanan 	if (ndm->ndm_state & NUD_PERMANENT) {
2445e94d4478SAnirudh Venkataramanan 		netdev_err(dev, "FDB only supports static addresses\n");
2446e94d4478SAnirudh Venkataramanan 		return -EINVAL;
2447e94d4478SAnirudh Venkataramanan 	}
2448e94d4478SAnirudh Venkataramanan 
2449e94d4478SAnirudh Venkataramanan 	if (is_unicast_ether_addr(addr))
2450e94d4478SAnirudh Venkataramanan 		err = dev_uc_del(dev, addr);
2451e94d4478SAnirudh Venkataramanan 	else if (is_multicast_ether_addr(addr))
2452e94d4478SAnirudh Venkataramanan 		err = dev_mc_del(dev, addr);
2453e94d4478SAnirudh Venkataramanan 	else
2454e94d4478SAnirudh Venkataramanan 		err = -EINVAL;
2455e94d4478SAnirudh Venkataramanan 
2456e94d4478SAnirudh Venkataramanan 	return err;
2457e94d4478SAnirudh Venkataramanan }
2458e94d4478SAnirudh Venkataramanan 
2459e94d4478SAnirudh Venkataramanan /**
2460d76a60baSAnirudh Venkataramanan  * ice_set_features - set the netdev feature flags
2461d76a60baSAnirudh Venkataramanan  * @netdev: ptr to the netdev being adjusted
2462d76a60baSAnirudh Venkataramanan  * @features: the feature set that the stack is suggesting
2463d76a60baSAnirudh Venkataramanan  */
2464d76a60baSAnirudh Venkataramanan static int ice_set_features(struct net_device *netdev,
2465d76a60baSAnirudh Venkataramanan 			    netdev_features_t features)
2466d76a60baSAnirudh Venkataramanan {
2467d76a60baSAnirudh Venkataramanan 	struct ice_netdev_priv *np = netdev_priv(netdev);
2468d76a60baSAnirudh Venkataramanan 	struct ice_vsi *vsi = np->vsi;
2469d76a60baSAnirudh Venkataramanan 	int ret = 0;
2470d76a60baSAnirudh Venkataramanan 
2471492af0abSMd Fahad Iqbal Polash 	if (features & NETIF_F_RXHASH && !(netdev->features & NETIF_F_RXHASH))
2472492af0abSMd Fahad Iqbal Polash 		ret = ice_vsi_manage_rss_lut(vsi, true);
2473492af0abSMd Fahad Iqbal Polash 	else if (!(features & NETIF_F_RXHASH) &&
2474492af0abSMd Fahad Iqbal Polash 		 netdev->features & NETIF_F_RXHASH)
2475492af0abSMd Fahad Iqbal Polash 		ret = ice_vsi_manage_rss_lut(vsi, false);
2476492af0abSMd Fahad Iqbal Polash 
2477d76a60baSAnirudh Venkataramanan 	if ((features & NETIF_F_HW_VLAN_CTAG_RX) &&
2478d76a60baSAnirudh Venkataramanan 	    !(netdev->features & NETIF_F_HW_VLAN_CTAG_RX))
2479d76a60baSAnirudh Venkataramanan 		ret = ice_vsi_manage_vlan_stripping(vsi, true);
2480d76a60baSAnirudh Venkataramanan 	else if (!(features & NETIF_F_HW_VLAN_CTAG_RX) &&
2481d76a60baSAnirudh Venkataramanan 		 (netdev->features & NETIF_F_HW_VLAN_CTAG_RX))
2482d76a60baSAnirudh Venkataramanan 		ret = ice_vsi_manage_vlan_stripping(vsi, false);
2483d76a60baSAnirudh Venkataramanan 	else if ((features & NETIF_F_HW_VLAN_CTAG_TX) &&
2484d76a60baSAnirudh Venkataramanan 		 !(netdev->features & NETIF_F_HW_VLAN_CTAG_TX))
2485d76a60baSAnirudh Venkataramanan 		ret = ice_vsi_manage_vlan_insertion(vsi);
2486d76a60baSAnirudh Venkataramanan 	else if (!(features & NETIF_F_HW_VLAN_CTAG_TX) &&
2487d76a60baSAnirudh Venkataramanan 		 (netdev->features & NETIF_F_HW_VLAN_CTAG_TX))
2488d76a60baSAnirudh Venkataramanan 		ret = ice_vsi_manage_vlan_insertion(vsi);
2489d76a60baSAnirudh Venkataramanan 
2490d76a60baSAnirudh Venkataramanan 	return ret;
2491d76a60baSAnirudh Venkataramanan }
2492d76a60baSAnirudh Venkataramanan 
2493d76a60baSAnirudh Venkataramanan /**
2494d76a60baSAnirudh Venkataramanan  * ice_vsi_vlan_setup - Setup vlan offload properties on a VSI
2495d76a60baSAnirudh Venkataramanan  * @vsi: VSI to setup vlan properties for
2496d76a60baSAnirudh Venkataramanan  */
2497d76a60baSAnirudh Venkataramanan static int ice_vsi_vlan_setup(struct ice_vsi *vsi)
2498d76a60baSAnirudh Venkataramanan {
2499d76a60baSAnirudh Venkataramanan 	int ret = 0;
2500d76a60baSAnirudh Venkataramanan 
2501d76a60baSAnirudh Venkataramanan 	if (vsi->netdev->features & NETIF_F_HW_VLAN_CTAG_RX)
2502d76a60baSAnirudh Venkataramanan 		ret = ice_vsi_manage_vlan_stripping(vsi, true);
2503d76a60baSAnirudh Venkataramanan 	if (vsi->netdev->features & NETIF_F_HW_VLAN_CTAG_TX)
2504d76a60baSAnirudh Venkataramanan 		ret = ice_vsi_manage_vlan_insertion(vsi);
2505d76a60baSAnirudh Venkataramanan 
2506d76a60baSAnirudh Venkataramanan 	return ret;
2507d76a60baSAnirudh Venkataramanan }
2508d76a60baSAnirudh Venkataramanan 
2509d76a60baSAnirudh Venkataramanan /**
2510d76a60baSAnirudh Venkataramanan  * ice_restore_vlan - Reinstate VLANs when vsi/netdev comes back up
2511d76a60baSAnirudh Venkataramanan  * @vsi: the VSI being brought back up
2512d76a60baSAnirudh Venkataramanan  */
2513d76a60baSAnirudh Venkataramanan static int ice_restore_vlan(struct ice_vsi *vsi)
2514d76a60baSAnirudh Venkataramanan {
2515d76a60baSAnirudh Venkataramanan 	int err;
2516d76a60baSAnirudh Venkataramanan 	u16 vid;
2517d76a60baSAnirudh Venkataramanan 
2518d76a60baSAnirudh Venkataramanan 	if (!vsi->netdev)
2519d76a60baSAnirudh Venkataramanan 		return -EINVAL;
2520d76a60baSAnirudh Venkataramanan 
2521d76a60baSAnirudh Venkataramanan 	err = ice_vsi_vlan_setup(vsi);
2522d76a60baSAnirudh Venkataramanan 	if (err)
2523d76a60baSAnirudh Venkataramanan 		return err;
2524d76a60baSAnirudh Venkataramanan 
2525d76a60baSAnirudh Venkataramanan 	for_each_set_bit(vid, vsi->active_vlans, VLAN_N_VID) {
2526d76a60baSAnirudh Venkataramanan 		err = ice_vlan_rx_add_vid(vsi->netdev, htons(ETH_P_8021Q), vid);
2527d76a60baSAnirudh Venkataramanan 		if (err)
2528d76a60baSAnirudh Venkataramanan 			break;
2529d76a60baSAnirudh Venkataramanan 	}
2530d76a60baSAnirudh Venkataramanan 
2531d76a60baSAnirudh Venkataramanan 	return err;
2532d76a60baSAnirudh Venkataramanan }
2533d76a60baSAnirudh Venkataramanan 
2534d76a60baSAnirudh Venkataramanan /**
2535cdedef59SAnirudh Venkataramanan  * ice_vsi_cfg - Setup the VSI
2536cdedef59SAnirudh Venkataramanan  * @vsi: the VSI being configured
2537cdedef59SAnirudh Venkataramanan  *
2538cdedef59SAnirudh Venkataramanan  * Return 0 on success and negative value on error
2539cdedef59SAnirudh Venkataramanan  */
2540cdedef59SAnirudh Venkataramanan static int ice_vsi_cfg(struct ice_vsi *vsi)
2541cdedef59SAnirudh Venkataramanan {
2542cdedef59SAnirudh Venkataramanan 	int err;
2543cdedef59SAnirudh Venkataramanan 
2544c7f2c42bSAnirudh Venkataramanan 	if (vsi->netdev) {
2545e94d4478SAnirudh Venkataramanan 		ice_set_rx_mode(vsi->netdev);
2546d76a60baSAnirudh Venkataramanan 		err = ice_restore_vlan(vsi);
2547d76a60baSAnirudh Venkataramanan 		if (err)
2548d76a60baSAnirudh Venkataramanan 			return err;
2549c7f2c42bSAnirudh Venkataramanan 	}
2550d76a60baSAnirudh Venkataramanan 
2551cdedef59SAnirudh Venkataramanan 	err = ice_vsi_cfg_txqs(vsi);
2552cdedef59SAnirudh Venkataramanan 	if (!err)
2553cdedef59SAnirudh Venkataramanan 		err = ice_vsi_cfg_rxqs(vsi);
2554cdedef59SAnirudh Venkataramanan 
2555cdedef59SAnirudh Venkataramanan 	return err;
2556cdedef59SAnirudh Venkataramanan }
2557cdedef59SAnirudh Venkataramanan 
2558cdedef59SAnirudh Venkataramanan /**
25592b245cb2SAnirudh Venkataramanan  * ice_napi_enable_all - Enable NAPI for all q_vectors in the VSI
25602b245cb2SAnirudh Venkataramanan  * @vsi: the VSI being configured
25612b245cb2SAnirudh Venkataramanan  */
25622b245cb2SAnirudh Venkataramanan static void ice_napi_enable_all(struct ice_vsi *vsi)
25632b245cb2SAnirudh Venkataramanan {
25642b245cb2SAnirudh Venkataramanan 	int q_idx;
25652b245cb2SAnirudh Venkataramanan 
25662b245cb2SAnirudh Venkataramanan 	if (!vsi->netdev)
25672b245cb2SAnirudh Venkataramanan 		return;
25682b245cb2SAnirudh Venkataramanan 
25692b245cb2SAnirudh Venkataramanan 	for (q_idx = 0; q_idx < vsi->num_q_vectors; q_idx++)
25702b245cb2SAnirudh Venkataramanan 		napi_enable(&vsi->q_vectors[q_idx]->napi);
25712b245cb2SAnirudh Venkataramanan }
25722b245cb2SAnirudh Venkataramanan 
25732b245cb2SAnirudh Venkataramanan /**
2574cdedef59SAnirudh Venkataramanan  * ice_up_complete - Finish the last steps of bringing up a connection
2575cdedef59SAnirudh Venkataramanan  * @vsi: The VSI being configured
2576cdedef59SAnirudh Venkataramanan  *
2577cdedef59SAnirudh Venkataramanan  * Return 0 on success and negative value on error
2578cdedef59SAnirudh Venkataramanan  */
2579cdedef59SAnirudh Venkataramanan static int ice_up_complete(struct ice_vsi *vsi)
2580cdedef59SAnirudh Venkataramanan {
2581cdedef59SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
2582cdedef59SAnirudh Venkataramanan 	int err;
2583cdedef59SAnirudh Venkataramanan 
2584cdedef59SAnirudh Venkataramanan 	if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags))
2585cdedef59SAnirudh Venkataramanan 		ice_vsi_cfg_msix(vsi);
2586cdedef59SAnirudh Venkataramanan 	else
2587cdedef59SAnirudh Venkataramanan 		return -ENOTSUPP;
2588cdedef59SAnirudh Venkataramanan 
2589cdedef59SAnirudh Venkataramanan 	/* Enable only Rx rings, Tx rings were enabled by the FW when the
2590cdedef59SAnirudh Venkataramanan 	 * Tx queue group list was configured and the context bits were
2591cdedef59SAnirudh Venkataramanan 	 * programmed using ice_vsi_cfg_txqs
2592cdedef59SAnirudh Venkataramanan 	 */
2593cdedef59SAnirudh Venkataramanan 	err = ice_vsi_start_rx_rings(vsi);
2594cdedef59SAnirudh Venkataramanan 	if (err)
2595cdedef59SAnirudh Venkataramanan 		return err;
2596cdedef59SAnirudh Venkataramanan 
2597cdedef59SAnirudh Venkataramanan 	clear_bit(__ICE_DOWN, vsi->state);
25982b245cb2SAnirudh Venkataramanan 	ice_napi_enable_all(vsi);
2599cdedef59SAnirudh Venkataramanan 	ice_vsi_ena_irq(vsi);
2600cdedef59SAnirudh Venkataramanan 
2601cdedef59SAnirudh Venkataramanan 	if (vsi->port_info &&
2602cdedef59SAnirudh Venkataramanan 	    (vsi->port_info->phy.link_info.link_info & ICE_AQ_LINK_UP) &&
2603cdedef59SAnirudh Venkataramanan 	    vsi->netdev) {
2604cdedef59SAnirudh Venkataramanan 		ice_print_link_msg(vsi, true);
2605cdedef59SAnirudh Venkataramanan 		netif_tx_start_all_queues(vsi->netdev);
2606cdedef59SAnirudh Venkataramanan 		netif_carrier_on(vsi->netdev);
2607cdedef59SAnirudh Venkataramanan 	}
2608cdedef59SAnirudh Venkataramanan 
2609cdedef59SAnirudh Venkataramanan 	ice_service_task_schedule(pf);
2610cdedef59SAnirudh Venkataramanan 
2611cdedef59SAnirudh Venkataramanan 	return err;
2612cdedef59SAnirudh Venkataramanan }
2613cdedef59SAnirudh Venkataramanan 
2614cdedef59SAnirudh Venkataramanan /**
2615fcea6f3dSAnirudh Venkataramanan  * ice_up - Bring the connection back up after being down
2616fcea6f3dSAnirudh Venkataramanan  * @vsi: VSI being configured
2617fcea6f3dSAnirudh Venkataramanan  */
2618fcea6f3dSAnirudh Venkataramanan int ice_up(struct ice_vsi *vsi)
2619fcea6f3dSAnirudh Venkataramanan {
2620fcea6f3dSAnirudh Venkataramanan 	int err;
2621fcea6f3dSAnirudh Venkataramanan 
2622fcea6f3dSAnirudh Venkataramanan 	err = ice_vsi_cfg(vsi);
2623fcea6f3dSAnirudh Venkataramanan 	if (!err)
2624fcea6f3dSAnirudh Venkataramanan 		err = ice_up_complete(vsi);
2625fcea6f3dSAnirudh Venkataramanan 
2626fcea6f3dSAnirudh Venkataramanan 	return err;
2627fcea6f3dSAnirudh Venkataramanan }
2628fcea6f3dSAnirudh Venkataramanan 
2629fcea6f3dSAnirudh Venkataramanan /**
2630fcea6f3dSAnirudh Venkataramanan  * ice_fetch_u64_stats_per_ring - get packets and bytes stats per ring
2631fcea6f3dSAnirudh Venkataramanan  * @ring: Tx or Rx ring to read stats from
2632fcea6f3dSAnirudh Venkataramanan  * @pkts: packets stats counter
2633fcea6f3dSAnirudh Venkataramanan  * @bytes: bytes stats counter
2634fcea6f3dSAnirudh Venkataramanan  *
2635fcea6f3dSAnirudh Venkataramanan  * This function fetches stats from the ring considering the atomic operations
2636fcea6f3dSAnirudh Venkataramanan  * that needs to be performed to read u64 values in 32 bit machine.
2637fcea6f3dSAnirudh Venkataramanan  */
2638fcea6f3dSAnirudh Venkataramanan static void ice_fetch_u64_stats_per_ring(struct ice_ring *ring, u64 *pkts,
2639fcea6f3dSAnirudh Venkataramanan 					 u64 *bytes)
2640fcea6f3dSAnirudh Venkataramanan {
2641fcea6f3dSAnirudh Venkataramanan 	unsigned int start;
2642fcea6f3dSAnirudh Venkataramanan 	*pkts = 0;
2643fcea6f3dSAnirudh Venkataramanan 	*bytes = 0;
2644fcea6f3dSAnirudh Venkataramanan 
2645fcea6f3dSAnirudh Venkataramanan 	if (!ring)
2646fcea6f3dSAnirudh Venkataramanan 		return;
2647fcea6f3dSAnirudh Venkataramanan 	do {
2648fcea6f3dSAnirudh Venkataramanan 		start = u64_stats_fetch_begin_irq(&ring->syncp);
2649fcea6f3dSAnirudh Venkataramanan 		*pkts = ring->stats.pkts;
2650fcea6f3dSAnirudh Venkataramanan 		*bytes = ring->stats.bytes;
2651fcea6f3dSAnirudh Venkataramanan 	} while (u64_stats_fetch_retry_irq(&ring->syncp, start));
2652fcea6f3dSAnirudh Venkataramanan }
2653fcea6f3dSAnirudh Venkataramanan 
2654fcea6f3dSAnirudh Venkataramanan /**
2655fcea6f3dSAnirudh Venkataramanan  * ice_update_vsi_ring_stats - Update VSI stats counters
2656fcea6f3dSAnirudh Venkataramanan  * @vsi: the VSI to be updated
2657fcea6f3dSAnirudh Venkataramanan  */
2658fcea6f3dSAnirudh Venkataramanan static void ice_update_vsi_ring_stats(struct ice_vsi *vsi)
2659fcea6f3dSAnirudh Venkataramanan {
2660fcea6f3dSAnirudh Venkataramanan 	struct rtnl_link_stats64 *vsi_stats = &vsi->net_stats;
2661fcea6f3dSAnirudh Venkataramanan 	struct ice_ring *ring;
2662fcea6f3dSAnirudh Venkataramanan 	u64 pkts, bytes;
2663fcea6f3dSAnirudh Venkataramanan 	int i;
2664fcea6f3dSAnirudh Venkataramanan 
2665fcea6f3dSAnirudh Venkataramanan 	/* reset netdev stats */
2666fcea6f3dSAnirudh Venkataramanan 	vsi_stats->tx_packets = 0;
2667fcea6f3dSAnirudh Venkataramanan 	vsi_stats->tx_bytes = 0;
2668fcea6f3dSAnirudh Venkataramanan 	vsi_stats->rx_packets = 0;
2669fcea6f3dSAnirudh Venkataramanan 	vsi_stats->rx_bytes = 0;
2670fcea6f3dSAnirudh Venkataramanan 
2671fcea6f3dSAnirudh Venkataramanan 	/* reset non-netdev (extended) stats */
2672fcea6f3dSAnirudh Venkataramanan 	vsi->tx_restart = 0;
2673fcea6f3dSAnirudh Venkataramanan 	vsi->tx_busy = 0;
2674fcea6f3dSAnirudh Venkataramanan 	vsi->tx_linearize = 0;
2675fcea6f3dSAnirudh Venkataramanan 	vsi->rx_buf_failed = 0;
2676fcea6f3dSAnirudh Venkataramanan 	vsi->rx_page_failed = 0;
2677fcea6f3dSAnirudh Venkataramanan 
2678fcea6f3dSAnirudh Venkataramanan 	rcu_read_lock();
2679fcea6f3dSAnirudh Venkataramanan 
2680fcea6f3dSAnirudh Venkataramanan 	/* update Tx rings counters */
2681fcea6f3dSAnirudh Venkataramanan 	ice_for_each_txq(vsi, i) {
2682fcea6f3dSAnirudh Venkataramanan 		ring = READ_ONCE(vsi->tx_rings[i]);
2683fcea6f3dSAnirudh Venkataramanan 		ice_fetch_u64_stats_per_ring(ring, &pkts, &bytes);
2684fcea6f3dSAnirudh Venkataramanan 		vsi_stats->tx_packets += pkts;
2685fcea6f3dSAnirudh Venkataramanan 		vsi_stats->tx_bytes += bytes;
2686fcea6f3dSAnirudh Venkataramanan 		vsi->tx_restart += ring->tx_stats.restart_q;
2687fcea6f3dSAnirudh Venkataramanan 		vsi->tx_busy += ring->tx_stats.tx_busy;
2688fcea6f3dSAnirudh Venkataramanan 		vsi->tx_linearize += ring->tx_stats.tx_linearize;
2689fcea6f3dSAnirudh Venkataramanan 	}
2690fcea6f3dSAnirudh Venkataramanan 
2691fcea6f3dSAnirudh Venkataramanan 	/* update Rx rings counters */
2692fcea6f3dSAnirudh Venkataramanan 	ice_for_each_rxq(vsi, i) {
2693fcea6f3dSAnirudh Venkataramanan 		ring = READ_ONCE(vsi->rx_rings[i]);
2694fcea6f3dSAnirudh Venkataramanan 		ice_fetch_u64_stats_per_ring(ring, &pkts, &bytes);
2695fcea6f3dSAnirudh Venkataramanan 		vsi_stats->rx_packets += pkts;
2696fcea6f3dSAnirudh Venkataramanan 		vsi_stats->rx_bytes += bytes;
2697fcea6f3dSAnirudh Venkataramanan 		vsi->rx_buf_failed += ring->rx_stats.alloc_buf_failed;
2698fcea6f3dSAnirudh Venkataramanan 		vsi->rx_page_failed += ring->rx_stats.alloc_page_failed;
2699fcea6f3dSAnirudh Venkataramanan 	}
2700fcea6f3dSAnirudh Venkataramanan 
2701fcea6f3dSAnirudh Venkataramanan 	rcu_read_unlock();
2702fcea6f3dSAnirudh Venkataramanan }
2703fcea6f3dSAnirudh Venkataramanan 
2704fcea6f3dSAnirudh Venkataramanan /**
2705fcea6f3dSAnirudh Venkataramanan  * ice_update_vsi_stats - Update VSI stats counters
2706fcea6f3dSAnirudh Venkataramanan  * @vsi: the VSI to be updated
2707fcea6f3dSAnirudh Venkataramanan  */
2708fcea6f3dSAnirudh Venkataramanan static void ice_update_vsi_stats(struct ice_vsi *vsi)
2709fcea6f3dSAnirudh Venkataramanan {
2710fcea6f3dSAnirudh Venkataramanan 	struct rtnl_link_stats64 *cur_ns = &vsi->net_stats;
2711fcea6f3dSAnirudh Venkataramanan 	struct ice_eth_stats *cur_es = &vsi->eth_stats;
2712fcea6f3dSAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
2713fcea6f3dSAnirudh Venkataramanan 
2714fcea6f3dSAnirudh Venkataramanan 	if (test_bit(__ICE_DOWN, vsi->state) ||
2715fcea6f3dSAnirudh Venkataramanan 	    test_bit(__ICE_CFG_BUSY, pf->state))
2716fcea6f3dSAnirudh Venkataramanan 		return;
2717fcea6f3dSAnirudh Venkataramanan 
2718fcea6f3dSAnirudh Venkataramanan 	/* get stats as recorded by Tx/Rx rings */
2719fcea6f3dSAnirudh Venkataramanan 	ice_update_vsi_ring_stats(vsi);
2720fcea6f3dSAnirudh Venkataramanan 
2721fcea6f3dSAnirudh Venkataramanan 	/* get VSI stats as recorded by the hardware */
2722fcea6f3dSAnirudh Venkataramanan 	ice_update_eth_stats(vsi);
2723fcea6f3dSAnirudh Venkataramanan 
2724fcea6f3dSAnirudh Venkataramanan 	cur_ns->tx_errors = cur_es->tx_errors;
2725fcea6f3dSAnirudh Venkataramanan 	cur_ns->rx_dropped = cur_es->rx_discards;
2726fcea6f3dSAnirudh Venkataramanan 	cur_ns->tx_dropped = cur_es->tx_discards;
2727fcea6f3dSAnirudh Venkataramanan 	cur_ns->multicast = cur_es->rx_multicast;
2728fcea6f3dSAnirudh Venkataramanan 
2729fcea6f3dSAnirudh Venkataramanan 	/* update some more netdev stats if this is main VSI */
2730fcea6f3dSAnirudh Venkataramanan 	if (vsi->type == ICE_VSI_PF) {
2731fcea6f3dSAnirudh Venkataramanan 		cur_ns->rx_crc_errors = pf->stats.crc_errors;
2732fcea6f3dSAnirudh Venkataramanan 		cur_ns->rx_errors = pf->stats.crc_errors +
2733fcea6f3dSAnirudh Venkataramanan 				    pf->stats.illegal_bytes;
2734fcea6f3dSAnirudh Venkataramanan 		cur_ns->rx_length_errors = pf->stats.rx_len_errors;
2735fcea6f3dSAnirudh Venkataramanan 	}
2736fcea6f3dSAnirudh Venkataramanan }
2737fcea6f3dSAnirudh Venkataramanan 
2738fcea6f3dSAnirudh Venkataramanan /**
2739fcea6f3dSAnirudh Venkataramanan  * ice_update_pf_stats - Update PF port stats counters
2740fcea6f3dSAnirudh Venkataramanan  * @pf: PF whose stats needs to be updated
2741fcea6f3dSAnirudh Venkataramanan  */
2742fcea6f3dSAnirudh Venkataramanan static void ice_update_pf_stats(struct ice_pf *pf)
2743fcea6f3dSAnirudh Venkataramanan {
2744fcea6f3dSAnirudh Venkataramanan 	struct ice_hw_port_stats *prev_ps, *cur_ps;
2745fcea6f3dSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
2746fcea6f3dSAnirudh Venkataramanan 	u8 pf_id;
2747fcea6f3dSAnirudh Venkataramanan 
2748fcea6f3dSAnirudh Venkataramanan 	prev_ps = &pf->stats_prev;
2749fcea6f3dSAnirudh Venkataramanan 	cur_ps = &pf->stats;
2750fcea6f3dSAnirudh Venkataramanan 	pf_id = hw->pf_id;
2751fcea6f3dSAnirudh Venkataramanan 
2752fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_GORCH(pf_id), GLPRT_GORCL(pf_id),
2753fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->eth.rx_bytes,
2754fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->eth.rx_bytes);
2755fcea6f3dSAnirudh Venkataramanan 
2756fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_UPRCH(pf_id), GLPRT_UPRCL(pf_id),
2757fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->eth.rx_unicast,
2758fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->eth.rx_unicast);
2759fcea6f3dSAnirudh Venkataramanan 
2760fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_MPRCH(pf_id), GLPRT_MPRCL(pf_id),
2761fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->eth.rx_multicast,
2762fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->eth.rx_multicast);
2763fcea6f3dSAnirudh Venkataramanan 
2764fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_BPRCH(pf_id), GLPRT_BPRCL(pf_id),
2765fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->eth.rx_broadcast,
2766fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->eth.rx_broadcast);
2767fcea6f3dSAnirudh Venkataramanan 
2768fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_GOTCH(pf_id), GLPRT_GOTCL(pf_id),
2769fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->eth.tx_bytes,
2770fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->eth.tx_bytes);
2771fcea6f3dSAnirudh Venkataramanan 
2772fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_UPTCH(pf_id), GLPRT_UPTCL(pf_id),
2773fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->eth.tx_unicast,
2774fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->eth.tx_unicast);
2775fcea6f3dSAnirudh Venkataramanan 
2776fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_MPTCH(pf_id), GLPRT_MPTCL(pf_id),
2777fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->eth.tx_multicast,
2778fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->eth.tx_multicast);
2779fcea6f3dSAnirudh Venkataramanan 
2780fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_BPTCH(pf_id), GLPRT_BPTCL(pf_id),
2781fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->eth.tx_broadcast,
2782fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->eth.tx_broadcast);
2783fcea6f3dSAnirudh Venkataramanan 
2784fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_TDOLD(pf_id), pf->stat_prev_loaded,
2785fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->tx_dropped_link_down,
2786fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->tx_dropped_link_down);
2787fcea6f3dSAnirudh Venkataramanan 
2788fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PRC64H(pf_id), GLPRT_PRC64L(pf_id),
2789fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->rx_size_64,
2790fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->rx_size_64);
2791fcea6f3dSAnirudh Venkataramanan 
2792fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PRC127H(pf_id), GLPRT_PRC127L(pf_id),
2793fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->rx_size_127,
2794fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->rx_size_127);
2795fcea6f3dSAnirudh Venkataramanan 
2796fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PRC255H(pf_id), GLPRT_PRC255L(pf_id),
2797fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->rx_size_255,
2798fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->rx_size_255);
2799fcea6f3dSAnirudh Venkataramanan 
2800fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PRC511H(pf_id), GLPRT_PRC511L(pf_id),
2801fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->rx_size_511,
2802fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->rx_size_511);
2803fcea6f3dSAnirudh Venkataramanan 
2804fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PRC1023H(pf_id),
2805fcea6f3dSAnirudh Venkataramanan 			  GLPRT_PRC1023L(pf_id), pf->stat_prev_loaded,
2806fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->rx_size_1023, &cur_ps->rx_size_1023);
2807fcea6f3dSAnirudh Venkataramanan 
2808fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PRC1522H(pf_id),
2809fcea6f3dSAnirudh Venkataramanan 			  GLPRT_PRC1522L(pf_id), pf->stat_prev_loaded,
2810fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->rx_size_1522, &cur_ps->rx_size_1522);
2811fcea6f3dSAnirudh Venkataramanan 
2812fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PRC9522H(pf_id),
2813fcea6f3dSAnirudh Venkataramanan 			  GLPRT_PRC9522L(pf_id), pf->stat_prev_loaded,
2814fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->rx_size_big, &cur_ps->rx_size_big);
2815fcea6f3dSAnirudh Venkataramanan 
2816fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PTC64H(pf_id), GLPRT_PTC64L(pf_id),
2817fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->tx_size_64,
2818fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->tx_size_64);
2819fcea6f3dSAnirudh Venkataramanan 
2820fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PTC127H(pf_id), GLPRT_PTC127L(pf_id),
2821fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->tx_size_127,
2822fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->tx_size_127);
2823fcea6f3dSAnirudh Venkataramanan 
2824fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PTC255H(pf_id), GLPRT_PTC255L(pf_id),
2825fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->tx_size_255,
2826fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->tx_size_255);
2827fcea6f3dSAnirudh Venkataramanan 
2828fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PTC511H(pf_id), GLPRT_PTC511L(pf_id),
2829fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->tx_size_511,
2830fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->tx_size_511);
2831fcea6f3dSAnirudh Venkataramanan 
2832fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PTC1023H(pf_id),
2833fcea6f3dSAnirudh Venkataramanan 			  GLPRT_PTC1023L(pf_id), pf->stat_prev_loaded,
2834fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->tx_size_1023, &cur_ps->tx_size_1023);
2835fcea6f3dSAnirudh Venkataramanan 
2836fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PTC1522H(pf_id),
2837fcea6f3dSAnirudh Venkataramanan 			  GLPRT_PTC1522L(pf_id), pf->stat_prev_loaded,
2838fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->tx_size_1522, &cur_ps->tx_size_1522);
2839fcea6f3dSAnirudh Venkataramanan 
2840fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PTC9522H(pf_id),
2841fcea6f3dSAnirudh Venkataramanan 			  GLPRT_PTC9522L(pf_id), pf->stat_prev_loaded,
2842fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->tx_size_big, &cur_ps->tx_size_big);
2843fcea6f3dSAnirudh Venkataramanan 
2844fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_LXONRXC(pf_id), pf->stat_prev_loaded,
2845fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->link_xon_rx, &cur_ps->link_xon_rx);
2846fcea6f3dSAnirudh Venkataramanan 
2847fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_LXOFFRXC(pf_id), pf->stat_prev_loaded,
2848fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->link_xoff_rx, &cur_ps->link_xoff_rx);
2849fcea6f3dSAnirudh Venkataramanan 
2850fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_LXONTXC(pf_id), pf->stat_prev_loaded,
2851fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->link_xon_tx, &cur_ps->link_xon_tx);
2852fcea6f3dSAnirudh Venkataramanan 
2853fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_LXOFFTXC(pf_id), pf->stat_prev_loaded,
2854fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->link_xoff_tx, &cur_ps->link_xoff_tx);
2855fcea6f3dSAnirudh Venkataramanan 
2856fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_CRCERRS(pf_id), pf->stat_prev_loaded,
2857fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->crc_errors, &cur_ps->crc_errors);
2858fcea6f3dSAnirudh Venkataramanan 
2859fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_ILLERRC(pf_id), pf->stat_prev_loaded,
2860fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->illegal_bytes, &cur_ps->illegal_bytes);
2861fcea6f3dSAnirudh Venkataramanan 
2862fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_MLFC(pf_id), pf->stat_prev_loaded,
2863fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->mac_local_faults,
2864fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->mac_local_faults);
2865fcea6f3dSAnirudh Venkataramanan 
2866fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_MRFC(pf_id), pf->stat_prev_loaded,
2867fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->mac_remote_faults,
2868fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->mac_remote_faults);
2869fcea6f3dSAnirudh Venkataramanan 
2870fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_RLEC(pf_id), pf->stat_prev_loaded,
2871fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->rx_len_errors, &cur_ps->rx_len_errors);
2872fcea6f3dSAnirudh Venkataramanan 
2873fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_RUC(pf_id), pf->stat_prev_loaded,
2874fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->rx_undersize, &cur_ps->rx_undersize);
2875fcea6f3dSAnirudh Venkataramanan 
2876fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_RFC(pf_id), pf->stat_prev_loaded,
2877fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->rx_fragments, &cur_ps->rx_fragments);
2878fcea6f3dSAnirudh Venkataramanan 
2879fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_ROC(pf_id), pf->stat_prev_loaded,
2880fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->rx_oversize, &cur_ps->rx_oversize);
2881fcea6f3dSAnirudh Venkataramanan 
2882fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_RJC(pf_id), pf->stat_prev_loaded,
2883fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->rx_jabber, &cur_ps->rx_jabber);
2884fcea6f3dSAnirudh Venkataramanan 
2885fcea6f3dSAnirudh Venkataramanan 	pf->stat_prev_loaded = true;
2886fcea6f3dSAnirudh Venkataramanan }
2887fcea6f3dSAnirudh Venkataramanan 
2888fcea6f3dSAnirudh Venkataramanan /**
2889fcea6f3dSAnirudh Venkataramanan  * ice_get_stats64 - get statistics for network device structure
2890fcea6f3dSAnirudh Venkataramanan  * @netdev: network interface device structure
2891fcea6f3dSAnirudh Venkataramanan  * @stats: main device statistics structure
2892fcea6f3dSAnirudh Venkataramanan  */
2893fcea6f3dSAnirudh Venkataramanan static
2894fcea6f3dSAnirudh Venkataramanan void ice_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
2895fcea6f3dSAnirudh Venkataramanan {
2896fcea6f3dSAnirudh Venkataramanan 	struct ice_netdev_priv *np = netdev_priv(netdev);
2897fcea6f3dSAnirudh Venkataramanan 	struct rtnl_link_stats64 *vsi_stats;
2898fcea6f3dSAnirudh Venkataramanan 	struct ice_vsi *vsi = np->vsi;
2899fcea6f3dSAnirudh Venkataramanan 
2900fcea6f3dSAnirudh Venkataramanan 	vsi_stats = &vsi->net_stats;
2901fcea6f3dSAnirudh Venkataramanan 
2902fcea6f3dSAnirudh Venkataramanan 	if (test_bit(__ICE_DOWN, vsi->state) || !vsi->num_txq || !vsi->num_rxq)
2903fcea6f3dSAnirudh Venkataramanan 		return;
2904fcea6f3dSAnirudh Venkataramanan 	/* netdev packet/byte stats come from ring counter. These are obtained
2905fcea6f3dSAnirudh Venkataramanan 	 * by summing up ring counters (done by ice_update_vsi_ring_stats).
2906fcea6f3dSAnirudh Venkataramanan 	 */
2907fcea6f3dSAnirudh Venkataramanan 	ice_update_vsi_ring_stats(vsi);
2908fcea6f3dSAnirudh Venkataramanan 	stats->tx_packets = vsi_stats->tx_packets;
2909fcea6f3dSAnirudh Venkataramanan 	stats->tx_bytes = vsi_stats->tx_bytes;
2910fcea6f3dSAnirudh Venkataramanan 	stats->rx_packets = vsi_stats->rx_packets;
2911fcea6f3dSAnirudh Venkataramanan 	stats->rx_bytes = vsi_stats->rx_bytes;
2912fcea6f3dSAnirudh Venkataramanan 
2913fcea6f3dSAnirudh Venkataramanan 	/* The rest of the stats can be read from the hardware but instead we
2914fcea6f3dSAnirudh Venkataramanan 	 * just return values that the watchdog task has already obtained from
2915fcea6f3dSAnirudh Venkataramanan 	 * the hardware.
2916fcea6f3dSAnirudh Venkataramanan 	 */
2917fcea6f3dSAnirudh Venkataramanan 	stats->multicast = vsi_stats->multicast;
2918fcea6f3dSAnirudh Venkataramanan 	stats->tx_errors = vsi_stats->tx_errors;
2919fcea6f3dSAnirudh Venkataramanan 	stats->tx_dropped = vsi_stats->tx_dropped;
2920fcea6f3dSAnirudh Venkataramanan 	stats->rx_errors = vsi_stats->rx_errors;
2921fcea6f3dSAnirudh Venkataramanan 	stats->rx_dropped = vsi_stats->rx_dropped;
2922fcea6f3dSAnirudh Venkataramanan 	stats->rx_crc_errors = vsi_stats->rx_crc_errors;
2923fcea6f3dSAnirudh Venkataramanan 	stats->rx_length_errors = vsi_stats->rx_length_errors;
2924fcea6f3dSAnirudh Venkataramanan }
2925fcea6f3dSAnirudh Venkataramanan 
2926fcea6f3dSAnirudh Venkataramanan /**
29272b245cb2SAnirudh Venkataramanan  * ice_napi_disable_all - Disable NAPI for all q_vectors in the VSI
29282b245cb2SAnirudh Venkataramanan  * @vsi: VSI having NAPI disabled
29292b245cb2SAnirudh Venkataramanan  */
29302b245cb2SAnirudh Venkataramanan static void ice_napi_disable_all(struct ice_vsi *vsi)
29312b245cb2SAnirudh Venkataramanan {
29322b245cb2SAnirudh Venkataramanan 	int q_idx;
29332b245cb2SAnirudh Venkataramanan 
29342b245cb2SAnirudh Venkataramanan 	if (!vsi->netdev)
29352b245cb2SAnirudh Venkataramanan 		return;
29362b245cb2SAnirudh Venkataramanan 
29372b245cb2SAnirudh Venkataramanan 	for (q_idx = 0; q_idx < vsi->num_q_vectors; q_idx++)
29382b245cb2SAnirudh Venkataramanan 		napi_disable(&vsi->q_vectors[q_idx]->napi);
29392b245cb2SAnirudh Venkataramanan }
29402b245cb2SAnirudh Venkataramanan 
29412b245cb2SAnirudh Venkataramanan /**
2942cdedef59SAnirudh Venkataramanan  * ice_down - Shutdown the connection
2943cdedef59SAnirudh Venkataramanan  * @vsi: The VSI being stopped
2944cdedef59SAnirudh Venkataramanan  */
2945fcea6f3dSAnirudh Venkataramanan int ice_down(struct ice_vsi *vsi)
2946cdedef59SAnirudh Venkataramanan {
294772adf242SAnirudh Venkataramanan 	int i, tx_err, rx_err;
2948cdedef59SAnirudh Venkataramanan 
2949cdedef59SAnirudh Venkataramanan 	/* Caller of this function is expected to set the
2950cdedef59SAnirudh Venkataramanan 	 * vsi->state __ICE_DOWN bit
2951cdedef59SAnirudh Venkataramanan 	 */
2952cdedef59SAnirudh Venkataramanan 	if (vsi->netdev) {
2953cdedef59SAnirudh Venkataramanan 		netif_carrier_off(vsi->netdev);
2954cdedef59SAnirudh Venkataramanan 		netif_tx_disable(vsi->netdev);
2955cdedef59SAnirudh Venkataramanan 	}
2956cdedef59SAnirudh Venkataramanan 
2957cdedef59SAnirudh Venkataramanan 	ice_vsi_dis_irq(vsi);
295872adf242SAnirudh Venkataramanan 	tx_err = ice_vsi_stop_tx_rings(vsi);
295972adf242SAnirudh Venkataramanan 	if (tx_err)
296072adf242SAnirudh Venkataramanan 		netdev_err(vsi->netdev,
296172adf242SAnirudh Venkataramanan 			   "Failed stop Tx rings, VSI %d error %d\n",
296272adf242SAnirudh Venkataramanan 			   vsi->vsi_num, tx_err);
296372adf242SAnirudh Venkataramanan 
296472adf242SAnirudh Venkataramanan 	rx_err = ice_vsi_stop_rx_rings(vsi);
296572adf242SAnirudh Venkataramanan 	if (rx_err)
296672adf242SAnirudh Venkataramanan 		netdev_err(vsi->netdev,
296772adf242SAnirudh Venkataramanan 			   "Failed stop Rx rings, VSI %d error %d\n",
296872adf242SAnirudh Venkataramanan 			   vsi->vsi_num, rx_err);
296972adf242SAnirudh Venkataramanan 
29702b245cb2SAnirudh Venkataramanan 	ice_napi_disable_all(vsi);
2971cdedef59SAnirudh Venkataramanan 
2972cdedef59SAnirudh Venkataramanan 	ice_for_each_txq(vsi, i)
2973cdedef59SAnirudh Venkataramanan 		ice_clean_tx_ring(vsi->tx_rings[i]);
2974cdedef59SAnirudh Venkataramanan 
2975cdedef59SAnirudh Venkataramanan 	ice_for_each_rxq(vsi, i)
2976cdedef59SAnirudh Venkataramanan 		ice_clean_rx_ring(vsi->rx_rings[i]);
2977cdedef59SAnirudh Venkataramanan 
297872adf242SAnirudh Venkataramanan 	if (tx_err || rx_err) {
297972adf242SAnirudh Venkataramanan 		netdev_err(vsi->netdev,
298072adf242SAnirudh Venkataramanan 			   "Failed to close VSI 0x%04X on switch 0x%04X\n",
2981cdedef59SAnirudh Venkataramanan 			   vsi->vsi_num, vsi->vsw->sw_id);
298272adf242SAnirudh Venkataramanan 		return -EIO;
298372adf242SAnirudh Venkataramanan 	}
298472adf242SAnirudh Venkataramanan 
298572adf242SAnirudh Venkataramanan 	return 0;
2986cdedef59SAnirudh Venkataramanan }
2987cdedef59SAnirudh Venkataramanan 
2988cdedef59SAnirudh Venkataramanan /**
2989cdedef59SAnirudh Venkataramanan  * ice_vsi_setup_tx_rings - Allocate VSI Tx queue resources
2990cdedef59SAnirudh Venkataramanan  * @vsi: VSI having resources allocated
2991cdedef59SAnirudh Venkataramanan  *
2992cdedef59SAnirudh Venkataramanan  * Return 0 on success, negative on failure
2993cdedef59SAnirudh Venkataramanan  */
2994cdedef59SAnirudh Venkataramanan static int ice_vsi_setup_tx_rings(struct ice_vsi *vsi)
2995cdedef59SAnirudh Venkataramanan {
2996dab0588fSJesse Brandeburg 	int i, err = 0;
2997cdedef59SAnirudh Venkataramanan 
2998cdedef59SAnirudh Venkataramanan 	if (!vsi->num_txq) {
2999cdedef59SAnirudh Venkataramanan 		dev_err(&vsi->back->pdev->dev, "VSI %d has 0 Tx queues\n",
3000cdedef59SAnirudh Venkataramanan 			vsi->vsi_num);
3001cdedef59SAnirudh Venkataramanan 		return -EINVAL;
3002cdedef59SAnirudh Venkataramanan 	}
3003cdedef59SAnirudh Venkataramanan 
3004cdedef59SAnirudh Venkataramanan 	ice_for_each_txq(vsi, i) {
300572adf242SAnirudh Venkataramanan 		vsi->tx_rings[i]->netdev = vsi->netdev;
3006cdedef59SAnirudh Venkataramanan 		err = ice_setup_tx_ring(vsi->tx_rings[i]);
3007cdedef59SAnirudh Venkataramanan 		if (err)
3008cdedef59SAnirudh Venkataramanan 			break;
3009cdedef59SAnirudh Venkataramanan 	}
3010cdedef59SAnirudh Venkataramanan 
3011cdedef59SAnirudh Venkataramanan 	return err;
3012cdedef59SAnirudh Venkataramanan }
3013cdedef59SAnirudh Venkataramanan 
3014cdedef59SAnirudh Venkataramanan /**
3015cdedef59SAnirudh Venkataramanan  * ice_vsi_setup_rx_rings - Allocate VSI Rx queue resources
3016cdedef59SAnirudh Venkataramanan  * @vsi: VSI having resources allocated
3017cdedef59SAnirudh Venkataramanan  *
3018cdedef59SAnirudh Venkataramanan  * Return 0 on success, negative on failure
3019cdedef59SAnirudh Venkataramanan  */
3020cdedef59SAnirudh Venkataramanan static int ice_vsi_setup_rx_rings(struct ice_vsi *vsi)
3021cdedef59SAnirudh Venkataramanan {
3022dab0588fSJesse Brandeburg 	int i, err = 0;
3023cdedef59SAnirudh Venkataramanan 
3024cdedef59SAnirudh Venkataramanan 	if (!vsi->num_rxq) {
3025cdedef59SAnirudh Venkataramanan 		dev_err(&vsi->back->pdev->dev, "VSI %d has 0 Rx queues\n",
3026cdedef59SAnirudh Venkataramanan 			vsi->vsi_num);
3027cdedef59SAnirudh Venkataramanan 		return -EINVAL;
3028cdedef59SAnirudh Venkataramanan 	}
3029cdedef59SAnirudh Venkataramanan 
3030cdedef59SAnirudh Venkataramanan 	ice_for_each_rxq(vsi, i) {
303172adf242SAnirudh Venkataramanan 		vsi->rx_rings[i]->netdev = vsi->netdev;
3032cdedef59SAnirudh Venkataramanan 		err = ice_setup_rx_ring(vsi->rx_rings[i]);
3033cdedef59SAnirudh Venkataramanan 		if (err)
3034cdedef59SAnirudh Venkataramanan 			break;
3035cdedef59SAnirudh Venkataramanan 	}
3036cdedef59SAnirudh Venkataramanan 
3037cdedef59SAnirudh Venkataramanan 	return err;
3038cdedef59SAnirudh Venkataramanan }
3039cdedef59SAnirudh Venkataramanan 
3040cdedef59SAnirudh Venkataramanan /**
3041cdedef59SAnirudh Venkataramanan  * ice_vsi_req_irq - Request IRQ from the OS
3042cdedef59SAnirudh Venkataramanan  * @vsi: The VSI IRQ is being requested for
3043cdedef59SAnirudh Venkataramanan  * @basename: name for the vector
3044cdedef59SAnirudh Venkataramanan  *
3045cdedef59SAnirudh Venkataramanan  * Return 0 on success and a negative value on error
3046cdedef59SAnirudh Venkataramanan  */
3047cdedef59SAnirudh Venkataramanan static int ice_vsi_req_irq(struct ice_vsi *vsi, char *basename)
3048cdedef59SAnirudh Venkataramanan {
3049cdedef59SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
3050cdedef59SAnirudh Venkataramanan 	int err = -EINVAL;
3051cdedef59SAnirudh Venkataramanan 
3052cdedef59SAnirudh Venkataramanan 	if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags))
3053cdedef59SAnirudh Venkataramanan 		err = ice_vsi_req_irq_msix(vsi, basename);
3054cdedef59SAnirudh Venkataramanan 
3055cdedef59SAnirudh Venkataramanan 	return err;
3056cdedef59SAnirudh Venkataramanan }
3057cdedef59SAnirudh Venkataramanan 
3058cdedef59SAnirudh Venkataramanan /**
3059cdedef59SAnirudh Venkataramanan  * ice_vsi_open - Called when a network interface is made active
3060cdedef59SAnirudh Venkataramanan  * @vsi: the VSI to open
3061cdedef59SAnirudh Venkataramanan  *
3062cdedef59SAnirudh Venkataramanan  * Initialization of the VSI
3063cdedef59SAnirudh Venkataramanan  *
3064cdedef59SAnirudh Venkataramanan  * Returns 0 on success, negative value on error
3065cdedef59SAnirudh Venkataramanan  */
3066cdedef59SAnirudh Venkataramanan static int ice_vsi_open(struct ice_vsi *vsi)
3067cdedef59SAnirudh Venkataramanan {
3068cdedef59SAnirudh Venkataramanan 	char int_name[ICE_INT_NAME_STR_LEN];
3069cdedef59SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
3070cdedef59SAnirudh Venkataramanan 	int err;
3071cdedef59SAnirudh Venkataramanan 
3072cdedef59SAnirudh Venkataramanan 	/* allocate descriptors */
3073cdedef59SAnirudh Venkataramanan 	err = ice_vsi_setup_tx_rings(vsi);
3074cdedef59SAnirudh Venkataramanan 	if (err)
3075cdedef59SAnirudh Venkataramanan 		goto err_setup_tx;
3076cdedef59SAnirudh Venkataramanan 
3077cdedef59SAnirudh Venkataramanan 	err = ice_vsi_setup_rx_rings(vsi);
3078cdedef59SAnirudh Venkataramanan 	if (err)
3079cdedef59SAnirudh Venkataramanan 		goto err_setup_rx;
3080cdedef59SAnirudh Venkataramanan 
3081cdedef59SAnirudh Venkataramanan 	err = ice_vsi_cfg(vsi);
3082cdedef59SAnirudh Venkataramanan 	if (err)
3083cdedef59SAnirudh Venkataramanan 		goto err_setup_rx;
3084cdedef59SAnirudh Venkataramanan 
3085cdedef59SAnirudh Venkataramanan 	snprintf(int_name, sizeof(int_name) - 1, "%s-%s",
3086cdedef59SAnirudh Venkataramanan 		 dev_driver_string(&pf->pdev->dev), vsi->netdev->name);
3087cdedef59SAnirudh Venkataramanan 	err = ice_vsi_req_irq(vsi, int_name);
3088cdedef59SAnirudh Venkataramanan 	if (err)
3089cdedef59SAnirudh Venkataramanan 		goto err_setup_rx;
3090cdedef59SAnirudh Venkataramanan 
3091cdedef59SAnirudh Venkataramanan 	/* Notify the stack of the actual queue counts. */
3092cdedef59SAnirudh Venkataramanan 	err = netif_set_real_num_tx_queues(vsi->netdev, vsi->num_txq);
3093cdedef59SAnirudh Venkataramanan 	if (err)
3094cdedef59SAnirudh Venkataramanan 		goto err_set_qs;
3095cdedef59SAnirudh Venkataramanan 
3096cdedef59SAnirudh Venkataramanan 	err = netif_set_real_num_rx_queues(vsi->netdev, vsi->num_rxq);
3097cdedef59SAnirudh Venkataramanan 	if (err)
3098cdedef59SAnirudh Venkataramanan 		goto err_set_qs;
3099cdedef59SAnirudh Venkataramanan 
3100cdedef59SAnirudh Venkataramanan 	err = ice_up_complete(vsi);
3101cdedef59SAnirudh Venkataramanan 	if (err)
3102cdedef59SAnirudh Venkataramanan 		goto err_up_complete;
3103cdedef59SAnirudh Venkataramanan 
3104cdedef59SAnirudh Venkataramanan 	return 0;
3105cdedef59SAnirudh Venkataramanan 
3106cdedef59SAnirudh Venkataramanan err_up_complete:
3107cdedef59SAnirudh Venkataramanan 	ice_down(vsi);
3108cdedef59SAnirudh Venkataramanan err_set_qs:
3109cdedef59SAnirudh Venkataramanan 	ice_vsi_free_irq(vsi);
3110cdedef59SAnirudh Venkataramanan err_setup_rx:
3111cdedef59SAnirudh Venkataramanan 	ice_vsi_free_rx_rings(vsi);
3112cdedef59SAnirudh Venkataramanan err_setup_tx:
3113cdedef59SAnirudh Venkataramanan 	ice_vsi_free_tx_rings(vsi);
3114cdedef59SAnirudh Venkataramanan 
3115cdedef59SAnirudh Venkataramanan 	return err;
3116cdedef59SAnirudh Venkataramanan }
3117cdedef59SAnirudh Venkataramanan 
3118cdedef59SAnirudh Venkataramanan /**
31190f9d5027SAnirudh Venkataramanan  * ice_vsi_release_all - Delete all VSIs
31200f9d5027SAnirudh Venkataramanan  * @pf: PF from which all VSIs are being removed
31210f9d5027SAnirudh Venkataramanan  */
31220f9d5027SAnirudh Venkataramanan static void ice_vsi_release_all(struct ice_pf *pf)
31230f9d5027SAnirudh Venkataramanan {
31240f9d5027SAnirudh Venkataramanan 	int err, i;
31250f9d5027SAnirudh Venkataramanan 
31260f9d5027SAnirudh Venkataramanan 	if (!pf->vsi)
31270f9d5027SAnirudh Venkataramanan 		return;
31280f9d5027SAnirudh Venkataramanan 
31290f9d5027SAnirudh Venkataramanan 	for (i = 0; i < pf->num_alloc_vsi; i++) {
31300f9d5027SAnirudh Venkataramanan 		if (!pf->vsi[i])
31310f9d5027SAnirudh Venkataramanan 			continue;
31320f9d5027SAnirudh Venkataramanan 
31330f9d5027SAnirudh Venkataramanan 		err = ice_vsi_release(pf->vsi[i]);
31340f9d5027SAnirudh Venkataramanan 		if (err)
31350f9d5027SAnirudh Venkataramanan 			dev_dbg(&pf->pdev->dev,
31360f9d5027SAnirudh Venkataramanan 				"Failed to release pf->vsi[%d], err %d, vsi_num = %d\n",
31370f9d5027SAnirudh Venkataramanan 				i, err, pf->vsi[i]->vsi_num);
31380f9d5027SAnirudh Venkataramanan 	}
31390f9d5027SAnirudh Venkataramanan }
31400f9d5027SAnirudh Venkataramanan 
31410f9d5027SAnirudh Venkataramanan /**
31420b28b702SAnirudh Venkataramanan  * ice_dis_vsi - pause a VSI
31430b28b702SAnirudh Venkataramanan  * @vsi: the VSI being paused
31440b28b702SAnirudh Venkataramanan  */
31450b28b702SAnirudh Venkataramanan static void ice_dis_vsi(struct ice_vsi *vsi)
31460b28b702SAnirudh Venkataramanan {
31470b28b702SAnirudh Venkataramanan 	if (test_bit(__ICE_DOWN, vsi->state))
31480b28b702SAnirudh Venkataramanan 		return;
31490b28b702SAnirudh Venkataramanan 
31500b28b702SAnirudh Venkataramanan 	set_bit(__ICE_NEEDS_RESTART, vsi->state);
31510b28b702SAnirudh Venkataramanan 
31520b28b702SAnirudh Venkataramanan 	if (vsi->netdev && netif_running(vsi->netdev) &&
31530f9d5027SAnirudh Venkataramanan 	    vsi->type == ICE_VSI_PF) {
31540f9d5027SAnirudh Venkataramanan 		rtnl_lock();
31550b28b702SAnirudh Venkataramanan 		vsi->netdev->netdev_ops->ndo_stop(vsi->netdev);
31560f9d5027SAnirudh Venkataramanan 		rtnl_unlock();
31570f9d5027SAnirudh Venkataramanan 	} else {
31580b28b702SAnirudh Venkataramanan 		ice_vsi_close(vsi);
31590b28b702SAnirudh Venkataramanan 	}
31600f9d5027SAnirudh Venkataramanan }
31610b28b702SAnirudh Venkataramanan 
31620b28b702SAnirudh Venkataramanan /**
31630b28b702SAnirudh Venkataramanan  * ice_ena_vsi - resume a VSI
31640b28b702SAnirudh Venkataramanan  * @vsi: the VSI being resume
31650b28b702SAnirudh Venkataramanan  */
31660f9d5027SAnirudh Venkataramanan static int ice_ena_vsi(struct ice_vsi *vsi)
31670b28b702SAnirudh Venkataramanan {
31680f9d5027SAnirudh Venkataramanan 	int err = 0;
31690b28b702SAnirudh Venkataramanan 
31700f9d5027SAnirudh Venkataramanan 	if (test_and_clear_bit(__ICE_NEEDS_RESTART, vsi->state))
31710f9d5027SAnirudh Venkataramanan 		if (vsi->netdev && netif_running(vsi->netdev)) {
31720f9d5027SAnirudh Venkataramanan 			rtnl_lock();
31730f9d5027SAnirudh Venkataramanan 			err = vsi->netdev->netdev_ops->ndo_open(vsi->netdev);
31740f9d5027SAnirudh Venkataramanan 			rtnl_unlock();
31750f9d5027SAnirudh Venkataramanan 		}
31760f9d5027SAnirudh Venkataramanan 
31770f9d5027SAnirudh Venkataramanan 	return err;
31780b28b702SAnirudh Venkataramanan }
31790b28b702SAnirudh Venkataramanan 
31800b28b702SAnirudh Venkataramanan /**
31810b28b702SAnirudh Venkataramanan  * ice_pf_dis_all_vsi - Pause all VSIs on a PF
31820b28b702SAnirudh Venkataramanan  * @pf: the PF
31830b28b702SAnirudh Venkataramanan  */
31840b28b702SAnirudh Venkataramanan static void ice_pf_dis_all_vsi(struct ice_pf *pf)
31850b28b702SAnirudh Venkataramanan {
31860b28b702SAnirudh Venkataramanan 	int v;
31870b28b702SAnirudh Venkataramanan 
31880b28b702SAnirudh Venkataramanan 	ice_for_each_vsi(pf, v)
31890b28b702SAnirudh Venkataramanan 		if (pf->vsi[v])
31900b28b702SAnirudh Venkataramanan 			ice_dis_vsi(pf->vsi[v]);
31910b28b702SAnirudh Venkataramanan }
31920b28b702SAnirudh Venkataramanan 
31930b28b702SAnirudh Venkataramanan /**
31940b28b702SAnirudh Venkataramanan  * ice_pf_ena_all_vsi - Resume all VSIs on a PF
31950b28b702SAnirudh Venkataramanan  * @pf: the PF
31960b28b702SAnirudh Venkataramanan  */
31970f9d5027SAnirudh Venkataramanan static int ice_pf_ena_all_vsi(struct ice_pf *pf)
31980b28b702SAnirudh Venkataramanan {
31990b28b702SAnirudh Venkataramanan 	int v;
32000b28b702SAnirudh Venkataramanan 
32010b28b702SAnirudh Venkataramanan 	ice_for_each_vsi(pf, v)
32020b28b702SAnirudh Venkataramanan 		if (pf->vsi[v])
32030f9d5027SAnirudh Venkataramanan 			if (ice_ena_vsi(pf->vsi[v]))
32040f9d5027SAnirudh Venkataramanan 				return -EIO;
32050f9d5027SAnirudh Venkataramanan 
32060f9d5027SAnirudh Venkataramanan 	return 0;
32070f9d5027SAnirudh Venkataramanan }
32080f9d5027SAnirudh Venkataramanan 
32090f9d5027SAnirudh Venkataramanan /**
32100f9d5027SAnirudh Venkataramanan  * ice_vsi_rebuild_all - rebuild all VSIs in pf
32110f9d5027SAnirudh Venkataramanan  * @pf: the PF
32120f9d5027SAnirudh Venkataramanan  */
32130f9d5027SAnirudh Venkataramanan static int ice_vsi_rebuild_all(struct ice_pf *pf)
32140f9d5027SAnirudh Venkataramanan {
32150f9d5027SAnirudh Venkataramanan 	int i;
32160f9d5027SAnirudh Venkataramanan 
32170f9d5027SAnirudh Venkataramanan 	/* loop through pf->vsi array and reinit the VSI if found */
32180f9d5027SAnirudh Venkataramanan 	for (i = 0; i < pf->num_alloc_vsi; i++) {
32190f9d5027SAnirudh Venkataramanan 		int err;
32200f9d5027SAnirudh Venkataramanan 
32210f9d5027SAnirudh Venkataramanan 		if (!pf->vsi[i])
32220f9d5027SAnirudh Venkataramanan 			continue;
32230f9d5027SAnirudh Venkataramanan 
32240f9d5027SAnirudh Venkataramanan 		err = ice_vsi_rebuild(pf->vsi[i]);
32250f9d5027SAnirudh Venkataramanan 		if (err) {
32260f9d5027SAnirudh Venkataramanan 			dev_err(&pf->pdev->dev,
32270f9d5027SAnirudh Venkataramanan 				"VSI at index %d rebuild failed\n",
32280f9d5027SAnirudh Venkataramanan 				pf->vsi[i]->idx);
32290f9d5027SAnirudh Venkataramanan 			return err;
32300f9d5027SAnirudh Venkataramanan 		}
32310f9d5027SAnirudh Venkataramanan 
32320f9d5027SAnirudh Venkataramanan 		dev_info(&pf->pdev->dev,
32330f9d5027SAnirudh Venkataramanan 			 "VSI at index %d rebuilt. vsi_num = 0x%x\n",
32340f9d5027SAnirudh Venkataramanan 			 pf->vsi[i]->idx, pf->vsi[i]->vsi_num);
32350f9d5027SAnirudh Venkataramanan 	}
32360f9d5027SAnirudh Venkataramanan 
32370f9d5027SAnirudh Venkataramanan 	return 0;
32380b28b702SAnirudh Venkataramanan }
32390b28b702SAnirudh Venkataramanan 
32400b28b702SAnirudh Venkataramanan /**
3241334cb062SAnirudh Venkataramanan  * ice_vsi_replay_all - replay all VSIs configuration in the PF
3242334cb062SAnirudh Venkataramanan  * @pf: the PF
3243334cb062SAnirudh Venkataramanan  */
3244334cb062SAnirudh Venkataramanan static int ice_vsi_replay_all(struct ice_pf *pf)
3245334cb062SAnirudh Venkataramanan {
3246334cb062SAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
3247334cb062SAnirudh Venkataramanan 	enum ice_status ret;
3248334cb062SAnirudh Venkataramanan 	int i;
3249334cb062SAnirudh Venkataramanan 
3250334cb062SAnirudh Venkataramanan 	/* loop through pf->vsi array and replay the VSI if found */
3251334cb062SAnirudh Venkataramanan 	for (i = 0; i < pf->num_alloc_vsi; i++) {
3252334cb062SAnirudh Venkataramanan 		if (!pf->vsi[i])
3253334cb062SAnirudh Venkataramanan 			continue;
3254334cb062SAnirudh Venkataramanan 
3255334cb062SAnirudh Venkataramanan 		ret = ice_replay_vsi(hw, pf->vsi[i]->idx);
3256334cb062SAnirudh Venkataramanan 		if (ret) {
3257334cb062SAnirudh Venkataramanan 			dev_err(&pf->pdev->dev,
3258334cb062SAnirudh Venkataramanan 				"VSI at index %d replay failed %d\n",
3259334cb062SAnirudh Venkataramanan 				pf->vsi[i]->idx, ret);
3260334cb062SAnirudh Venkataramanan 			return -EIO;
3261334cb062SAnirudh Venkataramanan 		}
3262334cb062SAnirudh Venkataramanan 
3263334cb062SAnirudh Venkataramanan 		/* Re-map HW VSI number, using VSI handle that has been
3264334cb062SAnirudh Venkataramanan 		 * previously validated in ice_replay_vsi() call above
3265334cb062SAnirudh Venkataramanan 		 */
3266334cb062SAnirudh Venkataramanan 		pf->vsi[i]->vsi_num = ice_get_hw_vsi_num(hw, pf->vsi[i]->idx);
3267334cb062SAnirudh Venkataramanan 
3268334cb062SAnirudh Venkataramanan 		dev_info(&pf->pdev->dev,
3269334cb062SAnirudh Venkataramanan 			 "VSI at index %d filter replayed successfully - vsi_num %i\n",
3270334cb062SAnirudh Venkataramanan 			 pf->vsi[i]->idx, pf->vsi[i]->vsi_num);
3271334cb062SAnirudh Venkataramanan 	}
3272334cb062SAnirudh Venkataramanan 
3273334cb062SAnirudh Venkataramanan 	/* Clean up replay filter after successful re-configuration */
3274334cb062SAnirudh Venkataramanan 	ice_replay_post(hw);
3275334cb062SAnirudh Venkataramanan 	return 0;
3276334cb062SAnirudh Venkataramanan }
3277334cb062SAnirudh Venkataramanan 
3278334cb062SAnirudh Venkataramanan /**
32790b28b702SAnirudh Venkataramanan  * ice_rebuild - rebuild after reset
32800b28b702SAnirudh Venkataramanan  * @pf: pf to rebuild
32810b28b702SAnirudh Venkataramanan  */
32820b28b702SAnirudh Venkataramanan static void ice_rebuild(struct ice_pf *pf)
32830b28b702SAnirudh Venkataramanan {
32840b28b702SAnirudh Venkataramanan 	struct device *dev = &pf->pdev->dev;
32850b28b702SAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
32860b28b702SAnirudh Venkataramanan 	enum ice_status ret;
32870b28b702SAnirudh Venkataramanan 	int err;
32880b28b702SAnirudh Venkataramanan 
32890b28b702SAnirudh Venkataramanan 	if (test_bit(__ICE_DOWN, pf->state))
32900b28b702SAnirudh Venkataramanan 		goto clear_recovery;
32910b28b702SAnirudh Venkataramanan 
32920b28b702SAnirudh Venkataramanan 	dev_dbg(dev, "rebuilding pf\n");
32930b28b702SAnirudh Venkataramanan 
32940b28b702SAnirudh Venkataramanan 	ret = ice_init_all_ctrlq(hw);
32950b28b702SAnirudh Venkataramanan 	if (ret) {
32960b28b702SAnirudh Venkataramanan 		dev_err(dev, "control queues init failed %d\n", ret);
32970f9d5027SAnirudh Venkataramanan 		goto err_init_ctrlq;
32980b28b702SAnirudh Venkataramanan 	}
32990b28b702SAnirudh Venkataramanan 
33000b28b702SAnirudh Venkataramanan 	ret = ice_clear_pf_cfg(hw);
33010b28b702SAnirudh Venkataramanan 	if (ret) {
33020b28b702SAnirudh Venkataramanan 		dev_err(dev, "clear PF configuration failed %d\n", ret);
33030f9d5027SAnirudh Venkataramanan 		goto err_init_ctrlq;
33040b28b702SAnirudh Venkataramanan 	}
33050b28b702SAnirudh Venkataramanan 
33060b28b702SAnirudh Venkataramanan 	ice_clear_pxe_mode(hw);
33070b28b702SAnirudh Venkataramanan 
33080b28b702SAnirudh Venkataramanan 	ret = ice_get_caps(hw);
33090b28b702SAnirudh Venkataramanan 	if (ret) {
33100b28b702SAnirudh Venkataramanan 		dev_err(dev, "ice_get_caps failed %d\n", ret);
33110f9d5027SAnirudh Venkataramanan 		goto err_init_ctrlq;
33120b28b702SAnirudh Venkataramanan 	}
33130b28b702SAnirudh Venkataramanan 
33140f9d5027SAnirudh Venkataramanan 	err = ice_sched_init_port(hw->port_info);
33150f9d5027SAnirudh Venkataramanan 	if (err)
33160f9d5027SAnirudh Venkataramanan 		goto err_sched_init_port;
33170f9d5027SAnirudh Venkataramanan 
3318eb0208ecSPreethi Banala 	/* reset search_hint of irq_trackers to 0 since interrupts are
3319eb0208ecSPreethi Banala 	 * reclaimed and could be allocated from beginning during VSI rebuild
3320eb0208ecSPreethi Banala 	 */
3321eb0208ecSPreethi Banala 	pf->sw_irq_tracker->search_hint = 0;
3322eb0208ecSPreethi Banala 	pf->hw_irq_tracker->search_hint = 0;
3323eb0208ecSPreethi Banala 
33240f9d5027SAnirudh Venkataramanan 	err = ice_vsi_rebuild_all(pf);
33250b28b702SAnirudh Venkataramanan 	if (err) {
33260f9d5027SAnirudh Venkataramanan 		dev_err(dev, "ice_vsi_rebuild_all failed\n");
33270f9d5027SAnirudh Venkataramanan 		goto err_vsi_rebuild;
33280f9d5027SAnirudh Venkataramanan 	}
33290f9d5027SAnirudh Venkataramanan 
33305755143dSDave Ertman 	err = ice_update_link_info(hw->port_info);
33315755143dSDave Ertman 	if (err)
33325755143dSDave Ertman 		dev_err(&pf->pdev->dev, "Get link status error %d\n", err);
33335755143dSDave Ertman 
3334334cb062SAnirudh Venkataramanan 	/* Replay all VSIs Configuration, including filters after reset */
3335334cb062SAnirudh Venkataramanan 	if (ice_vsi_replay_all(pf)) {
33360f9d5027SAnirudh Venkataramanan 		dev_err(&pf->pdev->dev,
3337334cb062SAnirudh Venkataramanan 			"error replaying VSI configurations with switch filter rules\n");
33380f9d5027SAnirudh Venkataramanan 		goto err_vsi_rebuild;
33390b28b702SAnirudh Venkataramanan 	}
33400b28b702SAnirudh Venkataramanan 
33410b28b702SAnirudh Venkataramanan 	/* start misc vector */
33420b28b702SAnirudh Venkataramanan 	if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) {
33430b28b702SAnirudh Venkataramanan 		err = ice_req_irq_msix_misc(pf);
33440b28b702SAnirudh Venkataramanan 		if (err) {
33450b28b702SAnirudh Venkataramanan 			dev_err(dev, "misc vector setup failed: %d\n", err);
33460f9d5027SAnirudh Venkataramanan 			goto err_vsi_rebuild;
33470b28b702SAnirudh Venkataramanan 		}
33480b28b702SAnirudh Venkataramanan 	}
33490b28b702SAnirudh Venkataramanan 
33500b28b702SAnirudh Venkataramanan 	/* restart the VSIs that were rebuilt and running before the reset */
33510f9d5027SAnirudh Venkataramanan 	err = ice_pf_ena_all_vsi(pf);
33520f9d5027SAnirudh Venkataramanan 	if (err) {
33530f9d5027SAnirudh Venkataramanan 		dev_err(&pf->pdev->dev, "error enabling VSIs\n");
33540f9d5027SAnirudh Venkataramanan 		/* no need to disable VSIs in tear down path in ice_rebuild()
33550f9d5027SAnirudh Venkataramanan 		 * since its already taken care in ice_vsi_open()
33560f9d5027SAnirudh Venkataramanan 		 */
33570f9d5027SAnirudh Venkataramanan 		goto err_vsi_rebuild;
33580f9d5027SAnirudh Venkataramanan 	}
33590b28b702SAnirudh Venkataramanan 
33600f9d5027SAnirudh Venkataramanan 	/* if we get here, reset flow is successful */
33610f9d5027SAnirudh Venkataramanan 	clear_bit(__ICE_RESET_FAILED, pf->state);
33620b28b702SAnirudh Venkataramanan 	return;
33630b28b702SAnirudh Venkataramanan 
33640f9d5027SAnirudh Venkataramanan err_vsi_rebuild:
33650f9d5027SAnirudh Venkataramanan 	ice_vsi_release_all(pf);
33660f9d5027SAnirudh Venkataramanan err_sched_init_port:
33670f9d5027SAnirudh Venkataramanan 	ice_sched_cleanup_all(hw);
33680f9d5027SAnirudh Venkataramanan err_init_ctrlq:
33690b28b702SAnirudh Venkataramanan 	ice_shutdown_all_ctrlq(hw);
33700b28b702SAnirudh Venkataramanan 	set_bit(__ICE_RESET_FAILED, pf->state);
33710b28b702SAnirudh Venkataramanan clear_recovery:
33720f9d5027SAnirudh Venkataramanan 	/* set this bit in PF state to control service task scheduling */
33730f9d5027SAnirudh Venkataramanan 	set_bit(__ICE_NEEDS_RESTART, pf->state);
33740f9d5027SAnirudh Venkataramanan 	dev_err(dev, "Rebuild failed, unload and reload driver\n");
33750b28b702SAnirudh Venkataramanan }
33760b28b702SAnirudh Venkataramanan 
33770b28b702SAnirudh Venkataramanan /**
3378e94d4478SAnirudh Venkataramanan  * ice_change_mtu - NDO callback to change the MTU
3379e94d4478SAnirudh Venkataramanan  * @netdev: network interface device structure
3380e94d4478SAnirudh Venkataramanan  * @new_mtu: new value for maximum frame size
3381e94d4478SAnirudh Venkataramanan  *
3382e94d4478SAnirudh Venkataramanan  * Returns 0 on success, negative on failure
3383e94d4478SAnirudh Venkataramanan  */
3384e94d4478SAnirudh Venkataramanan static int ice_change_mtu(struct net_device *netdev, int new_mtu)
3385e94d4478SAnirudh Venkataramanan {
3386e94d4478SAnirudh Venkataramanan 	struct ice_netdev_priv *np = netdev_priv(netdev);
3387e94d4478SAnirudh Venkataramanan 	struct ice_vsi *vsi = np->vsi;
3388e94d4478SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
3389e94d4478SAnirudh Venkataramanan 	u8 count = 0;
3390e94d4478SAnirudh Venkataramanan 
3391e94d4478SAnirudh Venkataramanan 	if (new_mtu == netdev->mtu) {
33923968540bSAnirudh Venkataramanan 		netdev_warn(netdev, "mtu is already %u\n", netdev->mtu);
3393e94d4478SAnirudh Venkataramanan 		return 0;
3394e94d4478SAnirudh Venkataramanan 	}
3395e94d4478SAnirudh Venkataramanan 
3396e94d4478SAnirudh Venkataramanan 	if (new_mtu < netdev->min_mtu) {
3397e94d4478SAnirudh Venkataramanan 		netdev_err(netdev, "new mtu invalid. min_mtu is %d\n",
3398e94d4478SAnirudh Venkataramanan 			   netdev->min_mtu);
3399e94d4478SAnirudh Venkataramanan 		return -EINVAL;
3400e94d4478SAnirudh Venkataramanan 	} else if (new_mtu > netdev->max_mtu) {
3401e94d4478SAnirudh Venkataramanan 		netdev_err(netdev, "new mtu invalid. max_mtu is %d\n",
3402e94d4478SAnirudh Venkataramanan 			   netdev->min_mtu);
3403e94d4478SAnirudh Venkataramanan 		return -EINVAL;
3404e94d4478SAnirudh Venkataramanan 	}
3405e94d4478SAnirudh Venkataramanan 	/* if a reset is in progress, wait for some time for it to complete */
3406e94d4478SAnirudh Venkataramanan 	do {
34075df7e45dSDave Ertman 		if (ice_is_reset_in_progress(pf->state)) {
3408e94d4478SAnirudh Venkataramanan 			count++;
3409e94d4478SAnirudh Venkataramanan 			usleep_range(1000, 2000);
3410e94d4478SAnirudh Venkataramanan 		} else {
3411e94d4478SAnirudh Venkataramanan 			break;
3412e94d4478SAnirudh Venkataramanan 		}
3413e94d4478SAnirudh Venkataramanan 
3414e94d4478SAnirudh Venkataramanan 	} while (count < 100);
3415e94d4478SAnirudh Venkataramanan 
3416e94d4478SAnirudh Venkataramanan 	if (count == 100) {
3417e94d4478SAnirudh Venkataramanan 		netdev_err(netdev, "can't change mtu. Device is busy\n");
3418e94d4478SAnirudh Venkataramanan 		return -EBUSY;
3419e94d4478SAnirudh Venkataramanan 	}
3420e94d4478SAnirudh Venkataramanan 
3421e94d4478SAnirudh Venkataramanan 	netdev->mtu = new_mtu;
3422e94d4478SAnirudh Venkataramanan 
3423e94d4478SAnirudh Venkataramanan 	/* if VSI is up, bring it down and then back up */
3424e94d4478SAnirudh Venkataramanan 	if (!test_and_set_bit(__ICE_DOWN, vsi->state)) {
3425e94d4478SAnirudh Venkataramanan 		int err;
3426e94d4478SAnirudh Venkataramanan 
3427e94d4478SAnirudh Venkataramanan 		err = ice_down(vsi);
3428e94d4478SAnirudh Venkataramanan 		if (err) {
3429e94d4478SAnirudh Venkataramanan 			netdev_err(netdev, "change mtu if_up err %d\n", err);
3430e94d4478SAnirudh Venkataramanan 			return err;
3431e94d4478SAnirudh Venkataramanan 		}
3432e94d4478SAnirudh Venkataramanan 
3433e94d4478SAnirudh Venkataramanan 		err = ice_up(vsi);
3434e94d4478SAnirudh Venkataramanan 		if (err) {
3435e94d4478SAnirudh Venkataramanan 			netdev_err(netdev, "change mtu if_up err %d\n", err);
3436e94d4478SAnirudh Venkataramanan 			return err;
3437e94d4478SAnirudh Venkataramanan 		}
3438e94d4478SAnirudh Venkataramanan 	}
3439e94d4478SAnirudh Venkataramanan 
3440e94d4478SAnirudh Venkataramanan 	netdev_dbg(netdev, "changed mtu to %d\n", new_mtu);
3441e94d4478SAnirudh Venkataramanan 	return 0;
3442e94d4478SAnirudh Venkataramanan }
3443e94d4478SAnirudh Venkataramanan 
3444e94d4478SAnirudh Venkataramanan /**
3445d76a60baSAnirudh Venkataramanan  * ice_set_rss - Set RSS keys and lut
3446d76a60baSAnirudh Venkataramanan  * @vsi: Pointer to VSI structure
3447d76a60baSAnirudh Venkataramanan  * @seed: RSS hash seed
3448d76a60baSAnirudh Venkataramanan  * @lut: Lookup table
3449d76a60baSAnirudh Venkataramanan  * @lut_size: Lookup table size
3450d76a60baSAnirudh Venkataramanan  *
3451d76a60baSAnirudh Venkataramanan  * Returns 0 on success, negative on failure
3452d76a60baSAnirudh Venkataramanan  */
3453d76a60baSAnirudh Venkataramanan int ice_set_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size)
3454d76a60baSAnirudh Venkataramanan {
3455d76a60baSAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
3456d76a60baSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
3457d76a60baSAnirudh Venkataramanan 	enum ice_status status;
3458d76a60baSAnirudh Venkataramanan 
3459d76a60baSAnirudh Venkataramanan 	if (seed) {
3460d76a60baSAnirudh Venkataramanan 		struct ice_aqc_get_set_rss_keys *buf =
3461d76a60baSAnirudh Venkataramanan 				  (struct ice_aqc_get_set_rss_keys *)seed;
3462d76a60baSAnirudh Venkataramanan 
34634fb33f31SAnirudh Venkataramanan 		status = ice_aq_set_rss_key(hw, vsi->idx, buf);
3464d76a60baSAnirudh Venkataramanan 
3465d76a60baSAnirudh Venkataramanan 		if (status) {
3466d76a60baSAnirudh Venkataramanan 			dev_err(&pf->pdev->dev,
3467d76a60baSAnirudh Venkataramanan 				"Cannot set RSS key, err %d aq_err %d\n",
3468d76a60baSAnirudh Venkataramanan 				status, hw->adminq.rq_last_status);
3469d76a60baSAnirudh Venkataramanan 			return -EIO;
3470d76a60baSAnirudh Venkataramanan 		}
3471d76a60baSAnirudh Venkataramanan 	}
3472d76a60baSAnirudh Venkataramanan 
3473d76a60baSAnirudh Venkataramanan 	if (lut) {
34744fb33f31SAnirudh Venkataramanan 		status = ice_aq_set_rss_lut(hw, vsi->idx, vsi->rss_lut_type,
34754fb33f31SAnirudh Venkataramanan 					    lut, lut_size);
3476d76a60baSAnirudh Venkataramanan 		if (status) {
3477d76a60baSAnirudh Venkataramanan 			dev_err(&pf->pdev->dev,
3478d76a60baSAnirudh Venkataramanan 				"Cannot set RSS lut, err %d aq_err %d\n",
3479d76a60baSAnirudh Venkataramanan 				status, hw->adminq.rq_last_status);
3480d76a60baSAnirudh Venkataramanan 			return -EIO;
3481d76a60baSAnirudh Venkataramanan 		}
3482d76a60baSAnirudh Venkataramanan 	}
3483d76a60baSAnirudh Venkataramanan 
3484d76a60baSAnirudh Venkataramanan 	return 0;
3485d76a60baSAnirudh Venkataramanan }
3486d76a60baSAnirudh Venkataramanan 
3487d76a60baSAnirudh Venkataramanan /**
3488d76a60baSAnirudh Venkataramanan  * ice_get_rss - Get RSS keys and lut
3489d76a60baSAnirudh Venkataramanan  * @vsi: Pointer to VSI structure
3490d76a60baSAnirudh Venkataramanan  * @seed: Buffer to store the keys
3491d76a60baSAnirudh Venkataramanan  * @lut: Buffer to store the lookup table entries
3492d76a60baSAnirudh Venkataramanan  * @lut_size: Size of buffer to store the lookup table entries
3493d76a60baSAnirudh Venkataramanan  *
3494d76a60baSAnirudh Venkataramanan  * Returns 0 on success, negative on failure
3495d76a60baSAnirudh Venkataramanan  */
3496d76a60baSAnirudh Venkataramanan int ice_get_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size)
3497d76a60baSAnirudh Venkataramanan {
3498d76a60baSAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
3499d76a60baSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
3500d76a60baSAnirudh Venkataramanan 	enum ice_status status;
3501d76a60baSAnirudh Venkataramanan 
3502d76a60baSAnirudh Venkataramanan 	if (seed) {
3503d76a60baSAnirudh Venkataramanan 		struct ice_aqc_get_set_rss_keys *buf =
3504d76a60baSAnirudh Venkataramanan 				  (struct ice_aqc_get_set_rss_keys *)seed;
3505d76a60baSAnirudh Venkataramanan 
35064fb33f31SAnirudh Venkataramanan 		status = ice_aq_get_rss_key(hw, vsi->idx, buf);
3507d76a60baSAnirudh Venkataramanan 		if (status) {
3508d76a60baSAnirudh Venkataramanan 			dev_err(&pf->pdev->dev,
3509d76a60baSAnirudh Venkataramanan 				"Cannot get RSS key, err %d aq_err %d\n",
3510d76a60baSAnirudh Venkataramanan 				status, hw->adminq.rq_last_status);
3511d76a60baSAnirudh Venkataramanan 			return -EIO;
3512d76a60baSAnirudh Venkataramanan 		}
3513d76a60baSAnirudh Venkataramanan 	}
3514d76a60baSAnirudh Venkataramanan 
3515d76a60baSAnirudh Venkataramanan 	if (lut) {
35164fb33f31SAnirudh Venkataramanan 		status = ice_aq_get_rss_lut(hw, vsi->idx, vsi->rss_lut_type,
35174fb33f31SAnirudh Venkataramanan 					    lut, lut_size);
3518d76a60baSAnirudh Venkataramanan 		if (status) {
3519d76a60baSAnirudh Venkataramanan 			dev_err(&pf->pdev->dev,
3520d76a60baSAnirudh Venkataramanan 				"Cannot get RSS lut, err %d aq_err %d\n",
3521d76a60baSAnirudh Venkataramanan 				status, hw->adminq.rq_last_status);
3522d76a60baSAnirudh Venkataramanan 			return -EIO;
3523d76a60baSAnirudh Venkataramanan 		}
3524d76a60baSAnirudh Venkataramanan 	}
3525d76a60baSAnirudh Venkataramanan 
3526d76a60baSAnirudh Venkataramanan 	return 0;
3527d76a60baSAnirudh Venkataramanan }
3528d76a60baSAnirudh Venkataramanan 
3529d76a60baSAnirudh Venkataramanan /**
3530b1edc14aSMd Fahad Iqbal Polash  * ice_bridge_getlink - Get the hardware bridge mode
3531b1edc14aSMd Fahad Iqbal Polash  * @skb: skb buff
3532b1edc14aSMd Fahad Iqbal Polash  * @pid: process id
3533b1edc14aSMd Fahad Iqbal Polash  * @seq: RTNL message seq
3534b1edc14aSMd Fahad Iqbal Polash  * @dev: the netdev being configured
3535b1edc14aSMd Fahad Iqbal Polash  * @filter_mask: filter mask passed in
3536b1edc14aSMd Fahad Iqbal Polash  * @nlflags: netlink flags passed in
3537b1edc14aSMd Fahad Iqbal Polash  *
3538b1edc14aSMd Fahad Iqbal Polash  * Return the bridge mode (VEB/VEPA)
3539b1edc14aSMd Fahad Iqbal Polash  */
3540b1edc14aSMd Fahad Iqbal Polash static int
3541b1edc14aSMd Fahad Iqbal Polash ice_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
3542b1edc14aSMd Fahad Iqbal Polash 		   struct net_device *dev, u32 filter_mask, int nlflags)
3543b1edc14aSMd Fahad Iqbal Polash {
3544b1edc14aSMd Fahad Iqbal Polash 	struct ice_netdev_priv *np = netdev_priv(dev);
3545b1edc14aSMd Fahad Iqbal Polash 	struct ice_vsi *vsi = np->vsi;
3546b1edc14aSMd Fahad Iqbal Polash 	struct ice_pf *pf = vsi->back;
3547b1edc14aSMd Fahad Iqbal Polash 	u16 bmode;
3548b1edc14aSMd Fahad Iqbal Polash 
3549b1edc14aSMd Fahad Iqbal Polash 	bmode = pf->first_sw->bridge_mode;
3550b1edc14aSMd Fahad Iqbal Polash 
3551b1edc14aSMd Fahad Iqbal Polash 	return ndo_dflt_bridge_getlink(skb, pid, seq, dev, bmode, 0, 0, nlflags,
3552b1edc14aSMd Fahad Iqbal Polash 				       filter_mask, NULL);
3553b1edc14aSMd Fahad Iqbal Polash }
3554b1edc14aSMd Fahad Iqbal Polash 
3555b1edc14aSMd Fahad Iqbal Polash /**
3556b1edc14aSMd Fahad Iqbal Polash  * ice_vsi_update_bridge_mode - Update VSI for switching bridge mode (VEB/VEPA)
3557b1edc14aSMd Fahad Iqbal Polash  * @vsi: Pointer to VSI structure
3558b1edc14aSMd Fahad Iqbal Polash  * @bmode: Hardware bridge mode (VEB/VEPA)
3559b1edc14aSMd Fahad Iqbal Polash  *
3560b1edc14aSMd Fahad Iqbal Polash  * Returns 0 on success, negative on failure
3561b1edc14aSMd Fahad Iqbal Polash  */
3562b1edc14aSMd Fahad Iqbal Polash static int ice_vsi_update_bridge_mode(struct ice_vsi *vsi, u16 bmode)
3563b1edc14aSMd Fahad Iqbal Polash {
3564b1edc14aSMd Fahad Iqbal Polash 	struct device *dev = &vsi->back->pdev->dev;
3565b1edc14aSMd Fahad Iqbal Polash 	struct ice_aqc_vsi_props *vsi_props;
3566b1edc14aSMd Fahad Iqbal Polash 	struct ice_hw *hw = &vsi->back->hw;
3567b1edc14aSMd Fahad Iqbal Polash 	struct ice_vsi_ctx ctxt = { 0 };
3568b1edc14aSMd Fahad Iqbal Polash 	enum ice_status status;
3569b1edc14aSMd Fahad Iqbal Polash 
3570b1edc14aSMd Fahad Iqbal Polash 	vsi_props = &vsi->info;
3571b1edc14aSMd Fahad Iqbal Polash 	ctxt.info = vsi->info;
3572b1edc14aSMd Fahad Iqbal Polash 
3573b1edc14aSMd Fahad Iqbal Polash 	if (bmode == BRIDGE_MODE_VEB)
3574b1edc14aSMd Fahad Iqbal Polash 		/* change from VEPA to VEB mode */
3575b1edc14aSMd Fahad Iqbal Polash 		ctxt.info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB;
3576b1edc14aSMd Fahad Iqbal Polash 	else
3577b1edc14aSMd Fahad Iqbal Polash 		/* change from VEB to VEPA mode */
3578b1edc14aSMd Fahad Iqbal Polash 		ctxt.info.sw_flags &= ~ICE_AQ_VSI_SW_FLAG_ALLOW_LB;
3579b1edc14aSMd Fahad Iqbal Polash 	ctxt.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SW_VALID);
35805726ca0eSAnirudh Venkataramanan 
35815726ca0eSAnirudh Venkataramanan 	status = ice_update_vsi(hw, vsi->idx, &ctxt, NULL);
3582b1edc14aSMd Fahad Iqbal Polash 	if (status) {
3583b1edc14aSMd Fahad Iqbal Polash 		dev_err(dev, "update VSI for bridge mode failed, bmode = %d err %d aq_err %d\n",
3584b1edc14aSMd Fahad Iqbal Polash 			bmode, status, hw->adminq.sq_last_status);
3585b1edc14aSMd Fahad Iqbal Polash 		return -EIO;
3586b1edc14aSMd Fahad Iqbal Polash 	}
3587b1edc14aSMd Fahad Iqbal Polash 	/* Update sw flags for book keeping */
3588b1edc14aSMd Fahad Iqbal Polash 	vsi_props->sw_flags = ctxt.info.sw_flags;
3589b1edc14aSMd Fahad Iqbal Polash 
3590b1edc14aSMd Fahad Iqbal Polash 	return 0;
3591b1edc14aSMd Fahad Iqbal Polash }
3592b1edc14aSMd Fahad Iqbal Polash 
3593b1edc14aSMd Fahad Iqbal Polash /**
3594b1edc14aSMd Fahad Iqbal Polash  * ice_bridge_setlink - Set the hardware bridge mode
3595b1edc14aSMd Fahad Iqbal Polash  * @dev: the netdev being configured
3596b1edc14aSMd Fahad Iqbal Polash  * @nlh: RTNL message
3597b1edc14aSMd Fahad Iqbal Polash  * @flags: bridge setlink flags
3598b1edc14aSMd Fahad Iqbal Polash  *
3599b1edc14aSMd Fahad Iqbal Polash  * Sets the bridge mode (VEB/VEPA) of the switch to which the netdev (VSI) is
3600b1edc14aSMd Fahad Iqbal Polash  * hooked up to. Iterates through the PF VSI list and sets the loopback mode (if
3601b1edc14aSMd Fahad Iqbal Polash  * not already set for all VSIs connected to this switch. And also update the
3602b1edc14aSMd Fahad Iqbal Polash  * unicast switch filter rules for the corresponding switch of the netdev.
3603b1edc14aSMd Fahad Iqbal Polash  */
3604b1edc14aSMd Fahad Iqbal Polash static int
3605b1edc14aSMd Fahad Iqbal Polash ice_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
3606b1edc14aSMd Fahad Iqbal Polash 		   u16 __always_unused flags)
3607b1edc14aSMd Fahad Iqbal Polash {
3608b1edc14aSMd Fahad Iqbal Polash 	struct ice_netdev_priv *np = netdev_priv(dev);
3609b1edc14aSMd Fahad Iqbal Polash 	struct ice_pf *pf = np->vsi->back;
3610b1edc14aSMd Fahad Iqbal Polash 	struct nlattr *attr, *br_spec;
3611b1edc14aSMd Fahad Iqbal Polash 	struct ice_hw *hw = &pf->hw;
3612b1edc14aSMd Fahad Iqbal Polash 	enum ice_status status;
3613b1edc14aSMd Fahad Iqbal Polash 	struct ice_sw *pf_sw;
3614b1edc14aSMd Fahad Iqbal Polash 	int rem, v, err = 0;
3615b1edc14aSMd Fahad Iqbal Polash 
3616b1edc14aSMd Fahad Iqbal Polash 	pf_sw = pf->first_sw;
3617b1edc14aSMd Fahad Iqbal Polash 	/* find the attribute in the netlink message */
3618b1edc14aSMd Fahad Iqbal Polash 	br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
3619b1edc14aSMd Fahad Iqbal Polash 
3620b1edc14aSMd Fahad Iqbal Polash 	nla_for_each_nested(attr, br_spec, rem) {
3621b1edc14aSMd Fahad Iqbal Polash 		__u16 mode;
3622b1edc14aSMd Fahad Iqbal Polash 
3623b1edc14aSMd Fahad Iqbal Polash 		if (nla_type(attr) != IFLA_BRIDGE_MODE)
3624b1edc14aSMd Fahad Iqbal Polash 			continue;
3625b1edc14aSMd Fahad Iqbal Polash 		mode = nla_get_u16(attr);
3626b1edc14aSMd Fahad Iqbal Polash 		if (mode != BRIDGE_MODE_VEPA && mode != BRIDGE_MODE_VEB)
3627b1edc14aSMd Fahad Iqbal Polash 			return -EINVAL;
3628b1edc14aSMd Fahad Iqbal Polash 		/* Continue  if bridge mode is not being flipped */
3629b1edc14aSMd Fahad Iqbal Polash 		if (mode == pf_sw->bridge_mode)
3630b1edc14aSMd Fahad Iqbal Polash 			continue;
3631b1edc14aSMd Fahad Iqbal Polash 		/* Iterates through the PF VSI list and update the loopback
3632b1edc14aSMd Fahad Iqbal Polash 		 * mode of the VSI
3633b1edc14aSMd Fahad Iqbal Polash 		 */
3634b1edc14aSMd Fahad Iqbal Polash 		ice_for_each_vsi(pf, v) {
3635b1edc14aSMd Fahad Iqbal Polash 			if (!pf->vsi[v])
3636b1edc14aSMd Fahad Iqbal Polash 				continue;
3637b1edc14aSMd Fahad Iqbal Polash 			err = ice_vsi_update_bridge_mode(pf->vsi[v], mode);
3638b1edc14aSMd Fahad Iqbal Polash 			if (err)
3639b1edc14aSMd Fahad Iqbal Polash 				return err;
3640b1edc14aSMd Fahad Iqbal Polash 		}
3641b1edc14aSMd Fahad Iqbal Polash 
3642b1edc14aSMd Fahad Iqbal Polash 		hw->evb_veb = (mode == BRIDGE_MODE_VEB);
3643b1edc14aSMd Fahad Iqbal Polash 		/* Update the unicast switch filter rules for the corresponding
3644b1edc14aSMd Fahad Iqbal Polash 		 * switch of the netdev
3645b1edc14aSMd Fahad Iqbal Polash 		 */
3646b1edc14aSMd Fahad Iqbal Polash 		status = ice_update_sw_rule_bridge_mode(hw);
3647b1edc14aSMd Fahad Iqbal Polash 		if (status) {
3648b1edc14aSMd Fahad Iqbal Polash 			netdev_err(dev, "update SW_RULE for bridge mode failed,  = %d err %d aq_err %d\n",
3649b1edc14aSMd Fahad Iqbal Polash 				   mode, status, hw->adminq.sq_last_status);
3650b1edc14aSMd Fahad Iqbal Polash 			/* revert hw->evb_veb */
3651b1edc14aSMd Fahad Iqbal Polash 			hw->evb_veb = (pf_sw->bridge_mode == BRIDGE_MODE_VEB);
3652b1edc14aSMd Fahad Iqbal Polash 			return -EIO;
3653b1edc14aSMd Fahad Iqbal Polash 		}
3654b1edc14aSMd Fahad Iqbal Polash 
3655b1edc14aSMd Fahad Iqbal Polash 		pf_sw->bridge_mode = mode;
3656b1edc14aSMd Fahad Iqbal Polash 	}
3657b1edc14aSMd Fahad Iqbal Polash 
3658b1edc14aSMd Fahad Iqbal Polash 	return 0;
3659b1edc14aSMd Fahad Iqbal Polash }
3660b1edc14aSMd Fahad Iqbal Polash 
3661b1edc14aSMd Fahad Iqbal Polash /**
3662b3969fd7SSudheer Mogilappagari  * ice_tx_timeout - Respond to a Tx Hang
3663b3969fd7SSudheer Mogilappagari  * @netdev: network interface device structure
3664b3969fd7SSudheer Mogilappagari  */
3665b3969fd7SSudheer Mogilappagari static void ice_tx_timeout(struct net_device *netdev)
3666b3969fd7SSudheer Mogilappagari {
3667b3969fd7SSudheer Mogilappagari 	struct ice_netdev_priv *np = netdev_priv(netdev);
3668b3969fd7SSudheer Mogilappagari 	struct ice_ring *tx_ring = NULL;
3669b3969fd7SSudheer Mogilappagari 	struct ice_vsi *vsi = np->vsi;
3670b3969fd7SSudheer Mogilappagari 	struct ice_pf *pf = vsi->back;
3671b3969fd7SSudheer Mogilappagari 	u32 head, val = 0, i;
3672b3969fd7SSudheer Mogilappagari 	int hung_queue = -1;
3673b3969fd7SSudheer Mogilappagari 
3674b3969fd7SSudheer Mogilappagari 	pf->tx_timeout_count++;
3675b3969fd7SSudheer Mogilappagari 
3676b3969fd7SSudheer Mogilappagari 	/* find the stopped queue the same way the stack does */
3677b3969fd7SSudheer Mogilappagari 	for (i = 0; i < netdev->num_tx_queues; i++) {
3678b3969fd7SSudheer Mogilappagari 		struct netdev_queue *q;
3679b3969fd7SSudheer Mogilappagari 		unsigned long trans_start;
3680b3969fd7SSudheer Mogilappagari 
3681b3969fd7SSudheer Mogilappagari 		q = netdev_get_tx_queue(netdev, i);
3682b3969fd7SSudheer Mogilappagari 		trans_start = q->trans_start;
3683b3969fd7SSudheer Mogilappagari 		if (netif_xmit_stopped(q) &&
3684b3969fd7SSudheer Mogilappagari 		    time_after(jiffies,
3685b3969fd7SSudheer Mogilappagari 			       (trans_start + netdev->watchdog_timeo))) {
3686b3969fd7SSudheer Mogilappagari 			hung_queue = i;
3687b3969fd7SSudheer Mogilappagari 			break;
3688b3969fd7SSudheer Mogilappagari 		}
3689b3969fd7SSudheer Mogilappagari 	}
3690b3969fd7SSudheer Mogilappagari 
3691b3969fd7SSudheer Mogilappagari 	if (i == netdev->num_tx_queues) {
3692b3969fd7SSudheer Mogilappagari 		netdev_info(netdev, "tx_timeout: no netdev hung queue found\n");
3693b3969fd7SSudheer Mogilappagari 	} else {
3694b3969fd7SSudheer Mogilappagari 		/* now that we have an index, find the tx_ring struct */
3695b3969fd7SSudheer Mogilappagari 		for (i = 0; i < vsi->num_txq; i++) {
3696b3969fd7SSudheer Mogilappagari 			if (vsi->tx_rings[i] && vsi->tx_rings[i]->desc) {
3697b3969fd7SSudheer Mogilappagari 				if (hung_queue ==
3698b3969fd7SSudheer Mogilappagari 				    vsi->tx_rings[i]->q_index) {
3699b3969fd7SSudheer Mogilappagari 					tx_ring = vsi->tx_rings[i];
3700b3969fd7SSudheer Mogilappagari 					break;
3701b3969fd7SSudheer Mogilappagari 				}
3702b3969fd7SSudheer Mogilappagari 			}
3703b3969fd7SSudheer Mogilappagari 		}
3704b3969fd7SSudheer Mogilappagari 	}
3705b3969fd7SSudheer Mogilappagari 
3706b3969fd7SSudheer Mogilappagari 	/* Reset recovery level if enough time has elapsed after last timeout.
3707b3969fd7SSudheer Mogilappagari 	 * Also ensure no new reset action happens before next timeout period.
3708b3969fd7SSudheer Mogilappagari 	 */
3709b3969fd7SSudheer Mogilappagari 	if (time_after(jiffies, (pf->tx_timeout_last_recovery + HZ * 20)))
3710b3969fd7SSudheer Mogilappagari 		pf->tx_timeout_recovery_level = 1;
3711b3969fd7SSudheer Mogilappagari 	else if (time_before(jiffies, (pf->tx_timeout_last_recovery +
3712b3969fd7SSudheer Mogilappagari 				       netdev->watchdog_timeo)))
3713b3969fd7SSudheer Mogilappagari 		return;
3714b3969fd7SSudheer Mogilappagari 
3715b3969fd7SSudheer Mogilappagari 	if (tx_ring) {
3716b3969fd7SSudheer Mogilappagari 		head = tx_ring->next_to_clean;
3717b3969fd7SSudheer Mogilappagari 		/* Read interrupt register */
3718b3969fd7SSudheer Mogilappagari 		if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags))
3719b3969fd7SSudheer Mogilappagari 			val = rd32(&pf->hw,
3720b3969fd7SSudheer Mogilappagari 				   GLINT_DYN_CTL(tx_ring->q_vector->v_idx +
3721eb0208ecSPreethi Banala 					tx_ring->vsi->hw_base_vector));
3722b3969fd7SSudheer Mogilappagari 
3723b3969fd7SSudheer Mogilappagari 		netdev_info(netdev, "tx_timeout: VSI_num: %d, Q %d, NTC: 0x%x, HWB: 0x%x, NTU: 0x%x, TAIL: 0x%x, INT: 0x%x\n",
3724b3969fd7SSudheer Mogilappagari 			    vsi->vsi_num, hung_queue, tx_ring->next_to_clean,
3725b3969fd7SSudheer Mogilappagari 			    head, tx_ring->next_to_use,
3726b3969fd7SSudheer Mogilappagari 			    readl(tx_ring->tail), val);
3727b3969fd7SSudheer Mogilappagari 	}
3728b3969fd7SSudheer Mogilappagari 
3729b3969fd7SSudheer Mogilappagari 	pf->tx_timeout_last_recovery = jiffies;
3730b3969fd7SSudheer Mogilappagari 	netdev_info(netdev, "tx_timeout recovery level %d, hung_queue %d\n",
3731b3969fd7SSudheer Mogilappagari 		    pf->tx_timeout_recovery_level, hung_queue);
3732b3969fd7SSudheer Mogilappagari 
3733b3969fd7SSudheer Mogilappagari 	switch (pf->tx_timeout_recovery_level) {
3734b3969fd7SSudheer Mogilappagari 	case 1:
3735b3969fd7SSudheer Mogilappagari 		set_bit(__ICE_PFR_REQ, pf->state);
3736b3969fd7SSudheer Mogilappagari 		break;
3737b3969fd7SSudheer Mogilappagari 	case 2:
3738b3969fd7SSudheer Mogilappagari 		set_bit(__ICE_CORER_REQ, pf->state);
3739b3969fd7SSudheer Mogilappagari 		break;
3740b3969fd7SSudheer Mogilappagari 	case 3:
3741b3969fd7SSudheer Mogilappagari 		set_bit(__ICE_GLOBR_REQ, pf->state);
3742b3969fd7SSudheer Mogilappagari 		break;
3743b3969fd7SSudheer Mogilappagari 	default:
3744b3969fd7SSudheer Mogilappagari 		netdev_err(netdev, "tx_timeout recovery unsuccessful, device is in unrecoverable state.\n");
3745b3969fd7SSudheer Mogilappagari 		set_bit(__ICE_DOWN, pf->state);
3746b3969fd7SSudheer Mogilappagari 		set_bit(__ICE_NEEDS_RESTART, vsi->state);
37478d81fa55SAkeem G Abodunrin 		set_bit(__ICE_SERVICE_DIS, pf->state);
3748b3969fd7SSudheer Mogilappagari 		break;
3749b3969fd7SSudheer Mogilappagari 	}
3750b3969fd7SSudheer Mogilappagari 
3751b3969fd7SSudheer Mogilappagari 	ice_service_task_schedule(pf);
3752b3969fd7SSudheer Mogilappagari 	pf->tx_timeout_recovery_level++;
3753b3969fd7SSudheer Mogilappagari }
3754b3969fd7SSudheer Mogilappagari 
3755b3969fd7SSudheer Mogilappagari /**
3756cdedef59SAnirudh Venkataramanan  * ice_open - Called when a network interface becomes active
3757cdedef59SAnirudh Venkataramanan  * @netdev: network interface device structure
3758cdedef59SAnirudh Venkataramanan  *
3759cdedef59SAnirudh Venkataramanan  * The open entry point is called when a network interface is made
3760cdedef59SAnirudh Venkataramanan  * active by the system (IFF_UP).  At this point all resources needed
3761cdedef59SAnirudh Venkataramanan  * for transmit and receive operations are allocated, the interrupt
3762cdedef59SAnirudh Venkataramanan  * handler is registered with the OS, the netdev watchdog is enabled,
3763cdedef59SAnirudh Venkataramanan  * and the stack is notified that the interface is ready.
3764cdedef59SAnirudh Venkataramanan  *
3765cdedef59SAnirudh Venkataramanan  * Returns 0 on success, negative value on failure
3766cdedef59SAnirudh Venkataramanan  */
3767cdedef59SAnirudh Venkataramanan static int ice_open(struct net_device *netdev)
3768cdedef59SAnirudh Venkataramanan {
3769cdedef59SAnirudh Venkataramanan 	struct ice_netdev_priv *np = netdev_priv(netdev);
3770cdedef59SAnirudh Venkataramanan 	struct ice_vsi *vsi = np->vsi;
3771cdedef59SAnirudh Venkataramanan 	int err;
3772cdedef59SAnirudh Venkataramanan 
37730f9d5027SAnirudh Venkataramanan 	if (test_bit(__ICE_NEEDS_RESTART, vsi->back->state)) {
37740f9d5027SAnirudh Venkataramanan 		netdev_err(netdev, "driver needs to be unloaded and reloaded\n");
37750f9d5027SAnirudh Venkataramanan 		return -EIO;
37760f9d5027SAnirudh Venkataramanan 	}
37770f9d5027SAnirudh Venkataramanan 
3778cdedef59SAnirudh Venkataramanan 	netif_carrier_off(netdev);
3779cdedef59SAnirudh Venkataramanan 
3780cdedef59SAnirudh Venkataramanan 	err = ice_vsi_open(vsi);
3781cdedef59SAnirudh Venkataramanan 
3782cdedef59SAnirudh Venkataramanan 	if (err)
3783cdedef59SAnirudh Venkataramanan 		netdev_err(netdev, "Failed to open VSI 0x%04X on switch 0x%04X\n",
3784cdedef59SAnirudh Venkataramanan 			   vsi->vsi_num, vsi->vsw->sw_id);
3785cdedef59SAnirudh Venkataramanan 	return err;
3786cdedef59SAnirudh Venkataramanan }
3787cdedef59SAnirudh Venkataramanan 
3788cdedef59SAnirudh Venkataramanan /**
3789cdedef59SAnirudh Venkataramanan  * ice_stop - Disables a network interface
3790cdedef59SAnirudh Venkataramanan  * @netdev: network interface device structure
3791cdedef59SAnirudh Venkataramanan  *
3792cdedef59SAnirudh Venkataramanan  * The stop entry point is called when an interface is de-activated by the OS,
3793cdedef59SAnirudh Venkataramanan  * and the netdevice enters the DOWN state.  The hardware is still under the
3794cdedef59SAnirudh Venkataramanan  * driver's control, but the netdev interface is disabled.
3795cdedef59SAnirudh Venkataramanan  *
3796cdedef59SAnirudh Venkataramanan  * Returns success only - not allowed to fail
3797cdedef59SAnirudh Venkataramanan  */
3798cdedef59SAnirudh Venkataramanan static int ice_stop(struct net_device *netdev)
3799cdedef59SAnirudh Venkataramanan {
3800cdedef59SAnirudh Venkataramanan 	struct ice_netdev_priv *np = netdev_priv(netdev);
3801cdedef59SAnirudh Venkataramanan 	struct ice_vsi *vsi = np->vsi;
3802cdedef59SAnirudh Venkataramanan 
3803cdedef59SAnirudh Venkataramanan 	ice_vsi_close(vsi);
3804cdedef59SAnirudh Venkataramanan 
3805cdedef59SAnirudh Venkataramanan 	return 0;
3806cdedef59SAnirudh Venkataramanan }
3807cdedef59SAnirudh Venkataramanan 
3808e94d4478SAnirudh Venkataramanan /**
3809e94d4478SAnirudh Venkataramanan  * ice_features_check - Validate encapsulated packet conforms to limits
3810e94d4478SAnirudh Venkataramanan  * @skb: skb buffer
3811e94d4478SAnirudh Venkataramanan  * @netdev: This port's netdev
3812e94d4478SAnirudh Venkataramanan  * @features: Offload features that the stack believes apply
3813e94d4478SAnirudh Venkataramanan  */
3814e94d4478SAnirudh Venkataramanan static netdev_features_t
3815e94d4478SAnirudh Venkataramanan ice_features_check(struct sk_buff *skb,
3816e94d4478SAnirudh Venkataramanan 		   struct net_device __always_unused *netdev,
3817e94d4478SAnirudh Venkataramanan 		   netdev_features_t features)
3818e94d4478SAnirudh Venkataramanan {
3819e94d4478SAnirudh Venkataramanan 	size_t len;
3820e94d4478SAnirudh Venkataramanan 
3821e94d4478SAnirudh Venkataramanan 	/* No point in doing any of this if neither checksum nor GSO are
3822e94d4478SAnirudh Venkataramanan 	 * being requested for this frame.  We can rule out both by just
3823e94d4478SAnirudh Venkataramanan 	 * checking for CHECKSUM_PARTIAL
3824e94d4478SAnirudh Venkataramanan 	 */
3825e94d4478SAnirudh Venkataramanan 	if (skb->ip_summed != CHECKSUM_PARTIAL)
3826e94d4478SAnirudh Venkataramanan 		return features;
3827e94d4478SAnirudh Venkataramanan 
3828e94d4478SAnirudh Venkataramanan 	/* We cannot support GSO if the MSS is going to be less than
3829e94d4478SAnirudh Venkataramanan 	 * 64 bytes.  If it is then we need to drop support for GSO.
3830e94d4478SAnirudh Venkataramanan 	 */
3831e94d4478SAnirudh Venkataramanan 	if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64))
3832e94d4478SAnirudh Venkataramanan 		features &= ~NETIF_F_GSO_MASK;
3833e94d4478SAnirudh Venkataramanan 
3834e94d4478SAnirudh Venkataramanan 	len = skb_network_header(skb) - skb->data;
3835e94d4478SAnirudh Venkataramanan 	if (len & ~(ICE_TXD_MACLEN_MAX))
3836e94d4478SAnirudh Venkataramanan 		goto out_rm_features;
3837e94d4478SAnirudh Venkataramanan 
3838e94d4478SAnirudh Venkataramanan 	len = skb_transport_header(skb) - skb_network_header(skb);
3839e94d4478SAnirudh Venkataramanan 	if (len & ~(ICE_TXD_IPLEN_MAX))
3840e94d4478SAnirudh Venkataramanan 		goto out_rm_features;
3841e94d4478SAnirudh Venkataramanan 
3842e94d4478SAnirudh Venkataramanan 	if (skb->encapsulation) {
3843e94d4478SAnirudh Venkataramanan 		len = skb_inner_network_header(skb) - skb_transport_header(skb);
3844e94d4478SAnirudh Venkataramanan 		if (len & ~(ICE_TXD_L4LEN_MAX))
3845e94d4478SAnirudh Venkataramanan 			goto out_rm_features;
3846e94d4478SAnirudh Venkataramanan 
3847e94d4478SAnirudh Venkataramanan 		len = skb_inner_transport_header(skb) -
3848e94d4478SAnirudh Venkataramanan 		      skb_inner_network_header(skb);
3849e94d4478SAnirudh Venkataramanan 		if (len & ~(ICE_TXD_IPLEN_MAX))
3850e94d4478SAnirudh Venkataramanan 			goto out_rm_features;
3851e94d4478SAnirudh Venkataramanan 	}
3852e94d4478SAnirudh Venkataramanan 
3853e94d4478SAnirudh Venkataramanan 	return features;
3854e94d4478SAnirudh Venkataramanan out_rm_features:
3855e94d4478SAnirudh Venkataramanan 	return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
3856e94d4478SAnirudh Venkataramanan }
3857e94d4478SAnirudh Venkataramanan 
3858cdedef59SAnirudh Venkataramanan static const struct net_device_ops ice_netdev_ops = {
3859cdedef59SAnirudh Venkataramanan 	.ndo_open = ice_open,
3860cdedef59SAnirudh Venkataramanan 	.ndo_stop = ice_stop,
38612b245cb2SAnirudh Venkataramanan 	.ndo_start_xmit = ice_start_xmit,
3862e94d4478SAnirudh Venkataramanan 	.ndo_features_check = ice_features_check,
3863e94d4478SAnirudh Venkataramanan 	.ndo_set_rx_mode = ice_set_rx_mode,
3864e94d4478SAnirudh Venkataramanan 	.ndo_set_mac_address = ice_set_mac_address,
3865e94d4478SAnirudh Venkataramanan 	.ndo_validate_addr = eth_validate_addr,
3866e94d4478SAnirudh Venkataramanan 	.ndo_change_mtu = ice_change_mtu,
3867fcea6f3dSAnirudh Venkataramanan 	.ndo_get_stats64 = ice_get_stats64,
3868d76a60baSAnirudh Venkataramanan 	.ndo_vlan_rx_add_vid = ice_vlan_rx_add_vid,
3869d76a60baSAnirudh Venkataramanan 	.ndo_vlan_rx_kill_vid = ice_vlan_rx_kill_vid,
3870d76a60baSAnirudh Venkataramanan 	.ndo_set_features = ice_set_features,
3871b1edc14aSMd Fahad Iqbal Polash 	.ndo_bridge_getlink = ice_bridge_getlink,
3872b1edc14aSMd Fahad Iqbal Polash 	.ndo_bridge_setlink = ice_bridge_setlink,
3873e94d4478SAnirudh Venkataramanan 	.ndo_fdb_add = ice_fdb_add,
3874e94d4478SAnirudh Venkataramanan 	.ndo_fdb_del = ice_fdb_del,
3875b3969fd7SSudheer Mogilappagari 	.ndo_tx_timeout = ice_tx_timeout,
3876cdedef59SAnirudh Venkataramanan };
3877