mic_intr.c 16 KB

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