mic_intr.c 17 KB

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