msi.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753
  1. /*
  2. * File: msi.c
  3. * Purpose: PCI Message Signaled Interrupt (MSI)
  4. *
  5. * Copyright (C) 2003-2004 Intel
  6. * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
  7. */
  8. #include <linux/err.h>
  9. #include <linux/mm.h>
  10. #include <linux/irq.h>
  11. #include <linux/interrupt.h>
  12. #include <linux/init.h>
  13. #include <linux/ioport.h>
  14. #include <linux/pci.h>
  15. #include <linux/proc_fs.h>
  16. #include <linux/msi.h>
  17. #include <linux/smp.h>
  18. #include <asm/errno.h>
  19. #include <asm/io.h>
  20. #include "pci.h"
  21. #include "msi.h"
  22. static int pci_msi_enable = 1;
  23. /* Arch hooks */
  24. int __attribute__ ((weak))
  25. arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
  26. {
  27. return 0;
  28. }
  29. int __attribute__ ((weak))
  30. arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *entry)
  31. {
  32. return 0;
  33. }
  34. int __attribute__ ((weak))
  35. arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
  36. {
  37. struct msi_desc *entry;
  38. int ret;
  39. list_for_each_entry(entry, &dev->msi_list, list) {
  40. ret = arch_setup_msi_irq(dev, entry);
  41. if (ret)
  42. return ret;
  43. }
  44. return 0;
  45. }
  46. void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq)
  47. {
  48. return;
  49. }
  50. void __attribute__ ((weak))
  51. arch_teardown_msi_irqs(struct pci_dev *dev)
  52. {
  53. struct msi_desc *entry;
  54. list_for_each_entry(entry, &dev->msi_list, list) {
  55. if (entry->irq != 0)
  56. arch_teardown_msi_irq(entry->irq);
  57. }
  58. }
  59. static void msi_set_enable(struct pci_dev *dev, int enable)
  60. {
  61. int pos;
  62. u16 control;
  63. pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
  64. if (pos) {
  65. pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
  66. control &= ~PCI_MSI_FLAGS_ENABLE;
  67. if (enable)
  68. control |= PCI_MSI_FLAGS_ENABLE;
  69. pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
  70. }
  71. }
  72. static void msix_set_enable(struct pci_dev *dev, int enable)
  73. {
  74. int pos;
  75. u16 control;
  76. pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
  77. if (pos) {
  78. pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
  79. control &= ~PCI_MSIX_FLAGS_ENABLE;
  80. if (enable)
  81. control |= PCI_MSIX_FLAGS_ENABLE;
  82. pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
  83. }
  84. }
  85. static void msix_flush_writes(unsigned int irq)
  86. {
  87. struct msi_desc *entry;
  88. entry = get_irq_msi(irq);
  89. BUG_ON(!entry || !entry->dev);
  90. switch (entry->msi_attrib.type) {
  91. case PCI_CAP_ID_MSI:
  92. /* nothing to do */
  93. break;
  94. case PCI_CAP_ID_MSIX:
  95. {
  96. int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
  97. PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET;
  98. readl(entry->mask_base + offset);
  99. break;
  100. }
  101. default:
  102. BUG();
  103. break;
  104. }
  105. }
  106. static void msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag)
  107. {
  108. struct msi_desc *entry;
  109. entry = get_irq_msi(irq);
  110. BUG_ON(!entry || !entry->dev);
  111. switch (entry->msi_attrib.type) {
  112. case PCI_CAP_ID_MSI:
  113. if (entry->msi_attrib.maskbit) {
  114. int pos;
  115. u32 mask_bits;
  116. pos = (long)entry->mask_base;
  117. pci_read_config_dword(entry->dev, pos, &mask_bits);
  118. mask_bits &= ~(mask);
  119. mask_bits |= flag & mask;
  120. pci_write_config_dword(entry->dev, pos, mask_bits);
  121. } else {
  122. msi_set_enable(entry->dev, !flag);
  123. }
  124. break;
  125. case PCI_CAP_ID_MSIX:
  126. {
  127. int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
  128. PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET;
  129. writel(flag, entry->mask_base + offset);
  130. readl(entry->mask_base + offset);
  131. break;
  132. }
  133. default:
  134. BUG();
  135. break;
  136. }
  137. entry->msi_attrib.masked = !!flag;
  138. }
  139. void read_msi_msg(unsigned int irq, struct msi_msg *msg)
  140. {
  141. struct msi_desc *entry = get_irq_msi(irq);
  142. switch(entry->msi_attrib.type) {
  143. case PCI_CAP_ID_MSI:
  144. {
  145. struct pci_dev *dev = entry->dev;
  146. int pos = entry->msi_attrib.pos;
  147. u16 data;
  148. pci_read_config_dword(dev, msi_lower_address_reg(pos),
  149. &msg->address_lo);
  150. if (entry->msi_attrib.is_64) {
  151. pci_read_config_dword(dev, msi_upper_address_reg(pos),
  152. &msg->address_hi);
  153. pci_read_config_word(dev, msi_data_reg(pos, 1), &data);
  154. } else {
  155. msg->address_hi = 0;
  156. pci_read_config_word(dev, msi_data_reg(pos, 0), &data);
  157. }
  158. msg->data = data;
  159. break;
  160. }
  161. case PCI_CAP_ID_MSIX:
  162. {
  163. void __iomem *base;
  164. base = entry->mask_base +
  165. entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE;
  166. msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
  167. msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
  168. msg->data = readl(base + PCI_MSIX_ENTRY_DATA_OFFSET);
  169. break;
  170. }
  171. default:
  172. BUG();
  173. }
  174. }
  175. void write_msi_msg(unsigned int irq, struct msi_msg *msg)
  176. {
  177. struct msi_desc *entry = get_irq_msi(irq);
  178. switch (entry->msi_attrib.type) {
  179. case PCI_CAP_ID_MSI:
  180. {
  181. struct pci_dev *dev = entry->dev;
  182. int pos = entry->msi_attrib.pos;
  183. pci_write_config_dword(dev, msi_lower_address_reg(pos),
  184. msg->address_lo);
  185. if (entry->msi_attrib.is_64) {
  186. pci_write_config_dword(dev, msi_upper_address_reg(pos),
  187. msg->address_hi);
  188. pci_write_config_word(dev, msi_data_reg(pos, 1),
  189. msg->data);
  190. } else {
  191. pci_write_config_word(dev, msi_data_reg(pos, 0),
  192. msg->data);
  193. }
  194. break;
  195. }
  196. case PCI_CAP_ID_MSIX:
  197. {
  198. void __iomem *base;
  199. base = entry->mask_base +
  200. entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE;
  201. writel(msg->address_lo,
  202. base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
  203. writel(msg->address_hi,
  204. base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
  205. writel(msg->data, base + PCI_MSIX_ENTRY_DATA_OFFSET);
  206. break;
  207. }
  208. default:
  209. BUG();
  210. }
  211. entry->msg = *msg;
  212. }
  213. void mask_msi_irq(unsigned int irq)
  214. {
  215. msi_set_mask_bits(irq, 1, 1);
  216. msix_flush_writes(irq);
  217. }
  218. void unmask_msi_irq(unsigned int irq)
  219. {
  220. msi_set_mask_bits(irq, 1, 0);
  221. msix_flush_writes(irq);
  222. }
  223. static int msi_free_irqs(struct pci_dev* dev);
  224. static struct msi_desc* alloc_msi_entry(void)
  225. {
  226. struct msi_desc *entry;
  227. entry = kzalloc(sizeof(struct msi_desc), GFP_KERNEL);
  228. if (!entry)
  229. return NULL;
  230. INIT_LIST_HEAD(&entry->list);
  231. entry->irq = 0;
  232. entry->dev = NULL;
  233. return entry;
  234. }
  235. static void pci_intx_for_msi(struct pci_dev *dev, int enable)
  236. {
  237. if (!(dev->dev_flags & PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG))
  238. pci_intx(dev, enable);
  239. }
  240. static void __pci_restore_msi_state(struct pci_dev *dev)
  241. {
  242. int pos;
  243. u16 control;
  244. struct msi_desc *entry;
  245. if (!dev->msi_enabled)
  246. return;
  247. entry = get_irq_msi(dev->irq);
  248. pos = entry->msi_attrib.pos;
  249. pci_intx_for_msi(dev, 0);
  250. msi_set_enable(dev, 0);
  251. write_msi_msg(dev->irq, &entry->msg);
  252. if (entry->msi_attrib.maskbit)
  253. msi_set_mask_bits(dev->irq, entry->msi_attrib.maskbits_mask,
  254. entry->msi_attrib.masked);
  255. pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
  256. control &= ~(PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE);
  257. if (entry->msi_attrib.maskbit || !entry->msi_attrib.masked)
  258. control |= PCI_MSI_FLAGS_ENABLE;
  259. pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
  260. }
  261. static void __pci_restore_msix_state(struct pci_dev *dev)
  262. {
  263. int pos;
  264. struct msi_desc *entry;
  265. u16 control;
  266. if (!dev->msix_enabled)
  267. return;
  268. /* route the table */
  269. pci_intx_for_msi(dev, 0);
  270. msix_set_enable(dev, 0);
  271. list_for_each_entry(entry, &dev->msi_list, list) {
  272. write_msi_msg(entry->irq, &entry->msg);
  273. msi_set_mask_bits(entry->irq, 1, entry->msi_attrib.masked);
  274. }
  275. BUG_ON(list_empty(&dev->msi_list));
  276. entry = list_entry(dev->msi_list.next, struct msi_desc, list);
  277. pos = entry->msi_attrib.pos;
  278. pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
  279. control &= ~PCI_MSIX_FLAGS_MASKALL;
  280. control |= PCI_MSIX_FLAGS_ENABLE;
  281. pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
  282. }
  283. void pci_restore_msi_state(struct pci_dev *dev)
  284. {
  285. __pci_restore_msi_state(dev);
  286. __pci_restore_msix_state(dev);
  287. }
  288. EXPORT_SYMBOL_GPL(pci_restore_msi_state);
  289. /**
  290. * msi_capability_init - configure device's MSI capability structure
  291. * @dev: pointer to the pci_dev data structure of MSI device function
  292. *
  293. * Setup the MSI capability structure of device function with a single
  294. * MSI irq, regardless of device function is capable of handling
  295. * multiple messages. A return of zero indicates the successful setup
  296. * of an entry zero with the new MSI irq or non-zero for otherwise.
  297. **/
  298. static int msi_capability_init(struct pci_dev *dev)
  299. {
  300. struct msi_desc *entry;
  301. int pos, ret;
  302. u16 control;
  303. msi_set_enable(dev, 0); /* Ensure msi is disabled as I set it up */
  304. pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
  305. pci_read_config_word(dev, msi_control_reg(pos), &control);
  306. /* MSI Entry Initialization */
  307. entry = alloc_msi_entry();
  308. if (!entry)
  309. return -ENOMEM;
  310. entry->msi_attrib.type = PCI_CAP_ID_MSI;
  311. entry->msi_attrib.is_64 = is_64bit_address(control);
  312. entry->msi_attrib.entry_nr = 0;
  313. entry->msi_attrib.maskbit = is_mask_bit_support(control);
  314. entry->msi_attrib.masked = 1;
  315. entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */
  316. entry->msi_attrib.pos = pos;
  317. if (is_mask_bit_support(control)) {
  318. entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos,
  319. is_64bit_address(control));
  320. }
  321. entry->dev = dev;
  322. if (entry->msi_attrib.maskbit) {
  323. unsigned int maskbits, temp;
  324. /* All MSIs are unmasked by default, Mask them all */
  325. pci_read_config_dword(dev,
  326. msi_mask_bits_reg(pos, is_64bit_address(control)),
  327. &maskbits);
  328. temp = (1 << multi_msi_capable(control));
  329. temp = ((temp - 1) & ~temp);
  330. maskbits |= temp;
  331. pci_write_config_dword(dev,
  332. msi_mask_bits_reg(pos, is_64bit_address(control)),
  333. maskbits);
  334. entry->msi_attrib.maskbits_mask = temp;
  335. }
  336. list_add_tail(&entry->list, &dev->msi_list);
  337. /* Configure MSI capability structure */
  338. ret = arch_setup_msi_irqs(dev, 1, PCI_CAP_ID_MSI);
  339. if (ret) {
  340. msi_free_irqs(dev);
  341. return ret;
  342. }
  343. /* Set MSI enabled bits */
  344. pci_intx_for_msi(dev, 0);
  345. msi_set_enable(dev, 1);
  346. dev->msi_enabled = 1;
  347. dev->irq = entry->irq;
  348. return 0;
  349. }
  350. /**
  351. * msix_capability_init - configure device's MSI-X capability
  352. * @dev: pointer to the pci_dev data structure of MSI-X device function
  353. * @entries: pointer to an array of struct msix_entry entries
  354. * @nvec: number of @entries
  355. *
  356. * Setup the MSI-X capability structure of device function with a
  357. * single MSI-X irq. A return of zero indicates the successful setup of
  358. * requested MSI-X entries with allocated irqs or non-zero for otherwise.
  359. **/
  360. static int msix_capability_init(struct pci_dev *dev,
  361. struct msix_entry *entries, int nvec)
  362. {
  363. struct msi_desc *entry;
  364. int pos, i, j, nr_entries, ret;
  365. unsigned long phys_addr;
  366. u32 table_offset;
  367. u16 control;
  368. u8 bir;
  369. void __iomem *base;
  370. msix_set_enable(dev, 0);/* Ensure msix is disabled as I set it up */
  371. pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
  372. /* Request & Map MSI-X table region */
  373. pci_read_config_word(dev, msi_control_reg(pos), &control);
  374. nr_entries = multi_msix_capable(control);
  375. pci_read_config_dword(dev, msix_table_offset_reg(pos), &table_offset);
  376. bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
  377. table_offset &= ~PCI_MSIX_FLAGS_BIRMASK;
  378. phys_addr = pci_resource_start (dev, bir) + table_offset;
  379. base = ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE);
  380. if (base == NULL)
  381. return -ENOMEM;
  382. /* MSI-X Table Initialization */
  383. for (i = 0; i < nvec; i++) {
  384. entry = alloc_msi_entry();
  385. if (!entry)
  386. break;
  387. j = entries[i].entry;
  388. entry->msi_attrib.type = PCI_CAP_ID_MSIX;
  389. entry->msi_attrib.is_64 = 1;
  390. entry->msi_attrib.entry_nr = j;
  391. entry->msi_attrib.maskbit = 1;
  392. entry->msi_attrib.masked = 1;
  393. entry->msi_attrib.default_irq = dev->irq;
  394. entry->msi_attrib.pos = pos;
  395. entry->dev = dev;
  396. entry->mask_base = base;
  397. list_add_tail(&entry->list, &dev->msi_list);
  398. }
  399. ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX);
  400. if (ret) {
  401. int avail = 0;
  402. list_for_each_entry(entry, &dev->msi_list, list) {
  403. if (entry->irq != 0) {
  404. avail++;
  405. }
  406. }
  407. msi_free_irqs(dev);
  408. /* If we had some success report the number of irqs
  409. * we succeeded in setting up.
  410. */
  411. if (avail == 0)
  412. avail = ret;
  413. return avail;
  414. }
  415. i = 0;
  416. list_for_each_entry(entry, &dev->msi_list, list) {
  417. entries[i].vector = entry->irq;
  418. set_irq_msi(entry->irq, entry);
  419. i++;
  420. }
  421. /* Set MSI-X enabled bits */
  422. pci_intx_for_msi(dev, 0);
  423. msix_set_enable(dev, 1);
  424. dev->msix_enabled = 1;
  425. return 0;
  426. }
  427. /**
  428. * pci_msi_check_device - check whether MSI may be enabled on a device
  429. * @dev: pointer to the pci_dev data structure of MSI device function
  430. * @nvec: how many MSIs have been requested ?
  431. * @type: are we checking for MSI or MSI-X ?
  432. *
  433. * Look at global flags, the device itself, and its parent busses
  434. * to determine if MSI/-X are supported for the device. If MSI/-X is
  435. * supported return 0, else return an error code.
  436. **/
  437. static int pci_msi_check_device(struct pci_dev* dev, int nvec, int type)
  438. {
  439. struct pci_bus *bus;
  440. int ret;
  441. /* MSI must be globally enabled and supported by the device */
  442. if (!pci_msi_enable || !dev || dev->no_msi)
  443. return -EINVAL;
  444. /*
  445. * You can't ask to have 0 or less MSIs configured.
  446. * a) it's stupid ..
  447. * b) the list manipulation code assumes nvec >= 1.
  448. */
  449. if (nvec < 1)
  450. return -ERANGE;
  451. /* Any bridge which does NOT route MSI transactions from it's
  452. * secondary bus to it's primary bus must set NO_MSI flag on
  453. * the secondary pci_bus.
  454. * We expect only arch-specific PCI host bus controller driver
  455. * or quirks for specific PCI bridges to be setting NO_MSI.
  456. */
  457. for (bus = dev->bus; bus; bus = bus->parent)
  458. if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
  459. return -EINVAL;
  460. ret = arch_msi_check_device(dev, nvec, type);
  461. if (ret)
  462. return ret;
  463. if (!pci_find_capability(dev, type))
  464. return -EINVAL;
  465. return 0;
  466. }
  467. /**
  468. * pci_enable_msi - configure device's MSI capability structure
  469. * @dev: pointer to the pci_dev data structure of MSI device function
  470. *
  471. * Setup the MSI capability structure of device function with
  472. * a single MSI irq upon its software driver call to request for
  473. * MSI mode enabled on its hardware device function. A return of zero
  474. * indicates the successful setup of an entry zero with the new MSI
  475. * irq or non-zero for otherwise.
  476. **/
  477. int pci_enable_msi(struct pci_dev* dev)
  478. {
  479. int status;
  480. status = pci_msi_check_device(dev, 1, PCI_CAP_ID_MSI);
  481. if (status)
  482. return status;
  483. WARN_ON(!!dev->msi_enabled);
  484. /* Check whether driver already requested for MSI-X irqs */
  485. if (dev->msix_enabled) {
  486. printk(KERN_INFO "PCI: %s: Can't enable MSI. "
  487. "Device already has MSI-X enabled\n",
  488. pci_name(dev));
  489. return -EINVAL;
  490. }
  491. status = msi_capability_init(dev);
  492. return status;
  493. }
  494. EXPORT_SYMBOL(pci_enable_msi);
  495. void pci_msi_shutdown(struct pci_dev* dev)
  496. {
  497. struct msi_desc *entry;
  498. if (!pci_msi_enable || !dev || !dev->msi_enabled)
  499. return;
  500. msi_set_enable(dev, 0);
  501. pci_intx_for_msi(dev, 1);
  502. dev->msi_enabled = 0;
  503. BUG_ON(list_empty(&dev->msi_list));
  504. entry = list_entry(dev->msi_list.next, struct msi_desc, list);
  505. /* Return the the pci reset with msi irqs unmasked */
  506. if (entry->msi_attrib.maskbit) {
  507. u32 mask = entry->msi_attrib.maskbits_mask;
  508. msi_set_mask_bits(dev->irq, mask, ~mask);
  509. }
  510. if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI)
  511. return;
  512. /* Restore dev->irq to its default pin-assertion irq */
  513. dev->irq = entry->msi_attrib.default_irq;
  514. }
  515. void pci_disable_msi(struct pci_dev* dev)
  516. {
  517. struct msi_desc *entry;
  518. if (!pci_msi_enable || !dev || !dev->msi_enabled)
  519. return;
  520. pci_msi_shutdown(dev);
  521. entry = list_entry(dev->msi_list.next, struct msi_desc, list);
  522. if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI)
  523. return;
  524. msi_free_irqs(dev);
  525. }
  526. EXPORT_SYMBOL(pci_disable_msi);
  527. static int msi_free_irqs(struct pci_dev* dev)
  528. {
  529. struct msi_desc *entry, *tmp;
  530. list_for_each_entry(entry, &dev->msi_list, list) {
  531. if (entry->irq)
  532. BUG_ON(irq_has_action(entry->irq));
  533. }
  534. arch_teardown_msi_irqs(dev);
  535. list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) {
  536. if (entry->msi_attrib.type == PCI_CAP_ID_MSIX) {
  537. writel(1, entry->mask_base + entry->msi_attrib.entry_nr
  538. * PCI_MSIX_ENTRY_SIZE
  539. + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
  540. if (list_is_last(&entry->list, &dev->msi_list))
  541. iounmap(entry->mask_base);
  542. }
  543. list_del(&entry->list);
  544. kfree(entry);
  545. }
  546. return 0;
  547. }
  548. /**
  549. * pci_enable_msix - configure device's MSI-X capability structure
  550. * @dev: pointer to the pci_dev data structure of MSI-X device function
  551. * @entries: pointer to an array of MSI-X entries
  552. * @nvec: number of MSI-X irqs requested for allocation by device driver
  553. *
  554. * Setup the MSI-X capability structure of device function with the number
  555. * of requested irqs upon its software driver call to request for
  556. * MSI-X mode enabled on its hardware device function. A return of zero
  557. * indicates the successful configuration of MSI-X capability structure
  558. * with new allocated MSI-X irqs. A return of < 0 indicates a failure.
  559. * Or a return of > 0 indicates that driver request is exceeding the number
  560. * of irqs available. Driver should use the returned value to re-send
  561. * its request.
  562. **/
  563. int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
  564. {
  565. int status, pos, nr_entries;
  566. int i, j;
  567. u16 control;
  568. if (!entries)
  569. return -EINVAL;
  570. status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSIX);
  571. if (status)
  572. return status;
  573. pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
  574. pci_read_config_word(dev, msi_control_reg(pos), &control);
  575. nr_entries = multi_msix_capable(control);
  576. if (nvec > nr_entries)
  577. return -EINVAL;
  578. /* Check for any invalid entries */
  579. for (i = 0; i < nvec; i++) {
  580. if (entries[i].entry >= nr_entries)
  581. return -EINVAL; /* invalid entry */
  582. for (j = i + 1; j < nvec; j++) {
  583. if (entries[i].entry == entries[j].entry)
  584. return -EINVAL; /* duplicate entry */
  585. }
  586. }
  587. WARN_ON(!!dev->msix_enabled);
  588. /* Check whether driver already requested for MSI irq */
  589. if (dev->msi_enabled) {
  590. printk(KERN_INFO "PCI: %s: Can't enable MSI-X. "
  591. "Device already has an MSI irq assigned\n",
  592. pci_name(dev));
  593. return -EINVAL;
  594. }
  595. status = msix_capability_init(dev, entries, nvec);
  596. return status;
  597. }
  598. EXPORT_SYMBOL(pci_enable_msix);
  599. static void msix_free_all_irqs(struct pci_dev *dev)
  600. {
  601. msi_free_irqs(dev);
  602. }
  603. void pci_msix_shutdown(struct pci_dev* dev)
  604. {
  605. if (!pci_msi_enable || !dev || !dev->msix_enabled)
  606. return;
  607. msix_set_enable(dev, 0);
  608. pci_intx_for_msi(dev, 1);
  609. dev->msix_enabled = 0;
  610. }
  611. void pci_disable_msix(struct pci_dev* dev)
  612. {
  613. if (!pci_msi_enable || !dev || !dev->msix_enabled)
  614. return;
  615. pci_msix_shutdown(dev);
  616. msix_free_all_irqs(dev);
  617. }
  618. EXPORT_SYMBOL(pci_disable_msix);
  619. /**
  620. * msi_remove_pci_irq_vectors - reclaim MSI(X) irqs to unused state
  621. * @dev: pointer to the pci_dev data structure of MSI(X) device function
  622. *
  623. * Being called during hotplug remove, from which the device function
  624. * is hot-removed. All previous assigned MSI/MSI-X irqs, if
  625. * allocated for this device function, are reclaimed to unused state,
  626. * which may be used later on.
  627. **/
  628. void msi_remove_pci_irq_vectors(struct pci_dev* dev)
  629. {
  630. if (!pci_msi_enable || !dev)
  631. return;
  632. if (dev->msi_enabled)
  633. msi_free_irqs(dev);
  634. if (dev->msix_enabled)
  635. msix_free_all_irqs(dev);
  636. }
  637. void pci_no_msi(void)
  638. {
  639. pci_msi_enable = 0;
  640. }
  641. void pci_msi_init_pci_dev(struct pci_dev *dev)
  642. {
  643. INIT_LIST_HEAD(&dev->msi_list);
  644. }