LCOV - code coverage report
Current view: top level - include/linux - msi.h (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 4 0.0 %
Date: 2022-04-01 13:59:58 Functions: 0 0 -
Branches: 0 4 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: GPL-2.0 */
       2                 :            : #ifndef LINUX_MSI_H
       3                 :            : #define LINUX_MSI_H
       4                 :            : 
       5                 :            : #include <linux/kobject.h>
       6                 :            : #include <linux/list.h>
       7                 :            : 
       8                 :            : struct msi_msg {
       9                 :            :         u32     address_lo;     /* low 32 bits of msi message address */
      10                 :            :         u32     address_hi;     /* high 32 bits of msi message address */
      11                 :            :         u32     data;           /* 16 bits of msi message data */
      12                 :            : };
      13                 :            : 
      14                 :            : extern int pci_msi_ignore_mask;
      15                 :            : /* Helper functions */
      16                 :            : struct irq_data;
      17                 :            : struct msi_desc;
      18                 :            : struct pci_dev;
      19                 :            : struct platform_msi_priv_data;
      20                 :            : void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
      21                 :            : #ifdef CONFIG_GENERIC_MSI_IRQ
      22                 :            : void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg);
      23                 :            : #else
      24                 :            : static inline void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg)
      25                 :            : {
      26                 :            : }
      27                 :            : #endif
      28                 :            : 
      29                 :            : typedef void (*irq_write_msi_msg_t)(struct msi_desc *desc,
      30                 :            :                                     struct msi_msg *msg);
      31                 :            : 
      32                 :            : /**
      33                 :            :  * platform_msi_desc - Platform device specific msi descriptor data
      34                 :            :  * @msi_priv_data:      Pointer to platform private data
      35                 :            :  * @msi_index:          The index of the MSI descriptor for multi MSI
      36                 :            :  */
      37                 :            : struct platform_msi_desc {
      38                 :            :         struct platform_msi_priv_data   *msi_priv_data;
      39                 :            :         u16                             msi_index;
      40                 :            : };
      41                 :            : 
      42                 :            : /**
      43                 :            :  * fsl_mc_msi_desc - FSL-MC device specific msi descriptor data
      44                 :            :  * @msi_index:          The index of the MSI descriptor
      45                 :            :  */
      46                 :            : struct fsl_mc_msi_desc {
      47                 :            :         u16                             msi_index;
      48                 :            : };
      49                 :            : 
      50                 :            : /**
      51                 :            :  * ti_sci_inta_msi_desc - TISCI based INTA specific msi descriptor data
      52                 :            :  * @dev_index: TISCI device index
      53                 :            :  */
      54                 :            : struct ti_sci_inta_msi_desc {
      55                 :            :         u16     dev_index;
      56                 :            : };
      57                 :            : 
      58                 :            : /**
      59                 :            :  * struct msi_desc - Descriptor structure for MSI based interrupts
      60                 :            :  * @list:       List head for management
      61                 :            :  * @irq:        The base interrupt number
      62                 :            :  * @nvec_used:  The number of vectors used
      63                 :            :  * @dev:        Pointer to the device which uses this descriptor
      64                 :            :  * @msg:        The last set MSI message cached for reuse
      65                 :            :  * @affinity:   Optional pointer to a cpu affinity mask for this descriptor
      66                 :            :  *
      67                 :            :  * @write_msi_msg:      Callback that may be called when the MSI message
      68                 :            :  *                      address or data changes
      69                 :            :  * @write_msi_msg_data: Data parameter for the callback.
      70                 :            :  *
      71                 :            :  * @masked:     [PCI MSI/X] Mask bits
      72                 :            :  * @is_msix:    [PCI MSI/X] True if MSI-X
      73                 :            :  * @multiple:   [PCI MSI/X] log2 num of messages allocated
      74                 :            :  * @multi_cap:  [PCI MSI/X] log2 num of messages supported
      75                 :            :  * @maskbit:    [PCI MSI/X] Mask-Pending bit supported?
      76                 :            :  * @is_64:      [PCI MSI/X] Address size: 0=32bit 1=64bit
      77                 :            :  * @entry_nr:   [PCI MSI/X] Entry which is described by this descriptor
      78                 :            :  * @default_irq:[PCI MSI/X] The default pre-assigned non-MSI irq
      79                 :            :  * @mask_pos:   [PCI MSI]   Mask register position
      80                 :            :  * @mask_base:  [PCI MSI-X] Mask register base address
      81                 :            :  * @platform:   [platform]  Platform device specific msi descriptor data
      82                 :            :  * @fsl_mc:     [fsl-mc]    FSL MC device specific msi descriptor data
      83                 :            :  * @inta:       [INTA]      TISCI based INTA specific msi descriptor data
      84                 :            :  */
      85                 :            : struct msi_desc {
      86                 :            :         /* Shared device/bus type independent data */
      87                 :            :         struct list_head                list;
      88                 :            :         unsigned int                    irq;
      89                 :            :         unsigned int                    nvec_used;
      90                 :            :         struct device                   *dev;
      91                 :            :         struct msi_msg                  msg;
      92                 :            :         struct irq_affinity_desc        *affinity;
      93                 :            : #ifdef CONFIG_IRQ_MSI_IOMMU
      94                 :            :         const void                      *iommu_cookie;
      95                 :            : #endif
      96                 :            : 
      97                 :            :         void (*write_msi_msg)(struct msi_desc *entry, void *data);
      98                 :            :         void *write_msi_msg_data;
      99                 :            : 
     100                 :            :         union {
     101                 :            :                 /* PCI MSI/X specific data */
     102                 :            :                 struct {
     103                 :            :                         u32 masked;
     104                 :            :                         struct {
     105                 :            :                                 u8      is_msix         : 1;
     106                 :            :                                 u8      multiple        : 3;
     107                 :            :                                 u8      multi_cap       : 3;
     108                 :            :                                 u8      maskbit         : 1;
     109                 :            :                                 u8      is_64           : 1;
     110                 :            :                                 u8      is_virtual      : 1;
     111                 :            :                                 u16     entry_nr;
     112                 :            :                                 unsigned default_irq;
     113                 :            :                         } msi_attrib;
     114                 :            :                         union {
     115                 :            :                                 u8      mask_pos;
     116                 :            :                                 void __iomem *mask_base;
     117                 :            :                         };
     118                 :            :                 };
     119                 :            : 
     120                 :            :                 /*
     121                 :            :                  * Non PCI variants add their data structure here. New
     122                 :            :                  * entries need to use a named structure. We want
     123                 :            :                  * proper name spaces for this. The PCI part is
     124                 :            :                  * anonymous for now as it would require an immediate
     125                 :            :                  * tree wide cleanup.
     126                 :            :                  */
     127                 :            :                 struct platform_msi_desc platform;
     128                 :            :                 struct fsl_mc_msi_desc fsl_mc;
     129                 :            :                 struct ti_sci_inta_msi_desc inta;
     130                 :            :         };
     131                 :            : };
     132                 :            : 
     133                 :            : /* Helpers to hide struct msi_desc implementation details */
     134                 :            : #define msi_desc_to_dev(desc)           ((desc)->dev)
     135                 :            : #define dev_to_msi_list(dev)            (&(dev)->msi_list)
     136                 :            : #define first_msi_entry(dev)            \
     137                 :            :         list_first_entry(dev_to_msi_list((dev)), struct msi_desc, list)
     138                 :            : #define for_each_msi_entry(desc, dev)   \
     139                 :            :         list_for_each_entry((desc), dev_to_msi_list((dev)), list)
     140                 :            : #define for_each_msi_entry_safe(desc, tmp, dev) \
     141                 :            :         list_for_each_entry_safe((desc), (tmp), dev_to_msi_list((dev)), list)
     142                 :            : 
     143                 :            : #ifdef CONFIG_IRQ_MSI_IOMMU
     144                 :          0 : static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc)
     145                 :            : {
     146         [ #  # ]:          0 :         return desc->iommu_cookie;
     147                 :            : }
     148                 :            : 
     149                 :          0 : static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc,
     150                 :            :                                              const void *iommu_cookie)
     151                 :            : {
     152         [ #  # ]:          0 :         desc->iommu_cookie = iommu_cookie;
     153                 :            : }
     154                 :            : #else
     155                 :            : static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc)
     156                 :            : {
     157                 :            :         return NULL;
     158                 :            : }
     159                 :            : 
     160                 :            : static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc,
     161                 :            :                                              const void *iommu_cookie)
     162                 :            : {
     163                 :            : }
     164                 :            : #endif
     165                 :            : 
     166                 :            : #ifdef CONFIG_PCI_MSI
     167                 :            : #define first_pci_msi_entry(pdev)       first_msi_entry(&(pdev)->dev)
     168                 :            : #define for_each_pci_msi_entry(desc, pdev)      \
     169                 :            :         for_each_msi_entry((desc), &(pdev)->dev)
     170                 :            : 
     171                 :            : struct pci_dev *msi_desc_to_pci_dev(struct msi_desc *desc);
     172                 :            : void *msi_desc_to_pci_sysdata(struct msi_desc *desc);
     173                 :            : void pci_write_msi_msg(unsigned int irq, struct msi_msg *msg);
     174                 :            : #else /* CONFIG_PCI_MSI */
     175                 :            : static inline void *msi_desc_to_pci_sysdata(struct msi_desc *desc)
     176                 :            : {
     177                 :            :         return NULL;
     178                 :            : }
     179                 :            : static inline void pci_write_msi_msg(unsigned int irq, struct msi_msg *msg)
     180                 :            : {
     181                 :            : }
     182                 :            : #endif /* CONFIG_PCI_MSI */
     183                 :            : 
     184                 :            : struct msi_desc *alloc_msi_entry(struct device *dev, int nvec,
     185                 :            :                                  const struct irq_affinity_desc *affinity);
     186                 :            : void free_msi_entry(struct msi_desc *entry);
     187                 :            : void __pci_read_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
     188                 :            : void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
     189                 :            : 
     190                 :            : u32 __pci_msix_desc_mask_irq(struct msi_desc *desc, u32 flag);
     191                 :            : u32 __pci_msi_desc_mask_irq(struct msi_desc *desc, u32 mask, u32 flag);
     192                 :            : void pci_msi_mask_irq(struct irq_data *data);
     193                 :            : void pci_msi_unmask_irq(struct irq_data *data);
     194                 :            : 
     195                 :            : /*
     196                 :            :  * The arch hooks to setup up msi irqs. Those functions are
     197                 :            :  * implemented as weak symbols so that they /can/ be overriden by
     198                 :            :  * architecture specific code if needed.
     199                 :            :  */
     200                 :            : int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
     201                 :            : void arch_teardown_msi_irq(unsigned int irq);
     202                 :            : int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
     203                 :            : void arch_teardown_msi_irqs(struct pci_dev *dev);
     204                 :            : void arch_restore_msi_irqs(struct pci_dev *dev);
     205                 :            : 
     206                 :            : void default_teardown_msi_irqs(struct pci_dev *dev);
     207                 :            : void default_restore_msi_irqs(struct pci_dev *dev);
     208                 :            : 
     209                 :            : struct msi_controller {
     210                 :            :         struct module *owner;
     211                 :            :         struct device *dev;
     212                 :            :         struct device_node *of_node;
     213                 :            :         struct list_head list;
     214                 :            : 
     215                 :            :         int (*setup_irq)(struct msi_controller *chip, struct pci_dev *dev,
     216                 :            :                          struct msi_desc *desc);
     217                 :            :         int (*setup_irqs)(struct msi_controller *chip, struct pci_dev *dev,
     218                 :            :                           int nvec, int type);
     219                 :            :         void (*teardown_irq)(struct msi_controller *chip, unsigned int irq);
     220                 :            : };
     221                 :            : 
     222                 :            : #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
     223                 :            : 
     224                 :            : #include <linux/irqhandler.h>
     225                 :            : #include <asm/msi.h>
     226                 :            : 
     227                 :            : struct irq_domain;
     228                 :            : struct irq_domain_ops;
     229                 :            : struct irq_chip;
     230                 :            : struct device_node;
     231                 :            : struct fwnode_handle;
     232                 :            : struct msi_domain_info;
     233                 :            : 
     234                 :            : /**
     235                 :            :  * struct msi_domain_ops - MSI interrupt domain callbacks
     236                 :            :  * @get_hwirq:          Retrieve the resulting hw irq number
     237                 :            :  * @msi_init:           Domain specific init function for MSI interrupts
     238                 :            :  * @msi_free:           Domain specific function to free a MSI interrupts
     239                 :            :  * @msi_check:          Callback for verification of the domain/info/dev data
     240                 :            :  * @msi_prepare:        Prepare the allocation of the interrupts in the domain
     241                 :            :  * @msi_finish:         Optional callback to finalize the allocation
     242                 :            :  * @set_desc:           Set the msi descriptor for an interrupt
     243                 :            :  * @handle_error:       Optional error handler if the allocation fails
     244                 :            :  *
     245                 :            :  * @get_hwirq, @msi_init and @msi_free are callbacks used by
     246                 :            :  * msi_create_irq_domain() and related interfaces
     247                 :            :  *
     248                 :            :  * @msi_check, @msi_prepare, @msi_finish, @set_desc and @handle_error
     249                 :            :  * are callbacks used by msi_domain_alloc_irqs() and related
     250                 :            :  * interfaces which are based on msi_desc.
     251                 :            :  */
     252                 :            : struct msi_domain_ops {
     253                 :            :         irq_hw_number_t (*get_hwirq)(struct msi_domain_info *info,
     254                 :            :                                      msi_alloc_info_t *arg);
     255                 :            :         int             (*msi_init)(struct irq_domain *domain,
     256                 :            :                                     struct msi_domain_info *info,
     257                 :            :                                     unsigned int virq, irq_hw_number_t hwirq,
     258                 :            :                                     msi_alloc_info_t *arg);
     259                 :            :         void            (*msi_free)(struct irq_domain *domain,
     260                 :            :                                     struct msi_domain_info *info,
     261                 :            :                                     unsigned int virq);
     262                 :            :         int             (*msi_check)(struct irq_domain *domain,
     263                 :            :                                      struct msi_domain_info *info,
     264                 :            :                                      struct device *dev);
     265                 :            :         int             (*msi_prepare)(struct irq_domain *domain,
     266                 :            :                                        struct device *dev, int nvec,
     267                 :            :                                        msi_alloc_info_t *arg);
     268                 :            :         void            (*msi_finish)(msi_alloc_info_t *arg, int retval);
     269                 :            :         void            (*set_desc)(msi_alloc_info_t *arg,
     270                 :            :                                     struct msi_desc *desc);
     271                 :            :         int             (*handle_error)(struct irq_domain *domain,
     272                 :            :                                         struct msi_desc *desc, int error);
     273                 :            : };
     274                 :            : 
     275                 :            : /**
     276                 :            :  * struct msi_domain_info - MSI interrupt domain data
     277                 :            :  * @flags:              Flags to decribe features and capabilities
     278                 :            :  * @ops:                The callback data structure
     279                 :            :  * @chip:               Optional: associated interrupt chip
     280                 :            :  * @chip_data:          Optional: associated interrupt chip data
     281                 :            :  * @handler:            Optional: associated interrupt flow handler
     282                 :            :  * @handler_data:       Optional: associated interrupt flow handler data
     283                 :            :  * @handler_name:       Optional: associated interrupt flow handler name
     284                 :            :  * @data:               Optional: domain specific data
     285                 :            :  */
     286                 :            : struct msi_domain_info {
     287                 :            :         u32                     flags;
     288                 :            :         struct msi_domain_ops   *ops;
     289                 :            :         struct irq_chip         *chip;
     290                 :            :         void                    *chip_data;
     291                 :            :         irq_flow_handler_t      handler;
     292                 :            :         void                    *handler_data;
     293                 :            :         const char              *handler_name;
     294                 :            :         void                    *data;
     295                 :            : };
     296                 :            : 
     297                 :            : /* Flags for msi_domain_info */
     298                 :            : enum {
     299                 :            :         /*
     300                 :            :          * Init non implemented ops callbacks with default MSI domain
     301                 :            :          * callbacks.
     302                 :            :          */
     303                 :            :         MSI_FLAG_USE_DEF_DOM_OPS        = (1 << 0),
     304                 :            :         /*
     305                 :            :          * Init non implemented chip callbacks with default MSI chip
     306                 :            :          * callbacks.
     307                 :            :          */
     308                 :            :         MSI_FLAG_USE_DEF_CHIP_OPS       = (1 << 1),
     309                 :            :         /* Support multiple PCI MSI interrupts */
     310                 :            :         MSI_FLAG_MULTI_PCI_MSI          = (1 << 2),
     311                 :            :         /* Support PCI MSIX interrupts */
     312                 :            :         MSI_FLAG_PCI_MSIX               = (1 << 3),
     313                 :            :         /* Needs early activate, required for PCI */
     314                 :            :         MSI_FLAG_ACTIVATE_EARLY         = (1 << 4),
     315                 :            :         /*
     316                 :            :          * Must reactivate when irq is started even when
     317                 :            :          * MSI_FLAG_ACTIVATE_EARLY has been set.
     318                 :            :          */
     319                 :            :         MSI_FLAG_MUST_REACTIVATE        = (1 << 5),
     320                 :            :         /* Is level-triggered capable, using two messages */
     321                 :            :         MSI_FLAG_LEVEL_CAPABLE          = (1 << 6),
     322                 :            : };
     323                 :            : 
     324                 :            : int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask,
     325                 :            :                             bool force);
     326                 :            : 
     327                 :            : struct irq_domain *msi_create_irq_domain(struct fwnode_handle *fwnode,
     328                 :            :                                          struct msi_domain_info *info,
     329                 :            :                                          struct irq_domain *parent);
     330                 :            : int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
     331                 :            :                           int nvec);
     332                 :            : void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev);
     333                 :            : struct msi_domain_info *msi_get_domain_info(struct irq_domain *domain);
     334                 :            : 
     335                 :            : struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode,
     336                 :            :                                                   struct msi_domain_info *info,
     337                 :            :                                                   struct irq_domain *parent);
     338                 :            : int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
     339                 :            :                                    irq_write_msi_msg_t write_msi_msg);
     340                 :            : void platform_msi_domain_free_irqs(struct device *dev);
     341                 :            : 
     342                 :            : /* When an MSI domain is used as an intermediate domain */
     343                 :            : int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,
     344                 :            :                             int nvec, msi_alloc_info_t *args);
     345                 :            : int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev,
     346                 :            :                              int virq, int nvec, msi_alloc_info_t *args);
     347                 :            : struct irq_domain *
     348                 :            : __platform_msi_create_device_domain(struct device *dev,
     349                 :            :                                     unsigned int nvec,
     350                 :            :                                     bool is_tree,
     351                 :            :                                     irq_write_msi_msg_t write_msi_msg,
     352                 :            :                                     const struct irq_domain_ops *ops,
     353                 :            :                                     void *host_data);
     354                 :            : 
     355                 :            : #define platform_msi_create_device_domain(dev, nvec, write, ops, data)  \
     356                 :            :         __platform_msi_create_device_domain(dev, nvec, false, write, ops, data)
     357                 :            : #define platform_msi_create_device_tree_domain(dev, nvec, write, ops, data) \
     358                 :            :         __platform_msi_create_device_domain(dev, nvec, true, write, ops, data)
     359                 :            : 
     360                 :            : int platform_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
     361                 :            :                               unsigned int nr_irqs);
     362                 :            : void platform_msi_domain_free(struct irq_domain *domain, unsigned int virq,
     363                 :            :                               unsigned int nvec);
     364                 :            : void *platform_msi_get_host_data(struct irq_domain *domain);
     365                 :            : #endif /* CONFIG_GENERIC_MSI_IRQ_DOMAIN */
     366                 :            : 
     367                 :            : #ifdef CONFIG_PCI_MSI_IRQ_DOMAIN
     368                 :            : void pci_msi_domain_write_msg(struct irq_data *irq_data, struct msi_msg *msg);
     369                 :            : struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode,
     370                 :            :                                              struct msi_domain_info *info,
     371                 :            :                                              struct irq_domain *parent);
     372                 :            : irq_hw_number_t pci_msi_domain_calc_hwirq(struct pci_dev *dev,
     373                 :            :                                           struct msi_desc *desc);
     374                 :            : int pci_msi_domain_check_cap(struct irq_domain *domain,
     375                 :            :                              struct msi_domain_info *info, struct device *dev);
     376                 :            : u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev);
     377                 :            : struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev);
     378                 :            : #else
     379                 :            : static inline struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev)
     380                 :            : {
     381                 :            :         return NULL;
     382                 :            : }
     383                 :            : #endif /* CONFIG_PCI_MSI_IRQ_DOMAIN */
     384                 :            : 
     385                 :            : #endif /* LINUX_MSI_H */

Generated by: LCOV version 1.14