diff options
author | Andy Fleming <afleming@freescale.com> | 2013-07-24 20:23:52 (GMT) |
---|---|---|
committer | Andy Fleming <afleming@freescale.com> | 2013-07-24 20:23:52 (GMT) |
commit | a8d022f84c57846be4b39ff740f86c8454c78b52 (patch) | |
tree | e6b54eff890fdc682a0ffda940f051fc6229b756 /drivers | |
parent | d14ad9193b5971f9028e63d45c3f6827c3ba8a2e (diff) | |
parent | e9f747c6bbdd5aa6642e2921ae1fd1f10e8f8a43 (diff) | |
download | linux-fsl-qoriq-a8d022f84c57846be4b39ff740f86c8454c78b52.tar.xz |
Merge remote-tracking branch 'fsl_devel/b4860rev2' into sdk1.4
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/iommu/fsl_pamu.c | 53 | ||||
-rw-r--r-- | drivers/iommu/fsl_pamu.h | 8 | ||||
-rw-r--r-- | drivers/iommu/fsl_pamu_domain.c | 187 | ||||
-rw-r--r-- | drivers/iommu/fsl_pamu_domain.h | 12 | ||||
-rw-r--r-- | drivers/staging/fsl_qbman/qman_driver.c | 1 |
5 files changed, 206 insertions, 55 deletions
diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c index 1f69fd1..4d466d6 100644 --- a/drivers/iommu/fsl_pamu.c +++ b/drivers/iommu/fsl_pamu.c @@ -35,11 +35,6 @@ #include "fsl_pamu.h" -/* define indexes for each operation mapping scenario */ -#define OMI_QMAN 0x00 -#define OMI_FMAN 0x01 -#define OMI_QMAN_PRIV 0x02 -#define OMI_CAAM 0x03 /* Handling access violations */ #define make64(high, low) (((u64)(high) << 32) | (low)) @@ -278,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; @@ -293,8 +288,19 @@ 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: + set_bf(paace->impl_attr, PAACE_IA_CID, value); + break; + case PAACE_OMI_FIELD: + set_bf(paace->impl_attr, PAACE_IA_OTM, PAACE_OTM_INDEXED); + paace->op_encode.index_ot.omi = value; + break; + default: + pr_debug("Invalid field, can't update\n"); + return -EINVAL; + } mb(); return 0; @@ -611,6 +617,7 @@ found_cpu_node: #define QMAN_PORTAL_PAACE 2 #define BMAN_PAACE 3 #define FMAN_PAACE 4 +#define PMAN_PAACE 5 /** * Setup operation mapping and stash destinations for QMAN and QMAN portal. @@ -646,6 +653,10 @@ static void setup_dpaa_paace(struct paace *ppaace, int paace_type) set_bf(ppaace->impl_attr, PAACE_IA_CID, get_stash_id(IOMMU_ATTR_CACHE_L3, 0)); break; + case PMAN_PAACE: + set_bf(ppaace->impl_attr, PAACE_IA_OTM, PAACE_OTM_INDEXED); + ppaace->op_encode.index_ot.omi = OMI_PMAN; + break; } } @@ -690,6 +701,32 @@ static void __init setup_omt(struct ome *omt) ome = &omt[OMI_CAAM]; ome->moe[IOE_READ_IDX] = EOE_VALID | EOE_READI; ome->moe[IOE_WRITE_IDX] = EOE_VALID | EOE_WRITE; + + /* Configure OMI_PMAN */ + ome = &omt[OMI_PMAN]; + ome->moe[IOE_DIRECT0_IDX] = EOE_LDEC | EOE_VALID; + ome->moe[IOE_DIRECT1_IDX] = EOE_LDEC | EOE_VALID; + + /* Configure OMI_DMA */ + ome = &omt[OMI_DMA]; + ome->moe[IOE_READ_IDX] = EOE_VALID | EOE_RSA; + ome->moe[IOE_EREAD0_IDX] = EOE_VALID | EOE_RSA; + ome->moe[IOE_WRITE_IDX] = EOE_VALID | EOE_WWSA; + ome->moe[IOE_EWRITE0_IDX] = EOE_VALID | EOE_WWSA; + + /* Configure OMI_DMA_READI */ + ome = &omt[OMI_DMA_READI]; + ome->moe[IOE_READ_IDX] = EOE_VALID | EOE_READI; + ome->moe[IOE_EREAD0_IDX] = EOE_VALID | EOE_READI; + ome->moe[IOE_WRITE_IDX] = EOE_VALID | EOE_WWSA; + ome->moe[IOE_EWRITE0_IDX] = EOE_VALID | EOE_WWSA; + + /* Configure OMI_MAPLE */ + ome = &omt[OMI_MAPLE]; + ome->moe[IOE_READ_IDX] = EOE_VALID | EOE_RSA; + ome->moe[IOE_EREAD0_IDX] = EOE_VALID | EOE_RSA; + ome->moe[IOE_WRITE_IDX] = EOE_VALID | EOE_WWSA; + ome->moe[IOE_EWRITE0_IDX] = EOE_VALID | EOE_WWSA; } /* @@ -809,6 +846,8 @@ static void __init setup_liodns(void) setup_dpaa_paace(ppaace, QMAN_PAACE); if (of_device_is_compatible(node, "fsl,bman")) setup_dpaa_paace(ppaace, BMAN_PAACE); + if (of_device_is_compatible(node, "fsl,pman")) + setup_dpaa_paace(ppaace, PMAN_PAACE); #ifdef CONFIG_FSL_FMAN_CPC_STASH if (of_device_is_compatible(node, "fsl,fman-port-10g-rx") || of_device_is_compatible(node, "fsl,fman-port-1g-rx")) diff --git a/drivers/iommu/fsl_pamu.h b/drivers/iommu/fsl_pamu.h index 83cbd26..fd9dd6d 100644 --- a/drivers/iommu/fsl_pamu.h +++ b/drivers/iommu/fsl_pamu.h @@ -384,6 +384,12 @@ struct ome { #define EOE_WWSAOL 0x1e /* Write with stash allocate only and lock */ #define EOE_VALID 0x80 +enum paace_field { + PAACE_STASH_FIELD, + PAACE_OMI_FIELD, + PAACE_FIELD_MAX, +}; + /* Function prototypes */ int pamu_domain_init(void); int pamu_enable_liodn(int liodn); @@ -398,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 5b54505..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; } @@ -794,27 +800,92 @@ static int configure_domain_geometry(struct iommu_domain *domain, void *data) return 0; } +/* Set the domain operation mapping attribute */ +static int configure_domain_op_map(struct fsl_dma_domain *dma_domain, + void *data) +{ + struct dma_window *wnd; + unsigned long flags; + struct pamu_attr_info attr_info; + int ret, i; + struct iommu_omi_attribute *omi_attr = data; + + spin_lock_irqsave(&dma_domain->domain_lock, flags); + + if (!dma_domain->win_arr) { + pr_err("Number of windows not configured\n"); + spin_unlock_irqrestore(&dma_domain->domain_lock, flags); + return -ENODEV; + } + + if (omi_attr->omi >= OMI_MAX) { + pr_err("Invalid operation mapping index\n"); + spin_unlock_irqrestore(&dma_domain->domain_lock, flags); + return -EINVAL; + } + + if (~omi_attr->window == 0) { + wnd = &dma_domain->win_arr[0]; + for (i = 0; i < dma_domain->win_cnt; i++) + wnd[i].omi = omi_attr->omi; + } else { + wnd = &dma_domain->win_arr[omi_attr->window]; + wnd->omi = omi_attr->omi; + } + + attr_info.window = omi_attr->window; + attr_info.field = PAACE_OMI_FIELD; + attr_info.value = omi_attr->omi; + ret = update_domain_attr(dma_domain, &attr_info); + + spin_unlock_irqrestore(&dma_domain->domain_lock, flags); + + return ret; +} + /* Set the domain stash attribute */ 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); @@ -869,6 +940,9 @@ static int fsl_pamu_set_domain_attr(struct iommu_domain *domain, case DOMAIN_ATTR_PAMU_ENABLE: ret = configure_domain_dma_state(dma_domain, *(int *)data); break; + case DOMAIN_ATTR_PAMU_OP_MAP: + ret = configure_domain_op_map(dma_domain, data); + break; default: pr_err("Unsupported attribute type\n"); ret = -EINVAL; @@ -886,16 +960,36 @@ 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; case DOMAIN_ATTR_FSL_PAMUV1: *(int *)data = DOMAIN_ATTR_FSL_PAMUV1; break; + case DOMAIN_ATTR_PAMU_STASH: { + struct iommu_stash_attribute *stash_attr = data; + struct dma_window *wnd; + + if (stash_attr->window >= dma_domain->win_cnt || + ~stash_attr->window == 0) + return -EINVAL; + + wnd = &dma_domain->win_arr[stash_attr->window]; + memcpy(stash_attr, &wnd->stash_attr, sizeof(struct iommu_stash_attribute)); + break; + } + case DOMAIN_ATTR_PAMU_OP_MAP: { + struct iommu_omi_attribute *omi_attr = data; + struct dma_window *wnd; + + if (omi_attr->window >= dma_domain->win_cnt || + ~omi_attr->window == 0) + return -EINVAL; + + wnd = &dma_domain->win_arr[omi_attr->window]; + omi_attr->omi = wnd->omi; + break; + } default: pr_err("Unsupported attribute type\n"); ret = -EINVAL; @@ -1058,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; @@ -1101,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 d564037..6d879a4 100644 --- a/drivers/staging/fsl_qbman/qman_driver.c +++ b/drivers/staging/fsl_qbman/qman_driver.c @@ -488,6 +488,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) { |