<p>Philipp Deppenwiese <strong>merged</strong> this change.</p><p><a href="https://review.coreboot.org/26329">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  build bot (Jenkins): Verified
  Philipp Deppenwiese: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">device/pci: Add MSI-X helper functions<br><br>Basic PCI MSI-X table helper functions.<br>Imported from GNU/Linux kernel PCI subsystem.<br><br>To be used on Cavium to configure MSI-X tables.<br><br>Change-Id: I94413712e7986efd17e6b11ba59f6eb390384c8c<br>Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com><br>Reviewed-on: https://review.coreboot.org/26329<br>Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com><br>Tested-by: build bot (Jenkins) <no-reply@coreboot.org><br>---<br>M src/device/pci_device.c<br>M src/include/device/pci.h<br>M src/include/device/pci_def.h<br>3 files changed, 98 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/device/pci_device.c b/src/device/pci_device.c</span><br><span>index c18f529..5938389 100644</span><br><span>--- a/src/device/pci_device.c</span><br><span>+++ b/src/device/pci_device.c</span><br><span>@@ -338,6 +338,74 @@</span><br><span> }</span><br><span> </span><br><span> /**</span><br><span style="color: hsl(120, 100%, 40%);">+ * Given a device, read the size of the MSI-X table.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param dev Pointer to the device structure.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return MSI-X table size or 0 if not MSI-X capable device</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+size_t pci_msix_table_size(struct device *dev)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    const size_t pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!pos)</span><br><span style="color: hsl(120, 100%, 40%);">+             return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   const u16 control = pci_read_config16(dev, pos + PCI_MSIX_FLAGS);</span><br><span style="color: hsl(120, 100%, 40%);">+     return (control & PCI_MSIX_FLAGS_QSIZE) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * Given a device, return the table offset and bar the MSI-X tables resides in.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param dev Pointer to the device structure.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param offset Returned value gives the offset in bytes inside the PCI BAR.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param idx The returned value is the index of the PCI_BASE_ADDRESS register</span><br><span style="color: hsl(120, 100%, 40%);">+ *            the MSI-X table is located in.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return Zero on success</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int pci_msix_table_bar(struct device *dev, u32 *offset, u8 *idx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    const size_t pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!pos || !offset || !idx)</span><br><span style="color: hsl(120, 100%, 40%);">+          return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   *offset = pci_read_config32(dev, pos + PCI_MSIX_TABLE);</span><br><span style="color: hsl(120, 100%, 40%);">+       *idx = (u8)(*offset & PCI_MSIX_PBA_BIR);</span><br><span style="color: hsl(120, 100%, 40%);">+  *offset &= PCI_MSIX_PBA_OFFSET;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * Given a device, return a msix_entry pointer or NULL if no table was found.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param dev Pointer to the device structure.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return NULL on error</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct msix_entry *pci_msix_get_table(struct device *dev)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct resource *res;</span><br><span style="color: hsl(120, 100%, 40%);">+ u32 offset;</span><br><span style="color: hsl(120, 100%, 40%);">+   u8 idx;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (pci_msix_table_bar(dev, &offset, &idx))</span><br><span style="color: hsl(120, 100%, 40%);">+           return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (idx > 5)</span><br><span style="color: hsl(120, 100%, 40%);">+               return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        res = probe_resource(dev, idx * 4 + PCI_BASE_ADDRESS_0);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!res || !res->base || offset >= res->size)</span><br><span style="color: hsl(120, 100%, 40%);">+               return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if ((res->flags & IORESOURCE_PCI64) &&</span><br><span style="color: hsl(120, 100%, 40%);">+     (uintptr_t)res->base != res->base)</span><br><span style="color: hsl(120, 100%, 40%);">+          return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        return (struct msix_entry *)((uintptr_t)res->base + offset);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span>  * Read the base address registers for a given device.</span><br><span>  *</span><br><span>  * @param dev Pointer to the dev structure.</span><br><span>diff --git a/src/include/device/pci.h b/src/include/device/pci.h</span><br><span>index 3cc2c64..f1ab91b 100644</span><br><span>--- a/src/include/device/pci.h</span><br><span>+++ b/src/include/device/pci.h</span><br><span>@@ -56,6 +56,20 @@</span><br><span>   const unsigned short *devices;</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct msix_entry {</span><br><span style="color: hsl(120, 100%, 40%);">+ union {</span><br><span style="color: hsl(120, 100%, 40%);">+               struct {</span><br><span style="color: hsl(120, 100%, 40%);">+                      u32 lower_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+                       u32 upper_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+               };</span><br><span style="color: hsl(120, 100%, 40%);">+            struct {</span><br><span style="color: hsl(120, 100%, 40%);">+                      u64 addr;</span><br><span style="color: hsl(120, 100%, 40%);">+             };</span><br><span style="color: hsl(120, 100%, 40%);">+    };</span><br><span style="color: hsl(120, 100%, 40%);">+    u32 data;</span><br><span style="color: hsl(120, 100%, 40%);">+     u32 vec_control;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #ifdef __SIMPLE_DEVICE__</span><br><span> #define __pci_driver __attribute__((unused))</span><br><span> #else</span><br><span>@@ -104,6 +118,10 @@</span><br><span> const char *get_pci_class_name(struct device *dev);</span><br><span> const char *get_pci_subclass_name(struct device *dev);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+size_t pci_msix_table_size(struct device *dev);</span><br><span style="color: hsl(120, 100%, 40%);">+int pci_msix_table_bar(struct device *dev, u32 *offset, u8 *idx);</span><br><span style="color: hsl(120, 100%, 40%);">+struct msix_entry *pci_msix_get_table(struct device *dev);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #define PCI_IO_BRIDGE_ALIGN 4096</span><br><span> #define PCI_MEM_BRIDGE_ALIGN (1024*1024)</span><br><span> </span><br><span>diff --git a/src/include/device/pci_def.h b/src/include/device/pci_def.h</span><br><span>index 60d9132..f9ce1a6 100644</span><br><span>--- a/src/include/device/pci_def.h</span><br><span>+++ b/src/include/device/pci_def.h</span><br><span>@@ -292,6 +292,18 @@</span><br><span> #define PCI_MSI_DATA_64            12      /* 16 bits of data for 64-bit devices */</span><br><span> #define PCI_MSI_MASK_BIT    16      /* Mask bits register */</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* MSI-X registers */</span><br><span style="color: hsl(120, 100%, 40%);">+#define PCI_MSIX_FLAGS             2</span><br><span style="color: hsl(120, 100%, 40%);">+#define  PCI_MSIX_FLAGS_QSIZE        0x7FF   /* table size */</span><br><span style="color: hsl(120, 100%, 40%);">+#define  PCI_MSIX_FLAGS_MASKALL       0x4000  /* Mask all vectors for this function */</span><br><span style="color: hsl(120, 100%, 40%);">+#define  PCI_MSIX_FLAGS_ENABLE        0x8000  /* MSI-X enable */</span><br><span style="color: hsl(120, 100%, 40%);">+#define PCI_MSIX_TABLE              4       /* Table offset */</span><br><span style="color: hsl(120, 100%, 40%);">+#define PCI_MSIX_PBA                8       /* Pending Bit Array offset */</span><br><span style="color: hsl(120, 100%, 40%);">+#define  PCI_MSIX_PBA_BIR       0x7     /* BAR index */</span><br><span style="color: hsl(120, 100%, 40%);">+#define  PCI_MSIX_PBA_OFFSET   ~0x7    /* Offset into specified BAR */</span><br><span style="color: hsl(120, 100%, 40%);">+#define PCI_CAP_MSIX_SIZEOF    12      /* size of MSIX registers */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* CompactPCI Hotswap Register */</span><br><span> </span><br><span> #define PCI_CHSWP_CSR              2       /* Control and Status Register */</span><br><span></span><br></pre><p>To view, visit <a href="https://review.coreboot.org/26329">change 26329</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/26329"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I94413712e7986efd17e6b11ba59f6eb390384c8c </div>
<div style="display:none"> Gerrit-Change-Number: 26329 </div>
<div style="display:none"> Gerrit-PatchSet: 17 </div>
<div style="display:none"> Gerrit-Owner: Patrick Rudolph <patrick.rudolph@9elements.com> </div>
<div style="display:none"> Gerrit-Reviewer: Aaron Durbin <adurbin@chromium.org> </div>
<div style="display:none"> Gerrit-Reviewer: Julius Werner <jwerner@chromium.org> </div>
<div style="display:none"> Gerrit-Reviewer: Patrick Rudolph <patrick.rudolph@9elements.com> </div>
<div style="display:none"> Gerrit-Reviewer: Paul Menzel <paulepanter@users.sourceforge.net> </div>
<div style="display:none"> Gerrit-Reviewer: Philipp Deppenwiese <zaolin.daisuki@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: build bot (Jenkins) <no-reply@coreboot.org> </div>
<div style="display:none"> Gerrit-CC: Nico Huber <nico.h@gmx.de> </div>