From de5791b34591b88911c350d835d8b45d274cc852 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 13 Jul 2017 08:31:46 +0200 Subject: 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"; }; }; }; }; --- .../drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 14 +++++++ linux/drivers/net/ethernet/freescale/fman/mac.c | 13 +++++++ linux/drivers/net/ethernet/freescale/fman/mac.h | 2 + linux/drivers/soc/fsl/qbman/qman.c | 43 ++++++++++++++++++++++ linux/drivers/soc/fsl/qbman/qman_portal.c | 28 ++++++++++++++ linux/drivers/soc/fsl/qbman/qman_priv.h | 6 +++ linux/include/soc/fsl/qman.h | 7 ++++ 7 files changed, 113 insertions(+) (limited to 'linux') 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 -- cgit v1.2.3