xref: /linux/drivers/net/ethernet/intel/idpf/idpf_lib.c (revision 95af467d9a4e3be0204a51e640509a701bbe4581)
18077c727SJoshua Hay // SPDX-License-Identifier: GPL-2.0-only
28077c727SJoshua Hay /* Copyright (C) 2023 Intel Corporation */
38077c727SJoshua Hay 
48077c727SJoshua Hay #include "idpf.h"
58077c727SJoshua Hay 
61c325aacSAlan Brady static const struct net_device_ops idpf_netdev_ops_splitq;
71c325aacSAlan Brady static const struct net_device_ops idpf_netdev_ops_singleq;
81c325aacSAlan Brady 
94930fbf4SPavan Kumar Linga const char * const idpf_vport_vc_state_str[] = {
104930fbf4SPavan Kumar Linga 	IDPF_FOREACH_VPORT_VC_STATE(IDPF_GEN_STRING)
114930fbf4SPavan Kumar Linga };
124930fbf4SPavan Kumar Linga 
134930fbf4SPavan Kumar Linga /**
144930fbf4SPavan Kumar Linga  * idpf_init_vector_stack - Fill the MSIX vector stack with vector index
154930fbf4SPavan Kumar Linga  * @adapter: private data struct
164930fbf4SPavan Kumar Linga  *
174930fbf4SPavan Kumar Linga  * Return 0 on success, error on failure
184930fbf4SPavan Kumar Linga  */
194930fbf4SPavan Kumar Linga static int idpf_init_vector_stack(struct idpf_adapter *adapter)
204930fbf4SPavan Kumar Linga {
214930fbf4SPavan Kumar Linga 	struct idpf_vector_lifo *stack;
224930fbf4SPavan Kumar Linga 	u16 min_vec;
234930fbf4SPavan Kumar Linga 	u32 i;
244930fbf4SPavan Kumar Linga 
254930fbf4SPavan Kumar Linga 	mutex_lock(&adapter->vector_lock);
264930fbf4SPavan Kumar Linga 	min_vec = adapter->num_msix_entries - adapter->num_avail_msix;
274930fbf4SPavan Kumar Linga 	stack = &adapter->vector_stack;
284930fbf4SPavan Kumar Linga 	stack->size = adapter->num_msix_entries;
294930fbf4SPavan Kumar Linga 	/* set the base and top to point at start of the 'free pool' to
304930fbf4SPavan Kumar Linga 	 * distribute the unused vectors on-demand basis
314930fbf4SPavan Kumar Linga 	 */
324930fbf4SPavan Kumar Linga 	stack->base = min_vec;
334930fbf4SPavan Kumar Linga 	stack->top = min_vec;
344930fbf4SPavan Kumar Linga 
354930fbf4SPavan Kumar Linga 	stack->vec_idx = kcalloc(stack->size, sizeof(u16), GFP_KERNEL);
364930fbf4SPavan Kumar Linga 	if (!stack->vec_idx) {
374930fbf4SPavan Kumar Linga 		mutex_unlock(&adapter->vector_lock);
384930fbf4SPavan Kumar Linga 
394930fbf4SPavan Kumar Linga 		return -ENOMEM;
404930fbf4SPavan Kumar Linga 	}
414930fbf4SPavan Kumar Linga 
424930fbf4SPavan Kumar Linga 	for (i = 0; i < stack->size; i++)
434930fbf4SPavan Kumar Linga 		stack->vec_idx[i] = i;
444930fbf4SPavan Kumar Linga 
454930fbf4SPavan Kumar Linga 	mutex_unlock(&adapter->vector_lock);
464930fbf4SPavan Kumar Linga 
474930fbf4SPavan Kumar Linga 	return 0;
484930fbf4SPavan Kumar Linga }
494930fbf4SPavan Kumar Linga 
504930fbf4SPavan Kumar Linga /**
514930fbf4SPavan Kumar Linga  * idpf_deinit_vector_stack - zero out the MSIX vector stack
524930fbf4SPavan Kumar Linga  * @adapter: private data struct
534930fbf4SPavan Kumar Linga  */
544930fbf4SPavan Kumar Linga static void idpf_deinit_vector_stack(struct idpf_adapter *adapter)
554930fbf4SPavan Kumar Linga {
564930fbf4SPavan Kumar Linga 	struct idpf_vector_lifo *stack;
574930fbf4SPavan Kumar Linga 
584930fbf4SPavan Kumar Linga 	mutex_lock(&adapter->vector_lock);
594930fbf4SPavan Kumar Linga 	stack = &adapter->vector_stack;
604930fbf4SPavan Kumar Linga 	kfree(stack->vec_idx);
614930fbf4SPavan Kumar Linga 	stack->vec_idx = NULL;
624930fbf4SPavan Kumar Linga 	mutex_unlock(&adapter->vector_lock);
634930fbf4SPavan Kumar Linga }
644930fbf4SPavan Kumar Linga 
654930fbf4SPavan Kumar Linga /**
664930fbf4SPavan Kumar Linga  * idpf_mb_intr_rel_irq - Free the IRQ association with the OS
674930fbf4SPavan Kumar Linga  * @adapter: adapter structure
684930fbf4SPavan Kumar Linga  *
694930fbf4SPavan Kumar Linga  * This will also disable interrupt mode and queue up mailbox task. Mailbox
704930fbf4SPavan Kumar Linga  * task will reschedule itself if not in interrupt mode.
714930fbf4SPavan Kumar Linga  */
724930fbf4SPavan Kumar Linga static void idpf_mb_intr_rel_irq(struct idpf_adapter *adapter)
734930fbf4SPavan Kumar Linga {
744930fbf4SPavan Kumar Linga 	clear_bit(IDPF_MB_INTR_MODE, adapter->flags);
754930fbf4SPavan Kumar Linga 	free_irq(adapter->msix_entries[0].vector, adapter);
764930fbf4SPavan Kumar Linga 	queue_delayed_work(adapter->mbx_wq, &adapter->mbx_task, 0);
774930fbf4SPavan Kumar Linga }
784930fbf4SPavan Kumar Linga 
794930fbf4SPavan Kumar Linga /**
804930fbf4SPavan Kumar Linga  * idpf_intr_rel - Release interrupt capabilities and free memory
814930fbf4SPavan Kumar Linga  * @adapter: adapter to disable interrupts on
824930fbf4SPavan Kumar Linga  */
834930fbf4SPavan Kumar Linga void idpf_intr_rel(struct idpf_adapter *adapter)
844930fbf4SPavan Kumar Linga {
854930fbf4SPavan Kumar Linga 	int err;
864930fbf4SPavan Kumar Linga 
874930fbf4SPavan Kumar Linga 	if (!adapter->msix_entries)
884930fbf4SPavan Kumar Linga 		return;
894930fbf4SPavan Kumar Linga 
904930fbf4SPavan Kumar Linga 	idpf_mb_intr_rel_irq(adapter);
914930fbf4SPavan Kumar Linga 	pci_free_irq_vectors(adapter->pdev);
924930fbf4SPavan Kumar Linga 
934930fbf4SPavan Kumar Linga 	err = idpf_send_dealloc_vectors_msg(adapter);
944930fbf4SPavan Kumar Linga 	if (err)
954930fbf4SPavan Kumar Linga 		dev_err(&adapter->pdev->dev,
964930fbf4SPavan Kumar Linga 			"Failed to deallocate vectors: %d\n", err);
974930fbf4SPavan Kumar Linga 
984930fbf4SPavan Kumar Linga 	idpf_deinit_vector_stack(adapter);
994930fbf4SPavan Kumar Linga 	kfree(adapter->msix_entries);
1004930fbf4SPavan Kumar Linga 	adapter->msix_entries = NULL;
1014930fbf4SPavan Kumar Linga }
1024930fbf4SPavan Kumar Linga 
1034930fbf4SPavan Kumar Linga /**
1044930fbf4SPavan Kumar Linga  * idpf_mb_intr_clean - Interrupt handler for the mailbox
1054930fbf4SPavan Kumar Linga  * @irq: interrupt number
1064930fbf4SPavan Kumar Linga  * @data: pointer to the adapter structure
1074930fbf4SPavan Kumar Linga  */
1084930fbf4SPavan Kumar Linga static irqreturn_t idpf_mb_intr_clean(int __always_unused irq, void *data)
1094930fbf4SPavan Kumar Linga {
1104930fbf4SPavan Kumar Linga 	struct idpf_adapter *adapter = (struct idpf_adapter *)data;
1114930fbf4SPavan Kumar Linga 
1124930fbf4SPavan Kumar Linga 	queue_delayed_work(adapter->mbx_wq, &adapter->mbx_task, 0);
1134930fbf4SPavan Kumar Linga 
1144930fbf4SPavan Kumar Linga 	return IRQ_HANDLED;
1154930fbf4SPavan Kumar Linga }
1164930fbf4SPavan Kumar Linga 
1174930fbf4SPavan Kumar Linga /**
1184930fbf4SPavan Kumar Linga  * idpf_mb_irq_enable - Enable MSIX interrupt for the mailbox
1194930fbf4SPavan Kumar Linga  * @adapter: adapter to get the hardware address for register write
1204930fbf4SPavan Kumar Linga  */
1214930fbf4SPavan Kumar Linga static void idpf_mb_irq_enable(struct idpf_adapter *adapter)
1224930fbf4SPavan Kumar Linga {
1234930fbf4SPavan Kumar Linga 	struct idpf_intr_reg *intr = &adapter->mb_vector.intr_reg;
1244930fbf4SPavan Kumar Linga 	u32 val;
1254930fbf4SPavan Kumar Linga 
1264930fbf4SPavan Kumar Linga 	val = intr->dyn_ctl_intena_m | intr->dyn_ctl_itridx_m;
1274930fbf4SPavan Kumar Linga 	writel(val, intr->dyn_ctl);
1284930fbf4SPavan Kumar Linga 	writel(intr->icr_ena_ctlq_m, intr->icr_ena);
1294930fbf4SPavan Kumar Linga }
1304930fbf4SPavan Kumar Linga 
1314930fbf4SPavan Kumar Linga /**
1324930fbf4SPavan Kumar Linga  * idpf_mb_intr_req_irq - Request irq for the mailbox interrupt
1334930fbf4SPavan Kumar Linga  * @adapter: adapter structure to pass to the mailbox irq handler
1344930fbf4SPavan Kumar Linga  */
1354930fbf4SPavan Kumar Linga static int idpf_mb_intr_req_irq(struct idpf_adapter *adapter)
1364930fbf4SPavan Kumar Linga {
1374930fbf4SPavan Kumar Linga 	struct idpf_q_vector *mb_vector = &adapter->mb_vector;
1384930fbf4SPavan Kumar Linga 	int irq_num, mb_vidx = 0, err;
1394930fbf4SPavan Kumar Linga 
1404930fbf4SPavan Kumar Linga 	irq_num = adapter->msix_entries[mb_vidx].vector;
1414930fbf4SPavan Kumar Linga 	mb_vector->name = kasprintf(GFP_KERNEL, "%s-%s-%d",
1424930fbf4SPavan Kumar Linga 				    dev_driver_string(&adapter->pdev->dev),
1434930fbf4SPavan Kumar Linga 				    "Mailbox", mb_vidx);
1444930fbf4SPavan Kumar Linga 	err = request_irq(irq_num, adapter->irq_mb_handler, 0,
1454930fbf4SPavan Kumar Linga 			  mb_vector->name, adapter);
1464930fbf4SPavan Kumar Linga 	if (err) {
1474930fbf4SPavan Kumar Linga 		dev_err(&adapter->pdev->dev,
1484930fbf4SPavan Kumar Linga 			"IRQ request for mailbox failed, error: %d\n", err);
1494930fbf4SPavan Kumar Linga 
1504930fbf4SPavan Kumar Linga 		return err;
1514930fbf4SPavan Kumar Linga 	}
1524930fbf4SPavan Kumar Linga 
1534930fbf4SPavan Kumar Linga 	set_bit(IDPF_MB_INTR_MODE, adapter->flags);
1544930fbf4SPavan Kumar Linga 
1554930fbf4SPavan Kumar Linga 	return 0;
1564930fbf4SPavan Kumar Linga }
1574930fbf4SPavan Kumar Linga 
1584930fbf4SPavan Kumar Linga /**
1594930fbf4SPavan Kumar Linga  * idpf_set_mb_vec_id - Set vector index for mailbox
1604930fbf4SPavan Kumar Linga  * @adapter: adapter structure to access the vector chunks
1614930fbf4SPavan Kumar Linga  *
1624930fbf4SPavan Kumar Linga  * The first vector id in the requested vector chunks from the CP is for
1634930fbf4SPavan Kumar Linga  * the mailbox
1644930fbf4SPavan Kumar Linga  */
1654930fbf4SPavan Kumar Linga static void idpf_set_mb_vec_id(struct idpf_adapter *adapter)
1664930fbf4SPavan Kumar Linga {
1674930fbf4SPavan Kumar Linga 	if (adapter->req_vec_chunks)
1684930fbf4SPavan Kumar Linga 		adapter->mb_vector.v_idx =
1694930fbf4SPavan Kumar Linga 			le16_to_cpu(adapter->caps.mailbox_vector_id);
1704930fbf4SPavan Kumar Linga 	else
1714930fbf4SPavan Kumar Linga 		adapter->mb_vector.v_idx = 0;
1724930fbf4SPavan Kumar Linga }
1734930fbf4SPavan Kumar Linga 
1744930fbf4SPavan Kumar Linga /**
1754930fbf4SPavan Kumar Linga  * idpf_mb_intr_init - Initialize the mailbox interrupt
1764930fbf4SPavan Kumar Linga  * @adapter: adapter structure to store the mailbox vector
1774930fbf4SPavan Kumar Linga  */
1784930fbf4SPavan Kumar Linga static int idpf_mb_intr_init(struct idpf_adapter *adapter)
1794930fbf4SPavan Kumar Linga {
1804930fbf4SPavan Kumar Linga 	adapter->dev_ops.reg_ops.mb_intr_reg_init(adapter);
1814930fbf4SPavan Kumar Linga 	adapter->irq_mb_handler = idpf_mb_intr_clean;
1824930fbf4SPavan Kumar Linga 
1834930fbf4SPavan Kumar Linga 	return idpf_mb_intr_req_irq(adapter);
1844930fbf4SPavan Kumar Linga }
1854930fbf4SPavan Kumar Linga 
1864930fbf4SPavan Kumar Linga /**
1874930fbf4SPavan Kumar Linga  * idpf_intr_req - Request interrupt capabilities
1884930fbf4SPavan Kumar Linga  * @adapter: adapter to enable interrupts on
1894930fbf4SPavan Kumar Linga  *
1904930fbf4SPavan Kumar Linga  * Returns 0 on success, negative on failure
1914930fbf4SPavan Kumar Linga  */
1924930fbf4SPavan Kumar Linga int idpf_intr_req(struct idpf_adapter *adapter)
1934930fbf4SPavan Kumar Linga {
1944930fbf4SPavan Kumar Linga 	u16 default_vports = idpf_get_default_vports(adapter);
1954930fbf4SPavan Kumar Linga 	int num_q_vecs, total_vecs, num_vec_ids;
1964930fbf4SPavan Kumar Linga 	int min_vectors, v_actual, err;
1974930fbf4SPavan Kumar Linga 	unsigned int vector;
1984930fbf4SPavan Kumar Linga 	u16 *vecids;
1994930fbf4SPavan Kumar Linga 
2004930fbf4SPavan Kumar Linga 	total_vecs = idpf_get_reserved_vecs(adapter);
2014930fbf4SPavan Kumar Linga 	num_q_vecs = total_vecs - IDPF_MBX_Q_VEC;
2024930fbf4SPavan Kumar Linga 
2034930fbf4SPavan Kumar Linga 	err = idpf_send_alloc_vectors_msg(adapter, num_q_vecs);
2044930fbf4SPavan Kumar Linga 	if (err) {
2054930fbf4SPavan Kumar Linga 		dev_err(&adapter->pdev->dev,
2064930fbf4SPavan Kumar Linga 			"Failed to allocate %d vectors: %d\n", num_q_vecs, err);
2074930fbf4SPavan Kumar Linga 
2084930fbf4SPavan Kumar Linga 		return -EAGAIN;
2094930fbf4SPavan Kumar Linga 	}
2104930fbf4SPavan Kumar Linga 
2114930fbf4SPavan Kumar Linga 	min_vectors = IDPF_MBX_Q_VEC + IDPF_MIN_Q_VEC * default_vports;
2124930fbf4SPavan Kumar Linga 	v_actual = pci_alloc_irq_vectors(adapter->pdev, min_vectors,
2134930fbf4SPavan Kumar Linga 					 total_vecs, PCI_IRQ_MSIX);
2144930fbf4SPavan Kumar Linga 	if (v_actual < min_vectors) {
2154930fbf4SPavan Kumar Linga 		dev_err(&adapter->pdev->dev, "Failed to allocate MSIX vectors: %d\n",
2164930fbf4SPavan Kumar Linga 			v_actual);
2174930fbf4SPavan Kumar Linga 		err = -EAGAIN;
2184930fbf4SPavan Kumar Linga 		goto send_dealloc_vecs;
2194930fbf4SPavan Kumar Linga 	}
2204930fbf4SPavan Kumar Linga 
2214930fbf4SPavan Kumar Linga 	adapter->msix_entries = kcalloc(v_actual, sizeof(struct msix_entry),
2224930fbf4SPavan Kumar Linga 					GFP_KERNEL);
2234930fbf4SPavan Kumar Linga 
2244930fbf4SPavan Kumar Linga 	if (!adapter->msix_entries) {
2254930fbf4SPavan Kumar Linga 		err = -ENOMEM;
2264930fbf4SPavan Kumar Linga 		goto free_irq;
2274930fbf4SPavan Kumar Linga 	}
2284930fbf4SPavan Kumar Linga 
2294930fbf4SPavan Kumar Linga 	idpf_set_mb_vec_id(adapter);
2304930fbf4SPavan Kumar Linga 
2314930fbf4SPavan Kumar Linga 	vecids = kcalloc(total_vecs, sizeof(u16), GFP_KERNEL);
2324930fbf4SPavan Kumar Linga 	if (!vecids) {
2334930fbf4SPavan Kumar Linga 		err = -ENOMEM;
2344930fbf4SPavan Kumar Linga 		goto free_msix;
2354930fbf4SPavan Kumar Linga 	}
2364930fbf4SPavan Kumar Linga 
2374930fbf4SPavan Kumar Linga 	if (adapter->req_vec_chunks) {
2384930fbf4SPavan Kumar Linga 		struct virtchnl2_vector_chunks *vchunks;
2394930fbf4SPavan Kumar Linga 		struct virtchnl2_alloc_vectors *ac;
2404930fbf4SPavan Kumar Linga 
2414930fbf4SPavan Kumar Linga 		ac = adapter->req_vec_chunks;
2424930fbf4SPavan Kumar Linga 		vchunks = &ac->vchunks;
2434930fbf4SPavan Kumar Linga 
2444930fbf4SPavan Kumar Linga 		num_vec_ids = idpf_get_vec_ids(adapter, vecids, total_vecs,
2454930fbf4SPavan Kumar Linga 					       vchunks);
2464930fbf4SPavan Kumar Linga 		if (num_vec_ids < v_actual) {
2474930fbf4SPavan Kumar Linga 			err = -EINVAL;
2484930fbf4SPavan Kumar Linga 			goto free_vecids;
2494930fbf4SPavan Kumar Linga 		}
2504930fbf4SPavan Kumar Linga 	} else {
2514930fbf4SPavan Kumar Linga 		int i;
2524930fbf4SPavan Kumar Linga 
2534930fbf4SPavan Kumar Linga 		for (i = 0; i < v_actual; i++)
2544930fbf4SPavan Kumar Linga 			vecids[i] = i;
2554930fbf4SPavan Kumar Linga 	}
2564930fbf4SPavan Kumar Linga 
2574930fbf4SPavan Kumar Linga 	for (vector = 0; vector < v_actual; vector++) {
2584930fbf4SPavan Kumar Linga 		adapter->msix_entries[vector].entry = vecids[vector];
2594930fbf4SPavan Kumar Linga 		adapter->msix_entries[vector].vector =
2604930fbf4SPavan Kumar Linga 			pci_irq_vector(adapter->pdev, vector);
2614930fbf4SPavan Kumar Linga 	}
2624930fbf4SPavan Kumar Linga 
2634930fbf4SPavan Kumar Linga 	adapter->num_req_msix = total_vecs;
2644930fbf4SPavan Kumar Linga 	adapter->num_msix_entries = v_actual;
2654930fbf4SPavan Kumar Linga 	/* 'num_avail_msix' is used to distribute excess vectors to the vports
2664930fbf4SPavan Kumar Linga 	 * after considering the minimum vectors required per each default
2674930fbf4SPavan Kumar Linga 	 * vport
2684930fbf4SPavan Kumar Linga 	 */
2694930fbf4SPavan Kumar Linga 	adapter->num_avail_msix = v_actual - min_vectors;
2704930fbf4SPavan Kumar Linga 
2714930fbf4SPavan Kumar Linga 	/* Fill MSIX vector lifo stack with vector indexes */
2724930fbf4SPavan Kumar Linga 	err = idpf_init_vector_stack(adapter);
2734930fbf4SPavan Kumar Linga 	if (err)
2744930fbf4SPavan Kumar Linga 		goto free_vecids;
2754930fbf4SPavan Kumar Linga 
2764930fbf4SPavan Kumar Linga 	err = idpf_mb_intr_init(adapter);
2774930fbf4SPavan Kumar Linga 	if (err)
2784930fbf4SPavan Kumar Linga 		goto deinit_vec_stack;
2794930fbf4SPavan Kumar Linga 	idpf_mb_irq_enable(adapter);
2804930fbf4SPavan Kumar Linga 	kfree(vecids);
2814930fbf4SPavan Kumar Linga 
2824930fbf4SPavan Kumar Linga 	return 0;
2834930fbf4SPavan Kumar Linga 
2844930fbf4SPavan Kumar Linga deinit_vec_stack:
2854930fbf4SPavan Kumar Linga 	idpf_deinit_vector_stack(adapter);
2864930fbf4SPavan Kumar Linga free_vecids:
2874930fbf4SPavan Kumar Linga 	kfree(vecids);
2884930fbf4SPavan Kumar Linga free_msix:
2894930fbf4SPavan Kumar Linga 	kfree(adapter->msix_entries);
2904930fbf4SPavan Kumar Linga 	adapter->msix_entries = NULL;
2914930fbf4SPavan Kumar Linga free_irq:
2924930fbf4SPavan Kumar Linga 	pci_free_irq_vectors(adapter->pdev);
2934930fbf4SPavan Kumar Linga send_dealloc_vecs:
2944930fbf4SPavan Kumar Linga 	idpf_send_dealloc_vectors_msg(adapter);
2954930fbf4SPavan Kumar Linga 
2964930fbf4SPavan Kumar Linga 	return err;
2974930fbf4SPavan Kumar Linga }
2984930fbf4SPavan Kumar Linga 
2994930fbf4SPavan Kumar Linga /**
300ce1b75d0SPavan Kumar Linga  * idpf_find_mac_filter - Search filter list for specific mac filter
301ce1b75d0SPavan Kumar Linga  * @vconfig: Vport config structure
302ce1b75d0SPavan Kumar Linga  * @macaddr: The MAC address
303ce1b75d0SPavan Kumar Linga  *
304ce1b75d0SPavan Kumar Linga  * Returns ptr to the filter object or NULL. Must be called while holding the
305ce1b75d0SPavan Kumar Linga  * mac_filter_list_lock.
306ce1b75d0SPavan Kumar Linga  **/
307ce1b75d0SPavan Kumar Linga static struct idpf_mac_filter *idpf_find_mac_filter(struct idpf_vport_config *vconfig,
308ce1b75d0SPavan Kumar Linga 						    const u8 *macaddr)
309ce1b75d0SPavan Kumar Linga {
310ce1b75d0SPavan Kumar Linga 	struct idpf_mac_filter *f;
311ce1b75d0SPavan Kumar Linga 
312ce1b75d0SPavan Kumar Linga 	if (!macaddr)
313ce1b75d0SPavan Kumar Linga 		return NULL;
314ce1b75d0SPavan Kumar Linga 
315ce1b75d0SPavan Kumar Linga 	list_for_each_entry(f, &vconfig->user_config.mac_filter_list, list) {
316ce1b75d0SPavan Kumar Linga 		if (ether_addr_equal(macaddr, f->macaddr))
317ce1b75d0SPavan Kumar Linga 			return f;
318ce1b75d0SPavan Kumar Linga 	}
319ce1b75d0SPavan Kumar Linga 
320ce1b75d0SPavan Kumar Linga 	return NULL;
321ce1b75d0SPavan Kumar Linga }
322ce1b75d0SPavan Kumar Linga 
323ce1b75d0SPavan Kumar Linga /**
324ce1b75d0SPavan Kumar Linga  * __idpf_add_mac_filter - Add mac filter helper function
325ce1b75d0SPavan Kumar Linga  * @vport_config: Vport config structure
326ce1b75d0SPavan Kumar Linga  * @macaddr: Address to add
327ce1b75d0SPavan Kumar Linga  *
328ce1b75d0SPavan Kumar Linga  * Takes mac_filter_list_lock spinlock to add new filter to list.
329ce1b75d0SPavan Kumar Linga  */
330ce1b75d0SPavan Kumar Linga static int __idpf_add_mac_filter(struct idpf_vport_config *vport_config,
331ce1b75d0SPavan Kumar Linga 				 const u8 *macaddr)
332ce1b75d0SPavan Kumar Linga {
333ce1b75d0SPavan Kumar Linga 	struct idpf_mac_filter *f;
334ce1b75d0SPavan Kumar Linga 
335ce1b75d0SPavan Kumar Linga 	spin_lock_bh(&vport_config->mac_filter_list_lock);
336ce1b75d0SPavan Kumar Linga 
337ce1b75d0SPavan Kumar Linga 	f = idpf_find_mac_filter(vport_config, macaddr);
338ce1b75d0SPavan Kumar Linga 	if (f) {
339ce1b75d0SPavan Kumar Linga 		f->remove = false;
340ce1b75d0SPavan Kumar Linga 		spin_unlock_bh(&vport_config->mac_filter_list_lock);
341ce1b75d0SPavan Kumar Linga 
342ce1b75d0SPavan Kumar Linga 		return 0;
343ce1b75d0SPavan Kumar Linga 	}
344ce1b75d0SPavan Kumar Linga 
345ce1b75d0SPavan Kumar Linga 	f = kzalloc(sizeof(*f), GFP_ATOMIC);
346ce1b75d0SPavan Kumar Linga 	if (!f) {
347ce1b75d0SPavan Kumar Linga 		spin_unlock_bh(&vport_config->mac_filter_list_lock);
348ce1b75d0SPavan Kumar Linga 
349ce1b75d0SPavan Kumar Linga 		return -ENOMEM;
350ce1b75d0SPavan Kumar Linga 	}
351ce1b75d0SPavan Kumar Linga 
352ce1b75d0SPavan Kumar Linga 	ether_addr_copy(f->macaddr, macaddr);
353ce1b75d0SPavan Kumar Linga 	list_add_tail(&f->list, &vport_config->user_config.mac_filter_list);
354ce1b75d0SPavan Kumar Linga 	f->add = true;
355ce1b75d0SPavan Kumar Linga 
356ce1b75d0SPavan Kumar Linga 	spin_unlock_bh(&vport_config->mac_filter_list_lock);
357ce1b75d0SPavan Kumar Linga 
358ce1b75d0SPavan Kumar Linga 	return 0;
359ce1b75d0SPavan Kumar Linga }
360ce1b75d0SPavan Kumar Linga 
361ce1b75d0SPavan Kumar Linga /**
362ce1b75d0SPavan Kumar Linga  * idpf_add_mac_filter - Add a mac filter to the filter list
363ce1b75d0SPavan Kumar Linga  * @vport: Main vport structure
364ce1b75d0SPavan Kumar Linga  * @np: Netdev private structure
365ce1b75d0SPavan Kumar Linga  * @macaddr: The MAC address
366ce1b75d0SPavan Kumar Linga  * @async: Don't wait for return message
367ce1b75d0SPavan Kumar Linga  *
368ce1b75d0SPavan Kumar Linga  * Returns 0 on success or error on failure. If interface is up, we'll also
369ce1b75d0SPavan Kumar Linga  * send the virtchnl message to tell hardware about the filter.
370ce1b75d0SPavan Kumar Linga  **/
371ce1b75d0SPavan Kumar Linga static int idpf_add_mac_filter(struct idpf_vport *vport,
372ce1b75d0SPavan Kumar Linga 			       struct idpf_netdev_priv *np,
373ce1b75d0SPavan Kumar Linga 			       const u8 *macaddr, bool async)
374ce1b75d0SPavan Kumar Linga {
375ce1b75d0SPavan Kumar Linga 	struct idpf_vport_config *vport_config;
376ce1b75d0SPavan Kumar Linga 	int err;
377ce1b75d0SPavan Kumar Linga 
378ce1b75d0SPavan Kumar Linga 	vport_config = np->adapter->vport_config[np->vport_idx];
379ce1b75d0SPavan Kumar Linga 	err = __idpf_add_mac_filter(vport_config, macaddr);
380ce1b75d0SPavan Kumar Linga 	if (err)
381ce1b75d0SPavan Kumar Linga 		return err;
382ce1b75d0SPavan Kumar Linga 
383ce1b75d0SPavan Kumar Linga 	if (np->state == __IDPF_VPORT_UP)
384ce1b75d0SPavan Kumar Linga 		err = idpf_add_del_mac_filters(vport, np, true, async);
385ce1b75d0SPavan Kumar Linga 
386ce1b75d0SPavan Kumar Linga 	return err;
387ce1b75d0SPavan Kumar Linga }
388ce1b75d0SPavan Kumar Linga 
389ce1b75d0SPavan Kumar Linga /**
390ce1b75d0SPavan Kumar Linga  * idpf_deinit_mac_addr - deinitialize mac address for vport
391ce1b75d0SPavan Kumar Linga  * @vport: main vport structure
392ce1b75d0SPavan Kumar Linga  */
393ce1b75d0SPavan Kumar Linga static void idpf_deinit_mac_addr(struct idpf_vport *vport)
394ce1b75d0SPavan Kumar Linga {
395ce1b75d0SPavan Kumar Linga 	struct idpf_vport_config *vport_config;
396ce1b75d0SPavan Kumar Linga 	struct idpf_mac_filter *f;
397ce1b75d0SPavan Kumar Linga 
398ce1b75d0SPavan Kumar Linga 	vport_config = vport->adapter->vport_config[vport->idx];
399ce1b75d0SPavan Kumar Linga 
400ce1b75d0SPavan Kumar Linga 	spin_lock_bh(&vport_config->mac_filter_list_lock);
401ce1b75d0SPavan Kumar Linga 
402ce1b75d0SPavan Kumar Linga 	f = idpf_find_mac_filter(vport_config, vport->default_mac_addr);
403ce1b75d0SPavan Kumar Linga 	if (f) {
404ce1b75d0SPavan Kumar Linga 		list_del(&f->list);
405ce1b75d0SPavan Kumar Linga 		kfree(f);
406ce1b75d0SPavan Kumar Linga 	}
407ce1b75d0SPavan Kumar Linga 
408ce1b75d0SPavan Kumar Linga 	spin_unlock_bh(&vport_config->mac_filter_list_lock);
409ce1b75d0SPavan Kumar Linga }
410ce1b75d0SPavan Kumar Linga 
411ce1b75d0SPavan Kumar Linga /**
412ce1b75d0SPavan Kumar Linga  * idpf_init_mac_addr - initialize mac address for vport
413ce1b75d0SPavan Kumar Linga  * @vport: main vport structure
414ce1b75d0SPavan Kumar Linga  * @netdev: pointer to netdev struct associated with this vport
415ce1b75d0SPavan Kumar Linga  */
416ce1b75d0SPavan Kumar Linga static int idpf_init_mac_addr(struct idpf_vport *vport,
417ce1b75d0SPavan Kumar Linga 			      struct net_device *netdev)
418ce1b75d0SPavan Kumar Linga {
419ce1b75d0SPavan Kumar Linga 	struct idpf_netdev_priv *np = netdev_priv(netdev);
420ce1b75d0SPavan Kumar Linga 	struct idpf_adapter *adapter = vport->adapter;
421ce1b75d0SPavan Kumar Linga 	int err;
422ce1b75d0SPavan Kumar Linga 
423ce1b75d0SPavan Kumar Linga 	if (is_valid_ether_addr(vport->default_mac_addr)) {
424ce1b75d0SPavan Kumar Linga 		eth_hw_addr_set(netdev, vport->default_mac_addr);
425ce1b75d0SPavan Kumar Linga 		ether_addr_copy(netdev->perm_addr, vport->default_mac_addr);
426ce1b75d0SPavan Kumar Linga 
427ce1b75d0SPavan Kumar Linga 		return idpf_add_mac_filter(vport, np, vport->default_mac_addr,
428ce1b75d0SPavan Kumar Linga 					   false);
429ce1b75d0SPavan Kumar Linga 	}
430ce1b75d0SPavan Kumar Linga 
431ce1b75d0SPavan Kumar Linga 	if (!idpf_is_cap_ena(adapter, IDPF_OTHER_CAPS,
432ce1b75d0SPavan Kumar Linga 			     VIRTCHNL2_CAP_MACFILTER)) {
433ce1b75d0SPavan Kumar Linga 		dev_err(&adapter->pdev->dev,
434ce1b75d0SPavan Kumar Linga 			"MAC address is not provided and capability is not set\n");
435ce1b75d0SPavan Kumar Linga 
436ce1b75d0SPavan Kumar Linga 		return -EINVAL;
437ce1b75d0SPavan Kumar Linga 	}
438ce1b75d0SPavan Kumar Linga 
439ce1b75d0SPavan Kumar Linga 	eth_hw_addr_random(netdev);
440ce1b75d0SPavan Kumar Linga 	err = idpf_add_mac_filter(vport, np, netdev->dev_addr, false);
441ce1b75d0SPavan Kumar Linga 	if (err)
442ce1b75d0SPavan Kumar Linga 		return err;
443ce1b75d0SPavan Kumar Linga 
444ce1b75d0SPavan Kumar Linga 	dev_info(&adapter->pdev->dev, "Invalid MAC address %pM, using random %pM\n",
445ce1b75d0SPavan Kumar Linga 		 vport->default_mac_addr, netdev->dev_addr);
446ce1b75d0SPavan Kumar Linga 	ether_addr_copy(vport->default_mac_addr, netdev->dev_addr);
447ce1b75d0SPavan Kumar Linga 
448ce1b75d0SPavan Kumar Linga 	return 0;
449ce1b75d0SPavan Kumar Linga }
450ce1b75d0SPavan Kumar Linga 
451ce1b75d0SPavan Kumar Linga /**
4520fe45467SPavan Kumar Linga  * idpf_cfg_netdev - Allocate, configure and register a netdev
4530fe45467SPavan Kumar Linga  * @vport: main vport structure
4540fe45467SPavan Kumar Linga  *
4550fe45467SPavan Kumar Linga  * Returns 0 on success, negative value on failure.
4560fe45467SPavan Kumar Linga  */
4570fe45467SPavan Kumar Linga static int idpf_cfg_netdev(struct idpf_vport *vport)
4580fe45467SPavan Kumar Linga {
4590fe45467SPavan Kumar Linga 	struct idpf_adapter *adapter = vport->adapter;
4600fe45467SPavan Kumar Linga 	struct idpf_vport_config *vport_config;
4610fe45467SPavan Kumar Linga 	netdev_features_t dflt_features;
4620fe45467SPavan Kumar Linga 	netdev_features_t offloads = 0;
4630fe45467SPavan Kumar Linga 	struct idpf_netdev_priv *np;
4640fe45467SPavan Kumar Linga 	struct net_device *netdev;
4650fe45467SPavan Kumar Linga 	u16 idx = vport->idx;
466ce1b75d0SPavan Kumar Linga 	int err;
4670fe45467SPavan Kumar Linga 
4680fe45467SPavan Kumar Linga 	vport_config = adapter->vport_config[idx];
4690fe45467SPavan Kumar Linga 
4700fe45467SPavan Kumar Linga 	/* It's possible we already have a netdev allocated and registered for
4710fe45467SPavan Kumar Linga 	 * this vport
4720fe45467SPavan Kumar Linga 	 */
4730fe45467SPavan Kumar Linga 	if (test_bit(IDPF_VPORT_REG_NETDEV, vport_config->flags)) {
4740fe45467SPavan Kumar Linga 		netdev = adapter->netdevs[idx];
4750fe45467SPavan Kumar Linga 		np = netdev_priv(netdev);
4760fe45467SPavan Kumar Linga 		np->vport = vport;
477ce1b75d0SPavan Kumar Linga 		np->vport_idx = vport->idx;
478ce1b75d0SPavan Kumar Linga 		np->vport_id = vport->vport_id;
4790fe45467SPavan Kumar Linga 		vport->netdev = netdev;
4800fe45467SPavan Kumar Linga 
481ce1b75d0SPavan Kumar Linga 		return idpf_init_mac_addr(vport, netdev);
4820fe45467SPavan Kumar Linga 	}
4830fe45467SPavan Kumar Linga 
4840fe45467SPavan Kumar Linga 	netdev = alloc_etherdev_mqs(sizeof(struct idpf_netdev_priv),
4850fe45467SPavan Kumar Linga 				    vport_config->max_q.max_txq,
4860fe45467SPavan Kumar Linga 				    vport_config->max_q.max_rxq);
4870fe45467SPavan Kumar Linga 	if (!netdev)
4880fe45467SPavan Kumar Linga 		return -ENOMEM;
4890fe45467SPavan Kumar Linga 
4900fe45467SPavan Kumar Linga 	vport->netdev = netdev;
4910fe45467SPavan Kumar Linga 	np = netdev_priv(netdev);
4920fe45467SPavan Kumar Linga 	np->vport = vport;
493ce1b75d0SPavan Kumar Linga 	np->adapter = adapter;
494ce1b75d0SPavan Kumar Linga 	np->vport_idx = vport->idx;
495ce1b75d0SPavan Kumar Linga 	np->vport_id = vport->vport_id;
496ce1b75d0SPavan Kumar Linga 
497ce1b75d0SPavan Kumar Linga 	err = idpf_init_mac_addr(vport, netdev);
498ce1b75d0SPavan Kumar Linga 	if (err) {
499ce1b75d0SPavan Kumar Linga 		free_netdev(vport->netdev);
500ce1b75d0SPavan Kumar Linga 		vport->netdev = NULL;
501ce1b75d0SPavan Kumar Linga 
502ce1b75d0SPavan Kumar Linga 		return err;
503ce1b75d0SPavan Kumar Linga 	}
5040fe45467SPavan Kumar Linga 
5051c325aacSAlan Brady 	/* assign netdev_ops */
5061c325aacSAlan Brady 	if (idpf_is_queue_model_split(vport->txq_model))
5071c325aacSAlan Brady 		netdev->netdev_ops = &idpf_netdev_ops_splitq;
5081c325aacSAlan Brady 	else
5091c325aacSAlan Brady 		netdev->netdev_ops = &idpf_netdev_ops_singleq;
5101c325aacSAlan Brady 
5110fe45467SPavan Kumar Linga 	/* setup watchdog timeout value to be 5 second */
5120fe45467SPavan Kumar Linga 	netdev->watchdog_timeo = 5 * HZ;
5130fe45467SPavan Kumar Linga 
5140fe45467SPavan Kumar Linga 	/* configure default MTU size */
5150fe45467SPavan Kumar Linga 	netdev->min_mtu = ETH_MIN_MTU;
5160fe45467SPavan Kumar Linga 	netdev->max_mtu = vport->max_mtu;
5170fe45467SPavan Kumar Linga 
5180fe45467SPavan Kumar Linga 	dflt_features = NETIF_F_SG	|
5190fe45467SPavan Kumar Linga 			NETIF_F_HIGHDMA;
5200fe45467SPavan Kumar Linga 
5210fe45467SPavan Kumar Linga 	if (idpf_is_cap_ena_all(adapter, IDPF_RSS_CAPS, IDPF_CAP_RSS))
5220fe45467SPavan Kumar Linga 		dflt_features |= NETIF_F_RXHASH;
5230fe45467SPavan Kumar Linga 	if (idpf_is_cap_ena_all(adapter, IDPF_CSUM_CAPS, IDPF_CAP_RX_CSUM_L4V4))
5240fe45467SPavan Kumar Linga 		dflt_features |= NETIF_F_IP_CSUM;
5250fe45467SPavan Kumar Linga 	if (idpf_is_cap_ena_all(adapter, IDPF_CSUM_CAPS, IDPF_CAP_RX_CSUM_L4V6))
5260fe45467SPavan Kumar Linga 		dflt_features |= NETIF_F_IPV6_CSUM;
5270fe45467SPavan Kumar Linga 	if (idpf_is_cap_ena(adapter, IDPF_CSUM_CAPS, IDPF_CAP_RX_CSUM))
5280fe45467SPavan Kumar Linga 		dflt_features |= NETIF_F_RXCSUM;
5290fe45467SPavan Kumar Linga 	if (idpf_is_cap_ena_all(adapter, IDPF_CSUM_CAPS, IDPF_CAP_SCTP_CSUM))
5300fe45467SPavan Kumar Linga 		dflt_features |= NETIF_F_SCTP_CRC;
5310fe45467SPavan Kumar Linga 
5320fe45467SPavan Kumar Linga 	if (idpf_is_cap_ena(adapter, IDPF_SEG_CAPS, VIRTCHNL2_CAP_SEG_IPV4_TCP))
5330fe45467SPavan Kumar Linga 		dflt_features |= NETIF_F_TSO;
5340fe45467SPavan Kumar Linga 	if (idpf_is_cap_ena(adapter, IDPF_SEG_CAPS, VIRTCHNL2_CAP_SEG_IPV6_TCP))
5350fe45467SPavan Kumar Linga 		dflt_features |= NETIF_F_TSO6;
5360fe45467SPavan Kumar Linga 	if (idpf_is_cap_ena_all(adapter, IDPF_SEG_CAPS,
5370fe45467SPavan Kumar Linga 				VIRTCHNL2_CAP_SEG_IPV4_UDP |
5380fe45467SPavan Kumar Linga 				VIRTCHNL2_CAP_SEG_IPV6_UDP))
5390fe45467SPavan Kumar Linga 		dflt_features |= NETIF_F_GSO_UDP_L4;
5400fe45467SPavan Kumar Linga 	if (idpf_is_cap_ena_all(adapter, IDPF_RSC_CAPS, IDPF_CAP_RSC))
5410fe45467SPavan Kumar Linga 		offloads |= NETIF_F_GRO_HW;
5420fe45467SPavan Kumar Linga 	/* advertise to stack only if offloads for encapsulated packets is
5430fe45467SPavan Kumar Linga 	 * supported
5440fe45467SPavan Kumar Linga 	 */
5450fe45467SPavan Kumar Linga 	if (idpf_is_cap_ena(vport->adapter, IDPF_SEG_CAPS,
5460fe45467SPavan Kumar Linga 			    VIRTCHNL2_CAP_SEG_TX_SINGLE_TUNNEL)) {
5470fe45467SPavan Kumar Linga 		offloads |= NETIF_F_GSO_UDP_TUNNEL	|
5480fe45467SPavan Kumar Linga 			    NETIF_F_GSO_GRE		|
5490fe45467SPavan Kumar Linga 			    NETIF_F_GSO_GRE_CSUM	|
5500fe45467SPavan Kumar Linga 			    NETIF_F_GSO_PARTIAL		|
5510fe45467SPavan Kumar Linga 			    NETIF_F_GSO_UDP_TUNNEL_CSUM	|
5520fe45467SPavan Kumar Linga 			    NETIF_F_GSO_IPXIP4		|
5530fe45467SPavan Kumar Linga 			    NETIF_F_GSO_IPXIP6		|
5540fe45467SPavan Kumar Linga 			    0;
5550fe45467SPavan Kumar Linga 
5560fe45467SPavan Kumar Linga 		if (!idpf_is_cap_ena_all(vport->adapter, IDPF_CSUM_CAPS,
5570fe45467SPavan Kumar Linga 					 IDPF_CAP_TUNNEL_TX_CSUM))
5580fe45467SPavan Kumar Linga 			netdev->gso_partial_features |=
5590fe45467SPavan Kumar Linga 				NETIF_F_GSO_UDP_TUNNEL_CSUM;
5600fe45467SPavan Kumar Linga 
5610fe45467SPavan Kumar Linga 		netdev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM;
5620fe45467SPavan Kumar Linga 		offloads |= NETIF_F_TSO_MANGLEID;
5630fe45467SPavan Kumar Linga 	}
5640fe45467SPavan Kumar Linga 	if (idpf_is_cap_ena(adapter, IDPF_OTHER_CAPS, VIRTCHNL2_CAP_LOOPBACK))
5650fe45467SPavan Kumar Linga 		offloads |= NETIF_F_LOOPBACK;
5660fe45467SPavan Kumar Linga 
5670fe45467SPavan Kumar Linga 	netdev->features |= dflt_features;
5680fe45467SPavan Kumar Linga 	netdev->hw_features |= dflt_features | offloads;
5690fe45467SPavan Kumar Linga 	netdev->hw_enc_features |= dflt_features | offloads;
5700fe45467SPavan Kumar Linga 	SET_NETDEV_DEV(netdev, &adapter->pdev->dev);
5710fe45467SPavan Kumar Linga 
5720fe45467SPavan Kumar Linga 	/* carrier off on init to avoid Tx hangs */
5730fe45467SPavan Kumar Linga 	netif_carrier_off(netdev);
5740fe45467SPavan Kumar Linga 
5750fe45467SPavan Kumar Linga 	/* make sure transmit queues start off as stopped */
5760fe45467SPavan Kumar Linga 	netif_tx_stop_all_queues(netdev);
5770fe45467SPavan Kumar Linga 
5780fe45467SPavan Kumar Linga 	/* The vport can be arbitrarily released so we need to also track
5790fe45467SPavan Kumar Linga 	 * netdevs in the adapter struct
5800fe45467SPavan Kumar Linga 	 */
5810fe45467SPavan Kumar Linga 	adapter->netdevs[idx] = netdev;
5820fe45467SPavan Kumar Linga 
5830fe45467SPavan Kumar Linga 	return 0;
5840fe45467SPavan Kumar Linga }
5850fe45467SPavan Kumar Linga 
5860fe45467SPavan Kumar Linga /**
5870fe45467SPavan Kumar Linga  * idpf_get_free_slot - get the next non-NULL location index in array
5880fe45467SPavan Kumar Linga  * @adapter: adapter in which to look for a free vport slot
5890fe45467SPavan Kumar Linga  */
5900fe45467SPavan Kumar Linga static int idpf_get_free_slot(struct idpf_adapter *adapter)
5910fe45467SPavan Kumar Linga {
5920fe45467SPavan Kumar Linga 	unsigned int i;
5930fe45467SPavan Kumar Linga 
5940fe45467SPavan Kumar Linga 	for (i = 0; i < adapter->max_vports; i++) {
5950fe45467SPavan Kumar Linga 		if (!adapter->vports[i])
5960fe45467SPavan Kumar Linga 			return i;
5970fe45467SPavan Kumar Linga 	}
5980fe45467SPavan Kumar Linga 
5990fe45467SPavan Kumar Linga 	return IDPF_NO_FREE_SLOT;
6000fe45467SPavan Kumar Linga }
6010fe45467SPavan Kumar Linga 
6020fe45467SPavan Kumar Linga /**
6031c325aacSAlan Brady  * idpf_vport_stop - Disable a vport
6041c325aacSAlan Brady  * @vport: vport to disable
6051c325aacSAlan Brady  */
6061c325aacSAlan Brady static void idpf_vport_stop(struct idpf_vport *vport)
6071c325aacSAlan Brady {
6081c325aacSAlan Brady 	struct idpf_netdev_priv *np = netdev_priv(vport->netdev);
6091c325aacSAlan Brady 
6101c325aacSAlan Brady 	if (np->state <= __IDPF_VPORT_DOWN)
6111c325aacSAlan Brady 		return;
6121c325aacSAlan Brady 
6131c325aacSAlan Brady 	netif_carrier_off(vport->netdev);
6141c325aacSAlan Brady 
6151c325aacSAlan Brady 	idpf_vport_intr_rel(vport);
6161c325aacSAlan Brady 	idpf_vport_queues_rel(vport);
6171c325aacSAlan Brady 	np->state = __IDPF_VPORT_DOWN;
6181c325aacSAlan Brady }
6191c325aacSAlan Brady 
6201c325aacSAlan Brady /**
6211c325aacSAlan Brady  * idpf_stop - Disables a network interface
6221c325aacSAlan Brady  * @netdev: network interface device structure
6231c325aacSAlan Brady  *
6241c325aacSAlan Brady  * The stop entry point is called when an interface is de-activated by the OS,
6251c325aacSAlan Brady  * and the netdevice enters the DOWN state.  The hardware is still under the
6261c325aacSAlan Brady  * driver's control, but the netdev interface is disabled.
6271c325aacSAlan Brady  *
6281c325aacSAlan Brady  * Returns success only - not allowed to fail
6291c325aacSAlan Brady  */
6301c325aacSAlan Brady static int idpf_stop(struct net_device *netdev)
6311c325aacSAlan Brady {
6321c325aacSAlan Brady 	struct idpf_netdev_priv *np = netdev_priv(netdev);
6331c325aacSAlan Brady 	struct idpf_vport *vport;
6341c325aacSAlan Brady 
6351c325aacSAlan Brady 	if (test_bit(IDPF_REMOVE_IN_PROG, np->adapter->flags))
6361c325aacSAlan Brady 		return 0;
6371c325aacSAlan Brady 
6381c325aacSAlan Brady 	idpf_vport_ctrl_lock(netdev);
6391c325aacSAlan Brady 	vport = idpf_netdev_to_vport(netdev);
6401c325aacSAlan Brady 
6411c325aacSAlan Brady 	idpf_vport_stop(vport);
6421c325aacSAlan Brady 
6431c325aacSAlan Brady 	idpf_vport_ctrl_unlock(netdev);
6441c325aacSAlan Brady 
6451c325aacSAlan Brady 	return 0;
6461c325aacSAlan Brady }
6471c325aacSAlan Brady 
6481c325aacSAlan Brady /**
6490fe45467SPavan Kumar Linga  * idpf_decfg_netdev - Unregister the netdev
6500fe45467SPavan Kumar Linga  * @vport: vport for which netdev to be unregistered
6510fe45467SPavan Kumar Linga  */
6520fe45467SPavan Kumar Linga static void idpf_decfg_netdev(struct idpf_vport *vport)
6530fe45467SPavan Kumar Linga {
6540fe45467SPavan Kumar Linga 	struct idpf_adapter *adapter = vport->adapter;
6550fe45467SPavan Kumar Linga 
6560fe45467SPavan Kumar Linga 	unregister_netdev(vport->netdev);
6570fe45467SPavan Kumar Linga 	free_netdev(vport->netdev);
6580fe45467SPavan Kumar Linga 	vport->netdev = NULL;
6590fe45467SPavan Kumar Linga 
6600fe45467SPavan Kumar Linga 	adapter->netdevs[vport->idx] = NULL;
6610fe45467SPavan Kumar Linga }
6620fe45467SPavan Kumar Linga 
6630fe45467SPavan Kumar Linga /**
6640fe45467SPavan Kumar Linga  * idpf_vport_rel - Delete a vport and free its resources
6650fe45467SPavan Kumar Linga  * @vport: the vport being removed
6660fe45467SPavan Kumar Linga  */
6670fe45467SPavan Kumar Linga static void idpf_vport_rel(struct idpf_vport *vport)
6680fe45467SPavan Kumar Linga {
6690fe45467SPavan Kumar Linga 	struct idpf_adapter *adapter = vport->adapter;
6700fe45467SPavan Kumar Linga 	struct idpf_vport_config *vport_config;
671*95af467dSAlan Brady 	struct idpf_rss_data *rss_data;
6720fe45467SPavan Kumar Linga 	struct idpf_vport_max_q max_q;
6730fe45467SPavan Kumar Linga 	u16 idx = vport->idx;
6740fe45467SPavan Kumar Linga 	int i;
6750fe45467SPavan Kumar Linga 
6760fe45467SPavan Kumar Linga 	vport_config = adapter->vport_config[vport->idx];
677*95af467dSAlan Brady 	idpf_deinit_rss(vport);
678*95af467dSAlan Brady 	rss_data = &vport_config->user_config.rss_data;
679*95af467dSAlan Brady 	kfree(rss_data->rss_key);
680*95af467dSAlan Brady 	rss_data->rss_key = NULL;
6810fe45467SPavan Kumar Linga 
6820fe45467SPavan Kumar Linga 	idpf_send_destroy_vport_msg(vport);
6830fe45467SPavan Kumar Linga 
6840fe45467SPavan Kumar Linga 	/* Set all bits as we dont know on which vc_state the vport vhnl_wq
6850fe45467SPavan Kumar Linga 	 * is waiting on and wakeup the virtchnl workqueue even if it is
6860fe45467SPavan Kumar Linga 	 * waiting for the response as we are going down
6870fe45467SPavan Kumar Linga 	 */
6880fe45467SPavan Kumar Linga 	for (i = 0; i < IDPF_VC_NBITS; i++)
6890fe45467SPavan Kumar Linga 		set_bit(i, vport->vc_state);
6900fe45467SPavan Kumar Linga 	wake_up(&vport->vchnl_wq);
6910fe45467SPavan Kumar Linga 
6920fe45467SPavan Kumar Linga 	mutex_destroy(&vport->vc_buf_lock);
6930fe45467SPavan Kumar Linga 
6940fe45467SPavan Kumar Linga 	/* Clear all the bits */
6950fe45467SPavan Kumar Linga 	for (i = 0; i < IDPF_VC_NBITS; i++)
6960fe45467SPavan Kumar Linga 		clear_bit(i, vport->vc_state);
6970fe45467SPavan Kumar Linga 
6980fe45467SPavan Kumar Linga 	/* Release all max queues allocated to the adapter's pool */
6990fe45467SPavan Kumar Linga 	max_q.max_rxq = vport_config->max_q.max_rxq;
7000fe45467SPavan Kumar Linga 	max_q.max_txq = vport_config->max_q.max_txq;
7010fe45467SPavan Kumar Linga 	max_q.max_bufq = vport_config->max_q.max_bufq;
7020fe45467SPavan Kumar Linga 	max_q.max_complq = vport_config->max_q.max_complq;
7030fe45467SPavan Kumar Linga 	idpf_vport_dealloc_max_qs(adapter, &max_q);
7040fe45467SPavan Kumar Linga 
7050fe45467SPavan Kumar Linga 	kfree(adapter->vport_params_recvd[idx]);
7060fe45467SPavan Kumar Linga 	adapter->vport_params_recvd[idx] = NULL;
7070fe45467SPavan Kumar Linga 	kfree(adapter->vport_params_reqd[idx]);
7080fe45467SPavan Kumar Linga 	adapter->vport_params_reqd[idx] = NULL;
7090fe45467SPavan Kumar Linga 	kfree(vport);
7100fe45467SPavan Kumar Linga 	adapter->num_alloc_vports--;
7110fe45467SPavan Kumar Linga }
7120fe45467SPavan Kumar Linga 
7130fe45467SPavan Kumar Linga /**
7140fe45467SPavan Kumar Linga  * idpf_vport_dealloc - cleanup and release a given vport
7150fe45467SPavan Kumar Linga  * @vport: pointer to idpf vport structure
7160fe45467SPavan Kumar Linga  *
7170fe45467SPavan Kumar Linga  * returns nothing
7180fe45467SPavan Kumar Linga  */
7190fe45467SPavan Kumar Linga static void idpf_vport_dealloc(struct idpf_vport *vport)
7200fe45467SPavan Kumar Linga {
7210fe45467SPavan Kumar Linga 	struct idpf_adapter *adapter = vport->adapter;
7220fe45467SPavan Kumar Linga 	unsigned int i = vport->idx;
7230fe45467SPavan Kumar Linga 
724ce1b75d0SPavan Kumar Linga 	idpf_deinit_mac_addr(vport);
725ce1b75d0SPavan Kumar Linga 
7260fe45467SPavan Kumar Linga 	if (!test_bit(IDPF_HR_RESET_IN_PROG, adapter->flags))
7270fe45467SPavan Kumar Linga 		idpf_decfg_netdev(vport);
7280fe45467SPavan Kumar Linga 
7290fe45467SPavan Kumar Linga 	if (adapter->netdevs[i]) {
7300fe45467SPavan Kumar Linga 		struct idpf_netdev_priv *np = netdev_priv(adapter->netdevs[i]);
7310fe45467SPavan Kumar Linga 
7320fe45467SPavan Kumar Linga 		np->vport = NULL;
7330fe45467SPavan Kumar Linga 	}
7340fe45467SPavan Kumar Linga 
7350fe45467SPavan Kumar Linga 	idpf_vport_rel(vport);
7360fe45467SPavan Kumar Linga 
7370fe45467SPavan Kumar Linga 	adapter->vports[i] = NULL;
7380fe45467SPavan Kumar Linga 	adapter->next_vport = idpf_get_free_slot(adapter);
7390fe45467SPavan Kumar Linga }
7400fe45467SPavan Kumar Linga 
7410fe45467SPavan Kumar Linga /**
7420fe45467SPavan Kumar Linga  * idpf_vport_alloc - Allocates the next available struct vport in the adapter
7430fe45467SPavan Kumar Linga  * @adapter: board private structure
7440fe45467SPavan Kumar Linga  * @max_q: vport max queue info
7450fe45467SPavan Kumar Linga  *
7460fe45467SPavan Kumar Linga  * returns a pointer to a vport on success, NULL on failure.
7470fe45467SPavan Kumar Linga  */
7480fe45467SPavan Kumar Linga static struct idpf_vport *idpf_vport_alloc(struct idpf_adapter *adapter,
7490fe45467SPavan Kumar Linga 					   struct idpf_vport_max_q *max_q)
7500fe45467SPavan Kumar Linga {
751*95af467dSAlan Brady 	struct idpf_rss_data *rss_data;
7520fe45467SPavan Kumar Linga 	u16 idx = adapter->next_vport;
7530fe45467SPavan Kumar Linga 	struct idpf_vport *vport;
7540fe45467SPavan Kumar Linga 
7550fe45467SPavan Kumar Linga 	if (idx == IDPF_NO_FREE_SLOT)
7560fe45467SPavan Kumar Linga 		return NULL;
7570fe45467SPavan Kumar Linga 
7580fe45467SPavan Kumar Linga 	vport = kzalloc(sizeof(*vport), GFP_KERNEL);
7590fe45467SPavan Kumar Linga 	if (!vport)
7600fe45467SPavan Kumar Linga 		return vport;
7610fe45467SPavan Kumar Linga 
7620fe45467SPavan Kumar Linga 	if (!adapter->vport_config[idx]) {
7630fe45467SPavan Kumar Linga 		struct idpf_vport_config *vport_config;
7640fe45467SPavan Kumar Linga 
7650fe45467SPavan Kumar Linga 		vport_config = kzalloc(sizeof(*vport_config), GFP_KERNEL);
7660fe45467SPavan Kumar Linga 		if (!vport_config) {
7670fe45467SPavan Kumar Linga 			kfree(vport);
7680fe45467SPavan Kumar Linga 
7690fe45467SPavan Kumar Linga 			return NULL;
7700fe45467SPavan Kumar Linga 		}
7710fe45467SPavan Kumar Linga 
7720fe45467SPavan Kumar Linga 		adapter->vport_config[idx] = vport_config;
7730fe45467SPavan Kumar Linga 	}
7740fe45467SPavan Kumar Linga 
7750fe45467SPavan Kumar Linga 	vport->idx = idx;
7760fe45467SPavan Kumar Linga 	vport->adapter = adapter;
7770fe45467SPavan Kumar Linga 	vport->default_vport = adapter->num_alloc_vports <
7780fe45467SPavan Kumar Linga 			       idpf_get_default_vports(adapter);
7790fe45467SPavan Kumar Linga 
7800fe45467SPavan Kumar Linga 	idpf_vport_init(vport, max_q);
7810fe45467SPavan Kumar Linga 
782*95af467dSAlan Brady 	/* This alloc is done separate from the LUT because it's not strictly
783*95af467dSAlan Brady 	 * dependent on how many queues we have. If we change number of queues
784*95af467dSAlan Brady 	 * and soft reset we'll need a new LUT but the key can remain the same
785*95af467dSAlan Brady 	 * for as long as the vport exists.
786*95af467dSAlan Brady 	 */
787*95af467dSAlan Brady 	rss_data = &adapter->vport_config[idx]->user_config.rss_data;
788*95af467dSAlan Brady 	rss_data->rss_key = kzalloc(rss_data->rss_key_size, GFP_KERNEL);
789*95af467dSAlan Brady 	if (!rss_data->rss_key) {
790*95af467dSAlan Brady 		kfree(vport);
791*95af467dSAlan Brady 
792*95af467dSAlan Brady 		return NULL;
793*95af467dSAlan Brady 	}
794*95af467dSAlan Brady 	/* Initialize default rss key */
795*95af467dSAlan Brady 	netdev_rss_key_fill((void *)rss_data->rss_key, rss_data->rss_key_size);
796*95af467dSAlan Brady 
7970fe45467SPavan Kumar Linga 	/* fill vport slot in the adapter struct */
7980fe45467SPavan Kumar Linga 	adapter->vports[idx] = vport;
7990fe45467SPavan Kumar Linga 	adapter->vport_ids[idx] = idpf_get_vport_id(vport);
8000fe45467SPavan Kumar Linga 
8010fe45467SPavan Kumar Linga 	adapter->num_alloc_vports++;
8020fe45467SPavan Kumar Linga 	/* prepare adapter->next_vport for next use */
8030fe45467SPavan Kumar Linga 	adapter->next_vport = idpf_get_free_slot(adapter);
8040fe45467SPavan Kumar Linga 
8050fe45467SPavan Kumar Linga 	return vport;
8060fe45467SPavan Kumar Linga }
8070fe45467SPavan Kumar Linga 
8080fe45467SPavan Kumar Linga /**
8094930fbf4SPavan Kumar Linga  * idpf_mbx_task - Delayed task to handle mailbox responses
8104930fbf4SPavan Kumar Linga  * @work: work_struct handle
8114930fbf4SPavan Kumar Linga  */
8124930fbf4SPavan Kumar Linga void idpf_mbx_task(struct work_struct *work)
8134930fbf4SPavan Kumar Linga {
8144930fbf4SPavan Kumar Linga 	struct idpf_adapter *adapter;
8154930fbf4SPavan Kumar Linga 
8164930fbf4SPavan Kumar Linga 	adapter = container_of(work, struct idpf_adapter, mbx_task.work);
8174930fbf4SPavan Kumar Linga 
8184930fbf4SPavan Kumar Linga 	if (test_bit(IDPF_MB_INTR_MODE, adapter->flags))
8194930fbf4SPavan Kumar Linga 		idpf_mb_irq_enable(adapter);
8204930fbf4SPavan Kumar Linga 	else
8214930fbf4SPavan Kumar Linga 		queue_delayed_work(adapter->mbx_wq, &adapter->mbx_task,
8224930fbf4SPavan Kumar Linga 				   msecs_to_jiffies(300));
8234930fbf4SPavan Kumar Linga 
8244930fbf4SPavan Kumar Linga 	idpf_recv_mb_msg(adapter, VIRTCHNL2_OP_UNKNOWN, NULL, 0);
8254930fbf4SPavan Kumar Linga }
8264930fbf4SPavan Kumar Linga 
8274930fbf4SPavan Kumar Linga /**
8284930fbf4SPavan Kumar Linga  * idpf_service_task - Delayed task for handling mailbox responses
8294930fbf4SPavan Kumar Linga  * @work: work_struct handle to our data
8304930fbf4SPavan Kumar Linga  *
8314930fbf4SPavan Kumar Linga  */
8324930fbf4SPavan Kumar Linga void idpf_service_task(struct work_struct *work)
8334930fbf4SPavan Kumar Linga {
8344930fbf4SPavan Kumar Linga 	struct idpf_adapter *adapter;
8354930fbf4SPavan Kumar Linga 
8364930fbf4SPavan Kumar Linga 	adapter = container_of(work, struct idpf_adapter, serv_task.work);
8374930fbf4SPavan Kumar Linga 
8384930fbf4SPavan Kumar Linga 	if (idpf_is_reset_detected(adapter) &&
8394930fbf4SPavan Kumar Linga 	    !idpf_is_reset_in_prog(adapter) &&
8404930fbf4SPavan Kumar Linga 	    !test_bit(IDPF_REMOVE_IN_PROG, adapter->flags)) {
8414930fbf4SPavan Kumar Linga 		dev_info(&adapter->pdev->dev, "HW reset detected\n");
8424930fbf4SPavan Kumar Linga 		set_bit(IDPF_HR_FUNC_RESET, adapter->flags);
8434930fbf4SPavan Kumar Linga 		queue_delayed_work(adapter->vc_event_wq,
8444930fbf4SPavan Kumar Linga 				   &adapter->vc_event_task,
8454930fbf4SPavan Kumar Linga 				   msecs_to_jiffies(10));
8464930fbf4SPavan Kumar Linga 	}
8474930fbf4SPavan Kumar Linga 
8484930fbf4SPavan Kumar Linga 	queue_delayed_work(adapter->serv_wq, &adapter->serv_task,
8494930fbf4SPavan Kumar Linga 			   msecs_to_jiffies(300));
8504930fbf4SPavan Kumar Linga }
8514930fbf4SPavan Kumar Linga 
8528077c727SJoshua Hay /**
8531c325aacSAlan Brady  * idpf_vport_open - Bring up a vport
8541c325aacSAlan Brady  * @vport: vport to bring up
8551c325aacSAlan Brady  * @alloc_res: allocate queue resources
8561c325aacSAlan Brady  */
8571c325aacSAlan Brady static int idpf_vport_open(struct idpf_vport *vport, bool alloc_res)
8581c325aacSAlan Brady {
8591c325aacSAlan Brady 	struct idpf_netdev_priv *np = netdev_priv(vport->netdev);
8601c325aacSAlan Brady 	struct idpf_adapter *adapter = vport->adapter;
861*95af467dSAlan Brady 	struct idpf_vport_config *vport_config;
8621c325aacSAlan Brady 	int err;
8631c325aacSAlan Brady 
8641c325aacSAlan Brady 	if (np->state != __IDPF_VPORT_DOWN)
8651c325aacSAlan Brady 		return -EBUSY;
8661c325aacSAlan Brady 
8671c325aacSAlan Brady 	/* we do not allow interface up just yet */
8681c325aacSAlan Brady 	netif_carrier_off(vport->netdev);
8691c325aacSAlan Brady 
8701c325aacSAlan Brady 	if (alloc_res) {
8711c325aacSAlan Brady 		err = idpf_vport_queues_alloc(vport);
8721c325aacSAlan Brady 		if (err)
8731c325aacSAlan Brady 			return err;
8741c325aacSAlan Brady 	}
8751c325aacSAlan Brady 
8761c325aacSAlan Brady 	err = idpf_vport_intr_alloc(vport);
8771c325aacSAlan Brady 	if (err) {
8781c325aacSAlan Brady 		dev_err(&adapter->pdev->dev, "Failed to allocate interrupts for vport %u: %d\n",
8791c325aacSAlan Brady 			vport->vport_id, err);
8801c325aacSAlan Brady 		goto queues_rel;
8811c325aacSAlan Brady 	}
8821c325aacSAlan Brady 
8831c325aacSAlan Brady 	err = idpf_vport_queue_ids_init(vport);
8841c325aacSAlan Brady 	if (err) {
8851c325aacSAlan Brady 		dev_err(&adapter->pdev->dev, "Failed to initialize queue ids for vport %u: %d\n",
8861c325aacSAlan Brady 			vport->vport_id, err);
8871c325aacSAlan Brady 		goto intr_rel;
8881c325aacSAlan Brady 	}
8891c325aacSAlan Brady 
890*95af467dSAlan Brady 	err = idpf_rx_bufs_init_all(vport);
891*95af467dSAlan Brady 	if (err) {
892*95af467dSAlan Brady 		dev_err(&adapter->pdev->dev, "Failed to initialize RX buffers for vport %u: %d\n",
893*95af467dSAlan Brady 			vport->vport_id, err);
894*95af467dSAlan Brady 		goto intr_rel;
895*95af467dSAlan Brady 	}
896*95af467dSAlan Brady 
8971c325aacSAlan Brady 	err = idpf_queue_reg_init(vport);
8981c325aacSAlan Brady 	if (err) {
8991c325aacSAlan Brady 		dev_err(&adapter->pdev->dev, "Failed to initialize queue registers for vport %u: %d\n",
9001c325aacSAlan Brady 			vport->vport_id, err);
9011c325aacSAlan Brady 		goto intr_rel;
9021c325aacSAlan Brady 	}
9031c325aacSAlan Brady 
904*95af467dSAlan Brady 	err = idpf_send_config_queues_msg(vport);
9051c325aacSAlan Brady 	if (err) {
9061c325aacSAlan Brady 		dev_err(&adapter->pdev->dev, "Failed to configure queues for vport %u, %d\n",
9071c325aacSAlan Brady 			vport->vport_id, err);
9081c325aacSAlan Brady 		goto intr_rel;
9091c325aacSAlan Brady 	}
9101c325aacSAlan Brady 
911*95af467dSAlan Brady 	vport_config = adapter->vport_config[vport->idx];
912*95af467dSAlan Brady 	if (vport_config->user_config.rss_data.rss_lut)
913*95af467dSAlan Brady 		err = idpf_config_rss(vport);
914*95af467dSAlan Brady 	else
915*95af467dSAlan Brady 		err = idpf_init_rss(vport);
916*95af467dSAlan Brady 	if (err) {
917*95af467dSAlan Brady 		dev_err(&adapter->pdev->dev, "Failed to initialize RSS for vport %u: %d\n",
918*95af467dSAlan Brady 			vport->vport_id, err);
919*95af467dSAlan Brady 		goto intr_rel;
920*95af467dSAlan Brady 	}
921*95af467dSAlan Brady 
9221c325aacSAlan Brady 	return 0;
9231c325aacSAlan Brady 
9241c325aacSAlan Brady intr_rel:
9251c325aacSAlan Brady 	idpf_vport_intr_rel(vport);
9261c325aacSAlan Brady queues_rel:
9271c325aacSAlan Brady 	idpf_vport_queues_rel(vport);
9281c325aacSAlan Brady 
9291c325aacSAlan Brady 	return err;
9301c325aacSAlan Brady }
9311c325aacSAlan Brady 
9321c325aacSAlan Brady /**
9330fe45467SPavan Kumar Linga  * idpf_init_task - Delayed initialization task
9340fe45467SPavan Kumar Linga  * @work: work_struct handle to our data
9350fe45467SPavan Kumar Linga  *
9360fe45467SPavan Kumar Linga  * Init task finishes up pending work started in probe. Due to the asynchronous
9370fe45467SPavan Kumar Linga  * nature in which the device communicates with hardware, we may have to wait
9380fe45467SPavan Kumar Linga  * several milliseconds to get a response.  Instead of busy polling in probe,
9390fe45467SPavan Kumar Linga  * pulling it out into a delayed work task prevents us from bogging down the
9400fe45467SPavan Kumar Linga  * whole system waiting for a response from hardware.
9410fe45467SPavan Kumar Linga  */
9420fe45467SPavan Kumar Linga void idpf_init_task(struct work_struct *work)
9430fe45467SPavan Kumar Linga {
944ce1b75d0SPavan Kumar Linga 	struct idpf_vport_config *vport_config;
9450fe45467SPavan Kumar Linga 	struct idpf_vport_max_q max_q;
9460fe45467SPavan Kumar Linga 	struct idpf_adapter *adapter;
9471c325aacSAlan Brady 	struct idpf_netdev_priv *np;
9480fe45467SPavan Kumar Linga 	struct idpf_vport *vport;
9490fe45467SPavan Kumar Linga 	u16 num_default_vports;
9500fe45467SPavan Kumar Linga 	struct pci_dev *pdev;
9510fe45467SPavan Kumar Linga 	bool default_vport;
9520fe45467SPavan Kumar Linga 	int index, err;
9530fe45467SPavan Kumar Linga 
9540fe45467SPavan Kumar Linga 	adapter = container_of(work, struct idpf_adapter, init_task.work);
9550fe45467SPavan Kumar Linga 
9560fe45467SPavan Kumar Linga 	num_default_vports = idpf_get_default_vports(adapter);
9570fe45467SPavan Kumar Linga 	if (adapter->num_alloc_vports < num_default_vports)
9580fe45467SPavan Kumar Linga 		default_vport = true;
9590fe45467SPavan Kumar Linga 	else
9600fe45467SPavan Kumar Linga 		default_vport = false;
9610fe45467SPavan Kumar Linga 
9620fe45467SPavan Kumar Linga 	err = idpf_vport_alloc_max_qs(adapter, &max_q);
9630fe45467SPavan Kumar Linga 	if (err)
9640fe45467SPavan Kumar Linga 		goto unwind_vports;
9650fe45467SPavan Kumar Linga 
9660fe45467SPavan Kumar Linga 	err = idpf_send_create_vport_msg(adapter, &max_q);
9670fe45467SPavan Kumar Linga 	if (err) {
9680fe45467SPavan Kumar Linga 		idpf_vport_dealloc_max_qs(adapter, &max_q);
9690fe45467SPavan Kumar Linga 		goto unwind_vports;
9700fe45467SPavan Kumar Linga 	}
9710fe45467SPavan Kumar Linga 
9720fe45467SPavan Kumar Linga 	pdev = adapter->pdev;
9730fe45467SPavan Kumar Linga 	vport = idpf_vport_alloc(adapter, &max_q);
9740fe45467SPavan Kumar Linga 	if (!vport) {
9750fe45467SPavan Kumar Linga 		err = -EFAULT;
9760fe45467SPavan Kumar Linga 		dev_err(&pdev->dev, "failed to allocate vport: %d\n",
9770fe45467SPavan Kumar Linga 			err);
9780fe45467SPavan Kumar Linga 		idpf_vport_dealloc_max_qs(adapter, &max_q);
9790fe45467SPavan Kumar Linga 		goto unwind_vports;
9800fe45467SPavan Kumar Linga 	}
9810fe45467SPavan Kumar Linga 
9820fe45467SPavan Kumar Linga 	index = vport->idx;
983ce1b75d0SPavan Kumar Linga 	vport_config = adapter->vport_config[index];
9840fe45467SPavan Kumar Linga 
9850fe45467SPavan Kumar Linga 	init_waitqueue_head(&vport->vchnl_wq);
9860fe45467SPavan Kumar Linga 
9870fe45467SPavan Kumar Linga 	mutex_init(&vport->vc_buf_lock);
988ce1b75d0SPavan Kumar Linga 	spin_lock_init(&vport_config->mac_filter_list_lock);
989ce1b75d0SPavan Kumar Linga 
990ce1b75d0SPavan Kumar Linga 	INIT_LIST_HEAD(&vport_config->user_config.mac_filter_list);
991ce1b75d0SPavan Kumar Linga 
992ce1b75d0SPavan Kumar Linga 	err = idpf_check_supported_desc_ids(vport);
993ce1b75d0SPavan Kumar Linga 	if (err) {
994ce1b75d0SPavan Kumar Linga 		dev_err(&pdev->dev, "failed to get required descriptor ids\n");
995ce1b75d0SPavan Kumar Linga 		goto cfg_netdev_err;
996ce1b75d0SPavan Kumar Linga 	}
9970fe45467SPavan Kumar Linga 
9980fe45467SPavan Kumar Linga 	if (idpf_cfg_netdev(vport))
9990fe45467SPavan Kumar Linga 		goto cfg_netdev_err;
10000fe45467SPavan Kumar Linga 
1001ce1b75d0SPavan Kumar Linga 	err = idpf_send_get_rx_ptype_msg(vport);
1002ce1b75d0SPavan Kumar Linga 	if (err)
1003ce1b75d0SPavan Kumar Linga 		goto handle_err;
1004ce1b75d0SPavan Kumar Linga 
10051c325aacSAlan Brady 	/* Once state is put into DOWN, driver is ready for dev_open */
10061c325aacSAlan Brady 	np = netdev_priv(vport->netdev);
10071c325aacSAlan Brady 	np->state = __IDPF_VPORT_DOWN;
10081c325aacSAlan Brady 	if (test_and_clear_bit(IDPF_VPORT_UP_REQUESTED, vport_config->flags))
10091c325aacSAlan Brady 		idpf_vport_open(vport, true);
10101c325aacSAlan Brady 
10110fe45467SPavan Kumar Linga 	/* Spawn and return 'idpf_init_task' work queue until all the
10120fe45467SPavan Kumar Linga 	 * default vports are created
10130fe45467SPavan Kumar Linga 	 */
10140fe45467SPavan Kumar Linga 	if (adapter->num_alloc_vports < num_default_vports) {
10150fe45467SPavan Kumar Linga 		queue_delayed_work(adapter->init_wq, &adapter->init_task,
10160fe45467SPavan Kumar Linga 				   msecs_to_jiffies(5 * (adapter->pdev->devfn & 0x07)));
10170fe45467SPavan Kumar Linga 
10180fe45467SPavan Kumar Linga 		return;
10190fe45467SPavan Kumar Linga 	}
10200fe45467SPavan Kumar Linga 
10210fe45467SPavan Kumar Linga 	for (index = 0; index < adapter->max_vports; index++) {
10220fe45467SPavan Kumar Linga 		if (adapter->netdevs[index] &&
10230fe45467SPavan Kumar Linga 		    !test_bit(IDPF_VPORT_REG_NETDEV,
10240fe45467SPavan Kumar Linga 			      adapter->vport_config[index]->flags)) {
10250fe45467SPavan Kumar Linga 			register_netdev(adapter->netdevs[index]);
10260fe45467SPavan Kumar Linga 			set_bit(IDPF_VPORT_REG_NETDEV,
10270fe45467SPavan Kumar Linga 				adapter->vport_config[index]->flags);
10280fe45467SPavan Kumar Linga 		}
10290fe45467SPavan Kumar Linga 	}
10300fe45467SPavan Kumar Linga 
10310fe45467SPavan Kumar Linga 	/* As all the required vports are created, clear the reset flag
10320fe45467SPavan Kumar Linga 	 * unconditionally here in case we were in reset and the link was down.
10330fe45467SPavan Kumar Linga 	 */
10340fe45467SPavan Kumar Linga 	clear_bit(IDPF_HR_RESET_IN_PROG, adapter->flags);
10350fe45467SPavan Kumar Linga 
10360fe45467SPavan Kumar Linga 	return;
10370fe45467SPavan Kumar Linga 
1038ce1b75d0SPavan Kumar Linga handle_err:
1039ce1b75d0SPavan Kumar Linga 	idpf_decfg_netdev(vport);
10400fe45467SPavan Kumar Linga cfg_netdev_err:
10410fe45467SPavan Kumar Linga 	idpf_vport_rel(vport);
10420fe45467SPavan Kumar Linga 	adapter->vports[index] = NULL;
10430fe45467SPavan Kumar Linga unwind_vports:
10440fe45467SPavan Kumar Linga 	if (default_vport) {
10450fe45467SPavan Kumar Linga 		for (index = 0; index < adapter->max_vports; index++) {
10460fe45467SPavan Kumar Linga 			if (adapter->vports[index])
10470fe45467SPavan Kumar Linga 				idpf_vport_dealloc(adapter->vports[index]);
10480fe45467SPavan Kumar Linga 		}
10490fe45467SPavan Kumar Linga 	}
10500fe45467SPavan Kumar Linga 	clear_bit(IDPF_HR_RESET_IN_PROG, adapter->flags);
10510fe45467SPavan Kumar Linga }
10520fe45467SPavan Kumar Linga 
10530fe45467SPavan Kumar Linga /**
10540fe45467SPavan Kumar Linga  * idpf_deinit_task - Device deinit routine
10550fe45467SPavan Kumar Linga  * @adapter: Driver specific private structure
10560fe45467SPavan Kumar Linga  *
10570fe45467SPavan Kumar Linga  * Extended remove logic which will be used for
10580fe45467SPavan Kumar Linga  * hard reset as well
10590fe45467SPavan Kumar Linga  */
10600fe45467SPavan Kumar Linga void idpf_deinit_task(struct idpf_adapter *adapter)
10610fe45467SPavan Kumar Linga {
10620fe45467SPavan Kumar Linga 	unsigned int i;
10630fe45467SPavan Kumar Linga 
10640fe45467SPavan Kumar Linga 	/* Wait until the init_task is done else this thread might release
10650fe45467SPavan Kumar Linga 	 * the resources first and the other thread might end up in a bad state
10660fe45467SPavan Kumar Linga 	 */
10670fe45467SPavan Kumar Linga 	cancel_delayed_work_sync(&adapter->init_task);
10680fe45467SPavan Kumar Linga 
10690fe45467SPavan Kumar Linga 	if (!adapter->vports)
10700fe45467SPavan Kumar Linga 		return;
10710fe45467SPavan Kumar Linga 
10720fe45467SPavan Kumar Linga 	for (i = 0; i < adapter->max_vports; i++) {
10730fe45467SPavan Kumar Linga 		if (adapter->vports[i])
10740fe45467SPavan Kumar Linga 			idpf_vport_dealloc(adapter->vports[i]);
10750fe45467SPavan Kumar Linga 	}
10760fe45467SPavan Kumar Linga }
10770fe45467SPavan Kumar Linga 
10780fe45467SPavan Kumar Linga /**
10798077c727SJoshua Hay  * idpf_check_reset_complete - check that reset is complete
10808077c727SJoshua Hay  * @hw: pointer to hw struct
10818077c727SJoshua Hay  * @reset_reg: struct with reset registers
10828077c727SJoshua Hay  *
10838077c727SJoshua Hay  * Returns 0 if device is ready to use, or -EBUSY if it's in reset.
10848077c727SJoshua Hay  **/
10858077c727SJoshua Hay static int idpf_check_reset_complete(struct idpf_hw *hw,
10868077c727SJoshua Hay 				     struct idpf_reset_reg *reset_reg)
10878077c727SJoshua Hay {
10888077c727SJoshua Hay 	struct idpf_adapter *adapter = hw->back;
10898077c727SJoshua Hay 	int i;
10908077c727SJoshua Hay 
10918077c727SJoshua Hay 	for (i = 0; i < 2000; i++) {
10928077c727SJoshua Hay 		u32 reg_val = readl(reset_reg->rstat);
10938077c727SJoshua Hay 
10948077c727SJoshua Hay 		/* 0xFFFFFFFF might be read if other side hasn't cleared the
10958077c727SJoshua Hay 		 * register for us yet and 0xFFFFFFFF is not a valid value for
10968077c727SJoshua Hay 		 * the register, so treat that as invalid.
10978077c727SJoshua Hay 		 */
10988077c727SJoshua Hay 		if (reg_val != 0xFFFFFFFF && (reg_val & reset_reg->rstat_m))
10998077c727SJoshua Hay 			return 0;
11008077c727SJoshua Hay 
11018077c727SJoshua Hay 		usleep_range(5000, 10000);
11028077c727SJoshua Hay 	}
11038077c727SJoshua Hay 
11048077c727SJoshua Hay 	dev_warn(&adapter->pdev->dev, "Device reset timeout!\n");
11058077c727SJoshua Hay 	/* Clear the reset flag unconditionally here since the reset
11068077c727SJoshua Hay 	 * technically isn't in progress anymore from the driver's perspective
11078077c727SJoshua Hay 	 */
11088077c727SJoshua Hay 	clear_bit(IDPF_HR_RESET_IN_PROG, adapter->flags);
11098077c727SJoshua Hay 
11108077c727SJoshua Hay 	return -EBUSY;
11118077c727SJoshua Hay }
11128077c727SJoshua Hay 
11138077c727SJoshua Hay /**
11140fe45467SPavan Kumar Linga  * idpf_set_vport_state - Set the vport state to be after the reset
11150fe45467SPavan Kumar Linga  * @adapter: Driver specific private structure
11160fe45467SPavan Kumar Linga  */
11170fe45467SPavan Kumar Linga static void idpf_set_vport_state(struct idpf_adapter *adapter)
11180fe45467SPavan Kumar Linga {
11190fe45467SPavan Kumar Linga 	u16 i;
11200fe45467SPavan Kumar Linga 
11210fe45467SPavan Kumar Linga 	for (i = 0; i < adapter->max_vports; i++) {
11220fe45467SPavan Kumar Linga 		struct idpf_netdev_priv *np;
11230fe45467SPavan Kumar Linga 
11240fe45467SPavan Kumar Linga 		if (!adapter->netdevs[i])
11250fe45467SPavan Kumar Linga 			continue;
11260fe45467SPavan Kumar Linga 
11270fe45467SPavan Kumar Linga 		np = netdev_priv(adapter->netdevs[i]);
11280fe45467SPavan Kumar Linga 		if (np->state == __IDPF_VPORT_UP)
11290fe45467SPavan Kumar Linga 			set_bit(IDPF_VPORT_UP_REQUESTED,
11300fe45467SPavan Kumar Linga 				adapter->vport_config[i]->flags);
11310fe45467SPavan Kumar Linga 	}
11320fe45467SPavan Kumar Linga }
11330fe45467SPavan Kumar Linga 
11340fe45467SPavan Kumar Linga /**
11358077c727SJoshua Hay  * idpf_init_hard_reset - Initiate a hardware reset
11368077c727SJoshua Hay  * @adapter: Driver specific private structure
11378077c727SJoshua Hay  *
11388077c727SJoshua Hay  * Deallocate the vports and all the resources associated with them and
11398077c727SJoshua Hay  * reallocate. Also reinitialize the mailbox. Return 0 on success,
11408077c727SJoshua Hay  * negative on failure.
11418077c727SJoshua Hay  */
11428077c727SJoshua Hay static int idpf_init_hard_reset(struct idpf_adapter *adapter)
11438077c727SJoshua Hay {
11448077c727SJoshua Hay 	struct idpf_reg_ops *reg_ops = &adapter->dev_ops.reg_ops;
11458077c727SJoshua Hay 	struct device *dev = &adapter->pdev->dev;
11460fe45467SPavan Kumar Linga 	struct net_device *netdev;
11478077c727SJoshua Hay 	int err;
11480fe45467SPavan Kumar Linga 	u16 i;
11498077c727SJoshua Hay 
11508077c727SJoshua Hay 	mutex_lock(&adapter->vport_ctrl_lock);
11518077c727SJoshua Hay 
11528077c727SJoshua Hay 	dev_info(dev, "Device HW Reset initiated\n");
11530fe45467SPavan Kumar Linga 
11540fe45467SPavan Kumar Linga 	/* Avoid TX hangs on reset */
11550fe45467SPavan Kumar Linga 	for (i = 0; i < adapter->max_vports; i++) {
11560fe45467SPavan Kumar Linga 		netdev = adapter->netdevs[i];
11570fe45467SPavan Kumar Linga 		if (!netdev)
11580fe45467SPavan Kumar Linga 			continue;
11590fe45467SPavan Kumar Linga 
11600fe45467SPavan Kumar Linga 		netif_carrier_off(netdev);
11610fe45467SPavan Kumar Linga 		netif_tx_disable(netdev);
11620fe45467SPavan Kumar Linga 	}
11630fe45467SPavan Kumar Linga 
11648077c727SJoshua Hay 	/* Prepare for reset */
11658077c727SJoshua Hay 	if (test_and_clear_bit(IDPF_HR_DRV_LOAD, adapter->flags)) {
11668077c727SJoshua Hay 		reg_ops->trigger_reset(adapter, IDPF_HR_DRV_LOAD);
11678077c727SJoshua Hay 	} else if (test_and_clear_bit(IDPF_HR_FUNC_RESET, adapter->flags)) {
11688077c727SJoshua Hay 		bool is_reset = idpf_is_reset_detected(adapter);
11698077c727SJoshua Hay 
11700fe45467SPavan Kumar Linga 		idpf_set_vport_state(adapter);
11714930fbf4SPavan Kumar Linga 		idpf_vc_core_deinit(adapter);
11728077c727SJoshua Hay 		if (!is_reset)
11738077c727SJoshua Hay 			reg_ops->trigger_reset(adapter, IDPF_HR_FUNC_RESET);
11748077c727SJoshua Hay 		idpf_deinit_dflt_mbx(adapter);
11758077c727SJoshua Hay 	} else {
11768077c727SJoshua Hay 		dev_err(dev, "Unhandled hard reset cause\n");
11778077c727SJoshua Hay 		err = -EBADRQC;
11788077c727SJoshua Hay 		goto unlock_mutex;
11798077c727SJoshua Hay 	}
11808077c727SJoshua Hay 
11818077c727SJoshua Hay 	/* Wait for reset to complete */
11828077c727SJoshua Hay 	err = idpf_check_reset_complete(&adapter->hw, &adapter->reset_reg);
11838077c727SJoshua Hay 	if (err) {
11848077c727SJoshua 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",
11858077c727SJoshua Hay 			adapter->state);
11868077c727SJoshua Hay 		goto unlock_mutex;
11878077c727SJoshua Hay 	}
11888077c727SJoshua Hay 
11898077c727SJoshua Hay 	/* Reset is complete and so start building the driver resources again */
11908077c727SJoshua Hay 	err = idpf_init_dflt_mbx(adapter);
11914930fbf4SPavan Kumar Linga 	if (err) {
11928077c727SJoshua Hay 		dev_err(dev, "Failed to initialize default mailbox: %d\n", err);
11934930fbf4SPavan Kumar Linga 		goto unlock_mutex;
11944930fbf4SPavan Kumar Linga 	}
11954930fbf4SPavan Kumar Linga 
11964930fbf4SPavan Kumar Linga 	/* Initialize the state machine, also allocate memory and request
11974930fbf4SPavan Kumar Linga 	 * resources
11984930fbf4SPavan Kumar Linga 	 */
11994930fbf4SPavan Kumar Linga 	err = idpf_vc_core_init(adapter);
12004930fbf4SPavan Kumar Linga 	if (err) {
12014930fbf4SPavan Kumar Linga 		idpf_deinit_dflt_mbx(adapter);
12024930fbf4SPavan Kumar Linga 		goto unlock_mutex;
12034930fbf4SPavan Kumar Linga 	}
12048077c727SJoshua Hay 
12050fe45467SPavan Kumar Linga 	/* Wait till all the vports are initialized to release the reset lock,
12060fe45467SPavan Kumar Linga 	 * else user space callbacks may access uninitialized vports
12070fe45467SPavan Kumar Linga 	 */
12080fe45467SPavan Kumar Linga 	while (test_bit(IDPF_HR_RESET_IN_PROG, adapter->flags))
12090fe45467SPavan Kumar Linga 		msleep(100);
12100fe45467SPavan Kumar Linga 
12118077c727SJoshua Hay unlock_mutex:
12128077c727SJoshua Hay 	mutex_unlock(&adapter->vport_ctrl_lock);
12138077c727SJoshua Hay 
12148077c727SJoshua Hay 	return err;
12158077c727SJoshua Hay }
12168077c727SJoshua Hay 
12178077c727SJoshua Hay /**
12188077c727SJoshua Hay  * idpf_vc_event_task - Handle virtchannel event logic
12198077c727SJoshua Hay  * @work: work queue struct
12208077c727SJoshua Hay  */
12218077c727SJoshua Hay void idpf_vc_event_task(struct work_struct *work)
12228077c727SJoshua Hay {
12238077c727SJoshua Hay 	struct idpf_adapter *adapter;
12248077c727SJoshua Hay 
12258077c727SJoshua Hay 	adapter = container_of(work, struct idpf_adapter, vc_event_task.work);
12268077c727SJoshua Hay 
12278077c727SJoshua Hay 	if (test_bit(IDPF_REMOVE_IN_PROG, adapter->flags))
12288077c727SJoshua Hay 		return;
12298077c727SJoshua Hay 
12308077c727SJoshua Hay 	if (test_bit(IDPF_HR_FUNC_RESET, adapter->flags) ||
12318077c727SJoshua Hay 	    test_bit(IDPF_HR_DRV_LOAD, adapter->flags)) {
12328077c727SJoshua Hay 		set_bit(IDPF_HR_RESET_IN_PROG, adapter->flags);
12338077c727SJoshua Hay 		idpf_init_hard_reset(adapter);
12348077c727SJoshua Hay 	}
12358077c727SJoshua Hay }
12368077c727SJoshua Hay 
12378077c727SJoshua Hay /**
12381c325aacSAlan Brady  * idpf_open - Called when a network interface becomes active
12391c325aacSAlan Brady  * @netdev: network interface device structure
12401c325aacSAlan Brady  *
12411c325aacSAlan Brady  * The open entry point is called when a network interface is made
12421c325aacSAlan Brady  * active by the system (IFF_UP).  At this point all resources needed
12431c325aacSAlan Brady  * for transmit and receive operations are allocated, the interrupt
12441c325aacSAlan Brady  * handler is registered with the OS, the netdev watchdog is enabled,
12451c325aacSAlan Brady  * and the stack is notified that the interface is ready.
12461c325aacSAlan Brady  *
12471c325aacSAlan Brady  * Returns 0 on success, negative value on failure
12481c325aacSAlan Brady  */
12491c325aacSAlan Brady static int idpf_open(struct net_device *netdev)
12501c325aacSAlan Brady {
12511c325aacSAlan Brady 	struct idpf_vport *vport;
12521c325aacSAlan Brady 	int err;
12531c325aacSAlan Brady 
12541c325aacSAlan Brady 	idpf_vport_ctrl_lock(netdev);
12551c325aacSAlan Brady 	vport = idpf_netdev_to_vport(netdev);
12561c325aacSAlan Brady 
12571c325aacSAlan Brady 	err = idpf_vport_open(vport, true);
12581c325aacSAlan Brady 
12591c325aacSAlan Brady 	idpf_vport_ctrl_unlock(netdev);
12601c325aacSAlan Brady 
12611c325aacSAlan Brady 	return err;
12621c325aacSAlan Brady }
12631c325aacSAlan Brady 
12641c325aacSAlan Brady /**
12658077c727SJoshua Hay  * idpf_alloc_dma_mem - Allocate dma memory
12668077c727SJoshua Hay  * @hw: pointer to hw struct
12678077c727SJoshua Hay  * @mem: pointer to dma_mem struct
12688077c727SJoshua Hay  * @size: size of the memory to allocate
12698077c727SJoshua Hay  */
12708077c727SJoshua Hay void *idpf_alloc_dma_mem(struct idpf_hw *hw, struct idpf_dma_mem *mem, u64 size)
12718077c727SJoshua Hay {
12728077c727SJoshua Hay 	struct idpf_adapter *adapter = hw->back;
12738077c727SJoshua Hay 	size_t sz = ALIGN(size, 4096);
12748077c727SJoshua Hay 
12758077c727SJoshua Hay 	mem->va = dma_alloc_coherent(&adapter->pdev->dev, sz,
12768077c727SJoshua Hay 				     &mem->pa, GFP_KERNEL);
12778077c727SJoshua Hay 	mem->size = sz;
12788077c727SJoshua Hay 
12798077c727SJoshua Hay 	return mem->va;
12808077c727SJoshua Hay }
12818077c727SJoshua Hay 
12828077c727SJoshua Hay /**
12838077c727SJoshua Hay  * idpf_free_dma_mem - Free the allocated dma memory
12848077c727SJoshua Hay  * @hw: pointer to hw struct
12858077c727SJoshua Hay  * @mem: pointer to dma_mem struct
12868077c727SJoshua Hay  */
12878077c727SJoshua Hay void idpf_free_dma_mem(struct idpf_hw *hw, struct idpf_dma_mem *mem)
12888077c727SJoshua Hay {
12898077c727SJoshua Hay 	struct idpf_adapter *adapter = hw->back;
12908077c727SJoshua Hay 
12918077c727SJoshua Hay 	dma_free_coherent(&adapter->pdev->dev, mem->size,
12928077c727SJoshua Hay 			  mem->va, mem->pa);
12938077c727SJoshua Hay 	mem->size = 0;
12948077c727SJoshua Hay 	mem->va = NULL;
12958077c727SJoshua Hay 	mem->pa = 0;
12968077c727SJoshua Hay }
12971c325aacSAlan Brady 
12981c325aacSAlan Brady static const struct net_device_ops idpf_netdev_ops_splitq = {
12991c325aacSAlan Brady 	.ndo_open = idpf_open,
13001c325aacSAlan Brady 	.ndo_stop = idpf_stop,
13011c325aacSAlan Brady };
13021c325aacSAlan Brady 
13031c325aacSAlan Brady static const struct net_device_ops idpf_netdev_ops_singleq = {
13041c325aacSAlan Brady 	.ndo_open = idpf_open,
13051c325aacSAlan Brady 	.ndo_stop = idpf_stop,
13061c325aacSAlan Brady };
1307