Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S936271AbcKDQUY (ORCPT ); Fri, 4 Nov 2016 12:20:24 -0400 Received: from mail-db5eur01on0057.outbound.protection.outlook.com ([104.47.2.57]:56422 "EHLO EUR01-DB5-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S932418AbcKDQUW (ORCPT ); Fri, 4 Nov 2016 12:20:22 -0400 From: Ruxandra Ioana Radulescu To: Stuart Yoder , "gregkh@linuxfoundation.org" CC: German Rivera , "devel@driverdev.osuosl.org" , "linux-kernel@vger.kernel.org" , "agraf@suse.de" , "arnd@arndb.de" , Leo Li , Roy Pledge , Haiying Wang , Stuart Yoder Subject: RE: [PATCH 7/9] bus: fsl-mc: dpio: add the DPAA2 DPIO service interface Thread-Topic: [PATCH 7/9] bus: fsl-mc: dpio: add the DPAA2 DPIO service interface Thread-Index: AQHSK6SWqPs9lCe8r0WaY7CuiHZX+6DHaHfwgAGTcUA= Date: Fri, 4 Nov 2016 14:46:40 +0000 Message-ID: References: <1477058509-12547-1-git-send-email-stuart.yoder@nxp.com> <1477058509-12547-8-git-send-email-stuart.yoder@nxp.com> In-Reply-To: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: spf=none (sender IP is ) smtp.mailfrom=ruxandra.radulescu@nxp.com; x-originating-ip: [192.88.146.1] x-ms-office365-filtering-correlation-id: 099ea42b-54ba-470f-1f0b-08d404c16359 x-microsoft-exchange-diagnostics: 1;DB4PR04MB0782;7:Ctuvdnv7gp8VEDoehaq7a0fLtfsWlbnCJJcEGEc/bTJuIHIy2YpO+MiU/I6/CVKwqAItg5MjA0Rl0aQN0qV0jlBZdd5SMAWcJMTeOsnrjREhPoGElGF2vNCyYOgELsvmsfnazpXEQTIcx6NKhnQKkydNGZnvUOf6i2rr4ZTIz1t7L6+uPXyG0IIQZUJq2KH2EnX3qOFo5GJD7nhkA6RHARhkufvZALTVKATzDmr7+DIf9uq3Ql2CpRnLlyTl+j0iTsVZcZmzqc+zg2lMLp8IyYaqWbgmGu4iz2rr3GHWct5XvXIgAoji84JQHo3nmotItpbD17o2h7PsyRGKLQhSRufAGFQ/1p2BMb2JrR/oLKA= x-microsoft-antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:DB4PR04MB0782; x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:(9452136761055)(185117386973197)(275809806118684); x-exchange-antispam-report-cfa-test: BCL:0;PCL:0;RULEID:(6060226)(6045074)(6040176)(601004)(2401047)(5005006)(8121501046)(3002001)(10201501046)(6055026)(6046074)(6061223);SRVR:DB4PR04MB0782;BCL:0;PCL:0;RULEID:;SRVR:DB4PR04MB0782; x-forefront-prvs: 01165471DB x-forefront-antispam-report: SFV:NSPM;SFS:(10009020)(6009001)(7916002)(13464003)(377454003)(189002)(199003)(5001770100001)(10400500002)(68736007)(102836003)(19580405001)(8676002)(122556002)(7846002)(19580395003)(2900100001)(77096005)(586003)(3846002)(66066001)(6116002)(5660300001)(3660700001)(81156014)(81166006)(2950100002)(3280700002)(87936001)(86362001)(7696004)(105586002)(106116001)(4326007)(5002640100001)(101416001)(76176999)(54356999)(33656002)(2906002)(50986999)(189998001)(8936002)(92566002)(305945005)(97736004)(7736002)(106356001)(9686002)(2501003)(5890100001)(74316002)(76576001)(2004002);DIR:OUT;SFP:1101;SCL:1;SRVR:DB4PR04MB0782;H:VI1PR0402MB2847.eurprd04.prod.outlook.com;FPR:;SPF:None;PTR:InfoNoRecords;MX:1;A:1;LANG:en; spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-originalarrivaltime: 04 Nov 2016 14:46:40.5334 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB4PR04MB0782 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from quoted-printable to 8bit by mail.home.local id uA4GKUYi022475 Content-Length: 12925 Lines: 396 > -----Original Message----- > From: Stuart Yoder [mailto:stuart.yoder@nxp.com] > Sent: Friday, October 21, 2016 9:02 AM > To: gregkh@linuxfoundation.org > Cc: German Rivera ; devel@driverdev.osuosl.org; > linux-kernel@vger.kernel.org; agraf@suse.de; arnd@arndb.de; Leo Li > ; Roy Pledge ; Roy Pledge > ; Haiying Wang ; Stuart > Yoder > Subject: [PATCH 7/9] bus: fsl-mc: dpio: add the DPAA2 DPIO service interface > > From: Roy Pledge > > The DPIO service interface handles initialization of DPIO objects > and exports APIs to be used by other DPAA2 object drivers to perform > queuing and buffer management related operations. The service allows > registration of callbacks when frames or notifications are received. > > Signed-off-by: Roy Pledge > Signed-off-by: Haiying Wang > Signed-off-by: Stuart Yoder > --- > drivers/bus/fsl-mc/dpio/Makefile | 2 +- > drivers/bus/fsl-mc/dpio/dpio-service.c | 614 > +++++++++++++++++++++++++++++++++ > include/linux/fsl/dpaa2-io.h | 138 ++++++++ > 3 files changed, 753 insertions(+), 1 deletion(-) > create mode 100644 drivers/bus/fsl-mc/dpio/dpio-service.c > create mode 100644 include/linux/fsl/dpaa2-io.h > > diff --git a/drivers/bus/fsl-mc/dpio/Makefile b/drivers/bus/fsl- > mc/dpio/Makefile > index 6588498..0778da7 100644 > --- a/drivers/bus/fsl-mc/dpio/Makefile > +++ b/drivers/bus/fsl-mc/dpio/Makefile > @@ -6,4 +6,4 @@ subdir-ccflags-y := -Werror > > obj-$(CONFIG_FSL_MC_DPIO) += fsl-mc-dpio.o > > -fsl-mc-dpio-objs := dpio.o qbman-portal.o > +fsl-mc-dpio-objs := dpio.o qbman-portal.o dpio-service.o > diff --git a/drivers/bus/fsl-mc/dpio/dpio-service.c b/drivers/bus/fsl- > mc/dpio/dpio-service.c > new file mode 100644 > index 0000000..7a455a7 > --- /dev/null > +++ b/drivers/bus/fsl-mc/dpio/dpio-service.c > @@ -0,0 +1,614 @@ > +/* > + * Copyright 2014-2016 Freescale Semiconductor Inc. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions are > met: > + * * Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * * Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the > distribution. > + * * Neither the name of Freescale Semiconductor nor the > + * names of its contributors may be used to endorse or promote > products > + * derived from this software without specific prior written permission. > + * > + * > + * ALTERNATIVELY, this software may be distributed under the terms of the > + * GNU General Public License ("GPL") as published by the Free Software > + * Foundation, either version 2 of that License or (at your option) any > + * later version. > + * > + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND > ANY > + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, > THE IMPLIED > + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR > PURPOSE ARE > + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR > ANY > + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR > CONSEQUENTIAL DAMAGES > + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE > GOODS OR SERVICES; > + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > HOWEVER CAUSED AND > + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, > OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF > THE USE OF THIS > + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "dpio.h" > +#include "qbman-portal.h" > + > +struct dpaa2_io { > + atomic_t refs; > + struct dpaa2_io_desc dpio_desc; > + struct qbman_swp_desc swp_desc; > + struct qbman_swp *swp; > + struct list_head node; > + spinlock_t lock_mgmt_cmd; > + spinlock_t lock_notifications; > + struct list_head notifications; > +}; > + > +struct dpaa2_io_store { > + unsigned int max; > + dma_addr_t paddr; > + struct dpaa2_dq *vaddr; > + void *alloced_addr; /* unaligned value from kmalloc() */ > + unsigned int idx; /* position of the next-to-be-returned entry */ > + struct qbman_swp *swp; /* portal used to issue VDQCR */ > + struct device *dev; /* device used for DMA mapping */ > +}; > + > +/* keep a per cpu array of DPIOs for fast access */ > +static struct dpaa2_io *dpio_by_cpu[NR_CPUS]; > +static struct list_head dpio_list = LIST_HEAD_INIT(dpio_list); > +static DEFINE_SPINLOCK(dpio_list_lock); > + > +static inline struct dpaa2_io *service_select_by_cpu(struct dpaa2_io *d, > + int cpu) > +{ > + if (d) > + return d; > + > + if (unlikely(cpu >= NR_CPUS)) > + return NULL; > + > + /* > + * If cpu == -1, choose the current cpu, with no guarantees about > + * potentially being migrated away. > + */ > + if (unlikely(cpu < 0)) > + cpu = smp_processor_id(); > + > + /* If a specific cpu was requested, pick it up immediately */ > + return dpio_by_cpu[cpu]; > +} > + > +static inline struct dpaa2_io *service_select(struct dpaa2_io *d) > +{ > + if (d) > + return d; > + > + spin_lock(&dpio_list_lock); > + d = list_entry(dpio_list.next, struct dpaa2_io, node); > + list_del(&d->node); > + list_add_tail(&d->node, &dpio_list); > + spin_unlock(&dpio_list_lock); > + > + return d; > +} > + > +/** > + * dpaa2_io_create() - create a dpaa2_io object. > + * @desc: the dpaa2_io descriptor > + * > + * Activates a "struct dpaa2_io" corresponding to the given config of an > actual > + * DPIO object. > + * > + * Return a valid dpaa2_io object for success, or NULL for failure. > + */ > +struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc) > +{ > + struct dpaa2_io *obj = kmalloc(sizeof(*obj), GFP_KERNEL); > + > + if (!obj) > + return NULL; > + > + /* check if CPU is out of range (-1 means any cpu) */ > + if (desc->cpu >= NR_CPUS) > + return NULL; > + > + atomic_set(&obj->refs, 1); > + obj->dpio_desc = *desc; > + obj->swp_desc.cena_bar = obj->dpio_desc.regs_cena; > + obj->swp_desc.cinh_bar = obj->dpio_desc.regs_cinh; > + obj->swp_desc.qman_version = obj->dpio_desc.qman_version; > + obj->swp = qbman_swp_init(&obj->swp_desc); > + > + if (!obj->swp) { > + kfree(obj); > + return NULL; > + } > + > + INIT_LIST_HEAD(&obj->node); > + spin_lock_init(&obj->lock_mgmt_cmd); > + spin_lock_init(&obj->lock_notifications); > + INIT_LIST_HEAD(&obj->notifications); > + > + /* For now only enable DQRR interrupts */ > + qbman_swp_interrupt_set_trigger(obj->swp, > + QBMAN_SWP_INTERRUPT_DQRI); > + qbman_swp_interrupt_clear_status(obj->swp, 0xffffffff); > + if (obj->dpio_desc.receives_notifications) > + qbman_swp_push_set(obj->swp, 0, 1); > + > + spin_lock(&dpio_list_lock); > + list_add_tail(&obj->node, &dpio_list); > + if (desc->cpu >= 0 && !dpio_by_cpu[desc->cpu]) > + dpio_by_cpu[desc->cpu] = obj; > + spin_unlock(&dpio_list_lock); > + > + return obj; > +} > +EXPORT_SYMBOL(dpaa2_io_create); > + > +/** > + * dpaa2_io_down() - release the dpaa2_io object. > + * @d: the dpaa2_io object to be released. > + * > + * The "struct dpaa2_io" type can represent an individual DPIO object (as > + * described by "struct dpaa2_io_desc") or an instance of a "DPIO service", > + * which can be used to group/encapsulate multiple DPIO objects. In all > cases, > + * each handle obtained should be released using this function. > + */ > +void dpaa2_io_down(struct dpaa2_io *d) > +{ > + if (!atomic_dec_and_test(&d->refs)) > + return; > + kfree(d); > +} > +EXPORT_SYMBOL(dpaa2_io_down); > + > +#define DPAA_POLL_MAX 32 > + > +/** > + * dpaa2_io_irq() - ISR for DPIO interrupts > + * > + * @obj: the given DPIO object. > + * > + * Return IRQ_HANDLED for success or IRQ_NONE if there > + * were no pending interrupts. > + */ > +irqreturn_t dpaa2_io_irq(struct dpaa2_io *obj) > +{ > + const struct dpaa2_dq *dq; > + int max = 0; > + struct qbman_swp *swp; > + u32 status; > + > + swp = obj->swp; > + status = qbman_swp_interrupt_read_status(swp); > + if (!status) > + return IRQ_NONE; > + > + dq = qbman_swp_dqrr_next(swp); > + while (dq) { > + if (qbman_result_is_SCN(dq)) { > + struct dpaa2_io_notification_ctx *ctx; > + u64 q64; > + > + q64 = qbman_result_SCN_ctx(dq); > + ctx = (void *)q64; > + ctx->cb(ctx); > + } else { > + pr_crit("fsl-mc-dpio: Unrecognised/ignored DQRR > entry\n"); > + } > + qbman_swp_dqrr_consume(swp, dq); > + ++max; > + if (max > DPAA_POLL_MAX) > + goto done; > + dq = qbman_swp_dqrr_next(swp); > + } > +done: > + qbman_swp_interrupt_clear_status(swp, status); > + qbman_swp_interrupt_set_inhibit(swp, 0); > + return IRQ_HANDLED; > +} > +EXPORT_SYMBOL(dpaa2_io_irq); > + > +/** > + * dpaa2_io_service_register() - Prepare for servicing of FQDAN or CDAN > + * notifications on the given DPIO service. > + * @d: the given DPIO service. > + * @ctx: the notification context. > + * > + * The caller should make the MC command to attach a DPAA2 object to > + * a DPIO after this function completes successfully. In that way: > + * (a) The DPIO service is "ready" to handle a notification arrival > + * (which might happen before the "attach" command to MC has > + * returned control of execution back to the caller) > + * (b) The DPIO service can provide back to the caller the 'dpio_id' and > + * 'qman64' parameters that it should pass along in the MC command > + * in order for the object to be configured to produce the right > + * notification fields to the DPIO service. > + * > + * Return 0 for success, or -ENODEV for failure. > + */ > +int dpaa2_io_service_register(struct dpaa2_io *d, > + struct dpaa2_io_notification_ctx *ctx) > +{ > + unsigned long irqflags; > + > + d = service_select_by_cpu(d, ctx->desired_cpu); > + if (!d) > + return -ENODEV; > + > + ctx->dpio_id = d->dpio_desc.dpio_id; > + ctx->qman64 = (u64)ctx; > + ctx->dpio_private = d; > + spin_lock_irqsave(&d->lock_notifications, irqflags); > + list_add(&ctx->node, &d->notifications); > + spin_unlock_irqrestore(&d->lock_notifications, irqflags); > + > + /* Enable the generation of CDAN notifications */ > + if (ctx->is_cdan) > + qbman_swp_CDAN_set_context_enable(d->swp, > + (u16)ctx->id, > + ctx->qman64); > + return 0; > +} > +EXPORT_SYMBOL(dpaa2_io_service_register); > + > +/** > + * dpaa2_io_service_deregister - The opposite of 'register'. > + * @service: the given DPIO service. > + * @ctx: the notification context. > + * > + * This function should be called only after sending the MC command to > + * to detach the notification-producing device from the DPIO. > + */ > +void dpaa2_io_service_deregister(struct dpaa2_io *service, > + struct dpaa2_io_notification_ctx *ctx) > +{ > + struct dpaa2_io *d = ctx->dpio_private; > + unsigned long irqflags; > + > + if (ctx->is_cdan) > + qbman_swp_CDAN_disable(d->swp, (u16)ctx->id); > + > + spin_lock_irqsave(&d->lock_notifications, irqflags); > + list_del(&ctx->node); > + spin_unlock_irqrestore(&d->lock_notifications, irqflags); > +} > +EXPORT_SYMBOL(dpaa2_io_service_deregister); > + > +/** > + * dpaa2_io_service_rearm() - Rearm the notification for the given DPIO > service. > + * @service: the given DPIO service. > + * @ctx: the notification context. > + * > + * Once a FQDAN/CDAN has been produced, the corresponding FQ/channel > is > + * considered "disarmed". Ie. the user can issue pull dequeue operations on > that > + * traffic source for as long as it likes. Eventually it may wish to "rearm" > + * that source to allow it to produce another FQDAN/CDAN, that's what this > + * function achieves. > + * > + * Return 0 for success. > + */ > +int dpaa2_io_service_rearm(struct dpaa2_io *d, > + struct dpaa2_io_notification_ctx *ctx) > +{ > + unsigned long irqflags; > + int err; > + > + d = service_select(d); Why not select the DPIO based on ctx->desired_cpu, like in the initial notification register? Thanks, Ioana > + if (!unlikely(d)) > + return -ENODEV; > + > + spin_lock_irqsave(&d->lock_mgmt_cmd, irqflags); > + if (ctx->is_cdan) > + err = qbman_swp_CDAN_enable(d->swp, (u16)ctx->id); > + else > + err = qbman_swp_fq_schedule(d->swp, ctx->id); > + spin_unlock_irqrestore(&d->lock_mgmt_cmd, irqflags); > + > + return err; > +} > +EXPORT_SYMBOL(dpaa2_io_service_rearm); [...]