mic_intr.c 17 KB

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