summaryrefslogtreecommitdiff
path: root/drivers/staging/fsl_qbman
diff options
context:
space:
mode:
authorEmil Medve <Emilian.Medve@Freescale.com>2013-04-09 16:34:41 (GMT)
committerFleming Andrew-AFLEMING <AFLEMING@freescale.com>2013-04-10 20:52:31 (GMT)
commita2fe11000bc73db327736378313c2d6c5a2e9173 (patch)
tree055637446c3a741b1daf2abebf1ee6536d8b728f /drivers/staging/fsl_qbman
parent4f1e206f2b70a8795aa27bb291e1fa0019f74aef (diff)
downloadlinux-fsl-qoriq-a2fe11000bc73db327736378313c2d6c5a2e9173.tar.xz
fsl_qman: Set stashing using the IOMMU API
This is using thew new PAMU driver This integration uses a *horrible hack* in order to provide the IOMMU/PAMU driver with a 'struct device'. Making the QMan portal driver nice and proper is part of the upstreaming effort Change-Id: I5f03a3b662949162bff7ac8c7b14ad5fbc0394ce Signed-off-by: Emil Medve <Emilian.Medve@Freescale.com> Change-Id: Ic66bb3904ffa537e497ba00c67e22d851087b435 Reviewed-on: http://git.am.freescale.net:8181/1173 Reviewed-by: Ladouceur Jeffrey-R11498 <Jeffrey.Ladouceur@freescale.com> Reviewed-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com> Tested-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com>
Diffstat (limited to 'drivers/staging/fsl_qbman')
-rw-r--r--drivers/staging/fsl_qbman/dpa_sys.h2
-rw-r--r--drivers/staging/fsl_qbman/dpa_uio.c2
-rw-r--r--drivers/staging/fsl_qbman/qman_driver.c87
-rw-r--r--drivers/staging/fsl_qbman/qman_private.h3
4 files changed, 87 insertions, 7 deletions
diff --git a/drivers/staging/fsl_qbman/dpa_sys.h b/drivers/staging/fsl_qbman/dpa_sys.h
index 8837684..4aa61ae 100644
--- a/drivers/staging/fsl_qbman/dpa_sys.h
+++ b/drivers/staging/fsl_qbman/dpa_sys.h
@@ -88,7 +88,7 @@ struct dpa_uio_vtable {
void (*destroy)(const struct list_head *pcfg, struct uio_info *info);
/* Called when the portal is opened (Qman uses this for rerouting
* stashing to the current cpu) */
- int (*on_open)(const struct list_head *pcfg);
+ int (*on_open)(struct list_head *pcfg);
void (*on_close)(const struct list_head *pcfg);
/* Called when an interrupt fires - must disable interrupts */
void (*on_interrupt)(const struct list_head *pcfg);
diff --git a/drivers/staging/fsl_qbman/dpa_uio.c b/drivers/staging/fsl_qbman/dpa_uio.c
index cdb78db..557be44 100644
--- a/drivers/staging/fsl_qbman/dpa_uio.c
+++ b/drivers/staging/fsl_qbman/dpa_uio.c
@@ -38,7 +38,7 @@ static LIST_HEAD(dpa_uio_list);
struct dpa_uio_info {
const struct dpa_uio_vtable *vtable;
- const struct list_head *pcfg;
+ struct list_head *pcfg;
atomic_t ref; /* exclusive, only one open() at a time */
struct uio_info uio;
struct platform_device *pdev;
diff --git a/drivers/staging/fsl_qbman/qman_driver.c b/drivers/staging/fsl_qbman/qman_driver.c
index 877bee2..90f85cc 100644
--- a/drivers/staging/fsl_qbman/qman_driver.c
+++ b/drivers/staging/fsl_qbman/qman_driver.c
@@ -31,6 +31,8 @@
#include "qman_private.h"
+#include <linux/iommu.h>
+
/* Global variable containing revision id (even on non-control plane systems
* where CCSR isn't available) */
u16 qman_ip_rev;
@@ -348,6 +350,18 @@ static struct qm_portal_config * __init parse_pcfg(struct device_node *node)
return NULL;
}
+ /*
+ * This is a *horrible hack*, but the IOMMU/PAMU driver needs a
+ * 'struct device' in order to get the PAMU stashing setup and the QMan
+ * portal [driver] won't function at all without ring stashing
+ *
+ * Making the QMan portal driver nice and proper is part of the
+ * upstreaming effort
+ */
+ pcfg->dev.bus = &platform_bus_type;
+ pcfg->dev.of_node = node;
+ pcfg->dev.archdata.iommu_domain = NULL;
+
ret = of_address_to_resource(node, DPA_PORTAL_CE,
&pcfg->addr_phys[DPA_PORTAL_CE]);
if (ret) {
@@ -390,7 +404,6 @@ static struct qm_portal_config * __init parse_pcfg(struct device_node *node)
}
pcfg->public_cfg.irq = irq;
pcfg->public_cfg.index = *index;
- pcfg->node = node;
#ifdef CONFIG_FSL_QMAN_CONFIG
/* We need the same LIODN offset for all portals */
qman_liodn_fixup(pcfg->public_cfg.channel);
@@ -429,17 +442,82 @@ static struct qm_portal_config *get_pcfg(struct list_head *list)
return pcfg;
}
-static void portal_set_cpu(const struct qm_portal_config *pcfg, int cpu)
+static void portal_set_cpu(struct qm_portal_config *pcfg, int cpu)
{
+ int ret;
+ int window_count = 1;
+ struct iommu_domain_geometry geom_attr;
+ struct iommu_stash_attribute stash_attr;
+
+ pcfg->iommu_domain = iommu_domain_alloc(&platform_bus_type);
+ if (!pcfg->iommu_domain) {
+ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_alloc() failed",
+ __func__);
+ return;
+ }
+ geom_attr.aperture_start = 0;
+ geom_attr.aperture_end = (1ULL << 36) - 1;
+ geom_attr.force_aperture = true;
+ ret = iommu_domain_set_attr(pcfg->iommu_domain, DOMAIN_ATTR_GEOMETRY,
+ &geom_attr);
+ if (ret < 0) {
+ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_set_attr() = %d",
+ __func__, ret);
+ goto _iommu_domain_free;
+ }
+ ret = iommu_domain_set_attr(pcfg->iommu_domain, DOMAIN_ATTR_WINDOWS,
+ &window_count);
+ if (ret < 0) {
+ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_set_attr() = %d",
+ __func__, ret);
+ goto _iommu_domain_free;
+ }
+ stash_attr.cpu = cpu;
+ stash_attr.cache = IOMMU_ATTR_CACHE_L1;
+ ret = iommu_domain_set_attr(pcfg->iommu_domain, DOMAIN_ATTR_PAMU_STASH,
+ &stash_attr);
+ if (ret < 0) {
+ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_set_attr() = %d",
+ __func__, ret);
+ goto _iommu_domain_free;
+ }
+ ret = iommu_domain_window_enable(pcfg->iommu_domain, 0, 0, 1ULL << 36,
+ IOMMU_READ | IOMMU_WRITE);
+ if (ret < 0) {
+ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_window_enable() = %d",
+ __func__, ret);
+ goto _iommu_domain_free;
+ }
+ ret = iommu_attach_device(pcfg->iommu_domain, &pcfg->dev);
+ if (ret < 0) {
+ pr_err(KBUILD_MODNAME ":%s(): iommu_device_attach() = %d",
+ __func__, ret);
+ goto _iommu_domain_free;
+ }
+ ret = iommu_domain_set_attr(pcfg->iommu_domain, DOMAIN_ATTR_PAMU_ENABLE,
+ &window_count);
+ if (ret < 0) {
+ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_set_attr() = %d",
+ __func__, ret);
+ goto _iommu_detach_device;
+ }
+
#ifdef CONFIG_FSL_QMAN_CONFIG
if (qman_set_sdest(pcfg->public_cfg.channel, cpu))
#endif
pr_warning("Failed to set QMan portal's stash request queue\n");
+
+ return;
+
+_iommu_detach_device:
+ iommu_detach_device(pcfg->iommu_domain, NULL);
+_iommu_domain_free:
+ iommu_domain_free(pcfg->iommu_domain);
}
/* UIO handling callbacks */
#define QMAN_UIO_PREAMBLE() \
- const struct qm_portal_config *pcfg = \
+ struct qm_portal_config *pcfg = \
container_of(__p, struct qm_portal_config, list)
static int qman_uio_cb_init(const struct list_head *__p, struct uio_info *info)
{
@@ -473,7 +551,7 @@ static void qman_uio_cb_destroy(const struct list_head *__p,
* Here it's passed back to us for final clean it up, so de-constify. */
destroy_pcfg((struct qm_portal_config *)pcfg);
}
-static int qman_uio_cb_open(const struct list_head *__p)
+static int qman_uio_cb_open(struct list_head *__p)
{
QMAN_UIO_PREAMBLE();
/* Bind stashing LIODNs to the CPU we are currently executing on, and
@@ -608,6 +686,7 @@ static __init int qman_init(void)
if (ret)
return ret;
}
+
/* Initialise portals. See bman_driver.c for comments */
for_each_compatible_node(dn, NULL, "fsl,qman-portal") {
if (!of_device_is_available(dn))
diff --git a/drivers/staging/fsl_qbman/qman_private.h b/drivers/staging/fsl_qbman/qman_private.h
index e43a41a..cea96d6 100644
--- a/drivers/staging/fsl_qbman/qman_private.h
+++ b/drivers/staging/fsl_qbman/qman_private.h
@@ -115,7 +115,8 @@ struct qm_portal_config {
* [0]==cache-enabled, [1]==cache-inhibited. */
__iomem void *addr_virt[2];
struct resource addr_phys[2];
- struct device_node *node;
+ struct device dev;
+ struct iommu_domain *iommu_domain;
/* Allow these to be joined in lists */
struct list_head list;
/* User-visible portal configuration settings */