summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVarun Sethi <Varun.Sethi@freescale.com>2013-07-22 13:41:28 (GMT)
committerAndy Fleming <afleming@freescale.com>2013-07-24 20:12:26 (GMT)
commit09f24fdb479b51ff7d55c4d3bccda909689a0510 (patch)
treee90930314bed27ac98a6e934d5d4631f8d01fbb5
parent390c78c105419834467ca9809da46947d20d812e (diff)
downloadlinux-fsl-qoriq-09f24fdb479b51ff7d55c4d3bccda909689a0510.tar.xz
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 <Varun.Sethi@freescale.com>
-rw-r--r--drivers/iommu/fsl_pamu.c11
-rw-r--r--drivers/iommu/fsl_pamu.h7
-rw-r--r--drivers/iommu/fsl_pamu_domain.c129
-rw-r--r--drivers/iommu/fsl_pamu_domain.h12
-rw-r--r--drivers/staging/fsl_qbman/qman_driver.c1
-rw-r--r--include/linux/iommu.h3
6 files changed, 112 insertions, 51 deletions
diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
index a96d0c2..75fe204 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,8 +288,15 @@ 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;
+ default:
+ pr_debug("Invalid field, can't update\n");
+ return -EINVAL;
+ }
mb();
return 0;
diff --git a/drivers/iommu/fsl_pamu.h b/drivers/iommu/fsl_pamu.h
index 83cbd26..82a9160 100644
--- a/drivers/iommu/fsl_pamu.h
+++ b/drivers/iommu/fsl_pamu.h
@@ -384,6 +384,11 @@ struct ome {
#define EOE_WWSAOL 0x1e /* Write with stash allocate only and lock */
#define EOE_VALID 0x80
+enum paace_field {
+ PAACE_STASH_FIELD,
+ PAACE_FIELD_MAX,
+};
+
/* Function prototypes */
int pamu_domain_init(void);
int pamu_enable_liodn(int liodn);
@@ -398,7 +403,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..ea93e1f 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;
}
@@ -798,23 +804,45 @@ static int configure_domain_geometry(struct iommu_domain *domain, void *data)
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);
@@ -886,16 +914,24 @@ 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;
+ }
default:
pr_err("Unsupported attribute type\n");
ret = -EINVAL;
@@ -1058,6 +1094,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 +1147,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 683a442..7b6108a 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) {
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index c7cfaf7..2984e6c 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_domain_geometry {