xref: /linux/drivers/net/ethernet/intel/idpf/idpf_lib.c (revision 9410645520e9b820069761f3450ef6661418e279)
18077c727SJoshua Hay // SPDX-License-Identifier: GPL-2.0-only
28077c727SJoshua Hay /* Copyright (C) 2023 Intel Corporation */
38077c727SJoshua Hay 
48077c727SJoshua Hay #include "idpf.h"
55dc283faSAlan Brady #include "idpf_virtchnl.h"
68077c727SJoshua Hay 
714f662b4SAlexander Lobakin static const struct net_device_ops idpf_netdev_ops;
81c325aacSAlan Brady 
94930fbf4SPavan Kumar Linga /**
104930fbf4SPavan Kumar Linga  * idpf_init_vector_stack - Fill the MSIX vector stack with vector index
114930fbf4SPavan Kumar Linga  * @adapter: private data struct
124930fbf4SPavan Kumar Linga  *
134930fbf4SPavan Kumar Linga  * Return 0 on success, error on failure
144930fbf4SPavan Kumar Linga  */
idpf_init_vector_stack(struct idpf_adapter * adapter)154930fbf4SPavan Kumar Linga static int idpf_init_vector_stack(struct idpf_adapter *adapter)
164930fbf4SPavan Kumar Linga {
174930fbf4SPavan Kumar Linga 	struct idpf_vector_lifo *stack;
184930fbf4SPavan Kumar Linga 	u16 min_vec;
194930fbf4SPavan Kumar Linga 	u32 i;
204930fbf4SPavan Kumar Linga 
214930fbf4SPavan Kumar Linga 	mutex_lock(&adapter->vector_lock);
224930fbf4SPavan Kumar Linga 	min_vec = adapter->num_msix_entries - adapter->num_avail_msix;
234930fbf4SPavan Kumar Linga 	stack = &adapter->vector_stack;
244930fbf4SPavan Kumar Linga 	stack->size = adapter->num_msix_entries;
254930fbf4SPavan Kumar Linga 	/* set the base and top to point at start of the 'free pool' to
264930fbf4SPavan Kumar Linga 	 * distribute the unused vectors on-demand basis
274930fbf4SPavan Kumar Linga 	 */
284930fbf4SPavan Kumar Linga 	stack->base = min_vec;
294930fbf4SPavan Kumar Linga 	stack->top = min_vec;
304930fbf4SPavan Kumar Linga 
314930fbf4SPavan Kumar Linga 	stack->vec_idx = kcalloc(stack->size, sizeof(u16), GFP_KERNEL);
324930fbf4SPavan Kumar Linga 	if (!stack->vec_idx) {
334930fbf4SPavan Kumar Linga 		mutex_unlock(&adapter->vector_lock);
344930fbf4SPavan Kumar Linga 
354930fbf4SPavan Kumar Linga 		return -ENOMEM;
364930fbf4SPavan Kumar Linga 	}
374930fbf4SPavan Kumar Linga 
384930fbf4SPavan Kumar Linga 	for (i = 0; i < stack->size; i++)
394930fbf4SPavan Kumar Linga 		stack->vec_idx[i] = i;
404930fbf4SPavan Kumar Linga 
414930fbf4SPavan Kumar Linga 	mutex_unlock(&adapter->vector_lock);
424930fbf4SPavan Kumar Linga 
434930fbf4SPavan Kumar Linga 	return 0;
444930fbf4SPavan Kumar Linga }
454930fbf4SPavan Kumar Linga 
464930fbf4SPavan Kumar Linga /**
474930fbf4SPavan Kumar Linga  * idpf_deinit_vector_stack - zero out the MSIX vector stack
484930fbf4SPavan Kumar Linga  * @adapter: private data struct
494930fbf4SPavan Kumar Linga  */
idpf_deinit_vector_stack(struct idpf_adapter * adapter)504930fbf4SPavan Kumar Linga static void idpf_deinit_vector_stack(struct idpf_adapter *adapter)
514930fbf4SPavan Kumar Linga {
524930fbf4SPavan Kumar Linga 	struct idpf_vector_lifo *stack;
534930fbf4SPavan Kumar Linga 
544930fbf4SPavan Kumar Linga 	mutex_lock(&adapter->vector_lock);
554930fbf4SPavan Kumar Linga 	stack = &adapter->vector_stack;
564930fbf4SPavan Kumar Linga 	kfree(stack->vec_idx);
574930fbf4SPavan Kumar Linga 	stack->vec_idx = NULL;
584930fbf4SPavan Kumar Linga 	mutex_unlock(&adapter->vector_lock);
594930fbf4SPavan Kumar Linga }
604930fbf4SPavan Kumar Linga 
614930fbf4SPavan Kumar Linga /**
624930fbf4SPavan Kumar Linga  * idpf_mb_intr_rel_irq - Free the IRQ association with the OS
634930fbf4SPavan Kumar Linga  * @adapter: adapter structure
644930fbf4SPavan Kumar Linga  *
654930fbf4SPavan Kumar Linga  * This will also disable interrupt mode and queue up mailbox task. Mailbox
664930fbf4SPavan Kumar Linga  * task will reschedule itself if not in interrupt mode.
674930fbf4SPavan Kumar Linga  */
idpf_mb_intr_rel_irq(struct idpf_adapter * adapter)684930fbf4SPavan Kumar Linga static void idpf_mb_intr_rel_irq(struct idpf_adapter *adapter)
694930fbf4SPavan Kumar Linga {
704930fbf4SPavan Kumar Linga 	clear_bit(IDPF_MB_INTR_MODE, adapter->flags);
71bf9bf704SAlexander Lobakin 	kfree(free_irq(adapter->msix_entries[0].vector, adapter));
724930fbf4SPavan Kumar Linga 	queue_delayed_work(adapter->mbx_wq, &adapter->mbx_task, 0);
734930fbf4SPavan Kumar Linga }
744930fbf4SPavan Kumar Linga 
754930fbf4SPavan Kumar Linga /**
764930fbf4SPavan Kumar Linga  * idpf_intr_rel - Release interrupt capabilities and free memory
774930fbf4SPavan Kumar Linga  * @adapter: adapter to disable interrupts on
784930fbf4SPavan Kumar Linga  */
idpf_intr_rel(struct idpf_adapter * adapter)794930fbf4SPavan Kumar Linga void idpf_intr_rel(struct idpf_adapter *adapter)
804930fbf4SPavan Kumar Linga {
814930fbf4SPavan Kumar Linga 	if (!adapter->msix_entries)
824930fbf4SPavan Kumar Linga 		return;
834930fbf4SPavan Kumar Linga 
844930fbf4SPavan Kumar Linga 	idpf_mb_intr_rel_irq(adapter);
854930fbf4SPavan Kumar Linga 	pci_free_irq_vectors(adapter->pdev);
866009e63cSAlan Brady 	idpf_send_dealloc_vectors_msg(adapter);
874930fbf4SPavan Kumar Linga 	idpf_deinit_vector_stack(adapter);
884930fbf4SPavan Kumar Linga 	kfree(adapter->msix_entries);
894930fbf4SPavan Kumar Linga 	adapter->msix_entries = NULL;
904930fbf4SPavan Kumar Linga }
914930fbf4SPavan Kumar Linga 
924930fbf4SPavan Kumar Linga /**
934930fbf4SPavan Kumar Linga  * idpf_mb_intr_clean - Interrupt handler for the mailbox
944930fbf4SPavan Kumar Linga  * @irq: interrupt number
954930fbf4SPavan Kumar Linga  * @data: pointer to the adapter structure
964930fbf4SPavan Kumar Linga  */
idpf_mb_intr_clean(int __always_unused irq,void * data)974930fbf4SPavan Kumar Linga static irqreturn_t idpf_mb_intr_clean(int __always_unused irq, void *data)
984930fbf4SPavan Kumar Linga {
994930fbf4SPavan Kumar Linga 	struct idpf_adapter *adapter = (struct idpf_adapter *)data;
1004930fbf4SPavan Kumar Linga 
1014930fbf4SPavan Kumar Linga 	queue_delayed_work(adapter->mbx_wq, &adapter->mbx_task, 0);
1024930fbf4SPavan Kumar Linga 
1034930fbf4SPavan Kumar Linga 	return IRQ_HANDLED;
1044930fbf4SPavan Kumar Linga }
1054930fbf4SPavan Kumar Linga 
1064930fbf4SPavan Kumar Linga /**
1074930fbf4SPavan Kumar Linga  * idpf_mb_irq_enable - Enable MSIX interrupt for the mailbox
1084930fbf4SPavan Kumar Linga  * @adapter: adapter to get the hardware address for register write
1094930fbf4SPavan Kumar Linga  */
idpf_mb_irq_enable(struct idpf_adapter * adapter)1104930fbf4SPavan Kumar Linga static void idpf_mb_irq_enable(struct idpf_adapter *adapter)
1114930fbf4SPavan Kumar Linga {
1124930fbf4SPavan Kumar Linga 	struct idpf_intr_reg *intr = &adapter->mb_vector.intr_reg;
1134930fbf4SPavan Kumar Linga 	u32 val;
1144930fbf4SPavan Kumar Linga 
1154930fbf4SPavan Kumar Linga 	val = intr->dyn_ctl_intena_m | intr->dyn_ctl_itridx_m;
1164930fbf4SPavan Kumar Linga 	writel(val, intr->dyn_ctl);
1174930fbf4SPavan Kumar Linga 	writel(intr->icr_ena_ctlq_m, intr->icr_ena);
1184930fbf4SPavan Kumar Linga }
1194930fbf4SPavan Kumar Linga 
1204930fbf4SPavan Kumar Linga /**
1214930fbf4SPavan Kumar Linga  * idpf_mb_intr_req_irq - Request irq for the mailbox interrupt
1224930fbf4SPavan Kumar Linga  * @adapter: adapter structure to pass to the mailbox irq handler
1234930fbf4SPavan Kumar Linga  */
idpf_mb_intr_req_irq(struct idpf_adapter * adapter)1244930fbf4SPavan Kumar Linga static int idpf_mb_intr_req_irq(struct idpf_adapter *adapter)
1254930fbf4SPavan Kumar Linga {
1264930fbf4SPavan Kumar Linga 	int irq_num, mb_vidx = 0, err;
127bf9bf704SAlexander Lobakin 	char *name;
1284930fbf4SPavan Kumar Linga 
1294930fbf4SPavan Kumar Linga 	irq_num = adapter->msix_entries[mb_vidx].vector;
130bf9bf704SAlexander Lobakin 	name = kasprintf(GFP_KERNEL, "%s-%s-%d",
1314930fbf4SPavan Kumar Linga 			 dev_driver_string(&adapter->pdev->dev),
1324930fbf4SPavan Kumar Linga 			 "Mailbox", mb_vidx);
133bf9bf704SAlexander Lobakin 	err = request_irq(irq_num, adapter->irq_mb_handler, 0, name, adapter);
1344930fbf4SPavan Kumar Linga 	if (err) {
1354930fbf4SPavan Kumar Linga 		dev_err(&adapter->pdev->dev,
1364930fbf4SPavan Kumar Linga 			"IRQ request for mailbox failed, error: %d\n", err);
1374930fbf4SPavan Kumar Linga 
1384930fbf4SPavan Kumar Linga 		return err;
1394930fbf4SPavan Kumar Linga 	}
1404930fbf4SPavan Kumar Linga 
1414930fbf4SPavan Kumar Linga 	set_bit(IDPF_MB_INTR_MODE, adapter->flags);
1424930fbf4SPavan Kumar Linga 
1434930fbf4SPavan Kumar Linga 	return 0;
1444930fbf4SPavan Kumar Linga }
1454930fbf4SPavan Kumar Linga 
1464930fbf4SPavan Kumar Linga /**
1474930fbf4SPavan Kumar Linga  * idpf_set_mb_vec_id - Set vector index for mailbox
1484930fbf4SPavan Kumar Linga  * @adapter: adapter structure to access the vector chunks
1494930fbf4SPavan Kumar Linga  *
1504930fbf4SPavan Kumar Linga  * The first vector id in the requested vector chunks from the CP is for
1514930fbf4SPavan Kumar Linga  * the mailbox
1524930fbf4SPavan Kumar Linga  */
idpf_set_mb_vec_id(struct idpf_adapter * adapter)1534930fbf4SPavan Kumar Linga static void idpf_set_mb_vec_id(struct idpf_adapter *adapter)
1544930fbf4SPavan Kumar Linga {
1554930fbf4SPavan Kumar Linga 	if (adapter->req_vec_chunks)
1564930fbf4SPavan Kumar Linga 		adapter->mb_vector.v_idx =
1574930fbf4SPavan Kumar Linga 			le16_to_cpu(adapter->caps.mailbox_vector_id);
1584930fbf4SPavan Kumar Linga 	else
1594930fbf4SPavan Kumar Linga 		adapter->mb_vector.v_idx = 0;
1604930fbf4SPavan Kumar Linga }
1614930fbf4SPavan Kumar Linga 
1624930fbf4SPavan Kumar Linga /**
1634930fbf4SPavan Kumar Linga  * idpf_mb_intr_init - Initialize the mailbox interrupt
1644930fbf4SPavan Kumar Linga  * @adapter: adapter structure to store the mailbox vector
1654930fbf4SPavan Kumar Linga  */
idpf_mb_intr_init(struct idpf_adapter * adapter)1664930fbf4SPavan Kumar Linga static int idpf_mb_intr_init(struct idpf_adapter *adapter)
1674930fbf4SPavan Kumar Linga {
1684930fbf4SPavan Kumar Linga 	adapter->dev_ops.reg_ops.mb_intr_reg_init(adapter);
1694930fbf4SPavan Kumar Linga 	adapter->irq_mb_handler = idpf_mb_intr_clean;
1704930fbf4SPavan Kumar Linga 
1714930fbf4SPavan Kumar Linga 	return idpf_mb_intr_req_irq(adapter);
1724930fbf4SPavan Kumar Linga }
1734930fbf4SPavan Kumar Linga 
1744930fbf4SPavan Kumar Linga /**
175d4d55871SPavan Kumar Linga  * idpf_vector_lifo_push - push MSIX vector index onto stack
176d4d55871SPavan Kumar Linga  * @adapter: private data struct
177d4d55871SPavan Kumar Linga  * @vec_idx: vector index to store
178d4d55871SPavan Kumar Linga  */
idpf_vector_lifo_push(struct idpf_adapter * adapter,u16 vec_idx)179d4d55871SPavan Kumar Linga static int idpf_vector_lifo_push(struct idpf_adapter *adapter, u16 vec_idx)
180d4d55871SPavan Kumar Linga {
181d4d55871SPavan Kumar Linga 	struct idpf_vector_lifo *stack = &adapter->vector_stack;
182d4d55871SPavan Kumar Linga 
183d4d55871SPavan Kumar Linga 	lockdep_assert_held(&adapter->vector_lock);
184d4d55871SPavan Kumar Linga 
185d4d55871SPavan Kumar Linga 	if (stack->top == stack->base) {
186d4d55871SPavan Kumar Linga 		dev_err(&adapter->pdev->dev, "Exceeded the vector stack limit: %d\n",
187d4d55871SPavan Kumar Linga 			stack->top);
188d4d55871SPavan Kumar Linga 		return -EINVAL;
189d4d55871SPavan Kumar Linga 	}
190d4d55871SPavan Kumar Linga 
191d4d55871SPavan Kumar Linga 	stack->vec_idx[--stack->top] = vec_idx;
192d4d55871SPavan Kumar Linga 
193d4d55871SPavan Kumar Linga 	return 0;
194d4d55871SPavan Kumar Linga }
195d4d55871SPavan Kumar Linga 
196d4d55871SPavan Kumar Linga /**
197d4d55871SPavan Kumar Linga  * idpf_vector_lifo_pop - pop MSIX vector index from stack
198d4d55871SPavan Kumar Linga  * @adapter: private data struct
199d4d55871SPavan Kumar Linga  */
idpf_vector_lifo_pop(struct idpf_adapter * adapter)200d4d55871SPavan Kumar Linga static int idpf_vector_lifo_pop(struct idpf_adapter *adapter)
201d4d55871SPavan Kumar Linga {
202d4d55871SPavan Kumar Linga 	struct idpf_vector_lifo *stack = &adapter->vector_stack;
203d4d55871SPavan Kumar Linga 
204d4d55871SPavan Kumar Linga 	lockdep_assert_held(&adapter->vector_lock);
205d4d55871SPavan Kumar Linga 
206d4d55871SPavan Kumar Linga 	if (stack->top == stack->size) {
207d4d55871SPavan Kumar Linga 		dev_err(&adapter->pdev->dev, "No interrupt vectors are available to distribute!\n");
208d4d55871SPavan Kumar Linga 
209d4d55871SPavan Kumar Linga 		return -EINVAL;
210d4d55871SPavan Kumar Linga 	}
211d4d55871SPavan Kumar Linga 
212d4d55871SPavan Kumar Linga 	return stack->vec_idx[stack->top++];
213d4d55871SPavan Kumar Linga }
214d4d55871SPavan Kumar Linga 
215d4d55871SPavan Kumar Linga /**
216d4d55871SPavan Kumar Linga  * idpf_vector_stash - Store the vector indexes onto the stack
217d4d55871SPavan Kumar Linga  * @adapter: private data struct
218d4d55871SPavan Kumar Linga  * @q_vector_idxs: vector index array
219d4d55871SPavan Kumar Linga  * @vec_info: info related to the number of vectors
220d4d55871SPavan Kumar Linga  *
221d4d55871SPavan Kumar Linga  * This function is a no-op if there are no vectors indexes to be stashed
222d4d55871SPavan Kumar Linga  */
idpf_vector_stash(struct idpf_adapter * adapter,u16 * q_vector_idxs,struct idpf_vector_info * vec_info)223d4d55871SPavan Kumar Linga static void idpf_vector_stash(struct idpf_adapter *adapter, u16 *q_vector_idxs,
224d4d55871SPavan Kumar Linga 			      struct idpf_vector_info *vec_info)
225d4d55871SPavan Kumar Linga {
226d4d55871SPavan Kumar Linga 	int i, base = 0;
227d4d55871SPavan Kumar Linga 	u16 vec_idx;
228d4d55871SPavan Kumar Linga 
229d4d55871SPavan Kumar Linga 	lockdep_assert_held(&adapter->vector_lock);
230d4d55871SPavan Kumar Linga 
231d4d55871SPavan Kumar Linga 	if (!vec_info->num_curr_vecs)
232d4d55871SPavan Kumar Linga 		return;
233d4d55871SPavan Kumar Linga 
234d4d55871SPavan Kumar Linga 	/* For default vports, no need to stash vector allocated from the
235d4d55871SPavan Kumar Linga 	 * default pool onto the stack
236d4d55871SPavan Kumar Linga 	 */
237d4d55871SPavan Kumar Linga 	if (vec_info->default_vport)
238d4d55871SPavan Kumar Linga 		base = IDPF_MIN_Q_VEC;
239d4d55871SPavan Kumar Linga 
240d4d55871SPavan Kumar Linga 	for (i = vec_info->num_curr_vecs - 1; i >= base ; i--) {
241d4d55871SPavan Kumar Linga 		vec_idx = q_vector_idxs[i];
242d4d55871SPavan Kumar Linga 		idpf_vector_lifo_push(adapter, vec_idx);
243d4d55871SPavan Kumar Linga 		adapter->num_avail_msix++;
244d4d55871SPavan Kumar Linga 	}
245d4d55871SPavan Kumar Linga }
246d4d55871SPavan Kumar Linga 
247d4d55871SPavan Kumar Linga /**
248d4d55871SPavan Kumar Linga  * idpf_req_rel_vector_indexes - Request or release MSIX vector indexes
249d4d55871SPavan Kumar Linga  * @adapter: driver specific private structure
250d4d55871SPavan Kumar Linga  * @q_vector_idxs: vector index array
251d4d55871SPavan Kumar Linga  * @vec_info: info related to the number of vectors
252d4d55871SPavan Kumar Linga  *
253d4d55871SPavan Kumar Linga  * This is the core function to distribute the MSIX vectors acquired from the
254d4d55871SPavan Kumar Linga  * OS. It expects the caller to pass the number of vectors required and
255d4d55871SPavan Kumar Linga  * also previously allocated. First, it stashes previously allocated vector
256d4d55871SPavan Kumar Linga  * indexes on to the stack and then figures out if it can allocate requested
257d4d55871SPavan Kumar Linga  * vectors. It can wait on acquiring the mutex lock. If the caller passes 0 as
258d4d55871SPavan Kumar Linga  * requested vectors, then this function just stashes the already allocated
259d4d55871SPavan Kumar Linga  * vectors and returns 0.
260d4d55871SPavan Kumar Linga  *
261d4d55871SPavan Kumar Linga  * Returns actual number of vectors allocated on success, error value on failure
262d4d55871SPavan Kumar Linga  * If 0 is returned, implies the stack has no vectors to allocate which is also
263d4d55871SPavan Kumar Linga  * a failure case for the caller
264d4d55871SPavan Kumar Linga  */
idpf_req_rel_vector_indexes(struct idpf_adapter * adapter,u16 * q_vector_idxs,struct idpf_vector_info * vec_info)265d4d55871SPavan Kumar Linga int idpf_req_rel_vector_indexes(struct idpf_adapter *adapter,
266d4d55871SPavan Kumar Linga 				u16 *q_vector_idxs,
267d4d55871SPavan Kumar Linga 				struct idpf_vector_info *vec_info)
268d4d55871SPavan Kumar Linga {
269d4d55871SPavan Kumar Linga 	u16 num_req_vecs, num_alloc_vecs = 0, max_vecs;
270d4d55871SPavan Kumar Linga 	struct idpf_vector_lifo *stack;
271d4d55871SPavan Kumar Linga 	int i, j, vecid;
272d4d55871SPavan Kumar Linga 
273d4d55871SPavan Kumar Linga 	mutex_lock(&adapter->vector_lock);
274d4d55871SPavan Kumar Linga 	stack = &adapter->vector_stack;
275d4d55871SPavan Kumar Linga 	num_req_vecs = vec_info->num_req_vecs;
276d4d55871SPavan Kumar Linga 
277d4d55871SPavan Kumar Linga 	/* Stash interrupt vector indexes onto the stack if required */
278d4d55871SPavan Kumar Linga 	idpf_vector_stash(adapter, q_vector_idxs, vec_info);
279d4d55871SPavan Kumar Linga 
280d4d55871SPavan Kumar Linga 	if (!num_req_vecs)
281d4d55871SPavan Kumar Linga 		goto rel_lock;
282d4d55871SPavan Kumar Linga 
283d4d55871SPavan Kumar Linga 	if (vec_info->default_vport) {
284d4d55871SPavan Kumar Linga 		/* As IDPF_MIN_Q_VEC per default vport is put aside in the
285d4d55871SPavan Kumar Linga 		 * default pool of the stack, use them for default vports
286d4d55871SPavan Kumar Linga 		 */
287d4d55871SPavan Kumar Linga 		j = vec_info->index * IDPF_MIN_Q_VEC + IDPF_MBX_Q_VEC;
288d4d55871SPavan Kumar Linga 		for (i = 0; i < IDPF_MIN_Q_VEC; i++) {
289d4d55871SPavan Kumar Linga 			q_vector_idxs[num_alloc_vecs++] = stack->vec_idx[j++];
290d4d55871SPavan Kumar Linga 			num_req_vecs--;
291d4d55871SPavan Kumar Linga 		}
292d4d55871SPavan Kumar Linga 	}
293d4d55871SPavan Kumar Linga 
294d4d55871SPavan Kumar Linga 	/* Find if stack has enough vector to allocate */
295d4d55871SPavan Kumar Linga 	max_vecs = min(adapter->num_avail_msix, num_req_vecs);
296d4d55871SPavan Kumar Linga 
297d4d55871SPavan Kumar Linga 	for (j = 0; j < max_vecs; j++) {
298d4d55871SPavan Kumar Linga 		vecid = idpf_vector_lifo_pop(adapter);
299d4d55871SPavan Kumar Linga 		q_vector_idxs[num_alloc_vecs++] = vecid;
300d4d55871SPavan Kumar Linga 	}
301d4d55871SPavan Kumar Linga 	adapter->num_avail_msix -= max_vecs;
302d4d55871SPavan Kumar Linga 
303d4d55871SPavan Kumar Linga rel_lock:
304d4d55871SPavan Kumar Linga 	mutex_unlock(&adapter->vector_lock);
305d4d55871SPavan Kumar Linga 
306d4d55871SPavan Kumar Linga 	return num_alloc_vecs;
307d4d55871SPavan Kumar Linga }
308d4d55871SPavan Kumar Linga 
309d4d55871SPavan Kumar Linga /**
3104930fbf4SPavan Kumar Linga  * idpf_intr_req - Request interrupt capabilities
3114930fbf4SPavan Kumar Linga  * @adapter: adapter to enable interrupts on
3124930fbf4SPavan Kumar Linga  *
3134930fbf4SPavan Kumar Linga  * Returns 0 on success, negative on failure
3144930fbf4SPavan Kumar Linga  */
idpf_intr_req(struct idpf_adapter * adapter)3154930fbf4SPavan Kumar Linga int idpf_intr_req(struct idpf_adapter *adapter)
3164930fbf4SPavan Kumar Linga {
3174930fbf4SPavan Kumar Linga 	u16 default_vports = idpf_get_default_vports(adapter);
3184930fbf4SPavan Kumar Linga 	int num_q_vecs, total_vecs, num_vec_ids;
3194930fbf4SPavan Kumar Linga 	int min_vectors, v_actual, err;
3204930fbf4SPavan Kumar Linga 	unsigned int vector;
3214930fbf4SPavan Kumar Linga 	u16 *vecids;
3224930fbf4SPavan Kumar Linga 
3234930fbf4SPavan Kumar Linga 	total_vecs = idpf_get_reserved_vecs(adapter);
3244930fbf4SPavan Kumar Linga 	num_q_vecs = total_vecs - IDPF_MBX_Q_VEC;
3254930fbf4SPavan Kumar Linga 
3264930fbf4SPavan Kumar Linga 	err = idpf_send_alloc_vectors_msg(adapter, num_q_vecs);
3274930fbf4SPavan Kumar Linga 	if (err) {
3284930fbf4SPavan Kumar Linga 		dev_err(&adapter->pdev->dev,
3294930fbf4SPavan Kumar Linga 			"Failed to allocate %d vectors: %d\n", num_q_vecs, err);
3304930fbf4SPavan Kumar Linga 
3314930fbf4SPavan Kumar Linga 		return -EAGAIN;
3324930fbf4SPavan Kumar Linga 	}
3334930fbf4SPavan Kumar Linga 
3344930fbf4SPavan Kumar Linga 	min_vectors = IDPF_MBX_Q_VEC + IDPF_MIN_Q_VEC * default_vports;
3354930fbf4SPavan Kumar Linga 	v_actual = pci_alloc_irq_vectors(adapter->pdev, min_vectors,
3364930fbf4SPavan Kumar Linga 					 total_vecs, PCI_IRQ_MSIX);
3374930fbf4SPavan Kumar Linga 	if (v_actual < min_vectors) {
3384930fbf4SPavan Kumar Linga 		dev_err(&adapter->pdev->dev, "Failed to allocate MSIX vectors: %d\n",
3394930fbf4SPavan Kumar Linga 			v_actual);
3404930fbf4SPavan Kumar Linga 		err = -EAGAIN;
3414930fbf4SPavan Kumar Linga 		goto send_dealloc_vecs;
3424930fbf4SPavan Kumar Linga 	}
3434930fbf4SPavan Kumar Linga 
3444930fbf4SPavan Kumar Linga 	adapter->msix_entries = kcalloc(v_actual, sizeof(struct msix_entry),
3454930fbf4SPavan Kumar Linga 					GFP_KERNEL);
3464930fbf4SPavan Kumar Linga 
3474930fbf4SPavan Kumar Linga 	if (!adapter->msix_entries) {
3484930fbf4SPavan Kumar Linga 		err = -ENOMEM;
3494930fbf4SPavan Kumar Linga 		goto free_irq;
3504930fbf4SPavan Kumar Linga 	}
3514930fbf4SPavan Kumar Linga 
3524930fbf4SPavan Kumar Linga 	idpf_set_mb_vec_id(adapter);
3534930fbf4SPavan Kumar Linga 
3544930fbf4SPavan Kumar Linga 	vecids = kcalloc(total_vecs, sizeof(u16), GFP_KERNEL);
3554930fbf4SPavan Kumar Linga 	if (!vecids) {
3564930fbf4SPavan Kumar Linga 		err = -ENOMEM;
3574930fbf4SPavan Kumar Linga 		goto free_msix;
3584930fbf4SPavan Kumar Linga 	}
3594930fbf4SPavan Kumar Linga 
3604930fbf4SPavan Kumar Linga 	num_vec_ids = idpf_get_vec_ids(adapter, vecids, total_vecs,
361*795b1aa8SPavan Kumar Linga 				       &adapter->req_vec_chunks->vchunks);
3624930fbf4SPavan Kumar Linga 	if (num_vec_ids < v_actual) {
3634930fbf4SPavan Kumar Linga 		err = -EINVAL;
3644930fbf4SPavan Kumar Linga 		goto free_vecids;
3654930fbf4SPavan Kumar Linga 	}
3664930fbf4SPavan Kumar Linga 
3674930fbf4SPavan Kumar Linga 	for (vector = 0; vector < v_actual; vector++) {
3684930fbf4SPavan Kumar Linga 		adapter->msix_entries[vector].entry = vecids[vector];
3694930fbf4SPavan Kumar Linga 		adapter->msix_entries[vector].vector =
3704930fbf4SPavan Kumar Linga 			pci_irq_vector(adapter->pdev, vector);
3714930fbf4SPavan Kumar Linga 	}
3724930fbf4SPavan Kumar Linga 
3734930fbf4SPavan Kumar Linga 	adapter->num_req_msix = total_vecs;
3744930fbf4SPavan Kumar Linga 	adapter->num_msix_entries = v_actual;
3754930fbf4SPavan Kumar Linga 	/* 'num_avail_msix' is used to distribute excess vectors to the vports
3764930fbf4SPavan Kumar Linga 	 * after considering the minimum vectors required per each default
3774930fbf4SPavan Kumar Linga 	 * vport
3784930fbf4SPavan Kumar Linga 	 */
3794930fbf4SPavan Kumar Linga 	adapter->num_avail_msix = v_actual - min_vectors;
3804930fbf4SPavan Kumar Linga 
3814930fbf4SPavan Kumar Linga 	/* Fill MSIX vector lifo stack with vector indexes */
3824930fbf4SPavan Kumar Linga 	err = idpf_init_vector_stack(adapter);
3834930fbf4SPavan Kumar Linga 	if (err)
3844930fbf4SPavan Kumar Linga 		goto free_vecids;
3854930fbf4SPavan Kumar Linga 
3864930fbf4SPavan Kumar Linga 	err = idpf_mb_intr_init(adapter);
3874930fbf4SPavan Kumar Linga 	if (err)
3884930fbf4SPavan Kumar Linga 		goto deinit_vec_stack;
3894930fbf4SPavan Kumar Linga 	idpf_mb_irq_enable(adapter);
3904930fbf4SPavan Kumar Linga 	kfree(vecids);
3914930fbf4SPavan Kumar Linga 
3924930fbf4SPavan Kumar Linga 	return 0;
3934930fbf4SPavan Kumar Linga 
3944930fbf4SPavan Kumar Linga deinit_vec_stack:
3954930fbf4SPavan Kumar Linga 	idpf_deinit_vector_stack(adapter);
3964930fbf4SPavan Kumar Linga free_vecids:
3974930fbf4SPavan Kumar Linga 	kfree(vecids);
3984930fbf4SPavan Kumar Linga free_msix:
3994930fbf4SPavan Kumar Linga 	kfree(adapter->msix_entries);
4004930fbf4SPavan Kumar Linga 	adapter->msix_entries = NULL;
4014930fbf4SPavan Kumar Linga free_irq:
4024930fbf4SPavan Kumar Linga 	pci_free_irq_vectors(adapter->pdev);
4034930fbf4SPavan Kumar Linga send_dealloc_vecs:
4044930fbf4SPavan Kumar Linga 	idpf_send_dealloc_vectors_msg(adapter);
4054930fbf4SPavan Kumar Linga 
4064930fbf4SPavan Kumar Linga 	return err;
4074930fbf4SPavan Kumar Linga }
4084930fbf4SPavan Kumar Linga 
4094930fbf4SPavan Kumar Linga /**
410ce1b75d0SPavan Kumar Linga  * idpf_find_mac_filter - Search filter list for specific mac filter
411ce1b75d0SPavan Kumar Linga  * @vconfig: Vport config structure
412ce1b75d0SPavan Kumar Linga  * @macaddr: The MAC address
413ce1b75d0SPavan Kumar Linga  *
414ce1b75d0SPavan Kumar Linga  * Returns ptr to the filter object or NULL. Must be called while holding the
415ce1b75d0SPavan Kumar Linga  * mac_filter_list_lock.
416ce1b75d0SPavan Kumar Linga  **/
idpf_find_mac_filter(struct idpf_vport_config * vconfig,const u8 * macaddr)417ce1b75d0SPavan Kumar Linga static struct idpf_mac_filter *idpf_find_mac_filter(struct idpf_vport_config *vconfig,
418ce1b75d0SPavan Kumar Linga 						    const u8 *macaddr)
419ce1b75d0SPavan Kumar Linga {
420ce1b75d0SPavan Kumar Linga 	struct idpf_mac_filter *f;
421ce1b75d0SPavan Kumar Linga 
422ce1b75d0SPavan Kumar Linga 	if (!macaddr)
423ce1b75d0SPavan Kumar Linga 		return NULL;
424ce1b75d0SPavan Kumar Linga 
425ce1b75d0SPavan Kumar Linga 	list_for_each_entry(f, &vconfig->user_config.mac_filter_list, list) {
426ce1b75d0SPavan Kumar Linga 		if (ether_addr_equal(macaddr, f->macaddr))
427ce1b75d0SPavan Kumar Linga 			return f;
428ce1b75d0SPavan Kumar Linga 	}
429ce1b75d0SPavan Kumar Linga 
430ce1b75d0SPavan Kumar Linga 	return NULL;
431ce1b75d0SPavan Kumar Linga }
432ce1b75d0SPavan Kumar Linga 
433ce1b75d0SPavan Kumar Linga /**
434a251eee6SJoshua Hay  * __idpf_del_mac_filter - Delete a MAC filter from the filter list
435a251eee6SJoshua Hay  * @vport_config: Vport config structure
436a251eee6SJoshua Hay  * @macaddr: The MAC address
437a251eee6SJoshua Hay  *
438a251eee6SJoshua Hay  * Returns 0 on success, error value on failure
439a251eee6SJoshua Hay  **/
__idpf_del_mac_filter(struct idpf_vport_config * vport_config,const u8 * macaddr)440a251eee6SJoshua Hay static int __idpf_del_mac_filter(struct idpf_vport_config *vport_config,
441a251eee6SJoshua Hay 				 const u8 *macaddr)
442a251eee6SJoshua Hay {
443a251eee6SJoshua Hay 	struct idpf_mac_filter *f;
444a251eee6SJoshua Hay 
445a251eee6SJoshua Hay 	spin_lock_bh(&vport_config->mac_filter_list_lock);
446a251eee6SJoshua Hay 	f = idpf_find_mac_filter(vport_config, macaddr);
447a251eee6SJoshua Hay 	if (f) {
448a251eee6SJoshua Hay 		list_del(&f->list);
449a251eee6SJoshua Hay 		kfree(f);
450a251eee6SJoshua Hay 	}
451a251eee6SJoshua Hay 	spin_unlock_bh(&vport_config->mac_filter_list_lock);
452a251eee6SJoshua Hay 
453a251eee6SJoshua Hay 	return 0;
454a251eee6SJoshua Hay }
455a251eee6SJoshua Hay 
456a251eee6SJoshua Hay /**
457a251eee6SJoshua Hay  * idpf_del_mac_filter - Delete a MAC filter from the filter list
458a251eee6SJoshua Hay  * @vport: Main vport structure
459a251eee6SJoshua Hay  * @np: Netdev private structure
460a251eee6SJoshua Hay  * @macaddr: The MAC address
461a251eee6SJoshua Hay  * @async: Don't wait for return message
462a251eee6SJoshua Hay  *
463a251eee6SJoshua Hay  * Removes filter from list and if interface is up, tells hardware about the
464a251eee6SJoshua Hay  * removed filter.
465a251eee6SJoshua Hay  **/
idpf_del_mac_filter(struct idpf_vport * vport,struct idpf_netdev_priv * np,const u8 * macaddr,bool async)466a251eee6SJoshua Hay static int idpf_del_mac_filter(struct idpf_vport *vport,
467a251eee6SJoshua Hay 			       struct idpf_netdev_priv *np,
468a251eee6SJoshua Hay 			       const u8 *macaddr, bool async)
469a251eee6SJoshua Hay {
470a251eee6SJoshua Hay 	struct idpf_vport_config *vport_config;
471a251eee6SJoshua Hay 	struct idpf_mac_filter *f;
472a251eee6SJoshua Hay 
473a251eee6SJoshua Hay 	vport_config = np->adapter->vport_config[np->vport_idx];
474a251eee6SJoshua Hay 
475a251eee6SJoshua Hay 	spin_lock_bh(&vport_config->mac_filter_list_lock);
476a251eee6SJoshua Hay 	f = idpf_find_mac_filter(vport_config, macaddr);
477a251eee6SJoshua Hay 	if (f) {
478a251eee6SJoshua Hay 		f->remove = true;
479a251eee6SJoshua Hay 	} else {
480a251eee6SJoshua Hay 		spin_unlock_bh(&vport_config->mac_filter_list_lock);
481a251eee6SJoshua Hay 
482a251eee6SJoshua Hay 		return -EINVAL;
483a251eee6SJoshua Hay 	}
484a251eee6SJoshua Hay 	spin_unlock_bh(&vport_config->mac_filter_list_lock);
485a251eee6SJoshua Hay 
486a251eee6SJoshua Hay 	if (np->state == __IDPF_VPORT_UP) {
487a251eee6SJoshua Hay 		int err;
488a251eee6SJoshua Hay 
489a251eee6SJoshua Hay 		err = idpf_add_del_mac_filters(vport, np, false, async);
490a251eee6SJoshua Hay 		if (err)
491a251eee6SJoshua Hay 			return err;
492a251eee6SJoshua Hay 	}
493a251eee6SJoshua Hay 
494a251eee6SJoshua Hay 	return  __idpf_del_mac_filter(vport_config, macaddr);
495a251eee6SJoshua Hay }
496a251eee6SJoshua Hay 
497a251eee6SJoshua Hay /**
498ce1b75d0SPavan Kumar Linga  * __idpf_add_mac_filter - Add mac filter helper function
499ce1b75d0SPavan Kumar Linga  * @vport_config: Vport config structure
500ce1b75d0SPavan Kumar Linga  * @macaddr: Address to add
501ce1b75d0SPavan Kumar Linga  *
502ce1b75d0SPavan Kumar Linga  * Takes mac_filter_list_lock spinlock to add new filter to list.
503ce1b75d0SPavan Kumar Linga  */
__idpf_add_mac_filter(struct idpf_vport_config * vport_config,const u8 * macaddr)504ce1b75d0SPavan Kumar Linga static int __idpf_add_mac_filter(struct idpf_vport_config *vport_config,
505ce1b75d0SPavan Kumar Linga 				 const u8 *macaddr)
506ce1b75d0SPavan Kumar Linga {
507ce1b75d0SPavan Kumar Linga 	struct idpf_mac_filter *f;
508ce1b75d0SPavan Kumar Linga 
509ce1b75d0SPavan Kumar Linga 	spin_lock_bh(&vport_config->mac_filter_list_lock);
510ce1b75d0SPavan Kumar Linga 
511ce1b75d0SPavan Kumar Linga 	f = idpf_find_mac_filter(vport_config, macaddr);
512ce1b75d0SPavan Kumar Linga 	if (f) {
513ce1b75d0SPavan Kumar Linga 		f->remove = false;
514ce1b75d0SPavan Kumar Linga 		spin_unlock_bh(&vport_config->mac_filter_list_lock);
515ce1b75d0SPavan Kumar Linga 
516ce1b75d0SPavan Kumar Linga 		return 0;
517ce1b75d0SPavan Kumar Linga 	}
518ce1b75d0SPavan Kumar Linga 
519ce1b75d0SPavan Kumar Linga 	f = kzalloc(sizeof(*f), GFP_ATOMIC);
520ce1b75d0SPavan Kumar Linga 	if (!f) {
521ce1b75d0SPavan Kumar Linga 		spin_unlock_bh(&vport_config->mac_filter_list_lock);
522ce1b75d0SPavan Kumar Linga 
523ce1b75d0SPavan Kumar Linga 		return -ENOMEM;
524ce1b75d0SPavan Kumar Linga 	}
525ce1b75d0SPavan Kumar Linga 
526ce1b75d0SPavan Kumar Linga 	ether_addr_copy(f->macaddr, macaddr);
527ce1b75d0SPavan Kumar Linga 	list_add_tail(&f->list, &vport_config->user_config.mac_filter_list);
528ce1b75d0SPavan Kumar Linga 	f->add = true;
529ce1b75d0SPavan Kumar Linga 
530ce1b75d0SPavan Kumar Linga 	spin_unlock_bh(&vport_config->mac_filter_list_lock);
531ce1b75d0SPavan Kumar Linga 
532ce1b75d0SPavan Kumar Linga 	return 0;
533ce1b75d0SPavan Kumar Linga }
534ce1b75d0SPavan Kumar Linga 
535ce1b75d0SPavan Kumar Linga /**
536ce1b75d0SPavan Kumar Linga  * idpf_add_mac_filter - Add a mac filter to the filter list
537ce1b75d0SPavan Kumar Linga  * @vport: Main vport structure
538ce1b75d0SPavan Kumar Linga  * @np: Netdev private structure
539ce1b75d0SPavan Kumar Linga  * @macaddr: The MAC address
540ce1b75d0SPavan Kumar Linga  * @async: Don't wait for return message
541ce1b75d0SPavan Kumar Linga  *
542ce1b75d0SPavan Kumar Linga  * Returns 0 on success or error on failure. If interface is up, we'll also
543ce1b75d0SPavan Kumar Linga  * send the virtchnl message to tell hardware about the filter.
544ce1b75d0SPavan Kumar Linga  **/
idpf_add_mac_filter(struct idpf_vport * vport,struct idpf_netdev_priv * np,const u8 * macaddr,bool async)545ce1b75d0SPavan Kumar Linga static int idpf_add_mac_filter(struct idpf_vport *vport,
546ce1b75d0SPavan Kumar Linga 			       struct idpf_netdev_priv *np,
547ce1b75d0SPavan Kumar Linga 			       const u8 *macaddr, bool async)
548ce1b75d0SPavan Kumar Linga {
549ce1b75d0SPavan Kumar Linga 	struct idpf_vport_config *vport_config;
550ce1b75d0SPavan Kumar Linga 	int err;
551ce1b75d0SPavan Kumar Linga 
552ce1b75d0SPavan Kumar Linga 	vport_config = np->adapter->vport_config[np->vport_idx];
553ce1b75d0SPavan Kumar Linga 	err = __idpf_add_mac_filter(vport_config, macaddr);
554ce1b75d0SPavan Kumar Linga 	if (err)
555ce1b75d0SPavan Kumar Linga 		return err;
556ce1b75d0SPavan Kumar Linga 
557ce1b75d0SPavan Kumar Linga 	if (np->state == __IDPF_VPORT_UP)
558ce1b75d0SPavan Kumar Linga 		err = idpf_add_del_mac_filters(vport, np, true, async);
559ce1b75d0SPavan Kumar Linga 
560ce1b75d0SPavan Kumar Linga 	return err;
561ce1b75d0SPavan Kumar Linga }
562ce1b75d0SPavan Kumar Linga 
563ce1b75d0SPavan Kumar Linga /**
564a251eee6SJoshua Hay  * idpf_del_all_mac_filters - Delete all MAC filters in list
565a251eee6SJoshua Hay  * @vport: main vport struct
566a251eee6SJoshua Hay  *
567a251eee6SJoshua Hay  * Takes mac_filter_list_lock spinlock.  Deletes all filters
568a251eee6SJoshua Hay  */
idpf_del_all_mac_filters(struct idpf_vport * vport)569a251eee6SJoshua Hay static void idpf_del_all_mac_filters(struct idpf_vport *vport)
570a251eee6SJoshua Hay {
571a251eee6SJoshua Hay 	struct idpf_vport_config *vport_config;
572a251eee6SJoshua Hay 	struct idpf_mac_filter *f, *ftmp;
573a251eee6SJoshua Hay 
574a251eee6SJoshua Hay 	vport_config = vport->adapter->vport_config[vport->idx];
575a251eee6SJoshua Hay 	spin_lock_bh(&vport_config->mac_filter_list_lock);
576a251eee6SJoshua Hay 
577a251eee6SJoshua Hay 	list_for_each_entry_safe(f, ftmp, &vport_config->user_config.mac_filter_list,
578a251eee6SJoshua Hay 				 list) {
579a251eee6SJoshua Hay 		list_del(&f->list);
580a251eee6SJoshua Hay 		kfree(f);
581a251eee6SJoshua Hay 	}
582a251eee6SJoshua Hay 
583a251eee6SJoshua Hay 	spin_unlock_bh(&vport_config->mac_filter_list_lock);
584a251eee6SJoshua Hay }
585a251eee6SJoshua Hay 
586a251eee6SJoshua Hay /**
587a251eee6SJoshua Hay  * idpf_restore_mac_filters - Re-add all MAC filters in list
588a251eee6SJoshua Hay  * @vport: main vport struct
589a251eee6SJoshua Hay  *
590a251eee6SJoshua Hay  * Takes mac_filter_list_lock spinlock.  Sets add field to true for filters to
591a251eee6SJoshua Hay  * resync filters back to HW.
592a251eee6SJoshua Hay  */
idpf_restore_mac_filters(struct idpf_vport * vport)593a251eee6SJoshua Hay static void idpf_restore_mac_filters(struct idpf_vport *vport)
594a251eee6SJoshua Hay {
595a251eee6SJoshua Hay 	struct idpf_vport_config *vport_config;
596a251eee6SJoshua Hay 	struct idpf_mac_filter *f;
597a251eee6SJoshua Hay 
598a251eee6SJoshua Hay 	vport_config = vport->adapter->vport_config[vport->idx];
599a251eee6SJoshua Hay 	spin_lock_bh(&vport_config->mac_filter_list_lock);
600a251eee6SJoshua Hay 
601a251eee6SJoshua Hay 	list_for_each_entry(f, &vport_config->user_config.mac_filter_list, list)
602a251eee6SJoshua Hay 		f->add = true;
603a251eee6SJoshua Hay 
604a251eee6SJoshua Hay 	spin_unlock_bh(&vport_config->mac_filter_list_lock);
605a251eee6SJoshua Hay 
606a251eee6SJoshua Hay 	idpf_add_del_mac_filters(vport, netdev_priv(vport->netdev),
607a251eee6SJoshua Hay 				 true, false);
608a251eee6SJoshua Hay }
609a251eee6SJoshua Hay 
610a251eee6SJoshua Hay /**
611a251eee6SJoshua Hay  * idpf_remove_mac_filters - Remove all MAC filters in list
612a251eee6SJoshua Hay  * @vport: main vport struct
613a251eee6SJoshua Hay  *
614a251eee6SJoshua Hay  * Takes mac_filter_list_lock spinlock. Sets remove field to true for filters
615a251eee6SJoshua Hay  * to remove filters in HW.
616a251eee6SJoshua Hay  */
idpf_remove_mac_filters(struct idpf_vport * vport)617a251eee6SJoshua Hay static void idpf_remove_mac_filters(struct idpf_vport *vport)
618a251eee6SJoshua Hay {
619a251eee6SJoshua Hay 	struct idpf_vport_config *vport_config;
620a251eee6SJoshua Hay 	struct idpf_mac_filter *f;
621a251eee6SJoshua Hay 
622a251eee6SJoshua Hay 	vport_config = vport->adapter->vport_config[vport->idx];
623a251eee6SJoshua Hay 	spin_lock_bh(&vport_config->mac_filter_list_lock);
624a251eee6SJoshua Hay 
625a251eee6SJoshua Hay 	list_for_each_entry(f, &vport_config->user_config.mac_filter_list, list)
626a251eee6SJoshua Hay 		f->remove = true;
627a251eee6SJoshua Hay 
628a251eee6SJoshua Hay 	spin_unlock_bh(&vport_config->mac_filter_list_lock);
629a251eee6SJoshua Hay 
630a251eee6SJoshua Hay 	idpf_add_del_mac_filters(vport, netdev_priv(vport->netdev),
631a251eee6SJoshua Hay 				 false, false);
632a251eee6SJoshua Hay }
633a251eee6SJoshua Hay 
634a251eee6SJoshua Hay /**
635ce1b75d0SPavan Kumar Linga  * idpf_deinit_mac_addr - deinitialize mac address for vport
636ce1b75d0SPavan Kumar Linga  * @vport: main vport structure
637ce1b75d0SPavan Kumar Linga  */
idpf_deinit_mac_addr(struct idpf_vport * vport)638ce1b75d0SPavan Kumar Linga static void idpf_deinit_mac_addr(struct idpf_vport *vport)
639ce1b75d0SPavan Kumar Linga {
640ce1b75d0SPavan Kumar Linga 	struct idpf_vport_config *vport_config;
641ce1b75d0SPavan Kumar Linga 	struct idpf_mac_filter *f;
642ce1b75d0SPavan Kumar Linga 
643ce1b75d0SPavan Kumar Linga 	vport_config = vport->adapter->vport_config[vport->idx];
644ce1b75d0SPavan Kumar Linga 
645ce1b75d0SPavan Kumar Linga 	spin_lock_bh(&vport_config->mac_filter_list_lock);
646ce1b75d0SPavan Kumar Linga 
647ce1b75d0SPavan Kumar Linga 	f = idpf_find_mac_filter(vport_config, vport->default_mac_addr);
648ce1b75d0SPavan Kumar Linga 	if (f) {
649ce1b75d0SPavan Kumar Linga 		list_del(&f->list);
650ce1b75d0SPavan Kumar Linga 		kfree(f);
651ce1b75d0SPavan Kumar Linga 	}
652ce1b75d0SPavan Kumar Linga 
653ce1b75d0SPavan Kumar Linga 	spin_unlock_bh(&vport_config->mac_filter_list_lock);
654ce1b75d0SPavan Kumar Linga }
655ce1b75d0SPavan Kumar Linga 
656ce1b75d0SPavan Kumar Linga /**
657ce1b75d0SPavan Kumar Linga  * idpf_init_mac_addr - initialize mac address for vport
658ce1b75d0SPavan Kumar Linga  * @vport: main vport structure
659ce1b75d0SPavan Kumar Linga  * @netdev: pointer to netdev struct associated with this vport
660ce1b75d0SPavan Kumar Linga  */
idpf_init_mac_addr(struct idpf_vport * vport,struct net_device * netdev)661ce1b75d0SPavan Kumar Linga static int idpf_init_mac_addr(struct idpf_vport *vport,
662ce1b75d0SPavan Kumar Linga 			      struct net_device *netdev)
663ce1b75d0SPavan Kumar Linga {
664ce1b75d0SPavan Kumar Linga 	struct idpf_netdev_priv *np = netdev_priv(netdev);
665ce1b75d0SPavan Kumar Linga 	struct idpf_adapter *adapter = vport->adapter;
666ce1b75d0SPavan Kumar Linga 	int err;
667ce1b75d0SPavan Kumar Linga 
668ce1b75d0SPavan Kumar Linga 	if (is_valid_ether_addr(vport->default_mac_addr)) {
669ce1b75d0SPavan Kumar Linga 		eth_hw_addr_set(netdev, vport->default_mac_addr);
670ce1b75d0SPavan Kumar Linga 		ether_addr_copy(netdev->perm_addr, vport->default_mac_addr);
671ce1b75d0SPavan Kumar Linga 
672ce1b75d0SPavan Kumar Linga 		return idpf_add_mac_filter(vport, np, vport->default_mac_addr,
673ce1b75d0SPavan Kumar Linga 					   false);
674ce1b75d0SPavan Kumar Linga 	}
675ce1b75d0SPavan Kumar Linga 
676ce1b75d0SPavan Kumar Linga 	if (!idpf_is_cap_ena(adapter, IDPF_OTHER_CAPS,
677ce1b75d0SPavan Kumar Linga 			     VIRTCHNL2_CAP_MACFILTER)) {
678ce1b75d0SPavan Kumar Linga 		dev_err(&adapter->pdev->dev,
679ce1b75d0SPavan Kumar Linga 			"MAC address is not provided and capability is not set\n");
680ce1b75d0SPavan Kumar Linga 
681ce1b75d0SPavan Kumar Linga 		return -EINVAL;
682ce1b75d0SPavan Kumar Linga 	}
683ce1b75d0SPavan Kumar Linga 
684ce1b75d0SPavan Kumar Linga 	eth_hw_addr_random(netdev);
685ce1b75d0SPavan Kumar Linga 	err = idpf_add_mac_filter(vport, np, netdev->dev_addr, false);
686ce1b75d0SPavan Kumar Linga 	if (err)
687ce1b75d0SPavan Kumar Linga 		return err;
688ce1b75d0SPavan Kumar Linga 
689ce1b75d0SPavan Kumar Linga 	dev_info(&adapter->pdev->dev, "Invalid MAC address %pM, using random %pM\n",
690ce1b75d0SPavan Kumar Linga 		 vport->default_mac_addr, netdev->dev_addr);
691ce1b75d0SPavan Kumar Linga 	ether_addr_copy(vport->default_mac_addr, netdev->dev_addr);
692ce1b75d0SPavan Kumar Linga 
693ce1b75d0SPavan Kumar Linga 	return 0;
694ce1b75d0SPavan Kumar Linga }
695ce1b75d0SPavan Kumar Linga 
696ce1b75d0SPavan Kumar Linga /**
6970fe45467SPavan Kumar Linga  * idpf_cfg_netdev - Allocate, configure and register a netdev
6980fe45467SPavan Kumar Linga  * @vport: main vport structure
6990fe45467SPavan Kumar Linga  *
7000fe45467SPavan Kumar Linga  * Returns 0 on success, negative value on failure.
7010fe45467SPavan Kumar Linga  */
idpf_cfg_netdev(struct idpf_vport * vport)7020fe45467SPavan Kumar Linga static int idpf_cfg_netdev(struct idpf_vport *vport)
7030fe45467SPavan Kumar Linga {
7040fe45467SPavan Kumar Linga 	struct idpf_adapter *adapter = vport->adapter;
7050fe45467SPavan Kumar Linga 	struct idpf_vport_config *vport_config;
7060fe45467SPavan Kumar Linga 	netdev_features_t dflt_features;
7070fe45467SPavan Kumar Linga 	netdev_features_t offloads = 0;
7080fe45467SPavan Kumar Linga 	struct idpf_netdev_priv *np;
7090fe45467SPavan Kumar Linga 	struct net_device *netdev;
7100fe45467SPavan Kumar Linga 	u16 idx = vport->idx;
711ce1b75d0SPavan Kumar Linga 	int err;
7120fe45467SPavan Kumar Linga 
7130fe45467SPavan Kumar Linga 	vport_config = adapter->vport_config[idx];
7140fe45467SPavan Kumar Linga 
7150fe45467SPavan Kumar Linga 	/* It's possible we already have a netdev allocated and registered for
7160fe45467SPavan Kumar Linga 	 * this vport
7170fe45467SPavan Kumar Linga 	 */
7180fe45467SPavan Kumar Linga 	if (test_bit(IDPF_VPORT_REG_NETDEV, vport_config->flags)) {
7190fe45467SPavan Kumar Linga 		netdev = adapter->netdevs[idx];
7200fe45467SPavan Kumar Linga 		np = netdev_priv(netdev);
7210fe45467SPavan Kumar Linga 		np->vport = vport;
722ce1b75d0SPavan Kumar Linga 		np->vport_idx = vport->idx;
723ce1b75d0SPavan Kumar Linga 		np->vport_id = vport->vport_id;
7240fe45467SPavan Kumar Linga 		vport->netdev = netdev;
7250fe45467SPavan Kumar Linga 
726ce1b75d0SPavan Kumar Linga 		return idpf_init_mac_addr(vport, netdev);
7270fe45467SPavan Kumar Linga 	}
7280fe45467SPavan Kumar Linga 
7290fe45467SPavan Kumar Linga 	netdev = alloc_etherdev_mqs(sizeof(struct idpf_netdev_priv),
7300fe45467SPavan Kumar Linga 				    vport_config->max_q.max_txq,
7310fe45467SPavan Kumar Linga 				    vport_config->max_q.max_rxq);
7320fe45467SPavan Kumar Linga 	if (!netdev)
7330fe45467SPavan Kumar Linga 		return -ENOMEM;
7340fe45467SPavan Kumar Linga 
7350fe45467SPavan Kumar Linga 	vport->netdev = netdev;
7360fe45467SPavan Kumar Linga 	np = netdev_priv(netdev);
7370fe45467SPavan Kumar Linga 	np->vport = vport;
738ce1b75d0SPavan Kumar Linga 	np->adapter = adapter;
739ce1b75d0SPavan Kumar Linga 	np->vport_idx = vport->idx;
740ce1b75d0SPavan Kumar Linga 	np->vport_id = vport->vport_id;
741ce1b75d0SPavan Kumar Linga 
742a251eee6SJoshua Hay 	spin_lock_init(&np->stats_lock);
743a251eee6SJoshua Hay 
744ce1b75d0SPavan Kumar Linga 	err = idpf_init_mac_addr(vport, netdev);
745ce1b75d0SPavan Kumar Linga 	if (err) {
746ce1b75d0SPavan Kumar Linga 		free_netdev(vport->netdev);
747ce1b75d0SPavan Kumar Linga 		vport->netdev = NULL;
748ce1b75d0SPavan Kumar Linga 
749ce1b75d0SPavan Kumar Linga 		return err;
750ce1b75d0SPavan Kumar Linga 	}
7510fe45467SPavan Kumar Linga 
7521c325aacSAlan Brady 	/* assign netdev_ops */
75314f662b4SAlexander Lobakin 	netdev->netdev_ops = &idpf_netdev_ops;
7541c325aacSAlan Brady 
7550fe45467SPavan Kumar Linga 	/* setup watchdog timeout value to be 5 second */
7560fe45467SPavan Kumar Linga 	netdev->watchdog_timeo = 5 * HZ;
7570fe45467SPavan Kumar Linga 
758359724faSMichal Schmidt 	netdev->dev_port = idx;
759359724faSMichal Schmidt 
7600fe45467SPavan Kumar Linga 	/* configure default MTU size */
7610fe45467SPavan Kumar Linga 	netdev->min_mtu = ETH_MIN_MTU;
7620fe45467SPavan Kumar Linga 	netdev->max_mtu = vport->max_mtu;
7630fe45467SPavan Kumar Linga 
7640fe45467SPavan Kumar Linga 	dflt_features = NETIF_F_SG	|
7650fe45467SPavan Kumar Linga 			NETIF_F_HIGHDMA;
7660fe45467SPavan Kumar Linga 
7670fe45467SPavan Kumar Linga 	if (idpf_is_cap_ena_all(adapter, IDPF_RSS_CAPS, IDPF_CAP_RSS))
7680fe45467SPavan Kumar Linga 		dflt_features |= NETIF_F_RXHASH;
7690fe45467SPavan Kumar Linga 	if (idpf_is_cap_ena_all(adapter, IDPF_CSUM_CAPS, IDPF_CAP_RX_CSUM_L4V4))
7700fe45467SPavan Kumar Linga 		dflt_features |= NETIF_F_IP_CSUM;
7710fe45467SPavan Kumar Linga 	if (idpf_is_cap_ena_all(adapter, IDPF_CSUM_CAPS, IDPF_CAP_RX_CSUM_L4V6))
7720fe45467SPavan Kumar Linga 		dflt_features |= NETIF_F_IPV6_CSUM;
7730fe45467SPavan Kumar Linga 	if (idpf_is_cap_ena(adapter, IDPF_CSUM_CAPS, IDPF_CAP_RX_CSUM))
7740fe45467SPavan Kumar Linga 		dflt_features |= NETIF_F_RXCSUM;
7750fe45467SPavan Kumar Linga 	if (idpf_is_cap_ena_all(adapter, IDPF_CSUM_CAPS, IDPF_CAP_SCTP_CSUM))
7760fe45467SPavan Kumar Linga 		dflt_features |= NETIF_F_SCTP_CRC;
7770fe45467SPavan Kumar Linga 
7780fe45467SPavan Kumar Linga 	if (idpf_is_cap_ena(adapter, IDPF_SEG_CAPS, VIRTCHNL2_CAP_SEG_IPV4_TCP))
7790fe45467SPavan Kumar Linga 		dflt_features |= NETIF_F_TSO;
7800fe45467SPavan Kumar Linga 	if (idpf_is_cap_ena(adapter, IDPF_SEG_CAPS, VIRTCHNL2_CAP_SEG_IPV6_TCP))
7810fe45467SPavan Kumar Linga 		dflt_features |= NETIF_F_TSO6;
7820fe45467SPavan Kumar Linga 	if (idpf_is_cap_ena_all(adapter, IDPF_SEG_CAPS,
7830fe45467SPavan Kumar Linga 				VIRTCHNL2_CAP_SEG_IPV4_UDP |
7840fe45467SPavan Kumar Linga 				VIRTCHNL2_CAP_SEG_IPV6_UDP))
7850fe45467SPavan Kumar Linga 		dflt_features |= NETIF_F_GSO_UDP_L4;
7860fe45467SPavan Kumar Linga 	if (idpf_is_cap_ena_all(adapter, IDPF_RSC_CAPS, IDPF_CAP_RSC))
7870fe45467SPavan Kumar Linga 		offloads |= NETIF_F_GRO_HW;
7880fe45467SPavan Kumar Linga 	/* advertise to stack only if offloads for encapsulated packets is
7890fe45467SPavan Kumar Linga 	 * supported
7900fe45467SPavan Kumar Linga 	 */
7910fe45467SPavan Kumar Linga 	if (idpf_is_cap_ena(vport->adapter, IDPF_SEG_CAPS,
7920fe45467SPavan Kumar Linga 			    VIRTCHNL2_CAP_SEG_TX_SINGLE_TUNNEL)) {
7930fe45467SPavan Kumar Linga 		offloads |= NETIF_F_GSO_UDP_TUNNEL	|
7940fe45467SPavan Kumar Linga 			    NETIF_F_GSO_GRE		|
7950fe45467SPavan Kumar Linga 			    NETIF_F_GSO_GRE_CSUM	|
7960fe45467SPavan Kumar Linga 			    NETIF_F_GSO_PARTIAL		|
7970fe45467SPavan Kumar Linga 			    NETIF_F_GSO_UDP_TUNNEL_CSUM	|
7980fe45467SPavan Kumar Linga 			    NETIF_F_GSO_IPXIP4		|
7990fe45467SPavan Kumar Linga 			    NETIF_F_GSO_IPXIP6		|
8000fe45467SPavan Kumar Linga 			    0;
8010fe45467SPavan Kumar Linga 
8020fe45467SPavan Kumar Linga 		if (!idpf_is_cap_ena_all(vport->adapter, IDPF_CSUM_CAPS,
8030fe45467SPavan Kumar Linga 					 IDPF_CAP_TUNNEL_TX_CSUM))
8040fe45467SPavan Kumar Linga 			netdev->gso_partial_features |=
8050fe45467SPavan Kumar Linga 				NETIF_F_GSO_UDP_TUNNEL_CSUM;
8060fe45467SPavan Kumar Linga 
8070fe45467SPavan Kumar Linga 		netdev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM;
8080fe45467SPavan Kumar Linga 		offloads |= NETIF_F_TSO_MANGLEID;
8090fe45467SPavan Kumar Linga 	}
8100fe45467SPavan Kumar Linga 	if (idpf_is_cap_ena(adapter, IDPF_OTHER_CAPS, VIRTCHNL2_CAP_LOOPBACK))
8110fe45467SPavan Kumar Linga 		offloads |= NETIF_F_LOOPBACK;
8120fe45467SPavan Kumar Linga 
8130fe45467SPavan Kumar Linga 	netdev->features |= dflt_features;
8140fe45467SPavan Kumar Linga 	netdev->hw_features |= dflt_features | offloads;
8150fe45467SPavan Kumar Linga 	netdev->hw_enc_features |= dflt_features | offloads;
81602cbfba1SAlan Brady 	idpf_set_ethtool_ops(netdev);
8170fe45467SPavan Kumar Linga 	SET_NETDEV_DEV(netdev, &adapter->pdev->dev);
8180fe45467SPavan Kumar Linga 
8190fe45467SPavan Kumar Linga 	/* carrier off on init to avoid Tx hangs */
8200fe45467SPavan Kumar Linga 	netif_carrier_off(netdev);
8210fe45467SPavan Kumar Linga 
8220fe45467SPavan Kumar Linga 	/* make sure transmit queues start off as stopped */
8230fe45467SPavan Kumar Linga 	netif_tx_stop_all_queues(netdev);
8240fe45467SPavan Kumar Linga 
8250fe45467SPavan Kumar Linga 	/* The vport can be arbitrarily released so we need to also track
8260fe45467SPavan Kumar Linga 	 * netdevs in the adapter struct
8270fe45467SPavan Kumar Linga 	 */
8280fe45467SPavan Kumar Linga 	adapter->netdevs[idx] = netdev;
8290fe45467SPavan Kumar Linga 
8300fe45467SPavan Kumar Linga 	return 0;
8310fe45467SPavan Kumar Linga }
8320fe45467SPavan Kumar Linga 
8330fe45467SPavan Kumar Linga /**
8340fe45467SPavan Kumar Linga  * idpf_get_free_slot - get the next non-NULL location index in array
8350fe45467SPavan Kumar Linga  * @adapter: adapter in which to look for a free vport slot
8360fe45467SPavan Kumar Linga  */
idpf_get_free_slot(struct idpf_adapter * adapter)8370fe45467SPavan Kumar Linga static int idpf_get_free_slot(struct idpf_adapter *adapter)
8380fe45467SPavan Kumar Linga {
8390fe45467SPavan Kumar Linga 	unsigned int i;
8400fe45467SPavan Kumar Linga 
8410fe45467SPavan Kumar Linga 	for (i = 0; i < adapter->max_vports; i++) {
8420fe45467SPavan Kumar Linga 		if (!adapter->vports[i])
8430fe45467SPavan Kumar Linga 			return i;
8440fe45467SPavan Kumar Linga 	}
8450fe45467SPavan Kumar Linga 
8460fe45467SPavan Kumar Linga 	return IDPF_NO_FREE_SLOT;
8470fe45467SPavan Kumar Linga }
8480fe45467SPavan Kumar Linga 
8490fe45467SPavan Kumar Linga /**
850a251eee6SJoshua Hay  * idpf_remove_features - Turn off feature configs
851a251eee6SJoshua Hay  * @vport: virtual port structure
852a251eee6SJoshua Hay  */
idpf_remove_features(struct idpf_vport * vport)853a251eee6SJoshua Hay static void idpf_remove_features(struct idpf_vport *vport)
854a251eee6SJoshua Hay {
855a251eee6SJoshua Hay 	struct idpf_adapter *adapter = vport->adapter;
856a251eee6SJoshua Hay 
857a251eee6SJoshua Hay 	if (idpf_is_cap_ena(adapter, IDPF_OTHER_CAPS, VIRTCHNL2_CAP_MACFILTER))
858a251eee6SJoshua Hay 		idpf_remove_mac_filters(vport);
859a251eee6SJoshua Hay }
860a251eee6SJoshua Hay 
861a251eee6SJoshua Hay /**
8621c325aacSAlan Brady  * idpf_vport_stop - Disable a vport
8631c325aacSAlan Brady  * @vport: vport to disable
8641c325aacSAlan Brady  */
idpf_vport_stop(struct idpf_vport * vport)8651c325aacSAlan Brady static void idpf_vport_stop(struct idpf_vport *vport)
8661c325aacSAlan Brady {
8671c325aacSAlan Brady 	struct idpf_netdev_priv *np = netdev_priv(vport->netdev);
8681c325aacSAlan Brady 
8691c325aacSAlan Brady 	if (np->state <= __IDPF_VPORT_DOWN)
8701c325aacSAlan Brady 		return;
8711c325aacSAlan Brady 
8721c325aacSAlan Brady 	netif_carrier_off(vport->netdev);
873d4d55871SPavan Kumar Linga 	netif_tx_disable(vport->netdev);
8741c325aacSAlan Brady 
875d4d55871SPavan Kumar Linga 	idpf_send_disable_vport_msg(vport);
876d4d55871SPavan Kumar Linga 	idpf_send_disable_queues_msg(vport);
877d4d55871SPavan Kumar Linga 	idpf_send_map_unmap_queue_vector_msg(vport, false);
878a251eee6SJoshua Hay 	/* Normally we ask for queues in create_vport, but if the number of
879a251eee6SJoshua Hay 	 * initially requested queues have changed, for example via ethtool
880a251eee6SJoshua Hay 	 * set channels, we do delete queues and then add the queues back
881a251eee6SJoshua Hay 	 * instead of deleting and reallocating the vport.
88202cbfba1SAlan Brady 	 */
88302cbfba1SAlan Brady 	if (test_and_clear_bit(IDPF_VPORT_DEL_QUEUES, vport->flags))
88402cbfba1SAlan Brady 		idpf_send_delete_queues_msg(vport);
885d4d55871SPavan Kumar Linga 
886a251eee6SJoshua Hay 	idpf_remove_features(vport);
887a251eee6SJoshua Hay 
888d4d55871SPavan Kumar Linga 	vport->link_up = false;
889d4d55871SPavan Kumar Linga 	idpf_vport_intr_deinit(vport);
8901c325aacSAlan Brady 	idpf_vport_queues_rel(vport);
891290f1c03SAlexander Lobakin 	idpf_vport_intr_rel(vport);
8921c325aacSAlan Brady 	np->state = __IDPF_VPORT_DOWN;
8931c325aacSAlan Brady }
8941c325aacSAlan Brady 
8951c325aacSAlan Brady /**
8961c325aacSAlan Brady  * idpf_stop - Disables a network interface
8971c325aacSAlan Brady  * @netdev: network interface device structure
8981c325aacSAlan Brady  *
8991c325aacSAlan Brady  * The stop entry point is called when an interface is de-activated by the OS,
9001c325aacSAlan Brady  * and the netdevice enters the DOWN state.  The hardware is still under the
9011c325aacSAlan Brady  * driver's control, but the netdev interface is disabled.
9021c325aacSAlan Brady  *
9031c325aacSAlan Brady  * Returns success only - not allowed to fail
9041c325aacSAlan Brady  */
idpf_stop(struct net_device * netdev)9051c325aacSAlan Brady static int idpf_stop(struct net_device *netdev)
9061c325aacSAlan Brady {
9071c325aacSAlan Brady 	struct idpf_netdev_priv *np = netdev_priv(netdev);
9081c325aacSAlan Brady 	struct idpf_vport *vport;
9091c325aacSAlan Brady 
9101c325aacSAlan Brady 	if (test_bit(IDPF_REMOVE_IN_PROG, np->adapter->flags))
9111c325aacSAlan Brady 		return 0;
9121c325aacSAlan Brady 
9131c325aacSAlan Brady 	idpf_vport_ctrl_lock(netdev);
9141c325aacSAlan Brady 	vport = idpf_netdev_to_vport(netdev);
9151c325aacSAlan Brady 
9161c325aacSAlan Brady 	idpf_vport_stop(vport);
9171c325aacSAlan Brady 
9181c325aacSAlan Brady 	idpf_vport_ctrl_unlock(netdev);
9191c325aacSAlan Brady 
9201c325aacSAlan Brady 	return 0;
9211c325aacSAlan Brady }
9221c325aacSAlan Brady 
9231c325aacSAlan Brady /**
9240fe45467SPavan Kumar Linga  * idpf_decfg_netdev - Unregister the netdev
9250fe45467SPavan Kumar Linga  * @vport: vport for which netdev to be unregistered
9260fe45467SPavan Kumar Linga  */
idpf_decfg_netdev(struct idpf_vport * vport)9270fe45467SPavan Kumar Linga static void idpf_decfg_netdev(struct idpf_vport *vport)
9280fe45467SPavan Kumar Linga {
9290fe45467SPavan Kumar Linga 	struct idpf_adapter *adapter = vport->adapter;
9300fe45467SPavan Kumar Linga 
9311b1b2620SAlexander Lobakin 	kfree(vport->rx_ptype_lkup);
9321b1b2620SAlexander Lobakin 	vport->rx_ptype_lkup = NULL;
9331b1b2620SAlexander Lobakin 
9340fe45467SPavan Kumar Linga 	unregister_netdev(vport->netdev);
9350fe45467SPavan Kumar Linga 	free_netdev(vport->netdev);
9360fe45467SPavan Kumar Linga 	vport->netdev = NULL;
9370fe45467SPavan Kumar Linga 
9380fe45467SPavan Kumar Linga 	adapter->netdevs[vport->idx] = NULL;
9390fe45467SPavan Kumar Linga }
9400fe45467SPavan Kumar Linga 
9410fe45467SPavan Kumar Linga /**
9420fe45467SPavan Kumar Linga  * idpf_vport_rel - Delete a vport and free its resources
9430fe45467SPavan Kumar Linga  * @vport: the vport being removed
9440fe45467SPavan Kumar Linga  */
idpf_vport_rel(struct idpf_vport * vport)9450fe45467SPavan Kumar Linga static void idpf_vport_rel(struct idpf_vport *vport)
9460fe45467SPavan Kumar Linga {
9470fe45467SPavan Kumar Linga 	struct idpf_adapter *adapter = vport->adapter;
9480fe45467SPavan Kumar Linga 	struct idpf_vport_config *vport_config;
949d4d55871SPavan Kumar Linga 	struct idpf_vector_info vec_info;
95095af467dSAlan Brady 	struct idpf_rss_data *rss_data;
9510fe45467SPavan Kumar Linga 	struct idpf_vport_max_q max_q;
9520fe45467SPavan Kumar Linga 	u16 idx = vport->idx;
9530fe45467SPavan Kumar Linga 
9540fe45467SPavan Kumar Linga 	vport_config = adapter->vport_config[vport->idx];
95595af467dSAlan Brady 	idpf_deinit_rss(vport);
95695af467dSAlan Brady 	rss_data = &vport_config->user_config.rss_data;
95795af467dSAlan Brady 	kfree(rss_data->rss_key);
95895af467dSAlan Brady 	rss_data->rss_key = NULL;
9590fe45467SPavan Kumar Linga 
9600fe45467SPavan Kumar Linga 	idpf_send_destroy_vport_msg(vport);
9610fe45467SPavan Kumar Linga 
9620fe45467SPavan Kumar Linga 	/* Release all max queues allocated to the adapter's pool */
9630fe45467SPavan Kumar Linga 	max_q.max_rxq = vport_config->max_q.max_rxq;
9640fe45467SPavan Kumar Linga 	max_q.max_txq = vport_config->max_q.max_txq;
9650fe45467SPavan Kumar Linga 	max_q.max_bufq = vport_config->max_q.max_bufq;
9660fe45467SPavan Kumar Linga 	max_q.max_complq = vport_config->max_q.max_complq;
9670fe45467SPavan Kumar Linga 	idpf_vport_dealloc_max_qs(adapter, &max_q);
9680fe45467SPavan Kumar Linga 
969d4d55871SPavan Kumar Linga 	/* Release all the allocated vectors on the stack */
970d4d55871SPavan Kumar Linga 	vec_info.num_req_vecs = 0;
971d4d55871SPavan Kumar Linga 	vec_info.num_curr_vecs = vport->num_q_vectors;
972d4d55871SPavan Kumar Linga 	vec_info.default_vport = vport->default_vport;
973d4d55871SPavan Kumar Linga 
974d4d55871SPavan Kumar Linga 	idpf_req_rel_vector_indexes(adapter, vport->q_vector_idxs, &vec_info);
975d4d55871SPavan Kumar Linga 
976d4d55871SPavan Kumar Linga 	kfree(vport->q_vector_idxs);
977d4d55871SPavan Kumar Linga 	vport->q_vector_idxs = NULL;
978d4d55871SPavan Kumar Linga 
9790fe45467SPavan Kumar Linga 	kfree(adapter->vport_params_recvd[idx]);
9800fe45467SPavan Kumar Linga 	adapter->vport_params_recvd[idx] = NULL;
9810fe45467SPavan Kumar Linga 	kfree(adapter->vport_params_reqd[idx]);
9820fe45467SPavan Kumar Linga 	adapter->vport_params_reqd[idx] = NULL;
983a251eee6SJoshua Hay 	if (adapter->vport_config[idx]) {
984a251eee6SJoshua Hay 		kfree(adapter->vport_config[idx]->req_qs_chunks);
985a251eee6SJoshua Hay 		adapter->vport_config[idx]->req_qs_chunks = NULL;
986a251eee6SJoshua Hay 	}
9870fe45467SPavan Kumar Linga 	kfree(vport);
9880fe45467SPavan Kumar Linga 	adapter->num_alloc_vports--;
9890fe45467SPavan Kumar Linga }
9900fe45467SPavan Kumar Linga 
9910fe45467SPavan Kumar Linga /**
9920fe45467SPavan Kumar Linga  * idpf_vport_dealloc - cleanup and release a given vport
9930fe45467SPavan Kumar Linga  * @vport: pointer to idpf vport structure
9940fe45467SPavan Kumar Linga  *
9950fe45467SPavan Kumar Linga  * returns nothing
9960fe45467SPavan Kumar Linga  */
idpf_vport_dealloc(struct idpf_vport * vport)9970fe45467SPavan Kumar Linga static void idpf_vport_dealloc(struct idpf_vport *vport)
9980fe45467SPavan Kumar Linga {
9990fe45467SPavan Kumar Linga 	struct idpf_adapter *adapter = vport->adapter;
10000fe45467SPavan Kumar Linga 	unsigned int i = vport->idx;
10010fe45467SPavan Kumar Linga 
1002ce1b75d0SPavan Kumar Linga 	idpf_deinit_mac_addr(vport);
1003d4d55871SPavan Kumar Linga 	idpf_vport_stop(vport);
1004ce1b75d0SPavan Kumar Linga 
10050fe45467SPavan Kumar Linga 	if (!test_bit(IDPF_HR_RESET_IN_PROG, adapter->flags))
10060fe45467SPavan Kumar Linga 		idpf_decfg_netdev(vport);
1007a251eee6SJoshua Hay 	if (test_bit(IDPF_REMOVE_IN_PROG, adapter->flags))
1008a251eee6SJoshua Hay 		idpf_del_all_mac_filters(vport);
10090fe45467SPavan Kumar Linga 
10100fe45467SPavan Kumar Linga 	if (adapter->netdevs[i]) {
10110fe45467SPavan Kumar Linga 		struct idpf_netdev_priv *np = netdev_priv(adapter->netdevs[i]);
10120fe45467SPavan Kumar Linga 
10130fe45467SPavan Kumar Linga 		np->vport = NULL;
10140fe45467SPavan Kumar Linga 	}
10150fe45467SPavan Kumar Linga 
10160fe45467SPavan Kumar Linga 	idpf_vport_rel(vport);
10170fe45467SPavan Kumar Linga 
10180fe45467SPavan Kumar Linga 	adapter->vports[i] = NULL;
10190fe45467SPavan Kumar Linga 	adapter->next_vport = idpf_get_free_slot(adapter);
10200fe45467SPavan Kumar Linga }
10210fe45467SPavan Kumar Linga 
10220fe45467SPavan Kumar Linga /**
10239b1aa3efSMichal Kubiak  * idpf_is_hsplit_supported - check whether the header split is supported
10249b1aa3efSMichal Kubiak  * @vport: virtual port to check the capability for
10259b1aa3efSMichal Kubiak  *
10269b1aa3efSMichal Kubiak  * Return: true if it's supported by the HW/FW, false if not.
10279b1aa3efSMichal Kubiak  */
idpf_is_hsplit_supported(const struct idpf_vport * vport)10289b1aa3efSMichal Kubiak static bool idpf_is_hsplit_supported(const struct idpf_vport *vport)
10299b1aa3efSMichal Kubiak {
10309b1aa3efSMichal Kubiak 	return idpf_is_queue_model_split(vport->rxq_model) &&
10319b1aa3efSMichal Kubiak 	       idpf_is_cap_ena_all(vport->adapter, IDPF_HSPLIT_CAPS,
10329b1aa3efSMichal Kubiak 				   IDPF_CAP_HSPLIT);
10339b1aa3efSMichal Kubiak }
10349b1aa3efSMichal Kubiak 
10359b1aa3efSMichal Kubiak /**
10369b1aa3efSMichal Kubiak  * idpf_vport_get_hsplit - get the current header split feature state
10379b1aa3efSMichal Kubiak  * @vport: virtual port to query the state for
10389b1aa3efSMichal Kubiak  *
10399b1aa3efSMichal Kubiak  * Return: ``ETHTOOL_TCP_DATA_SPLIT_UNKNOWN`` if not supported,
10409b1aa3efSMichal Kubiak  *         ``ETHTOOL_TCP_DATA_SPLIT_DISABLED`` if disabled,
10419b1aa3efSMichal Kubiak  *         ``ETHTOOL_TCP_DATA_SPLIT_ENABLED`` if active.
10429b1aa3efSMichal Kubiak  */
idpf_vport_get_hsplit(const struct idpf_vport * vport)10439b1aa3efSMichal Kubiak u8 idpf_vport_get_hsplit(const struct idpf_vport *vport)
10449b1aa3efSMichal Kubiak {
10459b1aa3efSMichal Kubiak 	const struct idpf_vport_user_config_data *config;
10469b1aa3efSMichal Kubiak 
10479b1aa3efSMichal Kubiak 	if (!idpf_is_hsplit_supported(vport))
10489b1aa3efSMichal Kubiak 		return ETHTOOL_TCP_DATA_SPLIT_UNKNOWN;
10499b1aa3efSMichal Kubiak 
10509b1aa3efSMichal Kubiak 	config = &vport->adapter->vport_config[vport->idx]->user_config;
10519b1aa3efSMichal Kubiak 
10529b1aa3efSMichal Kubiak 	return test_bit(__IDPF_USER_FLAG_HSPLIT, config->user_flags) ?
10539b1aa3efSMichal Kubiak 	       ETHTOOL_TCP_DATA_SPLIT_ENABLED :
10549b1aa3efSMichal Kubiak 	       ETHTOOL_TCP_DATA_SPLIT_DISABLED;
10559b1aa3efSMichal Kubiak }
10569b1aa3efSMichal Kubiak 
10579b1aa3efSMichal Kubiak /**
10589b1aa3efSMichal Kubiak  * idpf_vport_set_hsplit - enable or disable header split on a given vport
10599b1aa3efSMichal Kubiak  * @vport: virtual port to configure
10609b1aa3efSMichal Kubiak  * @val: Ethtool flag controlling the header split state
10619b1aa3efSMichal Kubiak  *
10629b1aa3efSMichal Kubiak  * Return: true on success, false if not supported by the HW.
10639b1aa3efSMichal Kubiak  */
idpf_vport_set_hsplit(const struct idpf_vport * vport,u8 val)10649b1aa3efSMichal Kubiak bool idpf_vport_set_hsplit(const struct idpf_vport *vport, u8 val)
10659b1aa3efSMichal Kubiak {
10669b1aa3efSMichal Kubiak 	struct idpf_vport_user_config_data *config;
10679b1aa3efSMichal Kubiak 
10689b1aa3efSMichal Kubiak 	if (!idpf_is_hsplit_supported(vport))
10699b1aa3efSMichal Kubiak 		return val == ETHTOOL_TCP_DATA_SPLIT_UNKNOWN;
10709b1aa3efSMichal Kubiak 
10719b1aa3efSMichal Kubiak 	config = &vport->adapter->vport_config[vport->idx]->user_config;
10729b1aa3efSMichal Kubiak 
10739b1aa3efSMichal Kubiak 	switch (val) {
10749b1aa3efSMichal Kubiak 	case ETHTOOL_TCP_DATA_SPLIT_UNKNOWN:
10759b1aa3efSMichal Kubiak 		/* Default is to enable */
10769b1aa3efSMichal Kubiak 	case ETHTOOL_TCP_DATA_SPLIT_ENABLED:
10779b1aa3efSMichal Kubiak 		__set_bit(__IDPF_USER_FLAG_HSPLIT, config->user_flags);
10789b1aa3efSMichal Kubiak 		return true;
10799b1aa3efSMichal Kubiak 	case ETHTOOL_TCP_DATA_SPLIT_DISABLED:
10809b1aa3efSMichal Kubiak 		__clear_bit(__IDPF_USER_FLAG_HSPLIT, config->user_flags);
10819b1aa3efSMichal Kubiak 		return true;
10829b1aa3efSMichal Kubiak 	default:
10839b1aa3efSMichal Kubiak 		return false;
10849b1aa3efSMichal Kubiak 	}
10859b1aa3efSMichal Kubiak }
10869b1aa3efSMichal Kubiak 
10879b1aa3efSMichal Kubiak /**
10880fe45467SPavan Kumar Linga  * idpf_vport_alloc - Allocates the next available struct vport in the adapter
10890fe45467SPavan Kumar Linga  * @adapter: board private structure
10900fe45467SPavan Kumar Linga  * @max_q: vport max queue info
10910fe45467SPavan Kumar Linga  *
10920fe45467SPavan Kumar Linga  * returns a pointer to a vport on success, NULL on failure.
10930fe45467SPavan Kumar Linga  */
idpf_vport_alloc(struct idpf_adapter * adapter,struct idpf_vport_max_q * max_q)10940fe45467SPavan Kumar Linga static struct idpf_vport *idpf_vport_alloc(struct idpf_adapter *adapter,
10950fe45467SPavan Kumar Linga 					   struct idpf_vport_max_q *max_q)
10960fe45467SPavan Kumar Linga {
109795af467dSAlan Brady 	struct idpf_rss_data *rss_data;
10980fe45467SPavan Kumar Linga 	u16 idx = adapter->next_vport;
10990fe45467SPavan Kumar Linga 	struct idpf_vport *vport;
1100d4d55871SPavan Kumar Linga 	u16 num_max_q;
11010fe45467SPavan Kumar Linga 
11020fe45467SPavan Kumar Linga 	if (idx == IDPF_NO_FREE_SLOT)
11030fe45467SPavan Kumar Linga 		return NULL;
11040fe45467SPavan Kumar Linga 
11050fe45467SPavan Kumar Linga 	vport = kzalloc(sizeof(*vport), GFP_KERNEL);
11060fe45467SPavan Kumar Linga 	if (!vport)
11070fe45467SPavan Kumar Linga 		return vport;
11080fe45467SPavan Kumar Linga 
11090fe45467SPavan Kumar Linga 	if (!adapter->vport_config[idx]) {
11100fe45467SPavan Kumar Linga 		struct idpf_vport_config *vport_config;
11110fe45467SPavan Kumar Linga 
11120fe45467SPavan Kumar Linga 		vport_config = kzalloc(sizeof(*vport_config), GFP_KERNEL);
11130fe45467SPavan Kumar Linga 		if (!vport_config) {
11140fe45467SPavan Kumar Linga 			kfree(vport);
11150fe45467SPavan Kumar Linga 
11160fe45467SPavan Kumar Linga 			return NULL;
11170fe45467SPavan Kumar Linga 		}
11180fe45467SPavan Kumar Linga 
11190fe45467SPavan Kumar Linga 		adapter->vport_config[idx] = vport_config;
11200fe45467SPavan Kumar Linga 	}
11210fe45467SPavan Kumar Linga 
11220fe45467SPavan Kumar Linga 	vport->idx = idx;
11230fe45467SPavan Kumar Linga 	vport->adapter = adapter;
1124c2d548caSJoshua Hay 	vport->compln_clean_budget = IDPF_TX_COMPLQ_CLEAN_BUDGET;
11250fe45467SPavan Kumar Linga 	vport->default_vport = adapter->num_alloc_vports <
11260fe45467SPavan Kumar Linga 			       idpf_get_default_vports(adapter);
11270fe45467SPavan Kumar Linga 
1128d4d55871SPavan Kumar Linga 	num_max_q = max(max_q->max_txq, max_q->max_rxq);
1129d4d55871SPavan Kumar Linga 	vport->q_vector_idxs = kcalloc(num_max_q, sizeof(u16), GFP_KERNEL);
1130d4d55871SPavan Kumar Linga 	if (!vport->q_vector_idxs) {
1131d4d55871SPavan Kumar Linga 		kfree(vport);
1132d4d55871SPavan Kumar Linga 
1133d4d55871SPavan Kumar Linga 		return NULL;
1134d4d55871SPavan Kumar Linga 	}
11350fe45467SPavan Kumar Linga 	idpf_vport_init(vport, max_q);
11360fe45467SPavan Kumar Linga 
113795af467dSAlan Brady 	/* This alloc is done separate from the LUT because it's not strictly
113895af467dSAlan Brady 	 * dependent on how many queues we have. If we change number of queues
113995af467dSAlan Brady 	 * and soft reset we'll need a new LUT but the key can remain the same
114095af467dSAlan Brady 	 * for as long as the vport exists.
114195af467dSAlan Brady 	 */
114295af467dSAlan Brady 	rss_data = &adapter->vport_config[idx]->user_config.rss_data;
114395af467dSAlan Brady 	rss_data->rss_key = kzalloc(rss_data->rss_key_size, GFP_KERNEL);
114495af467dSAlan Brady 	if (!rss_data->rss_key) {
114595af467dSAlan Brady 		kfree(vport);
114695af467dSAlan Brady 
114795af467dSAlan Brady 		return NULL;
114895af467dSAlan Brady 	}
114995af467dSAlan Brady 	/* Initialize default rss key */
115095af467dSAlan Brady 	netdev_rss_key_fill((void *)rss_data->rss_key, rss_data->rss_key_size);
115195af467dSAlan Brady 
11520fe45467SPavan Kumar Linga 	/* fill vport slot in the adapter struct */
11530fe45467SPavan Kumar Linga 	adapter->vports[idx] = vport;
11540fe45467SPavan Kumar Linga 	adapter->vport_ids[idx] = idpf_get_vport_id(vport);
11550fe45467SPavan Kumar Linga 
11560fe45467SPavan Kumar Linga 	adapter->num_alloc_vports++;
11570fe45467SPavan Kumar Linga 	/* prepare adapter->next_vport for next use */
11580fe45467SPavan Kumar Linga 	adapter->next_vport = idpf_get_free_slot(adapter);
11590fe45467SPavan Kumar Linga 
11600fe45467SPavan Kumar Linga 	return vport;
11610fe45467SPavan Kumar Linga }
11620fe45467SPavan Kumar Linga 
11630fe45467SPavan Kumar Linga /**
1164a251eee6SJoshua Hay  * idpf_get_stats64 - get statistics for network device structure
1165a251eee6SJoshua Hay  * @netdev: network interface device structure
1166a251eee6SJoshua Hay  * @stats: main device statistics structure
1167a251eee6SJoshua Hay  */
idpf_get_stats64(struct net_device * netdev,struct rtnl_link_stats64 * stats)1168a251eee6SJoshua Hay static void idpf_get_stats64(struct net_device *netdev,
1169a251eee6SJoshua Hay 			     struct rtnl_link_stats64 *stats)
1170a251eee6SJoshua Hay {
1171a251eee6SJoshua Hay 	struct idpf_netdev_priv *np = netdev_priv(netdev);
1172a251eee6SJoshua Hay 
1173a251eee6SJoshua Hay 	spin_lock_bh(&np->stats_lock);
1174a251eee6SJoshua Hay 	*stats = np->netstats;
1175a251eee6SJoshua Hay 	spin_unlock_bh(&np->stats_lock);
1176a251eee6SJoshua Hay }
1177a251eee6SJoshua Hay 
1178a251eee6SJoshua Hay /**
1179a251eee6SJoshua Hay  * idpf_statistics_task - Delayed task to get statistics over mailbox
1180a251eee6SJoshua Hay  * @work: work_struct handle to our data
1181a251eee6SJoshua Hay  */
idpf_statistics_task(struct work_struct * work)1182a251eee6SJoshua Hay void idpf_statistics_task(struct work_struct *work)
1183a251eee6SJoshua Hay {
1184a251eee6SJoshua Hay 	struct idpf_adapter *adapter;
1185a251eee6SJoshua Hay 	int i;
1186a251eee6SJoshua Hay 
1187a251eee6SJoshua Hay 	adapter = container_of(work, struct idpf_adapter, stats_task.work);
1188a251eee6SJoshua Hay 
1189a251eee6SJoshua Hay 	for (i = 0; i < adapter->max_vports; i++) {
1190a251eee6SJoshua Hay 		struct idpf_vport *vport = adapter->vports[i];
1191a251eee6SJoshua Hay 
1192a251eee6SJoshua Hay 		if (vport && !test_bit(IDPF_HR_RESET_IN_PROG, adapter->flags))
1193a251eee6SJoshua Hay 			idpf_send_get_stats_msg(vport);
1194a251eee6SJoshua Hay 	}
1195a251eee6SJoshua Hay 
1196a251eee6SJoshua Hay 	queue_delayed_work(adapter->stats_wq, &adapter->stats_task,
1197a251eee6SJoshua Hay 			   msecs_to_jiffies(10000));
1198a251eee6SJoshua Hay }
1199a251eee6SJoshua Hay 
1200a251eee6SJoshua Hay /**
12014930fbf4SPavan Kumar Linga  * idpf_mbx_task - Delayed task to handle mailbox responses
12024930fbf4SPavan Kumar Linga  * @work: work_struct handle
12034930fbf4SPavan Kumar Linga  */
idpf_mbx_task(struct work_struct * work)12044930fbf4SPavan Kumar Linga void idpf_mbx_task(struct work_struct *work)
12054930fbf4SPavan Kumar Linga {
12064930fbf4SPavan Kumar Linga 	struct idpf_adapter *adapter;
12074930fbf4SPavan Kumar Linga 
12084930fbf4SPavan Kumar Linga 	adapter = container_of(work, struct idpf_adapter, mbx_task.work);
12094930fbf4SPavan Kumar Linga 
12104930fbf4SPavan Kumar Linga 	if (test_bit(IDPF_MB_INTR_MODE, adapter->flags))
12114930fbf4SPavan Kumar Linga 		idpf_mb_irq_enable(adapter);
12124930fbf4SPavan Kumar Linga 	else
12134930fbf4SPavan Kumar Linga 		queue_delayed_work(adapter->mbx_wq, &adapter->mbx_task,
12144930fbf4SPavan Kumar Linga 				   msecs_to_jiffies(300));
12154930fbf4SPavan Kumar Linga 
1216e54232daSAlan Brady 	idpf_recv_mb_msg(adapter);
12174930fbf4SPavan Kumar Linga }
12184930fbf4SPavan Kumar Linga 
12194930fbf4SPavan Kumar Linga /**
12204930fbf4SPavan Kumar Linga  * idpf_service_task - Delayed task for handling mailbox responses
12214930fbf4SPavan Kumar Linga  * @work: work_struct handle to our data
12224930fbf4SPavan Kumar Linga  *
12234930fbf4SPavan Kumar Linga  */
idpf_service_task(struct work_struct * work)12244930fbf4SPavan Kumar Linga void idpf_service_task(struct work_struct *work)
12254930fbf4SPavan Kumar Linga {
12264930fbf4SPavan Kumar Linga 	struct idpf_adapter *adapter;
12274930fbf4SPavan Kumar Linga 
12284930fbf4SPavan Kumar Linga 	adapter = container_of(work, struct idpf_adapter, serv_task.work);
12294930fbf4SPavan Kumar Linga 
12304930fbf4SPavan Kumar Linga 	if (idpf_is_reset_detected(adapter) &&
12314930fbf4SPavan Kumar Linga 	    !idpf_is_reset_in_prog(adapter) &&
12324930fbf4SPavan Kumar Linga 	    !test_bit(IDPF_REMOVE_IN_PROG, adapter->flags)) {
12334930fbf4SPavan Kumar Linga 		dev_info(&adapter->pdev->dev, "HW reset detected\n");
12344930fbf4SPavan Kumar Linga 		set_bit(IDPF_HR_FUNC_RESET, adapter->flags);
12354930fbf4SPavan Kumar Linga 		queue_delayed_work(adapter->vc_event_wq,
12364930fbf4SPavan Kumar Linga 				   &adapter->vc_event_task,
12374930fbf4SPavan Kumar Linga 				   msecs_to_jiffies(10));
12384930fbf4SPavan Kumar Linga 	}
12394930fbf4SPavan Kumar Linga 
12404930fbf4SPavan Kumar Linga 	queue_delayed_work(adapter->serv_wq, &adapter->serv_task,
12414930fbf4SPavan Kumar Linga 			   msecs_to_jiffies(300));
12424930fbf4SPavan Kumar Linga }
12434930fbf4SPavan Kumar Linga 
12448077c727SJoshua Hay /**
1245a251eee6SJoshua Hay  * idpf_restore_features - Restore feature configs
1246a251eee6SJoshua Hay  * @vport: virtual port structure
1247a251eee6SJoshua Hay  */
idpf_restore_features(struct idpf_vport * vport)1248a251eee6SJoshua Hay static void idpf_restore_features(struct idpf_vport *vport)
1249a251eee6SJoshua Hay {
1250a251eee6SJoshua Hay 	struct idpf_adapter *adapter = vport->adapter;
1251a251eee6SJoshua Hay 
1252a251eee6SJoshua Hay 	if (idpf_is_cap_ena(adapter, IDPF_OTHER_CAPS, VIRTCHNL2_CAP_MACFILTER))
1253a251eee6SJoshua Hay 		idpf_restore_mac_filters(vport);
1254a251eee6SJoshua Hay }
1255a251eee6SJoshua Hay 
1256a251eee6SJoshua Hay /**
125702cbfba1SAlan Brady  * idpf_set_real_num_queues - set number of queues for netdev
125802cbfba1SAlan Brady  * @vport: virtual port structure
125902cbfba1SAlan Brady  *
126002cbfba1SAlan Brady  * Returns 0 on success, negative on failure.
126102cbfba1SAlan Brady  */
idpf_set_real_num_queues(struct idpf_vport * vport)126202cbfba1SAlan Brady static int idpf_set_real_num_queues(struct idpf_vport *vport)
126302cbfba1SAlan Brady {
126402cbfba1SAlan Brady 	int err;
126502cbfba1SAlan Brady 
126602cbfba1SAlan Brady 	err = netif_set_real_num_rx_queues(vport->netdev, vport->num_rxq);
126702cbfba1SAlan Brady 	if (err)
126802cbfba1SAlan Brady 		return err;
126902cbfba1SAlan Brady 
127002cbfba1SAlan Brady 	return netif_set_real_num_tx_queues(vport->netdev, vport->num_txq);
127102cbfba1SAlan Brady }
127202cbfba1SAlan Brady 
127302cbfba1SAlan Brady /**
1274d4d55871SPavan Kumar Linga  * idpf_up_complete - Complete interface up sequence
1275d4d55871SPavan Kumar Linga  * @vport: virtual port structure
1276d4d55871SPavan Kumar Linga  *
1277d4d55871SPavan Kumar Linga  * Returns 0 on success, negative on failure.
1278d4d55871SPavan Kumar Linga  */
idpf_up_complete(struct idpf_vport * vport)1279d4d55871SPavan Kumar Linga static int idpf_up_complete(struct idpf_vport *vport)
1280d4d55871SPavan Kumar Linga {
1281d4d55871SPavan Kumar Linga 	struct idpf_netdev_priv *np = netdev_priv(vport->netdev);
1282d4d55871SPavan Kumar Linga 
1283d4d55871SPavan Kumar Linga 	if (vport->link_up && !netif_carrier_ok(vport->netdev)) {
1284d4d55871SPavan Kumar Linga 		netif_carrier_on(vport->netdev);
1285d4d55871SPavan Kumar Linga 		netif_tx_start_all_queues(vport->netdev);
1286d4d55871SPavan Kumar Linga 	}
1287d4d55871SPavan Kumar Linga 
1288d4d55871SPavan Kumar Linga 	np->state = __IDPF_VPORT_UP;
1289d4d55871SPavan Kumar Linga 
1290d4d55871SPavan Kumar Linga 	return 0;
1291d4d55871SPavan Kumar Linga }
1292d4d55871SPavan Kumar Linga 
1293d4d55871SPavan Kumar Linga /**
1294d4d55871SPavan Kumar Linga  * idpf_rx_init_buf_tail - Write initial buffer ring tail value
1295d4d55871SPavan Kumar Linga  * @vport: virtual port struct
1296d4d55871SPavan Kumar Linga  */
idpf_rx_init_buf_tail(struct idpf_vport * vport)1297d4d55871SPavan Kumar Linga static void idpf_rx_init_buf_tail(struct idpf_vport *vport)
1298d4d55871SPavan Kumar Linga {
1299d4d55871SPavan Kumar Linga 	int i, j;
1300d4d55871SPavan Kumar Linga 
1301d4d55871SPavan Kumar Linga 	for (i = 0; i < vport->num_rxq_grp; i++) {
1302d4d55871SPavan Kumar Linga 		struct idpf_rxq_group *grp = &vport->rxq_grps[i];
1303d4d55871SPavan Kumar Linga 
1304d4d55871SPavan Kumar Linga 		if (idpf_is_queue_model_split(vport->rxq_model)) {
1305d4d55871SPavan Kumar Linga 			for (j = 0; j < vport->num_bufqs_per_qgrp; j++) {
1306e4891e46SAlexander Lobakin 				const struct idpf_buf_queue *q =
1307d4d55871SPavan Kumar Linga 					&grp->splitq.bufq_sets[j].bufq;
1308d4d55871SPavan Kumar Linga 
1309d4d55871SPavan Kumar Linga 				writel(q->next_to_alloc, q->tail);
1310d4d55871SPavan Kumar Linga 			}
1311d4d55871SPavan Kumar Linga 		} else {
1312d4d55871SPavan Kumar Linga 			for (j = 0; j < grp->singleq.num_rxq; j++) {
1313e4891e46SAlexander Lobakin 				const struct idpf_rx_queue *q =
1314d4d55871SPavan Kumar Linga 					grp->singleq.rxqs[j];
1315d4d55871SPavan Kumar Linga 
1316d4d55871SPavan Kumar Linga 				writel(q->next_to_alloc, q->tail);
1317d4d55871SPavan Kumar Linga 			}
1318d4d55871SPavan Kumar Linga 		}
1319d4d55871SPavan Kumar Linga 	}
1320d4d55871SPavan Kumar Linga }
1321d4d55871SPavan Kumar Linga 
1322d4d55871SPavan Kumar Linga /**
13231c325aacSAlan Brady  * idpf_vport_open - Bring up a vport
13241c325aacSAlan Brady  * @vport: vport to bring up
13251c325aacSAlan Brady  */
idpf_vport_open(struct idpf_vport * vport)1326f01032a2SAlexander Lobakin static int idpf_vport_open(struct idpf_vport *vport)
13271c325aacSAlan Brady {
13281c325aacSAlan Brady 	struct idpf_netdev_priv *np = netdev_priv(vport->netdev);
13291c325aacSAlan Brady 	struct idpf_adapter *adapter = vport->adapter;
133095af467dSAlan Brady 	struct idpf_vport_config *vport_config;
13311c325aacSAlan Brady 	int err;
13321c325aacSAlan Brady 
13331c325aacSAlan Brady 	if (np->state != __IDPF_VPORT_DOWN)
13341c325aacSAlan Brady 		return -EBUSY;
13351c325aacSAlan Brady 
13361c325aacSAlan Brady 	/* we do not allow interface up just yet */
13371c325aacSAlan Brady 	netif_carrier_off(vport->netdev);
13381c325aacSAlan Brady 
13391c325aacSAlan Brady 	err = idpf_vport_intr_alloc(vport);
13401c325aacSAlan Brady 	if (err) {
13411c325aacSAlan Brady 		dev_err(&adapter->pdev->dev, "Failed to allocate interrupts for vport %u: %d\n",
13421c325aacSAlan Brady 			vport->vport_id, err);
1343290f1c03SAlexander Lobakin 		return err;
13441c325aacSAlan Brady 	}
13451c325aacSAlan Brady 
1346290f1c03SAlexander Lobakin 	err = idpf_vport_queues_alloc(vport);
1347290f1c03SAlexander Lobakin 	if (err)
1348290f1c03SAlexander Lobakin 		goto intr_rel;
1349290f1c03SAlexander Lobakin 
13501c325aacSAlan Brady 	err = idpf_vport_queue_ids_init(vport);
13511c325aacSAlan Brady 	if (err) {
13521c325aacSAlan Brady 		dev_err(&adapter->pdev->dev, "Failed to initialize queue ids for vport %u: %d\n",
13531c325aacSAlan Brady 			vport->vport_id, err);
1354290f1c03SAlexander Lobakin 		goto queues_rel;
13551c325aacSAlan Brady 	}
13561c325aacSAlan Brady 
1357d4d55871SPavan Kumar Linga 	err = idpf_vport_intr_init(vport);
1358d4d55871SPavan Kumar Linga 	if (err) {
1359d4d55871SPavan Kumar Linga 		dev_err(&adapter->pdev->dev, "Failed to initialize interrupts for vport %u: %d\n",
1360d4d55871SPavan Kumar Linga 			vport->vport_id, err);
1361290f1c03SAlexander Lobakin 		goto queues_rel;
1362d4d55871SPavan Kumar Linga 	}
1363d4d55871SPavan Kumar Linga 
136495af467dSAlan Brady 	err = idpf_rx_bufs_init_all(vport);
136595af467dSAlan Brady 	if (err) {
136695af467dSAlan Brady 		dev_err(&adapter->pdev->dev, "Failed to initialize RX buffers for vport %u: %d\n",
136795af467dSAlan Brady 			vport->vport_id, err);
1368290f1c03SAlexander Lobakin 		goto queues_rel;
136995af467dSAlan Brady 	}
137095af467dSAlan Brady 
13711c325aacSAlan Brady 	err = idpf_queue_reg_init(vport);
13721c325aacSAlan Brady 	if (err) {
13731c325aacSAlan Brady 		dev_err(&adapter->pdev->dev, "Failed to initialize queue registers for vport %u: %d\n",
13741c325aacSAlan Brady 			vport->vport_id, err);
1375290f1c03SAlexander Lobakin 		goto queues_rel;
13761c325aacSAlan Brady 	}
13771c325aacSAlan Brady 
1378d4d55871SPavan Kumar Linga 	idpf_rx_init_buf_tail(vport);
1379d514c8b5SAlexander Lobakin 	idpf_vport_intr_ena(vport);
1380d4d55871SPavan Kumar Linga 
138195af467dSAlan Brady 	err = idpf_send_config_queues_msg(vport);
13821c325aacSAlan Brady 	if (err) {
13831c325aacSAlan Brady 		dev_err(&adapter->pdev->dev, "Failed to configure queues for vport %u, %d\n",
13841c325aacSAlan Brady 			vport->vport_id, err);
1385d4d55871SPavan Kumar Linga 		goto intr_deinit;
1386d4d55871SPavan Kumar Linga 	}
1387d4d55871SPavan Kumar Linga 
1388d4d55871SPavan Kumar Linga 	err = idpf_send_map_unmap_queue_vector_msg(vport, true);
1389d4d55871SPavan Kumar Linga 	if (err) {
1390d4d55871SPavan Kumar Linga 		dev_err(&adapter->pdev->dev, "Failed to map queue vectors for vport %u: %d\n",
1391d4d55871SPavan Kumar Linga 			vport->vport_id, err);
1392d4d55871SPavan Kumar Linga 		goto intr_deinit;
1393d4d55871SPavan Kumar Linga 	}
1394d4d55871SPavan Kumar Linga 
1395d4d55871SPavan Kumar Linga 	err = idpf_send_enable_queues_msg(vport);
1396d4d55871SPavan Kumar Linga 	if (err) {
1397d4d55871SPavan Kumar Linga 		dev_err(&adapter->pdev->dev, "Failed to enable queues for vport %u: %d\n",
1398d4d55871SPavan Kumar Linga 			vport->vport_id, err);
1399d4d55871SPavan Kumar Linga 		goto unmap_queue_vectors;
1400d4d55871SPavan Kumar Linga 	}
1401d4d55871SPavan Kumar Linga 
1402d4d55871SPavan Kumar Linga 	err = idpf_send_enable_vport_msg(vport);
1403d4d55871SPavan Kumar Linga 	if (err) {
1404d4d55871SPavan Kumar Linga 		dev_err(&adapter->pdev->dev, "Failed to enable vport %u: %d\n",
1405d4d55871SPavan Kumar Linga 			vport->vport_id, err);
1406d4d55871SPavan Kumar Linga 		err = -EAGAIN;
1407d4d55871SPavan Kumar Linga 		goto disable_queues;
14081c325aacSAlan Brady 	}
14091c325aacSAlan Brady 
1410a251eee6SJoshua Hay 	idpf_restore_features(vport);
1411a251eee6SJoshua Hay 
141295af467dSAlan Brady 	vport_config = adapter->vport_config[vport->idx];
141395af467dSAlan Brady 	if (vport_config->user_config.rss_data.rss_lut)
141495af467dSAlan Brady 		err = idpf_config_rss(vport);
141595af467dSAlan Brady 	else
141695af467dSAlan Brady 		err = idpf_init_rss(vport);
141795af467dSAlan Brady 	if (err) {
141895af467dSAlan Brady 		dev_err(&adapter->pdev->dev, "Failed to initialize RSS for vport %u: %d\n",
141995af467dSAlan Brady 			vport->vport_id, err);
1420d4d55871SPavan Kumar Linga 		goto disable_vport;
1421d4d55871SPavan Kumar Linga 	}
1422d4d55871SPavan Kumar Linga 
1423d4d55871SPavan Kumar Linga 	err = idpf_up_complete(vport);
1424d4d55871SPavan Kumar Linga 	if (err) {
1425d4d55871SPavan Kumar Linga 		dev_err(&adapter->pdev->dev, "Failed to complete interface up for vport %u: %d\n",
1426d4d55871SPavan Kumar Linga 			vport->vport_id, err);
1427d4d55871SPavan Kumar Linga 		goto deinit_rss;
142895af467dSAlan Brady 	}
142995af467dSAlan Brady 
14301c325aacSAlan Brady 	return 0;
14311c325aacSAlan Brady 
1432d4d55871SPavan Kumar Linga deinit_rss:
1433d4d55871SPavan Kumar Linga 	idpf_deinit_rss(vport);
1434d4d55871SPavan Kumar Linga disable_vport:
1435d4d55871SPavan Kumar Linga 	idpf_send_disable_vport_msg(vport);
1436d4d55871SPavan Kumar Linga disable_queues:
1437d4d55871SPavan Kumar Linga 	idpf_send_disable_queues_msg(vport);
1438d4d55871SPavan Kumar Linga unmap_queue_vectors:
1439d4d55871SPavan Kumar Linga 	idpf_send_map_unmap_queue_vector_msg(vport, false);
1440d4d55871SPavan Kumar Linga intr_deinit:
1441d4d55871SPavan Kumar Linga 	idpf_vport_intr_deinit(vport);
14421c325aacSAlan Brady queues_rel:
14431c325aacSAlan Brady 	idpf_vport_queues_rel(vport);
1444290f1c03SAlexander Lobakin intr_rel:
1445290f1c03SAlexander Lobakin 	idpf_vport_intr_rel(vport);
14461c325aacSAlan Brady 
14471c325aacSAlan Brady 	return err;
14481c325aacSAlan Brady }
14491c325aacSAlan Brady 
14501c325aacSAlan Brady /**
14510fe45467SPavan Kumar Linga  * idpf_init_task - Delayed initialization task
14520fe45467SPavan Kumar Linga  * @work: work_struct handle to our data
14530fe45467SPavan Kumar Linga  *
14540fe45467SPavan Kumar Linga  * Init task finishes up pending work started in probe. Due to the asynchronous
14550fe45467SPavan Kumar Linga  * nature in which the device communicates with hardware, we may have to wait
14560fe45467SPavan Kumar Linga  * several milliseconds to get a response.  Instead of busy polling in probe,
14570fe45467SPavan Kumar Linga  * pulling it out into a delayed work task prevents us from bogging down the
14580fe45467SPavan Kumar Linga  * whole system waiting for a response from hardware.
14590fe45467SPavan Kumar Linga  */
idpf_init_task(struct work_struct * work)14600fe45467SPavan Kumar Linga void idpf_init_task(struct work_struct *work)
14610fe45467SPavan Kumar Linga {
1462ce1b75d0SPavan Kumar Linga 	struct idpf_vport_config *vport_config;
14630fe45467SPavan Kumar Linga 	struct idpf_vport_max_q max_q;
14640fe45467SPavan Kumar Linga 	struct idpf_adapter *adapter;
14651c325aacSAlan Brady 	struct idpf_netdev_priv *np;
14660fe45467SPavan Kumar Linga 	struct idpf_vport *vport;
14670fe45467SPavan Kumar Linga 	u16 num_default_vports;
14680fe45467SPavan Kumar Linga 	struct pci_dev *pdev;
14690fe45467SPavan Kumar Linga 	bool default_vport;
14700fe45467SPavan Kumar Linga 	int index, err;
14710fe45467SPavan Kumar Linga 
14720fe45467SPavan Kumar Linga 	adapter = container_of(work, struct idpf_adapter, init_task.work);
14730fe45467SPavan Kumar Linga 
14740fe45467SPavan Kumar Linga 	num_default_vports = idpf_get_default_vports(adapter);
14750fe45467SPavan Kumar Linga 	if (adapter->num_alloc_vports < num_default_vports)
14760fe45467SPavan Kumar Linga 		default_vport = true;
14770fe45467SPavan Kumar Linga 	else
14780fe45467SPavan Kumar Linga 		default_vport = false;
14790fe45467SPavan Kumar Linga 
14800fe45467SPavan Kumar Linga 	err = idpf_vport_alloc_max_qs(adapter, &max_q);
14810fe45467SPavan Kumar Linga 	if (err)
14820fe45467SPavan Kumar Linga 		goto unwind_vports;
14830fe45467SPavan Kumar Linga 
14840fe45467SPavan Kumar Linga 	err = idpf_send_create_vport_msg(adapter, &max_q);
14850fe45467SPavan Kumar Linga 	if (err) {
14860fe45467SPavan Kumar Linga 		idpf_vport_dealloc_max_qs(adapter, &max_q);
14870fe45467SPavan Kumar Linga 		goto unwind_vports;
14880fe45467SPavan Kumar Linga 	}
14890fe45467SPavan Kumar Linga 
14900fe45467SPavan Kumar Linga 	pdev = adapter->pdev;
14910fe45467SPavan Kumar Linga 	vport = idpf_vport_alloc(adapter, &max_q);
14920fe45467SPavan Kumar Linga 	if (!vport) {
14930fe45467SPavan Kumar Linga 		err = -EFAULT;
14940fe45467SPavan Kumar Linga 		dev_err(&pdev->dev, "failed to allocate vport: %d\n",
14950fe45467SPavan Kumar Linga 			err);
14960fe45467SPavan Kumar Linga 		idpf_vport_dealloc_max_qs(adapter, &max_q);
14970fe45467SPavan Kumar Linga 		goto unwind_vports;
14980fe45467SPavan Kumar Linga 	}
14990fe45467SPavan Kumar Linga 
15000fe45467SPavan Kumar Linga 	index = vport->idx;
1501ce1b75d0SPavan Kumar Linga 	vport_config = adapter->vport_config[index];
15020fe45467SPavan Kumar Linga 
1503c2d548caSJoshua Hay 	init_waitqueue_head(&vport->sw_marker_wq);
15040fe45467SPavan Kumar Linga 
1505ce1b75d0SPavan Kumar Linga 	spin_lock_init(&vport_config->mac_filter_list_lock);
1506ce1b75d0SPavan Kumar Linga 
1507ce1b75d0SPavan Kumar Linga 	INIT_LIST_HEAD(&vport_config->user_config.mac_filter_list);
1508ce1b75d0SPavan Kumar Linga 
1509ce1b75d0SPavan Kumar Linga 	err = idpf_check_supported_desc_ids(vport);
1510ce1b75d0SPavan Kumar Linga 	if (err) {
1511ce1b75d0SPavan Kumar Linga 		dev_err(&pdev->dev, "failed to get required descriptor ids\n");
1512ce1b75d0SPavan Kumar Linga 		goto cfg_netdev_err;
1513ce1b75d0SPavan Kumar Linga 	}
15140fe45467SPavan Kumar Linga 
15150fe45467SPavan Kumar Linga 	if (idpf_cfg_netdev(vport))
15160fe45467SPavan Kumar Linga 		goto cfg_netdev_err;
15170fe45467SPavan Kumar Linga 
1518ce1b75d0SPavan Kumar Linga 	err = idpf_send_get_rx_ptype_msg(vport);
1519ce1b75d0SPavan Kumar Linga 	if (err)
1520ce1b75d0SPavan Kumar Linga 		goto handle_err;
1521ce1b75d0SPavan Kumar Linga 
15221c325aacSAlan Brady 	/* Once state is put into DOWN, driver is ready for dev_open */
15231c325aacSAlan Brady 	np = netdev_priv(vport->netdev);
15241c325aacSAlan Brady 	np->state = __IDPF_VPORT_DOWN;
15251c325aacSAlan Brady 	if (test_and_clear_bit(IDPF_VPORT_UP_REQUESTED, vport_config->flags))
1526f01032a2SAlexander Lobakin 		idpf_vport_open(vport);
15271c325aacSAlan Brady 
15280fe45467SPavan Kumar Linga 	/* Spawn and return 'idpf_init_task' work queue until all the
15290fe45467SPavan Kumar Linga 	 * default vports are created
15300fe45467SPavan Kumar Linga 	 */
15310fe45467SPavan Kumar Linga 	if (adapter->num_alloc_vports < num_default_vports) {
15320fe45467SPavan Kumar Linga 		queue_delayed_work(adapter->init_wq, &adapter->init_task,
15330fe45467SPavan Kumar Linga 				   msecs_to_jiffies(5 * (adapter->pdev->devfn & 0x07)));
15340fe45467SPavan Kumar Linga 
15350fe45467SPavan Kumar Linga 		return;
15360fe45467SPavan Kumar Linga 	}
15370fe45467SPavan Kumar Linga 
15380fe45467SPavan Kumar Linga 	for (index = 0; index < adapter->max_vports; index++) {
15390fe45467SPavan Kumar Linga 		if (adapter->netdevs[index] &&
15400fe45467SPavan Kumar Linga 		    !test_bit(IDPF_VPORT_REG_NETDEV,
15410fe45467SPavan Kumar Linga 			      adapter->vport_config[index]->flags)) {
15420fe45467SPavan Kumar Linga 			register_netdev(adapter->netdevs[index]);
15430fe45467SPavan Kumar Linga 			set_bit(IDPF_VPORT_REG_NETDEV,
15440fe45467SPavan Kumar Linga 				adapter->vport_config[index]->flags);
15450fe45467SPavan Kumar Linga 		}
15460fe45467SPavan Kumar Linga 	}
15470fe45467SPavan Kumar Linga 
15480fe45467SPavan Kumar Linga 	/* As all the required vports are created, clear the reset flag
15490fe45467SPavan Kumar Linga 	 * unconditionally here in case we were in reset and the link was down.
15500fe45467SPavan Kumar Linga 	 */
15510fe45467SPavan Kumar Linga 	clear_bit(IDPF_HR_RESET_IN_PROG, adapter->flags);
1552a251eee6SJoshua Hay 	/* Start the statistics task now */
1553a251eee6SJoshua Hay 	queue_delayed_work(adapter->stats_wq, &adapter->stats_task,
1554a251eee6SJoshua Hay 			   msecs_to_jiffies(10 * (pdev->devfn & 0x07)));
15550fe45467SPavan Kumar Linga 
15560fe45467SPavan Kumar Linga 	return;
15570fe45467SPavan Kumar Linga 
1558ce1b75d0SPavan Kumar Linga handle_err:
1559ce1b75d0SPavan Kumar Linga 	idpf_decfg_netdev(vport);
15600fe45467SPavan Kumar Linga cfg_netdev_err:
15610fe45467SPavan Kumar Linga 	idpf_vport_rel(vport);
15620fe45467SPavan Kumar Linga 	adapter->vports[index] = NULL;
15630fe45467SPavan Kumar Linga unwind_vports:
15640fe45467SPavan Kumar Linga 	if (default_vport) {
15650fe45467SPavan Kumar Linga 		for (index = 0; index < adapter->max_vports; index++) {
15660fe45467SPavan Kumar Linga 			if (adapter->vports[index])
15670fe45467SPavan Kumar Linga 				idpf_vport_dealloc(adapter->vports[index]);
15680fe45467SPavan Kumar Linga 		}
15690fe45467SPavan Kumar Linga 	}
15700fe45467SPavan Kumar Linga 	clear_bit(IDPF_HR_RESET_IN_PROG, adapter->flags);
15710fe45467SPavan Kumar Linga }
15720fe45467SPavan Kumar Linga 
15730fe45467SPavan Kumar Linga /**
1574a251eee6SJoshua Hay  * idpf_sriov_ena - Enable or change number of VFs
1575a251eee6SJoshua Hay  * @adapter: private data struct
1576a251eee6SJoshua Hay  * @num_vfs: number of VFs to allocate
1577a251eee6SJoshua Hay  */
idpf_sriov_ena(struct idpf_adapter * adapter,int num_vfs)1578a251eee6SJoshua Hay static int idpf_sriov_ena(struct idpf_adapter *adapter, int num_vfs)
1579a251eee6SJoshua Hay {
1580a251eee6SJoshua Hay 	struct device *dev = &adapter->pdev->dev;
1581a251eee6SJoshua Hay 	int err;
1582a251eee6SJoshua Hay 
1583a251eee6SJoshua Hay 	err = idpf_send_set_sriov_vfs_msg(adapter, num_vfs);
1584a251eee6SJoshua Hay 	if (err) {
1585a251eee6SJoshua Hay 		dev_err(dev, "Failed to allocate VFs: %d\n", err);
1586a251eee6SJoshua Hay 
1587a251eee6SJoshua Hay 		return err;
1588a251eee6SJoshua Hay 	}
1589a251eee6SJoshua Hay 
1590a251eee6SJoshua Hay 	err = pci_enable_sriov(adapter->pdev, num_vfs);
1591a251eee6SJoshua Hay 	if (err) {
1592a251eee6SJoshua Hay 		idpf_send_set_sriov_vfs_msg(adapter, 0);
1593a251eee6SJoshua Hay 		dev_err(dev, "Failed to enable SR-IOV: %d\n", err);
1594a251eee6SJoshua Hay 
1595a251eee6SJoshua Hay 		return err;
1596a251eee6SJoshua Hay 	}
1597a251eee6SJoshua Hay 
1598a251eee6SJoshua Hay 	adapter->num_vfs = num_vfs;
1599a251eee6SJoshua Hay 
1600a251eee6SJoshua Hay 	return num_vfs;
1601a251eee6SJoshua Hay }
1602a251eee6SJoshua Hay 
1603a251eee6SJoshua Hay /**
1604a251eee6SJoshua Hay  * idpf_sriov_configure - Configure the requested VFs
1605a251eee6SJoshua Hay  * @pdev: pointer to a pci_dev structure
1606a251eee6SJoshua Hay  * @num_vfs: number of vfs to allocate
1607a251eee6SJoshua Hay  *
1608a251eee6SJoshua Hay  * Enable or change the number of VFs. Called when the user updates the number
1609a251eee6SJoshua Hay  * of VFs in sysfs.
1610a251eee6SJoshua Hay  **/
idpf_sriov_configure(struct pci_dev * pdev,int num_vfs)1611a251eee6SJoshua Hay int idpf_sriov_configure(struct pci_dev *pdev, int num_vfs)
1612a251eee6SJoshua Hay {
1613a251eee6SJoshua Hay 	struct idpf_adapter *adapter = pci_get_drvdata(pdev);
1614a251eee6SJoshua Hay 
1615a251eee6SJoshua Hay 	if (!idpf_is_cap_ena(adapter, IDPF_OTHER_CAPS, VIRTCHNL2_CAP_SRIOV)) {
1616a251eee6SJoshua Hay 		dev_info(&pdev->dev, "SR-IOV is not supported on this device\n");
1617a251eee6SJoshua Hay 
1618a251eee6SJoshua Hay 		return -EOPNOTSUPP;
1619a251eee6SJoshua Hay 	}
1620a251eee6SJoshua Hay 
1621a251eee6SJoshua Hay 	if (num_vfs)
1622a251eee6SJoshua Hay 		return idpf_sriov_ena(adapter, num_vfs);
1623a251eee6SJoshua Hay 
1624a251eee6SJoshua Hay 	if (pci_vfs_assigned(pdev)) {
1625a251eee6SJoshua Hay 		dev_warn(&pdev->dev, "Unable to free VFs because some are assigned to VMs\n");
1626a251eee6SJoshua Hay 
1627a251eee6SJoshua Hay 		return -EBUSY;
1628a251eee6SJoshua Hay 	}
1629a251eee6SJoshua Hay 
1630a251eee6SJoshua Hay 	pci_disable_sriov(adapter->pdev);
1631a251eee6SJoshua Hay 	idpf_send_set_sriov_vfs_msg(adapter, 0);
1632a251eee6SJoshua Hay 	adapter->num_vfs = 0;
1633a251eee6SJoshua Hay 
1634a251eee6SJoshua Hay 	return 0;
1635a251eee6SJoshua Hay }
1636a251eee6SJoshua Hay 
1637a251eee6SJoshua Hay /**
16380fe45467SPavan Kumar Linga  * idpf_deinit_task - Device deinit routine
16390fe45467SPavan Kumar Linga  * @adapter: Driver specific private structure
16400fe45467SPavan Kumar Linga  *
16410fe45467SPavan Kumar Linga  * Extended remove logic which will be used for
16420fe45467SPavan Kumar Linga  * hard reset as well
16430fe45467SPavan Kumar Linga  */
idpf_deinit_task(struct idpf_adapter * adapter)16440fe45467SPavan Kumar Linga void idpf_deinit_task(struct idpf_adapter *adapter)
16450fe45467SPavan Kumar Linga {
16460fe45467SPavan Kumar Linga 	unsigned int i;
16470fe45467SPavan Kumar Linga 
16480fe45467SPavan Kumar Linga 	/* Wait until the init_task is done else this thread might release
16490fe45467SPavan Kumar Linga 	 * the resources first and the other thread might end up in a bad state
16500fe45467SPavan Kumar Linga 	 */
16510fe45467SPavan Kumar Linga 	cancel_delayed_work_sync(&adapter->init_task);
16520fe45467SPavan Kumar Linga 
16530fe45467SPavan Kumar Linga 	if (!adapter->vports)
16540fe45467SPavan Kumar Linga 		return;
16550fe45467SPavan Kumar Linga 
1656a251eee6SJoshua Hay 	cancel_delayed_work_sync(&adapter->stats_task);
1657a251eee6SJoshua Hay 
16580fe45467SPavan Kumar Linga 	for (i = 0; i < adapter->max_vports; i++) {
16590fe45467SPavan Kumar Linga 		if (adapter->vports[i])
16600fe45467SPavan Kumar Linga 			idpf_vport_dealloc(adapter->vports[i]);
16610fe45467SPavan Kumar Linga 	}
16620fe45467SPavan Kumar Linga }
16630fe45467SPavan Kumar Linga 
16640fe45467SPavan Kumar Linga /**
16658077c727SJoshua Hay  * idpf_check_reset_complete - check that reset is complete
16668077c727SJoshua Hay  * @hw: pointer to hw struct
16678077c727SJoshua Hay  * @reset_reg: struct with reset registers
16688077c727SJoshua Hay  *
16698077c727SJoshua Hay  * Returns 0 if device is ready to use, or -EBUSY if it's in reset.
16708077c727SJoshua Hay  **/
idpf_check_reset_complete(struct idpf_hw * hw,struct idpf_reset_reg * reset_reg)16718077c727SJoshua Hay static int idpf_check_reset_complete(struct idpf_hw *hw,
16728077c727SJoshua Hay 				     struct idpf_reset_reg *reset_reg)
16738077c727SJoshua Hay {
16748077c727SJoshua Hay 	struct idpf_adapter *adapter = hw->back;
16758077c727SJoshua Hay 	int i;
16768077c727SJoshua Hay 
16778077c727SJoshua Hay 	for (i = 0; i < 2000; i++) {
16788077c727SJoshua Hay 		u32 reg_val = readl(reset_reg->rstat);
16798077c727SJoshua Hay 
16808077c727SJoshua Hay 		/* 0xFFFFFFFF might be read if other side hasn't cleared the
16818077c727SJoshua Hay 		 * register for us yet and 0xFFFFFFFF is not a valid value for
16828077c727SJoshua Hay 		 * the register, so treat that as invalid.
16838077c727SJoshua Hay 		 */
16848077c727SJoshua Hay 		if (reg_val != 0xFFFFFFFF && (reg_val & reset_reg->rstat_m))
16858077c727SJoshua Hay 			return 0;
16868077c727SJoshua Hay 
16878077c727SJoshua Hay 		usleep_range(5000, 10000);
16888077c727SJoshua Hay 	}
16898077c727SJoshua Hay 
16908077c727SJoshua Hay 	dev_warn(&adapter->pdev->dev, "Device reset timeout!\n");
16918077c727SJoshua Hay 	/* Clear the reset flag unconditionally here since the reset
16928077c727SJoshua Hay 	 * technically isn't in progress anymore from the driver's perspective
16938077c727SJoshua Hay 	 */
16948077c727SJoshua Hay 	clear_bit(IDPF_HR_RESET_IN_PROG, adapter->flags);
16958077c727SJoshua Hay 
16968077c727SJoshua Hay 	return -EBUSY;
16978077c727SJoshua Hay }
16988077c727SJoshua Hay 
16998077c727SJoshua Hay /**
17000fe45467SPavan Kumar Linga  * idpf_set_vport_state - Set the vport state to be after the reset
17010fe45467SPavan Kumar Linga  * @adapter: Driver specific private structure
17020fe45467SPavan Kumar Linga  */
idpf_set_vport_state(struct idpf_adapter * adapter)17030fe45467SPavan Kumar Linga static void idpf_set_vport_state(struct idpf_adapter *adapter)
17040fe45467SPavan Kumar Linga {
17050fe45467SPavan Kumar Linga 	u16 i;
17060fe45467SPavan Kumar Linga 
17070fe45467SPavan Kumar Linga 	for (i = 0; i < adapter->max_vports; i++) {
17080fe45467SPavan Kumar Linga 		struct idpf_netdev_priv *np;
17090fe45467SPavan Kumar Linga 
17100fe45467SPavan Kumar Linga 		if (!adapter->netdevs[i])
17110fe45467SPavan Kumar Linga 			continue;
17120fe45467SPavan Kumar Linga 
17130fe45467SPavan Kumar Linga 		np = netdev_priv(adapter->netdevs[i]);
17140fe45467SPavan Kumar Linga 		if (np->state == __IDPF_VPORT_UP)
17150fe45467SPavan Kumar Linga 			set_bit(IDPF_VPORT_UP_REQUESTED,
17160fe45467SPavan Kumar Linga 				adapter->vport_config[i]->flags);
17170fe45467SPavan Kumar Linga 	}
17180fe45467SPavan Kumar Linga }
17190fe45467SPavan Kumar Linga 
17200fe45467SPavan Kumar Linga /**
17218077c727SJoshua Hay  * idpf_init_hard_reset - Initiate a hardware reset
17228077c727SJoshua Hay  * @adapter: Driver specific private structure
17238077c727SJoshua Hay  *
17248077c727SJoshua Hay  * Deallocate the vports and all the resources associated with them and
17258077c727SJoshua Hay  * reallocate. Also reinitialize the mailbox. Return 0 on success,
17268077c727SJoshua Hay  * negative on failure.
17278077c727SJoshua Hay  */
idpf_init_hard_reset(struct idpf_adapter * adapter)17288077c727SJoshua Hay static int idpf_init_hard_reset(struct idpf_adapter *adapter)
17298077c727SJoshua Hay {
17308077c727SJoshua Hay 	struct idpf_reg_ops *reg_ops = &adapter->dev_ops.reg_ops;
17318077c727SJoshua Hay 	struct device *dev = &adapter->pdev->dev;
17320fe45467SPavan Kumar Linga 	struct net_device *netdev;
17338077c727SJoshua Hay 	int err;
17340fe45467SPavan Kumar Linga 	u16 i;
17358077c727SJoshua Hay 
17368077c727SJoshua Hay 	mutex_lock(&adapter->vport_ctrl_lock);
17378077c727SJoshua Hay 
17388077c727SJoshua Hay 	dev_info(dev, "Device HW Reset initiated\n");
17390fe45467SPavan Kumar Linga 
17400fe45467SPavan Kumar Linga 	/* Avoid TX hangs on reset */
17410fe45467SPavan Kumar Linga 	for (i = 0; i < adapter->max_vports; i++) {
17420fe45467SPavan Kumar Linga 		netdev = adapter->netdevs[i];
17430fe45467SPavan Kumar Linga 		if (!netdev)
17440fe45467SPavan Kumar Linga 			continue;
17450fe45467SPavan Kumar Linga 
17460fe45467SPavan Kumar Linga 		netif_carrier_off(netdev);
17470fe45467SPavan Kumar Linga 		netif_tx_disable(netdev);
17480fe45467SPavan Kumar Linga 	}
17490fe45467SPavan Kumar Linga 
17508077c727SJoshua Hay 	/* Prepare for reset */
17518077c727SJoshua Hay 	if (test_and_clear_bit(IDPF_HR_DRV_LOAD, adapter->flags)) {
17528077c727SJoshua Hay 		reg_ops->trigger_reset(adapter, IDPF_HR_DRV_LOAD);
17538077c727SJoshua Hay 	} else if (test_and_clear_bit(IDPF_HR_FUNC_RESET, adapter->flags)) {
17548077c727SJoshua Hay 		bool is_reset = idpf_is_reset_detected(adapter);
17558077c727SJoshua Hay 
17560fe45467SPavan Kumar Linga 		idpf_set_vport_state(adapter);
17574930fbf4SPavan Kumar Linga 		idpf_vc_core_deinit(adapter);
17588077c727SJoshua Hay 		if (!is_reset)
17598077c727SJoshua Hay 			reg_ops->trigger_reset(adapter, IDPF_HR_FUNC_RESET);
17608077c727SJoshua Hay 		idpf_deinit_dflt_mbx(adapter);
17618077c727SJoshua Hay 	} else {
17628077c727SJoshua Hay 		dev_err(dev, "Unhandled hard reset cause\n");
17638077c727SJoshua Hay 		err = -EBADRQC;
17648077c727SJoshua Hay 		goto unlock_mutex;
17658077c727SJoshua Hay 	}
17668077c727SJoshua Hay 
17678077c727SJoshua Hay 	/* Wait for reset to complete */
17688077c727SJoshua Hay 	err = idpf_check_reset_complete(&adapter->hw, &adapter->reset_reg);
17698077c727SJoshua Hay 	if (err) {
17708077c727SJoshua Hay 		dev_err(dev, "The driver was unable to contact the device's firmware. Check that the FW is running. Driver state= 0x%x\n",
17718077c727SJoshua Hay 			adapter->state);
17728077c727SJoshua Hay 		goto unlock_mutex;
17738077c727SJoshua Hay 	}
17748077c727SJoshua Hay 
17758077c727SJoshua Hay 	/* Reset is complete and so start building the driver resources again */
17768077c727SJoshua Hay 	err = idpf_init_dflt_mbx(adapter);
17774930fbf4SPavan Kumar Linga 	if (err) {
17788077c727SJoshua Hay 		dev_err(dev, "Failed to initialize default mailbox: %d\n", err);
17794930fbf4SPavan Kumar Linga 		goto unlock_mutex;
17804930fbf4SPavan Kumar Linga 	}
17814930fbf4SPavan Kumar Linga 
178234c21fa8SAlan Brady 	queue_delayed_work(adapter->mbx_wq, &adapter->mbx_task, 0);
178334c21fa8SAlan Brady 
17844930fbf4SPavan Kumar Linga 	/* Initialize the state machine, also allocate memory and request
17854930fbf4SPavan Kumar Linga 	 * resources
17864930fbf4SPavan Kumar Linga 	 */
17874930fbf4SPavan Kumar Linga 	err = idpf_vc_core_init(adapter);
17884930fbf4SPavan Kumar Linga 	if (err) {
17894930fbf4SPavan Kumar Linga 		idpf_deinit_dflt_mbx(adapter);
17904930fbf4SPavan Kumar Linga 		goto unlock_mutex;
17914930fbf4SPavan Kumar Linga 	}
17928077c727SJoshua Hay 
17930fe45467SPavan Kumar Linga 	/* Wait till all the vports are initialized to release the reset lock,
17940fe45467SPavan Kumar Linga 	 * else user space callbacks may access uninitialized vports
17950fe45467SPavan Kumar Linga 	 */
17960fe45467SPavan Kumar Linga 	while (test_bit(IDPF_HR_RESET_IN_PROG, adapter->flags))
17970fe45467SPavan Kumar Linga 		msleep(100);
17980fe45467SPavan Kumar Linga 
17998077c727SJoshua Hay unlock_mutex:
18008077c727SJoshua Hay 	mutex_unlock(&adapter->vport_ctrl_lock);
18018077c727SJoshua Hay 
18028077c727SJoshua Hay 	return err;
18038077c727SJoshua Hay }
18048077c727SJoshua Hay 
18058077c727SJoshua Hay /**
18068077c727SJoshua Hay  * idpf_vc_event_task - Handle virtchannel event logic
18078077c727SJoshua Hay  * @work: work queue struct
18088077c727SJoshua Hay  */
idpf_vc_event_task(struct work_struct * work)18098077c727SJoshua Hay void idpf_vc_event_task(struct work_struct *work)
18108077c727SJoshua Hay {
18118077c727SJoshua Hay 	struct idpf_adapter *adapter;
18128077c727SJoshua Hay 
18138077c727SJoshua Hay 	adapter = container_of(work, struct idpf_adapter, vc_event_task.work);
18148077c727SJoshua Hay 
18158077c727SJoshua Hay 	if (test_bit(IDPF_REMOVE_IN_PROG, adapter->flags))
18168077c727SJoshua Hay 		return;
18178077c727SJoshua Hay 
18188077c727SJoshua Hay 	if (test_bit(IDPF_HR_FUNC_RESET, adapter->flags) ||
18198077c727SJoshua Hay 	    test_bit(IDPF_HR_DRV_LOAD, adapter->flags)) {
18208077c727SJoshua Hay 		set_bit(IDPF_HR_RESET_IN_PROG, adapter->flags);
18218077c727SJoshua Hay 		idpf_init_hard_reset(adapter);
18228077c727SJoshua Hay 	}
18238077c727SJoshua Hay }
18248077c727SJoshua Hay 
18258077c727SJoshua Hay /**
182602cbfba1SAlan Brady  * idpf_initiate_soft_reset - Initiate a software reset
182702cbfba1SAlan Brady  * @vport: virtual port data struct
182802cbfba1SAlan Brady  * @reset_cause: reason for the soft reset
182902cbfba1SAlan Brady  *
183002cbfba1SAlan Brady  * Soft reset only reallocs vport queue resources. Returns 0 on success,
183102cbfba1SAlan Brady  * negative on failure.
183202cbfba1SAlan Brady  */
idpf_initiate_soft_reset(struct idpf_vport * vport,enum idpf_vport_reset_cause reset_cause)183302cbfba1SAlan Brady int idpf_initiate_soft_reset(struct idpf_vport *vport,
183402cbfba1SAlan Brady 			     enum idpf_vport_reset_cause reset_cause)
183502cbfba1SAlan Brady {
183602cbfba1SAlan Brady 	struct idpf_netdev_priv *np = netdev_priv(vport->netdev);
183702cbfba1SAlan Brady 	enum idpf_vport_state current_state = np->state;
183802cbfba1SAlan Brady 	struct idpf_adapter *adapter = vport->adapter;
183902cbfba1SAlan Brady 	struct idpf_vport *new_vport;
1840e4891e46SAlexander Lobakin 	int err;
184102cbfba1SAlan Brady 
184202cbfba1SAlan Brady 	/* If the system is low on memory, we can end up in bad state if we
184302cbfba1SAlan Brady 	 * free all the memory for queue resources and try to allocate them
184402cbfba1SAlan Brady 	 * again. Instead, we can pre-allocate the new resources before doing
184502cbfba1SAlan Brady 	 * anything and bailing if the alloc fails.
184602cbfba1SAlan Brady 	 *
184702cbfba1SAlan Brady 	 * Make a clone of the existing vport to mimic its current
184802cbfba1SAlan Brady 	 * configuration, then modify the new structure with any requested
184902cbfba1SAlan Brady 	 * changes. Once the allocation of the new resources is done, stop the
185002cbfba1SAlan Brady 	 * existing vport and copy the configuration to the main vport. If an
185102cbfba1SAlan Brady 	 * error occurred, the existing vport will be untouched.
185202cbfba1SAlan Brady 	 *
185302cbfba1SAlan Brady 	 */
185402cbfba1SAlan Brady 	new_vport = kzalloc(sizeof(*vport), GFP_KERNEL);
185502cbfba1SAlan Brady 	if (!new_vport)
185602cbfba1SAlan Brady 		return -ENOMEM;
185702cbfba1SAlan Brady 
185802cbfba1SAlan Brady 	/* This purposely avoids copying the end of the struct because it
185902cbfba1SAlan Brady 	 * contains wait_queues and mutexes and other stuff we don't want to
186002cbfba1SAlan Brady 	 * mess with. Nothing below should use those variables from new_vport
186102cbfba1SAlan Brady 	 * and should instead always refer to them in vport if they need to.
186202cbfba1SAlan Brady 	 */
1863bcbedf25SAlan Brady 	memcpy(new_vport, vport, offsetof(struct idpf_vport, link_speed_mbps));
186402cbfba1SAlan Brady 
186502cbfba1SAlan Brady 	/* Adjust resource parameters prior to reallocating resources */
186602cbfba1SAlan Brady 	switch (reset_cause) {
186702cbfba1SAlan Brady 	case IDPF_SR_Q_CHANGE:
186802cbfba1SAlan Brady 		err = idpf_vport_adjust_qs(new_vport);
186902cbfba1SAlan Brady 		if (err)
187002cbfba1SAlan Brady 			goto free_vport;
187102cbfba1SAlan Brady 		break;
187202cbfba1SAlan Brady 	case IDPF_SR_Q_DESC_CHANGE:
187302cbfba1SAlan Brady 		/* Update queue parameters before allocating resources */
187402cbfba1SAlan Brady 		idpf_vport_calc_num_q_desc(new_vport);
187502cbfba1SAlan Brady 		break;
1876a251eee6SJoshua Hay 	case IDPF_SR_MTU_CHANGE:
1877a251eee6SJoshua Hay 	case IDPF_SR_RSC_CHANGE:
1878a251eee6SJoshua Hay 		break;
187902cbfba1SAlan Brady 	default:
188002cbfba1SAlan Brady 		dev_err(&adapter->pdev->dev, "Unhandled soft reset cause\n");
188102cbfba1SAlan Brady 		err = -EINVAL;
188202cbfba1SAlan Brady 		goto free_vport;
188302cbfba1SAlan Brady 	}
188402cbfba1SAlan Brady 
188502cbfba1SAlan Brady 	if (current_state <= __IDPF_VPORT_DOWN) {
188602cbfba1SAlan Brady 		idpf_send_delete_queues_msg(vport);
188702cbfba1SAlan Brady 	} else {
188802cbfba1SAlan Brady 		set_bit(IDPF_VPORT_DEL_QUEUES, vport->flags);
188902cbfba1SAlan Brady 		idpf_vport_stop(vport);
189002cbfba1SAlan Brady 	}
189102cbfba1SAlan Brady 
189202cbfba1SAlan Brady 	idpf_deinit_rss(vport);
189302cbfba1SAlan Brady 	/* We're passing in vport here because we need its wait_queue
189402cbfba1SAlan Brady 	 * to send a message and it should be getting all the vport
189502cbfba1SAlan Brady 	 * config data out of the adapter but we need to be careful not
189602cbfba1SAlan Brady 	 * to add code to add_queues to change the vport config within
189702cbfba1SAlan Brady 	 * vport itself as it will be wiped with a memcpy later.
189802cbfba1SAlan Brady 	 */
189902cbfba1SAlan Brady 	err = idpf_send_add_queues_msg(vport, new_vport->num_txq,
190002cbfba1SAlan Brady 				       new_vport->num_complq,
190102cbfba1SAlan Brady 				       new_vport->num_rxq,
190202cbfba1SAlan Brady 				       new_vport->num_bufq);
190302cbfba1SAlan Brady 	if (err)
190402cbfba1SAlan Brady 		goto err_reset;
190502cbfba1SAlan Brady 
190602cbfba1SAlan Brady 	/* Same comment as above regarding avoiding copying the wait_queues and
190702cbfba1SAlan Brady 	 * mutexes applies here. We do not want to mess with those if possible.
190802cbfba1SAlan Brady 	 */
1909bcbedf25SAlan Brady 	memcpy(vport, new_vport, offsetof(struct idpf_vport, link_speed_mbps));
191002cbfba1SAlan Brady 
191102cbfba1SAlan Brady 	if (reset_cause == IDPF_SR_Q_CHANGE)
191202cbfba1SAlan Brady 		idpf_vport_alloc_vec_indexes(vport);
191302cbfba1SAlan Brady 
191402cbfba1SAlan Brady 	err = idpf_set_real_num_queues(vport);
191502cbfba1SAlan Brady 	if (err)
1916f01032a2SAlexander Lobakin 		goto err_open;
191702cbfba1SAlan Brady 
191802cbfba1SAlan Brady 	if (current_state == __IDPF_VPORT_UP)
1919f01032a2SAlexander Lobakin 		err = idpf_vport_open(vport);
192002cbfba1SAlan Brady 
192102cbfba1SAlan Brady 	kfree(new_vport);
192202cbfba1SAlan Brady 
192302cbfba1SAlan Brady 	return err;
192402cbfba1SAlan Brady 
192502cbfba1SAlan Brady err_reset:
1926f01032a2SAlexander Lobakin 	idpf_send_add_queues_msg(vport, vport->num_txq, vport->num_complq,
1927f01032a2SAlexander Lobakin 				 vport->num_rxq, vport->num_bufq);
1928f01032a2SAlexander Lobakin 
1929f01032a2SAlexander Lobakin err_open:
1930f01032a2SAlexander Lobakin 	if (current_state == __IDPF_VPORT_UP)
1931f01032a2SAlexander Lobakin 		idpf_vport_open(vport);
1932f01032a2SAlexander Lobakin 
193302cbfba1SAlan Brady free_vport:
193402cbfba1SAlan Brady 	kfree(new_vport);
193502cbfba1SAlan Brady 
193602cbfba1SAlan Brady 	return err;
193702cbfba1SAlan Brady }
193802cbfba1SAlan Brady 
193902cbfba1SAlan Brady /**
1940a251eee6SJoshua Hay  * idpf_addr_sync - Callback for dev_(mc|uc)_sync to add address
1941a251eee6SJoshua Hay  * @netdev: the netdevice
1942a251eee6SJoshua Hay  * @addr: address to add
1943a251eee6SJoshua Hay  *
1944a251eee6SJoshua Hay  * Called by __dev_(mc|uc)_sync when an address needs to be added. We call
1945a251eee6SJoshua Hay  * __dev_(uc|mc)_sync from .set_rx_mode. Kernel takes addr_list_lock spinlock
1946a251eee6SJoshua Hay  * meaning we cannot sleep in this context. Due to this, we have to add the
1947a251eee6SJoshua Hay  * filter and send the virtchnl message asynchronously without waiting for the
1948a251eee6SJoshua Hay  * response from the other side. We won't know whether or not the operation
1949a251eee6SJoshua Hay  * actually succeeded until we get the message back.  Returns 0 on success,
1950a251eee6SJoshua Hay  * negative on failure.
1951a251eee6SJoshua Hay  */
idpf_addr_sync(struct net_device * netdev,const u8 * addr)1952a251eee6SJoshua Hay static int idpf_addr_sync(struct net_device *netdev, const u8 *addr)
1953a251eee6SJoshua Hay {
1954a251eee6SJoshua Hay 	struct idpf_netdev_priv *np = netdev_priv(netdev);
1955a251eee6SJoshua Hay 
1956a251eee6SJoshua Hay 	return idpf_add_mac_filter(np->vport, np, addr, true);
1957a251eee6SJoshua Hay }
1958a251eee6SJoshua Hay 
1959a251eee6SJoshua Hay /**
1960a251eee6SJoshua Hay  * idpf_addr_unsync - Callback for dev_(mc|uc)_sync to remove address
1961a251eee6SJoshua Hay  * @netdev: the netdevice
1962a251eee6SJoshua Hay  * @addr: address to add
1963a251eee6SJoshua Hay  *
1964a251eee6SJoshua Hay  * Called by __dev_(mc|uc)_sync when an address needs to be added. We call
1965a251eee6SJoshua Hay  * __dev_(uc|mc)_sync from .set_rx_mode. Kernel takes addr_list_lock spinlock
1966a251eee6SJoshua Hay  * meaning we cannot sleep in this context. Due to this we have to delete the
1967a251eee6SJoshua Hay  * filter and send the virtchnl message asynchronously without waiting for the
1968a251eee6SJoshua Hay  * return from the other side.  We won't know whether or not the operation
1969a251eee6SJoshua Hay  * actually succeeded until we get the message back. Returns 0 on success,
1970a251eee6SJoshua Hay  * negative on failure.
1971a251eee6SJoshua Hay  */
idpf_addr_unsync(struct net_device * netdev,const u8 * addr)1972a251eee6SJoshua Hay static int idpf_addr_unsync(struct net_device *netdev, const u8 *addr)
1973a251eee6SJoshua Hay {
1974a251eee6SJoshua Hay 	struct idpf_netdev_priv *np = netdev_priv(netdev);
1975a251eee6SJoshua Hay 
1976a251eee6SJoshua Hay 	/* Under some circumstances, we might receive a request to delete
1977a251eee6SJoshua Hay 	 * our own device address from our uc list. Because we store the
1978a251eee6SJoshua Hay 	 * device address in the VSI's MAC filter list, we need to ignore
1979a251eee6SJoshua Hay 	 * such requests and not delete our device address from this list.
1980a251eee6SJoshua Hay 	 */
1981a251eee6SJoshua Hay 	if (ether_addr_equal(addr, netdev->dev_addr))
1982a251eee6SJoshua Hay 		return 0;
1983a251eee6SJoshua Hay 
1984a251eee6SJoshua Hay 	idpf_del_mac_filter(np->vport, np, addr, true);
1985a251eee6SJoshua Hay 
1986a251eee6SJoshua Hay 	return 0;
1987a251eee6SJoshua Hay }
1988a251eee6SJoshua Hay 
1989a251eee6SJoshua Hay /**
1990a251eee6SJoshua Hay  * idpf_set_rx_mode - NDO callback to set the netdev filters
1991a251eee6SJoshua Hay  * @netdev: network interface device structure
1992a251eee6SJoshua Hay  *
1993a251eee6SJoshua Hay  * Stack takes addr_list_lock spinlock before calling our .set_rx_mode.  We
1994a251eee6SJoshua Hay  * cannot sleep in this context.
1995a251eee6SJoshua Hay  */
idpf_set_rx_mode(struct net_device * netdev)1996a251eee6SJoshua Hay static void idpf_set_rx_mode(struct net_device *netdev)
1997a251eee6SJoshua Hay {
1998a251eee6SJoshua Hay 	struct idpf_netdev_priv *np = netdev_priv(netdev);
1999a251eee6SJoshua Hay 	struct idpf_vport_user_config_data *config_data;
2000a251eee6SJoshua Hay 	struct idpf_adapter *adapter;
2001a251eee6SJoshua Hay 	bool changed = false;
2002a251eee6SJoshua Hay 	struct device *dev;
2003a251eee6SJoshua Hay 	int err;
2004a251eee6SJoshua Hay 
2005a251eee6SJoshua Hay 	adapter = np->adapter;
2006a251eee6SJoshua Hay 	dev = &adapter->pdev->dev;
2007a251eee6SJoshua Hay 
2008a251eee6SJoshua Hay 	if (idpf_is_cap_ena(adapter, IDPF_OTHER_CAPS, VIRTCHNL2_CAP_MACFILTER)) {
2009a251eee6SJoshua Hay 		__dev_uc_sync(netdev, idpf_addr_sync, idpf_addr_unsync);
2010a251eee6SJoshua Hay 		__dev_mc_sync(netdev, idpf_addr_sync, idpf_addr_unsync);
2011a251eee6SJoshua Hay 	}
2012a251eee6SJoshua Hay 
2013a251eee6SJoshua Hay 	if (!idpf_is_cap_ena(adapter, IDPF_OTHER_CAPS, VIRTCHNL2_CAP_PROMISC))
2014a251eee6SJoshua Hay 		return;
2015a251eee6SJoshua Hay 
2016a251eee6SJoshua Hay 	config_data = &adapter->vport_config[np->vport_idx]->user_config;
2017a251eee6SJoshua Hay 	/* IFF_PROMISC enables both unicast and multicast promiscuous,
2018a251eee6SJoshua Hay 	 * while IFF_ALLMULTI only enables multicast such that:
2019a251eee6SJoshua Hay 	 *
2020a251eee6SJoshua Hay 	 * promisc  + allmulti		= unicast | multicast
2021a251eee6SJoshua Hay 	 * promisc  + !allmulti		= unicast | multicast
2022a251eee6SJoshua Hay 	 * !promisc + allmulti		= multicast
2023a251eee6SJoshua Hay 	 */
2024a251eee6SJoshua Hay 	if ((netdev->flags & IFF_PROMISC) &&
2025a251eee6SJoshua Hay 	    !test_and_set_bit(__IDPF_PROMISC_UC, config_data->user_flags)) {
2026a251eee6SJoshua Hay 		changed = true;
2027a251eee6SJoshua Hay 		dev_info(&adapter->pdev->dev, "Entering promiscuous mode\n");
2028a251eee6SJoshua Hay 		if (!test_and_set_bit(__IDPF_PROMISC_MC, adapter->flags))
2029a251eee6SJoshua Hay 			dev_info(dev, "Entering multicast promiscuous mode\n");
2030a251eee6SJoshua Hay 	}
2031a251eee6SJoshua Hay 
2032a251eee6SJoshua Hay 	if (!(netdev->flags & IFF_PROMISC) &&
2033a251eee6SJoshua Hay 	    test_and_clear_bit(__IDPF_PROMISC_UC, config_data->user_flags)) {
2034a251eee6SJoshua Hay 		changed = true;
2035a251eee6SJoshua Hay 		dev_info(dev, "Leaving promiscuous mode\n");
2036a251eee6SJoshua Hay 	}
2037a251eee6SJoshua Hay 
2038a251eee6SJoshua Hay 	if (netdev->flags & IFF_ALLMULTI &&
2039a251eee6SJoshua Hay 	    !test_and_set_bit(__IDPF_PROMISC_MC, config_data->user_flags)) {
2040a251eee6SJoshua Hay 		changed = true;
2041a251eee6SJoshua Hay 		dev_info(dev, "Entering multicast promiscuous mode\n");
2042a251eee6SJoshua Hay 	}
2043a251eee6SJoshua Hay 
2044a251eee6SJoshua Hay 	if (!(netdev->flags & (IFF_ALLMULTI | IFF_PROMISC)) &&
2045a251eee6SJoshua Hay 	    test_and_clear_bit(__IDPF_PROMISC_MC, config_data->user_flags)) {
2046a251eee6SJoshua Hay 		changed = true;
2047a251eee6SJoshua Hay 		dev_info(dev, "Leaving multicast promiscuous mode\n");
2048a251eee6SJoshua Hay 	}
2049a251eee6SJoshua Hay 
2050a251eee6SJoshua Hay 	if (!changed)
2051a251eee6SJoshua Hay 		return;
2052a251eee6SJoshua Hay 
2053a251eee6SJoshua Hay 	err = idpf_set_promiscuous(adapter, config_data, np->vport_id);
2054a251eee6SJoshua Hay 	if (err)
2055a251eee6SJoshua Hay 		dev_err(dev, "Failed to set promiscuous mode: %d\n", err);
2056a251eee6SJoshua Hay }
2057a251eee6SJoshua Hay 
2058a251eee6SJoshua Hay /**
2059a251eee6SJoshua Hay  * idpf_vport_manage_rss_lut - disable/enable RSS
2060a251eee6SJoshua Hay  * @vport: the vport being changed
2061a251eee6SJoshua Hay  *
2062a251eee6SJoshua Hay  * In the event of disable request for RSS, this function will zero out RSS
2063a251eee6SJoshua Hay  * LUT, while in the event of enable request for RSS, it will reconfigure RSS
2064a251eee6SJoshua Hay  * LUT with the default LUT configuration.
2065a251eee6SJoshua Hay  */
idpf_vport_manage_rss_lut(struct idpf_vport * vport)2066a251eee6SJoshua Hay static int idpf_vport_manage_rss_lut(struct idpf_vport *vport)
2067a251eee6SJoshua Hay {
2068a251eee6SJoshua Hay 	bool ena = idpf_is_feature_ena(vport, NETIF_F_RXHASH);
2069a251eee6SJoshua Hay 	struct idpf_rss_data *rss_data;
2070a251eee6SJoshua Hay 	u16 idx = vport->idx;
2071a251eee6SJoshua Hay 	int lut_size;
2072a251eee6SJoshua Hay 
2073a251eee6SJoshua Hay 	rss_data = &vport->adapter->vport_config[idx]->user_config.rss_data;
2074a251eee6SJoshua Hay 	lut_size = rss_data->rss_lut_size * sizeof(u32);
2075a251eee6SJoshua Hay 
2076a251eee6SJoshua Hay 	if (ena) {
2077a251eee6SJoshua Hay 		/* This will contain the default or user configured LUT */
2078a251eee6SJoshua Hay 		memcpy(rss_data->rss_lut, rss_data->cached_lut, lut_size);
2079a251eee6SJoshua Hay 	} else {
2080a251eee6SJoshua Hay 		/* Save a copy of the current LUT to be restored later if
2081a251eee6SJoshua Hay 		 * requested.
2082a251eee6SJoshua Hay 		 */
2083a251eee6SJoshua Hay 		memcpy(rss_data->cached_lut, rss_data->rss_lut, lut_size);
2084a251eee6SJoshua Hay 
2085a251eee6SJoshua Hay 		/* Zero out the current LUT to disable */
2086a251eee6SJoshua Hay 		memset(rss_data->rss_lut, 0, lut_size);
2087a251eee6SJoshua Hay 	}
2088a251eee6SJoshua Hay 
2089a251eee6SJoshua Hay 	return idpf_config_rss(vport);
2090a251eee6SJoshua Hay }
2091a251eee6SJoshua Hay 
2092a251eee6SJoshua Hay /**
2093a251eee6SJoshua Hay  * idpf_set_features - set the netdev feature flags
2094a251eee6SJoshua Hay  * @netdev: ptr to the netdev being adjusted
2095a251eee6SJoshua Hay  * @features: the feature set that the stack is suggesting
2096a251eee6SJoshua Hay  */
idpf_set_features(struct net_device * netdev,netdev_features_t features)2097a251eee6SJoshua Hay static int idpf_set_features(struct net_device *netdev,
2098a251eee6SJoshua Hay 			     netdev_features_t features)
2099a251eee6SJoshua Hay {
2100a251eee6SJoshua Hay 	netdev_features_t changed = netdev->features ^ features;
2101a251eee6SJoshua Hay 	struct idpf_adapter *adapter;
2102a251eee6SJoshua Hay 	struct idpf_vport *vport;
2103a251eee6SJoshua Hay 	int err = 0;
2104a251eee6SJoshua Hay 
2105a251eee6SJoshua Hay 	idpf_vport_ctrl_lock(netdev);
2106a251eee6SJoshua Hay 	vport = idpf_netdev_to_vport(netdev);
2107a251eee6SJoshua Hay 
2108a251eee6SJoshua Hay 	adapter = vport->adapter;
2109a251eee6SJoshua Hay 
2110a251eee6SJoshua Hay 	if (idpf_is_reset_in_prog(adapter)) {
2111a251eee6SJoshua Hay 		dev_err(&adapter->pdev->dev, "Device is resetting, changing netdev features temporarily unavailable.\n");
2112a251eee6SJoshua Hay 		err = -EBUSY;
2113a251eee6SJoshua Hay 		goto unlock_mutex;
2114a251eee6SJoshua Hay 	}
2115a251eee6SJoshua Hay 
2116a251eee6SJoshua Hay 	if (changed & NETIF_F_RXHASH) {
2117a251eee6SJoshua Hay 		netdev->features ^= NETIF_F_RXHASH;
2118a251eee6SJoshua Hay 		err = idpf_vport_manage_rss_lut(vport);
2119a251eee6SJoshua Hay 		if (err)
2120a251eee6SJoshua Hay 			goto unlock_mutex;
2121a251eee6SJoshua Hay 	}
2122a251eee6SJoshua Hay 
2123a251eee6SJoshua Hay 	if (changed & NETIF_F_GRO_HW) {
2124a251eee6SJoshua Hay 		netdev->features ^= NETIF_F_GRO_HW;
2125a251eee6SJoshua Hay 		err = idpf_initiate_soft_reset(vport, IDPF_SR_RSC_CHANGE);
2126a251eee6SJoshua Hay 		if (err)
2127a251eee6SJoshua Hay 			goto unlock_mutex;
2128a251eee6SJoshua Hay 	}
2129a251eee6SJoshua Hay 
2130a251eee6SJoshua Hay 	if (changed & NETIF_F_LOOPBACK) {
2131a251eee6SJoshua Hay 		netdev->features ^= NETIF_F_LOOPBACK;
2132a251eee6SJoshua Hay 		err = idpf_send_ena_dis_loopback_msg(vport);
2133a251eee6SJoshua Hay 	}
2134a251eee6SJoshua Hay 
2135a251eee6SJoshua Hay unlock_mutex:
2136a251eee6SJoshua Hay 	idpf_vport_ctrl_unlock(netdev);
2137a251eee6SJoshua Hay 
2138a251eee6SJoshua Hay 	return err;
2139a251eee6SJoshua Hay }
2140a251eee6SJoshua Hay 
2141a251eee6SJoshua Hay /**
21421c325aacSAlan Brady  * idpf_open - Called when a network interface becomes active
21431c325aacSAlan Brady  * @netdev: network interface device structure
21441c325aacSAlan Brady  *
21451c325aacSAlan Brady  * The open entry point is called when a network interface is made
21461c325aacSAlan Brady  * active by the system (IFF_UP).  At this point all resources needed
21471c325aacSAlan Brady  * for transmit and receive operations are allocated, the interrupt
21481c325aacSAlan Brady  * handler is registered with the OS, the netdev watchdog is enabled,
21491c325aacSAlan Brady  * and the stack is notified that the interface is ready.
21501c325aacSAlan Brady  *
21511c325aacSAlan Brady  * Returns 0 on success, negative value on failure
21521c325aacSAlan Brady  */
idpf_open(struct net_device * netdev)21531c325aacSAlan Brady static int idpf_open(struct net_device *netdev)
21541c325aacSAlan Brady {
21551c325aacSAlan Brady 	struct idpf_vport *vport;
21561c325aacSAlan Brady 	int err;
21571c325aacSAlan Brady 
21581c325aacSAlan Brady 	idpf_vport_ctrl_lock(netdev);
21591c325aacSAlan Brady 	vport = idpf_netdev_to_vport(netdev);
21601c325aacSAlan Brady 
2161f01032a2SAlexander Lobakin 	err = idpf_vport_open(vport);
21621c325aacSAlan Brady 
21631c325aacSAlan Brady 	idpf_vport_ctrl_unlock(netdev);
21641c325aacSAlan Brady 
21651c325aacSAlan Brady 	return err;
21661c325aacSAlan Brady }
21671c325aacSAlan Brady 
21681c325aacSAlan Brady /**
2169a251eee6SJoshua Hay  * idpf_change_mtu - NDO callback to change the MTU
2170a251eee6SJoshua Hay  * @netdev: network interface device structure
2171a251eee6SJoshua Hay  * @new_mtu: new value for maximum frame size
2172a251eee6SJoshua Hay  *
2173a251eee6SJoshua Hay  * Returns 0 on success, negative on failure
2174a251eee6SJoshua Hay  */
idpf_change_mtu(struct net_device * netdev,int new_mtu)2175a251eee6SJoshua Hay static int idpf_change_mtu(struct net_device *netdev, int new_mtu)
2176a251eee6SJoshua Hay {
2177a251eee6SJoshua Hay 	struct idpf_vport *vport;
2178a251eee6SJoshua Hay 	int err;
2179a251eee6SJoshua Hay 
2180a251eee6SJoshua Hay 	idpf_vport_ctrl_lock(netdev);
2181a251eee6SJoshua Hay 	vport = idpf_netdev_to_vport(netdev);
2182a251eee6SJoshua Hay 
21831eb2cdedSEric Dumazet 	WRITE_ONCE(netdev->mtu, new_mtu);
2184a251eee6SJoshua Hay 
2185a251eee6SJoshua Hay 	err = idpf_initiate_soft_reset(vport, IDPF_SR_MTU_CHANGE);
2186a251eee6SJoshua Hay 
2187a251eee6SJoshua Hay 	idpf_vport_ctrl_unlock(netdev);
2188a251eee6SJoshua Hay 
2189a251eee6SJoshua Hay 	return err;
2190a251eee6SJoshua Hay }
2191a251eee6SJoshua Hay 
2192a251eee6SJoshua Hay /**
2193a251eee6SJoshua Hay  * idpf_features_check - Validate packet conforms to limits
2194a251eee6SJoshua Hay  * @skb: skb buffer
2195a251eee6SJoshua Hay  * @netdev: This port's netdev
2196a251eee6SJoshua Hay  * @features: Offload features that the stack believes apply
2197a251eee6SJoshua Hay  */
idpf_features_check(struct sk_buff * skb,struct net_device * netdev,netdev_features_t features)2198a251eee6SJoshua Hay static netdev_features_t idpf_features_check(struct sk_buff *skb,
2199a251eee6SJoshua Hay 					     struct net_device *netdev,
2200a251eee6SJoshua Hay 					     netdev_features_t features)
2201a251eee6SJoshua Hay {
2202a251eee6SJoshua Hay 	struct idpf_vport *vport = idpf_netdev_to_vport(netdev);
2203a251eee6SJoshua Hay 	struct idpf_adapter *adapter = vport->adapter;
2204a251eee6SJoshua Hay 	size_t len;
2205a251eee6SJoshua Hay 
2206a251eee6SJoshua Hay 	/* No point in doing any of this if neither checksum nor GSO are
2207a251eee6SJoshua Hay 	 * being requested for this frame.  We can rule out both by just
2208a251eee6SJoshua Hay 	 * checking for CHECKSUM_PARTIAL
2209a251eee6SJoshua Hay 	 */
2210a251eee6SJoshua Hay 	if (skb->ip_summed != CHECKSUM_PARTIAL)
2211a251eee6SJoshua Hay 		return features;
2212a251eee6SJoshua Hay 
2213a251eee6SJoshua Hay 	/* We cannot support GSO if the MSS is going to be less than
2214a251eee6SJoshua Hay 	 * 88 bytes. If it is then we need to drop support for GSO.
2215a251eee6SJoshua Hay 	 */
2216a251eee6SJoshua Hay 	if (skb_is_gso(skb) &&
2217a251eee6SJoshua Hay 	    (skb_shinfo(skb)->gso_size < IDPF_TX_TSO_MIN_MSS))
2218a251eee6SJoshua Hay 		features &= ~NETIF_F_GSO_MASK;
2219a251eee6SJoshua Hay 
2220a251eee6SJoshua Hay 	/* Ensure MACLEN is <= 126 bytes (63 words) and not an odd size */
2221a251eee6SJoshua Hay 	len = skb_network_offset(skb);
2222a251eee6SJoshua Hay 	if (unlikely(len & ~(126)))
2223a251eee6SJoshua Hay 		goto unsupported;
2224a251eee6SJoshua Hay 
2225a251eee6SJoshua Hay 	len = skb_network_header_len(skb);
2226a251eee6SJoshua Hay 	if (unlikely(len > idpf_get_max_tx_hdr_size(adapter)))
2227a251eee6SJoshua Hay 		goto unsupported;
2228a251eee6SJoshua Hay 
2229a251eee6SJoshua Hay 	if (!skb->encapsulation)
2230a251eee6SJoshua Hay 		return features;
2231a251eee6SJoshua Hay 
2232a251eee6SJoshua Hay 	/* L4TUNLEN can support 127 words */
2233a251eee6SJoshua Hay 	len = skb_inner_network_header(skb) - skb_transport_header(skb);
2234a251eee6SJoshua Hay 	if (unlikely(len & ~(127 * 2)))
2235a251eee6SJoshua Hay 		goto unsupported;
2236a251eee6SJoshua Hay 
2237a251eee6SJoshua Hay 	/* IPLEN can support at most 127 dwords */
2238a251eee6SJoshua Hay 	len = skb_inner_network_header_len(skb);
2239a251eee6SJoshua Hay 	if (unlikely(len > idpf_get_max_tx_hdr_size(adapter)))
2240a251eee6SJoshua Hay 		goto unsupported;
2241a251eee6SJoshua Hay 
2242a251eee6SJoshua Hay 	/* No need to validate L4LEN as TCP is the only protocol with a
2243a251eee6SJoshua Hay 	 * a flexible value and we support all possible values supported
2244a251eee6SJoshua Hay 	 * by TCP, which is at most 15 dwords
2245a251eee6SJoshua Hay 	 */
2246a251eee6SJoshua Hay 
2247a251eee6SJoshua Hay 	return features;
2248a251eee6SJoshua Hay 
2249a251eee6SJoshua Hay unsupported:
2250a251eee6SJoshua Hay 	return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
2251a251eee6SJoshua Hay }
2252a251eee6SJoshua Hay 
2253a251eee6SJoshua Hay /**
2254a251eee6SJoshua Hay  * idpf_set_mac - NDO callback to set port mac address
2255a251eee6SJoshua Hay  * @netdev: network interface device structure
2256a251eee6SJoshua Hay  * @p: pointer to an address structure
2257a251eee6SJoshua Hay  *
2258a251eee6SJoshua Hay  * Returns 0 on success, negative on failure
2259a251eee6SJoshua Hay  **/
idpf_set_mac(struct net_device * netdev,void * p)2260a251eee6SJoshua Hay static int idpf_set_mac(struct net_device *netdev, void *p)
2261a251eee6SJoshua Hay {
2262a251eee6SJoshua Hay 	struct idpf_netdev_priv *np = netdev_priv(netdev);
2263a251eee6SJoshua Hay 	struct idpf_vport_config *vport_config;
2264a251eee6SJoshua Hay 	struct sockaddr *addr = p;
2265a251eee6SJoshua Hay 	struct idpf_vport *vport;
2266a251eee6SJoshua Hay 	int err = 0;
2267a251eee6SJoshua Hay 
2268a251eee6SJoshua Hay 	idpf_vport_ctrl_lock(netdev);
2269a251eee6SJoshua Hay 	vport = idpf_netdev_to_vport(netdev);
2270a251eee6SJoshua Hay 
2271a251eee6SJoshua Hay 	if (!idpf_is_cap_ena(vport->adapter, IDPF_OTHER_CAPS,
2272a251eee6SJoshua Hay 			     VIRTCHNL2_CAP_MACFILTER)) {
2273a251eee6SJoshua Hay 		dev_info(&vport->adapter->pdev->dev, "Setting MAC address is not supported\n");
2274a251eee6SJoshua Hay 		err = -EOPNOTSUPP;
2275a251eee6SJoshua Hay 		goto unlock_mutex;
2276a251eee6SJoshua Hay 	}
2277a251eee6SJoshua Hay 
2278a251eee6SJoshua Hay 	if (!is_valid_ether_addr(addr->sa_data)) {
2279a251eee6SJoshua Hay 		dev_info(&vport->adapter->pdev->dev, "Invalid MAC address: %pM\n",
2280a251eee6SJoshua Hay 			 addr->sa_data);
2281a251eee6SJoshua Hay 		err = -EADDRNOTAVAIL;
2282a251eee6SJoshua Hay 		goto unlock_mutex;
2283a251eee6SJoshua Hay 	}
2284a251eee6SJoshua Hay 
2285a251eee6SJoshua Hay 	if (ether_addr_equal(netdev->dev_addr, addr->sa_data))
2286a251eee6SJoshua Hay 		goto unlock_mutex;
2287a251eee6SJoshua Hay 
2288a251eee6SJoshua Hay 	vport_config = vport->adapter->vport_config[vport->idx];
2289a251eee6SJoshua Hay 	err = idpf_add_mac_filter(vport, np, addr->sa_data, false);
2290a251eee6SJoshua Hay 	if (err) {
2291a251eee6SJoshua Hay 		__idpf_del_mac_filter(vport_config, addr->sa_data);
2292a251eee6SJoshua Hay 		goto unlock_mutex;
2293a251eee6SJoshua Hay 	}
2294a251eee6SJoshua Hay 
2295a251eee6SJoshua Hay 	if (is_valid_ether_addr(vport->default_mac_addr))
2296a251eee6SJoshua Hay 		idpf_del_mac_filter(vport, np, vport->default_mac_addr, false);
2297a251eee6SJoshua Hay 
2298a251eee6SJoshua Hay 	ether_addr_copy(vport->default_mac_addr, addr->sa_data);
2299a251eee6SJoshua Hay 	eth_hw_addr_set(netdev, addr->sa_data);
2300a251eee6SJoshua Hay 
2301a251eee6SJoshua Hay unlock_mutex:
2302a251eee6SJoshua Hay 	idpf_vport_ctrl_unlock(netdev);
2303a251eee6SJoshua Hay 
2304a251eee6SJoshua Hay 	return err;
2305a251eee6SJoshua Hay }
2306a251eee6SJoshua Hay 
2307a251eee6SJoshua Hay /**
23088077c727SJoshua Hay  * idpf_alloc_dma_mem - Allocate dma memory
23098077c727SJoshua Hay  * @hw: pointer to hw struct
23108077c727SJoshua Hay  * @mem: pointer to dma_mem struct
23118077c727SJoshua Hay  * @size: size of the memory to allocate
23128077c727SJoshua Hay  */
idpf_alloc_dma_mem(struct idpf_hw * hw,struct idpf_dma_mem * mem,u64 size)23138077c727SJoshua Hay void *idpf_alloc_dma_mem(struct idpf_hw *hw, struct idpf_dma_mem *mem, u64 size)
23148077c727SJoshua Hay {
23158077c727SJoshua Hay 	struct idpf_adapter *adapter = hw->back;
23168077c727SJoshua Hay 	size_t sz = ALIGN(size, 4096);
23178077c727SJoshua Hay 
23188077c727SJoshua Hay 	mem->va = dma_alloc_coherent(&adapter->pdev->dev, sz,
23198077c727SJoshua Hay 				     &mem->pa, GFP_KERNEL);
23208077c727SJoshua Hay 	mem->size = sz;
23218077c727SJoshua Hay 
23228077c727SJoshua Hay 	return mem->va;
23238077c727SJoshua Hay }
23248077c727SJoshua Hay 
23258077c727SJoshua Hay /**
23268077c727SJoshua Hay  * idpf_free_dma_mem - Free the allocated dma memory
23278077c727SJoshua Hay  * @hw: pointer to hw struct
23288077c727SJoshua Hay  * @mem: pointer to dma_mem struct
23298077c727SJoshua Hay  */
idpf_free_dma_mem(struct idpf_hw * hw,struct idpf_dma_mem * mem)23308077c727SJoshua Hay void idpf_free_dma_mem(struct idpf_hw *hw, struct idpf_dma_mem *mem)
23318077c727SJoshua Hay {
23328077c727SJoshua Hay 	struct idpf_adapter *adapter = hw->back;
23338077c727SJoshua Hay 
23348077c727SJoshua Hay 	dma_free_coherent(&adapter->pdev->dev, mem->size,
23358077c727SJoshua Hay 			  mem->va, mem->pa);
23368077c727SJoshua Hay 	mem->size = 0;
23378077c727SJoshua Hay 	mem->va = NULL;
23388077c727SJoshua Hay 	mem->pa = 0;
23398077c727SJoshua Hay }
23401c325aacSAlan Brady 
234114f662b4SAlexander Lobakin static const struct net_device_ops idpf_netdev_ops = {
23421c325aacSAlan Brady 	.ndo_open = idpf_open,
23431c325aacSAlan Brady 	.ndo_stop = idpf_stop,
234414f662b4SAlexander Lobakin 	.ndo_start_xmit = idpf_tx_start,
2345a251eee6SJoshua Hay 	.ndo_features_check = idpf_features_check,
2346a251eee6SJoshua Hay 	.ndo_set_rx_mode = idpf_set_rx_mode,
2347a251eee6SJoshua Hay 	.ndo_validate_addr = eth_validate_addr,
2348a251eee6SJoshua Hay 	.ndo_set_mac_address = idpf_set_mac,
2349a251eee6SJoshua Hay 	.ndo_change_mtu = idpf_change_mtu,
2350a251eee6SJoshua Hay 	.ndo_get_stats64 = idpf_get_stats64,
2351a251eee6SJoshua Hay 	.ndo_set_features = idpf_set_features,
2352a251eee6SJoshua Hay 	.ndo_tx_timeout = idpf_tx_timeout,
23531c325aacSAlan Brady };
2354