• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Intel MIC Platform Software Stack (MPSS)
4  *
5  * Copyright(c) 2013 Intel Corporation.
6  *
7  * Intel MIC Host driver.
8  */
9 #include <linux/pci.h>
10 #include <linux/interrupt.h>
11 
12 #include "../common/mic_dev.h"
13 #include "mic_device.h"
14 
mic_thread_fn(int irq,void * dev)15 static irqreturn_t mic_thread_fn(int irq, void *dev)
16 {
17 	struct mic_device *mdev = dev;
18 	struct mic_intr_info *intr_info = mdev->intr_info;
19 	struct mic_irq_info *irq_info = &mdev->irq_info;
20 	struct mic_intr_cb *intr_cb;
21 	struct pci_dev *pdev = mdev->pdev;
22 	int i;
23 
24 	spin_lock(&irq_info->mic_thread_lock);
25 	for (i = intr_info->intr_start_idx[MIC_INTR_DB];
26 			i < intr_info->intr_len[MIC_INTR_DB]; i++)
27 		if (test_and_clear_bit(i, &irq_info->mask)) {
28 			list_for_each_entry(intr_cb, &irq_info->cb_list[i],
29 					    list)
30 				if (intr_cb->thread_fn)
31 					intr_cb->thread_fn(pdev->irq,
32 							 intr_cb->data);
33 		}
34 	spin_unlock(&irq_info->mic_thread_lock);
35 	return IRQ_HANDLED;
36 }
37 /**
38  * mic_interrupt - Generic interrupt handler for
39  * MSI and INTx based interrupts.
40  */
mic_interrupt(int irq,void * dev)41 static irqreturn_t mic_interrupt(int irq, void *dev)
42 {
43 	struct mic_device *mdev = dev;
44 	struct mic_intr_info *intr_info = mdev->intr_info;
45 	struct mic_irq_info *irq_info = &mdev->irq_info;
46 	struct mic_intr_cb *intr_cb;
47 	struct pci_dev *pdev = mdev->pdev;
48 	u32 mask;
49 	int i;
50 
51 	mask = mdev->ops->ack_interrupt(mdev);
52 	if (!mask)
53 		return IRQ_NONE;
54 
55 	spin_lock(&irq_info->mic_intr_lock);
56 	for (i = intr_info->intr_start_idx[MIC_INTR_DB];
57 			i < intr_info->intr_len[MIC_INTR_DB]; i++)
58 		if (mask & BIT(i)) {
59 			list_for_each_entry(intr_cb, &irq_info->cb_list[i],
60 					    list)
61 				if (intr_cb->handler)
62 					intr_cb->handler(pdev->irq,
63 							 intr_cb->data);
64 			set_bit(i, &irq_info->mask);
65 		}
66 	spin_unlock(&irq_info->mic_intr_lock);
67 	return IRQ_WAKE_THREAD;
68 }
69 
70 /* Return the interrupt offset from the index. Index is 0 based. */
mic_map_src_to_offset(struct mic_device * mdev,int intr_src,enum mic_intr_type type)71 static u16 mic_map_src_to_offset(struct mic_device *mdev,
72 				 int intr_src, enum mic_intr_type type)
73 {
74 	if (type >= MIC_NUM_INTR_TYPES)
75 		return MIC_NUM_OFFSETS;
76 	if (intr_src >= mdev->intr_info->intr_len[type])
77 		return MIC_NUM_OFFSETS;
78 
79 	return mdev->intr_info->intr_start_idx[type] + intr_src;
80 }
81 
82 /* Return next available msix_entry. */
mic_get_available_vector(struct mic_device * mdev)83 static struct msix_entry *mic_get_available_vector(struct mic_device *mdev)
84 {
85 	int i;
86 	struct mic_irq_info *info = &mdev->irq_info;
87 
88 	for (i = 0; i < info->num_vectors; i++)
89 		if (!info->mic_msi_map[i])
90 			return &info->msix_entries[i];
91 	return NULL;
92 }
93 
94 /**
95  * mic_register_intr_callback - Register a callback handler for the
96  * given source id.
97  *
98  * @mdev: pointer to the mic_device instance
99  * @idx: The source id to be registered.
100  * @handler: The function to be called when the source id receives
101  * the interrupt.
102  * @thread_fn: thread fn. corresponding to the handler
103  * @data: Private data of the requester.
104  * Return the callback structure that was registered or an
105  * appropriate error on failure.
106  */
mic_register_intr_callback(struct mic_device * mdev,u8 idx,irq_handler_t handler,irq_handler_t thread_fn,void * data)107 static struct mic_intr_cb *mic_register_intr_callback(struct mic_device *mdev,
108 			u8 idx, irq_handler_t handler, irq_handler_t thread_fn,
109 			void *data)
110 {
111 	struct mic_intr_cb *intr_cb;
112 	unsigned long flags;
113 	int rc;
114 	intr_cb = kmalloc(sizeof(*intr_cb), GFP_KERNEL);
115 
116 	if (!intr_cb)
117 		return ERR_PTR(-ENOMEM);
118 
119 	intr_cb->handler = handler;
120 	intr_cb->thread_fn = thread_fn;
121 	intr_cb->data = data;
122 	intr_cb->cb_id = ida_simple_get(&mdev->irq_info.cb_ida,
123 		0, 0, GFP_KERNEL);
124 	if (intr_cb->cb_id < 0) {
125 		rc = intr_cb->cb_id;
126 		goto ida_fail;
127 	}
128 
129 	spin_lock(&mdev->irq_info.mic_thread_lock);
130 	spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
131 	list_add_tail(&intr_cb->list, &mdev->irq_info.cb_list[idx]);
132 	spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
133 	spin_unlock(&mdev->irq_info.mic_thread_lock);
134 
135 	return intr_cb;
136 ida_fail:
137 	kfree(intr_cb);
138 	return ERR_PTR(rc);
139 }
140 
141 /**
142  * mic_unregister_intr_callback - Unregister the callback handler
143  * identified by its callback id.
144  *
145  * @mdev: pointer to the mic_device instance
146  * @idx: The callback structure id to be unregistered.
147  * Return the source id that was unregistered or MIC_NUM_OFFSETS if no
148  * such callback handler was found.
149  */
mic_unregister_intr_callback(struct mic_device * mdev,u32 idx)150 static u8 mic_unregister_intr_callback(struct mic_device *mdev, u32 idx)
151 {
152 	struct list_head *pos, *tmp;
153 	struct mic_intr_cb *intr_cb;
154 	unsigned long flags;
155 	int i;
156 
157 	spin_lock(&mdev->irq_info.mic_thread_lock);
158 	spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
159 	for (i = 0;  i < MIC_NUM_OFFSETS; i++) {
160 		list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) {
161 			intr_cb = list_entry(pos, struct mic_intr_cb, list);
162 			if (intr_cb->cb_id == idx) {
163 				list_del(pos);
164 				ida_simple_remove(&mdev->irq_info.cb_ida,
165 						  intr_cb->cb_id);
166 				kfree(intr_cb);
167 				spin_unlock_irqrestore(
168 					&mdev->irq_info.mic_intr_lock, flags);
169 				spin_unlock(&mdev->irq_info.mic_thread_lock);
170 				return i;
171 			}
172 		}
173 	}
174 	spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
175 	spin_unlock(&mdev->irq_info.mic_thread_lock);
176 	return MIC_NUM_OFFSETS;
177 }
178 
179 /**
180  * mic_setup_msix - Initializes MSIx interrupts.
181  *
182  * @mdev: pointer to mic_device instance
183  *
184  *
185  * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
186  */
mic_setup_msix(struct mic_device * mdev,struct pci_dev * pdev)187 static int mic_setup_msix(struct mic_device *mdev, struct pci_dev *pdev)
188 {
189 	int rc, i;
190 	int entry_size = sizeof(*mdev->irq_info.msix_entries);
191 
192 	mdev->irq_info.msix_entries = kmalloc_array(MIC_MIN_MSIX,
193 						    entry_size, GFP_KERNEL);
194 	if (!mdev->irq_info.msix_entries) {
195 		rc = -ENOMEM;
196 		goto err_nomem1;
197 	}
198 
199 	for (i = 0; i < MIC_MIN_MSIX; i++)
200 		mdev->irq_info.msix_entries[i].entry = i;
201 
202 	rc = pci_enable_msix_exact(pdev, mdev->irq_info.msix_entries,
203 				   MIC_MIN_MSIX);
204 	if (rc) {
205 		dev_dbg(&pdev->dev, "Error enabling MSIx. rc = %d\n", rc);
206 		goto err_enable_msix;
207 	}
208 
209 	mdev->irq_info.num_vectors = MIC_MIN_MSIX;
210 	mdev->irq_info.mic_msi_map = kzalloc((sizeof(u32) *
211 		mdev->irq_info.num_vectors), GFP_KERNEL);
212 
213 	if (!mdev->irq_info.mic_msi_map) {
214 		rc = -ENOMEM;
215 		goto err_nomem2;
216 	}
217 
218 	dev_dbg(&mdev->pdev->dev,
219 		"%d MSIx irqs setup\n", mdev->irq_info.num_vectors);
220 	return 0;
221 err_nomem2:
222 	pci_disable_msix(pdev);
223 err_enable_msix:
224 	kfree(mdev->irq_info.msix_entries);
225 err_nomem1:
226 	mdev->irq_info.num_vectors = 0;
227 	return rc;
228 }
229 
230 /**
231  * mic_setup_callbacks - Initialize data structures needed
232  * to handle callbacks.
233  *
234  * @mdev: pointer to mic_device instance
235  */
mic_setup_callbacks(struct mic_device * mdev)236 static int mic_setup_callbacks(struct mic_device *mdev)
237 {
238 	int i;
239 
240 	mdev->irq_info.cb_list = kmalloc_array(MIC_NUM_OFFSETS,
241 					       sizeof(*mdev->irq_info.cb_list),
242 					       GFP_KERNEL);
243 	if (!mdev->irq_info.cb_list)
244 		return -ENOMEM;
245 
246 	for (i = 0; i < MIC_NUM_OFFSETS; i++)
247 		INIT_LIST_HEAD(&mdev->irq_info.cb_list[i]);
248 	ida_init(&mdev->irq_info.cb_ida);
249 	spin_lock_init(&mdev->irq_info.mic_intr_lock);
250 	spin_lock_init(&mdev->irq_info.mic_thread_lock);
251 	return 0;
252 }
253 
254 /**
255  * mic_release_callbacks - Uninitialize data structures needed
256  * to handle callbacks.
257  *
258  * @mdev: pointer to mic_device instance
259  */
mic_release_callbacks(struct mic_device * mdev)260 static void mic_release_callbacks(struct mic_device *mdev)
261 {
262 	unsigned long flags;
263 	struct list_head *pos, *tmp;
264 	struct mic_intr_cb *intr_cb;
265 	int i;
266 
267 	spin_lock(&mdev->irq_info.mic_thread_lock);
268 	spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
269 	for (i = 0; i < MIC_NUM_OFFSETS; i++) {
270 		if (list_empty(&mdev->irq_info.cb_list[i]))
271 			break;
272 
273 		list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) {
274 			intr_cb = list_entry(pos, struct mic_intr_cb, list);
275 			list_del(pos);
276 			ida_simple_remove(&mdev->irq_info.cb_ida,
277 					  intr_cb->cb_id);
278 			kfree(intr_cb);
279 		}
280 	}
281 	spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
282 	spin_unlock(&mdev->irq_info.mic_thread_lock);
283 	ida_destroy(&mdev->irq_info.cb_ida);
284 	kfree(mdev->irq_info.cb_list);
285 }
286 
287 /**
288  * mic_setup_msi - Initializes MSI interrupts.
289  *
290  * @mdev: pointer to mic_device instance
291  * @pdev: PCI device structure
292  *
293  * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
294  */
mic_setup_msi(struct mic_device * mdev,struct pci_dev * pdev)295 static int mic_setup_msi(struct mic_device *mdev, struct pci_dev *pdev)
296 {
297 	int rc;
298 
299 	rc = pci_enable_msi(pdev);
300 	if (rc) {
301 		dev_dbg(&pdev->dev, "Error enabling MSI. rc = %d\n", rc);
302 		return rc;
303 	}
304 
305 	mdev->irq_info.num_vectors = 1;
306 	mdev->irq_info.mic_msi_map = kzalloc((sizeof(u32) *
307 		mdev->irq_info.num_vectors), GFP_KERNEL);
308 
309 	if (!mdev->irq_info.mic_msi_map) {
310 		rc = -ENOMEM;
311 		goto err_nomem1;
312 	}
313 
314 	rc = mic_setup_callbacks(mdev);
315 	if (rc) {
316 		dev_err(&pdev->dev, "Error setting up callbacks\n");
317 		goto err_nomem2;
318 	}
319 
320 	rc = request_threaded_irq(pdev->irq, mic_interrupt, mic_thread_fn,
321 				  0, "mic-msi", mdev);
322 	if (rc) {
323 		dev_err(&pdev->dev, "Error allocating MSI interrupt\n");
324 		goto err_irq_req_fail;
325 	}
326 
327 	dev_dbg(&pdev->dev, "%d MSI irqs setup\n", mdev->irq_info.num_vectors);
328 	return 0;
329 err_irq_req_fail:
330 	mic_release_callbacks(mdev);
331 err_nomem2:
332 	kfree(mdev->irq_info.mic_msi_map);
333 err_nomem1:
334 	pci_disable_msi(pdev);
335 	mdev->irq_info.num_vectors = 0;
336 	return rc;
337 }
338 
339 /**
340  * mic_setup_intx - Initializes legacy interrupts.
341  *
342  * @mdev: pointer to mic_device instance
343  * @pdev: PCI device structure
344  *
345  * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
346  */
mic_setup_intx(struct mic_device * mdev,struct pci_dev * pdev)347 static int mic_setup_intx(struct mic_device *mdev, struct pci_dev *pdev)
348 {
349 	int rc;
350 
351 	/* Enable intx */
352 	pci_intx(pdev, 1);
353 	rc = mic_setup_callbacks(mdev);
354 	if (rc) {
355 		dev_err(&pdev->dev, "Error setting up callbacks\n");
356 		goto err_nomem;
357 	}
358 
359 	rc = request_threaded_irq(pdev->irq, mic_interrupt, mic_thread_fn,
360 				  IRQF_SHARED, "mic-intx", mdev);
361 	if (rc)
362 		goto err;
363 
364 	dev_dbg(&pdev->dev, "intx irq setup\n");
365 	return 0;
366 err:
367 	mic_release_callbacks(mdev);
368 err_nomem:
369 	return rc;
370 }
371 
372 /**
373  * mic_next_db - Retrieve the next doorbell interrupt source id.
374  * The id is picked sequentially from the available pool of
375  * doorlbell ids.
376  *
377  * @mdev: pointer to the mic_device instance.
378  *
379  * Returns the next doorbell interrupt source.
380  */
mic_next_db(struct mic_device * mdev)381 int mic_next_db(struct mic_device *mdev)
382 {
383 	int next_db;
384 
385 	next_db = mdev->irq_info.next_avail_src %
386 		mdev->intr_info->intr_len[MIC_INTR_DB];
387 	mdev->irq_info.next_avail_src++;
388 	return next_db;
389 }
390 
391 #define COOKIE_ID_SHIFT 16
392 #define GET_ENTRY(cookie) ((cookie) & 0xFFFF)
393 #define GET_OFFSET(cookie) ((cookie) >> COOKIE_ID_SHIFT)
394 #define MK_COOKIE(x, y) ((x) | (y) << COOKIE_ID_SHIFT)
395 
396 /**
397  * mic_request_threaded_irq - request an irq. mic_mutex needs
398  * to be held before calling this function.
399  *
400  * @mdev: pointer to mic_device instance
401  * @handler: The callback function that handles the interrupt.
402  * The function needs to call ack_interrupts
403  * (mdev->ops->ack_interrupt(mdev)) when handling the interrupts.
404  * @thread_fn: thread fn required by request_threaded_irq.
405  * @name: The ASCII name of the callee requesting the irq.
406  * @data: private data that is returned back when calling the
407  * function handler.
408  * @intr_src: The source id of the requester. Its the doorbell id
409  * for Doorbell interrupts and DMA channel id for DMA interrupts.
410  * @type: The type of interrupt. Values defined in mic_intr_type
411  *
412  * returns: The cookie that is transparent to the caller. Passed
413  * back when calling mic_free_irq. An appropriate error code
414  * is returned on failure. Caller needs to use IS_ERR(return_val)
415  * to check for failure and PTR_ERR(return_val) to obtained the
416  * error code.
417  *
418  */
419 struct mic_irq *
mic_request_threaded_irq(struct mic_device * mdev,irq_handler_t handler,irq_handler_t thread_fn,const char * name,void * data,int intr_src,enum mic_intr_type type)420 mic_request_threaded_irq(struct mic_device *mdev,
421 			 irq_handler_t handler, irq_handler_t thread_fn,
422 			 const char *name, void *data, int intr_src,
423 			 enum mic_intr_type type)
424 {
425 	u16 offset;
426 	int rc = 0;
427 	struct msix_entry *msix = NULL;
428 	unsigned long cookie = 0;
429 	u16 entry;
430 	struct mic_intr_cb *intr_cb;
431 	struct pci_dev *pdev = mdev->pdev;
432 
433 	offset = mic_map_src_to_offset(mdev, intr_src, type);
434 	if (offset >= MIC_NUM_OFFSETS) {
435 		dev_err(&mdev->pdev->dev,
436 			"Error mapping index %d to a valid source id.\n",
437 			intr_src);
438 		rc = -EINVAL;
439 		goto err;
440 	}
441 
442 	if (mdev->irq_info.num_vectors > 1) {
443 		msix = mic_get_available_vector(mdev);
444 		if (!msix) {
445 			dev_err(&mdev->pdev->dev,
446 				"No MSIx vectors available for use.\n");
447 			rc = -ENOSPC;
448 			goto err;
449 		}
450 
451 		rc = request_threaded_irq(msix->vector, handler, thread_fn,
452 					  0, name, data);
453 		if (rc) {
454 			dev_dbg(&mdev->pdev->dev,
455 				"request irq failed rc = %d\n", rc);
456 			goto err;
457 		}
458 		entry = msix->entry;
459 		mdev->irq_info.mic_msi_map[entry] |= BIT(offset);
460 		mdev->intr_ops->program_msi_to_src_map(mdev,
461 				entry, offset, true);
462 		cookie = MK_COOKIE(entry, offset);
463 		dev_dbg(&mdev->pdev->dev, "irq: %d assigned for src: %d\n",
464 			msix->vector, intr_src);
465 	} else {
466 		intr_cb = mic_register_intr_callback(mdev, offset, handler,
467 						     thread_fn, data);
468 		if (IS_ERR(intr_cb)) {
469 			dev_err(&mdev->pdev->dev,
470 				"No available callback entries for use\n");
471 			rc = PTR_ERR(intr_cb);
472 			goto err;
473 		}
474 
475 		entry = 0;
476 		if (pci_dev_msi_enabled(pdev)) {
477 			mdev->irq_info.mic_msi_map[entry] |= (1 << offset);
478 			mdev->intr_ops->program_msi_to_src_map(mdev,
479 				entry, offset, true);
480 		}
481 		cookie = MK_COOKIE(entry, intr_cb->cb_id);
482 		dev_dbg(&mdev->pdev->dev, "callback %d registered for src: %d\n",
483 			intr_cb->cb_id, intr_src);
484 	}
485 	return (struct mic_irq *)cookie;
486 err:
487 	return ERR_PTR(rc);
488 }
489 
490 /**
491  * mic_free_irq - free irq. mic_mutex
492  *  needs to be held before calling this function.
493  *
494  * @mdev: pointer to mic_device instance
495  * @cookie: cookie obtained during a successful call to mic_request_threaded_irq
496  * @data: private data specified by the calling function during the
497  * mic_request_threaded_irq
498  *
499  * returns: none.
500  */
mic_free_irq(struct mic_device * mdev,struct mic_irq * cookie,void * data)501 void mic_free_irq(struct mic_device *mdev,
502 		  struct mic_irq *cookie, void *data)
503 {
504 	u32 offset;
505 	u32 entry;
506 	u8 src_id;
507 	unsigned int irq;
508 	struct pci_dev *pdev = mdev->pdev;
509 
510 	entry = GET_ENTRY((unsigned long)cookie);
511 	offset = GET_OFFSET((unsigned long)cookie);
512 	if (mdev->irq_info.num_vectors > 1) {
513 		if (entry >= mdev->irq_info.num_vectors) {
514 			dev_warn(&mdev->pdev->dev,
515 				 "entry %d should be < num_irq %d\n",
516 				entry, mdev->irq_info.num_vectors);
517 			return;
518 		}
519 		irq = mdev->irq_info.msix_entries[entry].vector;
520 		free_irq(irq, data);
521 		mdev->irq_info.mic_msi_map[entry] &= ~(BIT(offset));
522 		mdev->intr_ops->program_msi_to_src_map(mdev,
523 			entry, offset, false);
524 
525 		dev_dbg(&mdev->pdev->dev, "irq: %d freed\n", irq);
526 	} else {
527 		irq = pdev->irq;
528 		src_id = mic_unregister_intr_callback(mdev, offset);
529 		if (src_id >= MIC_NUM_OFFSETS) {
530 			dev_warn(&mdev->pdev->dev, "Error unregistering callback\n");
531 			return;
532 		}
533 		if (pci_dev_msi_enabled(pdev)) {
534 			mdev->irq_info.mic_msi_map[entry] &= ~(BIT(src_id));
535 			mdev->intr_ops->program_msi_to_src_map(mdev,
536 				entry, src_id, false);
537 		}
538 		dev_dbg(&mdev->pdev->dev, "callback %d unregistered for src: %d\n",
539 			offset, src_id);
540 	}
541 }
542 
543 /**
544  * mic_setup_interrupts - Initializes interrupts.
545  *
546  * @mdev: pointer to mic_device instance
547  * @pdev: PCI device structure
548  *
549  * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
550  */
mic_setup_interrupts(struct mic_device * mdev,struct pci_dev * pdev)551 int mic_setup_interrupts(struct mic_device *mdev, struct pci_dev *pdev)
552 {
553 	int rc;
554 
555 	rc = mic_setup_msix(mdev, pdev);
556 	if (!rc)
557 		goto done;
558 
559 	rc = mic_setup_msi(mdev, pdev);
560 	if (!rc)
561 		goto done;
562 
563 	rc = mic_setup_intx(mdev, pdev);
564 	if (rc) {
565 		dev_err(&mdev->pdev->dev, "no usable interrupts\n");
566 		return rc;
567 	}
568 done:
569 	mdev->intr_ops->enable_interrupts(mdev);
570 	return 0;
571 }
572 
573 /**
574  * mic_free_interrupts - Frees interrupts setup by mic_setup_interrupts
575  *
576  * @mdev: pointer to mic_device instance
577  * @pdev: PCI device structure
578  *
579  * returns none.
580  */
mic_free_interrupts(struct mic_device * mdev,struct pci_dev * pdev)581 void mic_free_interrupts(struct mic_device *mdev, struct pci_dev *pdev)
582 {
583 	int i;
584 
585 	mdev->intr_ops->disable_interrupts(mdev);
586 	if (mdev->irq_info.num_vectors > 1) {
587 		for (i = 0; i < mdev->irq_info.num_vectors; i++) {
588 			if (mdev->irq_info.mic_msi_map[i])
589 				dev_warn(&pdev->dev, "irq %d may still be in use.\n",
590 					 mdev->irq_info.msix_entries[i].vector);
591 		}
592 		kfree(mdev->irq_info.mic_msi_map);
593 		kfree(mdev->irq_info.msix_entries);
594 		pci_disable_msix(pdev);
595 	} else {
596 		if (pci_dev_msi_enabled(pdev)) {
597 			free_irq(pdev->irq, mdev);
598 			kfree(mdev->irq_info.mic_msi_map);
599 			pci_disable_msi(pdev);
600 		} else {
601 			free_irq(pdev->irq, mdev);
602 		}
603 		mic_release_callbacks(mdev);
604 	}
605 }
606 
607 /**
608  * mic_intr_restore - Restore MIC interrupt registers.
609  *
610  * @mdev: pointer to mic_device instance.
611  *
612  * Restore the interrupt registers to values previously
613  * stored in the SW data structures. mic_mutex needs to
614  * be held before calling this function.
615  *
616  * returns None.
617  */
mic_intr_restore(struct mic_device * mdev)618 void mic_intr_restore(struct mic_device *mdev)
619 {
620 	int entry, offset;
621 	struct pci_dev *pdev = mdev->pdev;
622 
623 	if (!pci_dev_msi_enabled(pdev))
624 		return;
625 
626 	for (entry = 0; entry < mdev->irq_info.num_vectors; entry++) {
627 		for (offset = 0; offset < MIC_NUM_OFFSETS; offset++) {
628 			if (mdev->irq_info.mic_msi_map[entry] & BIT(offset))
629 				mdev->intr_ops->program_msi_to_src_map(mdev,
630 					entry, offset, true);
631 		}
632 	}
633 }
634