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