summaryrefslogtreecommitdiffstats
path: root/linux
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2017-07-13 08:31:46 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2017-10-23 09:24:07 +0200
commitde5791b34591b88911c350d835d8b45d274cc852 (patch)
tree20fda544699545de464a9ffcf5ad5716208c0b4a /linux
parente8181287892a255692f08f9f8e5d7df9f530f77d (diff)
downloadrtems-libbsd-de5791b34591b88911c350d835d8b45d274cc852.tar.bz2
dpaa: Add "libbsd,dedicated-portal" to QMan portals
By default, the network interfaces use a pool channel, see dpaa_get_channel() in dpaa_eth_priv_probe(). To enable a dedicated QMan software portal, use libbsd,dedicated-portal = "enabled";. This option is useful for special purpose 10Gbit/s Ethernet processing. / { soc: soc@ffe000000 { fman0: fman@400000 { enet7: ethernet@f2000 { libbsd,dedicated-portal = "enabled"; }; }; }; };
Diffstat (limited to 'linux')
-rw-r--r--linux/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c14
-rw-r--r--linux/drivers/net/ethernet/freescale/fman/mac.c13
-rw-r--r--linux/drivers/net/ethernet/freescale/fman/mac.h2
-rw-r--r--linux/drivers/soc/fsl/qbman/qman.c43
-rw-r--r--linux/drivers/soc/fsl/qbman/qman_portal.c28
-rw-r--r--linux/drivers/soc/fsl/qbman/qman_priv.h6
-rw-r--r--linux/include/soc/fsl/qman.h7
7 files changed, 113 insertions, 0 deletions
diff --git a/linux/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/linux/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index c2e9b378..3861420e 100644
--- a/linux/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/linux/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -3078,6 +3078,17 @@ dpaa_eth_priv_probe(struct platform_device *pdev, struct mac_device *mac_dev)
priv->mac_dev = mac_dev;
+#ifdef __rtems__
+ if (mac_dev->use_dedicated_portal) {
+ struct qman_portal *portal;
+
+ portal = qman_get_dedicated_portal(0);
+ BSD_ASSERT(portal != NULL);
+ mac_dev->portal = portal;
+ channel = qman_portal_get_channel(portal);
+ priv->channel = (u16)channel;
+ } else {
+#endif /* __rtems__ */
channel = dpaa_get_channel();
if (channel < 0) {
dev_err(dev, "dpaa_get_channel() failed\n");
@@ -3091,6 +3102,9 @@ dpaa_eth_priv_probe(struct platform_device *pdev, struct mac_device *mac_dev)
* and add this pool channel to each's dequeue mask.
*/
dpaa_eth_add_channel(priv->channel);
+#ifdef __rtems__
+ }
+#endif /* __rtems__ */
dpaa_fq_setup(priv, &dpaa_fq_cbs, priv->mac_dev->port[TX]);
diff --git a/linux/drivers/net/ethernet/freescale/fman/mac.c b/linux/drivers/net/ethernet/freescale/fman/mac.c
index b058b4ad..e34158e5 100644
--- a/linux/drivers/net/ethernet/freescale/fman/mac.c
+++ b/linux/drivers/net/ethernet/freescale/fman/mac.c
@@ -748,6 +748,16 @@ MODULE_DEVICE_TABLE(of, mac_match);
#ifndef __rtems__
static int mac_probe(struct platform_device *_of_dev)
#else /* __rtems__ */
+static bool
+use_dedicated_portal(const struct device_node *mac_node)
+{
+ const char *dp;
+ int len;
+
+ dp = of_get_property(mac_node, "libbsd,dedicated-portal", &len);
+ return (len > 0 && strcmp(dp, "enabled") == 0);
+}
+
static int mac_probe(device_t _dev, struct platform_device *_of_dev, struct fman *fman)
#endif /* __rtems__ */
{
@@ -1096,6 +1106,9 @@ static int mac_probe(device_t _dev, struct platform_device *_of_dev, struct fman
mac_dev->addr[0], mac_dev->addr[1], mac_dev->addr[2],
mac_dev->addr[3], mac_dev->addr[4], mac_dev->addr[5]);
+#ifdef __rtems__
+ mac_dev->use_dedicated_portal = use_dedicated_portal(mac_node);
+#endif /* __rtems__ */
priv->eth_dev = dpaa_eth_add_device(fman_id, mac_dev, mac_node);
if (IS_ERR(priv->eth_dev)) {
dev_err(dev, "failed to add Ethernet platform device for MAC %d\n",
diff --git a/linux/drivers/net/ethernet/freescale/fman/mac.h b/linux/drivers/net/ethernet/freescale/fman/mac.h
index 066072ab..ba1fcbca 100644
--- a/linux/drivers/net/ethernet/freescale/fman/mac.h
+++ b/linux/drivers/net/ethernet/freescale/fman/mac.h
@@ -85,6 +85,8 @@ struct mac_device {
struct phy_device *(*init_phy)(struct net_device *net_dev,
struct mac_device *mac_dev);
#else /* __rtems__ */
+ bool use_dedicated_portal;
+ struct qman_portal *portal;
void (*adjust_link)(struct mac_device *mac_dev, u16 speed);
#endif /* __rtems__ */
int (*init)(struct mac_device *mac_dev);
diff --git a/linux/drivers/soc/fsl/qbman/qman.c b/linux/drivers/soc/fsl/qbman/qman.c
index acb3a1d9..73e1f09d 100644
--- a/linux/drivers/soc/fsl/qbman/qman.c
+++ b/linux/drivers/soc/fsl/qbman/qman.c
@@ -1281,6 +1281,49 @@ fail_dqrr:
fail_eqcr:
return -EIO;
}
+#ifdef __rtems__
+int
+qman_portal_get_channel(const struct qman_portal *portal)
+{
+
+ if (portal == NULL) {
+ return (-1);
+ }
+
+ return (portal->config->channel);
+}
+
+int
+qman_portal_get_irq(const struct qman_portal *portal)
+{
+
+ if (portal == NULL) {
+ return (-1);
+ }
+
+ return (portal->config->irq);
+}
+
+struct qman_portal *
+qman_create_dedicated_portal(const struct qm_portal_config *c,
+ const struct qman_cgrs *cgrs)
+{
+ struct qman_portal *portal;
+ int err;
+
+ portal = kmalloc(sizeof(*portal), GFP_KERNEL);
+ if (portal == NULL)
+ return (NULL);
+
+ err = qman_create_portal(portal, c, cgrs);
+ if (err != 0) {
+ kfree(portal);
+ return (NULL);
+ }
+
+ return (portal);
+}
+#endif /* __rtems__ */
struct qman_portal *qman_create_affine_portal(const struct qm_portal_config *c,
const struct qman_cgrs *cgrs)
diff --git a/linux/drivers/soc/fsl/qbman/qman_portal.c b/linux/drivers/soc/fsl/qbman/qman_portal.c
index 45aba3a8..b4dd1cd0 100644
--- a/linux/drivers/soc/fsl/qbman/qman_portal.c
+++ b/linux/drivers/soc/fsl/qbman/qman_portal.c
@@ -385,6 +385,33 @@ module_driver(qman_portal_driver,
static struct qm_portal_config qman_configs[MAX_QMAN_PORTALS];
+static LIST_HEAD(qman_free_portals);
+
+struct qman_portal *
+qman_get_dedicated_portal(int cpu)
+{
+ struct qm_portal_config *pcfg;
+ struct qman_portal *p;
+ u32 irq_sources;
+
+ if (list_empty(&qman_free_portals))
+ return (NULL);
+
+ pcfg = list_first_entry(&qman_free_portals, struct qm_portal_config,
+ node);
+ pcfg->cpu = cpu;
+ p = qman_create_dedicated_portal(pcfg, NULL);
+ if (p == NULL)
+ return (NULL);
+
+ list_del(&pcfg->node);
+
+ irq_sources = QM_PIRQ_EQCI | QM_PIRQ_EQRI | QM_PIRQ_MRI | QM_PIRQ_CSCI
+ | QM_PIRQ_DQRI;
+ qman_p_irqsource_add(p, irq_sources);
+ return (p);
+}
+
static bool
is_dequeue_enabled(const struct device_node *dn)
{
@@ -475,6 +502,7 @@ qman_sysinit_portals(void)
qman_portal_update_sdest(pcfg, val);
} else {
pcfg->cpu = -1;
+ list_add_tail(&pcfg->node, &qman_free_portals);
}
node = fdt_next_subnode(fdt, node);
diff --git a/linux/drivers/soc/fsl/qbman/qman_priv.h b/linux/drivers/soc/fsl/qbman/qman_priv.h
index 369ba752..2db10889 100644
--- a/linux/drivers/soc/fsl/qbman/qman_priv.h
+++ b/linux/drivers/soc/fsl/qbman/qman_priv.h
@@ -165,6 +165,8 @@ struct qm_portal_config {
struct iommu_domain *iommu_domain;
/* Allow these to be joined in lists */
struct list_head list;
+#else /* __rtems__ */
+ struct list_head node;
#endif /* __rtems__ */
/* User-visible portal configuration settings */
/* portal is affined to this cpu */
@@ -201,6 +203,10 @@ int qman_wq_alloc(void);
void qman_liodn_fixup(u16 channel);
void qman_set_sdest(u16 channel, unsigned int cpu_idx);
+#ifdef __rtems__
+struct qman_portal *qman_create_dedicated_portal(
+ const struct qm_portal_config *c, const struct qman_cgrs *cgrs);
+#endif /* __rtems__ */
struct qman_portal *qman_create_affine_portal(
const struct qm_portal_config *config,
const struct qman_cgrs *cgrs);
diff --git a/linux/include/soc/fsl/qman.h b/linux/include/soc/fsl/qman.h
index 2504eef9..be4839b0 100644
--- a/linux/include/soc/fsl/qman.h
+++ b/linux/include/soc/fsl/qman.h
@@ -918,6 +918,13 @@ u16 qman_affine_channel(int cpu);
* @cpu: the cpu whose affine portal is the subject of the query
*/
struct qman_portal *qman_get_affine_portal(int cpu);
+#ifdef __rtems__
+struct qman_portal *qman_get_dedicated_portal(int cpu);
+
+int qman_portal_get_channel(const struct qman_portal *portal);
+
+int qman_portal_get_irq(const struct qman_portal *portal);
+#endif /* __rtems__ */
/**
* qman_p_poll_dqrr - process DQRR (fast-path) entries