xref: /openbmc/linux/drivers/infiniband/hw/hfi1/msix.c (revision 762f99f4f3cb41a775b5157dd761217beba65873)
109e71899SMichael J. Ruhl // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
209e71899SMichael J. Ruhl /*
389dcaa36SGrzegorz Andrejczuk  * Copyright(c) 2018 - 2020 Intel Corporation.
409e71899SMichael J. Ruhl  */
509e71899SMichael J. Ruhl 
609e71899SMichael J. Ruhl #include "hfi.h"
76eb4eb10SMichael J. Ruhl #include "affinity.h"
809e71899SMichael J. Ruhl #include "sdma.h"
90bae02d5SGrzegorz Andrejczuk #include "netdev.h"
1009e71899SMichael J. Ruhl 
116eb4eb10SMichael J. Ruhl /**
126eb4eb10SMichael J. Ruhl  * msix_initialize() - Calculate, request and configure MSIx IRQs
136eb4eb10SMichael J. Ruhl  * @dd: valid hfi1 devdata
146eb4eb10SMichael J. Ruhl  *
1509e71899SMichael J. Ruhl  */
msix_initialize(struct hfi1_devdata * dd)166eb4eb10SMichael J. Ruhl int msix_initialize(struct hfi1_devdata *dd)
1709e71899SMichael J. Ruhl {
1809e71899SMichael J. Ruhl 	u32 total;
196eb4eb10SMichael J. Ruhl 	int ret;
206eb4eb10SMichael J. Ruhl 	struct hfi1_msix_entry *entries;
2109e71899SMichael J. Ruhl 
2209e71899SMichael J. Ruhl 	/*
236eb4eb10SMichael J. Ruhl 	 * MSIx interrupt count:
246eb4eb10SMichael J. Ruhl 	 *	one for the general, "slow path" interrupt
256eb4eb10SMichael J. Ruhl 	 *	one per used SDMA engine
266eb4eb10SMichael J. Ruhl 	 *	one per kernel receive context
276eb4eb10SMichael J. Ruhl 	 *	one for each VNIC context
286eb4eb10SMichael J. Ruhl 	 *      ...any new IRQs should be added here.
2909e71899SMichael J. Ruhl 	 */
3089dcaa36SGrzegorz Andrejczuk 	total = 1 + dd->num_sdma + dd->n_krcv_queues + dd->num_netdev_contexts;
3109e71899SMichael J. Ruhl 
326eb4eb10SMichael J. Ruhl 	if (total >= CCE_NUM_MSIX_VECTORS)
336eb4eb10SMichael J. Ruhl 		return -EINVAL;
346eb4eb10SMichael J. Ruhl 
356eb4eb10SMichael J. Ruhl 	ret = pci_alloc_irq_vectors(dd->pcidev, total, total, PCI_IRQ_MSIX);
366eb4eb10SMichael J. Ruhl 	if (ret < 0) {
376eb4eb10SMichael J. Ruhl 		dd_dev_err(dd, "pci_alloc_irq_vectors() failed: %d\n", ret);
386eb4eb10SMichael J. Ruhl 		return ret;
396eb4eb10SMichael J. Ruhl 	}
406eb4eb10SMichael J. Ruhl 
416eb4eb10SMichael J. Ruhl 	entries = kcalloc(total, sizeof(*dd->msix_info.msix_entries),
4209e71899SMichael J. Ruhl 			  GFP_KERNEL);
436eb4eb10SMichael J. Ruhl 	if (!entries) {
446eb4eb10SMichael J. Ruhl 		pci_free_irq_vectors(dd->pcidev);
456eb4eb10SMichael J. Ruhl 		return -ENOMEM;
4609e71899SMichael J. Ruhl 	}
476eb4eb10SMichael J. Ruhl 
486eb4eb10SMichael J. Ruhl 	dd->msix_info.msix_entries = entries;
496eb4eb10SMichael J. Ruhl 	spin_lock_init(&dd->msix_info.msix_lock);
506eb4eb10SMichael J. Ruhl 	bitmap_zero(dd->msix_info.in_use_msix, total);
516eb4eb10SMichael J. Ruhl 	dd->msix_info.max_requested = total;
5209e71899SMichael J. Ruhl 	dd_dev_info(dd, "%u MSI-X interrupts allocated\n", total);
5309e71899SMichael J. Ruhl 
5409e71899SMichael J. Ruhl 	return 0;
5509e71899SMichael J. Ruhl }
5609e71899SMichael J. Ruhl 
576eb4eb10SMichael J. Ruhl /**
586eb4eb10SMichael J. Ruhl  * msix_request_irq() - Allocate a free MSIx IRQ
596eb4eb10SMichael J. Ruhl  * @dd: valid devdata
606eb4eb10SMichael J. Ruhl  * @arg: context information for the IRQ
616eb4eb10SMichael J. Ruhl  * @handler: IRQ handler
626eb4eb10SMichael J. Ruhl  * @thread: IRQ thread handler (could be NULL)
636eb4eb10SMichael J. Ruhl  * @type: affinty IRQ type
64e57a8db9SLee Jones  * @name: IRQ name
656eb4eb10SMichael J. Ruhl  *
666eb4eb10SMichael J. Ruhl  * Allocated an MSIx vector if available, and then create the appropriate
676eb4eb10SMichael J. Ruhl  * meta data needed to keep track of the pci IRQ request.
686eb4eb10SMichael J. Ruhl  *
696eb4eb10SMichael J. Ruhl  * Return:
706eb4eb10SMichael J. Ruhl  *   < 0   Error
716eb4eb10SMichael J. Ruhl  *   >= 0  MSIx vector
726eb4eb10SMichael J. Ruhl  *
736eb4eb10SMichael J. Ruhl  */
msix_request_irq(struct hfi1_devdata * dd,void * arg,irq_handler_t handler,irq_handler_t thread,enum irq_type type,const char * name)746eb4eb10SMichael J. Ruhl static int msix_request_irq(struct hfi1_devdata *dd, void *arg,
756eb4eb10SMichael J. Ruhl 			    irq_handler_t handler, irq_handler_t thread,
7613d2a838SGrzegorz Andrejczuk 			    enum irq_type type, const char *name)
7709e71899SMichael J. Ruhl {
786eb4eb10SMichael J. Ruhl 	unsigned long nr;
796eb4eb10SMichael J. Ruhl 	int irq;
806eb4eb10SMichael J. Ruhl 	int ret;
816eb4eb10SMichael J. Ruhl 	struct hfi1_msix_entry *me;
8209e71899SMichael J. Ruhl 
836eb4eb10SMichael J. Ruhl 	/* Allocate an MSIx vector */
846eb4eb10SMichael J. Ruhl 	spin_lock(&dd->msix_info.msix_lock);
856eb4eb10SMichael J. Ruhl 	nr = find_first_zero_bit(dd->msix_info.in_use_msix,
866eb4eb10SMichael J. Ruhl 				 dd->msix_info.max_requested);
876eb4eb10SMichael J. Ruhl 	if (nr < dd->msix_info.max_requested)
886eb4eb10SMichael J. Ruhl 		__set_bit(nr, dd->msix_info.in_use_msix);
896eb4eb10SMichael J. Ruhl 	spin_unlock(&dd->msix_info.msix_lock);
906eb4eb10SMichael J. Ruhl 
916eb4eb10SMichael J. Ruhl 	if (nr == dd->msix_info.max_requested)
926eb4eb10SMichael J. Ruhl 		return -ENOSPC;
936eb4eb10SMichael J. Ruhl 
9479ba4f93SNathan Chancellor 	if (type < IRQ_SDMA || type >= IRQ_OTHER)
956eb4eb10SMichael J. Ruhl 		return -EINVAL;
966eb4eb10SMichael J. Ruhl 
976eb4eb10SMichael J. Ruhl 	irq = pci_irq_vector(dd->pcidev, nr);
986eb4eb10SMichael J. Ruhl 	ret = pci_request_irq(dd->pcidev, nr, handler, thread, arg, name);
9909e71899SMichael J. Ruhl 	if (ret) {
10009e71899SMichael J. Ruhl 		dd_dev_err(dd,
1010bae02d5SGrzegorz Andrejczuk 			   "%s: request for IRQ %d failed, MSIx %lx, err %d\n",
10213d2a838SGrzegorz Andrejczuk 			   name, irq, nr, ret);
1036eb4eb10SMichael J. Ruhl 		spin_lock(&dd->msix_info.msix_lock);
1046eb4eb10SMichael J. Ruhl 		__clear_bit(nr, dd->msix_info.in_use_msix);
1056eb4eb10SMichael J. Ruhl 		spin_unlock(&dd->msix_info.msix_lock);
10609e71899SMichael J. Ruhl 		return ret;
10709e71899SMichael J. Ruhl 	}
1086eb4eb10SMichael J. Ruhl 
10909e71899SMichael J. Ruhl 	/*
11009e71899SMichael J. Ruhl 	 * assign arg after pci_request_irq call, so it will be
11109e71899SMichael J. Ruhl 	 * cleaned up
11209e71899SMichael J. Ruhl 	 */
1136eb4eb10SMichael J. Ruhl 	me = &dd->msix_info.msix_entries[nr];
1146eb4eb10SMichael J. Ruhl 	me->irq = irq;
11509e71899SMichael J. Ruhl 	me->arg = arg;
1166eb4eb10SMichael J. Ruhl 	me->type = type;
11709e71899SMichael J. Ruhl 
1186eb4eb10SMichael J. Ruhl 	/* This is a request, so a failure is not fatal */
11909e71899SMichael J. Ruhl 	ret = hfi1_get_irq_affinity(dd, me);
12009e71899SMichael J. Ruhl 	if (ret)
1210bae02d5SGrzegorz Andrejczuk 		dd_dev_err(dd, "%s: unable to pin IRQ %d\n", name, ret);
1226eb4eb10SMichael J. Ruhl 
1236eb4eb10SMichael J. Ruhl 	return nr;
12409e71899SMichael J. Ruhl }
12509e71899SMichael J. Ruhl 
msix_request_rcd_irq_common(struct hfi1_ctxtdata * rcd,irq_handler_t handler,irq_handler_t thread,const char * name)12613d2a838SGrzegorz Andrejczuk static int msix_request_rcd_irq_common(struct hfi1_ctxtdata *rcd,
12713d2a838SGrzegorz Andrejczuk 				       irq_handler_t handler,
12813d2a838SGrzegorz Andrejczuk 				       irq_handler_t thread,
12913d2a838SGrzegorz Andrejczuk 				       const char *name)
1306eb4eb10SMichael J. Ruhl {
13113d2a838SGrzegorz Andrejczuk 	int nr = msix_request_irq(rcd->dd, rcd, handler, thread,
1324730f4a6SGrzegorz Andrejczuk 				  rcd->is_vnic ? IRQ_NETDEVCTXT : IRQ_RCVCTXT,
1334730f4a6SGrzegorz Andrejczuk 				  name);
1346eb4eb10SMichael J. Ruhl 	if (nr < 0)
1356eb4eb10SMichael J. Ruhl 		return nr;
1366eb4eb10SMichael J. Ruhl 
1376eb4eb10SMichael J. Ruhl 	/*
1386eb4eb10SMichael J. Ruhl 	 * Set the interrupt register and mask for this
1396eb4eb10SMichael J. Ruhl 	 * context's interrupt.
1406eb4eb10SMichael J. Ruhl 	 */
1416eb4eb10SMichael J. Ruhl 	rcd->ireg = (IS_RCVAVAIL_START + rcd->ctxt) / 64;
1426eb4eb10SMichael J. Ruhl 	rcd->imask = ((u64)1) << ((IS_RCVAVAIL_START + rcd->ctxt) % 64);
1436eb4eb10SMichael J. Ruhl 	rcd->msix_intr = nr;
1446eb4eb10SMichael J. Ruhl 	remap_intr(rcd->dd, IS_RCVAVAIL_START + rcd->ctxt, nr);
1456eb4eb10SMichael J. Ruhl 
1466eb4eb10SMichael J. Ruhl 	return 0;
1476eb4eb10SMichael J. Ruhl }
1486eb4eb10SMichael J. Ruhl 
1496eb4eb10SMichael J. Ruhl /**
15013d2a838SGrzegorz Andrejczuk  * msix_request_rcd_irq() - Helper function for RCVAVAIL IRQs
15113d2a838SGrzegorz Andrejczuk  * @rcd: valid rcd context
15213d2a838SGrzegorz Andrejczuk  *
15313d2a838SGrzegorz Andrejczuk  */
msix_request_rcd_irq(struct hfi1_ctxtdata * rcd)15413d2a838SGrzegorz Andrejczuk int msix_request_rcd_irq(struct hfi1_ctxtdata *rcd)
15513d2a838SGrzegorz Andrejczuk {
15613d2a838SGrzegorz Andrejczuk 	char name[MAX_NAME_SIZE];
15713d2a838SGrzegorz Andrejczuk 
15813d2a838SGrzegorz Andrejczuk 	snprintf(name, sizeof(name), DRIVER_NAME "_%d kctxt%d",
15913d2a838SGrzegorz Andrejczuk 		 rcd->dd->unit, rcd->ctxt);
16013d2a838SGrzegorz Andrejczuk 
16113d2a838SGrzegorz Andrejczuk 	return msix_request_rcd_irq_common(rcd, receive_context_interrupt,
16213d2a838SGrzegorz Andrejczuk 					   receive_context_thread, name);
16313d2a838SGrzegorz Andrejczuk }
16413d2a838SGrzegorz Andrejczuk 
16513d2a838SGrzegorz Andrejczuk /**
166*ae360f41SLeon Romanovsky  * msix_netdev_request_rcd_irq  - Helper function for RCVAVAIL IRQs
1670bae02d5SGrzegorz Andrejczuk  * for netdev context
1680bae02d5SGrzegorz Andrejczuk  * @rcd: valid netdev contexti
1690bae02d5SGrzegorz Andrejczuk  */
msix_netdev_request_rcd_irq(struct hfi1_ctxtdata * rcd)1700bae02d5SGrzegorz Andrejczuk int msix_netdev_request_rcd_irq(struct hfi1_ctxtdata *rcd)
1710bae02d5SGrzegorz Andrejczuk {
1720bae02d5SGrzegorz Andrejczuk 	char name[MAX_NAME_SIZE];
1730bae02d5SGrzegorz Andrejczuk 
1740bae02d5SGrzegorz Andrejczuk 	snprintf(name, sizeof(name), DRIVER_NAME "_%d nd kctxt%d",
1750bae02d5SGrzegorz Andrejczuk 		 rcd->dd->unit, rcd->ctxt);
1760bae02d5SGrzegorz Andrejczuk 	return msix_request_rcd_irq_common(rcd, receive_context_interrupt_napi,
1770bae02d5SGrzegorz Andrejczuk 					   NULL, name);
1780bae02d5SGrzegorz Andrejczuk }
1790bae02d5SGrzegorz Andrejczuk 
1800bae02d5SGrzegorz Andrejczuk /**
181*ae360f41SLeon Romanovsky  * msix_request_sdma_irq  - Helper for getting SDMA IRQ resources
1826eb4eb10SMichael J. Ruhl  * @sde: valid sdma engine
1836eb4eb10SMichael J. Ruhl  *
1846eb4eb10SMichael J. Ruhl  */
msix_request_sdma_irq(struct sdma_engine * sde)1856eb4eb10SMichael J. Ruhl int msix_request_sdma_irq(struct sdma_engine *sde)
1866eb4eb10SMichael J. Ruhl {
1876eb4eb10SMichael J. Ruhl 	int nr;
18813d2a838SGrzegorz Andrejczuk 	char name[MAX_NAME_SIZE];
1896eb4eb10SMichael J. Ruhl 
19013d2a838SGrzegorz Andrejczuk 	snprintf(name, sizeof(name), DRIVER_NAME "_%d sdma%d",
19113d2a838SGrzegorz Andrejczuk 		 sde->dd->unit, sde->this_idx);
1926eb4eb10SMichael J. Ruhl 	nr = msix_request_irq(sde->dd, sde, sdma_interrupt, NULL,
19313d2a838SGrzegorz Andrejczuk 			      IRQ_SDMA, name);
1946eb4eb10SMichael J. Ruhl 	if (nr < 0)
1956eb4eb10SMichael J. Ruhl 		return nr;
1966eb4eb10SMichael J. Ruhl 	sde->msix_intr = nr;
1976eb4eb10SMichael J. Ruhl 	remap_sdma_interrupts(sde->dd, sde->this_idx, nr);
1986eb4eb10SMichael J. Ruhl 
1996eb4eb10SMichael J. Ruhl 	return 0;
2006eb4eb10SMichael J. Ruhl }
2016eb4eb10SMichael J. Ruhl 
2026eb4eb10SMichael J. Ruhl /**
203*ae360f41SLeon Romanovsky  * msix_request_general_irq - Helper for getting general IRQ
20413d2a838SGrzegorz Andrejczuk  * resources
20513d2a838SGrzegorz Andrejczuk  * @dd: valid device data
20613d2a838SGrzegorz Andrejczuk  */
msix_request_general_irq(struct hfi1_devdata * dd)20713d2a838SGrzegorz Andrejczuk int msix_request_general_irq(struct hfi1_devdata *dd)
20813d2a838SGrzegorz Andrejczuk {
20913d2a838SGrzegorz Andrejczuk 	int nr;
21013d2a838SGrzegorz Andrejczuk 	char name[MAX_NAME_SIZE];
21113d2a838SGrzegorz Andrejczuk 
21213d2a838SGrzegorz Andrejczuk 	snprintf(name, sizeof(name), DRIVER_NAME "_%d", dd->unit);
21313d2a838SGrzegorz Andrejczuk 	nr = msix_request_irq(dd, dd, general_interrupt, NULL, IRQ_GENERAL,
21413d2a838SGrzegorz Andrejczuk 			      name);
21513d2a838SGrzegorz Andrejczuk 	if (nr < 0)
21613d2a838SGrzegorz Andrejczuk 		return nr;
21713d2a838SGrzegorz Andrejczuk 
21813d2a838SGrzegorz Andrejczuk 	/* general interrupt must be MSIx vector 0 */
21913d2a838SGrzegorz Andrejczuk 	if (nr) {
22013d2a838SGrzegorz Andrejczuk 		msix_free_irq(dd, (u8)nr);
22113d2a838SGrzegorz Andrejczuk 		dd_dev_err(dd, "Invalid index %d for GENERAL IRQ\n", nr);
22213d2a838SGrzegorz Andrejczuk 		return -EINVAL;
22313d2a838SGrzegorz Andrejczuk 	}
22413d2a838SGrzegorz Andrejczuk 
22513d2a838SGrzegorz Andrejczuk 	return 0;
22613d2a838SGrzegorz Andrejczuk }
22713d2a838SGrzegorz Andrejczuk 
22813d2a838SGrzegorz Andrejczuk /**
229*ae360f41SLeon Romanovsky  * enable_sdma_srcs - Helper to enable SDMA IRQ srcs
230a2f7bbdcSMichael J. Ruhl  * @dd: valid devdata structure
231a2f7bbdcSMichael J. Ruhl  * @i: index of SDMA engine
232a2f7bbdcSMichael J. Ruhl  */
enable_sdma_srcs(struct hfi1_devdata * dd,int i)233a2f7bbdcSMichael J. Ruhl static void enable_sdma_srcs(struct hfi1_devdata *dd, int i)
234a2f7bbdcSMichael J. Ruhl {
235a2f7bbdcSMichael J. Ruhl 	set_intr_bits(dd, IS_SDMA_START + i, IS_SDMA_START + i, true);
236a2f7bbdcSMichael J. Ruhl 	set_intr_bits(dd, IS_SDMA_PROGRESS_START + i,
237a2f7bbdcSMichael J. Ruhl 		      IS_SDMA_PROGRESS_START + i, true);
238a2f7bbdcSMichael J. Ruhl 	set_intr_bits(dd, IS_SDMA_IDLE_START + i, IS_SDMA_IDLE_START + i, true);
239a2f7bbdcSMichael J. Ruhl 	set_intr_bits(dd, IS_SDMAENG_ERR_START + i, IS_SDMAENG_ERR_START + i,
240a2f7bbdcSMichael J. Ruhl 		      true);
241a2f7bbdcSMichael J. Ruhl }
242a2f7bbdcSMichael J. Ruhl 
243a2f7bbdcSMichael J. Ruhl /**
2446eb4eb10SMichael J. Ruhl  * msix_request_irqs() - Allocate all MSIx IRQs
2456eb4eb10SMichael J. Ruhl  * @dd: valid devdata structure
2466eb4eb10SMichael J. Ruhl  *
2476eb4eb10SMichael J. Ruhl  * Helper function to request the used MSIx IRQs.
2486eb4eb10SMichael J. Ruhl  *
2496eb4eb10SMichael J. Ruhl  */
msix_request_irqs(struct hfi1_devdata * dd)2506eb4eb10SMichael J. Ruhl int msix_request_irqs(struct hfi1_devdata *dd)
2516eb4eb10SMichael J. Ruhl {
2526eb4eb10SMichael J. Ruhl 	int i;
25313d2a838SGrzegorz Andrejczuk 	int ret = msix_request_general_irq(dd);
2546eb4eb10SMichael J. Ruhl 
25513d2a838SGrzegorz Andrejczuk 	if (ret)
2566eb4eb10SMichael J. Ruhl 		return ret;
2576eb4eb10SMichael J. Ruhl 
2586eb4eb10SMichael J. Ruhl 	for (i = 0; i < dd->num_sdma; i++) {
2596eb4eb10SMichael J. Ruhl 		struct sdma_engine *sde = &dd->per_sdma[i];
2606eb4eb10SMichael J. Ruhl 
2616eb4eb10SMichael J. Ruhl 		ret = msix_request_sdma_irq(sde);
2626eb4eb10SMichael J. Ruhl 		if (ret)
26309e71899SMichael J. Ruhl 			return ret;
264a2f7bbdcSMichael J. Ruhl 		enable_sdma_srcs(sde->dd, i);
26509e71899SMichael J. Ruhl 	}
26609e71899SMichael J. Ruhl 
2676eb4eb10SMichael J. Ruhl 	for (i = 0; i < dd->n_krcv_queues; i++) {
2686eb4eb10SMichael J. Ruhl 		struct hfi1_ctxtdata *rcd = hfi1_rcd_get_by_index_safe(dd, i);
2696eb4eb10SMichael J. Ruhl 
2706eb4eb10SMichael J. Ruhl 		if (rcd)
2716eb4eb10SMichael J. Ruhl 			ret = msix_request_rcd_irq(rcd);
2726eb4eb10SMichael J. Ruhl 		hfi1_rcd_put(rcd);
2736eb4eb10SMichael J. Ruhl 		if (ret)
2746eb4eb10SMichael J. Ruhl 			return ret;
2756eb4eb10SMichael J. Ruhl 	}
2766eb4eb10SMichael J. Ruhl 
2776eb4eb10SMichael J. Ruhl 	return 0;
2786eb4eb10SMichael J. Ruhl }
2796eb4eb10SMichael J. Ruhl 
2806eb4eb10SMichael J. Ruhl /**
2816eb4eb10SMichael J. Ruhl  * msix_free_irq() - Free the specified MSIx resources and IRQ
2826eb4eb10SMichael J. Ruhl  * @dd: valid devdata
2836eb4eb10SMichael J. Ruhl  * @msix_intr: MSIx vector to free.
2846eb4eb10SMichael J. Ruhl  *
2856eb4eb10SMichael J. Ruhl  */
msix_free_irq(struct hfi1_devdata * dd,u8 msix_intr)2866eb4eb10SMichael J. Ruhl void msix_free_irq(struct hfi1_devdata *dd, u8 msix_intr)
2876eb4eb10SMichael J. Ruhl {
2886eb4eb10SMichael J. Ruhl 	struct hfi1_msix_entry *me;
2896eb4eb10SMichael J. Ruhl 
2906eb4eb10SMichael J. Ruhl 	if (msix_intr >= dd->msix_info.max_requested)
2916eb4eb10SMichael J. Ruhl 		return;
2926eb4eb10SMichael J. Ruhl 
2936eb4eb10SMichael J. Ruhl 	me = &dd->msix_info.msix_entries[msix_intr];
2946eb4eb10SMichael J. Ruhl 
2956eb4eb10SMichael J. Ruhl 	if (!me->arg) /* => no irq, no affinity */
2966eb4eb10SMichael J. Ruhl 		return;
2976eb4eb10SMichael J. Ruhl 
2986eb4eb10SMichael J. Ruhl 	hfi1_put_irq_affinity(dd, me);
2996eb4eb10SMichael J. Ruhl 	pci_free_irq(dd->pcidev, msix_intr, me->arg);
3006eb4eb10SMichael J. Ruhl 
3016eb4eb10SMichael J. Ruhl 	me->arg = NULL;
3026eb4eb10SMichael J. Ruhl 
3036eb4eb10SMichael J. Ruhl 	spin_lock(&dd->msix_info.msix_lock);
3046eb4eb10SMichael J. Ruhl 	__clear_bit(msix_intr, dd->msix_info.in_use_msix);
3056eb4eb10SMichael J. Ruhl 	spin_unlock(&dd->msix_info.msix_lock);
3066eb4eb10SMichael J. Ruhl }
3076eb4eb10SMichael J. Ruhl 
3086eb4eb10SMichael J. Ruhl /**
309*ae360f41SLeon Romanovsky  * msix_clean_up_interrupts  - Free all MSIx IRQ resources
3106eb4eb10SMichael J. Ruhl  * @dd: valid device data data structure
3116eb4eb10SMichael J. Ruhl  *
3126eb4eb10SMichael J. Ruhl  * Free the MSIx and associated PCI resources, if they have been allocated.
3136eb4eb10SMichael J. Ruhl  */
msix_clean_up_interrupts(struct hfi1_devdata * dd)3146eb4eb10SMichael J. Ruhl void msix_clean_up_interrupts(struct hfi1_devdata *dd)
3156eb4eb10SMichael J. Ruhl {
3166eb4eb10SMichael J. Ruhl 	int i;
3176eb4eb10SMichael J. Ruhl 	struct hfi1_msix_entry *me = dd->msix_info.msix_entries;
3186eb4eb10SMichael J. Ruhl 
3196eb4eb10SMichael J. Ruhl 	/* remove irqs - must happen before disabling/turning off */
3206eb4eb10SMichael J. Ruhl 	for (i = 0; i < dd->msix_info.max_requested; i++, me++)
3216eb4eb10SMichael J. Ruhl 		msix_free_irq(dd, i);
3226eb4eb10SMichael J. Ruhl 
3236eb4eb10SMichael J. Ruhl 	/* clean structures */
3246eb4eb10SMichael J. Ruhl 	kfree(dd->msix_info.msix_entries);
3256eb4eb10SMichael J. Ruhl 	dd->msix_info.msix_entries = NULL;
3266eb4eb10SMichael J. Ruhl 	dd->msix_info.max_requested = 0;
3276eb4eb10SMichael J. Ruhl 
3286eb4eb10SMichael J. Ruhl 	pci_free_irq_vectors(dd->pcidev);
3296eb4eb10SMichael J. Ruhl }
3306eb4eb10SMichael J. Ruhl 
3316eb4eb10SMichael J. Ruhl /**
332*ae360f41SLeon Romanovsky  * msix_netdev_synchronize_irq - netdev IRQ synchronize
3336eb4eb10SMichael J. Ruhl  * @dd: valid devdata
3346eb4eb10SMichael J. Ruhl  */
msix_netdev_synchronize_irq(struct hfi1_devdata * dd)3354730f4a6SGrzegorz Andrejczuk void msix_netdev_synchronize_irq(struct hfi1_devdata *dd)
33609e71899SMichael J. Ruhl {
33709e71899SMichael J. Ruhl 	int i;
3384730f4a6SGrzegorz Andrejczuk 	int ctxt_count = hfi1_netdev_ctxt_count(dd);
33909e71899SMichael J. Ruhl 
3404730f4a6SGrzegorz Andrejczuk 	for (i = 0; i < ctxt_count; i++) {
3414730f4a6SGrzegorz Andrejczuk 		struct hfi1_ctxtdata *rcd = hfi1_netdev_get_ctxt(dd, i);
3426eb4eb10SMichael J. Ruhl 		struct hfi1_msix_entry *me;
3436eb4eb10SMichael J. Ruhl 
3446eb4eb10SMichael J. Ruhl 		me = &dd->msix_info.msix_entries[rcd->msix_intr];
34509e71899SMichael J. Ruhl 
34609e71899SMichael J. Ruhl 		synchronize_irq(me->irq);
34709e71899SMichael J. Ruhl 	}
34809e71899SMichael J. Ruhl }
349