slot.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /*
  2. * PCI Backend - Provides a Virtual PCI bus (with real devices)
  3. * to the frontend
  4. *
  5. * Author: Ryan Wilson <hap9@epoch.ncsc.mil> (vpci.c)
  6. * Author: Tristan Gingold <tristan.gingold@bull.net>, from vpci.c
  7. */
  8. #include <linux/list.h>
  9. #include <linux/slab.h>
  10. #include <linux/pci.h>
  11. #include <linux/spinlock.h>
  12. #include "pciback.h"
  13. /* There are at most 32 slots in a pci bus. */
  14. #define PCI_SLOT_MAX 32
  15. #define PCI_BUS_NBR 2
  16. struct slot_dev_data {
  17. /* Access to dev_list must be protected by lock */
  18. struct pci_dev *slots[PCI_BUS_NBR][PCI_SLOT_MAX];
  19. spinlock_t lock;
  20. };
  21. struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
  22. unsigned int domain, unsigned int bus,
  23. unsigned int devfn)
  24. {
  25. struct pci_dev *dev = NULL;
  26. struct slot_dev_data *slot_dev = pdev->pci_dev_data;
  27. unsigned long flags;
  28. if (domain != 0 || PCI_FUNC(devfn) != 0)
  29. return NULL;
  30. if (PCI_SLOT(devfn) >= PCI_SLOT_MAX || bus >= PCI_BUS_NBR)
  31. return NULL;
  32. spin_lock_irqsave(&slot_dev->lock, flags);
  33. dev = slot_dev->slots[bus][PCI_SLOT(devfn)];
  34. spin_unlock_irqrestore(&slot_dev->lock, flags);
  35. return dev;
  36. }
  37. int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev,
  38. int devid, publish_pci_dev_cb publish_cb)
  39. {
  40. int err = 0, slot, bus;
  41. struct slot_dev_data *slot_dev = pdev->pci_dev_data;
  42. unsigned long flags;
  43. if ((dev->class >> 24) == PCI_BASE_CLASS_BRIDGE) {
  44. err = -EFAULT;
  45. xenbus_dev_fatal(pdev->xdev, err,
  46. "Can't export bridges on the virtual PCI bus");
  47. goto out;
  48. }
  49. spin_lock_irqsave(&slot_dev->lock, flags);
  50. /* Assign to a new slot on the virtual PCI bus */
  51. for (bus = 0; bus < PCI_BUS_NBR; bus++)
  52. for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
  53. if (slot_dev->slots[bus][slot] == NULL) {
  54. printk(KERN_INFO
  55. "pciback: slot: %s: assign to virtual "
  56. "slot %d, bus %d\n",
  57. pci_name(dev), slot, bus);
  58. slot_dev->slots[bus][slot] = dev;
  59. goto unlock;
  60. }
  61. }
  62. err = -ENOMEM;
  63. xenbus_dev_fatal(pdev->xdev, err,
  64. "No more space on root virtual PCI bus");
  65. unlock:
  66. spin_unlock_irqrestore(&slot_dev->lock, flags);
  67. /* Publish this device. */
  68. if (!err)
  69. err = publish_cb(pdev, 0, 0, PCI_DEVFN(slot, 0), devid);
  70. out:
  71. return err;
  72. }
  73. void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
  74. {
  75. int slot, bus;
  76. struct slot_dev_data *slot_dev = pdev->pci_dev_data;
  77. struct pci_dev *found_dev = NULL;
  78. unsigned long flags;
  79. spin_lock_irqsave(&slot_dev->lock, flags);
  80. for (bus = 0; bus < PCI_BUS_NBR; bus++)
  81. for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
  82. if (slot_dev->slots[bus][slot] == dev) {
  83. slot_dev->slots[bus][slot] = NULL;
  84. found_dev = dev;
  85. goto out;
  86. }
  87. }
  88. out:
  89. spin_unlock_irqrestore(&slot_dev->lock, flags);
  90. if (found_dev)
  91. pcistub_put_pci_dev(found_dev);
  92. }
  93. int pciback_init_devices(struct pciback_device *pdev)
  94. {
  95. int slot, bus;
  96. struct slot_dev_data *slot_dev;
  97. slot_dev = kmalloc(sizeof(*slot_dev), GFP_KERNEL);
  98. if (!slot_dev)
  99. return -ENOMEM;
  100. spin_lock_init(&slot_dev->lock);
  101. for (bus = 0; bus < PCI_BUS_NBR; bus++)
  102. for (slot = 0; slot < PCI_SLOT_MAX; slot++)
  103. slot_dev->slots[bus][slot] = NULL;
  104. pdev->pci_dev_data = slot_dev;
  105. return 0;
  106. }
  107. int pciback_publish_pci_roots(struct pciback_device *pdev,
  108. publish_pci_root_cb publish_cb)
  109. {
  110. /* The Virtual PCI bus has only one root */
  111. return publish_cb(pdev, 0, 0);
  112. }
  113. void pciback_release_devices(struct pciback_device *pdev)
  114. {
  115. int slot, bus;
  116. struct slot_dev_data *slot_dev = pdev->pci_dev_data;
  117. struct pci_dev *dev;
  118. for (bus = 0; bus < PCI_BUS_NBR; bus++)
  119. for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
  120. dev = slot_dev->slots[bus][slot];
  121. if (dev != NULL)
  122. pcistub_put_pci_dev(dev);
  123. }
  124. kfree(slot_dev);
  125. pdev->pci_dev_data = NULL;
  126. }
  127. int pciback_get_pcifront_dev(struct pci_dev *pcidev,
  128. struct pciback_device *pdev,
  129. unsigned int *domain, unsigned int *bus,
  130. unsigned int *devfn)
  131. {
  132. int slot, busnr;
  133. struct slot_dev_data *slot_dev = pdev->pci_dev_data;
  134. struct pci_dev *dev;
  135. int found = 0;
  136. unsigned long flags;
  137. spin_lock_irqsave(&slot_dev->lock, flags);
  138. for (busnr = 0; busnr < PCI_BUS_NBR; bus++)
  139. for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
  140. dev = slot_dev->slots[busnr][slot];
  141. if (dev && dev->bus->number == pcidev->bus->number
  142. && dev->devfn == pcidev->devfn
  143. && pci_domain_nr(dev->bus) ==
  144. pci_domain_nr(pcidev->bus)) {
  145. found = 1;
  146. *domain = 0;
  147. *bus = busnr;
  148. *devfn = PCI_DEVFN(slot, 0);
  149. goto out;
  150. }
  151. }
  152. out:
  153. spin_unlock_irqrestore(&slot_dev->lock, flags);
  154. return found;
  155. }