From 3e9416a16c9c71bae0ecbe476bd3f832bab52f81 Mon Sep 17 00:00:00 2001 From: Varun Sethi Date: Mon, 22 Jul 2013 19:11:28 +0530 Subject: Make stash id and operation mapping index per window attributes. Stash ID and operation mapping can now be set per dma window. Signed-off-by: Varun Sethi Change-Id: I987abbcba0575fea1b43843c2bce342f4eae4df2 Reviewed-on: http://git.am.freescale.net:8181/3439 Reviewed-by: Yoder Stuart-B08248 Reviewed-by: Fleming Andrew-AFLEMING Tested-by: Fleming Andrew-AFLEMING Conflicts: drivers/iommu/fsl_pamu.c drivers/iommu/fsl_pamu.h drivers/iommu/fsl_pamu_domain.c diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c index 9fb4ee2..ddd0836 100644 --- a/drivers/iommu/fsl_pamu.c +++ b/drivers/iommu/fsl_pamu.c @@ -273,7 +273,7 @@ void pamu_free_subwins(int liodn) * Function used for updating stash destination for the coressponding * LIODN. */ -int pamu_update_paace_stash(int liodn, u32 subwin, u32 value) +int pamu_update_paace_field(int liodn, u32 subwin, int field, u32 value) { struct paace *paace; @@ -288,7 +288,6 @@ int pamu_update_paace_stash(int liodn, u32 subwin, u32 value) return -ENOENT; } } - set_bf(paace->impl_attr, PAACE_IA_CID, value); switch (field) { case PAACE_STASH_FIELD: diff --git a/drivers/iommu/fsl_pamu.h b/drivers/iommu/fsl_pamu.h index 480ec23..fd9dd6d 100644 --- a/drivers/iommu/fsl_pamu.h +++ b/drivers/iommu/fsl_pamu.h @@ -404,7 +404,7 @@ int pamu_config_spaace(int liodn, u32 subwin_cnt, u32 subwin_addr, u32 get_stash_id(u32 stash_dest_hint, u32 vcpu); void get_ome_index(u32 *omi_index, struct device *dev); -int pamu_update_paace_stash(int liodn, u32 subwin, u32 value); +int pamu_update_paace_field(int liodn, u32 subwin, int field, u32 value); int pamu_disable_spaace(int liodn, u32 subwin); u32 pamu_get_max_subwin_cnt(void); diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c index 07ec977..99c182d 100644 --- a/drivers/iommu/fsl_pamu_domain.c +++ b/drivers/iommu/fsl_pamu_domain.c @@ -122,10 +122,10 @@ static int map_subwins(int liodn, struct fsl_dma_domain *dma_domain) spin_lock(&iommu_lock); ret = pamu_config_spaace(liodn, dma_domain->win_cnt, i, sub_win_ptr[i].size, - ~(u32)0, + sub_win_ptr[i].omi, rpn, dma_domain->snoop_id, - dma_domain->stash_id, + sub_win_ptr[i].stash_id, (i > 0) ? 1 : 0, sub_win_ptr[i].prot); spin_unlock(&iommu_lock); @@ -149,9 +149,9 @@ static int map_win(int liodn, struct fsl_dma_domain *dma_domain) spin_lock(&iommu_lock); ret = pamu_config_ppaace(liodn, wnd_addr, wnd->size, - ~(u32)0, + wnd->omi, wnd->paddr >> PAMU_PAGE_SHIFT, - dma_domain->snoop_id, dma_domain->stash_id, + dma_domain->snoop_id, wnd->stash_id, 0, wnd->prot); spin_unlock(&iommu_lock); if (ret) @@ -181,10 +181,10 @@ static int update_liodn(int liodn, struct fsl_dma_domain *dma_domain, u32 wnd_nr if (dma_domain->win_cnt > 1) { ret = pamu_config_spaace(liodn, dma_domain->win_cnt, wnd_nr, wnd->size, - ~(u32)0, + wnd->omi, wnd->paddr >> PAMU_PAGE_SHIFT, dma_domain->snoop_id, - dma_domain->stash_id, + wnd->stash_id, (wnd_nr > 0) ? 1 : 0, wnd->prot); if (ret) @@ -196,9 +196,9 @@ static int update_liodn(int liodn, struct fsl_dma_domain *dma_domain, u32 wnd_nr ret = pamu_config_ppaace(liodn, wnd_addr, wnd->size, - ~(u32)0, + wnd->omi, wnd->paddr >> PAMU_PAGE_SHIFT, - dma_domain->snoop_id, dma_domain->stash_id, + dma_domain->snoop_id, wnd->stash_id, 0, wnd->prot); if (ret) pr_err("Window reconfiguration failed for liodn %d\n", liodn); @@ -209,29 +209,31 @@ static int update_liodn(int liodn, struct fsl_dma_domain *dma_domain, u32 wnd_nr return ret; } -static int update_liodn_stash(int liodn, struct fsl_dma_domain *dma_domain, - u32 val) +struct pamu_attr_info { + u32 window; + int field; + u32 value; +}; + +static int update_liodn_attr(int liodn, struct fsl_dma_domain *dma_domain, + struct pamu_attr_info *attr_info) { int ret = 0, i; spin_lock(&iommu_lock); - if (!dma_domain->win_cnt) { - ret = pamu_update_paace_stash(liodn, 0, val); - if (ret) { - pr_err("Failed to update PAACE field for liodn %d\n ", liodn); - spin_unlock(&iommu_lock); - return ret; - } - } else { + + + if (~attr_info->window == 0) { for (i = 0; i < dma_domain->win_cnt; i++) { - ret = pamu_update_paace_stash(liodn, i, val); - if (ret) { - pr_err("Failed to update SPAACE %d field for liodn %d\n ", i, liodn); - spin_unlock(&iommu_lock); - return ret; - } + ret = pamu_update_paace_field(liodn, i, attr_info->field, + attr_info->value); + if (ret) + break; } - } + } else + ret = pamu_update_paace_field(liodn, attr_info->window, attr_info->field, + attr_info->value); + spin_unlock(&iommu_lock); return ret; @@ -263,7 +265,7 @@ static int pamu_set_liodn(int liodn, struct device *dev, if (!ret) ret = pamu_config_ppaace(liodn, window_addr, window_size, omi_index, 0, dma_domain->snoop_id, - dma_domain->stash_id, win_cnt, 0); + ~(u32)0, win_cnt, 0); spin_unlock(&iommu_lock); if (ret) { pr_err("PAMU PAACE configuration failed for liodn %d, win_cnt =%d\n", liodn, win_cnt); @@ -279,7 +281,7 @@ static int pamu_set_liodn(int liodn, struct device *dev, ret = pamu_config_spaace(liodn, win_cnt, i, subwin_size, omi_index, 0, dma_domain->snoop_id, - dma_domain->stash_id, + ~(u32)0, 0, 0); spin_unlock(&iommu_lock); if (ret) { @@ -320,7 +322,6 @@ static struct fsl_dma_domain *iommu_alloc_dma_domain(void) if (!domain) return NULL; - domain->stash_id = ~(u32)0; domain->snoop_id = ~(u32)0; domain->win_cnt = pamu_get_max_subwin_cnt(); domain->geom_size = 0; @@ -476,15 +477,20 @@ static int pamu_set_domain_geometry(struct fsl_dma_domain *dma_domain, return ret; } -/* Update stash destination for all LIODNs associated with the domain */ -static int update_domain_stash(struct fsl_dma_domain *dma_domain, u32 val) +/* + * Update attribute for all LIODNs associated with the domain + * + */ +static int update_domain_attr(struct fsl_dma_domain *dma_domain, + struct pamu_attr_info *attr_info) { struct device_domain_info *info; int ret = 0; if (!list_empty(&dma_domain->devices)) { list_for_each_entry(info, &dma_domain->devices, link) { - ret = update_liodn_stash(info->liodn, dma_domain, val); + ret = update_liodn_attr(info->liodn, dma_domain, + attr_info); if (ret) break; } @@ -841,23 +847,45 @@ static int configure_domain_op_map(struct fsl_dma_domain *dma_domain, static int configure_domain_stash(struct fsl_dma_domain *dma_domain, void *data) { struct iommu_stash_attribute *stash_attr = data; + struct dma_window *wnd; unsigned long flags; - int ret; + u32 stash_id; + int ret, i; + struct pamu_attr_info attr_info; spin_lock_irqsave(&dma_domain->domain_lock, flags); - memcpy(&dma_domain->dma_stash, stash_attr, - sizeof(struct iommu_stash_attribute)); + if (!dma_domain->win_arr) { + pr_err("Number of windows not configured\n"); + spin_unlock_irqrestore(&dma_domain->domain_lock, flags); + return -ENODEV; + } - dma_domain->stash_id = get_stash_id(stash_attr->cache, + stash_id = get_stash_id(stash_attr->cache, stash_attr->cpu); - if (dma_domain->stash_id == ~(u32)0) { + if (~stash_id == 0) { pr_err("Invalid stash attributes\n"); spin_unlock_irqrestore(&dma_domain->domain_lock, flags); return -EINVAL; } - ret = update_domain_stash(dma_domain, dma_domain->stash_id); + if (~stash_attr->window == 0) { + wnd = &dma_domain->win_arr[0]; + for (i = 0; i < dma_domain->win_cnt; i++) { + wnd[i].stash_id = stash_id; + memcpy(&wnd[i].stash_attr, stash_attr, sizeof(struct iommu_stash_attribute)); + wnd[i].stash_attr.window = i; + } + } else { + wnd = &dma_domain->win_arr[stash_attr->window]; + wnd->stash_id = stash_id; + memcpy(&wnd->stash_attr, stash_attr, sizeof(struct iommu_stash_attribute)); + } + + attr_info.window = stash_attr->window; + attr_info.field = PAACE_STASH_FIELD; + attr_info.value = stash_id; + ret = update_domain_attr(dma_domain, &attr_info); spin_unlock_irqrestore(&dma_domain->domain_lock, flags); @@ -932,10 +960,6 @@ static int fsl_pamu_get_domain_attr(struct iommu_domain *domain, switch (attr_type) { - case DOMAIN_ATTR_PAMU_STASH: - memcpy((struct iommu_stash_attribute *) data, &dma_domain->dma_stash, - sizeof(struct iommu_stash_attribute)); - break; case DOMAIN_ATTR_PAMU_ENABLE: *(int *)data = dma_domain->enabled; break; @@ -1128,6 +1152,16 @@ static void fsl_pamu_remove_device(struct device *dev) iommu_group_remove_device(dev); } +static void dma_domain_init_windows(struct fsl_dma_domain *dma_domain) +{ + int i; + + for (i = 0; i < dma_domain->win_cnt; i++) { + dma_domain->win_arr[i].stash_id = ~(u32)0; + dma_domain->win_arr[i].omi = ~(u32)0; + } +} + static int fsl_pamu_set_windows(struct iommu_domain *domain, u32 w_count) { struct fsl_dma_domain *dma_domain = domain->priv; @@ -1171,6 +1205,7 @@ static int fsl_pamu_set_windows(struct iommu_domain *domain, u32 w_count) return -ENOMEM; } dma_domain->win_cnt = w_count; + dma_domain_init_windows(dma_domain); } spin_unlock_irqrestore(&dma_domain->domain_lock, flags); diff --git a/drivers/iommu/fsl_pamu_domain.h b/drivers/iommu/fsl_pamu_domain.h index 52dede7..1d55d25 100644 --- a/drivers/iommu/fsl_pamu_domain.h +++ b/drivers/iommu/fsl_pamu_domain.h @@ -22,10 +22,13 @@ #include "fsl_pamu.h" struct dma_window { - phys_addr_t paddr; + phys_addr_t paddr; u64 size; - int valid; - int prot; + struct iommu_stash_attribute stash_attr; + int valid; + int prot; + u32 stash_id; + u32 omi; }; struct fsl_dma_domain { @@ -67,9 +70,6 @@ struct fsl_dma_domain { */ int mapped; int enabled; - /* stash_id obtained from the stash attribute details */ - u32 stash_id; - struct iommu_stash_attribute dma_stash; u32 snoop_id; struct iommu_domain *iommu_domain; spinlock_t domain_lock; diff --git a/drivers/staging/fsl_qbman/qman_driver.c b/drivers/staging/fsl_qbman/qman_driver.c index 4c9f6c6..875c0df 100644 --- a/drivers/staging/fsl_qbman/qman_driver.c +++ b/drivers/staging/fsl_qbman/qman_driver.c @@ -487,6 +487,7 @@ static void portal_set_cpu(struct qm_portal_config *pcfg, int cpu) } stash_attr.cpu = cpu; stash_attr.cache = IOMMU_ATTR_CACHE_L1; + stash_attr.window = ~(u32)0; ret = iommu_domain_set_attr(pcfg->iommu_domain, DOMAIN_ATTR_PAMU_STASH, &stash_attr); if (ret < 0) { diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 9318d9f..afdf87b 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -56,7 +56,8 @@ enum stash_target { struct iommu_stash_attribute { u32 cpu; /* cpu number */ - u32 cache; /* cache to stash to: L1,L2,L3 */ + u32 cache; /* cache to stash to L1,L2,L3 */ + u32 window; /* ~0 indicates all windows */ }; struct iommu_omi_attribute { -- cgit v0.10.2