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,
98b3969fd7SSudheer Mogilappagari 				     GLINT_DYN_CTL(vsi->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;
714940b61afSAnirudh Venkataramanan 	default:
715940b61afSAnirudh Venkataramanan 		dev_warn(&pf->pdev->dev, "Unknown control queue type 0x%x\n",
716940b61afSAnirudh Venkataramanan 			 q_type);
717940b61afSAnirudh Venkataramanan 		return 0;
718940b61afSAnirudh Venkataramanan 	}
719940b61afSAnirudh Venkataramanan 
720940b61afSAnirudh Venkataramanan 	/* check for error indications - PF_xx_AxQLEN register layout for
721940b61afSAnirudh Venkataramanan 	 * FW/MBX/SB are identical so just use defines for PF_FW_AxQLEN.
722940b61afSAnirudh Venkataramanan 	 */
723940b61afSAnirudh Venkataramanan 	val = rd32(hw, cq->rq.len);
724940b61afSAnirudh Venkataramanan 	if (val & (PF_FW_ARQLEN_ARQVFE_M | PF_FW_ARQLEN_ARQOVFL_M |
725940b61afSAnirudh Venkataramanan 		   PF_FW_ARQLEN_ARQCRIT_M)) {
726940b61afSAnirudh Venkataramanan 		oldval = val;
727940b61afSAnirudh Venkataramanan 		if (val & PF_FW_ARQLEN_ARQVFE_M)
728940b61afSAnirudh Venkataramanan 			dev_dbg(&pf->pdev->dev,
729940b61afSAnirudh Venkataramanan 				"%s Receive Queue VF Error detected\n", qtype);
730940b61afSAnirudh Venkataramanan 		if (val & PF_FW_ARQLEN_ARQOVFL_M) {
731940b61afSAnirudh Venkataramanan 			dev_dbg(&pf->pdev->dev,
732940b61afSAnirudh Venkataramanan 				"%s Receive Queue Overflow Error detected\n",
733940b61afSAnirudh Venkataramanan 				qtype);
734940b61afSAnirudh Venkataramanan 		}
735940b61afSAnirudh Venkataramanan 		if (val & PF_FW_ARQLEN_ARQCRIT_M)
736940b61afSAnirudh Venkataramanan 			dev_dbg(&pf->pdev->dev,
737940b61afSAnirudh Venkataramanan 				"%s Receive Queue Critical Error detected\n",
738940b61afSAnirudh Venkataramanan 				qtype);
739940b61afSAnirudh Venkataramanan 		val &= ~(PF_FW_ARQLEN_ARQVFE_M | PF_FW_ARQLEN_ARQOVFL_M |
740940b61afSAnirudh Venkataramanan 			 PF_FW_ARQLEN_ARQCRIT_M);
741940b61afSAnirudh Venkataramanan 		if (oldval != val)
742940b61afSAnirudh Venkataramanan 			wr32(hw, cq->rq.len, val);
743940b61afSAnirudh Venkataramanan 	}
744940b61afSAnirudh Venkataramanan 
745940b61afSAnirudh Venkataramanan 	val = rd32(hw, cq->sq.len);
746940b61afSAnirudh Venkataramanan 	if (val & (PF_FW_ATQLEN_ATQVFE_M | PF_FW_ATQLEN_ATQOVFL_M |
747940b61afSAnirudh Venkataramanan 		   PF_FW_ATQLEN_ATQCRIT_M)) {
748940b61afSAnirudh Venkataramanan 		oldval = val;
749940b61afSAnirudh Venkataramanan 		if (val & PF_FW_ATQLEN_ATQVFE_M)
750940b61afSAnirudh Venkataramanan 			dev_dbg(&pf->pdev->dev,
751940b61afSAnirudh Venkataramanan 				"%s Send Queue VF Error detected\n", qtype);
752940b61afSAnirudh Venkataramanan 		if (val & PF_FW_ATQLEN_ATQOVFL_M) {
753940b61afSAnirudh Venkataramanan 			dev_dbg(&pf->pdev->dev,
754940b61afSAnirudh Venkataramanan 				"%s Send Queue Overflow Error detected\n",
755940b61afSAnirudh Venkataramanan 				qtype);
756940b61afSAnirudh Venkataramanan 		}
757940b61afSAnirudh Venkataramanan 		if (val & PF_FW_ATQLEN_ATQCRIT_M)
758940b61afSAnirudh Venkataramanan 			dev_dbg(&pf->pdev->dev,
759940b61afSAnirudh Venkataramanan 				"%s Send Queue Critical Error detected\n",
760940b61afSAnirudh Venkataramanan 				qtype);
761940b61afSAnirudh Venkataramanan 		val &= ~(PF_FW_ATQLEN_ATQVFE_M | PF_FW_ATQLEN_ATQOVFL_M |
762940b61afSAnirudh Venkataramanan 			 PF_FW_ATQLEN_ATQCRIT_M);
763940b61afSAnirudh Venkataramanan 		if (oldval != val)
764940b61afSAnirudh Venkataramanan 			wr32(hw, cq->sq.len, val);
765940b61afSAnirudh Venkataramanan 	}
766940b61afSAnirudh Venkataramanan 
767940b61afSAnirudh Venkataramanan 	event.buf_len = cq->rq_buf_size;
768940b61afSAnirudh Venkataramanan 	event.msg_buf = devm_kzalloc(&pf->pdev->dev, event.buf_len,
769940b61afSAnirudh Venkataramanan 				     GFP_KERNEL);
770940b61afSAnirudh Venkataramanan 	if (!event.msg_buf)
771940b61afSAnirudh Venkataramanan 		return 0;
772940b61afSAnirudh Venkataramanan 
773940b61afSAnirudh Venkataramanan 	do {
774940b61afSAnirudh Venkataramanan 		enum ice_status ret;
7750b28b702SAnirudh Venkataramanan 		u16 opcode;
776940b61afSAnirudh Venkataramanan 
777940b61afSAnirudh Venkataramanan 		ret = ice_clean_rq_elem(hw, cq, &event, &pending);
778940b61afSAnirudh Venkataramanan 		if (ret == ICE_ERR_AQ_NO_WORK)
779940b61afSAnirudh Venkataramanan 			break;
780940b61afSAnirudh Venkataramanan 		if (ret) {
781940b61afSAnirudh Venkataramanan 			dev_err(&pf->pdev->dev,
782940b61afSAnirudh Venkataramanan 				"%s Receive Queue event error %d\n", qtype,
783940b61afSAnirudh Venkataramanan 				ret);
784940b61afSAnirudh Venkataramanan 			break;
785940b61afSAnirudh Venkataramanan 		}
7860b28b702SAnirudh Venkataramanan 
7870b28b702SAnirudh Venkataramanan 		opcode = le16_to_cpu(event.desc.opcode);
7880b28b702SAnirudh Venkataramanan 
7890b28b702SAnirudh Venkataramanan 		switch (opcode) {
7900b28b702SAnirudh Venkataramanan 		case ice_aqc_opc_get_link_status:
7910b28b702SAnirudh Venkataramanan 			if (ice_handle_link_event(pf))
7920b28b702SAnirudh Venkataramanan 				dev_err(&pf->pdev->dev,
7933968540bSAnirudh Venkataramanan 					"Could not handle link event\n");
7940b28b702SAnirudh Venkataramanan 			break;
7958b97ceb1SHieu Tran 		case ice_aqc_opc_fw_logging:
7968b97ceb1SHieu Tran 			ice_output_fw_log(hw, &event.desc, event.msg_buf);
7978b97ceb1SHieu Tran 			break;
7980b28b702SAnirudh Venkataramanan 		default:
7990b28b702SAnirudh Venkataramanan 			dev_dbg(&pf->pdev->dev,
8000b28b702SAnirudh Venkataramanan 				"%s Receive Queue unknown event 0x%04x ignored\n",
8010b28b702SAnirudh Venkataramanan 				qtype, opcode);
8020b28b702SAnirudh Venkataramanan 			break;
8030b28b702SAnirudh Venkataramanan 		}
804940b61afSAnirudh Venkataramanan 	} while (pending && (i++ < ICE_DFLT_IRQ_WORK));
805940b61afSAnirudh Venkataramanan 
806940b61afSAnirudh Venkataramanan 	devm_kfree(&pf->pdev->dev, event.msg_buf);
807940b61afSAnirudh Venkataramanan 
808940b61afSAnirudh Venkataramanan 	return pending && (i == ICE_DFLT_IRQ_WORK);
809940b61afSAnirudh Venkataramanan }
810940b61afSAnirudh Venkataramanan 
811940b61afSAnirudh Venkataramanan /**
8123d6b640eSAnirudh Venkataramanan  * ice_ctrlq_pending - check if there is a difference between ntc and ntu
8133d6b640eSAnirudh Venkataramanan  * @hw: pointer to hardware info
8143d6b640eSAnirudh Venkataramanan  * @cq: control queue information
8153d6b640eSAnirudh Venkataramanan  *
8163d6b640eSAnirudh Venkataramanan  * returns true if there are pending messages in a queue, false if there aren't
8173d6b640eSAnirudh Venkataramanan  */
8183d6b640eSAnirudh Venkataramanan static bool ice_ctrlq_pending(struct ice_hw *hw, struct ice_ctl_q_info *cq)
8193d6b640eSAnirudh Venkataramanan {
8203d6b640eSAnirudh Venkataramanan 	u16 ntu;
8213d6b640eSAnirudh Venkataramanan 
8223d6b640eSAnirudh Venkataramanan 	ntu = (u16)(rd32(hw, cq->rq.head) & cq->rq.head_mask);
8233d6b640eSAnirudh Venkataramanan 	return cq->rq.next_to_clean != ntu;
8243d6b640eSAnirudh Venkataramanan }
8253d6b640eSAnirudh Venkataramanan 
8263d6b640eSAnirudh Venkataramanan /**
827940b61afSAnirudh Venkataramanan  * ice_clean_adminq_subtask - clean the AdminQ rings
828940b61afSAnirudh Venkataramanan  * @pf: board private structure
829940b61afSAnirudh Venkataramanan  */
830940b61afSAnirudh Venkataramanan static void ice_clean_adminq_subtask(struct ice_pf *pf)
831940b61afSAnirudh Venkataramanan {
832940b61afSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
833940b61afSAnirudh Venkataramanan 
834940b61afSAnirudh Venkataramanan 	if (!test_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state))
835940b61afSAnirudh Venkataramanan 		return;
836940b61afSAnirudh Venkataramanan 
837940b61afSAnirudh Venkataramanan 	if (__ice_clean_ctrlq(pf, ICE_CTL_Q_ADMIN))
838940b61afSAnirudh Venkataramanan 		return;
839940b61afSAnirudh Venkataramanan 
840940b61afSAnirudh Venkataramanan 	clear_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state);
841940b61afSAnirudh Venkataramanan 
8423d6b640eSAnirudh Venkataramanan 	/* There might be a situation where new messages arrive to a control
8433d6b640eSAnirudh Venkataramanan 	 * queue between processing the last message and clearing the
8443d6b640eSAnirudh Venkataramanan 	 * EVENT_PENDING bit. So before exiting, check queue head again (using
8453d6b640eSAnirudh Venkataramanan 	 * ice_ctrlq_pending) and process new messages if any.
8463d6b640eSAnirudh Venkataramanan 	 */
8473d6b640eSAnirudh Venkataramanan 	if (ice_ctrlq_pending(hw, &hw->adminq))
8483d6b640eSAnirudh Venkataramanan 		__ice_clean_ctrlq(pf, ICE_CTL_Q_ADMIN);
849940b61afSAnirudh Venkataramanan 
850940b61afSAnirudh Venkataramanan 	ice_flush(hw);
851940b61afSAnirudh Venkataramanan }
852940b61afSAnirudh Venkataramanan 
853940b61afSAnirudh Venkataramanan /**
854940b61afSAnirudh Venkataramanan  * ice_service_task_schedule - schedule the service task to wake up
855940b61afSAnirudh Venkataramanan  * @pf: board private structure
856940b61afSAnirudh Venkataramanan  *
857940b61afSAnirudh Venkataramanan  * If not already scheduled, this puts the task into the work queue.
858940b61afSAnirudh Venkataramanan  */
859940b61afSAnirudh Venkataramanan static void ice_service_task_schedule(struct ice_pf *pf)
860940b61afSAnirudh Venkataramanan {
8618d81fa55SAkeem G Abodunrin 	if (!test_bit(__ICE_SERVICE_DIS, pf->state) &&
8620f9d5027SAnirudh Venkataramanan 	    !test_and_set_bit(__ICE_SERVICE_SCHED, pf->state) &&
8630f9d5027SAnirudh Venkataramanan 	    !test_bit(__ICE_NEEDS_RESTART, pf->state))
864940b61afSAnirudh Venkataramanan 		queue_work(ice_wq, &pf->serv_task);
865940b61afSAnirudh Venkataramanan }
866940b61afSAnirudh Venkataramanan 
867940b61afSAnirudh Venkataramanan /**
868940b61afSAnirudh Venkataramanan  * ice_service_task_complete - finish up the service task
869940b61afSAnirudh Venkataramanan  * @pf: board private structure
870940b61afSAnirudh Venkataramanan  */
871940b61afSAnirudh Venkataramanan static void ice_service_task_complete(struct ice_pf *pf)
872940b61afSAnirudh Venkataramanan {
873940b61afSAnirudh Venkataramanan 	WARN_ON(!test_bit(__ICE_SERVICE_SCHED, pf->state));
874940b61afSAnirudh Venkataramanan 
875940b61afSAnirudh Venkataramanan 	/* force memory (pf->state) to sync before next service task */
876940b61afSAnirudh Venkataramanan 	smp_mb__before_atomic();
877940b61afSAnirudh Venkataramanan 	clear_bit(__ICE_SERVICE_SCHED, pf->state);
878940b61afSAnirudh Venkataramanan }
879940b61afSAnirudh Venkataramanan 
880940b61afSAnirudh Venkataramanan /**
8818d81fa55SAkeem G Abodunrin  * ice_service_task_stop - stop service task and cancel works
8828d81fa55SAkeem G Abodunrin  * @pf: board private structure
8838d81fa55SAkeem G Abodunrin  */
8848d81fa55SAkeem G Abodunrin static void ice_service_task_stop(struct ice_pf *pf)
8858d81fa55SAkeem G Abodunrin {
8868d81fa55SAkeem G Abodunrin 	set_bit(__ICE_SERVICE_DIS, pf->state);
8878d81fa55SAkeem G Abodunrin 
8888d81fa55SAkeem G Abodunrin 	if (pf->serv_tmr.function)
8898d81fa55SAkeem G Abodunrin 		del_timer_sync(&pf->serv_tmr);
8908d81fa55SAkeem G Abodunrin 	if (pf->serv_task.func)
8918d81fa55SAkeem G Abodunrin 		cancel_work_sync(&pf->serv_task);
8928d81fa55SAkeem G Abodunrin 
8938d81fa55SAkeem G Abodunrin 	clear_bit(__ICE_SERVICE_SCHED, pf->state);
8948d81fa55SAkeem G Abodunrin }
8958d81fa55SAkeem G Abodunrin 
8968d81fa55SAkeem G Abodunrin /**
897940b61afSAnirudh Venkataramanan  * ice_service_timer - timer callback to schedule service task
898940b61afSAnirudh Venkataramanan  * @t: pointer to timer_list
899940b61afSAnirudh Venkataramanan  */
900940b61afSAnirudh Venkataramanan static void ice_service_timer(struct timer_list *t)
901940b61afSAnirudh Venkataramanan {
902940b61afSAnirudh Venkataramanan 	struct ice_pf *pf = from_timer(pf, t, serv_tmr);
903940b61afSAnirudh Venkataramanan 
904940b61afSAnirudh Venkataramanan 	mod_timer(&pf->serv_tmr, round_jiffies(pf->serv_tmr_period + jiffies));
905940b61afSAnirudh Venkataramanan 	ice_service_task_schedule(pf);
906940b61afSAnirudh Venkataramanan }
907940b61afSAnirudh Venkataramanan 
908940b61afSAnirudh Venkataramanan /**
909b3969fd7SSudheer Mogilappagari  * ice_handle_mdd_event - handle malicious driver detect event
910b3969fd7SSudheer Mogilappagari  * @pf: pointer to the PF structure
911b3969fd7SSudheer Mogilappagari  *
912b3969fd7SSudheer Mogilappagari  * Called from service task. OICR interrupt handler indicates MDD event
913b3969fd7SSudheer Mogilappagari  */
914b3969fd7SSudheer Mogilappagari static void ice_handle_mdd_event(struct ice_pf *pf)
915b3969fd7SSudheer Mogilappagari {
916b3969fd7SSudheer Mogilappagari 	struct ice_hw *hw = &pf->hw;
917b3969fd7SSudheer Mogilappagari 	bool mdd_detected = false;
918b3969fd7SSudheer Mogilappagari 	u32 reg;
919b3969fd7SSudheer Mogilappagari 
920b3969fd7SSudheer Mogilappagari 	if (!test_bit(__ICE_MDD_EVENT_PENDING, pf->state))
921b3969fd7SSudheer Mogilappagari 		return;
922b3969fd7SSudheer Mogilappagari 
923b3969fd7SSudheer Mogilappagari 	/* find what triggered the MDD event */
924b3969fd7SSudheer Mogilappagari 	reg = rd32(hw, GL_MDET_TX_PQM);
925b3969fd7SSudheer Mogilappagari 	if (reg & GL_MDET_TX_PQM_VALID_M) {
926b3969fd7SSudheer Mogilappagari 		u8 pf_num = (reg & GL_MDET_TX_PQM_PF_NUM_M) >>
927b3969fd7SSudheer Mogilappagari 				GL_MDET_TX_PQM_PF_NUM_S;
928b3969fd7SSudheer Mogilappagari 		u16 vf_num = (reg & GL_MDET_TX_PQM_VF_NUM_M) >>
929b3969fd7SSudheer Mogilappagari 				GL_MDET_TX_PQM_VF_NUM_S;
930b3969fd7SSudheer Mogilappagari 		u8 event = (reg & GL_MDET_TX_PQM_MAL_TYPE_M) >>
931b3969fd7SSudheer Mogilappagari 				GL_MDET_TX_PQM_MAL_TYPE_S;
932b3969fd7SSudheer Mogilappagari 		u16 queue = ((reg & GL_MDET_TX_PQM_QNUM_M) >>
933b3969fd7SSudheer Mogilappagari 				GL_MDET_TX_PQM_QNUM_S);
934b3969fd7SSudheer Mogilappagari 
935b3969fd7SSudheer Mogilappagari 		if (netif_msg_tx_err(pf))
936b3969fd7SSudheer Mogilappagari 			dev_info(&pf->pdev->dev, "Malicious Driver Detection event %d on TX queue %d PF# %d VF# %d\n",
937b3969fd7SSudheer Mogilappagari 				 event, queue, pf_num, vf_num);
938b3969fd7SSudheer Mogilappagari 		wr32(hw, GL_MDET_TX_PQM, 0xffffffff);
939b3969fd7SSudheer Mogilappagari 		mdd_detected = true;
940b3969fd7SSudheer Mogilappagari 	}
941b3969fd7SSudheer Mogilappagari 
942b3969fd7SSudheer Mogilappagari 	reg = rd32(hw, GL_MDET_TX_TCLAN);
943b3969fd7SSudheer Mogilappagari 	if (reg & GL_MDET_TX_TCLAN_VALID_M) {
944b3969fd7SSudheer Mogilappagari 		u8 pf_num = (reg & GL_MDET_TX_TCLAN_PF_NUM_M) >>
945b3969fd7SSudheer Mogilappagari 				GL_MDET_TX_TCLAN_PF_NUM_S;
946b3969fd7SSudheer Mogilappagari 		u16 vf_num = (reg & GL_MDET_TX_TCLAN_VF_NUM_M) >>
947b3969fd7SSudheer Mogilappagari 				GL_MDET_TX_TCLAN_VF_NUM_S;
948b3969fd7SSudheer Mogilappagari 		u8 event = (reg & GL_MDET_TX_TCLAN_MAL_TYPE_M) >>
949b3969fd7SSudheer Mogilappagari 				GL_MDET_TX_TCLAN_MAL_TYPE_S;
950b3969fd7SSudheer Mogilappagari 		u16 queue = ((reg & GL_MDET_TX_TCLAN_QNUM_M) >>
951b3969fd7SSudheer Mogilappagari 				GL_MDET_TX_TCLAN_QNUM_S);
952b3969fd7SSudheer Mogilappagari 
953b3969fd7SSudheer Mogilappagari 		if (netif_msg_rx_err(pf))
954b3969fd7SSudheer Mogilappagari 			dev_info(&pf->pdev->dev, "Malicious Driver Detection event %d on TX queue %d PF# %d VF# %d\n",
955b3969fd7SSudheer Mogilappagari 				 event, queue, pf_num, vf_num);
956b3969fd7SSudheer Mogilappagari 		wr32(hw, GL_MDET_TX_TCLAN, 0xffffffff);
957b3969fd7SSudheer Mogilappagari 		mdd_detected = true;
958b3969fd7SSudheer Mogilappagari 	}
959b3969fd7SSudheer Mogilappagari 
960b3969fd7SSudheer Mogilappagari 	reg = rd32(hw, GL_MDET_RX);
961b3969fd7SSudheer Mogilappagari 	if (reg & GL_MDET_RX_VALID_M) {
962b3969fd7SSudheer Mogilappagari 		u8 pf_num = (reg & GL_MDET_RX_PF_NUM_M) >>
963b3969fd7SSudheer Mogilappagari 				GL_MDET_RX_PF_NUM_S;
964b3969fd7SSudheer Mogilappagari 		u16 vf_num = (reg & GL_MDET_RX_VF_NUM_M) >>
965b3969fd7SSudheer Mogilappagari 				GL_MDET_RX_VF_NUM_S;
966b3969fd7SSudheer Mogilappagari 		u8 event = (reg & GL_MDET_RX_MAL_TYPE_M) >>
967b3969fd7SSudheer Mogilappagari 				GL_MDET_RX_MAL_TYPE_S;
968b3969fd7SSudheer Mogilappagari 		u16 queue = ((reg & GL_MDET_RX_QNUM_M) >>
969b3969fd7SSudheer Mogilappagari 				GL_MDET_RX_QNUM_S);
970b3969fd7SSudheer Mogilappagari 
971b3969fd7SSudheer Mogilappagari 		if (netif_msg_rx_err(pf))
972b3969fd7SSudheer Mogilappagari 			dev_info(&pf->pdev->dev, "Malicious Driver Detection event %d on RX queue %d PF# %d VF# %d\n",
973b3969fd7SSudheer Mogilappagari 				 event, queue, pf_num, vf_num);
974b3969fd7SSudheer Mogilappagari 		wr32(hw, GL_MDET_RX, 0xffffffff);
975b3969fd7SSudheer Mogilappagari 		mdd_detected = true;
976b3969fd7SSudheer Mogilappagari 	}
977b3969fd7SSudheer Mogilappagari 
978b3969fd7SSudheer Mogilappagari 	if (mdd_detected) {
979b3969fd7SSudheer Mogilappagari 		bool pf_mdd_detected = false;
980b3969fd7SSudheer Mogilappagari 
981b3969fd7SSudheer Mogilappagari 		reg = rd32(hw, PF_MDET_TX_PQM);
982b3969fd7SSudheer Mogilappagari 		if (reg & PF_MDET_TX_PQM_VALID_M) {
983b3969fd7SSudheer Mogilappagari 			wr32(hw, PF_MDET_TX_PQM, 0xFFFF);
984b3969fd7SSudheer Mogilappagari 			dev_info(&pf->pdev->dev, "TX driver issue detected, PF reset issued\n");
985b3969fd7SSudheer Mogilappagari 			pf_mdd_detected = true;
986b3969fd7SSudheer Mogilappagari 		}
987b3969fd7SSudheer Mogilappagari 
988b3969fd7SSudheer Mogilappagari 		reg = rd32(hw, PF_MDET_TX_TCLAN);
989b3969fd7SSudheer Mogilappagari 		if (reg & PF_MDET_TX_TCLAN_VALID_M) {
990b3969fd7SSudheer Mogilappagari 			wr32(hw, PF_MDET_TX_TCLAN, 0xFFFF);
991b3969fd7SSudheer Mogilappagari 			dev_info(&pf->pdev->dev, "TX driver issue detected, PF reset issued\n");
992b3969fd7SSudheer Mogilappagari 			pf_mdd_detected = true;
993b3969fd7SSudheer Mogilappagari 		}
994b3969fd7SSudheer Mogilappagari 
995b3969fd7SSudheer Mogilappagari 		reg = rd32(hw, PF_MDET_RX);
996b3969fd7SSudheer Mogilappagari 		if (reg & PF_MDET_RX_VALID_M) {
997b3969fd7SSudheer Mogilappagari 			wr32(hw, PF_MDET_RX, 0xFFFF);
998b3969fd7SSudheer Mogilappagari 			dev_info(&pf->pdev->dev, "RX driver issue detected, PF reset issued\n");
999b3969fd7SSudheer Mogilappagari 			pf_mdd_detected = true;
1000b3969fd7SSudheer Mogilappagari 		}
1001b3969fd7SSudheer Mogilappagari 		/* Queue belongs to the PF initiate a reset */
1002b3969fd7SSudheer Mogilappagari 		if (pf_mdd_detected) {
1003b3969fd7SSudheer Mogilappagari 			set_bit(__ICE_NEEDS_RESTART, pf->state);
1004b3969fd7SSudheer Mogilappagari 			ice_service_task_schedule(pf);
1005b3969fd7SSudheer Mogilappagari 		}
1006b3969fd7SSudheer Mogilappagari 	}
1007b3969fd7SSudheer Mogilappagari 
1008b3969fd7SSudheer Mogilappagari 	/* re-enable MDD interrupt cause */
1009b3969fd7SSudheer Mogilappagari 	clear_bit(__ICE_MDD_EVENT_PENDING, pf->state);
1010b3969fd7SSudheer Mogilappagari 	reg = rd32(hw, PFINT_OICR_ENA);
1011b3969fd7SSudheer Mogilappagari 	reg |= PFINT_OICR_MAL_DETECT_M;
1012b3969fd7SSudheer Mogilappagari 	wr32(hw, PFINT_OICR_ENA, reg);
1013b3969fd7SSudheer Mogilappagari 	ice_flush(hw);
1014b3969fd7SSudheer Mogilappagari }
1015b3969fd7SSudheer Mogilappagari 
1016b3969fd7SSudheer Mogilappagari /**
1017940b61afSAnirudh Venkataramanan  * ice_service_task - manage and run subtasks
1018940b61afSAnirudh Venkataramanan  * @work: pointer to work_struct contained by the PF struct
1019940b61afSAnirudh Venkataramanan  */
1020940b61afSAnirudh Venkataramanan static void ice_service_task(struct work_struct *work)
1021940b61afSAnirudh Venkataramanan {
1022940b61afSAnirudh Venkataramanan 	struct ice_pf *pf = container_of(work, struct ice_pf, serv_task);
1023940b61afSAnirudh Venkataramanan 	unsigned long start_time = jiffies;
1024940b61afSAnirudh Venkataramanan 
1025940b61afSAnirudh Venkataramanan 	/* subtasks */
10260b28b702SAnirudh Venkataramanan 
10270b28b702SAnirudh Venkataramanan 	/* process reset requests first */
10280b28b702SAnirudh Venkataramanan 	ice_reset_subtask(pf);
10290b28b702SAnirudh Venkataramanan 
10300f9d5027SAnirudh Venkataramanan 	/* bail if a reset/recovery cycle is pending or rebuild failed */
10315df7e45dSDave Ertman 	if (ice_is_reset_in_progress(pf->state) ||
10320f9d5027SAnirudh Venkataramanan 	    test_bit(__ICE_SUSPENDED, pf->state) ||
10330f9d5027SAnirudh Venkataramanan 	    test_bit(__ICE_NEEDS_RESTART, pf->state)) {
10340b28b702SAnirudh Venkataramanan 		ice_service_task_complete(pf);
10350b28b702SAnirudh Venkataramanan 		return;
10360b28b702SAnirudh Venkataramanan 	}
10370b28b702SAnirudh Venkataramanan 
1038b3969fd7SSudheer Mogilappagari 	ice_check_for_hang_subtask(pf);
1039e94d4478SAnirudh Venkataramanan 	ice_sync_fltr_subtask(pf);
1040b3969fd7SSudheer Mogilappagari 	ice_handle_mdd_event(pf);
1041fcea6f3dSAnirudh Venkataramanan 	ice_watchdog_subtask(pf);
1042940b61afSAnirudh Venkataramanan 	ice_clean_adminq_subtask(pf);
1043940b61afSAnirudh Venkataramanan 
1044940b61afSAnirudh Venkataramanan 	/* Clear __ICE_SERVICE_SCHED flag to allow scheduling next event */
1045940b61afSAnirudh Venkataramanan 	ice_service_task_complete(pf);
1046940b61afSAnirudh Venkataramanan 
1047940b61afSAnirudh Venkataramanan 	/* If the tasks have taken longer than one service timer period
1048940b61afSAnirudh Venkataramanan 	 * or there is more work to be done, reset the service timer to
1049940b61afSAnirudh Venkataramanan 	 * schedule the service task now.
1050940b61afSAnirudh Venkataramanan 	 */
1051940b61afSAnirudh Venkataramanan 	if (time_after(jiffies, (start_time + pf->serv_tmr_period)) ||
1052b3969fd7SSudheer Mogilappagari 	    test_bit(__ICE_MDD_EVENT_PENDING, pf->state) ||
1053940b61afSAnirudh Venkataramanan 	    test_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state))
1054940b61afSAnirudh Venkataramanan 		mod_timer(&pf->serv_tmr, jiffies);
1055940b61afSAnirudh Venkataramanan }
1056940b61afSAnirudh Venkataramanan 
1057837f08fdSAnirudh Venkataramanan /**
1058f31e4b6fSAnirudh Venkataramanan  * ice_set_ctrlq_len - helper function to set controlq length
1059f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hw instance
1060f31e4b6fSAnirudh Venkataramanan  */
1061f31e4b6fSAnirudh Venkataramanan static void ice_set_ctrlq_len(struct ice_hw *hw)
1062f31e4b6fSAnirudh Venkataramanan {
1063f31e4b6fSAnirudh Venkataramanan 	hw->adminq.num_rq_entries = ICE_AQ_LEN;
1064f31e4b6fSAnirudh Venkataramanan 	hw->adminq.num_sq_entries = ICE_AQ_LEN;
1065f31e4b6fSAnirudh Venkataramanan 	hw->adminq.rq_buf_size = ICE_AQ_MAX_BUF_LEN;
1066f31e4b6fSAnirudh Venkataramanan 	hw->adminq.sq_buf_size = ICE_AQ_MAX_BUF_LEN;
1067f31e4b6fSAnirudh Venkataramanan }
1068f31e4b6fSAnirudh Venkataramanan 
1069f31e4b6fSAnirudh Venkataramanan /**
1070cdedef59SAnirudh Venkataramanan  * ice_irq_affinity_notify - Callback for affinity changes
1071cdedef59SAnirudh Venkataramanan  * @notify: context as to what irq was changed
1072cdedef59SAnirudh Venkataramanan  * @mask: the new affinity mask
1073cdedef59SAnirudh Venkataramanan  *
1074cdedef59SAnirudh Venkataramanan  * This is a callback function used by the irq_set_affinity_notifier function
1075cdedef59SAnirudh Venkataramanan  * so that we may register to receive changes to the irq affinity masks.
1076cdedef59SAnirudh Venkataramanan  */
1077cdedef59SAnirudh Venkataramanan static void ice_irq_affinity_notify(struct irq_affinity_notify *notify,
1078cdedef59SAnirudh Venkataramanan 				    const cpumask_t *mask)
1079cdedef59SAnirudh Venkataramanan {
1080cdedef59SAnirudh Venkataramanan 	struct ice_q_vector *q_vector =
1081cdedef59SAnirudh Venkataramanan 		container_of(notify, struct ice_q_vector, affinity_notify);
1082cdedef59SAnirudh Venkataramanan 
1083cdedef59SAnirudh Venkataramanan 	cpumask_copy(&q_vector->affinity_mask, mask);
1084cdedef59SAnirudh Venkataramanan }
1085cdedef59SAnirudh Venkataramanan 
1086cdedef59SAnirudh Venkataramanan /**
1087cdedef59SAnirudh Venkataramanan  * ice_irq_affinity_release - Callback for affinity notifier release
1088cdedef59SAnirudh Venkataramanan  * @ref: internal core kernel usage
1089cdedef59SAnirudh Venkataramanan  *
1090cdedef59SAnirudh Venkataramanan  * This is a callback function used by the irq_set_affinity_notifier function
1091cdedef59SAnirudh Venkataramanan  * to inform the current notification subscriber that they will no longer
1092cdedef59SAnirudh Venkataramanan  * receive notifications.
1093cdedef59SAnirudh Venkataramanan  */
1094cdedef59SAnirudh Venkataramanan static void ice_irq_affinity_release(struct kref __always_unused *ref) {}
1095cdedef59SAnirudh Venkataramanan 
1096cdedef59SAnirudh Venkataramanan /**
1097cdedef59SAnirudh Venkataramanan  * ice_vsi_ena_irq - Enable IRQ for the given VSI
1098cdedef59SAnirudh Venkataramanan  * @vsi: the VSI being configured
1099cdedef59SAnirudh Venkataramanan  */
1100cdedef59SAnirudh Venkataramanan static int ice_vsi_ena_irq(struct ice_vsi *vsi)
1101cdedef59SAnirudh Venkataramanan {
1102cdedef59SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
1103cdedef59SAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
1104cdedef59SAnirudh Venkataramanan 
1105cdedef59SAnirudh Venkataramanan 	if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) {
1106cdedef59SAnirudh Venkataramanan 		int i;
1107cdedef59SAnirudh Venkataramanan 
1108cdedef59SAnirudh Venkataramanan 		for (i = 0; i < vsi->num_q_vectors; i++)
1109cdedef59SAnirudh Venkataramanan 			ice_irq_dynamic_ena(hw, vsi, vsi->q_vectors[i]);
1110cdedef59SAnirudh Venkataramanan 	}
1111cdedef59SAnirudh Venkataramanan 
1112cdedef59SAnirudh Venkataramanan 	ice_flush(hw);
1113cdedef59SAnirudh Venkataramanan 	return 0;
1114cdedef59SAnirudh Venkataramanan }
1115cdedef59SAnirudh Venkataramanan 
1116cdedef59SAnirudh Venkataramanan /**
1117cdedef59SAnirudh Venkataramanan  * ice_vsi_req_irq_msix - get MSI-X vectors from the OS for the VSI
1118cdedef59SAnirudh Venkataramanan  * @vsi: the VSI being configured
1119cdedef59SAnirudh Venkataramanan  * @basename: name for the vector
1120cdedef59SAnirudh Venkataramanan  */
1121cdedef59SAnirudh Venkataramanan static int ice_vsi_req_irq_msix(struct ice_vsi *vsi, char *basename)
1122cdedef59SAnirudh Venkataramanan {
1123cdedef59SAnirudh Venkataramanan 	int q_vectors = vsi->num_q_vectors;
1124cdedef59SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
1125cdedef59SAnirudh Venkataramanan 	int base = vsi->base_vector;
1126cdedef59SAnirudh Venkataramanan 	int rx_int_idx = 0;
1127cdedef59SAnirudh Venkataramanan 	int tx_int_idx = 0;
1128cdedef59SAnirudh Venkataramanan 	int vector, err;
1129cdedef59SAnirudh Venkataramanan 	int irq_num;
1130cdedef59SAnirudh Venkataramanan 
1131cdedef59SAnirudh Venkataramanan 	for (vector = 0; vector < q_vectors; vector++) {
1132cdedef59SAnirudh Venkataramanan 		struct ice_q_vector *q_vector = vsi->q_vectors[vector];
1133cdedef59SAnirudh Venkataramanan 
1134cdedef59SAnirudh Venkataramanan 		irq_num = pf->msix_entries[base + vector].vector;
1135cdedef59SAnirudh Venkataramanan 
1136cdedef59SAnirudh Venkataramanan 		if (q_vector->tx.ring && q_vector->rx.ring) {
1137cdedef59SAnirudh Venkataramanan 			snprintf(q_vector->name, sizeof(q_vector->name) - 1,
1138cdedef59SAnirudh Venkataramanan 				 "%s-%s-%d", basename, "TxRx", rx_int_idx++);
1139cdedef59SAnirudh Venkataramanan 			tx_int_idx++;
1140cdedef59SAnirudh Venkataramanan 		} else if (q_vector->rx.ring) {
1141cdedef59SAnirudh Venkataramanan 			snprintf(q_vector->name, sizeof(q_vector->name) - 1,
1142cdedef59SAnirudh Venkataramanan 				 "%s-%s-%d", basename, "rx", rx_int_idx++);
1143cdedef59SAnirudh Venkataramanan 		} else if (q_vector->tx.ring) {
1144cdedef59SAnirudh Venkataramanan 			snprintf(q_vector->name, sizeof(q_vector->name) - 1,
1145cdedef59SAnirudh Venkataramanan 				 "%s-%s-%d", basename, "tx", tx_int_idx++);
1146cdedef59SAnirudh Venkataramanan 		} else {
1147cdedef59SAnirudh Venkataramanan 			/* skip this unused q_vector */
1148cdedef59SAnirudh Venkataramanan 			continue;
1149cdedef59SAnirudh Venkataramanan 		}
1150cdedef59SAnirudh Venkataramanan 		err = devm_request_irq(&pf->pdev->dev,
1151cdedef59SAnirudh Venkataramanan 				       pf->msix_entries[base + vector].vector,
1152cdedef59SAnirudh Venkataramanan 				       vsi->irq_handler, 0, q_vector->name,
1153cdedef59SAnirudh Venkataramanan 				       q_vector);
1154cdedef59SAnirudh Venkataramanan 		if (err) {
1155cdedef59SAnirudh Venkataramanan 			netdev_err(vsi->netdev,
1156cdedef59SAnirudh Venkataramanan 				   "MSIX request_irq failed, error: %d\n", err);
1157cdedef59SAnirudh Venkataramanan 			goto free_q_irqs;
1158cdedef59SAnirudh Venkataramanan 		}
1159cdedef59SAnirudh Venkataramanan 
1160cdedef59SAnirudh Venkataramanan 		/* register for affinity change notifications */
1161cdedef59SAnirudh Venkataramanan 		q_vector->affinity_notify.notify = ice_irq_affinity_notify;
1162cdedef59SAnirudh Venkataramanan 		q_vector->affinity_notify.release = ice_irq_affinity_release;
1163cdedef59SAnirudh Venkataramanan 		irq_set_affinity_notifier(irq_num, &q_vector->affinity_notify);
1164cdedef59SAnirudh Venkataramanan 
1165cdedef59SAnirudh Venkataramanan 		/* assign the mask for this irq */
1166cdedef59SAnirudh Venkataramanan 		irq_set_affinity_hint(irq_num, &q_vector->affinity_mask);
1167cdedef59SAnirudh Venkataramanan 	}
1168cdedef59SAnirudh Venkataramanan 
1169cdedef59SAnirudh Venkataramanan 	vsi->irqs_ready = true;
1170cdedef59SAnirudh Venkataramanan 	return 0;
1171cdedef59SAnirudh Venkataramanan 
1172cdedef59SAnirudh Venkataramanan free_q_irqs:
1173cdedef59SAnirudh Venkataramanan 	while (vector) {
1174cdedef59SAnirudh Venkataramanan 		vector--;
1175cdedef59SAnirudh Venkataramanan 		irq_num = pf->msix_entries[base + vector].vector,
1176cdedef59SAnirudh Venkataramanan 		irq_set_affinity_notifier(irq_num, NULL);
1177cdedef59SAnirudh Venkataramanan 		irq_set_affinity_hint(irq_num, NULL);
1178cdedef59SAnirudh Venkataramanan 		devm_free_irq(&pf->pdev->dev, irq_num, &vsi->q_vectors[vector]);
1179cdedef59SAnirudh Venkataramanan 	}
1180cdedef59SAnirudh Venkataramanan 	return err;
1181cdedef59SAnirudh Venkataramanan }
1182cdedef59SAnirudh Venkataramanan 
1183cdedef59SAnirudh Venkataramanan /**
1184940b61afSAnirudh Venkataramanan  * ice_ena_misc_vector - enable the non-queue interrupts
1185940b61afSAnirudh Venkataramanan  * @pf: board private structure
1186940b61afSAnirudh Venkataramanan  */
1187940b61afSAnirudh Venkataramanan static void ice_ena_misc_vector(struct ice_pf *pf)
1188940b61afSAnirudh Venkataramanan {
1189940b61afSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
1190940b61afSAnirudh Venkataramanan 	u32 val;
1191940b61afSAnirudh Venkataramanan 
1192940b61afSAnirudh Venkataramanan 	/* clear things first */
1193940b61afSAnirudh Venkataramanan 	wr32(hw, PFINT_OICR_ENA, 0);	/* disable all */
1194940b61afSAnirudh Venkataramanan 	rd32(hw, PFINT_OICR);		/* read to clear */
1195940b61afSAnirudh Venkataramanan 
11963bcd7fa3SBruce Allan 	val = (PFINT_OICR_ECC_ERR_M |
1197940b61afSAnirudh Venkataramanan 	       PFINT_OICR_MAL_DETECT_M |
1198940b61afSAnirudh Venkataramanan 	       PFINT_OICR_GRST_M |
1199940b61afSAnirudh Venkataramanan 	       PFINT_OICR_PCI_EXCEPTION_M |
12003bcd7fa3SBruce Allan 	       PFINT_OICR_HMC_ERR_M |
12013bcd7fa3SBruce Allan 	       PFINT_OICR_PE_CRITERR_M);
1202940b61afSAnirudh Venkataramanan 
1203940b61afSAnirudh Venkataramanan 	wr32(hw, PFINT_OICR_ENA, val);
1204940b61afSAnirudh Venkataramanan 
1205940b61afSAnirudh Venkataramanan 	/* SW_ITR_IDX = 0, but don't change INTENA */
1206940b61afSAnirudh Venkataramanan 	wr32(hw, GLINT_DYN_CTL(pf->oicr_idx),
1207940b61afSAnirudh Venkataramanan 	     GLINT_DYN_CTL_SW_ITR_INDX_M | GLINT_DYN_CTL_INTENA_MSK_M);
1208940b61afSAnirudh Venkataramanan }
1209940b61afSAnirudh Venkataramanan 
1210940b61afSAnirudh Venkataramanan /**
1211940b61afSAnirudh Venkataramanan  * ice_misc_intr - misc interrupt handler
1212940b61afSAnirudh Venkataramanan  * @irq: interrupt number
1213940b61afSAnirudh Venkataramanan  * @data: pointer to a q_vector
1214940b61afSAnirudh Venkataramanan  */
1215940b61afSAnirudh Venkataramanan static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
1216940b61afSAnirudh Venkataramanan {
1217940b61afSAnirudh Venkataramanan 	struct ice_pf *pf = (struct ice_pf *)data;
1218940b61afSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
1219940b61afSAnirudh Venkataramanan 	irqreturn_t ret = IRQ_NONE;
1220940b61afSAnirudh Venkataramanan 	u32 oicr, ena_mask;
1221940b61afSAnirudh Venkataramanan 
1222940b61afSAnirudh Venkataramanan 	set_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state);
1223940b61afSAnirudh Venkataramanan 
1224940b61afSAnirudh Venkataramanan 	oicr = rd32(hw, PFINT_OICR);
1225940b61afSAnirudh Venkataramanan 	ena_mask = rd32(hw, PFINT_OICR_ENA);
1226940b61afSAnirudh Venkataramanan 
1227b3969fd7SSudheer Mogilappagari 	if (oicr & PFINT_OICR_MAL_DETECT_M) {
1228b3969fd7SSudheer Mogilappagari 		ena_mask &= ~PFINT_OICR_MAL_DETECT_M;
1229b3969fd7SSudheer Mogilappagari 		set_bit(__ICE_MDD_EVENT_PENDING, pf->state);
1230b3969fd7SSudheer Mogilappagari 	}
1231b3969fd7SSudheer Mogilappagari 
12320b28b702SAnirudh Venkataramanan 	if (oicr & PFINT_OICR_GRST_M) {
12330b28b702SAnirudh Venkataramanan 		u32 reset;
1234b3969fd7SSudheer Mogilappagari 
12350b28b702SAnirudh Venkataramanan 		/* we have a reset warning */
12360b28b702SAnirudh Venkataramanan 		ena_mask &= ~PFINT_OICR_GRST_M;
12370b28b702SAnirudh Venkataramanan 		reset = (rd32(hw, GLGEN_RSTAT) & GLGEN_RSTAT_RESET_TYPE_M) >>
12380b28b702SAnirudh Venkataramanan 			GLGEN_RSTAT_RESET_TYPE_S;
12390b28b702SAnirudh Venkataramanan 
12400b28b702SAnirudh Venkataramanan 		if (reset == ICE_RESET_CORER)
12410b28b702SAnirudh Venkataramanan 			pf->corer_count++;
12420b28b702SAnirudh Venkataramanan 		else if (reset == ICE_RESET_GLOBR)
12430b28b702SAnirudh Venkataramanan 			pf->globr_count++;
12440b28b702SAnirudh Venkataramanan 		else
12450b28b702SAnirudh Venkataramanan 			pf->empr_count++;
12460b28b702SAnirudh Venkataramanan 
12470b28b702SAnirudh Venkataramanan 		/* If a reset cycle isn't already in progress, we set a bit in
12480b28b702SAnirudh Venkataramanan 		 * pf->state so that the service task can start a reset/rebuild.
12490b28b702SAnirudh Venkataramanan 		 * We also make note of which reset happened so that peer
12500b28b702SAnirudh Venkataramanan 		 * devices/drivers can be informed.
12510b28b702SAnirudh Venkataramanan 		 */
12525df7e45dSDave Ertman 		if (!test_and_set_bit(__ICE_RESET_OICR_RECV, pf->state)) {
12530b28b702SAnirudh Venkataramanan 			if (reset == ICE_RESET_CORER)
12540b28b702SAnirudh Venkataramanan 				set_bit(__ICE_CORER_RECV, pf->state);
12550b28b702SAnirudh Venkataramanan 			else if (reset == ICE_RESET_GLOBR)
12560b28b702SAnirudh Venkataramanan 				set_bit(__ICE_GLOBR_RECV, pf->state);
12570b28b702SAnirudh Venkataramanan 			else
12580b28b702SAnirudh Venkataramanan 				set_bit(__ICE_EMPR_RECV, pf->state);
12590b28b702SAnirudh Venkataramanan 
1260fd2a9817SAnirudh Venkataramanan 			/* There are couple of different bits at play here.
1261fd2a9817SAnirudh Venkataramanan 			 * hw->reset_ongoing indicates whether the hardware is
1262fd2a9817SAnirudh Venkataramanan 			 * in reset. This is set to true when a reset interrupt
1263fd2a9817SAnirudh Venkataramanan 			 * is received and set back to false after the driver
1264fd2a9817SAnirudh Venkataramanan 			 * has determined that the hardware is out of reset.
1265fd2a9817SAnirudh Venkataramanan 			 *
12665df7e45dSDave Ertman 			 * __ICE_RESET_OICR_RECV in pf->state indicates
1267fd2a9817SAnirudh Venkataramanan 			 * that a post reset rebuild is required before the
1268fd2a9817SAnirudh Venkataramanan 			 * driver is operational again. This is set above.
1269fd2a9817SAnirudh Venkataramanan 			 *
1270fd2a9817SAnirudh Venkataramanan 			 * As this is the start of the reset/rebuild cycle, set
1271fd2a9817SAnirudh Venkataramanan 			 * both to indicate that.
1272fd2a9817SAnirudh Venkataramanan 			 */
1273fd2a9817SAnirudh Venkataramanan 			hw->reset_ongoing = true;
12740b28b702SAnirudh Venkataramanan 		}
12750b28b702SAnirudh Venkataramanan 	}
12760b28b702SAnirudh Venkataramanan 
1277940b61afSAnirudh Venkataramanan 	if (oicr & PFINT_OICR_HMC_ERR_M) {
1278940b61afSAnirudh Venkataramanan 		ena_mask &= ~PFINT_OICR_HMC_ERR_M;
1279940b61afSAnirudh Venkataramanan 		dev_dbg(&pf->pdev->dev,
1280940b61afSAnirudh Venkataramanan 			"HMC Error interrupt - info 0x%x, data 0x%x\n",
1281940b61afSAnirudh Venkataramanan 			rd32(hw, PFHMC_ERRORINFO),
1282940b61afSAnirudh Venkataramanan 			rd32(hw, PFHMC_ERRORDATA));
1283940b61afSAnirudh Venkataramanan 	}
1284940b61afSAnirudh Venkataramanan 
1285940b61afSAnirudh Venkataramanan 	/* Report and mask off any remaining unexpected interrupts */
1286940b61afSAnirudh Venkataramanan 	oicr &= ena_mask;
1287940b61afSAnirudh Venkataramanan 	if (oicr) {
1288940b61afSAnirudh Venkataramanan 		dev_dbg(&pf->pdev->dev, "unhandled interrupt oicr=0x%08x\n",
1289940b61afSAnirudh Venkataramanan 			oicr);
1290940b61afSAnirudh Venkataramanan 		/* If a critical error is pending there is no choice but to
1291940b61afSAnirudh Venkataramanan 		 * reset the device.
1292940b61afSAnirudh Venkataramanan 		 */
1293940b61afSAnirudh Venkataramanan 		if (oicr & (PFINT_OICR_PE_CRITERR_M |
1294940b61afSAnirudh Venkataramanan 			    PFINT_OICR_PCI_EXCEPTION_M |
12950b28b702SAnirudh Venkataramanan 			    PFINT_OICR_ECC_ERR_M)) {
1296940b61afSAnirudh Venkataramanan 			set_bit(__ICE_PFR_REQ, pf->state);
12970b28b702SAnirudh Venkataramanan 			ice_service_task_schedule(pf);
12980b28b702SAnirudh Venkataramanan 		}
1299940b61afSAnirudh Venkataramanan 		ena_mask &= ~oicr;
1300940b61afSAnirudh Venkataramanan 	}
1301940b61afSAnirudh Venkataramanan 	ret = IRQ_HANDLED;
1302940b61afSAnirudh Venkataramanan 
1303940b61afSAnirudh Venkataramanan 	/* re-enable interrupt causes that are not handled during this pass */
1304940b61afSAnirudh Venkataramanan 	wr32(hw, PFINT_OICR_ENA, ena_mask);
1305940b61afSAnirudh Venkataramanan 	if (!test_bit(__ICE_DOWN, pf->state)) {
1306940b61afSAnirudh Venkataramanan 		ice_service_task_schedule(pf);
1307cdedef59SAnirudh Venkataramanan 		ice_irq_dynamic_ena(hw, NULL, NULL);
1308940b61afSAnirudh Venkataramanan 	}
1309940b61afSAnirudh Venkataramanan 
1310940b61afSAnirudh Venkataramanan 	return ret;
1311940b61afSAnirudh Venkataramanan }
1312940b61afSAnirudh Venkataramanan 
1313940b61afSAnirudh Venkataramanan /**
1314940b61afSAnirudh Venkataramanan  * ice_free_irq_msix_misc - Unroll misc vector setup
1315940b61afSAnirudh Venkataramanan  * @pf: board private structure
1316940b61afSAnirudh Venkataramanan  */
1317940b61afSAnirudh Venkataramanan static void ice_free_irq_msix_misc(struct ice_pf *pf)
1318940b61afSAnirudh Venkataramanan {
1319940b61afSAnirudh Venkataramanan 	/* disable OICR interrupt */
1320940b61afSAnirudh Venkataramanan 	wr32(&pf->hw, PFINT_OICR_ENA, 0);
1321940b61afSAnirudh Venkataramanan 	ice_flush(&pf->hw);
1322940b61afSAnirudh Venkataramanan 
1323940b61afSAnirudh Venkataramanan 	if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags) && pf->msix_entries) {
1324940b61afSAnirudh Venkataramanan 		synchronize_irq(pf->msix_entries[pf->oicr_idx].vector);
1325940b61afSAnirudh Venkataramanan 		devm_free_irq(&pf->pdev->dev,
1326940b61afSAnirudh Venkataramanan 			      pf->msix_entries[pf->oicr_idx].vector, pf);
1327940b61afSAnirudh Venkataramanan 	}
1328940b61afSAnirudh Venkataramanan 
1329940b61afSAnirudh Venkataramanan 	ice_free_res(pf->irq_tracker, pf->oicr_idx, ICE_RES_MISC_VEC_ID);
1330940b61afSAnirudh Venkataramanan }
1331940b61afSAnirudh Venkataramanan 
1332940b61afSAnirudh Venkataramanan /**
1333940b61afSAnirudh Venkataramanan  * ice_req_irq_msix_misc - Setup the misc vector to handle non queue events
1334940b61afSAnirudh Venkataramanan  * @pf: board private structure
1335940b61afSAnirudh Venkataramanan  *
1336940b61afSAnirudh Venkataramanan  * This sets up the handler for MSIX 0, which is used to manage the
1337940b61afSAnirudh Venkataramanan  * non-queue interrupts, e.g. AdminQ and errors.  This is not used
1338940b61afSAnirudh Venkataramanan  * when in MSI or Legacy interrupt mode.
1339940b61afSAnirudh Venkataramanan  */
1340940b61afSAnirudh Venkataramanan static int ice_req_irq_msix_misc(struct ice_pf *pf)
1341940b61afSAnirudh Venkataramanan {
1342940b61afSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
1343940b61afSAnirudh Venkataramanan 	int oicr_idx, err = 0;
1344940b61afSAnirudh Venkataramanan 	u8 itr_gran;
1345940b61afSAnirudh Venkataramanan 	u32 val;
1346940b61afSAnirudh Venkataramanan 
1347940b61afSAnirudh Venkataramanan 	if (!pf->int_name[0])
1348940b61afSAnirudh Venkataramanan 		snprintf(pf->int_name, sizeof(pf->int_name) - 1, "%s-%s:misc",
1349940b61afSAnirudh Venkataramanan 			 dev_driver_string(&pf->pdev->dev),
1350940b61afSAnirudh Venkataramanan 			 dev_name(&pf->pdev->dev));
1351940b61afSAnirudh Venkataramanan 
13520b28b702SAnirudh Venkataramanan 	/* Do not request IRQ but do enable OICR interrupt since settings are
13530b28b702SAnirudh Venkataramanan 	 * lost during reset. Note that this function is called only during
13540b28b702SAnirudh Venkataramanan 	 * rebuild path and not while reset is in progress.
13550b28b702SAnirudh Venkataramanan 	 */
13565df7e45dSDave Ertman 	if (ice_is_reset_in_progress(pf->state))
13570b28b702SAnirudh Venkataramanan 		goto skip_req_irq;
13580b28b702SAnirudh Venkataramanan 
1359940b61afSAnirudh Venkataramanan 	/* reserve one vector in irq_tracker for misc interrupts */
1360940b61afSAnirudh Venkataramanan 	oicr_idx = ice_get_res(pf, pf->irq_tracker, 1, ICE_RES_MISC_VEC_ID);
1361940b61afSAnirudh Venkataramanan 	if (oicr_idx < 0)
1362940b61afSAnirudh Venkataramanan 		return oicr_idx;
1363940b61afSAnirudh Venkataramanan 
1364940b61afSAnirudh Venkataramanan 	pf->oicr_idx = oicr_idx;
1365940b61afSAnirudh Venkataramanan 
1366940b61afSAnirudh Venkataramanan 	err = devm_request_irq(&pf->pdev->dev,
1367940b61afSAnirudh Venkataramanan 			       pf->msix_entries[pf->oicr_idx].vector,
1368940b61afSAnirudh Venkataramanan 			       ice_misc_intr, 0, pf->int_name, pf);
1369940b61afSAnirudh Venkataramanan 	if (err) {
1370940b61afSAnirudh Venkataramanan 		dev_err(&pf->pdev->dev,
1371940b61afSAnirudh Venkataramanan 			"devm_request_irq for %s failed: %d\n",
1372940b61afSAnirudh Venkataramanan 			pf->int_name, err);
1373940b61afSAnirudh Venkataramanan 		ice_free_res(pf->irq_tracker, 1, ICE_RES_MISC_VEC_ID);
1374940b61afSAnirudh Venkataramanan 		return err;
1375940b61afSAnirudh Venkataramanan 	}
1376940b61afSAnirudh Venkataramanan 
13770b28b702SAnirudh Venkataramanan skip_req_irq:
1378940b61afSAnirudh Venkataramanan 	ice_ena_misc_vector(pf);
1379940b61afSAnirudh Venkataramanan 
13804381147dSAnirudh Venkataramanan 	val = ((pf->oicr_idx & PFINT_OICR_CTL_MSIX_INDX_M) |
13814381147dSAnirudh Venkataramanan 	       PFINT_OICR_CTL_CAUSE_ENA_M);
1382940b61afSAnirudh Venkataramanan 	wr32(hw, PFINT_OICR_CTL, val);
1383940b61afSAnirudh Venkataramanan 
1384940b61afSAnirudh Venkataramanan 	/* This enables Admin queue Interrupt causes */
13854381147dSAnirudh Venkataramanan 	val = ((pf->oicr_idx & PFINT_FW_CTL_MSIX_INDX_M) |
13864381147dSAnirudh Venkataramanan 	       PFINT_FW_CTL_CAUSE_ENA_M);
1387940b61afSAnirudh Venkataramanan 	wr32(hw, PFINT_FW_CTL, val);
1388940b61afSAnirudh Venkataramanan 
1389940b61afSAnirudh Venkataramanan 	itr_gran = hw->itr_gran_200;
1390940b61afSAnirudh Venkataramanan 
1391940b61afSAnirudh Venkataramanan 	wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->oicr_idx),
1392940b61afSAnirudh Venkataramanan 	     ITR_TO_REG(ICE_ITR_8K, itr_gran));
1393940b61afSAnirudh Venkataramanan 
1394940b61afSAnirudh Venkataramanan 	ice_flush(hw);
1395cdedef59SAnirudh Venkataramanan 	ice_irq_dynamic_ena(hw, NULL, NULL);
1396940b61afSAnirudh Venkataramanan 
1397940b61afSAnirudh Venkataramanan 	return 0;
1398940b61afSAnirudh Venkataramanan }
1399940b61afSAnirudh Venkataramanan 
1400940b61afSAnirudh Venkataramanan /**
1401df0f8479SAnirudh Venkataramanan  * ice_napi_del - Remove NAPI handler for the VSI
1402df0f8479SAnirudh Venkataramanan  * @vsi: VSI for which NAPI handler is to be removed
14033a858ba3SAnirudh Venkataramanan  */
1404df0f8479SAnirudh Venkataramanan static void ice_napi_del(struct ice_vsi *vsi)
14053a858ba3SAnirudh Venkataramanan {
14063a858ba3SAnirudh Venkataramanan 	int v_idx;
14073a858ba3SAnirudh Venkataramanan 
1408df0f8479SAnirudh Venkataramanan 	if (!vsi->netdev)
1409df0f8479SAnirudh Venkataramanan 		return;
1410df0f8479SAnirudh Venkataramanan 
14113a858ba3SAnirudh Venkataramanan 	for (v_idx = 0; v_idx < vsi->num_q_vectors; v_idx++)
1412df0f8479SAnirudh Venkataramanan 		netif_napi_del(&vsi->q_vectors[v_idx]->napi);
14133a858ba3SAnirudh Venkataramanan }
14143a858ba3SAnirudh Venkataramanan 
14153a858ba3SAnirudh Venkataramanan /**
1416df0f8479SAnirudh Venkataramanan  * ice_napi_add - register NAPI handler for the VSI
1417df0f8479SAnirudh Venkataramanan  * @vsi: VSI for which NAPI handler is to be registered
1418df0f8479SAnirudh Venkataramanan  *
1419df0f8479SAnirudh Venkataramanan  * This function is only called in the driver's load path. Registering the NAPI
1420df0f8479SAnirudh Venkataramanan  * handler is done in ice_vsi_alloc_q_vector() for all other cases (i.e. resume,
1421df0f8479SAnirudh Venkataramanan  * reset/rebuild, etc.)
1422df0f8479SAnirudh Venkataramanan  */
1423df0f8479SAnirudh Venkataramanan static void ice_napi_add(struct ice_vsi *vsi)
1424df0f8479SAnirudh Venkataramanan {
1425df0f8479SAnirudh Venkataramanan 	int v_idx;
1426df0f8479SAnirudh Venkataramanan 
1427df0f8479SAnirudh Venkataramanan 	if (!vsi->netdev)
1428df0f8479SAnirudh Venkataramanan 		return;
1429df0f8479SAnirudh Venkataramanan 
1430df0f8479SAnirudh Venkataramanan 	for (v_idx = 0; v_idx < vsi->num_q_vectors; v_idx++)
1431df0f8479SAnirudh Venkataramanan 		netif_napi_add(vsi->netdev, &vsi->q_vectors[v_idx]->napi,
1432df0f8479SAnirudh Venkataramanan 			       ice_napi_poll, NAPI_POLL_WEIGHT);
1433df0f8479SAnirudh Venkataramanan }
1434df0f8479SAnirudh Venkataramanan 
1435df0f8479SAnirudh Venkataramanan /**
1436df0f8479SAnirudh Venkataramanan  * ice_cfg_netdev - Allocate, configure and register a netdev
1437df0f8479SAnirudh Venkataramanan  * @vsi: the VSI associated with the new netdev
14383a858ba3SAnirudh Venkataramanan  *
14393a858ba3SAnirudh Venkataramanan  * Returns 0 on success, negative value on failure
14403a858ba3SAnirudh Venkataramanan  */
14413a858ba3SAnirudh Venkataramanan static int ice_cfg_netdev(struct ice_vsi *vsi)
14423a858ba3SAnirudh Venkataramanan {
1443d76a60baSAnirudh Venkataramanan 	netdev_features_t csumo_features;
1444d76a60baSAnirudh Venkataramanan 	netdev_features_t vlano_features;
1445d76a60baSAnirudh Venkataramanan 	netdev_features_t dflt_features;
1446d76a60baSAnirudh Venkataramanan 	netdev_features_t tso_features;
14473a858ba3SAnirudh Venkataramanan 	struct ice_netdev_priv *np;
14483a858ba3SAnirudh Venkataramanan 	struct net_device *netdev;
14493a858ba3SAnirudh Venkataramanan 	u8 mac_addr[ETH_ALEN];
1450df0f8479SAnirudh Venkataramanan 	int err;
14513a858ba3SAnirudh Venkataramanan 
14523a858ba3SAnirudh Venkataramanan 	netdev = alloc_etherdev_mqs(sizeof(struct ice_netdev_priv),
14533a858ba3SAnirudh Venkataramanan 				    vsi->alloc_txq, vsi->alloc_rxq);
14543a858ba3SAnirudh Venkataramanan 	if (!netdev)
14553a858ba3SAnirudh Venkataramanan 		return -ENOMEM;
14563a858ba3SAnirudh Venkataramanan 
14573a858ba3SAnirudh Venkataramanan 	vsi->netdev = netdev;
14583a858ba3SAnirudh Venkataramanan 	np = netdev_priv(netdev);
14593a858ba3SAnirudh Venkataramanan 	np->vsi = vsi;
14603a858ba3SAnirudh Venkataramanan 
1461d76a60baSAnirudh Venkataramanan 	dflt_features = NETIF_F_SG	|
14623a858ba3SAnirudh Venkataramanan 			NETIF_F_HIGHDMA	|
14633a858ba3SAnirudh Venkataramanan 			NETIF_F_RXHASH;
14643a858ba3SAnirudh Venkataramanan 
1465d76a60baSAnirudh Venkataramanan 	csumo_features = NETIF_F_RXCSUM	  |
1466d76a60baSAnirudh Venkataramanan 			 NETIF_F_IP_CSUM  |
1467d76a60baSAnirudh Venkataramanan 			 NETIF_F_IPV6_CSUM;
1468d76a60baSAnirudh Venkataramanan 
1469d76a60baSAnirudh Venkataramanan 	vlano_features = NETIF_F_HW_VLAN_CTAG_FILTER |
1470d76a60baSAnirudh Venkataramanan 			 NETIF_F_HW_VLAN_CTAG_TX     |
1471d76a60baSAnirudh Venkataramanan 			 NETIF_F_HW_VLAN_CTAG_RX;
1472d76a60baSAnirudh Venkataramanan 
1473d76a60baSAnirudh Venkataramanan 	tso_features = NETIF_F_TSO;
1474d76a60baSAnirudh Venkataramanan 
1475d76a60baSAnirudh Venkataramanan 	/* set features that user can change */
1476d76a60baSAnirudh Venkataramanan 	netdev->hw_features = dflt_features | csumo_features |
1477d76a60baSAnirudh Venkataramanan 			      vlano_features | tso_features;
1478d76a60baSAnirudh Venkataramanan 
14793a858ba3SAnirudh Venkataramanan 	/* enable features */
14803a858ba3SAnirudh Venkataramanan 	netdev->features |= netdev->hw_features;
1481d76a60baSAnirudh Venkataramanan 	/* encap and VLAN devices inherit default, csumo and tso features */
1482d76a60baSAnirudh Venkataramanan 	netdev->hw_enc_features |= dflt_features | csumo_features |
1483d76a60baSAnirudh Venkataramanan 				   tso_features;
1484d76a60baSAnirudh Venkataramanan 	netdev->vlan_features |= dflt_features | csumo_features |
1485d76a60baSAnirudh Venkataramanan 				 tso_features;
14863a858ba3SAnirudh Venkataramanan 
14873a858ba3SAnirudh Venkataramanan 	if (vsi->type == ICE_VSI_PF) {
14883a858ba3SAnirudh Venkataramanan 		SET_NETDEV_DEV(netdev, &vsi->back->pdev->dev);
14893a858ba3SAnirudh Venkataramanan 		ether_addr_copy(mac_addr, vsi->port_info->mac.perm_addr);
14903a858ba3SAnirudh Venkataramanan 
14913a858ba3SAnirudh Venkataramanan 		ether_addr_copy(netdev->dev_addr, mac_addr);
14923a858ba3SAnirudh Venkataramanan 		ether_addr_copy(netdev->perm_addr, mac_addr);
14933a858ba3SAnirudh Venkataramanan 	}
14943a858ba3SAnirudh Venkataramanan 
14953a858ba3SAnirudh Venkataramanan 	netdev->priv_flags |= IFF_UNICAST_FLT;
14963a858ba3SAnirudh Venkataramanan 
1497cdedef59SAnirudh Venkataramanan 	/* assign netdev_ops */
1498cdedef59SAnirudh Venkataramanan 	netdev->netdev_ops = &ice_netdev_ops;
1499cdedef59SAnirudh Venkataramanan 
15003a858ba3SAnirudh Venkataramanan 	/* setup watchdog timeout value to be 5 second */
15013a858ba3SAnirudh Venkataramanan 	netdev->watchdog_timeo = 5 * HZ;
15023a858ba3SAnirudh Venkataramanan 
1503fcea6f3dSAnirudh Venkataramanan 	ice_set_ethtool_ops(netdev);
1504fcea6f3dSAnirudh Venkataramanan 
15053a858ba3SAnirudh Venkataramanan 	netdev->min_mtu = ETH_MIN_MTU;
15063a858ba3SAnirudh Venkataramanan 	netdev->max_mtu = ICE_MAX_MTU;
15073a858ba3SAnirudh Venkataramanan 
1508df0f8479SAnirudh Venkataramanan 	err = register_netdev(vsi->netdev);
15093a858ba3SAnirudh Venkataramanan 	if (err)
15103a858ba3SAnirudh Venkataramanan 		return err;
15113a858ba3SAnirudh Venkataramanan 
1512df0f8479SAnirudh Venkataramanan 	netif_carrier_off(vsi->netdev);
15133a858ba3SAnirudh Venkataramanan 
1514df0f8479SAnirudh Venkataramanan 	/* make sure transmit queues start off as stopped */
1515df0f8479SAnirudh Venkataramanan 	netif_tx_stop_all_queues(vsi->netdev);
15163a858ba3SAnirudh Venkataramanan 
15173a858ba3SAnirudh Venkataramanan 	return 0;
15183a858ba3SAnirudh Venkataramanan }
15193a858ba3SAnirudh Venkataramanan 
15203a858ba3SAnirudh Venkataramanan /**
1521d76a60baSAnirudh Venkataramanan  * ice_fill_rss_lut - Fill the RSS lookup table with default values
1522d76a60baSAnirudh Venkataramanan  * @lut: Lookup table
1523d76a60baSAnirudh Venkataramanan  * @rss_table_size: Lookup table size
1524d76a60baSAnirudh Venkataramanan  * @rss_size: Range of queue number for hashing
1525d76a60baSAnirudh Venkataramanan  */
1526d76a60baSAnirudh Venkataramanan void ice_fill_rss_lut(u8 *lut, u16 rss_table_size, u16 rss_size)
1527d76a60baSAnirudh Venkataramanan {
1528d76a60baSAnirudh Venkataramanan 	u16 i;
1529d76a60baSAnirudh Venkataramanan 
1530d76a60baSAnirudh Venkataramanan 	for (i = 0; i < rss_table_size; i++)
1531d76a60baSAnirudh Venkataramanan 		lut[i] = i % rss_size;
1532d76a60baSAnirudh Venkataramanan }
1533d76a60baSAnirudh Venkataramanan 
1534d76a60baSAnirudh Venkataramanan /**
15350f9d5027SAnirudh Venkataramanan  * ice_pf_vsi_setup - Set up a PF VSI
15360f9d5027SAnirudh Venkataramanan  * @pf: board private structure
15370f9d5027SAnirudh Venkataramanan  * @pi: pointer to the port_info instance
15380f9d5027SAnirudh Venkataramanan  *
15390f9d5027SAnirudh Venkataramanan  * Returns pointer to the successfully allocated VSI sw struct on success,
15400f9d5027SAnirudh Venkataramanan  * otherwise returns NULL on failure.
15410f9d5027SAnirudh Venkataramanan  */
15420f9d5027SAnirudh Venkataramanan static struct ice_vsi *
15430f9d5027SAnirudh Venkataramanan ice_pf_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi)
15440f9d5027SAnirudh Venkataramanan {
15450f9d5027SAnirudh Venkataramanan 	return ice_vsi_setup(pf, pi, ICE_VSI_PF, ICE_INVAL_VFID);
15460f9d5027SAnirudh Venkataramanan }
15470f9d5027SAnirudh Venkataramanan 
15480f9d5027SAnirudh Venkataramanan /**
1549d76a60baSAnirudh Venkataramanan  * ice_vlan_rx_add_vid - Add a vlan id filter to HW offload
1550d76a60baSAnirudh Venkataramanan  * @netdev: network interface to be adjusted
1551d76a60baSAnirudh Venkataramanan  * @proto: unused protocol
1552d76a60baSAnirudh Venkataramanan  * @vid: vlan id to be added
1553d76a60baSAnirudh Venkataramanan  *
1554d76a60baSAnirudh Venkataramanan  * net_device_ops implementation for adding vlan ids
1555d76a60baSAnirudh Venkataramanan  */
1556d76a60baSAnirudh Venkataramanan static int ice_vlan_rx_add_vid(struct net_device *netdev,
1557d76a60baSAnirudh Venkataramanan 			       __always_unused __be16 proto, u16 vid)
1558d76a60baSAnirudh Venkataramanan {
1559d76a60baSAnirudh Venkataramanan 	struct ice_netdev_priv *np = netdev_priv(netdev);
1560d76a60baSAnirudh Venkataramanan 	struct ice_vsi *vsi = np->vsi;
15614f74dcc1SBrett Creeley 	int ret;
1562d76a60baSAnirudh Venkataramanan 
1563d76a60baSAnirudh Venkataramanan 	if (vid >= VLAN_N_VID) {
1564d76a60baSAnirudh Venkataramanan 		netdev_err(netdev, "VLAN id requested %d is out of range %d\n",
1565d76a60baSAnirudh Venkataramanan 			   vid, VLAN_N_VID);
1566d76a60baSAnirudh Venkataramanan 		return -EINVAL;
1567d76a60baSAnirudh Venkataramanan 	}
1568d76a60baSAnirudh Venkataramanan 
1569d76a60baSAnirudh Venkataramanan 	if (vsi->info.pvid)
1570d76a60baSAnirudh Venkataramanan 		return -EINVAL;
1571d76a60baSAnirudh Venkataramanan 
15724f74dcc1SBrett Creeley 	/* Enable VLAN pruning when VLAN 0 is added */
15734f74dcc1SBrett Creeley 	if (unlikely(!vid)) {
15744f74dcc1SBrett Creeley 		ret = ice_cfg_vlan_pruning(vsi, true);
15754f74dcc1SBrett Creeley 		if (ret)
15764f74dcc1SBrett Creeley 			return ret;
15774f74dcc1SBrett Creeley 	}
15784f74dcc1SBrett Creeley 
1579d76a60baSAnirudh Venkataramanan 	/* Add all VLAN ids including 0 to the switch filter. VLAN id 0 is
1580d76a60baSAnirudh Venkataramanan 	 * needed to continue allowing all untagged packets since VLAN prune
1581d76a60baSAnirudh Venkataramanan 	 * list is applied to all packets by the switch
1582d76a60baSAnirudh Venkataramanan 	 */
1583d76a60baSAnirudh Venkataramanan 	ret = ice_vsi_add_vlan(vsi, vid);
1584d76a60baSAnirudh Venkataramanan 
1585d76a60baSAnirudh Venkataramanan 	if (!ret)
1586d76a60baSAnirudh Venkataramanan 		set_bit(vid, vsi->active_vlans);
1587d76a60baSAnirudh Venkataramanan 
1588d76a60baSAnirudh Venkataramanan 	return ret;
1589d76a60baSAnirudh Venkataramanan }
1590d76a60baSAnirudh Venkataramanan 
1591d76a60baSAnirudh Venkataramanan /**
1592d76a60baSAnirudh Venkataramanan  * ice_vlan_rx_kill_vid - Remove a vlan id filter from HW offload
1593d76a60baSAnirudh Venkataramanan  * @netdev: network interface to be adjusted
1594d76a60baSAnirudh Venkataramanan  * @proto: unused protocol
1595d76a60baSAnirudh Venkataramanan  * @vid: vlan id to be removed
1596d76a60baSAnirudh Venkataramanan  *
1597d76a60baSAnirudh Venkataramanan  * net_device_ops implementation for removing vlan ids
1598d76a60baSAnirudh Venkataramanan  */
1599d76a60baSAnirudh Venkataramanan static int ice_vlan_rx_kill_vid(struct net_device *netdev,
1600d76a60baSAnirudh Venkataramanan 				__always_unused __be16 proto, u16 vid)
1601d76a60baSAnirudh Venkataramanan {
1602d76a60baSAnirudh Venkataramanan 	struct ice_netdev_priv *np = netdev_priv(netdev);
1603d76a60baSAnirudh Venkataramanan 	struct ice_vsi *vsi = np->vsi;
16044f74dcc1SBrett Creeley 	int status;
1605d76a60baSAnirudh Venkataramanan 
1606d76a60baSAnirudh Venkataramanan 	if (vsi->info.pvid)
1607d76a60baSAnirudh Venkataramanan 		return -EINVAL;
1608d76a60baSAnirudh Venkataramanan 
16094f74dcc1SBrett Creeley 	/* Make sure ice_vsi_kill_vlan is successful before updating VLAN
16104f74dcc1SBrett Creeley 	 * information
1611d76a60baSAnirudh Venkataramanan 	 */
16124f74dcc1SBrett Creeley 	status = ice_vsi_kill_vlan(vsi, vid);
16134f74dcc1SBrett Creeley 	if (status)
16144f74dcc1SBrett Creeley 		return status;
1615d76a60baSAnirudh Venkataramanan 
1616d76a60baSAnirudh Venkataramanan 	clear_bit(vid, vsi->active_vlans);
1617d76a60baSAnirudh Venkataramanan 
16184f74dcc1SBrett Creeley 	/* Disable VLAN pruning when VLAN 0 is removed */
16194f74dcc1SBrett Creeley 	if (unlikely(!vid))
16204f74dcc1SBrett Creeley 		status = ice_cfg_vlan_pruning(vsi, false);
16214f74dcc1SBrett Creeley 
16224f74dcc1SBrett Creeley 	return status;
1623d76a60baSAnirudh Venkataramanan }
1624d76a60baSAnirudh Venkataramanan 
1625d76a60baSAnirudh Venkataramanan /**
16263a858ba3SAnirudh Venkataramanan  * ice_setup_pf_sw - Setup the HW switch on startup or after reset
16273a858ba3SAnirudh Venkataramanan  * @pf: board private structure
16283a858ba3SAnirudh Venkataramanan  *
16293a858ba3SAnirudh Venkataramanan  * Returns 0 on success, negative value on failure
16303a858ba3SAnirudh Venkataramanan  */
16313a858ba3SAnirudh Venkataramanan static int ice_setup_pf_sw(struct ice_pf *pf)
16323a858ba3SAnirudh Venkataramanan {
16339daf8208SAnirudh Venkataramanan 	LIST_HEAD(tmp_add_list);
16349daf8208SAnirudh Venkataramanan 	u8 broadcast[ETH_ALEN];
16353a858ba3SAnirudh Venkataramanan 	struct ice_vsi *vsi;
16363a858ba3SAnirudh Venkataramanan 	int status = 0;
16373a858ba3SAnirudh Venkataramanan 
16385df7e45dSDave Ertman 	if (ice_is_reset_in_progress(pf->state))
16390f9d5027SAnirudh Venkataramanan 		return -EBUSY;
16400f9d5027SAnirudh Venkataramanan 
16410f9d5027SAnirudh Venkataramanan 	vsi = ice_pf_vsi_setup(pf, pf->hw.port_info);
16423a858ba3SAnirudh Venkataramanan 	if (!vsi) {
16433a858ba3SAnirudh Venkataramanan 		status = -ENOMEM;
16440f9d5027SAnirudh Venkataramanan 		goto unroll_vsi_setup;
16450b28b702SAnirudh Venkataramanan 	}
16463a858ba3SAnirudh Venkataramanan 
1647df0f8479SAnirudh Venkataramanan 	status = ice_cfg_netdev(vsi);
1648df0f8479SAnirudh Venkataramanan 	if (status) {
1649df0f8479SAnirudh Venkataramanan 		status = -ENODEV;
1650df0f8479SAnirudh Venkataramanan 		goto unroll_vsi_setup;
1651df0f8479SAnirudh Venkataramanan 	}
1652df0f8479SAnirudh Venkataramanan 
1653df0f8479SAnirudh Venkataramanan 	/* registering the NAPI handler requires both the queues and
1654df0f8479SAnirudh Venkataramanan 	 * netdev to be created, which are done in ice_pf_vsi_setup()
1655df0f8479SAnirudh Venkataramanan 	 * and ice_cfg_netdev() respectively
1656df0f8479SAnirudh Venkataramanan 	 */
1657df0f8479SAnirudh Venkataramanan 	ice_napi_add(vsi);
1658df0f8479SAnirudh Venkataramanan 
16590f9d5027SAnirudh Venkataramanan 	/* To add a MAC filter, first add the MAC to a list and then
16600f9d5027SAnirudh Venkataramanan 	 * pass the list to ice_add_mac.
16619daf8208SAnirudh Venkataramanan 	 */
16620f9d5027SAnirudh Venkataramanan 
16630f9d5027SAnirudh Venkataramanan 	 /* Add a unicast MAC filter so the VSI can get its packets */
16649daf8208SAnirudh Venkataramanan 	status = ice_add_mac_to_list(vsi, &tmp_add_list,
16659daf8208SAnirudh Venkataramanan 				     vsi->port_info->mac.perm_addr);
16669daf8208SAnirudh Venkataramanan 	if (status)
1667df0f8479SAnirudh Venkataramanan 		goto unroll_napi_add;
16689daf8208SAnirudh Venkataramanan 
16699daf8208SAnirudh Venkataramanan 	/* VSI needs to receive broadcast traffic, so add the broadcast
16700f9d5027SAnirudh Venkataramanan 	 * MAC address to the list as well.
16719daf8208SAnirudh Venkataramanan 	 */
16729daf8208SAnirudh Venkataramanan 	eth_broadcast_addr(broadcast);
16739daf8208SAnirudh Venkataramanan 	status = ice_add_mac_to_list(vsi, &tmp_add_list, broadcast);
16749daf8208SAnirudh Venkataramanan 	if (status)
16750f9d5027SAnirudh Venkataramanan 		goto free_mac_list;
16769daf8208SAnirudh Venkataramanan 
16779daf8208SAnirudh Venkataramanan 	/* program MAC filters for entries in tmp_add_list */
16789daf8208SAnirudh Venkataramanan 	status = ice_add_mac(&pf->hw, &tmp_add_list);
16799daf8208SAnirudh Venkataramanan 	if (status) {
16809daf8208SAnirudh Venkataramanan 		dev_err(&pf->pdev->dev, "Could not add MAC filters\n");
16819daf8208SAnirudh Venkataramanan 		status = -ENOMEM;
16820f9d5027SAnirudh Venkataramanan 		goto free_mac_list;
16839daf8208SAnirudh Venkataramanan 	}
16849daf8208SAnirudh Venkataramanan 
16859daf8208SAnirudh Venkataramanan 	ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list);
16869daf8208SAnirudh Venkataramanan 	return status;
16879daf8208SAnirudh Venkataramanan 
16880f9d5027SAnirudh Venkataramanan free_mac_list:
16899daf8208SAnirudh Venkataramanan 	ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list);
16909daf8208SAnirudh Venkataramanan 
1691df0f8479SAnirudh Venkataramanan unroll_napi_add:
16923a858ba3SAnirudh Venkataramanan 	if (vsi) {
1693df0f8479SAnirudh Venkataramanan 		ice_napi_del(vsi);
16943a858ba3SAnirudh Venkataramanan 		if (vsi->netdev) {
1695df0f8479SAnirudh Venkataramanan 			if (vsi->netdev->reg_state == NETREG_REGISTERED)
1696df0f8479SAnirudh Venkataramanan 				unregister_netdev(vsi->netdev);
16973a858ba3SAnirudh Venkataramanan 			free_netdev(vsi->netdev);
16983a858ba3SAnirudh Venkataramanan 			vsi->netdev = NULL;
16993a858ba3SAnirudh Venkataramanan 		}
1700df0f8479SAnirudh Venkataramanan 	}
17019daf8208SAnirudh Venkataramanan 
1702df0f8479SAnirudh Venkataramanan unroll_vsi_setup:
1703df0f8479SAnirudh Venkataramanan 	if (vsi) {
1704df0f8479SAnirudh Venkataramanan 		ice_vsi_free_q_vectors(vsi);
17053a858ba3SAnirudh Venkataramanan 		ice_vsi_delete(vsi);
17063a858ba3SAnirudh Venkataramanan 		ice_vsi_put_qs(vsi);
17073a858ba3SAnirudh Venkataramanan 		pf->q_left_tx += vsi->alloc_txq;
17083a858ba3SAnirudh Venkataramanan 		pf->q_left_rx += vsi->alloc_rxq;
17093a858ba3SAnirudh Venkataramanan 		ice_vsi_clear(vsi);
17103a858ba3SAnirudh Venkataramanan 	}
17113a858ba3SAnirudh Venkataramanan 	return status;
17123a858ba3SAnirudh Venkataramanan }
17133a858ba3SAnirudh Venkataramanan 
17143a858ba3SAnirudh Venkataramanan /**
1715940b61afSAnirudh Venkataramanan  * ice_determine_q_usage - Calculate queue distribution
1716940b61afSAnirudh Venkataramanan  * @pf: board private structure
1717940b61afSAnirudh Venkataramanan  *
1718940b61afSAnirudh Venkataramanan  * Return -ENOMEM if we don't get enough queues for all ports
1719940b61afSAnirudh Venkataramanan  */
1720940b61afSAnirudh Venkataramanan static void ice_determine_q_usage(struct ice_pf *pf)
1721940b61afSAnirudh Venkataramanan {
1722940b61afSAnirudh Venkataramanan 	u16 q_left_tx, q_left_rx;
1723940b61afSAnirudh Venkataramanan 
1724940b61afSAnirudh Venkataramanan 	q_left_tx = pf->hw.func_caps.common_cap.num_txq;
1725940b61afSAnirudh Venkataramanan 	q_left_rx = pf->hw.func_caps.common_cap.num_rxq;
1726940b61afSAnirudh Venkataramanan 
17275513b920SAnirudh Venkataramanan 	pf->num_lan_tx = min_t(int, q_left_tx, num_online_cpus());
1728d76a60baSAnirudh Venkataramanan 
1729d76a60baSAnirudh Venkataramanan 	/* only 1 rx queue unless RSS is enabled */
1730d76a60baSAnirudh Venkataramanan 	if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags))
1731940b61afSAnirudh Venkataramanan 		pf->num_lan_rx = 1;
1732d76a60baSAnirudh Venkataramanan 	else
1733d76a60baSAnirudh Venkataramanan 		pf->num_lan_rx = min_t(int, q_left_rx, num_online_cpus());
1734940b61afSAnirudh Venkataramanan 
1735940b61afSAnirudh Venkataramanan 	pf->q_left_tx = q_left_tx - pf->num_lan_tx;
1736940b61afSAnirudh Venkataramanan 	pf->q_left_rx = q_left_rx - pf->num_lan_rx;
1737940b61afSAnirudh Venkataramanan }
1738940b61afSAnirudh Venkataramanan 
1739940b61afSAnirudh Venkataramanan /**
1740940b61afSAnirudh Venkataramanan  * ice_deinit_pf - Unrolls initialziations done by ice_init_pf
1741940b61afSAnirudh Venkataramanan  * @pf: board private structure to initialize
1742940b61afSAnirudh Venkataramanan  */
1743940b61afSAnirudh Venkataramanan static void ice_deinit_pf(struct ice_pf *pf)
1744940b61afSAnirudh Venkataramanan {
17458d81fa55SAkeem G Abodunrin 	ice_service_task_stop(pf);
1746940b61afSAnirudh Venkataramanan 	mutex_destroy(&pf->sw_mutex);
1747940b61afSAnirudh Venkataramanan 	mutex_destroy(&pf->avail_q_mutex);
1748940b61afSAnirudh Venkataramanan }
1749940b61afSAnirudh Venkataramanan 
1750940b61afSAnirudh Venkataramanan /**
1751940b61afSAnirudh Venkataramanan  * ice_init_pf - Initialize general software structures (struct ice_pf)
1752940b61afSAnirudh Venkataramanan  * @pf: board private structure to initialize
1753940b61afSAnirudh Venkataramanan  */
1754940b61afSAnirudh Venkataramanan static void ice_init_pf(struct ice_pf *pf)
1755940b61afSAnirudh Venkataramanan {
1756940b61afSAnirudh Venkataramanan 	bitmap_zero(pf->flags, ICE_PF_FLAGS_NBITS);
1757940b61afSAnirudh Venkataramanan 	set_bit(ICE_FLAG_MSIX_ENA, pf->flags);
1758940b61afSAnirudh Venkataramanan 
1759940b61afSAnirudh Venkataramanan 	mutex_init(&pf->sw_mutex);
1760940b61afSAnirudh Venkataramanan 	mutex_init(&pf->avail_q_mutex);
1761940b61afSAnirudh Venkataramanan 
1762940b61afSAnirudh Venkataramanan 	/* Clear avail_[t|r]x_qs bitmaps (set all to avail) */
1763940b61afSAnirudh Venkataramanan 	mutex_lock(&pf->avail_q_mutex);
1764940b61afSAnirudh Venkataramanan 	bitmap_zero(pf->avail_txqs, ICE_MAX_TXQS);
1765940b61afSAnirudh Venkataramanan 	bitmap_zero(pf->avail_rxqs, ICE_MAX_RXQS);
1766940b61afSAnirudh Venkataramanan 	mutex_unlock(&pf->avail_q_mutex);
1767940b61afSAnirudh Venkataramanan 
1768d76a60baSAnirudh Venkataramanan 	if (pf->hw.func_caps.common_cap.rss_table_size)
1769d76a60baSAnirudh Venkataramanan 		set_bit(ICE_FLAG_RSS_ENA, pf->flags);
1770d76a60baSAnirudh Venkataramanan 
1771940b61afSAnirudh Venkataramanan 	/* setup service timer and periodic service task */
1772940b61afSAnirudh Venkataramanan 	timer_setup(&pf->serv_tmr, ice_service_timer, 0);
1773940b61afSAnirudh Venkataramanan 	pf->serv_tmr_period = HZ;
1774940b61afSAnirudh Venkataramanan 	INIT_WORK(&pf->serv_task, ice_service_task);
1775940b61afSAnirudh Venkataramanan 	clear_bit(__ICE_SERVICE_SCHED, pf->state);
1776940b61afSAnirudh Venkataramanan }
1777940b61afSAnirudh Venkataramanan 
1778940b61afSAnirudh Venkataramanan /**
1779940b61afSAnirudh Venkataramanan  * ice_ena_msix_range - Request a range of MSIX vectors from the OS
1780940b61afSAnirudh Venkataramanan  * @pf: board private structure
1781940b61afSAnirudh Venkataramanan  *
1782940b61afSAnirudh Venkataramanan  * compute the number of MSIX vectors required (v_budget) and request from
1783940b61afSAnirudh Venkataramanan  * the OS. Return the number of vectors reserved or negative on failure
1784940b61afSAnirudh Venkataramanan  */
1785940b61afSAnirudh Venkataramanan static int ice_ena_msix_range(struct ice_pf *pf)
1786940b61afSAnirudh Venkataramanan {
1787940b61afSAnirudh Venkataramanan 	int v_left, v_actual, v_budget = 0;
1788940b61afSAnirudh Venkataramanan 	int needed, err, i;
1789940b61afSAnirudh Venkataramanan 
1790940b61afSAnirudh Venkataramanan 	v_left = pf->hw.func_caps.common_cap.num_msix_vectors;
1791940b61afSAnirudh Venkataramanan 
1792940b61afSAnirudh Venkataramanan 	/* reserve one vector for miscellaneous handler */
1793940b61afSAnirudh Venkataramanan 	needed = 1;
1794940b61afSAnirudh Venkataramanan 	v_budget += needed;
1795940b61afSAnirudh Venkataramanan 	v_left -= needed;
1796940b61afSAnirudh Venkataramanan 
1797940b61afSAnirudh Venkataramanan 	/* reserve vectors for LAN traffic */
1798940b61afSAnirudh Venkataramanan 	pf->num_lan_msix = min_t(int, num_online_cpus(), v_left);
1799940b61afSAnirudh Venkataramanan 	v_budget += pf->num_lan_msix;
1800940b61afSAnirudh Venkataramanan 
1801940b61afSAnirudh Venkataramanan 	pf->msix_entries = devm_kcalloc(&pf->pdev->dev, v_budget,
1802940b61afSAnirudh Venkataramanan 					sizeof(struct msix_entry), GFP_KERNEL);
1803940b61afSAnirudh Venkataramanan 
1804940b61afSAnirudh Venkataramanan 	if (!pf->msix_entries) {
1805940b61afSAnirudh Venkataramanan 		err = -ENOMEM;
1806940b61afSAnirudh Venkataramanan 		goto exit_err;
1807940b61afSAnirudh Venkataramanan 	}
1808940b61afSAnirudh Venkataramanan 
1809940b61afSAnirudh Venkataramanan 	for (i = 0; i < v_budget; i++)
1810940b61afSAnirudh Venkataramanan 		pf->msix_entries[i].entry = i;
1811940b61afSAnirudh Venkataramanan 
1812940b61afSAnirudh Venkataramanan 	/* actually reserve the vectors */
1813940b61afSAnirudh Venkataramanan 	v_actual = pci_enable_msix_range(pf->pdev, pf->msix_entries,
1814940b61afSAnirudh Venkataramanan 					 ICE_MIN_MSIX, v_budget);
1815940b61afSAnirudh Venkataramanan 
1816940b61afSAnirudh Venkataramanan 	if (v_actual < 0) {
1817940b61afSAnirudh Venkataramanan 		dev_err(&pf->pdev->dev, "unable to reserve MSI-X vectors\n");
1818940b61afSAnirudh Venkataramanan 		err = v_actual;
1819940b61afSAnirudh Venkataramanan 		goto msix_err;
1820940b61afSAnirudh Venkataramanan 	}
1821940b61afSAnirudh Venkataramanan 
1822940b61afSAnirudh Venkataramanan 	if (v_actual < v_budget) {
1823940b61afSAnirudh Venkataramanan 		dev_warn(&pf->pdev->dev,
1824940b61afSAnirudh Venkataramanan 			 "not enough vectors. requested = %d, obtained = %d\n",
1825940b61afSAnirudh Venkataramanan 			 v_budget, v_actual);
1826940b61afSAnirudh Venkataramanan 		if (v_actual >= (pf->num_lan_msix + 1)) {
1827940b61afSAnirudh Venkataramanan 			pf->num_avail_msix = v_actual - (pf->num_lan_msix + 1);
1828940b61afSAnirudh Venkataramanan 		} else if (v_actual >= 2) {
1829940b61afSAnirudh Venkataramanan 			pf->num_lan_msix = 1;
1830940b61afSAnirudh Venkataramanan 			pf->num_avail_msix = v_actual - 2;
1831940b61afSAnirudh Venkataramanan 		} else {
1832940b61afSAnirudh Venkataramanan 			pci_disable_msix(pf->pdev);
1833940b61afSAnirudh Venkataramanan 			err = -ERANGE;
1834940b61afSAnirudh Venkataramanan 			goto msix_err;
1835940b61afSAnirudh Venkataramanan 		}
1836940b61afSAnirudh Venkataramanan 	}
1837940b61afSAnirudh Venkataramanan 
1838940b61afSAnirudh Venkataramanan 	return v_actual;
1839940b61afSAnirudh Venkataramanan 
1840940b61afSAnirudh Venkataramanan msix_err:
1841940b61afSAnirudh Venkataramanan 	devm_kfree(&pf->pdev->dev, pf->msix_entries);
1842940b61afSAnirudh Venkataramanan 	goto exit_err;
1843940b61afSAnirudh Venkataramanan 
1844940b61afSAnirudh Venkataramanan exit_err:
1845940b61afSAnirudh Venkataramanan 	pf->num_lan_msix = 0;
1846940b61afSAnirudh Venkataramanan 	clear_bit(ICE_FLAG_MSIX_ENA, pf->flags);
1847940b61afSAnirudh Venkataramanan 	return err;
1848940b61afSAnirudh Venkataramanan }
1849940b61afSAnirudh Venkataramanan 
1850940b61afSAnirudh Venkataramanan /**
1851940b61afSAnirudh Venkataramanan  * ice_dis_msix - Disable MSI-X interrupt setup in OS
1852940b61afSAnirudh Venkataramanan  * @pf: board private structure
1853940b61afSAnirudh Venkataramanan  */
1854940b61afSAnirudh Venkataramanan static void ice_dis_msix(struct ice_pf *pf)
1855940b61afSAnirudh Venkataramanan {
1856940b61afSAnirudh Venkataramanan 	pci_disable_msix(pf->pdev);
1857940b61afSAnirudh Venkataramanan 	devm_kfree(&pf->pdev->dev, pf->msix_entries);
1858940b61afSAnirudh Venkataramanan 	pf->msix_entries = NULL;
1859940b61afSAnirudh Venkataramanan 	clear_bit(ICE_FLAG_MSIX_ENA, pf->flags);
1860940b61afSAnirudh Venkataramanan }
1861940b61afSAnirudh Venkataramanan 
1862940b61afSAnirudh Venkataramanan /**
1863940b61afSAnirudh Venkataramanan  * ice_init_interrupt_scheme - Determine proper interrupt scheme
1864940b61afSAnirudh Venkataramanan  * @pf: board private structure to initialize
1865940b61afSAnirudh Venkataramanan  */
1866940b61afSAnirudh Venkataramanan static int ice_init_interrupt_scheme(struct ice_pf *pf)
1867940b61afSAnirudh Venkataramanan {
1868940b61afSAnirudh Venkataramanan 	int vectors = 0;
1869940b61afSAnirudh Venkataramanan 	ssize_t size;
1870940b61afSAnirudh Venkataramanan 
1871940b61afSAnirudh Venkataramanan 	if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags))
1872940b61afSAnirudh Venkataramanan 		vectors = ice_ena_msix_range(pf);
1873940b61afSAnirudh Venkataramanan 	else
1874940b61afSAnirudh Venkataramanan 		return -ENODEV;
1875940b61afSAnirudh Venkataramanan 
1876940b61afSAnirudh Venkataramanan 	if (vectors < 0)
1877940b61afSAnirudh Venkataramanan 		return vectors;
1878940b61afSAnirudh Venkataramanan 
1879940b61afSAnirudh Venkataramanan 	/* set up vector assignment tracking */
1880940b61afSAnirudh Venkataramanan 	size = sizeof(struct ice_res_tracker) + (sizeof(u16) * vectors);
1881940b61afSAnirudh Venkataramanan 
1882940b61afSAnirudh Venkataramanan 	pf->irq_tracker = devm_kzalloc(&pf->pdev->dev, size, GFP_KERNEL);
1883940b61afSAnirudh Venkataramanan 	if (!pf->irq_tracker) {
1884940b61afSAnirudh Venkataramanan 		ice_dis_msix(pf);
1885940b61afSAnirudh Venkataramanan 		return -ENOMEM;
1886940b61afSAnirudh Venkataramanan 	}
1887940b61afSAnirudh Venkataramanan 
1888940b61afSAnirudh Venkataramanan 	pf->irq_tracker->num_entries = vectors;
1889940b61afSAnirudh Venkataramanan 
1890940b61afSAnirudh Venkataramanan 	return 0;
1891940b61afSAnirudh Venkataramanan }
1892940b61afSAnirudh Venkataramanan 
1893940b61afSAnirudh Venkataramanan /**
1894940b61afSAnirudh Venkataramanan  * ice_clear_interrupt_scheme - Undo things done by ice_init_interrupt_scheme
1895940b61afSAnirudh Venkataramanan  * @pf: board private structure
1896940b61afSAnirudh Venkataramanan  */
1897940b61afSAnirudh Venkataramanan static void ice_clear_interrupt_scheme(struct ice_pf *pf)
1898940b61afSAnirudh Venkataramanan {
1899940b61afSAnirudh Venkataramanan 	if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags))
1900940b61afSAnirudh Venkataramanan 		ice_dis_msix(pf);
1901940b61afSAnirudh Venkataramanan 
1902c7f2c42bSAnirudh Venkataramanan 	if (pf->irq_tracker) {
1903940b61afSAnirudh Venkataramanan 		devm_kfree(&pf->pdev->dev, pf->irq_tracker);
1904940b61afSAnirudh Venkataramanan 		pf->irq_tracker = NULL;
1905940b61afSAnirudh Venkataramanan 	}
1906c7f2c42bSAnirudh Venkataramanan }
1907940b61afSAnirudh Venkataramanan 
1908940b61afSAnirudh Venkataramanan /**
1909837f08fdSAnirudh Venkataramanan  * ice_probe - Device initialization routine
1910837f08fdSAnirudh Venkataramanan  * @pdev: PCI device information struct
1911837f08fdSAnirudh Venkataramanan  * @ent: entry in ice_pci_tbl
1912837f08fdSAnirudh Venkataramanan  *
1913837f08fdSAnirudh Venkataramanan  * Returns 0 on success, negative on failure
1914837f08fdSAnirudh Venkataramanan  */
1915837f08fdSAnirudh Venkataramanan static int ice_probe(struct pci_dev *pdev,
1916837f08fdSAnirudh Venkataramanan 		     const struct pci_device_id __always_unused *ent)
1917837f08fdSAnirudh Venkataramanan {
1918837f08fdSAnirudh Venkataramanan 	struct ice_pf *pf;
1919837f08fdSAnirudh Venkataramanan 	struct ice_hw *hw;
1920837f08fdSAnirudh Venkataramanan 	int err;
1921837f08fdSAnirudh Venkataramanan 
1922837f08fdSAnirudh Venkataramanan 	/* this driver uses devres, see Documentation/driver-model/devres.txt */
1923837f08fdSAnirudh Venkataramanan 	err = pcim_enable_device(pdev);
1924837f08fdSAnirudh Venkataramanan 	if (err)
1925837f08fdSAnirudh Venkataramanan 		return err;
1926837f08fdSAnirudh Venkataramanan 
1927837f08fdSAnirudh Venkataramanan 	err = pcim_iomap_regions(pdev, BIT(ICE_BAR0), pci_name(pdev));
1928837f08fdSAnirudh Venkataramanan 	if (err) {
19293968540bSAnirudh Venkataramanan 		dev_err(&pdev->dev, "BAR0 I/O map error %d\n", err);
1930837f08fdSAnirudh Venkataramanan 		return err;
1931837f08fdSAnirudh Venkataramanan 	}
1932837f08fdSAnirudh Venkataramanan 
1933837f08fdSAnirudh Venkataramanan 	pf = devm_kzalloc(&pdev->dev, sizeof(*pf), GFP_KERNEL);
1934837f08fdSAnirudh Venkataramanan 	if (!pf)
1935837f08fdSAnirudh Venkataramanan 		return -ENOMEM;
1936837f08fdSAnirudh Venkataramanan 
1937837f08fdSAnirudh Venkataramanan 	/* set up for high or low dma */
1938837f08fdSAnirudh Venkataramanan 	err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
1939837f08fdSAnirudh Venkataramanan 	if (err)
1940837f08fdSAnirudh Venkataramanan 		err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
1941837f08fdSAnirudh Venkataramanan 	if (err) {
1942837f08fdSAnirudh Venkataramanan 		dev_err(&pdev->dev, "DMA configuration failed: 0x%x\n", err);
1943837f08fdSAnirudh Venkataramanan 		return err;
1944837f08fdSAnirudh Venkataramanan 	}
1945837f08fdSAnirudh Venkataramanan 
1946837f08fdSAnirudh Venkataramanan 	pci_enable_pcie_error_reporting(pdev);
1947837f08fdSAnirudh Venkataramanan 	pci_set_master(pdev);
1948837f08fdSAnirudh Venkataramanan 
1949837f08fdSAnirudh Venkataramanan 	pf->pdev = pdev;
1950837f08fdSAnirudh Venkataramanan 	pci_set_drvdata(pdev, pf);
1951837f08fdSAnirudh Venkataramanan 	set_bit(__ICE_DOWN, pf->state);
19528d81fa55SAkeem G Abodunrin 	/* Disable service task until DOWN bit is cleared */
19538d81fa55SAkeem G Abodunrin 	set_bit(__ICE_SERVICE_DIS, pf->state);
1954837f08fdSAnirudh Venkataramanan 
1955837f08fdSAnirudh Venkataramanan 	hw = &pf->hw;
1956837f08fdSAnirudh Venkataramanan 	hw->hw_addr = pcim_iomap_table(pdev)[ICE_BAR0];
1957837f08fdSAnirudh Venkataramanan 	hw->back = pf;
1958837f08fdSAnirudh Venkataramanan 	hw->vendor_id = pdev->vendor;
1959837f08fdSAnirudh Venkataramanan 	hw->device_id = pdev->device;
1960837f08fdSAnirudh Venkataramanan 	pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
1961837f08fdSAnirudh Venkataramanan 	hw->subsystem_vendor_id = pdev->subsystem_vendor;
1962837f08fdSAnirudh Venkataramanan 	hw->subsystem_device_id = pdev->subsystem_device;
1963837f08fdSAnirudh Venkataramanan 	hw->bus.device = PCI_SLOT(pdev->devfn);
1964837f08fdSAnirudh Venkataramanan 	hw->bus.func = PCI_FUNC(pdev->devfn);
1965f31e4b6fSAnirudh Venkataramanan 	ice_set_ctrlq_len(hw);
1966f31e4b6fSAnirudh Venkataramanan 
1967837f08fdSAnirudh Venkataramanan 	pf->msg_enable = netif_msg_init(debug, ICE_DFLT_NETIF_M);
1968837f08fdSAnirudh Venkataramanan 
19697ec59eeaSAnirudh Venkataramanan #ifndef CONFIG_DYNAMIC_DEBUG
19707ec59eeaSAnirudh Venkataramanan 	if (debug < -1)
19717ec59eeaSAnirudh Venkataramanan 		hw->debug_mask = debug;
19727ec59eeaSAnirudh Venkataramanan #endif
19737ec59eeaSAnirudh Venkataramanan 
1974f31e4b6fSAnirudh Venkataramanan 	err = ice_init_hw(hw);
1975f31e4b6fSAnirudh Venkataramanan 	if (err) {
1976f31e4b6fSAnirudh Venkataramanan 		dev_err(&pdev->dev, "ice_init_hw failed: %d\n", err);
1977f31e4b6fSAnirudh Venkataramanan 		err = -EIO;
1978f31e4b6fSAnirudh Venkataramanan 		goto err_exit_unroll;
1979f31e4b6fSAnirudh Venkataramanan 	}
1980f31e4b6fSAnirudh Venkataramanan 
1981f31e4b6fSAnirudh Venkataramanan 	dev_info(&pdev->dev, "firmware %d.%d.%05d api %d.%d\n",
1982f31e4b6fSAnirudh Venkataramanan 		 hw->fw_maj_ver, hw->fw_min_ver, hw->fw_build,
1983f31e4b6fSAnirudh Venkataramanan 		 hw->api_maj_ver, hw->api_min_ver);
1984f31e4b6fSAnirudh Venkataramanan 
1985940b61afSAnirudh Venkataramanan 	ice_init_pf(pf);
1986940b61afSAnirudh Venkataramanan 
1987940b61afSAnirudh Venkataramanan 	ice_determine_q_usage(pf);
1988940b61afSAnirudh Venkataramanan 
1989940b61afSAnirudh Venkataramanan 	pf->num_alloc_vsi = min_t(u16, ICE_MAX_VSI_ALLOC,
1990940b61afSAnirudh Venkataramanan 				  hw->func_caps.guaranteed_num_vsi);
1991940b61afSAnirudh Venkataramanan 	if (!pf->num_alloc_vsi) {
1992940b61afSAnirudh Venkataramanan 		err = -EIO;
1993940b61afSAnirudh Venkataramanan 		goto err_init_pf_unroll;
1994940b61afSAnirudh Venkataramanan 	}
1995940b61afSAnirudh Venkataramanan 
1996940b61afSAnirudh Venkataramanan 	pf->vsi = devm_kcalloc(&pdev->dev, pf->num_alloc_vsi,
1997940b61afSAnirudh Venkataramanan 			       sizeof(struct ice_vsi *), GFP_KERNEL);
1998940b61afSAnirudh Venkataramanan 	if (!pf->vsi) {
1999940b61afSAnirudh Venkataramanan 		err = -ENOMEM;
2000940b61afSAnirudh Venkataramanan 		goto err_init_pf_unroll;
2001940b61afSAnirudh Venkataramanan 	}
2002940b61afSAnirudh Venkataramanan 
2003940b61afSAnirudh Venkataramanan 	err = ice_init_interrupt_scheme(pf);
2004940b61afSAnirudh Venkataramanan 	if (err) {
2005940b61afSAnirudh Venkataramanan 		dev_err(&pdev->dev,
2006940b61afSAnirudh Venkataramanan 			"ice_init_interrupt_scheme failed: %d\n", err);
2007940b61afSAnirudh Venkataramanan 		err = -EIO;
2008940b61afSAnirudh Venkataramanan 		goto err_init_interrupt_unroll;
2009940b61afSAnirudh Venkataramanan 	}
2010940b61afSAnirudh Venkataramanan 
20118d81fa55SAkeem G Abodunrin 	/* Driver is mostly up */
20128d81fa55SAkeem G Abodunrin 	clear_bit(__ICE_DOWN, pf->state);
20138d81fa55SAkeem G Abodunrin 
2014940b61afSAnirudh Venkataramanan 	/* In case of MSIX we are going to setup the misc vector right here
2015940b61afSAnirudh Venkataramanan 	 * to handle admin queue events etc. In case of legacy and MSI
2016940b61afSAnirudh Venkataramanan 	 * the misc functionality and queue processing is combined in
2017940b61afSAnirudh Venkataramanan 	 * the same vector and that gets setup at open.
2018940b61afSAnirudh Venkataramanan 	 */
2019940b61afSAnirudh Venkataramanan 	if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) {
2020940b61afSAnirudh Venkataramanan 		err = ice_req_irq_msix_misc(pf);
2021940b61afSAnirudh Venkataramanan 		if (err) {
2022940b61afSAnirudh Venkataramanan 			dev_err(&pdev->dev,
2023940b61afSAnirudh Venkataramanan 				"setup of misc vector failed: %d\n", err);
2024940b61afSAnirudh Venkataramanan 			goto err_init_interrupt_unroll;
2025940b61afSAnirudh Venkataramanan 		}
2026940b61afSAnirudh Venkataramanan 	}
2027940b61afSAnirudh Venkataramanan 
2028940b61afSAnirudh Venkataramanan 	/* create switch struct for the switch element created by FW on boot */
2029940b61afSAnirudh Venkataramanan 	pf->first_sw = devm_kzalloc(&pdev->dev, sizeof(struct ice_sw),
2030940b61afSAnirudh Venkataramanan 				    GFP_KERNEL);
2031940b61afSAnirudh Venkataramanan 	if (!pf->first_sw) {
2032940b61afSAnirudh Venkataramanan 		err = -ENOMEM;
2033940b61afSAnirudh Venkataramanan 		goto err_msix_misc_unroll;
2034940b61afSAnirudh Venkataramanan 	}
2035940b61afSAnirudh Venkataramanan 
2036b1edc14aSMd Fahad Iqbal Polash 	if (hw->evb_veb)
2037940b61afSAnirudh Venkataramanan 		pf->first_sw->bridge_mode = BRIDGE_MODE_VEB;
2038b1edc14aSMd Fahad Iqbal Polash 	else
2039b1edc14aSMd Fahad Iqbal Polash 		pf->first_sw->bridge_mode = BRIDGE_MODE_VEPA;
2040b1edc14aSMd Fahad Iqbal Polash 
2041940b61afSAnirudh Venkataramanan 	pf->first_sw->pf = pf;
2042940b61afSAnirudh Venkataramanan 
2043940b61afSAnirudh Venkataramanan 	/* record the sw_id available for later use */
2044940b61afSAnirudh Venkataramanan 	pf->first_sw->sw_id = hw->port_info->sw_id;
2045940b61afSAnirudh Venkataramanan 
20463a858ba3SAnirudh Venkataramanan 	err = ice_setup_pf_sw(pf);
20473a858ba3SAnirudh Venkataramanan 	if (err) {
20483a858ba3SAnirudh Venkataramanan 		dev_err(&pdev->dev,
20493a858ba3SAnirudh Venkataramanan 			"probe failed due to setup pf switch:%d\n", err);
20503a858ba3SAnirudh Venkataramanan 		goto err_alloc_sw_unroll;
20513a858ba3SAnirudh Venkataramanan 	}
20529daf8208SAnirudh Venkataramanan 
20538d81fa55SAkeem G Abodunrin 	clear_bit(__ICE_SERVICE_DIS, pf->state);
20549daf8208SAnirudh Venkataramanan 
20559daf8208SAnirudh Venkataramanan 	/* since everything is good, start the service timer */
20569daf8208SAnirudh Venkataramanan 	mod_timer(&pf->serv_tmr, round_jiffies(jiffies + pf->serv_tmr_period));
20579daf8208SAnirudh Venkataramanan 
20580b28b702SAnirudh Venkataramanan 	err = ice_init_link_events(pf->hw.port_info);
20590b28b702SAnirudh Venkataramanan 	if (err) {
20600b28b702SAnirudh Venkataramanan 		dev_err(&pdev->dev, "ice_init_link_events failed: %d\n", err);
20610b28b702SAnirudh Venkataramanan 		goto err_alloc_sw_unroll;
20620b28b702SAnirudh Venkataramanan 	}
20630b28b702SAnirudh Venkataramanan 
2064837f08fdSAnirudh Venkataramanan 	return 0;
2065f31e4b6fSAnirudh Venkataramanan 
20663a858ba3SAnirudh Venkataramanan err_alloc_sw_unroll:
20678d81fa55SAkeem G Abodunrin 	set_bit(__ICE_SERVICE_DIS, pf->state);
20683a858ba3SAnirudh Venkataramanan 	set_bit(__ICE_DOWN, pf->state);
20693a858ba3SAnirudh Venkataramanan 	devm_kfree(&pf->pdev->dev, pf->first_sw);
2070940b61afSAnirudh Venkataramanan err_msix_misc_unroll:
2071940b61afSAnirudh Venkataramanan 	ice_free_irq_msix_misc(pf);
2072940b61afSAnirudh Venkataramanan err_init_interrupt_unroll:
2073940b61afSAnirudh Venkataramanan 	ice_clear_interrupt_scheme(pf);
2074940b61afSAnirudh Venkataramanan 	devm_kfree(&pdev->dev, pf->vsi);
2075940b61afSAnirudh Venkataramanan err_init_pf_unroll:
2076940b61afSAnirudh Venkataramanan 	ice_deinit_pf(pf);
2077940b61afSAnirudh Venkataramanan 	ice_deinit_hw(hw);
2078f31e4b6fSAnirudh Venkataramanan err_exit_unroll:
2079f31e4b6fSAnirudh Venkataramanan 	pci_disable_pcie_error_reporting(pdev);
2080f31e4b6fSAnirudh Venkataramanan 	return err;
2081837f08fdSAnirudh Venkataramanan }
2082837f08fdSAnirudh Venkataramanan 
2083837f08fdSAnirudh Venkataramanan /**
2084837f08fdSAnirudh Venkataramanan  * ice_remove - Device removal routine
2085837f08fdSAnirudh Venkataramanan  * @pdev: PCI device information struct
2086837f08fdSAnirudh Venkataramanan  */
2087837f08fdSAnirudh Venkataramanan static void ice_remove(struct pci_dev *pdev)
2088837f08fdSAnirudh Venkataramanan {
2089837f08fdSAnirudh Venkataramanan 	struct ice_pf *pf = pci_get_drvdata(pdev);
2090837f08fdSAnirudh Venkataramanan 
2091837f08fdSAnirudh Venkataramanan 	if (!pf)
2092837f08fdSAnirudh Venkataramanan 		return;
2093837f08fdSAnirudh Venkataramanan 
2094837f08fdSAnirudh Venkataramanan 	set_bit(__ICE_DOWN, pf->state);
20958d81fa55SAkeem G Abodunrin 	ice_service_task_stop(pf);
2096f31e4b6fSAnirudh Venkataramanan 
20970f9d5027SAnirudh Venkataramanan 	ice_vsi_release_all(pf);
2098940b61afSAnirudh Venkataramanan 	ice_free_irq_msix_misc(pf);
2099940b61afSAnirudh Venkataramanan 	ice_clear_interrupt_scheme(pf);
2100940b61afSAnirudh Venkataramanan 	ice_deinit_pf(pf);
2101f31e4b6fSAnirudh Venkataramanan 	ice_deinit_hw(&pf->hw);
2102837f08fdSAnirudh Venkataramanan 	pci_disable_pcie_error_reporting(pdev);
2103837f08fdSAnirudh Venkataramanan }
2104837f08fdSAnirudh Venkataramanan 
2105837f08fdSAnirudh Venkataramanan /* ice_pci_tbl - PCI Device ID Table
2106837f08fdSAnirudh Venkataramanan  *
2107837f08fdSAnirudh Venkataramanan  * Wildcard entries (PCI_ANY_ID) should come last
2108837f08fdSAnirudh Venkataramanan  * Last entry must be all 0s
2109837f08fdSAnirudh Venkataramanan  *
2110837f08fdSAnirudh Venkataramanan  * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
2111837f08fdSAnirudh Venkataramanan  *   Class, Class Mask, private data (not used) }
2112837f08fdSAnirudh Venkataramanan  */
2113837f08fdSAnirudh Venkataramanan static const struct pci_device_id ice_pci_tbl[] = {
2114837f08fdSAnirudh Venkataramanan 	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_C810_BACKPLANE), 0 },
2115837f08fdSAnirudh Venkataramanan 	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_C810_QSFP), 0 },
2116837f08fdSAnirudh Venkataramanan 	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_C810_SFP), 0 },
2117837f08fdSAnirudh Venkataramanan 	/* required last entry */
2118837f08fdSAnirudh Venkataramanan 	{ 0, }
2119837f08fdSAnirudh Venkataramanan };
2120837f08fdSAnirudh Venkataramanan MODULE_DEVICE_TABLE(pci, ice_pci_tbl);
2121837f08fdSAnirudh Venkataramanan 
2122837f08fdSAnirudh Venkataramanan static struct pci_driver ice_driver = {
2123837f08fdSAnirudh Venkataramanan 	.name = KBUILD_MODNAME,
2124837f08fdSAnirudh Venkataramanan 	.id_table = ice_pci_tbl,
2125837f08fdSAnirudh Venkataramanan 	.probe = ice_probe,
2126837f08fdSAnirudh Venkataramanan 	.remove = ice_remove,
2127837f08fdSAnirudh Venkataramanan };
2128837f08fdSAnirudh Venkataramanan 
2129837f08fdSAnirudh Venkataramanan /**
2130837f08fdSAnirudh Venkataramanan  * ice_module_init - Driver registration routine
2131837f08fdSAnirudh Venkataramanan  *
2132837f08fdSAnirudh Venkataramanan  * ice_module_init is the first routine called when the driver is
2133837f08fdSAnirudh Venkataramanan  * loaded. All it does is register with the PCI subsystem.
2134837f08fdSAnirudh Venkataramanan  */
2135837f08fdSAnirudh Venkataramanan static int __init ice_module_init(void)
2136837f08fdSAnirudh Venkataramanan {
2137837f08fdSAnirudh Venkataramanan 	int status;
2138837f08fdSAnirudh Venkataramanan 
2139837f08fdSAnirudh Venkataramanan 	pr_info("%s - version %s\n", ice_driver_string, ice_drv_ver);
2140837f08fdSAnirudh Venkataramanan 	pr_info("%s\n", ice_copyright);
2141837f08fdSAnirudh Venkataramanan 
21420f9d5027SAnirudh Venkataramanan 	ice_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 0, KBUILD_MODNAME);
2143940b61afSAnirudh Venkataramanan 	if (!ice_wq) {
2144940b61afSAnirudh Venkataramanan 		pr_err("Failed to create workqueue\n");
2145940b61afSAnirudh Venkataramanan 		return -ENOMEM;
2146940b61afSAnirudh Venkataramanan 	}
2147940b61afSAnirudh Venkataramanan 
2148837f08fdSAnirudh Venkataramanan 	status = pci_register_driver(&ice_driver);
2149940b61afSAnirudh Venkataramanan 	if (status) {
2150837f08fdSAnirudh Venkataramanan 		pr_err("failed to register pci driver, err %d\n", status);
2151940b61afSAnirudh Venkataramanan 		destroy_workqueue(ice_wq);
2152940b61afSAnirudh Venkataramanan 	}
2153837f08fdSAnirudh Venkataramanan 
2154837f08fdSAnirudh Venkataramanan 	return status;
2155837f08fdSAnirudh Venkataramanan }
2156837f08fdSAnirudh Venkataramanan module_init(ice_module_init);
2157837f08fdSAnirudh Venkataramanan 
2158837f08fdSAnirudh Venkataramanan /**
2159837f08fdSAnirudh Venkataramanan  * ice_module_exit - Driver exit cleanup routine
2160837f08fdSAnirudh Venkataramanan  *
2161837f08fdSAnirudh Venkataramanan  * ice_module_exit is called just before the driver is removed
2162837f08fdSAnirudh Venkataramanan  * from memory.
2163837f08fdSAnirudh Venkataramanan  */
2164837f08fdSAnirudh Venkataramanan static void __exit ice_module_exit(void)
2165837f08fdSAnirudh Venkataramanan {
2166837f08fdSAnirudh Venkataramanan 	pci_unregister_driver(&ice_driver);
2167940b61afSAnirudh Venkataramanan 	destroy_workqueue(ice_wq);
2168837f08fdSAnirudh Venkataramanan 	pr_info("module unloaded\n");
2169837f08fdSAnirudh Venkataramanan }
2170837f08fdSAnirudh Venkataramanan module_exit(ice_module_exit);
21713a858ba3SAnirudh Venkataramanan 
21723a858ba3SAnirudh Venkataramanan /**
2173e94d4478SAnirudh Venkataramanan  * ice_set_mac_address - NDO callback to set mac address
2174e94d4478SAnirudh Venkataramanan  * @netdev: network interface device structure
2175e94d4478SAnirudh Venkataramanan  * @pi: pointer to an address structure
2176e94d4478SAnirudh Venkataramanan  *
2177e94d4478SAnirudh Venkataramanan  * Returns 0 on success, negative on failure
2178e94d4478SAnirudh Venkataramanan  */
2179e94d4478SAnirudh Venkataramanan static int ice_set_mac_address(struct net_device *netdev, void *pi)
2180e94d4478SAnirudh Venkataramanan {
2181e94d4478SAnirudh Venkataramanan 	struct ice_netdev_priv *np = netdev_priv(netdev);
2182e94d4478SAnirudh Venkataramanan 	struct ice_vsi *vsi = np->vsi;
2183e94d4478SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
2184e94d4478SAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
2185e94d4478SAnirudh Venkataramanan 	struct sockaddr *addr = pi;
2186e94d4478SAnirudh Venkataramanan 	enum ice_status status;
2187e94d4478SAnirudh Venkataramanan 	LIST_HEAD(a_mac_list);
2188e94d4478SAnirudh Venkataramanan 	LIST_HEAD(r_mac_list);
2189e94d4478SAnirudh Venkataramanan 	u8 flags = 0;
2190e94d4478SAnirudh Venkataramanan 	int err;
2191e94d4478SAnirudh Venkataramanan 	u8 *mac;
2192e94d4478SAnirudh Venkataramanan 
2193e94d4478SAnirudh Venkataramanan 	mac = (u8 *)addr->sa_data;
2194e94d4478SAnirudh Venkataramanan 
2195e94d4478SAnirudh Venkataramanan 	if (!is_valid_ether_addr(mac))
2196e94d4478SAnirudh Venkataramanan 		return -EADDRNOTAVAIL;
2197e94d4478SAnirudh Venkataramanan 
2198e94d4478SAnirudh Venkataramanan 	if (ether_addr_equal(netdev->dev_addr, mac)) {
2199e94d4478SAnirudh Venkataramanan 		netdev_warn(netdev, "already using mac %pM\n", mac);
2200e94d4478SAnirudh Venkataramanan 		return 0;
2201e94d4478SAnirudh Venkataramanan 	}
2202e94d4478SAnirudh Venkataramanan 
2203e94d4478SAnirudh Venkataramanan 	if (test_bit(__ICE_DOWN, pf->state) ||
22045df7e45dSDave Ertman 	    ice_is_reset_in_progress(pf->state)) {
2205e94d4478SAnirudh Venkataramanan 		netdev_err(netdev, "can't set mac %pM. device not ready\n",
2206e94d4478SAnirudh Venkataramanan 			   mac);
2207e94d4478SAnirudh Venkataramanan 		return -EBUSY;
2208e94d4478SAnirudh Venkataramanan 	}
2209e94d4478SAnirudh Venkataramanan 
2210e94d4478SAnirudh Venkataramanan 	/* When we change the mac address we also have to change the mac address
2211e94d4478SAnirudh Venkataramanan 	 * based filter rules that were created previously for the old mac
2212e94d4478SAnirudh Venkataramanan 	 * address. So first, we remove the old filter rule using ice_remove_mac
2213e94d4478SAnirudh Venkataramanan 	 * and then create a new filter rule using ice_add_mac. Note that for
2214e94d4478SAnirudh Venkataramanan 	 * both these operations, we first need to form a "list" of mac
2215e94d4478SAnirudh Venkataramanan 	 * addresses (even though in this case, we have only 1 mac address to be
2216e94d4478SAnirudh Venkataramanan 	 * added/removed) and this done using ice_add_mac_to_list. Depending on
2217e94d4478SAnirudh Venkataramanan 	 * the ensuing operation this "list" of mac addresses is either to be
2218e94d4478SAnirudh Venkataramanan 	 * added or removed from the filter.
2219e94d4478SAnirudh Venkataramanan 	 */
2220e94d4478SAnirudh Venkataramanan 	err = ice_add_mac_to_list(vsi, &r_mac_list, netdev->dev_addr);
2221e94d4478SAnirudh Venkataramanan 	if (err) {
2222e94d4478SAnirudh Venkataramanan 		err = -EADDRNOTAVAIL;
2223e94d4478SAnirudh Venkataramanan 		goto free_lists;
2224e94d4478SAnirudh Venkataramanan 	}
2225e94d4478SAnirudh Venkataramanan 
2226e94d4478SAnirudh Venkataramanan 	status = ice_remove_mac(hw, &r_mac_list);
2227e94d4478SAnirudh Venkataramanan 	if (status) {
2228e94d4478SAnirudh Venkataramanan 		err = -EADDRNOTAVAIL;
2229e94d4478SAnirudh Venkataramanan 		goto free_lists;
2230e94d4478SAnirudh Venkataramanan 	}
2231e94d4478SAnirudh Venkataramanan 
2232e94d4478SAnirudh Venkataramanan 	err = ice_add_mac_to_list(vsi, &a_mac_list, mac);
2233e94d4478SAnirudh Venkataramanan 	if (err) {
2234e94d4478SAnirudh Venkataramanan 		err = -EADDRNOTAVAIL;
2235e94d4478SAnirudh Venkataramanan 		goto free_lists;
2236e94d4478SAnirudh Venkataramanan 	}
2237e94d4478SAnirudh Venkataramanan 
2238e94d4478SAnirudh Venkataramanan 	status = ice_add_mac(hw, &a_mac_list);
2239e94d4478SAnirudh Venkataramanan 	if (status) {
2240e94d4478SAnirudh Venkataramanan 		err = -EADDRNOTAVAIL;
2241e94d4478SAnirudh Venkataramanan 		goto free_lists;
2242e94d4478SAnirudh Venkataramanan 	}
2243e94d4478SAnirudh Venkataramanan 
2244e94d4478SAnirudh Venkataramanan free_lists:
2245e94d4478SAnirudh Venkataramanan 	/* free list entries */
2246e94d4478SAnirudh Venkataramanan 	ice_free_fltr_list(&pf->pdev->dev, &r_mac_list);
2247e94d4478SAnirudh Venkataramanan 	ice_free_fltr_list(&pf->pdev->dev, &a_mac_list);
2248e94d4478SAnirudh Venkataramanan 
2249e94d4478SAnirudh Venkataramanan 	if (err) {
2250e94d4478SAnirudh Venkataramanan 		netdev_err(netdev, "can't set mac %pM. filter update failed\n",
2251e94d4478SAnirudh Venkataramanan 			   mac);
2252e94d4478SAnirudh Venkataramanan 		return err;
2253e94d4478SAnirudh Venkataramanan 	}
2254e94d4478SAnirudh Venkataramanan 
2255e94d4478SAnirudh Venkataramanan 	/* change the netdev's mac address */
2256e94d4478SAnirudh Venkataramanan 	memcpy(netdev->dev_addr, mac, netdev->addr_len);
2257e94d4478SAnirudh Venkataramanan 	netdev_dbg(vsi->netdev, "updated mac address to %pM\n",
2258e94d4478SAnirudh Venkataramanan 		   netdev->dev_addr);
2259e94d4478SAnirudh Venkataramanan 
2260e94d4478SAnirudh Venkataramanan 	/* write new mac address to the firmware */
2261e94d4478SAnirudh Venkataramanan 	flags = ICE_AQC_MAN_MAC_UPDATE_LAA_WOL;
2262e94d4478SAnirudh Venkataramanan 	status = ice_aq_manage_mac_write(hw, mac, flags, NULL);
2263e94d4478SAnirudh Venkataramanan 	if (status) {
2264e94d4478SAnirudh Venkataramanan 		netdev_err(netdev, "can't set mac %pM. write to firmware failed.\n",
2265e94d4478SAnirudh Venkataramanan 			   mac);
2266e94d4478SAnirudh Venkataramanan 	}
2267e94d4478SAnirudh Venkataramanan 	return 0;
2268e94d4478SAnirudh Venkataramanan }
2269e94d4478SAnirudh Venkataramanan 
2270e94d4478SAnirudh Venkataramanan /**
2271e94d4478SAnirudh Venkataramanan  * ice_set_rx_mode - NDO callback to set the netdev filters
2272e94d4478SAnirudh Venkataramanan  * @netdev: network interface device structure
2273e94d4478SAnirudh Venkataramanan  */
2274e94d4478SAnirudh Venkataramanan static void ice_set_rx_mode(struct net_device *netdev)
2275e94d4478SAnirudh Venkataramanan {
2276e94d4478SAnirudh Venkataramanan 	struct ice_netdev_priv *np = netdev_priv(netdev);
2277e94d4478SAnirudh Venkataramanan 	struct ice_vsi *vsi = np->vsi;
2278e94d4478SAnirudh Venkataramanan 
2279e94d4478SAnirudh Venkataramanan 	if (!vsi)
2280e94d4478SAnirudh Venkataramanan 		return;
2281e94d4478SAnirudh Venkataramanan 
2282e94d4478SAnirudh Venkataramanan 	/* Set the flags to synchronize filters
2283e94d4478SAnirudh Venkataramanan 	 * ndo_set_rx_mode may be triggered even without a change in netdev
2284e94d4478SAnirudh Venkataramanan 	 * flags
2285e94d4478SAnirudh Venkataramanan 	 */
2286e94d4478SAnirudh Venkataramanan 	set_bit(ICE_VSI_FLAG_UMAC_FLTR_CHANGED, vsi->flags);
2287e94d4478SAnirudh Venkataramanan 	set_bit(ICE_VSI_FLAG_MMAC_FLTR_CHANGED, vsi->flags);
2288e94d4478SAnirudh Venkataramanan 	set_bit(ICE_FLAG_FLTR_SYNC, vsi->back->flags);
2289e94d4478SAnirudh Venkataramanan 
2290e94d4478SAnirudh Venkataramanan 	/* schedule our worker thread which will take care of
2291e94d4478SAnirudh Venkataramanan 	 * applying the new filter changes
2292e94d4478SAnirudh Venkataramanan 	 */
2293e94d4478SAnirudh Venkataramanan 	ice_service_task_schedule(vsi->back);
2294e94d4478SAnirudh Venkataramanan }
2295e94d4478SAnirudh Venkataramanan 
2296e94d4478SAnirudh Venkataramanan /**
2297e94d4478SAnirudh Venkataramanan  * ice_fdb_add - add an entry to the hardware database
2298e94d4478SAnirudh Venkataramanan  * @ndm: the input from the stack
2299e94d4478SAnirudh Venkataramanan  * @tb: pointer to array of nladdr (unused)
2300e94d4478SAnirudh Venkataramanan  * @dev: the net device pointer
2301e94d4478SAnirudh Venkataramanan  * @addr: the MAC address entry being added
2302e94d4478SAnirudh Venkataramanan  * @vid: VLAN id
2303e94d4478SAnirudh Venkataramanan  * @flags: instructions from stack about fdb operation
2304e94d4478SAnirudh Venkataramanan  */
2305e94d4478SAnirudh Venkataramanan static int ice_fdb_add(struct ndmsg *ndm, struct nlattr __always_unused *tb[],
2306e94d4478SAnirudh Venkataramanan 		       struct net_device *dev, const unsigned char *addr,
2307e94d4478SAnirudh Venkataramanan 		       u16 vid, u16 flags)
2308e94d4478SAnirudh Venkataramanan {
2309e94d4478SAnirudh Venkataramanan 	int err;
2310e94d4478SAnirudh Venkataramanan 
2311e94d4478SAnirudh Venkataramanan 	if (vid) {
2312e94d4478SAnirudh Venkataramanan 		netdev_err(dev, "VLANs aren't supported yet for dev_uc|mc_add()\n");
2313e94d4478SAnirudh Venkataramanan 		return -EINVAL;
2314e94d4478SAnirudh Venkataramanan 	}
2315e94d4478SAnirudh Venkataramanan 	if (ndm->ndm_state && !(ndm->ndm_state & NUD_PERMANENT)) {
2316e94d4478SAnirudh Venkataramanan 		netdev_err(dev, "FDB only supports static addresses\n");
2317e94d4478SAnirudh Venkataramanan 		return -EINVAL;
2318e94d4478SAnirudh Venkataramanan 	}
2319e94d4478SAnirudh Venkataramanan 
2320e94d4478SAnirudh Venkataramanan 	if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr))
2321e94d4478SAnirudh Venkataramanan 		err = dev_uc_add_excl(dev, addr);
2322e94d4478SAnirudh Venkataramanan 	else if (is_multicast_ether_addr(addr))
2323e94d4478SAnirudh Venkataramanan 		err = dev_mc_add_excl(dev, addr);
2324e94d4478SAnirudh Venkataramanan 	else
2325e94d4478SAnirudh Venkataramanan 		err = -EINVAL;
2326e94d4478SAnirudh Venkataramanan 
2327e94d4478SAnirudh Venkataramanan 	/* Only return duplicate errors if NLM_F_EXCL is set */
2328e94d4478SAnirudh Venkataramanan 	if (err == -EEXIST && !(flags & NLM_F_EXCL))
2329e94d4478SAnirudh Venkataramanan 		err = 0;
2330e94d4478SAnirudh Venkataramanan 
2331e94d4478SAnirudh Venkataramanan 	return err;
2332e94d4478SAnirudh Venkataramanan }
2333e94d4478SAnirudh Venkataramanan 
2334e94d4478SAnirudh Venkataramanan /**
2335e94d4478SAnirudh Venkataramanan  * ice_fdb_del - delete an entry from the hardware database
2336e94d4478SAnirudh Venkataramanan  * @ndm: the input from the stack
2337e94d4478SAnirudh Venkataramanan  * @tb: pointer to array of nladdr (unused)
2338e94d4478SAnirudh Venkataramanan  * @dev: the net device pointer
2339e94d4478SAnirudh Venkataramanan  * @addr: the MAC address entry being added
2340e94d4478SAnirudh Venkataramanan  * @vid: VLAN id
2341e94d4478SAnirudh Venkataramanan  */
2342e94d4478SAnirudh Venkataramanan static int ice_fdb_del(struct ndmsg *ndm, __always_unused struct nlattr *tb[],
2343e94d4478SAnirudh Venkataramanan 		       struct net_device *dev, const unsigned char *addr,
2344e94d4478SAnirudh Venkataramanan 		       __always_unused u16 vid)
2345e94d4478SAnirudh Venkataramanan {
2346e94d4478SAnirudh Venkataramanan 	int err;
2347e94d4478SAnirudh Venkataramanan 
2348e94d4478SAnirudh Venkataramanan 	if (ndm->ndm_state & NUD_PERMANENT) {
2349e94d4478SAnirudh Venkataramanan 		netdev_err(dev, "FDB only supports static addresses\n");
2350e94d4478SAnirudh Venkataramanan 		return -EINVAL;
2351e94d4478SAnirudh Venkataramanan 	}
2352e94d4478SAnirudh Venkataramanan 
2353e94d4478SAnirudh Venkataramanan 	if (is_unicast_ether_addr(addr))
2354e94d4478SAnirudh Venkataramanan 		err = dev_uc_del(dev, addr);
2355e94d4478SAnirudh Venkataramanan 	else if (is_multicast_ether_addr(addr))
2356e94d4478SAnirudh Venkataramanan 		err = dev_mc_del(dev, addr);
2357e94d4478SAnirudh Venkataramanan 	else
2358e94d4478SAnirudh Venkataramanan 		err = -EINVAL;
2359e94d4478SAnirudh Venkataramanan 
2360e94d4478SAnirudh Venkataramanan 	return err;
2361e94d4478SAnirudh Venkataramanan }
2362e94d4478SAnirudh Venkataramanan 
2363e94d4478SAnirudh Venkataramanan /**
2364d76a60baSAnirudh Venkataramanan  * ice_set_features - set the netdev feature flags
2365d76a60baSAnirudh Venkataramanan  * @netdev: ptr to the netdev being adjusted
2366d76a60baSAnirudh Venkataramanan  * @features: the feature set that the stack is suggesting
2367d76a60baSAnirudh Venkataramanan  */
2368d76a60baSAnirudh Venkataramanan static int ice_set_features(struct net_device *netdev,
2369d76a60baSAnirudh Venkataramanan 			    netdev_features_t features)
2370d76a60baSAnirudh Venkataramanan {
2371d76a60baSAnirudh Venkataramanan 	struct ice_netdev_priv *np = netdev_priv(netdev);
2372d76a60baSAnirudh Venkataramanan 	struct ice_vsi *vsi = np->vsi;
2373d76a60baSAnirudh Venkataramanan 	int ret = 0;
2374d76a60baSAnirudh Venkataramanan 
2375d76a60baSAnirudh Venkataramanan 	if ((features & NETIF_F_HW_VLAN_CTAG_RX) &&
2376d76a60baSAnirudh Venkataramanan 	    !(netdev->features & NETIF_F_HW_VLAN_CTAG_RX))
2377d76a60baSAnirudh Venkataramanan 		ret = ice_vsi_manage_vlan_stripping(vsi, true);
2378d76a60baSAnirudh Venkataramanan 	else if (!(features & NETIF_F_HW_VLAN_CTAG_RX) &&
2379d76a60baSAnirudh Venkataramanan 		 (netdev->features & NETIF_F_HW_VLAN_CTAG_RX))
2380d76a60baSAnirudh Venkataramanan 		ret = ice_vsi_manage_vlan_stripping(vsi, false);
2381d76a60baSAnirudh Venkataramanan 	else if ((features & NETIF_F_HW_VLAN_CTAG_TX) &&
2382d76a60baSAnirudh Venkataramanan 		 !(netdev->features & NETIF_F_HW_VLAN_CTAG_TX))
2383d76a60baSAnirudh Venkataramanan 		ret = ice_vsi_manage_vlan_insertion(vsi);
2384d76a60baSAnirudh Venkataramanan 	else if (!(features & NETIF_F_HW_VLAN_CTAG_TX) &&
2385d76a60baSAnirudh Venkataramanan 		 (netdev->features & NETIF_F_HW_VLAN_CTAG_TX))
2386d76a60baSAnirudh Venkataramanan 		ret = ice_vsi_manage_vlan_insertion(vsi);
2387d76a60baSAnirudh Venkataramanan 
2388d76a60baSAnirudh Venkataramanan 	return ret;
2389d76a60baSAnirudh Venkataramanan }
2390d76a60baSAnirudh Venkataramanan 
2391d76a60baSAnirudh Venkataramanan /**
2392d76a60baSAnirudh Venkataramanan  * ice_vsi_vlan_setup - Setup vlan offload properties on a VSI
2393d76a60baSAnirudh Venkataramanan  * @vsi: VSI to setup vlan properties for
2394d76a60baSAnirudh Venkataramanan  */
2395d76a60baSAnirudh Venkataramanan static int ice_vsi_vlan_setup(struct ice_vsi *vsi)
2396d76a60baSAnirudh Venkataramanan {
2397d76a60baSAnirudh Venkataramanan 	int ret = 0;
2398d76a60baSAnirudh Venkataramanan 
2399d76a60baSAnirudh Venkataramanan 	if (vsi->netdev->features & NETIF_F_HW_VLAN_CTAG_RX)
2400d76a60baSAnirudh Venkataramanan 		ret = ice_vsi_manage_vlan_stripping(vsi, true);
2401d76a60baSAnirudh Venkataramanan 	if (vsi->netdev->features & NETIF_F_HW_VLAN_CTAG_TX)
2402d76a60baSAnirudh Venkataramanan 		ret = ice_vsi_manage_vlan_insertion(vsi);
2403d76a60baSAnirudh Venkataramanan 
2404d76a60baSAnirudh Venkataramanan 	return ret;
2405d76a60baSAnirudh Venkataramanan }
2406d76a60baSAnirudh Venkataramanan 
2407d76a60baSAnirudh Venkataramanan /**
2408d76a60baSAnirudh Venkataramanan  * ice_restore_vlan - Reinstate VLANs when vsi/netdev comes back up
2409d76a60baSAnirudh Venkataramanan  * @vsi: the VSI being brought back up
2410d76a60baSAnirudh Venkataramanan  */
2411d76a60baSAnirudh Venkataramanan static int ice_restore_vlan(struct ice_vsi *vsi)
2412d76a60baSAnirudh Venkataramanan {
2413d76a60baSAnirudh Venkataramanan 	int err;
2414d76a60baSAnirudh Venkataramanan 	u16 vid;
2415d76a60baSAnirudh Venkataramanan 
2416d76a60baSAnirudh Venkataramanan 	if (!vsi->netdev)
2417d76a60baSAnirudh Venkataramanan 		return -EINVAL;
2418d76a60baSAnirudh Venkataramanan 
2419d76a60baSAnirudh Venkataramanan 	err = ice_vsi_vlan_setup(vsi);
2420d76a60baSAnirudh Venkataramanan 	if (err)
2421d76a60baSAnirudh Venkataramanan 		return err;
2422d76a60baSAnirudh Venkataramanan 
2423d76a60baSAnirudh Venkataramanan 	for_each_set_bit(vid, vsi->active_vlans, VLAN_N_VID) {
2424d76a60baSAnirudh Venkataramanan 		err = ice_vlan_rx_add_vid(vsi->netdev, htons(ETH_P_8021Q), vid);
2425d76a60baSAnirudh Venkataramanan 		if (err)
2426d76a60baSAnirudh Venkataramanan 			break;
2427d76a60baSAnirudh Venkataramanan 	}
2428d76a60baSAnirudh Venkataramanan 
2429d76a60baSAnirudh Venkataramanan 	return err;
2430d76a60baSAnirudh Venkataramanan }
2431d76a60baSAnirudh Venkataramanan 
2432d76a60baSAnirudh Venkataramanan /**
2433cdedef59SAnirudh Venkataramanan  * ice_vsi_cfg - Setup the VSI
2434cdedef59SAnirudh Venkataramanan  * @vsi: the VSI being configured
2435cdedef59SAnirudh Venkataramanan  *
2436cdedef59SAnirudh Venkataramanan  * Return 0 on success and negative value on error
2437cdedef59SAnirudh Venkataramanan  */
2438cdedef59SAnirudh Venkataramanan static int ice_vsi_cfg(struct ice_vsi *vsi)
2439cdedef59SAnirudh Venkataramanan {
2440cdedef59SAnirudh Venkataramanan 	int err;
2441cdedef59SAnirudh Venkataramanan 
2442c7f2c42bSAnirudh Venkataramanan 	if (vsi->netdev) {
2443e94d4478SAnirudh Venkataramanan 		ice_set_rx_mode(vsi->netdev);
2444d76a60baSAnirudh Venkataramanan 		err = ice_restore_vlan(vsi);
2445d76a60baSAnirudh Venkataramanan 		if (err)
2446d76a60baSAnirudh Venkataramanan 			return err;
2447c7f2c42bSAnirudh Venkataramanan 	}
2448d76a60baSAnirudh Venkataramanan 
2449cdedef59SAnirudh Venkataramanan 	err = ice_vsi_cfg_txqs(vsi);
2450cdedef59SAnirudh Venkataramanan 	if (!err)
2451cdedef59SAnirudh Venkataramanan 		err = ice_vsi_cfg_rxqs(vsi);
2452cdedef59SAnirudh Venkataramanan 
2453cdedef59SAnirudh Venkataramanan 	return err;
2454cdedef59SAnirudh Venkataramanan }
2455cdedef59SAnirudh Venkataramanan 
2456cdedef59SAnirudh Venkataramanan /**
24572b245cb2SAnirudh Venkataramanan  * ice_napi_enable_all - Enable NAPI for all q_vectors in the VSI
24582b245cb2SAnirudh Venkataramanan  * @vsi: the VSI being configured
24592b245cb2SAnirudh Venkataramanan  */
24602b245cb2SAnirudh Venkataramanan static void ice_napi_enable_all(struct ice_vsi *vsi)
24612b245cb2SAnirudh Venkataramanan {
24622b245cb2SAnirudh Venkataramanan 	int q_idx;
24632b245cb2SAnirudh Venkataramanan 
24642b245cb2SAnirudh Venkataramanan 	if (!vsi->netdev)
24652b245cb2SAnirudh Venkataramanan 		return;
24662b245cb2SAnirudh Venkataramanan 
24672b245cb2SAnirudh Venkataramanan 	for (q_idx = 0; q_idx < vsi->num_q_vectors; q_idx++)
24682b245cb2SAnirudh Venkataramanan 		napi_enable(&vsi->q_vectors[q_idx]->napi);
24692b245cb2SAnirudh Venkataramanan }
24702b245cb2SAnirudh Venkataramanan 
24712b245cb2SAnirudh Venkataramanan /**
2472cdedef59SAnirudh Venkataramanan  * ice_up_complete - Finish the last steps of bringing up a connection
2473cdedef59SAnirudh Venkataramanan  * @vsi: The VSI being configured
2474cdedef59SAnirudh Venkataramanan  *
2475cdedef59SAnirudh Venkataramanan  * Return 0 on success and negative value on error
2476cdedef59SAnirudh Venkataramanan  */
2477cdedef59SAnirudh Venkataramanan static int ice_up_complete(struct ice_vsi *vsi)
2478cdedef59SAnirudh Venkataramanan {
2479cdedef59SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
2480cdedef59SAnirudh Venkataramanan 	int err;
2481cdedef59SAnirudh Venkataramanan 
2482cdedef59SAnirudh Venkataramanan 	if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags))
2483cdedef59SAnirudh Venkataramanan 		ice_vsi_cfg_msix(vsi);
2484cdedef59SAnirudh Venkataramanan 	else
2485cdedef59SAnirudh Venkataramanan 		return -ENOTSUPP;
2486cdedef59SAnirudh Venkataramanan 
2487cdedef59SAnirudh Venkataramanan 	/* Enable only Rx rings, Tx rings were enabled by the FW when the
2488cdedef59SAnirudh Venkataramanan 	 * Tx queue group list was configured and the context bits were
2489cdedef59SAnirudh Venkataramanan 	 * programmed using ice_vsi_cfg_txqs
2490cdedef59SAnirudh Venkataramanan 	 */
2491cdedef59SAnirudh Venkataramanan 	err = ice_vsi_start_rx_rings(vsi);
2492cdedef59SAnirudh Venkataramanan 	if (err)
2493cdedef59SAnirudh Venkataramanan 		return err;
2494cdedef59SAnirudh Venkataramanan 
2495cdedef59SAnirudh Venkataramanan 	clear_bit(__ICE_DOWN, vsi->state);
24962b245cb2SAnirudh Venkataramanan 	ice_napi_enable_all(vsi);
2497cdedef59SAnirudh Venkataramanan 	ice_vsi_ena_irq(vsi);
2498cdedef59SAnirudh Venkataramanan 
2499cdedef59SAnirudh Venkataramanan 	if (vsi->port_info &&
2500cdedef59SAnirudh Venkataramanan 	    (vsi->port_info->phy.link_info.link_info & ICE_AQ_LINK_UP) &&
2501cdedef59SAnirudh Venkataramanan 	    vsi->netdev) {
2502cdedef59SAnirudh Venkataramanan 		ice_print_link_msg(vsi, true);
2503cdedef59SAnirudh Venkataramanan 		netif_tx_start_all_queues(vsi->netdev);
2504cdedef59SAnirudh Venkataramanan 		netif_carrier_on(vsi->netdev);
2505cdedef59SAnirudh Venkataramanan 	}
2506cdedef59SAnirudh Venkataramanan 
2507cdedef59SAnirudh Venkataramanan 	ice_service_task_schedule(pf);
2508cdedef59SAnirudh Venkataramanan 
2509cdedef59SAnirudh Venkataramanan 	return err;
2510cdedef59SAnirudh Venkataramanan }
2511cdedef59SAnirudh Venkataramanan 
2512cdedef59SAnirudh Venkataramanan /**
2513fcea6f3dSAnirudh Venkataramanan  * ice_up - Bring the connection back up after being down
2514fcea6f3dSAnirudh Venkataramanan  * @vsi: VSI being configured
2515fcea6f3dSAnirudh Venkataramanan  */
2516fcea6f3dSAnirudh Venkataramanan int ice_up(struct ice_vsi *vsi)
2517fcea6f3dSAnirudh Venkataramanan {
2518fcea6f3dSAnirudh Venkataramanan 	int err;
2519fcea6f3dSAnirudh Venkataramanan 
2520fcea6f3dSAnirudh Venkataramanan 	err = ice_vsi_cfg(vsi);
2521fcea6f3dSAnirudh Venkataramanan 	if (!err)
2522fcea6f3dSAnirudh Venkataramanan 		err = ice_up_complete(vsi);
2523fcea6f3dSAnirudh Venkataramanan 
2524fcea6f3dSAnirudh Venkataramanan 	return err;
2525fcea6f3dSAnirudh Venkataramanan }
2526fcea6f3dSAnirudh Venkataramanan 
2527fcea6f3dSAnirudh Venkataramanan /**
2528fcea6f3dSAnirudh Venkataramanan  * ice_fetch_u64_stats_per_ring - get packets and bytes stats per ring
2529fcea6f3dSAnirudh Venkataramanan  * @ring: Tx or Rx ring to read stats from
2530fcea6f3dSAnirudh Venkataramanan  * @pkts: packets stats counter
2531fcea6f3dSAnirudh Venkataramanan  * @bytes: bytes stats counter
2532fcea6f3dSAnirudh Venkataramanan  *
2533fcea6f3dSAnirudh Venkataramanan  * This function fetches stats from the ring considering the atomic operations
2534fcea6f3dSAnirudh Venkataramanan  * that needs to be performed to read u64 values in 32 bit machine.
2535fcea6f3dSAnirudh Venkataramanan  */
2536fcea6f3dSAnirudh Venkataramanan static void ice_fetch_u64_stats_per_ring(struct ice_ring *ring, u64 *pkts,
2537fcea6f3dSAnirudh Venkataramanan 					 u64 *bytes)
2538fcea6f3dSAnirudh Venkataramanan {
2539fcea6f3dSAnirudh Venkataramanan 	unsigned int start;
2540fcea6f3dSAnirudh Venkataramanan 	*pkts = 0;
2541fcea6f3dSAnirudh Venkataramanan 	*bytes = 0;
2542fcea6f3dSAnirudh Venkataramanan 
2543fcea6f3dSAnirudh Venkataramanan 	if (!ring)
2544fcea6f3dSAnirudh Venkataramanan 		return;
2545fcea6f3dSAnirudh Venkataramanan 	do {
2546fcea6f3dSAnirudh Venkataramanan 		start = u64_stats_fetch_begin_irq(&ring->syncp);
2547fcea6f3dSAnirudh Venkataramanan 		*pkts = ring->stats.pkts;
2548fcea6f3dSAnirudh Venkataramanan 		*bytes = ring->stats.bytes;
2549fcea6f3dSAnirudh Venkataramanan 	} while (u64_stats_fetch_retry_irq(&ring->syncp, start));
2550fcea6f3dSAnirudh Venkataramanan }
2551fcea6f3dSAnirudh Venkataramanan 
2552fcea6f3dSAnirudh Venkataramanan /**
2553fcea6f3dSAnirudh Venkataramanan  * ice_update_vsi_ring_stats - Update VSI stats counters
2554fcea6f3dSAnirudh Venkataramanan  * @vsi: the VSI to be updated
2555fcea6f3dSAnirudh Venkataramanan  */
2556fcea6f3dSAnirudh Venkataramanan static void ice_update_vsi_ring_stats(struct ice_vsi *vsi)
2557fcea6f3dSAnirudh Venkataramanan {
2558fcea6f3dSAnirudh Venkataramanan 	struct rtnl_link_stats64 *vsi_stats = &vsi->net_stats;
2559fcea6f3dSAnirudh Venkataramanan 	struct ice_ring *ring;
2560fcea6f3dSAnirudh Venkataramanan 	u64 pkts, bytes;
2561fcea6f3dSAnirudh Venkataramanan 	int i;
2562fcea6f3dSAnirudh Venkataramanan 
2563fcea6f3dSAnirudh Venkataramanan 	/* reset netdev stats */
2564fcea6f3dSAnirudh Venkataramanan 	vsi_stats->tx_packets = 0;
2565fcea6f3dSAnirudh Venkataramanan 	vsi_stats->tx_bytes = 0;
2566fcea6f3dSAnirudh Venkataramanan 	vsi_stats->rx_packets = 0;
2567fcea6f3dSAnirudh Venkataramanan 	vsi_stats->rx_bytes = 0;
2568fcea6f3dSAnirudh Venkataramanan 
2569fcea6f3dSAnirudh Venkataramanan 	/* reset non-netdev (extended) stats */
2570fcea6f3dSAnirudh Venkataramanan 	vsi->tx_restart = 0;
2571fcea6f3dSAnirudh Venkataramanan 	vsi->tx_busy = 0;
2572fcea6f3dSAnirudh Venkataramanan 	vsi->tx_linearize = 0;
2573fcea6f3dSAnirudh Venkataramanan 	vsi->rx_buf_failed = 0;
2574fcea6f3dSAnirudh Venkataramanan 	vsi->rx_page_failed = 0;
2575fcea6f3dSAnirudh Venkataramanan 
2576fcea6f3dSAnirudh Venkataramanan 	rcu_read_lock();
2577fcea6f3dSAnirudh Venkataramanan 
2578fcea6f3dSAnirudh Venkataramanan 	/* update Tx rings counters */
2579fcea6f3dSAnirudh Venkataramanan 	ice_for_each_txq(vsi, i) {
2580fcea6f3dSAnirudh Venkataramanan 		ring = READ_ONCE(vsi->tx_rings[i]);
2581fcea6f3dSAnirudh Venkataramanan 		ice_fetch_u64_stats_per_ring(ring, &pkts, &bytes);
2582fcea6f3dSAnirudh Venkataramanan 		vsi_stats->tx_packets += pkts;
2583fcea6f3dSAnirudh Venkataramanan 		vsi_stats->tx_bytes += bytes;
2584fcea6f3dSAnirudh Venkataramanan 		vsi->tx_restart += ring->tx_stats.restart_q;
2585fcea6f3dSAnirudh Venkataramanan 		vsi->tx_busy += ring->tx_stats.tx_busy;
2586fcea6f3dSAnirudh Venkataramanan 		vsi->tx_linearize += ring->tx_stats.tx_linearize;
2587fcea6f3dSAnirudh Venkataramanan 	}
2588fcea6f3dSAnirudh Venkataramanan 
2589fcea6f3dSAnirudh Venkataramanan 	/* update Rx rings counters */
2590fcea6f3dSAnirudh Venkataramanan 	ice_for_each_rxq(vsi, i) {
2591fcea6f3dSAnirudh Venkataramanan 		ring = READ_ONCE(vsi->rx_rings[i]);
2592fcea6f3dSAnirudh Venkataramanan 		ice_fetch_u64_stats_per_ring(ring, &pkts, &bytes);
2593fcea6f3dSAnirudh Venkataramanan 		vsi_stats->rx_packets += pkts;
2594fcea6f3dSAnirudh Venkataramanan 		vsi_stats->rx_bytes += bytes;
2595fcea6f3dSAnirudh Venkataramanan 		vsi->rx_buf_failed += ring->rx_stats.alloc_buf_failed;
2596fcea6f3dSAnirudh Venkataramanan 		vsi->rx_page_failed += ring->rx_stats.alloc_page_failed;
2597fcea6f3dSAnirudh Venkataramanan 	}
2598fcea6f3dSAnirudh Venkataramanan 
2599fcea6f3dSAnirudh Venkataramanan 	rcu_read_unlock();
2600fcea6f3dSAnirudh Venkataramanan }
2601fcea6f3dSAnirudh Venkataramanan 
2602fcea6f3dSAnirudh Venkataramanan /**
2603fcea6f3dSAnirudh Venkataramanan  * ice_update_vsi_stats - Update VSI stats counters
2604fcea6f3dSAnirudh Venkataramanan  * @vsi: the VSI to be updated
2605fcea6f3dSAnirudh Venkataramanan  */
2606fcea6f3dSAnirudh Venkataramanan static void ice_update_vsi_stats(struct ice_vsi *vsi)
2607fcea6f3dSAnirudh Venkataramanan {
2608fcea6f3dSAnirudh Venkataramanan 	struct rtnl_link_stats64 *cur_ns = &vsi->net_stats;
2609fcea6f3dSAnirudh Venkataramanan 	struct ice_eth_stats *cur_es = &vsi->eth_stats;
2610fcea6f3dSAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
2611fcea6f3dSAnirudh Venkataramanan 
2612fcea6f3dSAnirudh Venkataramanan 	if (test_bit(__ICE_DOWN, vsi->state) ||
2613fcea6f3dSAnirudh Venkataramanan 	    test_bit(__ICE_CFG_BUSY, pf->state))
2614fcea6f3dSAnirudh Venkataramanan 		return;
2615fcea6f3dSAnirudh Venkataramanan 
2616fcea6f3dSAnirudh Venkataramanan 	/* get stats as recorded by Tx/Rx rings */
2617fcea6f3dSAnirudh Venkataramanan 	ice_update_vsi_ring_stats(vsi);
2618fcea6f3dSAnirudh Venkataramanan 
2619fcea6f3dSAnirudh Venkataramanan 	/* get VSI stats as recorded by the hardware */
2620fcea6f3dSAnirudh Venkataramanan 	ice_update_eth_stats(vsi);
2621fcea6f3dSAnirudh Venkataramanan 
2622fcea6f3dSAnirudh Venkataramanan 	cur_ns->tx_errors = cur_es->tx_errors;
2623fcea6f3dSAnirudh Venkataramanan 	cur_ns->rx_dropped = cur_es->rx_discards;
2624fcea6f3dSAnirudh Venkataramanan 	cur_ns->tx_dropped = cur_es->tx_discards;
2625fcea6f3dSAnirudh Venkataramanan 	cur_ns->multicast = cur_es->rx_multicast;
2626fcea6f3dSAnirudh Venkataramanan 
2627fcea6f3dSAnirudh Venkataramanan 	/* update some more netdev stats if this is main VSI */
2628fcea6f3dSAnirudh Venkataramanan 	if (vsi->type == ICE_VSI_PF) {
2629fcea6f3dSAnirudh Venkataramanan 		cur_ns->rx_crc_errors = pf->stats.crc_errors;
2630fcea6f3dSAnirudh Venkataramanan 		cur_ns->rx_errors = pf->stats.crc_errors +
2631fcea6f3dSAnirudh Venkataramanan 				    pf->stats.illegal_bytes;
2632fcea6f3dSAnirudh Venkataramanan 		cur_ns->rx_length_errors = pf->stats.rx_len_errors;
2633fcea6f3dSAnirudh Venkataramanan 	}
2634fcea6f3dSAnirudh Venkataramanan }
2635fcea6f3dSAnirudh Venkataramanan 
2636fcea6f3dSAnirudh Venkataramanan /**
2637fcea6f3dSAnirudh Venkataramanan  * ice_update_pf_stats - Update PF port stats counters
2638fcea6f3dSAnirudh Venkataramanan  * @pf: PF whose stats needs to be updated
2639fcea6f3dSAnirudh Venkataramanan  */
2640fcea6f3dSAnirudh Venkataramanan static void ice_update_pf_stats(struct ice_pf *pf)
2641fcea6f3dSAnirudh Venkataramanan {
2642fcea6f3dSAnirudh Venkataramanan 	struct ice_hw_port_stats *prev_ps, *cur_ps;
2643fcea6f3dSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
2644fcea6f3dSAnirudh Venkataramanan 	u8 pf_id;
2645fcea6f3dSAnirudh Venkataramanan 
2646fcea6f3dSAnirudh Venkataramanan 	prev_ps = &pf->stats_prev;
2647fcea6f3dSAnirudh Venkataramanan 	cur_ps = &pf->stats;
2648fcea6f3dSAnirudh Venkataramanan 	pf_id = hw->pf_id;
2649fcea6f3dSAnirudh Venkataramanan 
2650fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_GORCH(pf_id), GLPRT_GORCL(pf_id),
2651fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->eth.rx_bytes,
2652fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->eth.rx_bytes);
2653fcea6f3dSAnirudh Venkataramanan 
2654fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_UPRCH(pf_id), GLPRT_UPRCL(pf_id),
2655fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->eth.rx_unicast,
2656fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->eth.rx_unicast);
2657fcea6f3dSAnirudh Venkataramanan 
2658fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_MPRCH(pf_id), GLPRT_MPRCL(pf_id),
2659fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->eth.rx_multicast,
2660fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->eth.rx_multicast);
2661fcea6f3dSAnirudh Venkataramanan 
2662fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_BPRCH(pf_id), GLPRT_BPRCL(pf_id),
2663fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->eth.rx_broadcast,
2664fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->eth.rx_broadcast);
2665fcea6f3dSAnirudh Venkataramanan 
2666fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_GOTCH(pf_id), GLPRT_GOTCL(pf_id),
2667fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->eth.tx_bytes,
2668fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->eth.tx_bytes);
2669fcea6f3dSAnirudh Venkataramanan 
2670fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_UPTCH(pf_id), GLPRT_UPTCL(pf_id),
2671fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->eth.tx_unicast,
2672fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->eth.tx_unicast);
2673fcea6f3dSAnirudh Venkataramanan 
2674fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_MPTCH(pf_id), GLPRT_MPTCL(pf_id),
2675fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->eth.tx_multicast,
2676fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->eth.tx_multicast);
2677fcea6f3dSAnirudh Venkataramanan 
2678fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_BPTCH(pf_id), GLPRT_BPTCL(pf_id),
2679fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->eth.tx_broadcast,
2680fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->eth.tx_broadcast);
2681fcea6f3dSAnirudh Venkataramanan 
2682fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_TDOLD(pf_id), pf->stat_prev_loaded,
2683fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->tx_dropped_link_down,
2684fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->tx_dropped_link_down);
2685fcea6f3dSAnirudh Venkataramanan 
2686fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PRC64H(pf_id), GLPRT_PRC64L(pf_id),
2687fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->rx_size_64,
2688fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->rx_size_64);
2689fcea6f3dSAnirudh Venkataramanan 
2690fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PRC127H(pf_id), GLPRT_PRC127L(pf_id),
2691fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->rx_size_127,
2692fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->rx_size_127);
2693fcea6f3dSAnirudh Venkataramanan 
2694fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PRC255H(pf_id), GLPRT_PRC255L(pf_id),
2695fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->rx_size_255,
2696fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->rx_size_255);
2697fcea6f3dSAnirudh Venkataramanan 
2698fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PRC511H(pf_id), GLPRT_PRC511L(pf_id),
2699fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->rx_size_511,
2700fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->rx_size_511);
2701fcea6f3dSAnirudh Venkataramanan 
2702fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PRC1023H(pf_id),
2703fcea6f3dSAnirudh Venkataramanan 			  GLPRT_PRC1023L(pf_id), pf->stat_prev_loaded,
2704fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->rx_size_1023, &cur_ps->rx_size_1023);
2705fcea6f3dSAnirudh Venkataramanan 
2706fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PRC1522H(pf_id),
2707fcea6f3dSAnirudh Venkataramanan 			  GLPRT_PRC1522L(pf_id), pf->stat_prev_loaded,
2708fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->rx_size_1522, &cur_ps->rx_size_1522);
2709fcea6f3dSAnirudh Venkataramanan 
2710fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PRC9522H(pf_id),
2711fcea6f3dSAnirudh Venkataramanan 			  GLPRT_PRC9522L(pf_id), pf->stat_prev_loaded,
2712fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->rx_size_big, &cur_ps->rx_size_big);
2713fcea6f3dSAnirudh Venkataramanan 
2714fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PTC64H(pf_id), GLPRT_PTC64L(pf_id),
2715fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->tx_size_64,
2716fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->tx_size_64);
2717fcea6f3dSAnirudh Venkataramanan 
2718fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PTC127H(pf_id), GLPRT_PTC127L(pf_id),
2719fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->tx_size_127,
2720fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->tx_size_127);
2721fcea6f3dSAnirudh Venkataramanan 
2722fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PTC255H(pf_id), GLPRT_PTC255L(pf_id),
2723fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->tx_size_255,
2724fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->tx_size_255);
2725fcea6f3dSAnirudh Venkataramanan 
2726fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PTC511H(pf_id), GLPRT_PTC511L(pf_id),
2727fcea6f3dSAnirudh Venkataramanan 			  pf->stat_prev_loaded, &prev_ps->tx_size_511,
2728fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->tx_size_511);
2729fcea6f3dSAnirudh Venkataramanan 
2730fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PTC1023H(pf_id),
2731fcea6f3dSAnirudh Venkataramanan 			  GLPRT_PTC1023L(pf_id), pf->stat_prev_loaded,
2732fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->tx_size_1023, &cur_ps->tx_size_1023);
2733fcea6f3dSAnirudh Venkataramanan 
2734fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PTC1522H(pf_id),
2735fcea6f3dSAnirudh Venkataramanan 			  GLPRT_PTC1522L(pf_id), pf->stat_prev_loaded,
2736fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->tx_size_1522, &cur_ps->tx_size_1522);
2737fcea6f3dSAnirudh Venkataramanan 
2738fcea6f3dSAnirudh Venkataramanan 	ice_stat_update40(hw, GLPRT_PTC9522H(pf_id),
2739fcea6f3dSAnirudh Venkataramanan 			  GLPRT_PTC9522L(pf_id), pf->stat_prev_loaded,
2740fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->tx_size_big, &cur_ps->tx_size_big);
2741fcea6f3dSAnirudh Venkataramanan 
2742fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_LXONRXC(pf_id), pf->stat_prev_loaded,
2743fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->link_xon_rx, &cur_ps->link_xon_rx);
2744fcea6f3dSAnirudh Venkataramanan 
2745fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_LXOFFRXC(pf_id), pf->stat_prev_loaded,
2746fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->link_xoff_rx, &cur_ps->link_xoff_rx);
2747fcea6f3dSAnirudh Venkataramanan 
2748fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_LXONTXC(pf_id), pf->stat_prev_loaded,
2749fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->link_xon_tx, &cur_ps->link_xon_tx);
2750fcea6f3dSAnirudh Venkataramanan 
2751fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_LXOFFTXC(pf_id), pf->stat_prev_loaded,
2752fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->link_xoff_tx, &cur_ps->link_xoff_tx);
2753fcea6f3dSAnirudh Venkataramanan 
2754fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_CRCERRS(pf_id), pf->stat_prev_loaded,
2755fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->crc_errors, &cur_ps->crc_errors);
2756fcea6f3dSAnirudh Venkataramanan 
2757fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_ILLERRC(pf_id), pf->stat_prev_loaded,
2758fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->illegal_bytes, &cur_ps->illegal_bytes);
2759fcea6f3dSAnirudh Venkataramanan 
2760fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_MLFC(pf_id), pf->stat_prev_loaded,
2761fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->mac_local_faults,
2762fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->mac_local_faults);
2763fcea6f3dSAnirudh Venkataramanan 
2764fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_MRFC(pf_id), pf->stat_prev_loaded,
2765fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->mac_remote_faults,
2766fcea6f3dSAnirudh Venkataramanan 			  &cur_ps->mac_remote_faults);
2767fcea6f3dSAnirudh Venkataramanan 
2768fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_RLEC(pf_id), pf->stat_prev_loaded,
2769fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->rx_len_errors, &cur_ps->rx_len_errors);
2770fcea6f3dSAnirudh Venkataramanan 
2771fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_RUC(pf_id), pf->stat_prev_loaded,
2772fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->rx_undersize, &cur_ps->rx_undersize);
2773fcea6f3dSAnirudh Venkataramanan 
2774fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_RFC(pf_id), pf->stat_prev_loaded,
2775fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->rx_fragments, &cur_ps->rx_fragments);
2776fcea6f3dSAnirudh Venkataramanan 
2777fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_ROC(pf_id), pf->stat_prev_loaded,
2778fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->rx_oversize, &cur_ps->rx_oversize);
2779fcea6f3dSAnirudh Venkataramanan 
2780fcea6f3dSAnirudh Venkataramanan 	ice_stat_update32(hw, GLPRT_RJC(pf_id), pf->stat_prev_loaded,
2781fcea6f3dSAnirudh Venkataramanan 			  &prev_ps->rx_jabber, &cur_ps->rx_jabber);
2782fcea6f3dSAnirudh Venkataramanan 
2783fcea6f3dSAnirudh Venkataramanan 	pf->stat_prev_loaded = true;
2784fcea6f3dSAnirudh Venkataramanan }
2785fcea6f3dSAnirudh Venkataramanan 
2786fcea6f3dSAnirudh Venkataramanan /**
2787fcea6f3dSAnirudh Venkataramanan  * ice_get_stats64 - get statistics for network device structure
2788fcea6f3dSAnirudh Venkataramanan  * @netdev: network interface device structure
2789fcea6f3dSAnirudh Venkataramanan  * @stats: main device statistics structure
2790fcea6f3dSAnirudh Venkataramanan  */
2791fcea6f3dSAnirudh Venkataramanan static
2792fcea6f3dSAnirudh Venkataramanan void ice_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
2793fcea6f3dSAnirudh Venkataramanan {
2794fcea6f3dSAnirudh Venkataramanan 	struct ice_netdev_priv *np = netdev_priv(netdev);
2795fcea6f3dSAnirudh Venkataramanan 	struct rtnl_link_stats64 *vsi_stats;
2796fcea6f3dSAnirudh Venkataramanan 	struct ice_vsi *vsi = np->vsi;
2797fcea6f3dSAnirudh Venkataramanan 
2798fcea6f3dSAnirudh Venkataramanan 	vsi_stats = &vsi->net_stats;
2799fcea6f3dSAnirudh Venkataramanan 
2800fcea6f3dSAnirudh Venkataramanan 	if (test_bit(__ICE_DOWN, vsi->state) || !vsi->num_txq || !vsi->num_rxq)
2801fcea6f3dSAnirudh Venkataramanan 		return;
2802fcea6f3dSAnirudh Venkataramanan 	/* netdev packet/byte stats come from ring counter. These are obtained
2803fcea6f3dSAnirudh Venkataramanan 	 * by summing up ring counters (done by ice_update_vsi_ring_stats).
2804fcea6f3dSAnirudh Venkataramanan 	 */
2805fcea6f3dSAnirudh Venkataramanan 	ice_update_vsi_ring_stats(vsi);
2806fcea6f3dSAnirudh Venkataramanan 	stats->tx_packets = vsi_stats->tx_packets;
2807fcea6f3dSAnirudh Venkataramanan 	stats->tx_bytes = vsi_stats->tx_bytes;
2808fcea6f3dSAnirudh Venkataramanan 	stats->rx_packets = vsi_stats->rx_packets;
2809fcea6f3dSAnirudh Venkataramanan 	stats->rx_bytes = vsi_stats->rx_bytes;
2810fcea6f3dSAnirudh Venkataramanan 
2811fcea6f3dSAnirudh Venkataramanan 	/* The rest of the stats can be read from the hardware but instead we
2812fcea6f3dSAnirudh Venkataramanan 	 * just return values that the watchdog task has already obtained from
2813fcea6f3dSAnirudh Venkataramanan 	 * the hardware.
2814fcea6f3dSAnirudh Venkataramanan 	 */
2815fcea6f3dSAnirudh Venkataramanan 	stats->multicast = vsi_stats->multicast;
2816fcea6f3dSAnirudh Venkataramanan 	stats->tx_errors = vsi_stats->tx_errors;
2817fcea6f3dSAnirudh Venkataramanan 	stats->tx_dropped = vsi_stats->tx_dropped;
2818fcea6f3dSAnirudh Venkataramanan 	stats->rx_errors = vsi_stats->rx_errors;
2819fcea6f3dSAnirudh Venkataramanan 	stats->rx_dropped = vsi_stats->rx_dropped;
2820fcea6f3dSAnirudh Venkataramanan 	stats->rx_crc_errors = vsi_stats->rx_crc_errors;
2821fcea6f3dSAnirudh Venkataramanan 	stats->rx_length_errors = vsi_stats->rx_length_errors;
2822fcea6f3dSAnirudh Venkataramanan }
2823fcea6f3dSAnirudh Venkataramanan 
2824fcea6f3dSAnirudh Venkataramanan /**
28252b245cb2SAnirudh Venkataramanan  * ice_napi_disable_all - Disable NAPI for all q_vectors in the VSI
28262b245cb2SAnirudh Venkataramanan  * @vsi: VSI having NAPI disabled
28272b245cb2SAnirudh Venkataramanan  */
28282b245cb2SAnirudh Venkataramanan static void ice_napi_disable_all(struct ice_vsi *vsi)
28292b245cb2SAnirudh Venkataramanan {
28302b245cb2SAnirudh Venkataramanan 	int q_idx;
28312b245cb2SAnirudh Venkataramanan 
28322b245cb2SAnirudh Venkataramanan 	if (!vsi->netdev)
28332b245cb2SAnirudh Venkataramanan 		return;
28342b245cb2SAnirudh Venkataramanan 
28352b245cb2SAnirudh Venkataramanan 	for (q_idx = 0; q_idx < vsi->num_q_vectors; q_idx++)
28362b245cb2SAnirudh Venkataramanan 		napi_disable(&vsi->q_vectors[q_idx]->napi);
28372b245cb2SAnirudh Venkataramanan }
28382b245cb2SAnirudh Venkataramanan 
28392b245cb2SAnirudh Venkataramanan /**
2840cdedef59SAnirudh Venkataramanan  * ice_down - Shutdown the connection
2841cdedef59SAnirudh Venkataramanan  * @vsi: The VSI being stopped
2842cdedef59SAnirudh Venkataramanan  */
2843fcea6f3dSAnirudh Venkataramanan int ice_down(struct ice_vsi *vsi)
2844cdedef59SAnirudh Venkataramanan {
284572adf242SAnirudh Venkataramanan 	int i, tx_err, rx_err;
2846cdedef59SAnirudh Venkataramanan 
2847cdedef59SAnirudh Venkataramanan 	/* Caller of this function is expected to set the
2848cdedef59SAnirudh Venkataramanan 	 * vsi->state __ICE_DOWN bit
2849cdedef59SAnirudh Venkataramanan 	 */
2850cdedef59SAnirudh Venkataramanan 	if (vsi->netdev) {
2851cdedef59SAnirudh Venkataramanan 		netif_carrier_off(vsi->netdev);
2852cdedef59SAnirudh Venkataramanan 		netif_tx_disable(vsi->netdev);
2853cdedef59SAnirudh Venkataramanan 	}
2854cdedef59SAnirudh Venkataramanan 
2855cdedef59SAnirudh Venkataramanan 	ice_vsi_dis_irq(vsi);
285672adf242SAnirudh Venkataramanan 	tx_err = ice_vsi_stop_tx_rings(vsi);
285772adf242SAnirudh Venkataramanan 	if (tx_err)
285872adf242SAnirudh Venkataramanan 		netdev_err(vsi->netdev,
285972adf242SAnirudh Venkataramanan 			   "Failed stop Tx rings, VSI %d error %d\n",
286072adf242SAnirudh Venkataramanan 			   vsi->vsi_num, tx_err);
286172adf242SAnirudh Venkataramanan 
286272adf242SAnirudh Venkataramanan 	rx_err = ice_vsi_stop_rx_rings(vsi);
286372adf242SAnirudh Venkataramanan 	if (rx_err)
286472adf242SAnirudh Venkataramanan 		netdev_err(vsi->netdev,
286572adf242SAnirudh Venkataramanan 			   "Failed stop Rx rings, VSI %d error %d\n",
286672adf242SAnirudh Venkataramanan 			   vsi->vsi_num, rx_err);
286772adf242SAnirudh Venkataramanan 
28682b245cb2SAnirudh Venkataramanan 	ice_napi_disable_all(vsi);
2869cdedef59SAnirudh Venkataramanan 
2870cdedef59SAnirudh Venkataramanan 	ice_for_each_txq(vsi, i)
2871cdedef59SAnirudh Venkataramanan 		ice_clean_tx_ring(vsi->tx_rings[i]);
2872cdedef59SAnirudh Venkataramanan 
2873cdedef59SAnirudh Venkataramanan 	ice_for_each_rxq(vsi, i)
2874cdedef59SAnirudh Venkataramanan 		ice_clean_rx_ring(vsi->rx_rings[i]);
2875cdedef59SAnirudh Venkataramanan 
287672adf242SAnirudh Venkataramanan 	if (tx_err || rx_err) {
287772adf242SAnirudh Venkataramanan 		netdev_err(vsi->netdev,
287872adf242SAnirudh Venkataramanan 			   "Failed to close VSI 0x%04X on switch 0x%04X\n",
2879cdedef59SAnirudh Venkataramanan 			   vsi->vsi_num, vsi->vsw->sw_id);
288072adf242SAnirudh Venkataramanan 		return -EIO;
288172adf242SAnirudh Venkataramanan 	}
288272adf242SAnirudh Venkataramanan 
288372adf242SAnirudh Venkataramanan 	return 0;
2884cdedef59SAnirudh Venkataramanan }
2885cdedef59SAnirudh Venkataramanan 
2886cdedef59SAnirudh Venkataramanan /**
2887cdedef59SAnirudh Venkataramanan  * ice_vsi_setup_tx_rings - Allocate VSI Tx queue resources
2888cdedef59SAnirudh Venkataramanan  * @vsi: VSI having resources allocated
2889cdedef59SAnirudh Venkataramanan  *
2890cdedef59SAnirudh Venkataramanan  * Return 0 on success, negative on failure
2891cdedef59SAnirudh Venkataramanan  */
2892cdedef59SAnirudh Venkataramanan static int ice_vsi_setup_tx_rings(struct ice_vsi *vsi)
2893cdedef59SAnirudh Venkataramanan {
2894dab0588fSJesse Brandeburg 	int i, err = 0;
2895cdedef59SAnirudh Venkataramanan 
2896cdedef59SAnirudh Venkataramanan 	if (!vsi->num_txq) {
2897cdedef59SAnirudh Venkataramanan 		dev_err(&vsi->back->pdev->dev, "VSI %d has 0 Tx queues\n",
2898cdedef59SAnirudh Venkataramanan 			vsi->vsi_num);
2899cdedef59SAnirudh Venkataramanan 		return -EINVAL;
2900cdedef59SAnirudh Venkataramanan 	}
2901cdedef59SAnirudh Venkataramanan 
2902cdedef59SAnirudh Venkataramanan 	ice_for_each_txq(vsi, i) {
290372adf242SAnirudh Venkataramanan 		vsi->tx_rings[i]->netdev = vsi->netdev;
2904cdedef59SAnirudh Venkataramanan 		err = ice_setup_tx_ring(vsi->tx_rings[i]);
2905cdedef59SAnirudh Venkataramanan 		if (err)
2906cdedef59SAnirudh Venkataramanan 			break;
2907cdedef59SAnirudh Venkataramanan 	}
2908cdedef59SAnirudh Venkataramanan 
2909cdedef59SAnirudh Venkataramanan 	return err;
2910cdedef59SAnirudh Venkataramanan }
2911cdedef59SAnirudh Venkataramanan 
2912cdedef59SAnirudh Venkataramanan /**
2913cdedef59SAnirudh Venkataramanan  * ice_vsi_setup_rx_rings - Allocate VSI Rx queue resources
2914cdedef59SAnirudh Venkataramanan  * @vsi: VSI having resources allocated
2915cdedef59SAnirudh Venkataramanan  *
2916cdedef59SAnirudh Venkataramanan  * Return 0 on success, negative on failure
2917cdedef59SAnirudh Venkataramanan  */
2918cdedef59SAnirudh Venkataramanan static int ice_vsi_setup_rx_rings(struct ice_vsi *vsi)
2919cdedef59SAnirudh Venkataramanan {
2920dab0588fSJesse Brandeburg 	int i, err = 0;
2921cdedef59SAnirudh Venkataramanan 
2922cdedef59SAnirudh Venkataramanan 	if (!vsi->num_rxq) {
2923cdedef59SAnirudh Venkataramanan 		dev_err(&vsi->back->pdev->dev, "VSI %d has 0 Rx queues\n",
2924cdedef59SAnirudh Venkataramanan 			vsi->vsi_num);
2925cdedef59SAnirudh Venkataramanan 		return -EINVAL;
2926cdedef59SAnirudh Venkataramanan 	}
2927cdedef59SAnirudh Venkataramanan 
2928cdedef59SAnirudh Venkataramanan 	ice_for_each_rxq(vsi, i) {
292972adf242SAnirudh Venkataramanan 		vsi->rx_rings[i]->netdev = vsi->netdev;
2930cdedef59SAnirudh Venkataramanan 		err = ice_setup_rx_ring(vsi->rx_rings[i]);
2931cdedef59SAnirudh Venkataramanan 		if (err)
2932cdedef59SAnirudh Venkataramanan 			break;
2933cdedef59SAnirudh Venkataramanan 	}
2934cdedef59SAnirudh Venkataramanan 
2935cdedef59SAnirudh Venkataramanan 	return err;
2936cdedef59SAnirudh Venkataramanan }
2937cdedef59SAnirudh Venkataramanan 
2938cdedef59SAnirudh Venkataramanan /**
2939cdedef59SAnirudh Venkataramanan  * ice_vsi_req_irq - Request IRQ from the OS
2940cdedef59SAnirudh Venkataramanan  * @vsi: The VSI IRQ is being requested for
2941cdedef59SAnirudh Venkataramanan  * @basename: name for the vector
2942cdedef59SAnirudh Venkataramanan  *
2943cdedef59SAnirudh Venkataramanan  * Return 0 on success and a negative value on error
2944cdedef59SAnirudh Venkataramanan  */
2945cdedef59SAnirudh Venkataramanan static int ice_vsi_req_irq(struct ice_vsi *vsi, char *basename)
2946cdedef59SAnirudh Venkataramanan {
2947cdedef59SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
2948cdedef59SAnirudh Venkataramanan 	int err = -EINVAL;
2949cdedef59SAnirudh Venkataramanan 
2950cdedef59SAnirudh Venkataramanan 	if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags))
2951cdedef59SAnirudh Venkataramanan 		err = ice_vsi_req_irq_msix(vsi, basename);
2952cdedef59SAnirudh Venkataramanan 
2953cdedef59SAnirudh Venkataramanan 	return err;
2954cdedef59SAnirudh Venkataramanan }
2955cdedef59SAnirudh Venkataramanan 
2956cdedef59SAnirudh Venkataramanan /**
2957cdedef59SAnirudh Venkataramanan  * ice_vsi_open - Called when a network interface is made active
2958cdedef59SAnirudh Venkataramanan  * @vsi: the VSI to open
2959cdedef59SAnirudh Venkataramanan  *
2960cdedef59SAnirudh Venkataramanan  * Initialization of the VSI
2961cdedef59SAnirudh Venkataramanan  *
2962cdedef59SAnirudh Venkataramanan  * Returns 0 on success, negative value on error
2963cdedef59SAnirudh Venkataramanan  */
2964cdedef59SAnirudh Venkataramanan static int ice_vsi_open(struct ice_vsi *vsi)
2965cdedef59SAnirudh Venkataramanan {
2966cdedef59SAnirudh Venkataramanan 	char int_name[ICE_INT_NAME_STR_LEN];
2967cdedef59SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
2968cdedef59SAnirudh Venkataramanan 	int err;
2969cdedef59SAnirudh Venkataramanan 
2970cdedef59SAnirudh Venkataramanan 	/* allocate descriptors */
2971cdedef59SAnirudh Venkataramanan 	err = ice_vsi_setup_tx_rings(vsi);
2972cdedef59SAnirudh Venkataramanan 	if (err)
2973cdedef59SAnirudh Venkataramanan 		goto err_setup_tx;
2974cdedef59SAnirudh Venkataramanan 
2975cdedef59SAnirudh Venkataramanan 	err = ice_vsi_setup_rx_rings(vsi);
2976cdedef59SAnirudh Venkataramanan 	if (err)
2977cdedef59SAnirudh Venkataramanan 		goto err_setup_rx;
2978cdedef59SAnirudh Venkataramanan 
2979cdedef59SAnirudh Venkataramanan 	err = ice_vsi_cfg(vsi);
2980cdedef59SAnirudh Venkataramanan 	if (err)
2981cdedef59SAnirudh Venkataramanan 		goto err_setup_rx;
2982cdedef59SAnirudh Venkataramanan 
2983cdedef59SAnirudh Venkataramanan 	snprintf(int_name, sizeof(int_name) - 1, "%s-%s",
2984cdedef59SAnirudh Venkataramanan 		 dev_driver_string(&pf->pdev->dev), vsi->netdev->name);
2985cdedef59SAnirudh Venkataramanan 	err = ice_vsi_req_irq(vsi, int_name);
2986cdedef59SAnirudh Venkataramanan 	if (err)
2987cdedef59SAnirudh Venkataramanan 		goto err_setup_rx;
2988cdedef59SAnirudh Venkataramanan 
2989cdedef59SAnirudh Venkataramanan 	/* Notify the stack of the actual queue counts. */
2990cdedef59SAnirudh Venkataramanan 	err = netif_set_real_num_tx_queues(vsi->netdev, vsi->num_txq);
2991cdedef59SAnirudh Venkataramanan 	if (err)
2992cdedef59SAnirudh Venkataramanan 		goto err_set_qs;
2993cdedef59SAnirudh Venkataramanan 
2994cdedef59SAnirudh Venkataramanan 	err = netif_set_real_num_rx_queues(vsi->netdev, vsi->num_rxq);
2995cdedef59SAnirudh Venkataramanan 	if (err)
2996cdedef59SAnirudh Venkataramanan 		goto err_set_qs;
2997cdedef59SAnirudh Venkataramanan 
2998cdedef59SAnirudh Venkataramanan 	err = ice_up_complete(vsi);
2999cdedef59SAnirudh Venkataramanan 	if (err)
3000cdedef59SAnirudh Venkataramanan 		goto err_up_complete;
3001cdedef59SAnirudh Venkataramanan 
3002cdedef59SAnirudh Venkataramanan 	return 0;
3003cdedef59SAnirudh Venkataramanan 
3004cdedef59SAnirudh Venkataramanan err_up_complete:
3005cdedef59SAnirudh Venkataramanan 	ice_down(vsi);
3006cdedef59SAnirudh Venkataramanan err_set_qs:
3007cdedef59SAnirudh Venkataramanan 	ice_vsi_free_irq(vsi);
3008cdedef59SAnirudh Venkataramanan err_setup_rx:
3009cdedef59SAnirudh Venkataramanan 	ice_vsi_free_rx_rings(vsi);
3010cdedef59SAnirudh Venkataramanan err_setup_tx:
3011cdedef59SAnirudh Venkataramanan 	ice_vsi_free_tx_rings(vsi);
3012cdedef59SAnirudh Venkataramanan 
3013cdedef59SAnirudh Venkataramanan 	return err;
3014cdedef59SAnirudh Venkataramanan }
3015cdedef59SAnirudh Venkataramanan 
3016cdedef59SAnirudh Venkataramanan /**
30170f9d5027SAnirudh Venkataramanan  * ice_vsi_release_all - Delete all VSIs
30180f9d5027SAnirudh Venkataramanan  * @pf: PF from which all VSIs are being removed
30190f9d5027SAnirudh Venkataramanan  */
30200f9d5027SAnirudh Venkataramanan static void ice_vsi_release_all(struct ice_pf *pf)
30210f9d5027SAnirudh Venkataramanan {
30220f9d5027SAnirudh Venkataramanan 	int err, i;
30230f9d5027SAnirudh Venkataramanan 
30240f9d5027SAnirudh Venkataramanan 	if (!pf->vsi)
30250f9d5027SAnirudh Venkataramanan 		return;
30260f9d5027SAnirudh Venkataramanan 
30270f9d5027SAnirudh Venkataramanan 	for (i = 0; i < pf->num_alloc_vsi; i++) {
30280f9d5027SAnirudh Venkataramanan 		if (!pf->vsi[i])
30290f9d5027SAnirudh Venkataramanan 			continue;
30300f9d5027SAnirudh Venkataramanan 
30310f9d5027SAnirudh Venkataramanan 		err = ice_vsi_release(pf->vsi[i]);
30320f9d5027SAnirudh Venkataramanan 		if (err)
30330f9d5027SAnirudh Venkataramanan 			dev_dbg(&pf->pdev->dev,
30340f9d5027SAnirudh Venkataramanan 				"Failed to release pf->vsi[%d], err %d, vsi_num = %d\n",
30350f9d5027SAnirudh Venkataramanan 				i, err, pf->vsi[i]->vsi_num);
30360f9d5027SAnirudh Venkataramanan 	}
30370f9d5027SAnirudh Venkataramanan }
30380f9d5027SAnirudh Venkataramanan 
30390f9d5027SAnirudh Venkataramanan /**
30400b28b702SAnirudh Venkataramanan  * ice_dis_vsi - pause a VSI
30410b28b702SAnirudh Venkataramanan  * @vsi: the VSI being paused
30420b28b702SAnirudh Venkataramanan  */
30430b28b702SAnirudh Venkataramanan static void ice_dis_vsi(struct ice_vsi *vsi)
30440b28b702SAnirudh Venkataramanan {
30450b28b702SAnirudh Venkataramanan 	if (test_bit(__ICE_DOWN, vsi->state))
30460b28b702SAnirudh Venkataramanan 		return;
30470b28b702SAnirudh Venkataramanan 
30480b28b702SAnirudh Venkataramanan 	set_bit(__ICE_NEEDS_RESTART, vsi->state);
30490b28b702SAnirudh Venkataramanan 
30500b28b702SAnirudh Venkataramanan 	if (vsi->netdev && netif_running(vsi->netdev) &&
30510f9d5027SAnirudh Venkataramanan 	    vsi->type == ICE_VSI_PF) {
30520f9d5027SAnirudh Venkataramanan 		rtnl_lock();
30530b28b702SAnirudh Venkataramanan 		vsi->netdev->netdev_ops->ndo_stop(vsi->netdev);
30540f9d5027SAnirudh Venkataramanan 		rtnl_unlock();
30550f9d5027SAnirudh Venkataramanan 	} else {
30560b28b702SAnirudh Venkataramanan 		ice_vsi_close(vsi);
30570b28b702SAnirudh Venkataramanan 	}
30580f9d5027SAnirudh Venkataramanan }
30590b28b702SAnirudh Venkataramanan 
30600b28b702SAnirudh Venkataramanan /**
30610b28b702SAnirudh Venkataramanan  * ice_ena_vsi - resume a VSI
30620b28b702SAnirudh Venkataramanan  * @vsi: the VSI being resume
30630b28b702SAnirudh Venkataramanan  */
30640f9d5027SAnirudh Venkataramanan static int ice_ena_vsi(struct ice_vsi *vsi)
30650b28b702SAnirudh Venkataramanan {
30660f9d5027SAnirudh Venkataramanan 	int err = 0;
30670b28b702SAnirudh Venkataramanan 
30680f9d5027SAnirudh Venkataramanan 	if (test_and_clear_bit(__ICE_NEEDS_RESTART, vsi->state))
30690f9d5027SAnirudh Venkataramanan 		if (vsi->netdev && netif_running(vsi->netdev)) {
30700f9d5027SAnirudh Venkataramanan 			rtnl_lock();
30710f9d5027SAnirudh Venkataramanan 			err = vsi->netdev->netdev_ops->ndo_open(vsi->netdev);
30720f9d5027SAnirudh Venkataramanan 			rtnl_unlock();
30730f9d5027SAnirudh Venkataramanan 		}
30740f9d5027SAnirudh Venkataramanan 
30750f9d5027SAnirudh Venkataramanan 	return err;
30760b28b702SAnirudh Venkataramanan }
30770b28b702SAnirudh Venkataramanan 
30780b28b702SAnirudh Venkataramanan /**
30790b28b702SAnirudh Venkataramanan  * ice_pf_dis_all_vsi - Pause all VSIs on a PF
30800b28b702SAnirudh Venkataramanan  * @pf: the PF
30810b28b702SAnirudh Venkataramanan  */
30820b28b702SAnirudh Venkataramanan static void ice_pf_dis_all_vsi(struct ice_pf *pf)
30830b28b702SAnirudh Venkataramanan {
30840b28b702SAnirudh Venkataramanan 	int v;
30850b28b702SAnirudh Venkataramanan 
30860b28b702SAnirudh Venkataramanan 	ice_for_each_vsi(pf, v)
30870b28b702SAnirudh Venkataramanan 		if (pf->vsi[v])
30880b28b702SAnirudh Venkataramanan 			ice_dis_vsi(pf->vsi[v]);
30890b28b702SAnirudh Venkataramanan }
30900b28b702SAnirudh Venkataramanan 
30910b28b702SAnirudh Venkataramanan /**
30920b28b702SAnirudh Venkataramanan  * ice_pf_ena_all_vsi - Resume all VSIs on a PF
30930b28b702SAnirudh Venkataramanan  * @pf: the PF
30940b28b702SAnirudh Venkataramanan  */
30950f9d5027SAnirudh Venkataramanan static int ice_pf_ena_all_vsi(struct ice_pf *pf)
30960b28b702SAnirudh Venkataramanan {
30970b28b702SAnirudh Venkataramanan 	int v;
30980b28b702SAnirudh Venkataramanan 
30990b28b702SAnirudh Venkataramanan 	ice_for_each_vsi(pf, v)
31000b28b702SAnirudh Venkataramanan 		if (pf->vsi[v])
31010f9d5027SAnirudh Venkataramanan 			if (ice_ena_vsi(pf->vsi[v]))
31020f9d5027SAnirudh Venkataramanan 				return -EIO;
31030f9d5027SAnirudh Venkataramanan 
31040f9d5027SAnirudh Venkataramanan 	return 0;
31050f9d5027SAnirudh Venkataramanan }
31060f9d5027SAnirudh Venkataramanan 
31070f9d5027SAnirudh Venkataramanan /**
31080f9d5027SAnirudh Venkataramanan  * ice_vsi_rebuild_all - rebuild all VSIs in pf
31090f9d5027SAnirudh Venkataramanan  * @pf: the PF
31100f9d5027SAnirudh Venkataramanan  */
31110f9d5027SAnirudh Venkataramanan static int ice_vsi_rebuild_all(struct ice_pf *pf)
31120f9d5027SAnirudh Venkataramanan {
31130f9d5027SAnirudh Venkataramanan 	int i;
31140f9d5027SAnirudh Venkataramanan 
31150f9d5027SAnirudh Venkataramanan 	/* loop through pf->vsi array and reinit the VSI if found */
31160f9d5027SAnirudh Venkataramanan 	for (i = 0; i < pf->num_alloc_vsi; i++) {
31170f9d5027SAnirudh Venkataramanan 		int err;
31180f9d5027SAnirudh Venkataramanan 
31190f9d5027SAnirudh Venkataramanan 		if (!pf->vsi[i])
31200f9d5027SAnirudh Venkataramanan 			continue;
31210f9d5027SAnirudh Venkataramanan 
31220f9d5027SAnirudh Venkataramanan 		err = ice_vsi_rebuild(pf->vsi[i]);
31230f9d5027SAnirudh Venkataramanan 		if (err) {
31240f9d5027SAnirudh Venkataramanan 			dev_err(&pf->pdev->dev,
31250f9d5027SAnirudh Venkataramanan 				"VSI at index %d rebuild failed\n",
31260f9d5027SAnirudh Venkataramanan 				pf->vsi[i]->idx);
31270f9d5027SAnirudh Venkataramanan 			return err;
31280f9d5027SAnirudh Venkataramanan 		}
31290f9d5027SAnirudh Venkataramanan 
31300f9d5027SAnirudh Venkataramanan 		dev_info(&pf->pdev->dev,
31310f9d5027SAnirudh Venkataramanan 			 "VSI at index %d rebuilt. vsi_num = 0x%x\n",
31320f9d5027SAnirudh Venkataramanan 			 pf->vsi[i]->idx, pf->vsi[i]->vsi_num);
31330f9d5027SAnirudh Venkataramanan 	}
31340f9d5027SAnirudh Venkataramanan 
31350f9d5027SAnirudh Venkataramanan 	return 0;
31360b28b702SAnirudh Venkataramanan }
31370b28b702SAnirudh Venkataramanan 
31380b28b702SAnirudh Venkataramanan /**
31390b28b702SAnirudh Venkataramanan  * ice_rebuild - rebuild after reset
31400b28b702SAnirudh Venkataramanan  * @pf: pf to rebuild
31410b28b702SAnirudh Venkataramanan  */
31420b28b702SAnirudh Venkataramanan static void ice_rebuild(struct ice_pf *pf)
31430b28b702SAnirudh Venkataramanan {
31440b28b702SAnirudh Venkataramanan 	struct device *dev = &pf->pdev->dev;
31450b28b702SAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
31460b28b702SAnirudh Venkataramanan 	enum ice_status ret;
31470b28b702SAnirudh Venkataramanan 	int err;
31480b28b702SAnirudh Venkataramanan 
31490b28b702SAnirudh Venkataramanan 	if (test_bit(__ICE_DOWN, pf->state))
31500b28b702SAnirudh Venkataramanan 		goto clear_recovery;
31510b28b702SAnirudh Venkataramanan 
31520b28b702SAnirudh Venkataramanan 	dev_dbg(dev, "rebuilding pf\n");
31530b28b702SAnirudh Venkataramanan 
31540b28b702SAnirudh Venkataramanan 	ret = ice_init_all_ctrlq(hw);
31550b28b702SAnirudh Venkataramanan 	if (ret) {
31560b28b702SAnirudh Venkataramanan 		dev_err(dev, "control queues init failed %d\n", ret);
31570f9d5027SAnirudh Venkataramanan 		goto err_init_ctrlq;
31580b28b702SAnirudh Venkataramanan 	}
31590b28b702SAnirudh Venkataramanan 
31600b28b702SAnirudh Venkataramanan 	ret = ice_clear_pf_cfg(hw);
31610b28b702SAnirudh Venkataramanan 	if (ret) {
31620b28b702SAnirudh Venkataramanan 		dev_err(dev, "clear PF configuration failed %d\n", ret);
31630f9d5027SAnirudh Venkataramanan 		goto err_init_ctrlq;
31640b28b702SAnirudh Venkataramanan 	}
31650b28b702SAnirudh Venkataramanan 
31660b28b702SAnirudh Venkataramanan 	ice_clear_pxe_mode(hw);
31670b28b702SAnirudh Venkataramanan 
31680b28b702SAnirudh Venkataramanan 	ret = ice_get_caps(hw);
31690b28b702SAnirudh Venkataramanan 	if (ret) {
31700b28b702SAnirudh Venkataramanan 		dev_err(dev, "ice_get_caps failed %d\n", ret);
31710f9d5027SAnirudh Venkataramanan 		goto err_init_ctrlq;
31720b28b702SAnirudh Venkataramanan 	}
31730b28b702SAnirudh Venkataramanan 
31740f9d5027SAnirudh Venkataramanan 	err = ice_sched_init_port(hw->port_info);
31750f9d5027SAnirudh Venkataramanan 	if (err)
31760f9d5027SAnirudh Venkataramanan 		goto err_sched_init_port;
31770f9d5027SAnirudh Venkataramanan 
31780f9d5027SAnirudh Venkataramanan 	err = ice_vsi_rebuild_all(pf);
31790b28b702SAnirudh Venkataramanan 	if (err) {
31800f9d5027SAnirudh Venkataramanan 		dev_err(dev, "ice_vsi_rebuild_all failed\n");
31810f9d5027SAnirudh Venkataramanan 		goto err_vsi_rebuild;
31820f9d5027SAnirudh Venkataramanan 	}
31830f9d5027SAnirudh Venkataramanan 
31840f9d5027SAnirudh Venkataramanan 	ret = ice_replay_all_fltr(&pf->hw);
31850f9d5027SAnirudh Venkataramanan 	if (ret) {
31860f9d5027SAnirudh Venkataramanan 		dev_err(&pf->pdev->dev,
31870f9d5027SAnirudh Venkataramanan 			"error replaying switch filter rules\n");
31880f9d5027SAnirudh Venkataramanan 		goto err_vsi_rebuild;
31890b28b702SAnirudh Venkataramanan 	}
31900b28b702SAnirudh Venkataramanan 
31910b28b702SAnirudh Venkataramanan 	/* start misc vector */
31920b28b702SAnirudh Venkataramanan 	if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) {
31930b28b702SAnirudh Venkataramanan 		err = ice_req_irq_msix_misc(pf);
31940b28b702SAnirudh Venkataramanan 		if (err) {
31950b28b702SAnirudh Venkataramanan 			dev_err(dev, "misc vector setup failed: %d\n", err);
31960f9d5027SAnirudh Venkataramanan 			goto err_vsi_rebuild;
31970b28b702SAnirudh Venkataramanan 		}
31980b28b702SAnirudh Venkataramanan 	}
31990b28b702SAnirudh Venkataramanan 
32000b28b702SAnirudh Venkataramanan 	/* restart the VSIs that were rebuilt and running before the reset */
32010f9d5027SAnirudh Venkataramanan 	err = ice_pf_ena_all_vsi(pf);
32020f9d5027SAnirudh Venkataramanan 	if (err) {
32030f9d5027SAnirudh Venkataramanan 		dev_err(&pf->pdev->dev, "error enabling VSIs\n");
32040f9d5027SAnirudh Venkataramanan 		/* no need to disable VSIs in tear down path in ice_rebuild()
32050f9d5027SAnirudh Venkataramanan 		 * since its already taken care in ice_vsi_open()
32060f9d5027SAnirudh Venkataramanan 		 */
32070f9d5027SAnirudh Venkataramanan 		goto err_vsi_rebuild;
32080f9d5027SAnirudh Venkataramanan 	}
32090b28b702SAnirudh Venkataramanan 
32100f9d5027SAnirudh Venkataramanan 	/* if we get here, reset flow is successful */
32110f9d5027SAnirudh Venkataramanan 	clear_bit(__ICE_RESET_FAILED, pf->state);
32120b28b702SAnirudh Venkataramanan 	return;
32130b28b702SAnirudh Venkataramanan 
32140f9d5027SAnirudh Venkataramanan err_vsi_rebuild:
32150f9d5027SAnirudh Venkataramanan 	ice_vsi_release_all(pf);
32160f9d5027SAnirudh Venkataramanan err_sched_init_port:
32170f9d5027SAnirudh Venkataramanan 	ice_sched_cleanup_all(hw);
32180f9d5027SAnirudh Venkataramanan err_init_ctrlq:
32190b28b702SAnirudh Venkataramanan 	ice_shutdown_all_ctrlq(hw);
32200b28b702SAnirudh Venkataramanan 	set_bit(__ICE_RESET_FAILED, pf->state);
32210b28b702SAnirudh Venkataramanan clear_recovery:
32220f9d5027SAnirudh Venkataramanan 	/* set this bit in PF state to control service task scheduling */
32230f9d5027SAnirudh Venkataramanan 	set_bit(__ICE_NEEDS_RESTART, pf->state);
32240f9d5027SAnirudh Venkataramanan 	dev_err(dev, "Rebuild failed, unload and reload driver\n");
32250b28b702SAnirudh Venkataramanan }
32260b28b702SAnirudh Venkataramanan 
32270b28b702SAnirudh Venkataramanan /**
3228e94d4478SAnirudh Venkataramanan  * ice_change_mtu - NDO callback to change the MTU
3229e94d4478SAnirudh Venkataramanan  * @netdev: network interface device structure
3230e94d4478SAnirudh Venkataramanan  * @new_mtu: new value for maximum frame size
3231e94d4478SAnirudh Venkataramanan  *
3232e94d4478SAnirudh Venkataramanan  * Returns 0 on success, negative on failure
3233e94d4478SAnirudh Venkataramanan  */
3234e94d4478SAnirudh Venkataramanan static int ice_change_mtu(struct net_device *netdev, int new_mtu)
3235e94d4478SAnirudh Venkataramanan {
3236e94d4478SAnirudh Venkataramanan 	struct ice_netdev_priv *np = netdev_priv(netdev);
3237e94d4478SAnirudh Venkataramanan 	struct ice_vsi *vsi = np->vsi;
3238e94d4478SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
3239e94d4478SAnirudh Venkataramanan 	u8 count = 0;
3240e94d4478SAnirudh Venkataramanan 
3241e94d4478SAnirudh Venkataramanan 	if (new_mtu == netdev->mtu) {
32423968540bSAnirudh Venkataramanan 		netdev_warn(netdev, "mtu is already %u\n", netdev->mtu);
3243e94d4478SAnirudh Venkataramanan 		return 0;
3244e94d4478SAnirudh Venkataramanan 	}
3245e94d4478SAnirudh Venkataramanan 
3246e94d4478SAnirudh Venkataramanan 	if (new_mtu < netdev->min_mtu) {
3247e94d4478SAnirudh Venkataramanan 		netdev_err(netdev, "new mtu invalid. min_mtu is %d\n",
3248e94d4478SAnirudh Venkataramanan 			   netdev->min_mtu);
3249e94d4478SAnirudh Venkataramanan 		return -EINVAL;
3250e94d4478SAnirudh Venkataramanan 	} else if (new_mtu > netdev->max_mtu) {
3251e94d4478SAnirudh Venkataramanan 		netdev_err(netdev, "new mtu invalid. max_mtu is %d\n",
3252e94d4478SAnirudh Venkataramanan 			   netdev->min_mtu);
3253e94d4478SAnirudh Venkataramanan 		return -EINVAL;
3254e94d4478SAnirudh Venkataramanan 	}
3255e94d4478SAnirudh Venkataramanan 	/* if a reset is in progress, wait for some time for it to complete */
3256e94d4478SAnirudh Venkataramanan 	do {
32575df7e45dSDave Ertman 		if (ice_is_reset_in_progress(pf->state)) {
3258e94d4478SAnirudh Venkataramanan 			count++;
3259e94d4478SAnirudh Venkataramanan 			usleep_range(1000, 2000);
3260e94d4478SAnirudh Venkataramanan 		} else {
3261e94d4478SAnirudh Venkataramanan 			break;
3262e94d4478SAnirudh Venkataramanan 		}
3263e94d4478SAnirudh Venkataramanan 
3264e94d4478SAnirudh Venkataramanan 	} while (count < 100);
3265e94d4478SAnirudh Venkataramanan 
3266e94d4478SAnirudh Venkataramanan 	if (count == 100) {
3267e94d4478SAnirudh Venkataramanan 		netdev_err(netdev, "can't change mtu. Device is busy\n");
3268e94d4478SAnirudh Venkataramanan 		return -EBUSY;
3269e94d4478SAnirudh Venkataramanan 	}
3270e94d4478SAnirudh Venkataramanan 
3271e94d4478SAnirudh Venkataramanan 	netdev->mtu = new_mtu;
3272e94d4478SAnirudh Venkataramanan 
3273e94d4478SAnirudh Venkataramanan 	/* if VSI is up, bring it down and then back up */
3274e94d4478SAnirudh Venkataramanan 	if (!test_and_set_bit(__ICE_DOWN, vsi->state)) {
3275e94d4478SAnirudh Venkataramanan 		int err;
3276e94d4478SAnirudh Venkataramanan 
3277e94d4478SAnirudh Venkataramanan 		err = ice_down(vsi);
3278e94d4478SAnirudh Venkataramanan 		if (err) {
3279e94d4478SAnirudh Venkataramanan 			netdev_err(netdev, "change mtu if_up err %d\n", err);
3280e94d4478SAnirudh Venkataramanan 			return err;
3281e94d4478SAnirudh Venkataramanan 		}
3282e94d4478SAnirudh Venkataramanan 
3283e94d4478SAnirudh Venkataramanan 		err = ice_up(vsi);
3284e94d4478SAnirudh Venkataramanan 		if (err) {
3285e94d4478SAnirudh Venkataramanan 			netdev_err(netdev, "change mtu if_up err %d\n", err);
3286e94d4478SAnirudh Venkataramanan 			return err;
3287e94d4478SAnirudh Venkataramanan 		}
3288e94d4478SAnirudh Venkataramanan 	}
3289e94d4478SAnirudh Venkataramanan 
3290e94d4478SAnirudh Venkataramanan 	netdev_dbg(netdev, "changed mtu to %d\n", new_mtu);
3291e94d4478SAnirudh Venkataramanan 	return 0;
3292e94d4478SAnirudh Venkataramanan }
3293e94d4478SAnirudh Venkataramanan 
3294e94d4478SAnirudh Venkataramanan /**
3295d76a60baSAnirudh Venkataramanan  * ice_set_rss - Set RSS keys and lut
3296d76a60baSAnirudh Venkataramanan  * @vsi: Pointer to VSI structure
3297d76a60baSAnirudh Venkataramanan  * @seed: RSS hash seed
3298d76a60baSAnirudh Venkataramanan  * @lut: Lookup table
3299d76a60baSAnirudh Venkataramanan  * @lut_size: Lookup table size
3300d76a60baSAnirudh Venkataramanan  *
3301d76a60baSAnirudh Venkataramanan  * Returns 0 on success, negative on failure
3302d76a60baSAnirudh Venkataramanan  */
3303d76a60baSAnirudh Venkataramanan int ice_set_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size)
3304d76a60baSAnirudh Venkataramanan {
3305d76a60baSAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
3306d76a60baSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
3307d76a60baSAnirudh Venkataramanan 	enum ice_status status;
3308d76a60baSAnirudh Venkataramanan 
3309d76a60baSAnirudh Venkataramanan 	if (seed) {
3310d76a60baSAnirudh Venkataramanan 		struct ice_aqc_get_set_rss_keys *buf =
3311d76a60baSAnirudh Venkataramanan 				  (struct ice_aqc_get_set_rss_keys *)seed;
3312d76a60baSAnirudh Venkataramanan 
33134fb33f31SAnirudh Venkataramanan 		status = ice_aq_set_rss_key(hw, vsi->idx, buf);
3314d76a60baSAnirudh Venkataramanan 
3315d76a60baSAnirudh Venkataramanan 		if (status) {
3316d76a60baSAnirudh Venkataramanan 			dev_err(&pf->pdev->dev,
3317d76a60baSAnirudh Venkataramanan 				"Cannot set RSS key, err %d aq_err %d\n",
3318d76a60baSAnirudh Venkataramanan 				status, hw->adminq.rq_last_status);
3319d76a60baSAnirudh Venkataramanan 			return -EIO;
3320d76a60baSAnirudh Venkataramanan 		}
3321d76a60baSAnirudh Venkataramanan 	}
3322d76a60baSAnirudh Venkataramanan 
3323d76a60baSAnirudh Venkataramanan 	if (lut) {
33244fb33f31SAnirudh Venkataramanan 		status = ice_aq_set_rss_lut(hw, vsi->idx, vsi->rss_lut_type,
33254fb33f31SAnirudh Venkataramanan 					    lut, lut_size);
3326d76a60baSAnirudh Venkataramanan 		if (status) {
3327d76a60baSAnirudh Venkataramanan 			dev_err(&pf->pdev->dev,
3328d76a60baSAnirudh Venkataramanan 				"Cannot set RSS lut, err %d aq_err %d\n",
3329d76a60baSAnirudh Venkataramanan 				status, hw->adminq.rq_last_status);
3330d76a60baSAnirudh Venkataramanan 			return -EIO;
3331d76a60baSAnirudh Venkataramanan 		}
3332d76a60baSAnirudh Venkataramanan 	}
3333d76a60baSAnirudh Venkataramanan 
3334d76a60baSAnirudh Venkataramanan 	return 0;
3335d76a60baSAnirudh Venkataramanan }
3336d76a60baSAnirudh Venkataramanan 
3337d76a60baSAnirudh Venkataramanan /**
3338d76a60baSAnirudh Venkataramanan  * ice_get_rss - Get RSS keys and lut
3339d76a60baSAnirudh Venkataramanan  * @vsi: Pointer to VSI structure
3340d76a60baSAnirudh Venkataramanan  * @seed: Buffer to store the keys
3341d76a60baSAnirudh Venkataramanan  * @lut: Buffer to store the lookup table entries
3342d76a60baSAnirudh Venkataramanan  * @lut_size: Size of buffer to store the lookup table entries
3343d76a60baSAnirudh Venkataramanan  *
3344d76a60baSAnirudh Venkataramanan  * Returns 0 on success, negative on failure
3345d76a60baSAnirudh Venkataramanan  */
3346d76a60baSAnirudh Venkataramanan int ice_get_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size)
3347d76a60baSAnirudh Venkataramanan {
3348d76a60baSAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
3349d76a60baSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
3350d76a60baSAnirudh Venkataramanan 	enum ice_status status;
3351d76a60baSAnirudh Venkataramanan 
3352d76a60baSAnirudh Venkataramanan 	if (seed) {
3353d76a60baSAnirudh Venkataramanan 		struct ice_aqc_get_set_rss_keys *buf =
3354d76a60baSAnirudh Venkataramanan 				  (struct ice_aqc_get_set_rss_keys *)seed;
3355d76a60baSAnirudh Venkataramanan 
33564fb33f31SAnirudh Venkataramanan 		status = ice_aq_get_rss_key(hw, vsi->idx, buf);
3357d76a60baSAnirudh Venkataramanan 		if (status) {
3358d76a60baSAnirudh Venkataramanan 			dev_err(&pf->pdev->dev,
3359d76a60baSAnirudh Venkataramanan 				"Cannot get RSS key, err %d aq_err %d\n",
3360d76a60baSAnirudh Venkataramanan 				status, hw->adminq.rq_last_status);
3361d76a60baSAnirudh Venkataramanan 			return -EIO;
3362d76a60baSAnirudh Venkataramanan 		}
3363d76a60baSAnirudh Venkataramanan 	}
3364d76a60baSAnirudh Venkataramanan 
3365d76a60baSAnirudh Venkataramanan 	if (lut) {
33664fb33f31SAnirudh Venkataramanan 		status = ice_aq_get_rss_lut(hw, vsi->idx, vsi->rss_lut_type,
33674fb33f31SAnirudh Venkataramanan 					    lut, lut_size);
3368d76a60baSAnirudh Venkataramanan 		if (status) {
3369d76a60baSAnirudh Venkataramanan 			dev_err(&pf->pdev->dev,
3370d76a60baSAnirudh Venkataramanan 				"Cannot get RSS lut, err %d aq_err %d\n",
3371d76a60baSAnirudh Venkataramanan 				status, hw->adminq.rq_last_status);
3372d76a60baSAnirudh Venkataramanan 			return -EIO;
3373d76a60baSAnirudh Venkataramanan 		}
3374d76a60baSAnirudh Venkataramanan 	}
3375d76a60baSAnirudh Venkataramanan 
3376d76a60baSAnirudh Venkataramanan 	return 0;
3377d76a60baSAnirudh Venkataramanan }
3378d76a60baSAnirudh Venkataramanan 
3379d76a60baSAnirudh Venkataramanan /**
3380b1edc14aSMd Fahad Iqbal Polash  * ice_bridge_getlink - Get the hardware bridge mode
3381b1edc14aSMd Fahad Iqbal Polash  * @skb: skb buff
3382b1edc14aSMd Fahad Iqbal Polash  * @pid: process id
3383b1edc14aSMd Fahad Iqbal Polash  * @seq: RTNL message seq
3384b1edc14aSMd Fahad Iqbal Polash  * @dev: the netdev being configured
3385b1edc14aSMd Fahad Iqbal Polash  * @filter_mask: filter mask passed in
3386b1edc14aSMd Fahad Iqbal Polash  * @nlflags: netlink flags passed in
3387b1edc14aSMd Fahad Iqbal Polash  *
3388b1edc14aSMd Fahad Iqbal Polash  * Return the bridge mode (VEB/VEPA)
3389b1edc14aSMd Fahad Iqbal Polash  */
3390b1edc14aSMd Fahad Iqbal Polash static int
3391b1edc14aSMd Fahad Iqbal Polash ice_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
3392b1edc14aSMd Fahad Iqbal Polash 		   struct net_device *dev, u32 filter_mask, int nlflags)
3393b1edc14aSMd Fahad Iqbal Polash {
3394b1edc14aSMd Fahad Iqbal Polash 	struct ice_netdev_priv *np = netdev_priv(dev);
3395b1edc14aSMd Fahad Iqbal Polash 	struct ice_vsi *vsi = np->vsi;
3396b1edc14aSMd Fahad Iqbal Polash 	struct ice_pf *pf = vsi->back;
3397b1edc14aSMd Fahad Iqbal Polash 	u16 bmode;
3398b1edc14aSMd Fahad Iqbal Polash 
3399b1edc14aSMd Fahad Iqbal Polash 	bmode = pf->first_sw->bridge_mode;
3400b1edc14aSMd Fahad Iqbal Polash 
3401b1edc14aSMd Fahad Iqbal Polash 	return ndo_dflt_bridge_getlink(skb, pid, seq, dev, bmode, 0, 0, nlflags,
3402b1edc14aSMd Fahad Iqbal Polash 				       filter_mask, NULL);
3403b1edc14aSMd Fahad Iqbal Polash }
3404b1edc14aSMd Fahad Iqbal Polash 
3405b1edc14aSMd Fahad Iqbal Polash /**
3406b1edc14aSMd Fahad Iqbal Polash  * ice_vsi_update_bridge_mode - Update VSI for switching bridge mode (VEB/VEPA)
3407b1edc14aSMd Fahad Iqbal Polash  * @vsi: Pointer to VSI structure
3408b1edc14aSMd Fahad Iqbal Polash  * @bmode: Hardware bridge mode (VEB/VEPA)
3409b1edc14aSMd Fahad Iqbal Polash  *
3410b1edc14aSMd Fahad Iqbal Polash  * Returns 0 on success, negative on failure
3411b1edc14aSMd Fahad Iqbal Polash  */
3412b1edc14aSMd Fahad Iqbal Polash static int ice_vsi_update_bridge_mode(struct ice_vsi *vsi, u16 bmode)
3413b1edc14aSMd Fahad Iqbal Polash {
3414b1edc14aSMd Fahad Iqbal Polash 	struct device *dev = &vsi->back->pdev->dev;
3415b1edc14aSMd Fahad Iqbal Polash 	struct ice_aqc_vsi_props *vsi_props;
3416b1edc14aSMd Fahad Iqbal Polash 	struct ice_hw *hw = &vsi->back->hw;
3417b1edc14aSMd Fahad Iqbal Polash 	struct ice_vsi_ctx ctxt = { 0 };
3418b1edc14aSMd Fahad Iqbal Polash 	enum ice_status status;
3419b1edc14aSMd Fahad Iqbal Polash 
3420b1edc14aSMd Fahad Iqbal Polash 	vsi_props = &vsi->info;
3421b1edc14aSMd Fahad Iqbal Polash 	ctxt.info = vsi->info;
3422b1edc14aSMd Fahad Iqbal Polash 
3423b1edc14aSMd Fahad Iqbal Polash 	if (bmode == BRIDGE_MODE_VEB)
3424b1edc14aSMd Fahad Iqbal Polash 		/* change from VEPA to VEB mode */
3425b1edc14aSMd Fahad Iqbal Polash 		ctxt.info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB;
3426b1edc14aSMd Fahad Iqbal Polash 	else
3427b1edc14aSMd Fahad Iqbal Polash 		/* change from VEB to VEPA mode */
3428b1edc14aSMd Fahad Iqbal Polash 		ctxt.info.sw_flags &= ~ICE_AQ_VSI_SW_FLAG_ALLOW_LB;
3429b1edc14aSMd Fahad Iqbal Polash 	ctxt.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SW_VALID);
34305726ca0eSAnirudh Venkataramanan 
34315726ca0eSAnirudh Venkataramanan 	status = ice_update_vsi(hw, vsi->idx, &ctxt, NULL);
3432b1edc14aSMd Fahad Iqbal Polash 	if (status) {
3433b1edc14aSMd Fahad Iqbal Polash 		dev_err(dev, "update VSI for bridge mode failed, bmode = %d err %d aq_err %d\n",
3434b1edc14aSMd Fahad Iqbal Polash 			bmode, status, hw->adminq.sq_last_status);
3435b1edc14aSMd Fahad Iqbal Polash 		return -EIO;
3436b1edc14aSMd Fahad Iqbal Polash 	}
3437b1edc14aSMd Fahad Iqbal Polash 	/* Update sw flags for book keeping */
3438b1edc14aSMd Fahad Iqbal Polash 	vsi_props->sw_flags = ctxt.info.sw_flags;
3439b1edc14aSMd Fahad Iqbal Polash 
3440b1edc14aSMd Fahad Iqbal Polash 	return 0;
3441b1edc14aSMd Fahad Iqbal Polash }
3442b1edc14aSMd Fahad Iqbal Polash 
3443b1edc14aSMd Fahad Iqbal Polash /**
3444b1edc14aSMd Fahad Iqbal Polash  * ice_bridge_setlink - Set the hardware bridge mode
3445b1edc14aSMd Fahad Iqbal Polash  * @dev: the netdev being configured
3446b1edc14aSMd Fahad Iqbal Polash  * @nlh: RTNL message
3447b1edc14aSMd Fahad Iqbal Polash  * @flags: bridge setlink flags
3448b1edc14aSMd Fahad Iqbal Polash  *
3449b1edc14aSMd Fahad Iqbal Polash  * Sets the bridge mode (VEB/VEPA) of the switch to which the netdev (VSI) is
3450b1edc14aSMd Fahad Iqbal Polash  * hooked up to. Iterates through the PF VSI list and sets the loopback mode (if
3451b1edc14aSMd Fahad Iqbal Polash  * not already set for all VSIs connected to this switch. And also update the
3452b1edc14aSMd Fahad Iqbal Polash  * unicast switch filter rules for the corresponding switch of the netdev.
3453b1edc14aSMd Fahad Iqbal Polash  */
3454b1edc14aSMd Fahad Iqbal Polash static int
3455b1edc14aSMd Fahad Iqbal Polash ice_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
3456b1edc14aSMd Fahad Iqbal Polash 		   u16 __always_unused flags)
3457b1edc14aSMd Fahad Iqbal Polash {
3458b1edc14aSMd Fahad Iqbal Polash 	struct ice_netdev_priv *np = netdev_priv(dev);
3459b1edc14aSMd Fahad Iqbal Polash 	struct ice_pf *pf = np->vsi->back;
3460b1edc14aSMd Fahad Iqbal Polash 	struct nlattr *attr, *br_spec;
3461b1edc14aSMd Fahad Iqbal Polash 	struct ice_hw *hw = &pf->hw;
3462b1edc14aSMd Fahad Iqbal Polash 	enum ice_status status;
3463b1edc14aSMd Fahad Iqbal Polash 	struct ice_sw *pf_sw;
3464b1edc14aSMd Fahad Iqbal Polash 	int rem, v, err = 0;
3465b1edc14aSMd Fahad Iqbal Polash 
3466b1edc14aSMd Fahad Iqbal Polash 	pf_sw = pf->first_sw;
3467b1edc14aSMd Fahad Iqbal Polash 	/* find the attribute in the netlink message */
3468b1edc14aSMd Fahad Iqbal Polash 	br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
3469b1edc14aSMd Fahad Iqbal Polash 
3470b1edc14aSMd Fahad Iqbal Polash 	nla_for_each_nested(attr, br_spec, rem) {
3471b1edc14aSMd Fahad Iqbal Polash 		__u16 mode;
3472b1edc14aSMd Fahad Iqbal Polash 
3473b1edc14aSMd Fahad Iqbal Polash 		if (nla_type(attr) != IFLA_BRIDGE_MODE)
3474b1edc14aSMd Fahad Iqbal Polash 			continue;
3475b1edc14aSMd Fahad Iqbal Polash 		mode = nla_get_u16(attr);
3476b1edc14aSMd Fahad Iqbal Polash 		if (mode != BRIDGE_MODE_VEPA && mode != BRIDGE_MODE_VEB)
3477b1edc14aSMd Fahad Iqbal Polash 			return -EINVAL;
3478b1edc14aSMd Fahad Iqbal Polash 		/* Continue  if bridge mode is not being flipped */
3479b1edc14aSMd Fahad Iqbal Polash 		if (mode == pf_sw->bridge_mode)
3480b1edc14aSMd Fahad Iqbal Polash 			continue;
3481b1edc14aSMd Fahad Iqbal Polash 		/* Iterates through the PF VSI list and update the loopback
3482b1edc14aSMd Fahad Iqbal Polash 		 * mode of the VSI
3483b1edc14aSMd Fahad Iqbal Polash 		 */
3484b1edc14aSMd Fahad Iqbal Polash 		ice_for_each_vsi(pf, v) {
3485b1edc14aSMd Fahad Iqbal Polash 			if (!pf->vsi[v])
3486b1edc14aSMd Fahad Iqbal Polash 				continue;
3487b1edc14aSMd Fahad Iqbal Polash 			err = ice_vsi_update_bridge_mode(pf->vsi[v], mode);
3488b1edc14aSMd Fahad Iqbal Polash 			if (err)
3489b1edc14aSMd Fahad Iqbal Polash 				return err;
3490b1edc14aSMd Fahad Iqbal Polash 		}
3491b1edc14aSMd Fahad Iqbal Polash 
3492b1edc14aSMd Fahad Iqbal Polash 		hw->evb_veb = (mode == BRIDGE_MODE_VEB);
3493b1edc14aSMd Fahad Iqbal Polash 		/* Update the unicast switch filter rules for the corresponding
3494b1edc14aSMd Fahad Iqbal Polash 		 * switch of the netdev
3495b1edc14aSMd Fahad Iqbal Polash 		 */
3496b1edc14aSMd Fahad Iqbal Polash 		status = ice_update_sw_rule_bridge_mode(hw);
3497b1edc14aSMd Fahad Iqbal Polash 		if (status) {
3498b1edc14aSMd Fahad Iqbal Polash 			netdev_err(dev, "update SW_RULE for bridge mode failed,  = %d err %d aq_err %d\n",
3499b1edc14aSMd Fahad Iqbal Polash 				   mode, status, hw->adminq.sq_last_status);
3500b1edc14aSMd Fahad Iqbal Polash 			/* revert hw->evb_veb */
3501b1edc14aSMd Fahad Iqbal Polash 			hw->evb_veb = (pf_sw->bridge_mode == BRIDGE_MODE_VEB);
3502b1edc14aSMd Fahad Iqbal Polash 			return -EIO;
3503b1edc14aSMd Fahad Iqbal Polash 		}
3504b1edc14aSMd Fahad Iqbal Polash 
3505b1edc14aSMd Fahad Iqbal Polash 		pf_sw->bridge_mode = mode;
3506b1edc14aSMd Fahad Iqbal Polash 	}
3507b1edc14aSMd Fahad Iqbal Polash 
3508b1edc14aSMd Fahad Iqbal Polash 	return 0;
3509b1edc14aSMd Fahad Iqbal Polash }
3510b1edc14aSMd Fahad Iqbal Polash 
3511b1edc14aSMd Fahad Iqbal Polash /**
3512b3969fd7SSudheer Mogilappagari  * ice_tx_timeout - Respond to a Tx Hang
3513b3969fd7SSudheer Mogilappagari  * @netdev: network interface device structure
3514b3969fd7SSudheer Mogilappagari  */
3515b3969fd7SSudheer Mogilappagari static void ice_tx_timeout(struct net_device *netdev)
3516b3969fd7SSudheer Mogilappagari {
3517b3969fd7SSudheer Mogilappagari 	struct ice_netdev_priv *np = netdev_priv(netdev);
3518b3969fd7SSudheer Mogilappagari 	struct ice_ring *tx_ring = NULL;
3519b3969fd7SSudheer Mogilappagari 	struct ice_vsi *vsi = np->vsi;
3520b3969fd7SSudheer Mogilappagari 	struct ice_pf *pf = vsi->back;
3521b3969fd7SSudheer Mogilappagari 	u32 head, val = 0, i;
3522b3969fd7SSudheer Mogilappagari 	int hung_queue = -1;
3523b3969fd7SSudheer Mogilappagari 
3524b3969fd7SSudheer Mogilappagari 	pf->tx_timeout_count++;
3525b3969fd7SSudheer Mogilappagari 
3526b3969fd7SSudheer Mogilappagari 	/* find the stopped queue the same way the stack does */
3527b3969fd7SSudheer Mogilappagari 	for (i = 0; i < netdev->num_tx_queues; i++) {
3528b3969fd7SSudheer Mogilappagari 		struct netdev_queue *q;
3529b3969fd7SSudheer Mogilappagari 		unsigned long trans_start;
3530b3969fd7SSudheer Mogilappagari 
3531b3969fd7SSudheer Mogilappagari 		q = netdev_get_tx_queue(netdev, i);
3532b3969fd7SSudheer Mogilappagari 		trans_start = q->trans_start;
3533b3969fd7SSudheer Mogilappagari 		if (netif_xmit_stopped(q) &&
3534b3969fd7SSudheer Mogilappagari 		    time_after(jiffies,
3535b3969fd7SSudheer Mogilappagari 			       (trans_start + netdev->watchdog_timeo))) {
3536b3969fd7SSudheer Mogilappagari 			hung_queue = i;
3537b3969fd7SSudheer Mogilappagari 			break;
3538b3969fd7SSudheer Mogilappagari 		}
3539b3969fd7SSudheer Mogilappagari 	}
3540b3969fd7SSudheer Mogilappagari 
3541b3969fd7SSudheer Mogilappagari 	if (i == netdev->num_tx_queues) {
3542b3969fd7SSudheer Mogilappagari 		netdev_info(netdev, "tx_timeout: no netdev hung queue found\n");
3543b3969fd7SSudheer Mogilappagari 	} else {
3544b3969fd7SSudheer Mogilappagari 		/* now that we have an index, find the tx_ring struct */
3545b3969fd7SSudheer Mogilappagari 		for (i = 0; i < vsi->num_txq; i++) {
3546b3969fd7SSudheer Mogilappagari 			if (vsi->tx_rings[i] && vsi->tx_rings[i]->desc) {
3547b3969fd7SSudheer Mogilappagari 				if (hung_queue ==
3548b3969fd7SSudheer Mogilappagari 				    vsi->tx_rings[i]->q_index) {
3549b3969fd7SSudheer Mogilappagari 					tx_ring = vsi->tx_rings[i];
3550b3969fd7SSudheer Mogilappagari 					break;
3551b3969fd7SSudheer Mogilappagari 				}
3552b3969fd7SSudheer Mogilappagari 			}
3553b3969fd7SSudheer Mogilappagari 		}
3554b3969fd7SSudheer Mogilappagari 	}
3555b3969fd7SSudheer Mogilappagari 
3556b3969fd7SSudheer Mogilappagari 	/* Reset recovery level if enough time has elapsed after last timeout.
3557b3969fd7SSudheer Mogilappagari 	 * Also ensure no new reset action happens before next timeout period.
3558b3969fd7SSudheer Mogilappagari 	 */
3559b3969fd7SSudheer Mogilappagari 	if (time_after(jiffies, (pf->tx_timeout_last_recovery + HZ * 20)))
3560b3969fd7SSudheer Mogilappagari 		pf->tx_timeout_recovery_level = 1;
3561b3969fd7SSudheer Mogilappagari 	else if (time_before(jiffies, (pf->tx_timeout_last_recovery +
3562b3969fd7SSudheer Mogilappagari 				       netdev->watchdog_timeo)))
3563b3969fd7SSudheer Mogilappagari 		return;
3564b3969fd7SSudheer Mogilappagari 
3565b3969fd7SSudheer Mogilappagari 	if (tx_ring) {
3566b3969fd7SSudheer Mogilappagari 		head = tx_ring->next_to_clean;
3567b3969fd7SSudheer Mogilappagari 		/* Read interrupt register */
3568b3969fd7SSudheer Mogilappagari 		if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags))
3569b3969fd7SSudheer Mogilappagari 			val = rd32(&pf->hw,
3570b3969fd7SSudheer Mogilappagari 				   GLINT_DYN_CTL(tx_ring->q_vector->v_idx +
3571b3969fd7SSudheer Mogilappagari 						tx_ring->vsi->base_vector - 1));
3572b3969fd7SSudheer Mogilappagari 
3573b3969fd7SSudheer 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",
3574b3969fd7SSudheer Mogilappagari 			    vsi->vsi_num, hung_queue, tx_ring->next_to_clean,
3575b3969fd7SSudheer Mogilappagari 			    head, tx_ring->next_to_use,
3576b3969fd7SSudheer Mogilappagari 			    readl(tx_ring->tail), val);
3577b3969fd7SSudheer Mogilappagari 	}
3578b3969fd7SSudheer Mogilappagari 
3579b3969fd7SSudheer Mogilappagari 	pf->tx_timeout_last_recovery = jiffies;
3580b3969fd7SSudheer Mogilappagari 	netdev_info(netdev, "tx_timeout recovery level %d, hung_queue %d\n",
3581b3969fd7SSudheer Mogilappagari 		    pf->tx_timeout_recovery_level, hung_queue);
3582b3969fd7SSudheer Mogilappagari 
3583b3969fd7SSudheer Mogilappagari 	switch (pf->tx_timeout_recovery_level) {
3584b3969fd7SSudheer Mogilappagari 	case 1:
3585b3969fd7SSudheer Mogilappagari 		set_bit(__ICE_PFR_REQ, pf->state);
3586b3969fd7SSudheer Mogilappagari 		break;
3587b3969fd7SSudheer Mogilappagari 	case 2:
3588b3969fd7SSudheer Mogilappagari 		set_bit(__ICE_CORER_REQ, pf->state);
3589b3969fd7SSudheer Mogilappagari 		break;
3590b3969fd7SSudheer Mogilappagari 	case 3:
3591b3969fd7SSudheer Mogilappagari 		set_bit(__ICE_GLOBR_REQ, pf->state);
3592b3969fd7SSudheer Mogilappagari 		break;
3593b3969fd7SSudheer Mogilappagari 	default:
3594b3969fd7SSudheer Mogilappagari 		netdev_err(netdev, "tx_timeout recovery unsuccessful, device is in unrecoverable state.\n");
3595b3969fd7SSudheer Mogilappagari 		set_bit(__ICE_DOWN, pf->state);
3596b3969fd7SSudheer Mogilappagari 		set_bit(__ICE_NEEDS_RESTART, vsi->state);
35978d81fa55SAkeem G Abodunrin 		set_bit(__ICE_SERVICE_DIS, pf->state);
3598b3969fd7SSudheer Mogilappagari 		break;
3599b3969fd7SSudheer Mogilappagari 	}
3600b3969fd7SSudheer Mogilappagari 
3601b3969fd7SSudheer Mogilappagari 	ice_service_task_schedule(pf);
3602b3969fd7SSudheer Mogilappagari 	pf->tx_timeout_recovery_level++;
3603b3969fd7SSudheer Mogilappagari }
3604b3969fd7SSudheer Mogilappagari 
3605b3969fd7SSudheer Mogilappagari /**
3606cdedef59SAnirudh Venkataramanan  * ice_open - Called when a network interface becomes active
3607cdedef59SAnirudh Venkataramanan  * @netdev: network interface device structure
3608cdedef59SAnirudh Venkataramanan  *
3609cdedef59SAnirudh Venkataramanan  * The open entry point is called when a network interface is made
3610cdedef59SAnirudh Venkataramanan  * active by the system (IFF_UP).  At this point all resources needed
3611cdedef59SAnirudh Venkataramanan  * for transmit and receive operations are allocated, the interrupt
3612cdedef59SAnirudh Venkataramanan  * handler is registered with the OS, the netdev watchdog is enabled,
3613cdedef59SAnirudh Venkataramanan  * and the stack is notified that the interface is ready.
3614cdedef59SAnirudh Venkataramanan  *
3615cdedef59SAnirudh Venkataramanan  * Returns 0 on success, negative value on failure
3616cdedef59SAnirudh Venkataramanan  */
3617cdedef59SAnirudh Venkataramanan static int ice_open(struct net_device *netdev)
3618cdedef59SAnirudh Venkataramanan {
3619cdedef59SAnirudh Venkataramanan 	struct ice_netdev_priv *np = netdev_priv(netdev);
3620cdedef59SAnirudh Venkataramanan 	struct ice_vsi *vsi = np->vsi;
3621cdedef59SAnirudh Venkataramanan 	int err;
3622cdedef59SAnirudh Venkataramanan 
36230f9d5027SAnirudh Venkataramanan 	if (test_bit(__ICE_NEEDS_RESTART, vsi->back->state)) {
36240f9d5027SAnirudh Venkataramanan 		netdev_err(netdev, "driver needs to be unloaded and reloaded\n");
36250f9d5027SAnirudh Venkataramanan 		return -EIO;
36260f9d5027SAnirudh Venkataramanan 	}
36270f9d5027SAnirudh Venkataramanan 
3628cdedef59SAnirudh Venkataramanan 	netif_carrier_off(netdev);
3629cdedef59SAnirudh Venkataramanan 
3630cdedef59SAnirudh Venkataramanan 	err = ice_vsi_open(vsi);
3631cdedef59SAnirudh Venkataramanan 
3632cdedef59SAnirudh Venkataramanan 	if (err)
3633cdedef59SAnirudh Venkataramanan 		netdev_err(netdev, "Failed to open VSI 0x%04X on switch 0x%04X\n",
3634cdedef59SAnirudh Venkataramanan 			   vsi->vsi_num, vsi->vsw->sw_id);
3635cdedef59SAnirudh Venkataramanan 	return err;
3636cdedef59SAnirudh Venkataramanan }
3637cdedef59SAnirudh Venkataramanan 
3638cdedef59SAnirudh Venkataramanan /**
3639cdedef59SAnirudh Venkataramanan  * ice_stop - Disables a network interface
3640cdedef59SAnirudh Venkataramanan  * @netdev: network interface device structure
3641cdedef59SAnirudh Venkataramanan  *
3642cdedef59SAnirudh Venkataramanan  * The stop entry point is called when an interface is de-activated by the OS,
3643cdedef59SAnirudh Venkataramanan  * and the netdevice enters the DOWN state.  The hardware is still under the
3644cdedef59SAnirudh Venkataramanan  * driver's control, but the netdev interface is disabled.
3645cdedef59SAnirudh Venkataramanan  *
3646cdedef59SAnirudh Venkataramanan  * Returns success only - not allowed to fail
3647cdedef59SAnirudh Venkataramanan  */
3648cdedef59SAnirudh Venkataramanan static int ice_stop(struct net_device *netdev)
3649cdedef59SAnirudh Venkataramanan {
3650cdedef59SAnirudh Venkataramanan 	struct ice_netdev_priv *np = netdev_priv(netdev);
3651cdedef59SAnirudh Venkataramanan 	struct ice_vsi *vsi = np->vsi;
3652cdedef59SAnirudh Venkataramanan 
3653cdedef59SAnirudh Venkataramanan 	ice_vsi_close(vsi);
3654cdedef59SAnirudh Venkataramanan 
3655cdedef59SAnirudh Venkataramanan 	return 0;
3656cdedef59SAnirudh Venkataramanan }
3657cdedef59SAnirudh Venkataramanan 
3658e94d4478SAnirudh Venkataramanan /**
3659e94d4478SAnirudh Venkataramanan  * ice_features_check - Validate encapsulated packet conforms to limits
3660e94d4478SAnirudh Venkataramanan  * @skb: skb buffer
3661e94d4478SAnirudh Venkataramanan  * @netdev: This port's netdev
3662e94d4478SAnirudh Venkataramanan  * @features: Offload features that the stack believes apply
3663e94d4478SAnirudh Venkataramanan  */
3664e94d4478SAnirudh Venkataramanan static netdev_features_t
3665e94d4478SAnirudh Venkataramanan ice_features_check(struct sk_buff *skb,
3666e94d4478SAnirudh Venkataramanan 		   struct net_device __always_unused *netdev,
3667e94d4478SAnirudh Venkataramanan 		   netdev_features_t features)
3668e94d4478SAnirudh Venkataramanan {
3669e94d4478SAnirudh Venkataramanan 	size_t len;
3670e94d4478SAnirudh Venkataramanan 
3671e94d4478SAnirudh Venkataramanan 	/* No point in doing any of this if neither checksum nor GSO are
3672e94d4478SAnirudh Venkataramanan 	 * being requested for this frame.  We can rule out both by just
3673e94d4478SAnirudh Venkataramanan 	 * checking for CHECKSUM_PARTIAL
3674e94d4478SAnirudh Venkataramanan 	 */
3675e94d4478SAnirudh Venkataramanan 	if (skb->ip_summed != CHECKSUM_PARTIAL)
3676e94d4478SAnirudh Venkataramanan 		return features;
3677e94d4478SAnirudh Venkataramanan 
3678e94d4478SAnirudh Venkataramanan 	/* We cannot support GSO if the MSS is going to be less than
3679e94d4478SAnirudh Venkataramanan 	 * 64 bytes.  If it is then we need to drop support for GSO.
3680e94d4478SAnirudh Venkataramanan 	 */
3681e94d4478SAnirudh Venkataramanan 	if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64))
3682e94d4478SAnirudh Venkataramanan 		features &= ~NETIF_F_GSO_MASK;
3683e94d4478SAnirudh Venkataramanan 
3684e94d4478SAnirudh Venkataramanan 	len = skb_network_header(skb) - skb->data;
3685e94d4478SAnirudh Venkataramanan 	if (len & ~(ICE_TXD_MACLEN_MAX))
3686e94d4478SAnirudh Venkataramanan 		goto out_rm_features;
3687e94d4478SAnirudh Venkataramanan 
3688e94d4478SAnirudh Venkataramanan 	len = skb_transport_header(skb) - skb_network_header(skb);
3689e94d4478SAnirudh Venkataramanan 	if (len & ~(ICE_TXD_IPLEN_MAX))
3690e94d4478SAnirudh Venkataramanan 		goto out_rm_features;
3691e94d4478SAnirudh Venkataramanan 
3692e94d4478SAnirudh Venkataramanan 	if (skb->encapsulation) {
3693e94d4478SAnirudh Venkataramanan 		len = skb_inner_network_header(skb) - skb_transport_header(skb);
3694e94d4478SAnirudh Venkataramanan 		if (len & ~(ICE_TXD_L4LEN_MAX))
3695e94d4478SAnirudh Venkataramanan 			goto out_rm_features;
3696e94d4478SAnirudh Venkataramanan 
3697e94d4478SAnirudh Venkataramanan 		len = skb_inner_transport_header(skb) -
3698e94d4478SAnirudh Venkataramanan 		      skb_inner_network_header(skb);
3699e94d4478SAnirudh Venkataramanan 		if (len & ~(ICE_TXD_IPLEN_MAX))
3700e94d4478SAnirudh Venkataramanan 			goto out_rm_features;
3701e94d4478SAnirudh Venkataramanan 	}
3702e94d4478SAnirudh Venkataramanan 
3703e94d4478SAnirudh Venkataramanan 	return features;
3704e94d4478SAnirudh Venkataramanan out_rm_features:
3705e94d4478SAnirudh Venkataramanan 	return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
3706e94d4478SAnirudh Venkataramanan }
3707e94d4478SAnirudh Venkataramanan 
3708cdedef59SAnirudh Venkataramanan static const struct net_device_ops ice_netdev_ops = {
3709cdedef59SAnirudh Venkataramanan 	.ndo_open = ice_open,
3710cdedef59SAnirudh Venkataramanan 	.ndo_stop = ice_stop,
37112b245cb2SAnirudh Venkataramanan 	.ndo_start_xmit = ice_start_xmit,
3712e94d4478SAnirudh Venkataramanan 	.ndo_features_check = ice_features_check,
3713e94d4478SAnirudh Venkataramanan 	.ndo_set_rx_mode = ice_set_rx_mode,
3714e94d4478SAnirudh Venkataramanan 	.ndo_set_mac_address = ice_set_mac_address,
3715e94d4478SAnirudh Venkataramanan 	.ndo_validate_addr = eth_validate_addr,
3716e94d4478SAnirudh Venkataramanan 	.ndo_change_mtu = ice_change_mtu,
3717fcea6f3dSAnirudh Venkataramanan 	.ndo_get_stats64 = ice_get_stats64,
3718d76a60baSAnirudh Venkataramanan 	.ndo_vlan_rx_add_vid = ice_vlan_rx_add_vid,
3719d76a60baSAnirudh Venkataramanan 	.ndo_vlan_rx_kill_vid = ice_vlan_rx_kill_vid,
3720d76a60baSAnirudh Venkataramanan 	.ndo_set_features = ice_set_features,
3721b1edc14aSMd Fahad Iqbal Polash 	.ndo_bridge_getlink = ice_bridge_getlink,
3722b1edc14aSMd Fahad Iqbal Polash 	.ndo_bridge_setlink = ice_bridge_setlink,
3723e94d4478SAnirudh Venkataramanan 	.ndo_fdb_add = ice_fdb_add,
3724e94d4478SAnirudh Venkataramanan 	.ndo_fdb_del = ice_fdb_del,
3725b3969fd7SSudheer Mogilappagari 	.ndo_tx_timeout = ice_tx_timeout,
3726cdedef59SAnirudh Venkataramanan };
3727