]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branches 'debug/dma-api', 'arm/omap', 'arm/msm', 'core', 'iommu/fault-reporting...
authorJoerg Roedel <joerg.roedel@amd.com>
Fri, 30 Sep 2011 14:47:19 +0000 (16:47 +0200)
committerJoerg Roedel <joerg.roedel@amd.com>
Fri, 30 Sep 2011 14:47:19 +0000 (16:47 +0200)
Conflicts:
drivers/iommu/iommu.c

1  2  3 
drivers/iommu/iommu.c
drivers/iommu/omap-iommu.c
include/linux/iommu.h

index 6e6b6a11b3ced64d1c90e3c9d35d25823f6b5ccf,bd2d4d2764ddf2cf54491d43a3c49f109ba638db,64419c88727e1a57351aa4d323ef56649d7e1954..2fb2963df55376a3a8efbf09490457e08b28b836
   #include <linux/errno.h>
   #include <linux/iommu.h>
   
-- static struct iommu_ops *iommu_ops;
++ static void iommu_bus_init(struct bus_type *bus, struct iommu_ops *ops)
++ {
++ }
   
-- void register_iommu(struct iommu_ops *ops)
++ /**
++  * bus_set_iommu - set iommu-callbacks for the bus
++  * @bus: bus.
++  * @ops: the callbacks provided by the iommu-driver
++  *
++  * This function is called by an iommu driver to set the iommu methods
++  * used for a particular bus. Drivers for devices on that bus can use
++  * the iommu-api after these ops are registered.
++  * This special function is needed because IOMMUs are usually devices on
++  * the bus itself, so the iommu drivers are not initialized when the bus
++  * is set up. With this function the iommu-driver can set the iommu-ops
++  * afterwards.
++  */
++ int bus_set_iommu(struct bus_type *bus, struct iommu_ops *ops)
   {
--      if (iommu_ops)
--              BUG();
++      if (bus->iommu_ops != NULL)
++              return -EBUSY;
+  
 -      iommu_ops = ops;
++      bus->iommu_ops = ops;
++ 
++      /* Do IOMMU specific setup for this bus-type */
++      iommu_bus_init(bus, ops);
 + 
-       iommu_ops = ops;
++      return 0;
   }
++ EXPORT_SYMBOL_GPL(bus_set_iommu);
   
-- bool iommu_found(void)
++ bool iommu_present(struct bus_type *bus)
   {
--      return iommu_ops != NULL;
++      return bus->iommu_ops != NULL;
   }
-- EXPORT_SYMBOL_GPL(iommu_found);
++ EXPORT_SYMBOL_GPL(iommu_present);
   
-  struct iommu_domain *iommu_domain_alloc(void)
+ +/**
+ + * iommu_set_fault_handler() - set a fault handler for an iommu domain
+ + * @domain: iommu domain
+ + * @handler: fault handler
+ + *
+ + * This function should be used by IOMMU users which want to be notified
+ + * whenever an IOMMU fault happens.
+ + *
+ + * The fault handler itself should return 0 on success, and an appropriate
+ + * error code otherwise.
+ + */
+ +void iommu_set_fault_handler(struct iommu_domain *domain,
+ +                                     iommu_fault_handler_t handler)
+ +{
+ +     BUG_ON(!domain);
+ +
+ +     domain->handler = handler;
+ +}
+ +EXPORT_SYMBOL_GPL(iommu_set_fault_handler);
+ +
 - struct iommu_domain *iommu_domain_alloc(void)
++ struct iommu_domain *iommu_domain_alloc(struct bus_type *bus)
   {
        struct iommu_domain *domain;
        int ret;
Simple merge
index 9940319d6f9d3ab0d1442a5fa31a7db9be6dafa3,ddad0ae0a43354451352803f0175c429ad663676,609ebf6bbe0c15cd0f1ecf8801c14c521fdf993d..432acc4c054df1134dddb9be501de5c27d84d926
   #define IOMMU_WRITE  (2)
   #define IOMMU_CACHE  (4) /* DMA cache coherency */
   
++ struct iommu_ops;
++ struct bus_type;
   struct device;
+ +struct iommu_domain;
+ +
+ +/* iommu fault flags */
+ +#define IOMMU_FAULT_READ     0x0
+ +#define IOMMU_FAULT_WRITE    0x1
+ +
+ +typedef int (*iommu_fault_handler_t)(struct iommu_domain *,
+ +                             struct device *, unsigned long, int);
   
   struct iommu_domain {
++      struct iommu_ops *ops;
        void *priv;
+ +     iommu_fault_handler_t handler;
   };
   
   #define IOMMU_CAP_CACHE_COHERENCY    0x1
@@@@ -67,14 -76,55 -70,12 +79,53 @@@@ extern phys_addr_t iommu_iova_to_phys(s
                                      unsigned long iova);
   extern int iommu_domain_has_cap(struct iommu_domain *domain,
                                unsigned long cap);
-  #else /* CONFIG_IOMMU_API */
+ +extern void iommu_set_fault_handler(struct iommu_domain *domain,
+ +                                     iommu_fault_handler_t handler);
+ +
+ +/**
+ + * report_iommu_fault() - report about an IOMMU fault to the IOMMU framework
+ + * @domain: the iommu domain where the fault has happened
+ + * @dev: the device where the fault has happened
+ + * @iova: the faulting address
+ + * @flags: mmu fault flags (e.g. IOMMU_FAULT_READ/IOMMU_FAULT_WRITE/...)
+ + *
+ + * This function should be called by the low-level IOMMU implementations
+ + * whenever IOMMU faults happen, to allow high-level users, that are
+ + * interested in such events, to know about them.
+ + *
+ + * This event may be useful for several possible use cases:
+ + * - mere logging of the event
+ + * - dynamic TLB/PTE loading
+ + * - if restarting of the faulting device is required
+ + *
+ + * Returns 0 on success and an appropriate error code otherwise (if dynamic
+ + * PTE/TLB loading will one day be supported, implementations will be able
+ + * to tell whether it succeeded or not according to this return value).
+ + *
+ + * Specifically, -ENOSYS is returned if a fault handler isn't installed
+ + * (though fault handlers can also return -ENOSYS, in case they want to
+ + * elicit the default behavior of the IOMMU drivers).
+ + */
+ +static inline int report_iommu_fault(struct iommu_domain *domain,
+ +             struct device *dev, unsigned long iova, int flags)
+ +{
+ +     int ret = -ENOSYS;
  +
-  static inline void register_iommu(struct iommu_ops *ops)
-  {
+ +     /*
+ +      * if upper layers showed interest and installed a fault handler,
+ +      * invoke it.
+ +      */
+ +     if (domain->handler)
+ +             ret = domain->handler(domain, dev, iova, flags);
  +
+ +     return ret;
  +}
   
-  static inline bool iommu_found(void)
+  #else /* CONFIG_IOMMU_API */
+  
 - static inline void register_iommu(struct iommu_ops *ops)
 - {
 - }
++ struct iommu_ops {};
+  
 - static inline bool iommu_found(void)
++ static inline bool iommu_present(struct bus_type *bus)
   {
        return false;
   }