LCOV - code coverage report
Current view: top level - include/linux - msi.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 1 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 0 -

          Line data    Source code
       1             : /* SPDX-License-Identifier: GPL-2.0 */
       2             : #ifndef LINUX_MSI_H
       3             : #define LINUX_MSI_H
       4             : 
       5             : /*
       6             :  * This header file contains MSI data structures and functions which are
       7             :  * only relevant for:
       8             :  *      - Interrupt core code
       9             :  *      - PCI/MSI core code
      10             :  *      - MSI interrupt domain implementations
      11             :  *      - IOMMU, low level VFIO, NTB and other justified exceptions
      12             :  *        dealing with low level MSI details.
      13             :  *
      14             :  * Regular device drivers have no business with any of these functions and
      15             :  * especially storing MSI descriptor pointers in random code is considered
      16             :  * abuse. The only function which is relevant for drivers is msi_get_virq().
      17             :  */
      18             : 
      19             : #include <linux/cpumask.h>
      20             : #include <linux/xarray.h>
      21             : #include <linux/mutex.h>
      22             : #include <linux/list.h>
      23             : #include <asm/msi.h>
      24             : 
      25             : /* Dummy shadow structures if an architecture does not define them */
      26             : #ifndef arch_msi_msg_addr_lo
      27             : typedef struct arch_msi_msg_addr_lo {
      28             :         u32     address_lo;
      29             : } __attribute__ ((packed)) arch_msi_msg_addr_lo_t;
      30             : #endif
      31             : 
      32             : #ifndef arch_msi_msg_addr_hi
      33             : typedef struct arch_msi_msg_addr_hi {
      34             :         u32     address_hi;
      35             : } __attribute__ ((packed)) arch_msi_msg_addr_hi_t;
      36             : #endif
      37             : 
      38             : #ifndef arch_msi_msg_data
      39             : typedef struct arch_msi_msg_data {
      40             :         u32     data;
      41             : } __attribute__ ((packed)) arch_msi_msg_data_t;
      42             : #endif
      43             : 
      44             : /**
      45             :  * msi_msg - Representation of a MSI message
      46             :  * @address_lo:         Low 32 bits of msi message address
      47             :  * @arch_addrlo:        Architecture specific shadow of @address_lo
      48             :  * @address_hi:         High 32 bits of msi message address
      49             :  *                      (only used when device supports it)
      50             :  * @arch_addrhi:        Architecture specific shadow of @address_hi
      51             :  * @data:               MSI message data (usually 16 bits)
      52             :  * @arch_data:          Architecture specific shadow of @data
      53             :  */
      54             : struct msi_msg {
      55             :         union {
      56             :                 u32                     address_lo;
      57             :                 arch_msi_msg_addr_lo_t  arch_addr_lo;
      58             :         };
      59             :         union {
      60             :                 u32                     address_hi;
      61             :                 arch_msi_msg_addr_hi_t  arch_addr_hi;
      62             :         };
      63             :         union {
      64             :                 u32                     data;
      65             :                 arch_msi_msg_data_t     arch_data;
      66             :         };
      67             : };
      68             : 
      69             : extern int pci_msi_ignore_mask;
      70             : /* Helper functions */
      71             : struct irq_data;
      72             : struct msi_desc;
      73             : struct pci_dev;
      74             : struct platform_msi_priv_data;
      75             : struct device_attribute;
      76             : 
      77             : void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
      78             : #ifdef CONFIG_GENERIC_MSI_IRQ
      79             : void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg);
      80             : #else
      81             : static inline void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg)
      82             : {
      83             : }
      84             : #endif
      85             : 
      86             : typedef void (*irq_write_msi_msg_t)(struct msi_desc *desc,
      87             :                                     struct msi_msg *msg);
      88             : 
      89             : /**
      90             :  * pci_msi_desc - PCI/MSI specific MSI descriptor data
      91             :  *
      92             :  * @msi_mask:   [PCI MSI]   MSI cached mask bits
      93             :  * @msix_ctrl:  [PCI MSI-X] MSI-X cached per vector control bits
      94             :  * @is_msix:    [PCI MSI/X] True if MSI-X
      95             :  * @multiple:   [PCI MSI/X] log2 num of messages allocated
      96             :  * @multi_cap:  [PCI MSI/X] log2 num of messages supported
      97             :  * @can_mask:   [PCI MSI/X] Masking supported?
      98             :  * @is_64:      [PCI MSI/X] Address size: 0=32bit 1=64bit
      99             :  * @default_irq:[PCI MSI/X] The default pre-assigned non-MSI irq
     100             :  * @mask_pos:   [PCI MSI]   Mask register position
     101             :  * @mask_base:  [PCI MSI-X] Mask register base address
     102             :  */
     103             : struct pci_msi_desc {
     104             :         union {
     105             :                 u32 msi_mask;
     106             :                 u32 msix_ctrl;
     107             :         };
     108             :         struct {
     109             :                 u8      is_msix         : 1;
     110             :                 u8      multiple        : 3;
     111             :                 u8      multi_cap       : 3;
     112             :                 u8      can_mask        : 1;
     113             :                 u8      is_64           : 1;
     114             :                 u8      is_virtual      : 1;
     115             :                 unsigned default_irq;
     116             :         } msi_attrib;
     117             :         union {
     118             :                 u8      mask_pos;
     119             :                 void __iomem *mask_base;
     120             :         };
     121             : };
     122             : 
     123             : #define MSI_MAX_INDEX           ((unsigned int)USHRT_MAX)
     124             : 
     125             : /**
     126             :  * struct msi_desc - Descriptor structure for MSI based interrupts
     127             :  * @irq:        The base interrupt number
     128             :  * @nvec_used:  The number of vectors used
     129             :  * @dev:        Pointer to the device which uses this descriptor
     130             :  * @msg:        The last set MSI message cached for reuse
     131             :  * @affinity:   Optional pointer to a cpu affinity mask for this descriptor
     132             :  * @sysfs_attr: Pointer to sysfs device attribute
     133             :  *
     134             :  * @write_msi_msg:      Callback that may be called when the MSI message
     135             :  *                      address or data changes
     136             :  * @write_msi_msg_data: Data parameter for the callback.
     137             :  *
     138             :  * @msi_index:  Index of the msi descriptor
     139             :  * @pci:        PCI specific msi descriptor data
     140             :  */
     141             : struct msi_desc {
     142             :         /* Shared device/bus type independent data */
     143             :         unsigned int                    irq;
     144             :         unsigned int                    nvec_used;
     145             :         struct device                   *dev;
     146             :         struct msi_msg                  msg;
     147             :         struct irq_affinity_desc        *affinity;
     148             : #ifdef CONFIG_IRQ_MSI_IOMMU
     149             :         const void                      *iommu_cookie;
     150             : #endif
     151             : #ifdef CONFIG_SYSFS
     152             :         struct device_attribute         *sysfs_attrs;
     153             : #endif
     154             : 
     155             :         void (*write_msi_msg)(struct msi_desc *entry, void *data);
     156             :         void *write_msi_msg_data;
     157             : 
     158             :         u16                             msi_index;
     159             :         struct pci_msi_desc             pci;
     160             : };
     161             : 
     162             : /*
     163             :  * Filter values for the MSI descriptor iterators and accessor functions.
     164             :  */
     165             : enum msi_desc_filter {
     166             :         /* All descriptors */
     167             :         MSI_DESC_ALL,
     168             :         /* Descriptors which have no interrupt associated */
     169             :         MSI_DESC_NOTASSOCIATED,
     170             :         /* Descriptors which have an interrupt associated */
     171             :         MSI_DESC_ASSOCIATED,
     172             : };
     173             : 
     174             : /**
     175             :  * msi_device_data - MSI per device data
     176             :  * @properties:         MSI properties which are interesting to drivers
     177             :  * @platform_data:      Platform-MSI specific data
     178             :  * @mutex:              Mutex protecting the MSI descriptor store
     179             :  * @__store:            Xarray for storing MSI descriptor pointers
     180             :  * @__iter_idx:         Index to search the next entry for iterators
     181             :  */
     182             : struct msi_device_data {
     183             :         unsigned long                   properties;
     184             :         struct platform_msi_priv_data   *platform_data;
     185             :         struct mutex                    mutex;
     186             :         struct xarray                   __store;
     187             :         unsigned long                   __iter_idx;
     188             : };
     189             : 
     190             : int msi_setup_device_data(struct device *dev);
     191             : 
     192             : unsigned int msi_get_virq(struct device *dev, unsigned int index);
     193             : void msi_lock_descs(struct device *dev);
     194             : void msi_unlock_descs(struct device *dev);
     195             : 
     196             : struct msi_desc *msi_first_desc(struct device *dev, enum msi_desc_filter filter);
     197             : struct msi_desc *msi_next_desc(struct device *dev, enum msi_desc_filter filter);
     198             : 
     199             : /**
     200             :  * msi_for_each_desc - Iterate the MSI descriptors
     201             :  *
     202             :  * @desc:       struct msi_desc pointer used as iterator
     203             :  * @dev:        struct device pointer - device to iterate
     204             :  * @filter:     Filter for descriptor selection
     205             :  *
     206             :  * Notes:
     207             :  *  - The loop must be protected with a msi_lock_descs()/msi_unlock_descs()
     208             :  *    pair.
     209             :  *  - It is safe to remove a retrieved MSI descriptor in the loop.
     210             :  */
     211             : #define msi_for_each_desc(desc, dev, filter)                    \
     212             :         for ((desc) = msi_first_desc((dev), (filter)); (desc);  \
     213             :              (desc) = msi_next_desc((dev), (filter)))
     214             : 
     215             : #define msi_desc_to_dev(desc)           ((desc)->dev)
     216             : 
     217             : #ifdef CONFIG_IRQ_MSI_IOMMU
     218             : static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc)
     219             : {
     220             :         return desc->iommu_cookie;
     221             : }
     222             : 
     223             : static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc,
     224             :                                              const void *iommu_cookie)
     225             : {
     226             :         desc->iommu_cookie = iommu_cookie;
     227             : }
     228             : #else
     229             : static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc)
     230             : {
     231             :         return NULL;
     232             : }
     233             : 
     234             : static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc,
     235             :                                              const void *iommu_cookie)
     236             : {
     237             : }
     238             : #endif
     239             : 
     240             : #ifdef CONFIG_PCI_MSI
     241             : struct pci_dev *msi_desc_to_pci_dev(struct msi_desc *desc);
     242             : void pci_write_msi_msg(unsigned int irq, struct msi_msg *msg);
     243             : #else /* CONFIG_PCI_MSI */
     244             : static inline void pci_write_msi_msg(unsigned int irq, struct msi_msg *msg)
     245             : {
     246             : }
     247             : #endif /* CONFIG_PCI_MSI */
     248             : 
     249             : int msi_add_msi_desc(struct device *dev, struct msi_desc *init_desc);
     250             : void msi_free_msi_descs_range(struct device *dev, enum msi_desc_filter filter,
     251             :                               unsigned int first_index, unsigned int last_index);
     252             : 
     253             : /**
     254             :  * msi_free_msi_descs - Free MSI descriptors of a device
     255             :  * @dev:        Device to free the descriptors
     256             :  */
     257             : static inline void msi_free_msi_descs(struct device *dev)
     258             : {
     259           0 :         msi_free_msi_descs_range(dev, MSI_DESC_ALL, 0, MSI_MAX_INDEX);
     260             : }
     261             : 
     262             : void __pci_read_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
     263             : void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
     264             : 
     265             : void pci_msi_mask_irq(struct irq_data *data);
     266             : void pci_msi_unmask_irq(struct irq_data *data);
     267             : 
     268             : /*
     269             :  * The arch hooks to setup up msi irqs. Default functions are implemented
     270             :  * as weak symbols so that they /can/ be overriden by architecture specific
     271             :  * code if needed. These hooks can only be enabled by the architecture.
     272             :  *
     273             :  * If CONFIG_PCI_MSI_ARCH_FALLBACKS is not selected they are replaced by
     274             :  * stubs with warnings.
     275             :  */
     276             : #ifdef CONFIG_PCI_MSI_ARCH_FALLBACKS
     277             : int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
     278             : void arch_teardown_msi_irq(unsigned int irq);
     279             : int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
     280             : void arch_teardown_msi_irqs(struct pci_dev *dev);
     281             : #ifdef CONFIG_SYSFS
     282             : int msi_device_populate_sysfs(struct device *dev);
     283             : void msi_device_destroy_sysfs(struct device *dev);
     284             : #else /* CONFIG_SYSFS */
     285             : static inline int msi_device_populate_sysfs(struct device *dev) { return 0; }
     286             : static inline void msi_device_destroy_sysfs(struct device *dev) { }
     287             : #endif /* !CONFIG_SYSFS */
     288             : #endif /* CONFIG_PCI_MSI_ARCH_FALLBACKS */
     289             : 
     290             : /*
     291             :  * The restore hook is still available even for fully irq domain based
     292             :  * setups. Courtesy to XEN/X86.
     293             :  */
     294             : bool arch_restore_msi_irqs(struct pci_dev *dev);
     295             : 
     296             : #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
     297             : 
     298             : #include <linux/irqhandler.h>
     299             : 
     300             : struct irq_domain;
     301             : struct irq_domain_ops;
     302             : struct irq_chip;
     303             : struct device_node;
     304             : struct fwnode_handle;
     305             : struct msi_domain_info;
     306             : 
     307             : /**
     308             :  * struct msi_domain_ops - MSI interrupt domain callbacks
     309             :  * @get_hwirq:          Retrieve the resulting hw irq number
     310             :  * @msi_init:           Domain specific init function for MSI interrupts
     311             :  * @msi_free:           Domain specific function to free a MSI interrupts
     312             :  * @msi_check:          Callback for verification of the domain/info/dev data
     313             :  * @msi_prepare:        Prepare the allocation of the interrupts in the domain
     314             :  * @set_desc:           Set the msi descriptor for an interrupt
     315             :  * @domain_alloc_irqs:  Optional function to override the default allocation
     316             :  *                      function.
     317             :  * @domain_free_irqs:   Optional function to override the default free
     318             :  *                      function.
     319             :  *
     320             :  * @get_hwirq, @msi_init and @msi_free are callbacks used by the underlying
     321             :  * irqdomain.
     322             :  *
     323             :  * @msi_check, @msi_prepare and @set_desc are callbacks used by
     324             :  * msi_domain_alloc/free_irqs().
     325             :  *
     326             :  * @domain_alloc_irqs, @domain_free_irqs can be used to override the
     327             :  * default allocation/free functions (__msi_domain_alloc/free_irqs). This
     328             :  * is initially for a wrapper around XENs seperate MSI universe which can't
     329             :  * be wrapped into the regular irq domains concepts by mere mortals.  This
     330             :  * allows to universally use msi_domain_alloc/free_irqs without having to
     331             :  * special case XEN all over the place.
     332             :  *
     333             :  * Contrary to other operations @domain_alloc_irqs and @domain_free_irqs
     334             :  * are set to the default implementation if NULL and even when
     335             :  * MSI_FLAG_USE_DEF_DOM_OPS is not set to avoid breaking existing users and
     336             :  * because these callbacks are obviously mandatory.
     337             :  *
     338             :  * This is NOT meant to be abused, but it can be useful to build wrappers
     339             :  * for specialized MSI irq domains which need extra work before and after
     340             :  * calling __msi_domain_alloc_irqs()/__msi_domain_free_irqs().
     341             :  */
     342             : struct msi_domain_ops {
     343             :         irq_hw_number_t (*get_hwirq)(struct msi_domain_info *info,
     344             :                                      msi_alloc_info_t *arg);
     345             :         int             (*msi_init)(struct irq_domain *domain,
     346             :                                     struct msi_domain_info *info,
     347             :                                     unsigned int virq, irq_hw_number_t hwirq,
     348             :                                     msi_alloc_info_t *arg);
     349             :         void            (*msi_free)(struct irq_domain *domain,
     350             :                                     struct msi_domain_info *info,
     351             :                                     unsigned int virq);
     352             :         int             (*msi_check)(struct irq_domain *domain,
     353             :                                      struct msi_domain_info *info,
     354             :                                      struct device *dev);
     355             :         int             (*msi_prepare)(struct irq_domain *domain,
     356             :                                        struct device *dev, int nvec,
     357             :                                        msi_alloc_info_t *arg);
     358             :         void            (*set_desc)(msi_alloc_info_t *arg,
     359             :                                     struct msi_desc *desc);
     360             :         int             (*domain_alloc_irqs)(struct irq_domain *domain,
     361             :                                              struct device *dev, int nvec);
     362             :         void            (*domain_free_irqs)(struct irq_domain *domain,
     363             :                                             struct device *dev);
     364             : };
     365             : 
     366             : /**
     367             :  * struct msi_domain_info - MSI interrupt domain data
     368             :  * @flags:              Flags to decribe features and capabilities
     369             :  * @ops:                The callback data structure
     370             :  * @chip:               Optional: associated interrupt chip
     371             :  * @chip_data:          Optional: associated interrupt chip data
     372             :  * @handler:            Optional: associated interrupt flow handler
     373             :  * @handler_data:       Optional: associated interrupt flow handler data
     374             :  * @handler_name:       Optional: associated interrupt flow handler name
     375             :  * @data:               Optional: domain specific data
     376             :  */
     377             : struct msi_domain_info {
     378             :         u32                     flags;
     379             :         struct msi_domain_ops   *ops;
     380             :         struct irq_chip         *chip;
     381             :         void                    *chip_data;
     382             :         irq_flow_handler_t      handler;
     383             :         void                    *handler_data;
     384             :         const char              *handler_name;
     385             :         void                    *data;
     386             : };
     387             : 
     388             : /* Flags for msi_domain_info */
     389             : enum {
     390             :         /*
     391             :          * Init non implemented ops callbacks with default MSI domain
     392             :          * callbacks.
     393             :          */
     394             :         MSI_FLAG_USE_DEF_DOM_OPS        = (1 << 0),
     395             :         /*
     396             :          * Init non implemented chip callbacks with default MSI chip
     397             :          * callbacks.
     398             :          */
     399             :         MSI_FLAG_USE_DEF_CHIP_OPS       = (1 << 1),
     400             :         /* Support multiple PCI MSI interrupts */
     401             :         MSI_FLAG_MULTI_PCI_MSI          = (1 << 2),
     402             :         /* Support PCI MSIX interrupts */
     403             :         MSI_FLAG_PCI_MSIX               = (1 << 3),
     404             :         /* Needs early activate, required for PCI */
     405             :         MSI_FLAG_ACTIVATE_EARLY         = (1 << 4),
     406             :         /*
     407             :          * Must reactivate when irq is started even when
     408             :          * MSI_FLAG_ACTIVATE_EARLY has been set.
     409             :          */
     410             :         MSI_FLAG_MUST_REACTIVATE        = (1 << 5),
     411             :         /* Is level-triggered capable, using two messages */
     412             :         MSI_FLAG_LEVEL_CAPABLE          = (1 << 6),
     413             :         /* Populate sysfs on alloc() and destroy it on free() */
     414             :         MSI_FLAG_DEV_SYSFS              = (1 << 7),
     415             :         /* MSI-X entries must be contiguous */
     416             :         MSI_FLAG_MSIX_CONTIGUOUS        = (1 << 8),
     417             :         /* Allocate simple MSI descriptors */
     418             :         MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS = (1 << 9),
     419             :         /* Free MSI descriptors */
     420             :         MSI_FLAG_FREE_MSI_DESCS         = (1 << 10),
     421             : };
     422             : 
     423             : int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask,
     424             :                             bool force);
     425             : 
     426             : struct irq_domain *msi_create_irq_domain(struct fwnode_handle *fwnode,
     427             :                                          struct msi_domain_info *info,
     428             :                                          struct irq_domain *parent);
     429             : int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
     430             :                             int nvec);
     431             : int msi_domain_alloc_irqs_descs_locked(struct irq_domain *domain, struct device *dev,
     432             :                                        int nvec);
     433             : int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
     434             :                           int nvec);
     435             : void __msi_domain_free_irqs(struct irq_domain *domain, struct device *dev);
     436             : void msi_domain_free_irqs_descs_locked(struct irq_domain *domain, struct device *dev);
     437             : void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev);
     438             : struct msi_domain_info *msi_get_domain_info(struct irq_domain *domain);
     439             : 
     440             : struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode,
     441             :                                                   struct msi_domain_info *info,
     442             :                                                   struct irq_domain *parent);
     443             : int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
     444             :                                    irq_write_msi_msg_t write_msi_msg);
     445             : void platform_msi_domain_free_irqs(struct device *dev);
     446             : 
     447             : /* When an MSI domain is used as an intermediate domain */
     448             : int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,
     449             :                             int nvec, msi_alloc_info_t *args);
     450             : int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev,
     451             :                              int virq, int nvec, msi_alloc_info_t *args);
     452             : struct irq_domain *
     453             : __platform_msi_create_device_domain(struct device *dev,
     454             :                                     unsigned int nvec,
     455             :                                     bool is_tree,
     456             :                                     irq_write_msi_msg_t write_msi_msg,
     457             :                                     const struct irq_domain_ops *ops,
     458             :                                     void *host_data);
     459             : 
     460             : #define platform_msi_create_device_domain(dev, nvec, write, ops, data)  \
     461             :         __platform_msi_create_device_domain(dev, nvec, false, write, ops, data)
     462             : #define platform_msi_create_device_tree_domain(dev, nvec, write, ops, data) \
     463             :         __platform_msi_create_device_domain(dev, nvec, true, write, ops, data)
     464             : 
     465             : int platform_msi_device_domain_alloc(struct irq_domain *domain, unsigned int virq,
     466             :                                      unsigned int nr_irqs);
     467             : void platform_msi_device_domain_free(struct irq_domain *domain, unsigned int virq,
     468             :                                      unsigned int nvec);
     469             : void *platform_msi_get_host_data(struct irq_domain *domain);
     470             : #endif /* CONFIG_GENERIC_MSI_IRQ_DOMAIN */
     471             : 
     472             : #ifdef CONFIG_PCI_MSI_IRQ_DOMAIN
     473             : struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode,
     474             :                                              struct msi_domain_info *info,
     475             :                                              struct irq_domain *parent);
     476             : u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev);
     477             : struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev);
     478             : bool pci_dev_has_special_msi_domain(struct pci_dev *pdev);
     479             : #else
     480             : static inline struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev)
     481             : {
     482             :         return NULL;
     483             : }
     484             : #endif /* CONFIG_PCI_MSI_IRQ_DOMAIN */
     485             : 
     486             : #endif /* LINUX_MSI_H */

Generated by: LCOV version 1.14