diff options
Diffstat (limited to 'drivers/iommu/fsl_pamu_domain.c')
-rw-r--r-- | drivers/iommu/fsl_pamu_domain.c | 173 |
1 files changed, 74 insertions, 99 deletions
diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c index c828f80d48b0..ceebd287b660 100644 --- a/drivers/iommu/fsl_pamu_domain.c +++ b/drivers/iommu/fsl_pamu_domain.c @@ -19,26 +19,10 @@ #define pr_fmt(fmt) "fsl-pamu-domain: %s: " fmt, __func__ -#include <linux/init.h> -#include <linux/iommu.h> -#include <linux/notifier.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/device.h> -#include <linux/of_platform.h> -#include <linux/bootmem.h> -#include <linux/err.h> -#include <asm/io.h> -#include <asm/bitops.h> - -#include <asm/pci-bridge.h> -#include <sysdev/fsl_pci.h> - #include "fsl_pamu_domain.h" +#include <sysdev/fsl_pci.h> + /* * Global spinlock that needs to be held while * configuring PAMU. @@ -51,23 +35,21 @@ static DEFINE_SPINLOCK(device_domain_lock); static int __init iommu_init_mempool(void) { - fsl_pamu_domain_cache = kmem_cache_create("fsl_pamu_domain", - sizeof(struct fsl_dma_domain), - 0, - SLAB_HWCACHE_ALIGN, - - NULL); + sizeof(struct fsl_dma_domain), + 0, + SLAB_HWCACHE_ALIGN, + NULL); if (!fsl_pamu_domain_cache) { pr_debug("Couldn't create fsl iommu_domain cache\n"); return -ENOMEM; } iommu_devinfo_cache = kmem_cache_create("iommu_devinfo", - sizeof(struct device_domain_info), - 0, - SLAB_HWCACHE_ALIGN, - NULL); + sizeof(struct device_domain_info), + 0, + SLAB_HWCACHE_ALIGN, + NULL); if (!iommu_devinfo_cache) { pr_debug("Couldn't create devinfo cache\n"); kmem_cache_destroy(fsl_pamu_domain_cache); @@ -80,8 +62,7 @@ static int __init iommu_init_mempool(void) static phys_addr_t get_phys_addr(struct fsl_dma_domain *dma_domain, dma_addr_t iova) { u32 win_cnt = dma_domain->win_cnt; - struct dma_window *win_ptr = - &dma_domain->win_arr[0]; + struct dma_window *win_ptr = &dma_domain->win_arr[0]; struct iommu_domain_geometry *geom; geom = &dma_domain->iommu_domain->geometry; @@ -103,22 +84,20 @@ static phys_addr_t get_phys_addr(struct fsl_dma_domain *dma_domain, dma_addr_t i } if (win_ptr->valid) - return (win_ptr->paddr + (iova & (win_ptr->size - 1))); + return win_ptr->paddr + (iova & (win_ptr->size - 1)); return 0; } static int map_subwins(int liodn, struct fsl_dma_domain *dma_domain) { - struct dma_window *sub_win_ptr = - &dma_domain->win_arr[0]; + struct dma_window *sub_win_ptr = &dma_domain->win_arr[0]; int i, ret; unsigned long rpn, flags; for (i = 0; i < dma_domain->win_cnt; i++) { if (sub_win_ptr[i].valid) { - rpn = sub_win_ptr[i].paddr >> - PAMU_PAGE_SHIFT; + rpn = sub_win_ptr[i].paddr >> PAMU_PAGE_SHIFT; spin_lock_irqsave(&iommu_lock, flags); ret = pamu_config_spaace(liodn, dma_domain->win_cnt, i, sub_win_ptr[i].size, @@ -130,7 +109,7 @@ static int map_subwins(int liodn, struct fsl_dma_domain *dma_domain) sub_win_ptr[i].prot); spin_unlock_irqrestore(&iommu_lock, flags); if (ret) { - pr_debug("PAMU SPAACE configuration failed for liodn %d\n", + pr_debug("SPAACE configuration failed for liodn %d\n", liodn); return ret; } @@ -156,8 +135,7 @@ static int map_win(int liodn, struct fsl_dma_domain *dma_domain) 0, wnd->prot); spin_unlock_irqrestore(&iommu_lock, flags); if (ret) - pr_debug("PAMU PAACE configuration failed for liodn %d\n", - liodn); + pr_debug("PAACE configuration failed for liodn %d\n", liodn); return ret; } @@ -169,7 +147,6 @@ static int map_liodn(int liodn, struct fsl_dma_domain *dma_domain) return map_subwins(liodn, dma_domain); else return map_win(liodn, dma_domain); - } /* Update window/subwindow mapping for the LIODN */ @@ -190,7 +167,8 @@ static int update_liodn(int liodn, struct fsl_dma_domain *dma_domain, u32 wnd_nr (wnd_nr > 0) ? 1 : 0, wnd->prot); if (ret) - pr_debug("Subwindow reconfiguration failed for liodn %d\n", liodn); + pr_debug("Subwindow reconfiguration failed for liodn %d\n", + liodn); } else { phys_addr_t wnd_addr; @@ -200,10 +178,11 @@ static int update_liodn(int liodn, struct fsl_dma_domain *dma_domain, u32 wnd_nr wnd->size, ~(u32)0, wnd->paddr >> PAMU_PAGE_SHIFT, - dma_domain->snoop_id, dma_domain->stash_id, - 0, wnd->prot); + dma_domain->snoop_id, dma_domain->stash_id, + 0, wnd->prot); if (ret) - pr_debug("Window reconfiguration failed for liodn %d\n", liodn); + pr_debug("Window reconfiguration failed for liodn %d\n", + liodn); } spin_unlock_irqrestore(&iommu_lock, flags); @@ -212,14 +191,15 @@ static int update_liodn(int liodn, struct fsl_dma_domain *dma_domain, u32 wnd_nr } static int update_liodn_stash(int liodn, struct fsl_dma_domain *dma_domain, - u32 val) + u32 val) { int ret = 0, i; unsigned long flags; spin_lock_irqsave(&iommu_lock, flags); if (!dma_domain->win_arr) { - pr_debug("Windows not configured, stash destination update failed for liodn %d\n", liodn); + pr_debug("Windows not configured, stash destination update failed for liodn %d\n", + liodn); spin_unlock_irqrestore(&iommu_lock, flags); return -EINVAL; } @@ -227,7 +207,8 @@ static int update_liodn_stash(int liodn, struct fsl_dma_domain *dma_domain, for (i = 0; i < dma_domain->win_cnt; i++) { ret = pamu_update_paace_stash(liodn, i, val); if (ret) { - pr_debug("Failed to update SPAACE %d field for liodn %d\n ", i, liodn); + pr_debug("Failed to update SPAACE %d field for liodn %d\n ", + i, liodn); spin_unlock_irqrestore(&iommu_lock, flags); return ret; } @@ -240,9 +221,9 @@ static int update_liodn_stash(int liodn, struct fsl_dma_domain *dma_domain, /* Set the geometry parameters for a LIODN */ static int pamu_set_liodn(int liodn, struct device *dev, - struct fsl_dma_domain *dma_domain, - struct iommu_domain_geometry *geom_attr, - u32 win_cnt) + struct fsl_dma_domain *dma_domain, + struct iommu_domain_geometry *geom_attr, + u32 win_cnt) { phys_addr_t window_addr, window_size; phys_addr_t subwin_size; @@ -268,7 +249,8 @@ static int pamu_set_liodn(int liodn, struct device *dev, dma_domain->stash_id, win_cnt, 0); spin_unlock_irqrestore(&iommu_lock, flags); if (ret) { - pr_debug("PAMU PAACE configuration failed for liodn %d, win_cnt =%d\n", liodn, win_cnt); + pr_debug("PAACE configuration failed for liodn %d, win_cnt =%d\n", + liodn, win_cnt); return ret; } @@ -285,7 +267,8 @@ static int pamu_set_liodn(int liodn, struct device *dev, 0, 0); spin_unlock_irqrestore(&iommu_lock, flags); if (ret) { - pr_debug("PAMU SPAACE configuration failed for liodn %d\n", liodn); + pr_debug("SPAACE configuration failed for liodn %d\n", + liodn); return ret; } } @@ -301,13 +284,13 @@ static int check_size(u64 size, dma_addr_t iova) * to PAMU page size. */ if ((size & (size - 1)) || size < PAMU_PAGE_SIZE) { - pr_debug("%s: size too small or not a power of two\n", __func__); + pr_debug("Size too small or not a power of two\n"); return -EINVAL; } - /* iova must be page size aligned*/ + /* iova must be page size aligned */ if (iova & (size - 1)) { - pr_debug("%s: address is not aligned with window size\n", __func__); + pr_debug("Address is not aligned with window size\n"); return -EINVAL; } @@ -396,16 +379,15 @@ static void attach_device(struct fsl_dma_domain *dma_domain, int liodn, struct d if (!dev->archdata.iommu_domain) dev->archdata.iommu_domain = info; spin_unlock_irqrestore(&device_domain_lock, flags); - } static phys_addr_t fsl_pamu_iova_to_phys(struct iommu_domain *domain, - dma_addr_t iova) + dma_addr_t iova) { struct fsl_dma_domain *dma_domain = domain->priv; - if ((iova < domain->geometry.aperture_start) || - iova > (domain->geometry.aperture_end)) + if (iova < domain->geometry.aperture_start || + iova > domain->geometry.aperture_end) return 0; return get_phys_addr(dma_domain, iova); @@ -460,7 +442,7 @@ static int pamu_set_domain_geometry(struct fsl_dma_domain *dma_domain, list_for_each_entry(info, &dma_domain->devices, link) { ret = pamu_set_liodn(info->liodn, info->dev, dma_domain, - geom_attr, win_cnt); + geom_attr, win_cnt); if (ret) break; } @@ -543,7 +525,6 @@ static void fsl_pamu_window_disable(struct iommu_domain *domain, u32 wnd_nr) } spin_unlock_irqrestore(&dma_domain->domain_lock, flags); - } static int fsl_pamu_window_enable(struct iommu_domain *domain, u32 wnd_nr, @@ -576,7 +557,7 @@ static int fsl_pamu_window_enable(struct iommu_domain *domain, u32 wnd_nr, win_size = dma_domain->geom_size >> ilog2(dma_domain->win_cnt); if (size > win_size) { - pr_debug("Invalid window size \n"); + pr_debug("Invalid window size\n"); spin_unlock_irqrestore(&dma_domain->domain_lock, flags); return -EINVAL; } @@ -622,8 +603,8 @@ static int fsl_pamu_window_enable(struct iommu_domain *domain, u32 wnd_nr, * and window mappings. */ static int handle_attach_device(struct fsl_dma_domain *dma_domain, - struct device *dev, const u32 *liodn, - int num) + struct device *dev, const u32 *liodn, + int num) { unsigned long flags; struct iommu_domain *domain = dma_domain->iommu_domain; @@ -632,11 +613,10 @@ static int handle_attach_device(struct fsl_dma_domain *dma_domain, spin_lock_irqsave(&dma_domain->domain_lock, flags); for (i = 0; i < num; i++) { - /* Ensure that LIODN value is valid */ if (liodn[i] >= PAACE_NUMBER_ENTRIES) { pr_debug("Invalid liodn %d, attach device failed for %s\n", - liodn[i], dev->of_node->full_name); + liodn[i], dev->of_node->full_name); ret = -EINVAL; break; } @@ -649,9 +629,9 @@ static int handle_attach_device(struct fsl_dma_domain *dma_domain, */ if (dma_domain->win_arr) { u32 win_cnt = dma_domain->win_cnt > 1 ? dma_domain->win_cnt : 0; + ret = pamu_set_liodn(liodn[i], dev, dma_domain, - &domain->geometry, - win_cnt); + &domain->geometry, win_cnt); if (ret) break; if (dma_domain->mapped) { @@ -698,19 +678,18 @@ static int fsl_pamu_attach_device(struct iommu_domain *domain, liodn = of_get_property(dev->of_node, "fsl,liodn", &len); if (liodn) { liodn_cnt = len / sizeof(u32); - ret = handle_attach_device(dma_domain, dev, - liodn, liodn_cnt); + ret = handle_attach_device(dma_domain, dev, liodn, liodn_cnt); } else { pr_debug("missing fsl,liodn property at %s\n", - dev->of_node->full_name); - ret = -EINVAL; + dev->of_node->full_name); + ret = -EINVAL; } return ret; } static void fsl_pamu_detach_device(struct iommu_domain *domain, - struct device *dev) + struct device *dev) { struct fsl_dma_domain *dma_domain = domain->priv; const u32 *prop; @@ -738,7 +717,7 @@ static void fsl_pamu_detach_device(struct iommu_domain *domain, detach_device(dev, dma_domain); else pr_debug("missing fsl,liodn property at %s\n", - dev->of_node->full_name); + dev->of_node->full_name); } static int configure_domain_geometry(struct iommu_domain *domain, void *data) @@ -754,10 +733,10 @@ static int configure_domain_geometry(struct iommu_domain *domain, void *data) * DMA outside of the geometry. */ if (check_size(geom_size, geom_attr->aperture_start) || - !geom_attr->force_aperture) { - pr_debug("Invalid PAMU geometry attributes\n"); - return -EINVAL; - } + !geom_attr->force_aperture) { + pr_debug("Invalid PAMU geometry attributes\n"); + return -EINVAL; + } spin_lock_irqsave(&dma_domain->domain_lock, flags); if (dma_domain->enabled) { @@ -786,7 +765,7 @@ static int configure_domain_stash(struct fsl_dma_domain *dma_domain, void *data) spin_lock_irqsave(&dma_domain->domain_lock, flags); memcpy(&dma_domain->dma_stash, stash_attr, - sizeof(struct pamu_stash_attribute)); + sizeof(struct pamu_stash_attribute)); dma_domain->stash_id = get_stash_id(stash_attr->cache, stash_attr->cpu); @@ -803,7 +782,7 @@ static int configure_domain_stash(struct fsl_dma_domain *dma_domain, void *data) return ret; } -/* Configure domain dma state i.e. enable/disable DMA*/ +/* Configure domain dma state i.e. enable/disable DMA */ static int configure_domain_dma_state(struct fsl_dma_domain *dma_domain, bool enable) { struct device_domain_info *info; @@ -819,8 +798,7 @@ static int configure_domain_dma_state(struct fsl_dma_domain *dma_domain, bool en } dma_domain->enabled = enable; - list_for_each_entry(info, &dma_domain->devices, - link) { + list_for_each_entry(info, &dma_domain->devices, link) { ret = (enable) ? pamu_enable_liodn(info->liodn) : pamu_disable_liodn(info->liodn); if (ret) @@ -833,12 +811,11 @@ static int configure_domain_dma_state(struct fsl_dma_domain *dma_domain, bool en } static int fsl_pamu_set_domain_attr(struct iommu_domain *domain, - enum iommu_attr attr_type, void *data) + enum iommu_attr attr_type, void *data) { struct fsl_dma_domain *dma_domain = domain->priv; int ret = 0; - switch (attr_type) { case DOMAIN_ATTR_GEOMETRY: ret = configure_domain_geometry(domain, data); @@ -853,22 +830,21 @@ static int fsl_pamu_set_domain_attr(struct iommu_domain *domain, pr_debug("Unsupported attribute type\n"); ret = -EINVAL; break; - }; + } return ret; } static int fsl_pamu_get_domain_attr(struct iommu_domain *domain, - enum iommu_attr attr_type, void *data) + enum iommu_attr attr_type, void *data) { struct fsl_dma_domain *dma_domain = domain->priv; int ret = 0; - switch (attr_type) { case DOMAIN_ATTR_FSL_PAMU_STASH: - memcpy((struct pamu_stash_attribute *) data, &dma_domain->dma_stash, - sizeof(struct pamu_stash_attribute)); + memcpy(data, &dma_domain->dma_stash, + sizeof(struct pamu_stash_attribute)); break; case DOMAIN_ATTR_FSL_PAMU_ENABLE: *(int *)data = dma_domain->enabled; @@ -880,7 +856,7 @@ static int fsl_pamu_get_domain_attr(struct iommu_domain *domain, pr_debug("Unsupported attribute type\n"); ret = -EINVAL; break; - }; + } return ret; } @@ -903,11 +879,8 @@ static bool check_pci_ctl_endpt_part(struct pci_controller *pci_ctl) /* Check the PCI controller version number by readding BRR1 register */ version = in_be32(pci_ctl->cfg_addr + (PCI_FSL_BRR1 >> 2)); version &= PCI_FSL_BRR1_VER; - /* If PCI controller version is >= 0x204 we can partition endpoints*/ - if (version >= 0x204) - return 1; - - return 0; + /* If PCI controller version is >= 0x204 we can partition endpoints */ + return version >= 0x204; } /* Get iommu group information from peer devices or devices on the parent bus */ @@ -968,8 +941,9 @@ static struct iommu_group *get_pci_device_group(struct pci_dev *pdev) if (pci_ctl->parent->iommu_group) { group = get_device_iommu_group(pci_ctl->parent); iommu_group_remove_device(pci_ctl->parent); - } else + } else { group = get_shared_pci_device_group(pdev); + } } if (!group) @@ -1055,11 +1029,12 @@ static int fsl_pamu_set_windows(struct iommu_domain *domain, u32 w_count) } ret = pamu_set_domain_geometry(dma_domain, &domain->geometry, - ((w_count > 1) ? w_count : 0)); + w_count > 1 ? w_count : 0); if (!ret) { kfree(dma_domain->win_arr); - dma_domain->win_arr = kzalloc(sizeof(struct dma_window) * - w_count, GFP_ATOMIC); + dma_domain->win_arr = kcalloc(w_count, + sizeof(*dma_domain->win_arr), + GFP_ATOMIC); if (!dma_domain->win_arr) { spin_unlock_irqrestore(&dma_domain->domain_lock, flags); return -ENOMEM; @@ -1095,7 +1070,7 @@ static const struct iommu_ops fsl_pamu_ops = { .remove_device = fsl_pamu_remove_device, }; -int pamu_domain_init(void) +int __init pamu_domain_init(void) { int ret = 0; |