xref: /linux/drivers/net/ethernet/intel/idpf/idpf_lib.c (revision 4930fbf419a72d7477426fd883bfc37e20a61a6e)
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 
6*4930fbf4SPavan Kumar Linga const char * const idpf_vport_vc_state_str[] = {
7*4930fbf4SPavan Kumar Linga 	IDPF_FOREACH_VPORT_VC_STATE(IDPF_GEN_STRING)
8*4930fbf4SPavan Kumar Linga };
9*4930fbf4SPavan Kumar Linga 
10*4930fbf4SPavan Kumar Linga /**
11*4930fbf4SPavan Kumar Linga  * idpf_init_vector_stack - Fill the MSIX vector stack with vector index
12*4930fbf4SPavan Kumar Linga  * @adapter: private data struct
13*4930fbf4SPavan Kumar Linga  *
14*4930fbf4SPavan Kumar Linga  * Return 0 on success, error on failure
15*4930fbf4SPavan Kumar Linga  */
16*4930fbf4SPavan Kumar Linga static int idpf_init_vector_stack(struct idpf_adapter *adapter)
17*4930fbf4SPavan Kumar Linga {
18*4930fbf4SPavan Kumar Linga 	struct idpf_vector_lifo *stack;
19*4930fbf4SPavan Kumar Linga 	u16 min_vec;
20*4930fbf4SPavan Kumar Linga 	u32 i;
21*4930fbf4SPavan Kumar Linga 
22*4930fbf4SPavan Kumar Linga 	mutex_lock(&adapter->vector_lock);
23*4930fbf4SPavan Kumar Linga 	min_vec = adapter->num_msix_entries - adapter->num_avail_msix;
24*4930fbf4SPavan Kumar Linga 	stack = &adapter->vector_stack;
25*4930fbf4SPavan Kumar Linga 	stack->size = adapter->num_msix_entries;
26*4930fbf4SPavan Kumar Linga 	/* set the base and top to point at start of the 'free pool' to
27*4930fbf4SPavan Kumar Linga 	 * distribute the unused vectors on-demand basis
28*4930fbf4SPavan Kumar Linga 	 */
29*4930fbf4SPavan Kumar Linga 	stack->base = min_vec;
30*4930fbf4SPavan Kumar Linga 	stack->top = min_vec;
31*4930fbf4SPavan Kumar Linga 
32*4930fbf4SPavan Kumar Linga 	stack->vec_idx = kcalloc(stack->size, sizeof(u16), GFP_KERNEL);
33*4930fbf4SPavan Kumar Linga 	if (!stack->vec_idx) {
34*4930fbf4SPavan Kumar Linga 		mutex_unlock(&adapter->vector_lock);
35*4930fbf4SPavan Kumar Linga 
36*4930fbf4SPavan Kumar Linga 		return -ENOMEM;
37*4930fbf4SPavan Kumar Linga 	}
38*4930fbf4SPavan Kumar Linga 
39*4930fbf4SPavan Kumar Linga 	for (i = 0; i < stack->size; i++)
40*4930fbf4SPavan Kumar Linga 		stack->vec_idx[i] = i;
41*4930fbf4SPavan Kumar Linga 
42*4930fbf4SPavan Kumar Linga 	mutex_unlock(&adapter->vector_lock);
43*4930fbf4SPavan Kumar Linga 
44*4930fbf4SPavan Kumar Linga 	return 0;
45*4930fbf4SPavan Kumar Linga }
46*4930fbf4SPavan Kumar Linga 
47*4930fbf4SPavan Kumar Linga /**
48*4930fbf4SPavan Kumar Linga  * idpf_deinit_vector_stack - zero out the MSIX vector stack
49*4930fbf4SPavan Kumar Linga  * @adapter: private data struct
50*4930fbf4SPavan Kumar Linga  */
51*4930fbf4SPavan Kumar Linga static void idpf_deinit_vector_stack(struct idpf_adapter *adapter)
52*4930fbf4SPavan Kumar Linga {
53*4930fbf4SPavan Kumar Linga 	struct idpf_vector_lifo *stack;
54*4930fbf4SPavan Kumar Linga 
55*4930fbf4SPavan Kumar Linga 	mutex_lock(&adapter->vector_lock);
56*4930fbf4SPavan Kumar Linga 	stack = &adapter->vector_stack;
57*4930fbf4SPavan Kumar Linga 	kfree(stack->vec_idx);
58*4930fbf4SPavan Kumar Linga 	stack->vec_idx = NULL;
59*4930fbf4SPavan Kumar Linga 	mutex_unlock(&adapter->vector_lock);
60*4930fbf4SPavan Kumar Linga }
61*4930fbf4SPavan Kumar Linga 
62*4930fbf4SPavan Kumar Linga /**
63*4930fbf4SPavan Kumar Linga  * idpf_mb_intr_rel_irq - Free the IRQ association with the OS
64*4930fbf4SPavan Kumar Linga  * @adapter: adapter structure
65*4930fbf4SPavan Kumar Linga  *
66*4930fbf4SPavan Kumar Linga  * This will also disable interrupt mode and queue up mailbox task. Mailbox
67*4930fbf4SPavan Kumar Linga  * task will reschedule itself if not in interrupt mode.
68*4930fbf4SPavan Kumar Linga  */
69*4930fbf4SPavan Kumar Linga static void idpf_mb_intr_rel_irq(struct idpf_adapter *adapter)
70*4930fbf4SPavan Kumar Linga {
71*4930fbf4SPavan Kumar Linga 	clear_bit(IDPF_MB_INTR_MODE, adapter->flags);
72*4930fbf4SPavan Kumar Linga 	free_irq(adapter->msix_entries[0].vector, adapter);
73*4930fbf4SPavan Kumar Linga 	queue_delayed_work(adapter->mbx_wq, &adapter->mbx_task, 0);
74*4930fbf4SPavan Kumar Linga }
75*4930fbf4SPavan Kumar Linga 
76*4930fbf4SPavan Kumar Linga /**
77*4930fbf4SPavan Kumar Linga  * idpf_intr_rel - Release interrupt capabilities and free memory
78*4930fbf4SPavan Kumar Linga  * @adapter: adapter to disable interrupts on
79*4930fbf4SPavan Kumar Linga  */
80*4930fbf4SPavan Kumar Linga void idpf_intr_rel(struct idpf_adapter *adapter)
81*4930fbf4SPavan Kumar Linga {
82*4930fbf4SPavan Kumar Linga 	int err;
83*4930fbf4SPavan Kumar Linga 
84*4930fbf4SPavan Kumar Linga 	if (!adapter->msix_entries)
85*4930fbf4SPavan Kumar Linga 		return;
86*4930fbf4SPavan Kumar Linga 
87*4930fbf4SPavan Kumar Linga 	idpf_mb_intr_rel_irq(adapter);
88*4930fbf4SPavan Kumar Linga 	pci_free_irq_vectors(adapter->pdev);
89*4930fbf4SPavan Kumar Linga 
90*4930fbf4SPavan Kumar Linga 	err = idpf_send_dealloc_vectors_msg(adapter);
91*4930fbf4SPavan Kumar Linga 	if (err)
92*4930fbf4SPavan Kumar Linga 		dev_err(&adapter->pdev->dev,
93*4930fbf4SPavan Kumar Linga 			"Failed to deallocate vectors: %d\n", err);
94*4930fbf4SPavan Kumar Linga 
95*4930fbf4SPavan Kumar Linga 	idpf_deinit_vector_stack(adapter);
96*4930fbf4SPavan Kumar Linga 	kfree(adapter->msix_entries);
97*4930fbf4SPavan Kumar Linga 	adapter->msix_entries = NULL;
98*4930fbf4SPavan Kumar Linga }
99*4930fbf4SPavan Kumar Linga 
100*4930fbf4SPavan Kumar Linga /**
101*4930fbf4SPavan Kumar Linga  * idpf_mb_intr_clean - Interrupt handler for the mailbox
102*4930fbf4SPavan Kumar Linga  * @irq: interrupt number
103*4930fbf4SPavan Kumar Linga  * @data: pointer to the adapter structure
104*4930fbf4SPavan Kumar Linga  */
105*4930fbf4SPavan Kumar Linga static irqreturn_t idpf_mb_intr_clean(int __always_unused irq, void *data)
106*4930fbf4SPavan Kumar Linga {
107*4930fbf4SPavan Kumar Linga 	struct idpf_adapter *adapter = (struct idpf_adapter *)data;
108*4930fbf4SPavan Kumar Linga 
109*4930fbf4SPavan Kumar Linga 	queue_delayed_work(adapter->mbx_wq, &adapter->mbx_task, 0);
110*4930fbf4SPavan Kumar Linga 
111*4930fbf4SPavan Kumar Linga 	return IRQ_HANDLED;
112*4930fbf4SPavan Kumar Linga }
113*4930fbf4SPavan Kumar Linga 
114*4930fbf4SPavan Kumar Linga /**
115*4930fbf4SPavan Kumar Linga  * idpf_mb_irq_enable - Enable MSIX interrupt for the mailbox
116*4930fbf4SPavan Kumar Linga  * @adapter: adapter to get the hardware address for register write
117*4930fbf4SPavan Kumar Linga  */
118*4930fbf4SPavan Kumar Linga static void idpf_mb_irq_enable(struct idpf_adapter *adapter)
119*4930fbf4SPavan Kumar Linga {
120*4930fbf4SPavan Kumar Linga 	struct idpf_intr_reg *intr = &adapter->mb_vector.intr_reg;
121*4930fbf4SPavan Kumar Linga 	u32 val;
122*4930fbf4SPavan Kumar Linga 
123*4930fbf4SPavan Kumar Linga 	val = intr->dyn_ctl_intena_m | intr->dyn_ctl_itridx_m;
124*4930fbf4SPavan Kumar Linga 	writel(val, intr->dyn_ctl);
125*4930fbf4SPavan Kumar Linga 	writel(intr->icr_ena_ctlq_m, intr->icr_ena);
126*4930fbf4SPavan Kumar Linga }
127*4930fbf4SPavan Kumar Linga 
128*4930fbf4SPavan Kumar Linga /**
129*4930fbf4SPavan Kumar Linga  * idpf_mb_intr_req_irq - Request irq for the mailbox interrupt
130*4930fbf4SPavan Kumar Linga  * @adapter: adapter structure to pass to the mailbox irq handler
131*4930fbf4SPavan Kumar Linga  */
132*4930fbf4SPavan Kumar Linga static int idpf_mb_intr_req_irq(struct idpf_adapter *adapter)
133*4930fbf4SPavan Kumar Linga {
134*4930fbf4SPavan Kumar Linga 	struct idpf_q_vector *mb_vector = &adapter->mb_vector;
135*4930fbf4SPavan Kumar Linga 	int irq_num, mb_vidx = 0, err;
136*4930fbf4SPavan Kumar Linga 
137*4930fbf4SPavan Kumar Linga 	irq_num = adapter->msix_entries[mb_vidx].vector;
138*4930fbf4SPavan Kumar Linga 	mb_vector->name = kasprintf(GFP_KERNEL, "%s-%s-%d",
139*4930fbf4SPavan Kumar Linga 				    dev_driver_string(&adapter->pdev->dev),
140*4930fbf4SPavan Kumar Linga 				    "Mailbox", mb_vidx);
141*4930fbf4SPavan Kumar Linga 	err = request_irq(irq_num, adapter->irq_mb_handler, 0,
142*4930fbf4SPavan Kumar Linga 			  mb_vector->name, adapter);
143*4930fbf4SPavan Kumar Linga 	if (err) {
144*4930fbf4SPavan Kumar Linga 		dev_err(&adapter->pdev->dev,
145*4930fbf4SPavan Kumar Linga 			"IRQ request for mailbox failed, error: %d\n", err);
146*4930fbf4SPavan Kumar Linga 
147*4930fbf4SPavan Kumar Linga 		return err;
148*4930fbf4SPavan Kumar Linga 	}
149*4930fbf4SPavan Kumar Linga 
150*4930fbf4SPavan Kumar Linga 	set_bit(IDPF_MB_INTR_MODE, adapter->flags);
151*4930fbf4SPavan Kumar Linga 
152*4930fbf4SPavan Kumar Linga 	return 0;
153*4930fbf4SPavan Kumar Linga }
154*4930fbf4SPavan Kumar Linga 
155*4930fbf4SPavan Kumar Linga /**
156*4930fbf4SPavan Kumar Linga  * idpf_set_mb_vec_id - Set vector index for mailbox
157*4930fbf4SPavan Kumar Linga  * @adapter: adapter structure to access the vector chunks
158*4930fbf4SPavan Kumar Linga  *
159*4930fbf4SPavan Kumar Linga  * The first vector id in the requested vector chunks from the CP is for
160*4930fbf4SPavan Kumar Linga  * the mailbox
161*4930fbf4SPavan Kumar Linga  */
162*4930fbf4SPavan Kumar Linga static void idpf_set_mb_vec_id(struct idpf_adapter *adapter)
163*4930fbf4SPavan Kumar Linga {
164*4930fbf4SPavan Kumar Linga 	if (adapter->req_vec_chunks)
165*4930fbf4SPavan Kumar Linga 		adapter->mb_vector.v_idx =
166*4930fbf4SPavan Kumar Linga 			le16_to_cpu(adapter->caps.mailbox_vector_id);
167*4930fbf4SPavan Kumar Linga 	else
168*4930fbf4SPavan Kumar Linga 		adapter->mb_vector.v_idx = 0;
169*4930fbf4SPavan Kumar Linga }
170*4930fbf4SPavan Kumar Linga 
171*4930fbf4SPavan Kumar Linga /**
172*4930fbf4SPavan Kumar Linga  * idpf_mb_intr_init - Initialize the mailbox interrupt
173*4930fbf4SPavan Kumar Linga  * @adapter: adapter structure to store the mailbox vector
174*4930fbf4SPavan Kumar Linga  */
175*4930fbf4SPavan Kumar Linga static int idpf_mb_intr_init(struct idpf_adapter *adapter)
176*4930fbf4SPavan Kumar Linga {
177*4930fbf4SPavan Kumar Linga 	adapter->dev_ops.reg_ops.mb_intr_reg_init(adapter);
178*4930fbf4SPavan Kumar Linga 	adapter->irq_mb_handler = idpf_mb_intr_clean;
179*4930fbf4SPavan Kumar Linga 
180*4930fbf4SPavan Kumar Linga 	return idpf_mb_intr_req_irq(adapter);
181*4930fbf4SPavan Kumar Linga }
182*4930fbf4SPavan Kumar Linga 
183*4930fbf4SPavan Kumar Linga /**
184*4930fbf4SPavan Kumar Linga  * idpf_intr_req - Request interrupt capabilities
185*4930fbf4SPavan Kumar Linga  * @adapter: adapter to enable interrupts on
186*4930fbf4SPavan Kumar Linga  *
187*4930fbf4SPavan Kumar Linga  * Returns 0 on success, negative on failure
188*4930fbf4SPavan Kumar Linga  */
189*4930fbf4SPavan Kumar Linga int idpf_intr_req(struct idpf_adapter *adapter)
190*4930fbf4SPavan Kumar Linga {
191*4930fbf4SPavan Kumar Linga 	u16 default_vports = idpf_get_default_vports(adapter);
192*4930fbf4SPavan Kumar Linga 	int num_q_vecs, total_vecs, num_vec_ids;
193*4930fbf4SPavan Kumar Linga 	int min_vectors, v_actual, err;
194*4930fbf4SPavan Kumar Linga 	unsigned int vector;
195*4930fbf4SPavan Kumar Linga 	u16 *vecids;
196*4930fbf4SPavan Kumar Linga 
197*4930fbf4SPavan Kumar Linga 	total_vecs = idpf_get_reserved_vecs(adapter);
198*4930fbf4SPavan Kumar Linga 	num_q_vecs = total_vecs - IDPF_MBX_Q_VEC;
199*4930fbf4SPavan Kumar Linga 
200*4930fbf4SPavan Kumar Linga 	err = idpf_send_alloc_vectors_msg(adapter, num_q_vecs);
201*4930fbf4SPavan Kumar Linga 	if (err) {
202*4930fbf4SPavan Kumar Linga 		dev_err(&adapter->pdev->dev,
203*4930fbf4SPavan Kumar Linga 			"Failed to allocate %d vectors: %d\n", num_q_vecs, err);
204*4930fbf4SPavan Kumar Linga 
205*4930fbf4SPavan Kumar Linga 		return -EAGAIN;
206*4930fbf4SPavan Kumar Linga 	}
207*4930fbf4SPavan Kumar Linga 
208*4930fbf4SPavan Kumar Linga 	min_vectors = IDPF_MBX_Q_VEC + IDPF_MIN_Q_VEC * default_vports;
209*4930fbf4SPavan Kumar Linga 	v_actual = pci_alloc_irq_vectors(adapter->pdev, min_vectors,
210*4930fbf4SPavan Kumar Linga 					 total_vecs, PCI_IRQ_MSIX);
211*4930fbf4SPavan Kumar Linga 	if (v_actual < min_vectors) {
212*4930fbf4SPavan Kumar Linga 		dev_err(&adapter->pdev->dev, "Failed to allocate MSIX vectors: %d\n",
213*4930fbf4SPavan Kumar Linga 			v_actual);
214*4930fbf4SPavan Kumar Linga 		err = -EAGAIN;
215*4930fbf4SPavan Kumar Linga 		goto send_dealloc_vecs;
216*4930fbf4SPavan Kumar Linga 	}
217*4930fbf4SPavan Kumar Linga 
218*4930fbf4SPavan Kumar Linga 	adapter->msix_entries = kcalloc(v_actual, sizeof(struct msix_entry),
219*4930fbf4SPavan Kumar Linga 					GFP_KERNEL);
220*4930fbf4SPavan Kumar Linga 
221*4930fbf4SPavan Kumar Linga 	if (!adapter->msix_entries) {
222*4930fbf4SPavan Kumar Linga 		err = -ENOMEM;
223*4930fbf4SPavan Kumar Linga 		goto free_irq;
224*4930fbf4SPavan Kumar Linga 	}
225*4930fbf4SPavan Kumar Linga 
226*4930fbf4SPavan Kumar Linga 	idpf_set_mb_vec_id(adapter);
227*4930fbf4SPavan Kumar Linga 
228*4930fbf4SPavan Kumar Linga 	vecids = kcalloc(total_vecs, sizeof(u16), GFP_KERNEL);
229*4930fbf4SPavan Kumar Linga 	if (!vecids) {
230*4930fbf4SPavan Kumar Linga 		err = -ENOMEM;
231*4930fbf4SPavan Kumar Linga 		goto free_msix;
232*4930fbf4SPavan Kumar Linga 	}
233*4930fbf4SPavan Kumar Linga 
234*4930fbf4SPavan Kumar Linga 	if (adapter->req_vec_chunks) {
235*4930fbf4SPavan Kumar Linga 		struct virtchnl2_vector_chunks *vchunks;
236*4930fbf4SPavan Kumar Linga 		struct virtchnl2_alloc_vectors *ac;
237*4930fbf4SPavan Kumar Linga 
238*4930fbf4SPavan Kumar Linga 		ac = adapter->req_vec_chunks;
239*4930fbf4SPavan Kumar Linga 		vchunks = &ac->vchunks;
240*4930fbf4SPavan Kumar Linga 
241*4930fbf4SPavan Kumar Linga 		num_vec_ids = idpf_get_vec_ids(adapter, vecids, total_vecs,
242*4930fbf4SPavan Kumar Linga 					       vchunks);
243*4930fbf4SPavan Kumar Linga 		if (num_vec_ids < v_actual) {
244*4930fbf4SPavan Kumar Linga 			err = -EINVAL;
245*4930fbf4SPavan Kumar Linga 			goto free_vecids;
246*4930fbf4SPavan Kumar Linga 		}
247*4930fbf4SPavan Kumar Linga 	} else {
248*4930fbf4SPavan Kumar Linga 		int i;
249*4930fbf4SPavan Kumar Linga 
250*4930fbf4SPavan Kumar Linga 		for (i = 0; i < v_actual; i++)
251*4930fbf4SPavan Kumar Linga 			vecids[i] = i;
252*4930fbf4SPavan Kumar Linga 	}
253*4930fbf4SPavan Kumar Linga 
254*4930fbf4SPavan Kumar Linga 	for (vector = 0; vector < v_actual; vector++) {
255*4930fbf4SPavan Kumar Linga 		adapter->msix_entries[vector].entry = vecids[vector];
256*4930fbf4SPavan Kumar Linga 		adapter->msix_entries[vector].vector =
257*4930fbf4SPavan Kumar Linga 			pci_irq_vector(adapter->pdev, vector);
258*4930fbf4SPavan Kumar Linga 	}
259*4930fbf4SPavan Kumar Linga 
260*4930fbf4SPavan Kumar Linga 	adapter->num_req_msix = total_vecs;
261*4930fbf4SPavan Kumar Linga 	adapter->num_msix_entries = v_actual;
262*4930fbf4SPavan Kumar Linga 	/* 'num_avail_msix' is used to distribute excess vectors to the vports
263*4930fbf4SPavan Kumar Linga 	 * after considering the minimum vectors required per each default
264*4930fbf4SPavan Kumar Linga 	 * vport
265*4930fbf4SPavan Kumar Linga 	 */
266*4930fbf4SPavan Kumar Linga 	adapter->num_avail_msix = v_actual - min_vectors;
267*4930fbf4SPavan Kumar Linga 
268*4930fbf4SPavan Kumar Linga 	/* Fill MSIX vector lifo stack with vector indexes */
269*4930fbf4SPavan Kumar Linga 	err = idpf_init_vector_stack(adapter);
270*4930fbf4SPavan Kumar Linga 	if (err)
271*4930fbf4SPavan Kumar Linga 		goto free_vecids;
272*4930fbf4SPavan Kumar Linga 
273*4930fbf4SPavan Kumar Linga 	err = idpf_mb_intr_init(adapter);
274*4930fbf4SPavan Kumar Linga 	if (err)
275*4930fbf4SPavan Kumar Linga 		goto deinit_vec_stack;
276*4930fbf4SPavan Kumar Linga 	idpf_mb_irq_enable(adapter);
277*4930fbf4SPavan Kumar Linga 	kfree(vecids);
278*4930fbf4SPavan Kumar Linga 
279*4930fbf4SPavan Kumar Linga 	return 0;
280*4930fbf4SPavan Kumar Linga 
281*4930fbf4SPavan Kumar Linga deinit_vec_stack:
282*4930fbf4SPavan Kumar Linga 	idpf_deinit_vector_stack(adapter);
283*4930fbf4SPavan Kumar Linga free_vecids:
284*4930fbf4SPavan Kumar Linga 	kfree(vecids);
285*4930fbf4SPavan Kumar Linga free_msix:
286*4930fbf4SPavan Kumar Linga 	kfree(adapter->msix_entries);
287*4930fbf4SPavan Kumar Linga 	adapter->msix_entries = NULL;
288*4930fbf4SPavan Kumar Linga free_irq:
289*4930fbf4SPavan Kumar Linga 	pci_free_irq_vectors(adapter->pdev);
290*4930fbf4SPavan Kumar Linga send_dealloc_vecs:
291*4930fbf4SPavan Kumar Linga 	idpf_send_dealloc_vectors_msg(adapter);
292*4930fbf4SPavan Kumar Linga 
293*4930fbf4SPavan Kumar Linga 	return err;
294*4930fbf4SPavan Kumar Linga }
295*4930fbf4SPavan Kumar Linga 
296*4930fbf4SPavan Kumar Linga /**
297*4930fbf4SPavan Kumar Linga  * idpf_mbx_task - Delayed task to handle mailbox responses
298*4930fbf4SPavan Kumar Linga  * @work: work_struct handle
299*4930fbf4SPavan Kumar Linga  */
300*4930fbf4SPavan Kumar Linga void idpf_mbx_task(struct work_struct *work)
301*4930fbf4SPavan Kumar Linga {
302*4930fbf4SPavan Kumar Linga 	struct idpf_adapter *adapter;
303*4930fbf4SPavan Kumar Linga 
304*4930fbf4SPavan Kumar Linga 	adapter = container_of(work, struct idpf_adapter, mbx_task.work);
305*4930fbf4SPavan Kumar Linga 
306*4930fbf4SPavan Kumar Linga 	if (test_bit(IDPF_MB_INTR_MODE, adapter->flags))
307*4930fbf4SPavan Kumar Linga 		idpf_mb_irq_enable(adapter);
308*4930fbf4SPavan Kumar Linga 	else
309*4930fbf4SPavan Kumar Linga 		queue_delayed_work(adapter->mbx_wq, &adapter->mbx_task,
310*4930fbf4SPavan Kumar Linga 				   msecs_to_jiffies(300));
311*4930fbf4SPavan Kumar Linga 
312*4930fbf4SPavan Kumar Linga 	idpf_recv_mb_msg(adapter, VIRTCHNL2_OP_UNKNOWN, NULL, 0);
313*4930fbf4SPavan Kumar Linga }
314*4930fbf4SPavan Kumar Linga 
315*4930fbf4SPavan Kumar Linga /**
316*4930fbf4SPavan Kumar Linga  * idpf_service_task - Delayed task for handling mailbox responses
317*4930fbf4SPavan Kumar Linga  * @work: work_struct handle to our data
318*4930fbf4SPavan Kumar Linga  *
319*4930fbf4SPavan Kumar Linga  */
320*4930fbf4SPavan Kumar Linga void idpf_service_task(struct work_struct *work)
321*4930fbf4SPavan Kumar Linga {
322*4930fbf4SPavan Kumar Linga 	struct idpf_adapter *adapter;
323*4930fbf4SPavan Kumar Linga 
324*4930fbf4SPavan Kumar Linga 	adapter = container_of(work, struct idpf_adapter, serv_task.work);
325*4930fbf4SPavan Kumar Linga 
326*4930fbf4SPavan Kumar Linga 	if (idpf_is_reset_detected(adapter) &&
327*4930fbf4SPavan Kumar Linga 	    !idpf_is_reset_in_prog(adapter) &&
328*4930fbf4SPavan Kumar Linga 	    !test_bit(IDPF_REMOVE_IN_PROG, adapter->flags)) {
329*4930fbf4SPavan Kumar Linga 		dev_info(&adapter->pdev->dev, "HW reset detected\n");
330*4930fbf4SPavan Kumar Linga 		set_bit(IDPF_HR_FUNC_RESET, adapter->flags);
331*4930fbf4SPavan Kumar Linga 		queue_delayed_work(adapter->vc_event_wq,
332*4930fbf4SPavan Kumar Linga 				   &adapter->vc_event_task,
333*4930fbf4SPavan Kumar Linga 				   msecs_to_jiffies(10));
334*4930fbf4SPavan Kumar Linga 	}
335*4930fbf4SPavan Kumar Linga 
336*4930fbf4SPavan Kumar Linga 	queue_delayed_work(adapter->serv_wq, &adapter->serv_task,
337*4930fbf4SPavan Kumar Linga 			   msecs_to_jiffies(300));
338*4930fbf4SPavan Kumar Linga }
339*4930fbf4SPavan Kumar Linga 
3408077c727SJoshua Hay /**
3418077c727SJoshua Hay  * idpf_check_reset_complete - check that reset is complete
3428077c727SJoshua Hay  * @hw: pointer to hw struct
3438077c727SJoshua Hay  * @reset_reg: struct with reset registers
3448077c727SJoshua Hay  *
3458077c727SJoshua Hay  * Returns 0 if device is ready to use, or -EBUSY if it's in reset.
3468077c727SJoshua Hay  **/
3478077c727SJoshua Hay static int idpf_check_reset_complete(struct idpf_hw *hw,
3488077c727SJoshua Hay 				     struct idpf_reset_reg *reset_reg)
3498077c727SJoshua Hay {
3508077c727SJoshua Hay 	struct idpf_adapter *adapter = hw->back;
3518077c727SJoshua Hay 	int i;
3528077c727SJoshua Hay 
3538077c727SJoshua Hay 	for (i = 0; i < 2000; i++) {
3548077c727SJoshua Hay 		u32 reg_val = readl(reset_reg->rstat);
3558077c727SJoshua Hay 
3568077c727SJoshua Hay 		/* 0xFFFFFFFF might be read if other side hasn't cleared the
3578077c727SJoshua Hay 		 * register for us yet and 0xFFFFFFFF is not a valid value for
3588077c727SJoshua Hay 		 * the register, so treat that as invalid.
3598077c727SJoshua Hay 		 */
3608077c727SJoshua Hay 		if (reg_val != 0xFFFFFFFF && (reg_val & reset_reg->rstat_m))
3618077c727SJoshua Hay 			return 0;
3628077c727SJoshua Hay 
3638077c727SJoshua Hay 		usleep_range(5000, 10000);
3648077c727SJoshua Hay 	}
3658077c727SJoshua Hay 
3668077c727SJoshua Hay 	dev_warn(&adapter->pdev->dev, "Device reset timeout!\n");
3678077c727SJoshua Hay 	/* Clear the reset flag unconditionally here since the reset
3688077c727SJoshua Hay 	 * technically isn't in progress anymore from the driver's perspective
3698077c727SJoshua Hay 	 */
3708077c727SJoshua Hay 	clear_bit(IDPF_HR_RESET_IN_PROG, adapter->flags);
3718077c727SJoshua Hay 
3728077c727SJoshua Hay 	return -EBUSY;
3738077c727SJoshua Hay }
3748077c727SJoshua Hay 
3758077c727SJoshua Hay /**
3768077c727SJoshua Hay  * idpf_init_hard_reset - Initiate a hardware reset
3778077c727SJoshua Hay  * @adapter: Driver specific private structure
3788077c727SJoshua Hay  *
3798077c727SJoshua Hay  * Deallocate the vports and all the resources associated with them and
3808077c727SJoshua Hay  * reallocate. Also reinitialize the mailbox. Return 0 on success,
3818077c727SJoshua Hay  * negative on failure.
3828077c727SJoshua Hay  */
3838077c727SJoshua Hay static int idpf_init_hard_reset(struct idpf_adapter *adapter)
3848077c727SJoshua Hay {
3858077c727SJoshua Hay 	struct idpf_reg_ops *reg_ops = &adapter->dev_ops.reg_ops;
3868077c727SJoshua Hay 	struct device *dev = &adapter->pdev->dev;
3878077c727SJoshua Hay 	int err;
3888077c727SJoshua Hay 
3898077c727SJoshua Hay 	mutex_lock(&adapter->vport_ctrl_lock);
3908077c727SJoshua Hay 
3918077c727SJoshua Hay 	dev_info(dev, "Device HW Reset initiated\n");
3928077c727SJoshua Hay 	/* Prepare for reset */
3938077c727SJoshua Hay 	if (test_and_clear_bit(IDPF_HR_DRV_LOAD, adapter->flags)) {
3948077c727SJoshua Hay 		reg_ops->trigger_reset(adapter, IDPF_HR_DRV_LOAD);
3958077c727SJoshua Hay 	} else if (test_and_clear_bit(IDPF_HR_FUNC_RESET, adapter->flags)) {
3968077c727SJoshua Hay 		bool is_reset = idpf_is_reset_detected(adapter);
3978077c727SJoshua Hay 
398*4930fbf4SPavan Kumar Linga 		idpf_vc_core_deinit(adapter);
3998077c727SJoshua Hay 		if (!is_reset)
4008077c727SJoshua Hay 			reg_ops->trigger_reset(adapter, IDPF_HR_FUNC_RESET);
4018077c727SJoshua Hay 		idpf_deinit_dflt_mbx(adapter);
4028077c727SJoshua Hay 	} else {
4038077c727SJoshua Hay 		dev_err(dev, "Unhandled hard reset cause\n");
4048077c727SJoshua Hay 		err = -EBADRQC;
4058077c727SJoshua Hay 		goto unlock_mutex;
4068077c727SJoshua Hay 	}
4078077c727SJoshua Hay 
4088077c727SJoshua Hay 	/* Wait for reset to complete */
4098077c727SJoshua Hay 	err = idpf_check_reset_complete(&adapter->hw, &adapter->reset_reg);
4108077c727SJoshua Hay 	if (err) {
4118077c727SJoshua 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",
4128077c727SJoshua Hay 			adapter->state);
4138077c727SJoshua Hay 		goto unlock_mutex;
4148077c727SJoshua Hay 	}
4158077c727SJoshua Hay 
4168077c727SJoshua Hay 	/* Reset is complete and so start building the driver resources again */
4178077c727SJoshua Hay 	err = idpf_init_dflt_mbx(adapter);
418*4930fbf4SPavan Kumar Linga 	if (err) {
4198077c727SJoshua Hay 		dev_err(dev, "Failed to initialize default mailbox: %d\n", err);
420*4930fbf4SPavan Kumar Linga 		goto unlock_mutex;
421*4930fbf4SPavan Kumar Linga 	}
422*4930fbf4SPavan Kumar Linga 
423*4930fbf4SPavan Kumar Linga 	/* Initialize the state machine, also allocate memory and request
424*4930fbf4SPavan Kumar Linga 	 * resources
425*4930fbf4SPavan Kumar Linga 	 */
426*4930fbf4SPavan Kumar Linga 	err = idpf_vc_core_init(adapter);
427*4930fbf4SPavan Kumar Linga 	if (err) {
428*4930fbf4SPavan Kumar Linga 		idpf_deinit_dflt_mbx(adapter);
429*4930fbf4SPavan Kumar Linga 		goto unlock_mutex;
430*4930fbf4SPavan Kumar Linga 	}
4318077c727SJoshua Hay 
4328077c727SJoshua Hay unlock_mutex:
4338077c727SJoshua Hay 	mutex_unlock(&adapter->vport_ctrl_lock);
4348077c727SJoshua Hay 
4358077c727SJoshua Hay 	return err;
4368077c727SJoshua Hay }
4378077c727SJoshua Hay 
4388077c727SJoshua Hay /**
4398077c727SJoshua Hay  * idpf_vc_event_task - Handle virtchannel event logic
4408077c727SJoshua Hay  * @work: work queue struct
4418077c727SJoshua Hay  */
4428077c727SJoshua Hay void idpf_vc_event_task(struct work_struct *work)
4438077c727SJoshua Hay {
4448077c727SJoshua Hay 	struct idpf_adapter *adapter;
4458077c727SJoshua Hay 
4468077c727SJoshua Hay 	adapter = container_of(work, struct idpf_adapter, vc_event_task.work);
4478077c727SJoshua Hay 
4488077c727SJoshua Hay 	if (test_bit(IDPF_REMOVE_IN_PROG, adapter->flags))
4498077c727SJoshua Hay 		return;
4508077c727SJoshua Hay 
4518077c727SJoshua Hay 	if (test_bit(IDPF_HR_FUNC_RESET, adapter->flags) ||
4528077c727SJoshua Hay 	    test_bit(IDPF_HR_DRV_LOAD, adapter->flags)) {
4538077c727SJoshua Hay 		set_bit(IDPF_HR_RESET_IN_PROG, adapter->flags);
4548077c727SJoshua Hay 		idpf_init_hard_reset(adapter);
4558077c727SJoshua Hay 	}
4568077c727SJoshua Hay }
4578077c727SJoshua Hay 
4588077c727SJoshua Hay /**
4598077c727SJoshua Hay  * idpf_alloc_dma_mem - Allocate dma memory
4608077c727SJoshua Hay  * @hw: pointer to hw struct
4618077c727SJoshua Hay  * @mem: pointer to dma_mem struct
4628077c727SJoshua Hay  * @size: size of the memory to allocate
4638077c727SJoshua Hay  */
4648077c727SJoshua Hay void *idpf_alloc_dma_mem(struct idpf_hw *hw, struct idpf_dma_mem *mem, u64 size)
4658077c727SJoshua Hay {
4668077c727SJoshua Hay 	struct idpf_adapter *adapter = hw->back;
4678077c727SJoshua Hay 	size_t sz = ALIGN(size, 4096);
4688077c727SJoshua Hay 
4698077c727SJoshua Hay 	mem->va = dma_alloc_coherent(&adapter->pdev->dev, sz,
4708077c727SJoshua Hay 				     &mem->pa, GFP_KERNEL);
4718077c727SJoshua Hay 	mem->size = sz;
4728077c727SJoshua Hay 
4738077c727SJoshua Hay 	return mem->va;
4748077c727SJoshua Hay }
4758077c727SJoshua Hay 
4768077c727SJoshua Hay /**
4778077c727SJoshua Hay  * idpf_free_dma_mem - Free the allocated dma memory
4788077c727SJoshua Hay  * @hw: pointer to hw struct
4798077c727SJoshua Hay  * @mem: pointer to dma_mem struct
4808077c727SJoshua Hay  */
4818077c727SJoshua Hay void idpf_free_dma_mem(struct idpf_hw *hw, struct idpf_dma_mem *mem)
4828077c727SJoshua Hay {
4838077c727SJoshua Hay 	struct idpf_adapter *adapter = hw->back;
4848077c727SJoshua Hay 
4858077c727SJoshua Hay 	dma_free_coherent(&adapter->pdev->dev, mem->size,
4868077c727SJoshua Hay 			  mem->va, mem->pa);
4878077c727SJoshua Hay 	mem->size = 0;
4888077c727SJoshua Hay 	mem->va = NULL;
4898077c727SJoshua Hay 	mem->pa = 0;
4908077c727SJoshua Hay }
491