diff --git a/UPDATING b/UPDATING --- a/UPDATING +++ b/UPDATING @@ -27,6 +27,10 @@ world, or to merely disable the most expensive debugging functionality at runtime, run "ln -s 'abort:false,junk:false' /etc/malloc.conf".) +20230113: + LinuxKPI pci.h changes may require out-of-tree drivers to be recompiled. + Bump _FreeBSD_version to 1400078 to be able to detect this change. + 20221212: llvm-objump is now always installed as objdump. Previously there was no /usr/bin/objdump unless the WITH_LLVM_BINUTILS knob was used. diff --git a/sys/compat/linuxkpi/common/include/linux/interrupt.h b/sys/compat/linuxkpi/common/include/linux/interrupt.h --- a/sys/compat/linuxkpi/common/include/linux/interrupt.h +++ b/sys/compat/linuxkpi/common/include/linux/interrupt.h @@ -131,6 +131,13 @@ return (-error); } +static inline struct msi_desc * +irq_get_msi_desc(unsigned int irq) +{ + + return (lkpi_pci_msi_desc_alloc(irq)); +} + /* * LinuxKPI tasklet support */ diff --git a/sys/compat/linuxkpi/common/include/linux/pci.h b/sys/compat/linuxkpi/common/include/linux/pci.h --- a/sys/compat/linuxkpi/common/include/linux/pci.h +++ b/sys/compat/linuxkpi/common/include/linux/pci.h @@ -285,6 +285,17 @@ module_init(_pci_init); \ module_exit(_pci_exit) +struct msi_msg { + uint32_t data; +}; + +struct msi_desc { + struct msi_msg msg; + struct { + bool is_64; + } msi_attrib; +}; + /* * If we find drivers accessing this from multiple KPIs we may have to * refcount objects of this structure. @@ -311,12 +322,18 @@ unsigned int devfn; uint32_t class; uint8_t revision; + uint8_t msi_cap; bool managed; /* devres "pcim_*(). */ bool want_iomap_res; bool msi_enabled; bool msix_enabled; phys_addr_t rom; size_t romlen; + /* + * msi_desc should be an array one day? For as long as we only support + * 1 MSI vector this is fine. + */ + struct msi_desc *msi_desc; TAILQ_HEAD(, pci_mmio_region) mmio; }; @@ -345,6 +362,7 @@ struct pcim_iomap_devres *lkpi_pcim_iomap_devres_find(struct pci_dev *pdev); void lkpi_pcim_iomap_table_release(struct device *, void *); struct pci_dev *lkpi_pci_get_device(uint16_t, uint16_t, struct pci_dev *); +struct msi_desc *lkpi_pci_msi_desc_alloc(int); static inline bool dev_is_pci(struct device *dev) diff --git a/sys/compat/linuxkpi/common/src/linux_pci.c b/sys/compat/linuxkpi/common/src/linux_pci.c --- a/sys/compat/linuxkpi/common/src/linux_pci.c +++ b/sys/compat/linuxkpi/common/src/linux_pci.c @@ -339,6 +339,8 @@ if (pdev->bus->self != pdev) pci_dev_put(pdev->bus->self); free(pdev->bus, M_DEVBUF); + if (pdev->msi_desc != NULL) + free(pdev->msi_desc, M_DEVBUF); free(pdev, M_DEVBUF); } @@ -965,6 +967,35 @@ return (-EINVAL); } +struct msi_desc * +lkpi_pci_msi_desc_alloc(int irq) +{ + struct device *dev; + struct pci_dev *pdev; + struct msi_desc *desc; + struct pci_devinfo *dinfo; + struct pcicfg_msi *msi; + + dev = linux_pci_find_irq_dev(irq); + if (dev == NULL) + return (NULL); + + pdev = to_pci_dev(dev); + if (pdev->msi_desc != NULL) + return (pdev->msi_desc); + + dinfo = device_get_ivars(dev->bsddev); + msi = &dinfo->cfg.msi; + + desc = malloc(sizeof(*desc), M_DEVBUF, M_WAITOK | M_ZERO); + + desc->msi_attrib.is_64 = + (msi->msi_ctrl & PCIM_MSICTRL_64BIT) ? true : false; + desc->msg.data = msi->msi_data; + + return (desc); +} + CTASSERT(sizeof(dma_addr_t) <= sizeof(uint64_t)); struct linux_dma_obj { diff --git a/sys/sys/param.h b/sys/sys/param.h --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -76,7 +76,7 @@ * cannot include sys/param.h and should only be updated here. */ #undef __FreeBSD_version -#define __FreeBSD_version 1400077 +#define __FreeBSD_version 1400078 /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,