From c89105c9b39037bbf2aca0614e39afe176e867c5 Mon Sep 17 00:00:00 2001 From: Roy Pledge Date: Tue, 24 Jul 2018 09:21:29 -0500 Subject: staging: fsl-mc: Move DPIO from staging to drivers/soc/fsl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the NXP DPIO (Datapath I/O Driver) out of the drivers/staging directory and into the drivers/soc/fsl directory. The DPIO driver enables access to Queue and Buffer Manager (QBMAN) hardware on NXP DPAA2 devices. This is a prerequisite to moving the DPAA2 Ethernet driver out of staging. Signed-off-by: Roy Pledge Reviewed-by: Horia Geantă Reviewed-by: Ioana Radulescu Signed-off-by: Li Yang --- drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h | 4 +- drivers/staging/fsl-mc/bus/Kconfig | 9 - drivers/staging/fsl-mc/bus/Makefile | 2 - drivers/staging/fsl-mc/bus/dpio/Makefile | 8 - drivers/staging/fsl-mc/bus/dpio/dpio-cmd.h | 49 -- drivers/staging/fsl-mc/bus/dpio/dpio-driver.c | 281 ------- drivers/staging/fsl-mc/bus/dpio/dpio-driver.txt | 135 --- drivers/staging/fsl-mc/bus/dpio/dpio-service.c | 545 ------------ drivers/staging/fsl-mc/bus/dpio/dpio.c | 198 ----- drivers/staging/fsl-mc/bus/dpio/dpio.h | 83 -- drivers/staging/fsl-mc/bus/dpio/qbman-portal.c | 1005 ----------------------- drivers/staging/fsl-mc/bus/dpio/qbman-portal.h | 444 ---------- drivers/staging/fsl-mc/include/dpaa2-fd.h | 438 ---------- drivers/staging/fsl-mc/include/dpaa2-global.h | 177 ---- drivers/staging/fsl-mc/include/dpaa2-io.h | 115 --- 15 files changed, 2 insertions(+), 3491 deletions(-) delete mode 100644 drivers/staging/fsl-mc/bus/dpio/Makefile delete mode 100644 drivers/staging/fsl-mc/bus/dpio/dpio-cmd.h delete mode 100644 drivers/staging/fsl-mc/bus/dpio/dpio-driver.c delete mode 100644 drivers/staging/fsl-mc/bus/dpio/dpio-driver.txt delete mode 100644 drivers/staging/fsl-mc/bus/dpio/dpio-service.c delete mode 100644 drivers/staging/fsl-mc/bus/dpio/dpio.c delete mode 100644 drivers/staging/fsl-mc/bus/dpio/dpio.h delete mode 100644 drivers/staging/fsl-mc/bus/dpio/qbman-portal.c delete mode 100644 drivers/staging/fsl-mc/bus/dpio/qbman-portal.h delete mode 100644 drivers/staging/fsl-mc/include/dpaa2-fd.h delete mode 100644 drivers/staging/fsl-mc/include/dpaa2-global.h delete mode 100644 drivers/staging/fsl-mc/include/dpaa2-io.h (limited to 'drivers/staging') diff --git a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h index 9269cb05a84b..f2917b55b85a 100644 --- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h @@ -37,8 +37,8 @@ #include #include -#include "../../fsl-mc/include/dpaa2-io.h" -#include "../../fsl-mc/include/dpaa2-fd.h" +#include +#include #include "dpni.h" #include "dpni-cmd.h" diff --git a/drivers/staging/fsl-mc/bus/Kconfig b/drivers/staging/fsl-mc/bus/Kconfig index 342453035269..90f234deb1de 100644 --- a/drivers/staging/fsl-mc/bus/Kconfig +++ b/drivers/staging/fsl-mc/bus/Kconfig @@ -5,12 +5,3 @@ # Copyright (C) 2014-2016 Freescale Semiconductor, Inc. # -config FSL_MC_DPIO - tristate "QorIQ DPAA2 DPIO driver" - depends on FSL_MC_BUS - help - Driver for the DPAA2 DPIO object. A DPIO provides queue and - buffer management facilities for software to interact with - other DPAA2 objects. This driver does not expose the DPIO - objects individually, but groups them under a service layer - API. diff --git a/drivers/staging/fsl-mc/bus/Makefile b/drivers/staging/fsl-mc/bus/Makefile index 21d8ebc8ce21..2141e4b590b2 100644 --- a/drivers/staging/fsl-mc/bus/Makefile +++ b/drivers/staging/fsl-mc/bus/Makefile @@ -5,5 +5,3 @@ # Copyright (C) 2014 Freescale Semiconductor, Inc. # -# MC DPIO driver -obj-$(CONFIG_FSL_MC_DPIO) += dpio/ diff --git a/drivers/staging/fsl-mc/bus/dpio/Makefile b/drivers/staging/fsl-mc/bus/dpio/Makefile deleted file mode 100644 index b9ff24c76582..000000000000 --- a/drivers/staging/fsl-mc/bus/dpio/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# QorIQ DPAA2 DPIO driver -# - -obj-$(CONFIG_FSL_MC_DPIO) += fsl-mc-dpio.o - -fsl-mc-dpio-objs := dpio.o qbman-portal.o dpio-service.o dpio-driver.o diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio-cmd.h b/drivers/staging/fsl-mc/bus/dpio/dpio-cmd.h deleted file mode 100644 index ab8f82ee7ee5..000000000000 --- a/drivers/staging/fsl-mc/bus/dpio/dpio-cmd.h +++ /dev/null @@ -1,49 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ -/* - * Copyright 2013-2016 Freescale Semiconductor Inc. - * Copyright 2016 NXP - * - */ -#ifndef _FSL_DPIO_CMD_H -#define _FSL_DPIO_CMD_H - -/* DPIO Version */ -#define DPIO_VER_MAJOR 4 -#define DPIO_VER_MINOR 2 - -/* Command Versioning */ - -#define DPIO_CMD_ID_OFFSET 4 -#define DPIO_CMD_BASE_VERSION 1 - -#define DPIO_CMD(id) (((id) << DPIO_CMD_ID_OFFSET) | DPIO_CMD_BASE_VERSION) - -/* Command IDs */ -#define DPIO_CMDID_CLOSE DPIO_CMD(0x800) -#define DPIO_CMDID_OPEN DPIO_CMD(0x803) -#define DPIO_CMDID_GET_API_VERSION DPIO_CMD(0xa03) -#define DPIO_CMDID_ENABLE DPIO_CMD(0x002) -#define DPIO_CMDID_DISABLE DPIO_CMD(0x003) -#define DPIO_CMDID_GET_ATTR DPIO_CMD(0x004) - -struct dpio_cmd_open { - __le32 dpio_id; -}; - -#define DPIO_CHANNEL_MODE_MASK 0x3 - -struct dpio_rsp_get_attr { - /* cmd word 0 */ - __le32 id; - __le16 qbman_portal_id; - u8 num_priorities; - u8 channel_mode; - /* cmd word 1 */ - __le64 qbman_portal_ce_addr; - /* cmd word 2 */ - __le64 qbman_portal_ci_addr; - /* cmd word 3 */ - __le32 qbman_version; -}; - -#endif /* _FSL_DPIO_CMD_H */ diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio-driver.c b/drivers/staging/fsl-mc/bus/dpio/dpio-driver.c deleted file mode 100644 index 11a90a90d827..000000000000 --- a/drivers/staging/fsl-mc/bus/dpio/dpio-driver.c +++ /dev/null @@ -1,281 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -/* - * Copyright 2014-2016 Freescale Semiconductor Inc. - * Copyright NXP 2016 - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "../../include/dpaa2-io.h" - -#include "qbman-portal.h" -#include "dpio.h" -#include "dpio-cmd.h" - -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_AUTHOR("Freescale Semiconductor, Inc"); -MODULE_DESCRIPTION("DPIO Driver"); - -struct dpio_priv { - struct dpaa2_io *io; -}; - -static irqreturn_t dpio_irq_handler(int irq_num, void *arg) -{ - struct device *dev = (struct device *)arg; - struct dpio_priv *priv = dev_get_drvdata(dev); - - return dpaa2_io_irq(priv->io); -} - -static void unregister_dpio_irq_handlers(struct fsl_mc_device *dpio_dev) -{ - struct fsl_mc_device_irq *irq; - - irq = dpio_dev->irqs[0]; - - /* clear the affinity hint */ - irq_set_affinity_hint(irq->msi_desc->irq, NULL); -} - -static int register_dpio_irq_handlers(struct fsl_mc_device *dpio_dev, int cpu) -{ - struct dpio_priv *priv; - int error; - struct fsl_mc_device_irq *irq; - cpumask_t mask; - - priv = dev_get_drvdata(&dpio_dev->dev); - - irq = dpio_dev->irqs[0]; - error = devm_request_irq(&dpio_dev->dev, - irq->msi_desc->irq, - dpio_irq_handler, - 0, - dev_name(&dpio_dev->dev), - &dpio_dev->dev); - if (error < 0) { - dev_err(&dpio_dev->dev, - "devm_request_irq() failed: %d\n", - error); - return error; - } - - /* set the affinity hint */ - cpumask_clear(&mask); - cpumask_set_cpu(cpu, &mask); - if (irq_set_affinity_hint(irq->msi_desc->irq, &mask)) - dev_err(&dpio_dev->dev, - "irq_set_affinity failed irq %d cpu %d\n", - irq->msi_desc->irq, cpu); - - return 0; -} - -static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev) -{ - struct dpio_attr dpio_attrs; - struct dpaa2_io_desc desc; - struct dpio_priv *priv; - int err = -ENOMEM; - struct device *dev = &dpio_dev->dev; - static int next_cpu = -1; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - goto err_priv_alloc; - - dev_set_drvdata(dev, priv); - - err = fsl_mc_portal_allocate(dpio_dev, 0, &dpio_dev->mc_io); - if (err) { - dev_dbg(dev, "MC portal allocation failed\n"); - err = -EPROBE_DEFER; - goto err_priv_alloc; - } - - err = dpio_open(dpio_dev->mc_io, 0, dpio_dev->obj_desc.id, - &dpio_dev->mc_handle); - if (err) { - dev_err(dev, "dpio_open() failed\n"); - goto err_open; - } - - err = dpio_get_attributes(dpio_dev->mc_io, 0, dpio_dev->mc_handle, - &dpio_attrs); - if (err) { - dev_err(dev, "dpio_get_attributes() failed %d\n", err); - goto err_get_attr; - } - desc.qman_version = dpio_attrs.qbman_version; - - err = dpio_enable(dpio_dev->mc_io, 0, dpio_dev->mc_handle); - if (err) { - dev_err(dev, "dpio_enable() failed %d\n", err); - goto err_get_attr; - } - - /* initialize DPIO descriptor */ - desc.receives_notifications = dpio_attrs.num_priorities ? 1 : 0; - desc.has_8prio = dpio_attrs.num_priorities == 8 ? 1 : 0; - desc.dpio_id = dpio_dev->obj_desc.id; - - /* get the cpu to use for the affinity hint */ - if (next_cpu == -1) - next_cpu = cpumask_first(cpu_online_mask); - else - next_cpu = cpumask_next(next_cpu, cpu_online_mask); - - if (!cpu_possible(next_cpu)) { - dev_err(dev, "probe failed. Number of DPIOs exceeds NR_CPUS.\n"); - err = -ERANGE; - goto err_allocate_irqs; - } - desc.cpu = next_cpu; - - /* - * Set the CENA regs to be the cache inhibited area of the portal to - * avoid coherency issues if a user migrates to another core. - */ - desc.regs_cena = devm_memremap(dev, dpio_dev->regions[1].start, - resource_size(&dpio_dev->regions[1]), - MEMREMAP_WC); - if (IS_ERR(desc.regs_cena)) { - dev_err(dev, "devm_memremap failed\n"); - err = PTR_ERR(desc.regs_cena); - goto err_allocate_irqs; - } - - desc.regs_cinh = devm_ioremap(dev, dpio_dev->regions[1].start, - resource_size(&dpio_dev->regions[1])); - if (!desc.regs_cinh) { - err = -ENOMEM; - dev_err(dev, "devm_ioremap failed\n"); - goto err_allocate_irqs; - } - - err = fsl_mc_allocate_irqs(dpio_dev); - if (err) { - dev_err(dev, "fsl_mc_allocate_irqs failed. err=%d\n", err); - goto err_allocate_irqs; - } - - err = register_dpio_irq_handlers(dpio_dev, desc.cpu); - if (err) - goto err_register_dpio_irq; - - priv->io = dpaa2_io_create(&desc); - if (!priv->io) { - dev_err(dev, "dpaa2_io_create failed\n"); - err = -ENOMEM; - goto err_dpaa2_io_create; - } - - dev_info(dev, "probed\n"); - dev_dbg(dev, " receives_notifications = %d\n", - desc.receives_notifications); - dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle); - fsl_mc_portal_free(dpio_dev->mc_io); - - return 0; - -err_dpaa2_io_create: - unregister_dpio_irq_handlers(dpio_dev); -err_register_dpio_irq: - fsl_mc_free_irqs(dpio_dev); -err_allocate_irqs: - dpio_disable(dpio_dev->mc_io, 0, dpio_dev->mc_handle); -err_get_attr: - dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle); -err_open: - fsl_mc_portal_free(dpio_dev->mc_io); -err_priv_alloc: - return err; -} - -/* Tear down interrupts for a given DPIO object */ -static void dpio_teardown_irqs(struct fsl_mc_device *dpio_dev) -{ - unregister_dpio_irq_handlers(dpio_dev); - fsl_mc_free_irqs(dpio_dev); -} - -static int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev) -{ - struct device *dev; - struct dpio_priv *priv; - int err; - - dev = &dpio_dev->dev; - priv = dev_get_drvdata(dev); - - dpaa2_io_down(priv->io); - - dpio_teardown_irqs(dpio_dev); - - err = fsl_mc_portal_allocate(dpio_dev, 0, &dpio_dev->mc_io); - if (err) { - dev_err(dev, "MC portal allocation failed\n"); - goto err_mcportal; - } - - err = dpio_open(dpio_dev->mc_io, 0, dpio_dev->obj_desc.id, - &dpio_dev->mc_handle); - if (err) { - dev_err(dev, "dpio_open() failed\n"); - goto err_open; - } - - dpio_disable(dpio_dev->mc_io, 0, dpio_dev->mc_handle); - - dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle); - - fsl_mc_portal_free(dpio_dev->mc_io); - - return 0; - -err_open: - fsl_mc_portal_free(dpio_dev->mc_io); -err_mcportal: - return err; -} - -static const struct fsl_mc_device_id dpaa2_dpio_match_id_table[] = { - { - .vendor = FSL_MC_VENDOR_FREESCALE, - .obj_type = "dpio", - }, - { .vendor = 0x0 } -}; - -static struct fsl_mc_driver dpaa2_dpio_driver = { - .driver = { - .name = KBUILD_MODNAME, - .owner = THIS_MODULE, - }, - .probe = dpaa2_dpio_probe, - .remove = dpaa2_dpio_remove, - .match_id_table = dpaa2_dpio_match_id_table -}; - -static int dpio_driver_init(void) -{ - return fsl_mc_driver_register(&dpaa2_dpio_driver); -} - -static void dpio_driver_exit(void) -{ - fsl_mc_driver_unregister(&dpaa2_dpio_driver); -} -module_init(dpio_driver_init); -module_exit(dpio_driver_exit); diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio-driver.txt b/drivers/staging/fsl-mc/bus/dpio/dpio-driver.txt deleted file mode 100644 index 72ba9da3d179..000000000000 --- a/drivers/staging/fsl-mc/bus/dpio/dpio-driver.txt +++ /dev/null @@ -1,135 +0,0 @@ -Copyright 2016 NXP - -Introduction ------------- - -A DPAA2 DPIO (Data Path I/O) is a hardware object that provides -interfaces to enqueue and dequeue frames to/from network interfaces -and other accelerators. A DPIO also provides hardware buffer -pool management for network interfaces. - -This document provides an overview the Linux DPIO driver, its -subcomponents, and its APIs. - -See Documentation/networking/dpaa2/overview.rst for a general overview of DPAA2 -and the general DPAA2 driver architecture in Linux. - -Driver Overview ---------------- - -The DPIO driver is bound to DPIO objects discovered on the fsl-mc bus and -provides services that: - A) allow other drivers, such as the Ethernet driver, to enqueue and dequeue - frames for their respective objects - B) allow drivers to register callbacks for data availability notifications - when data becomes available on a queue or channel - C) allow drivers to manage hardware buffer pools - -The Linux DPIO driver consists of 3 primary components-- - DPIO object driver-- fsl-mc driver that manages the DPIO object - DPIO service-- provides APIs to other Linux drivers for services - QBman portal interface-- sends portal commands, gets responses - - fsl-mc other - bus drivers - | | - +---+----+ +------+-----+ - |DPIO obj| |DPIO service| - | driver |---| (DPIO) | - +--------+ +------+-----+ - | - +------+-----+ - | QBman | - | portal i/f | - +------------+ - | - hardware - -The diagram below shows how the DPIO driver components fit with the other -DPAA2 Linux driver components: - +------------+ - | OS Network | - | Stack | - +------------+ +------------+ - | Allocator |. . . . . . . | Ethernet | - |(DPMCP,DPBP)| | (DPNI) | - +-.----------+ +---+---+----+ - . . ^ | - . . | | dequeue> - +-------------+ . | | - | DPRC driver | . +--------+ +------------+ - | (DPRC) | . . |DPIO obj| |DPIO service| - +----------+--+ | driver |-| (DPIO) | - | +--------+ +------+-----+ - | +------|-----+ - | | QBman | - +----+--------------+ | portal i/f | - | MC-bus driver | +------------+ - | | | - | /soc/fsl-mc | | - +-------------------+ | - | - =========================================|=========|======================== - +-+--DPIO---|-----------+ - | | | - | QBman Portal | - +-----------------------+ - - ============================================================================ - - -DPIO Object Driver (dpio-driver.c) ----------------------------------- - - The dpio-driver component registers with the fsl-mc bus to handle objects of - type "dpio". The implementation of probe() handles basic initialization - of the DPIO including mapping of the DPIO regions (the QBman SW portal) - and initializing interrupts and registering irq handlers. The dpio-driver - registers the probed DPIO with dpio-service. - -DPIO service (dpio-service.c, dpaa2-io.h) ------------------------------------------- - - The dpio service component provides queuing, notification, and buffers - management services to DPAA2 drivers, such as the Ethernet driver. A system - will typically allocate 1 DPIO object per CPU to allow queuing operations - to happen simultaneously across all CPUs. - - Notification handling - dpaa2_io_service_register() - dpaa2_io_service_deregister() - dpaa2_io_service_rearm() - - Queuing - dpaa2_io_service_pull_fq() - dpaa2_io_service_pull_channel() - dpaa2_io_service_enqueue_fq() - dpaa2_io_service_enqueue_qd() - dpaa2_io_store_create() - dpaa2_io_store_destroy() - dpaa2_io_store_next() - - Buffer pool management - dpaa2_io_service_release() - dpaa2_io_service_acquire() - -QBman portal interface (qbman-portal.c) ---------------------------------------- - - The qbman-portal component provides APIs to do the low level hardware - bit twiddling for operations such as: - -initializing Qman software portals - -building and sending portal commands - -portal interrupt configuration and processing - - The qbman-portal APIs are not public to other drivers, and are - only used by dpio-service. - -Other (dpaa2-fd.h, dpaa2-global.h) ----------------------------------- - - Frame descriptor and scatter-gather definitions and the APIs used to - manipulate them are defined in dpaa2-fd.h. - - Dequeue result struct and parsing APIs are defined in dpaa2-global.h. diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio-service.c b/drivers/staging/fsl-mc/bus/dpio/dpio-service.c deleted file mode 100644 index 14ed2beb7432..000000000000 --- a/drivers/staging/fsl-mc/bus/dpio/dpio-service.c +++ /dev/null @@ -1,545 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -/* - * Copyright 2014-2016 Freescale Semiconductor Inc. - * Copyright 2016 NXP - * - */ -#include -#include -#include "../../include/dpaa2-io.h" -#include -#include -#include -#include -#include -#include - -#include "dpio.h" -#include "qbman-portal.h" - -struct dpaa2_io { - struct dpaa2_io_desc dpio_desc; - struct qbman_swp_desc swp_desc; - struct qbman_swp *swp; - struct list_head node; - /* protect against multiple management commands */ - spinlock_t lock_mgmt_cmd; - /* protect notifications list */ - 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 (cpu != DPAA2_IO_ANY_CPU && cpu >= num_possible_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_service_select() - return a dpaa2_io service affined to this cpu - * @cpu: the cpu id - * - * Return the affine dpaa2_io service, or NULL if there is no service affined - * to the specified cpu. If DPAA2_IO_ANY_CPU is used, return the next available - * service. - */ -struct dpaa2_io *dpaa2_io_service_select(int cpu) -{ - if (cpu == DPAA2_IO_ANY_CPU) - return service_select(NULL); - - return service_select_by_cpu(NULL, cpu); -} -EXPORT_SYMBOL_GPL(dpaa2_io_service_select); - -/** - * 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 != DPAA2_IO_ANY_CPU && desc->cpu >= num_possible_cpus()) { - kfree(obj); - return NULL; - } - - 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; -} - -/** - * 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) -{ - kfree(d); -} - -#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 *)(uintptr_t)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; -} - -/** - * 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)(uintptr_t)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) - return qbman_swp_CDAN_set_context_enable(d->swp, - (u16)ctx->id, - ctx->qman64); - return 0; -} -EXPORT_SYMBOL_GPL(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_GPL(dpaa2_io_service_deregister); - -/** - * dpaa2_io_service_rearm() - Rearm the notification for the given DPIO service. - * @d: 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_by_cpu(d, ctx->desired_cpu); - 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_GPL(dpaa2_io_service_rearm); - -/** - * dpaa2_io_service_pull_channel() - pull dequeue functions from a channel. - * @d: the given DPIO service. - * @channelid: the given channel id. - * @s: the dpaa2_io_store object for the result. - * - * Return 0 for success, or error code for failure. - */ -int dpaa2_io_service_pull_channel(struct dpaa2_io *d, u32 channelid, - struct dpaa2_io_store *s) -{ - struct qbman_pull_desc pd; - int err; - - qbman_pull_desc_clear(&pd); - qbman_pull_desc_set_storage(&pd, s->vaddr, s->paddr, 1); - qbman_pull_desc_set_numframes(&pd, (u8)s->max); - qbman_pull_desc_set_channel(&pd, channelid, qbman_pull_type_prio); - - d = service_select(d); - if (!d) - return -ENODEV; - - s->swp = d->swp; - err = qbman_swp_pull(d->swp, &pd); - if (err) - s->swp = NULL; - - return err; -} -EXPORT_SYMBOL_GPL(dpaa2_io_service_pull_channel); - -/** - * dpaa2_io_service_enqueue_qd() - Enqueue a frame to a QD. - * @d: the given DPIO service. - * @qdid: the given queuing destination id. - * @prio: the given queuing priority. - * @qdbin: the given queuing destination bin. - * @fd: the frame descriptor which is enqueued. - * - * Return 0 for successful enqueue, or -EBUSY if the enqueue ring is not ready, - * or -ENODEV if there is no dpio service. - */ -int dpaa2_io_service_enqueue_qd(struct dpaa2_io *d, - u32 qdid, u8 prio, u16 qdbin, - const struct dpaa2_fd *fd) -{ - struct qbman_eq_desc ed; - - d = service_select(d); - if (!d) - return -ENODEV; - - qbman_eq_desc_clear(&ed); - qbman_eq_desc_set_no_orp(&ed, 0); - qbman_eq_desc_set_qd(&ed, qdid, qdbin, prio); - - return qbman_swp_enqueue(d->swp, &ed, fd); -} -EXPORT_SYMBOL_GPL(dpaa2_io_service_enqueue_qd); - -/** - * dpaa2_io_service_release() - Release buffers to a buffer pool. - * @d: the given DPIO object. - * @bpid: the buffer pool id. - * @buffers: the buffers to be released. - * @num_buffers: the number of the buffers to be released. - * - * Return 0 for success, and negative error code for failure. - */ -int dpaa2_io_service_release(struct dpaa2_io *d, - u32 bpid, - const u64 *buffers, - unsigned int num_buffers) -{ - struct qbman_release_desc rd; - - d = service_select(d); - if (!d) - return -ENODEV; - - qbman_release_desc_clear(&rd); - qbman_release_desc_set_bpid(&rd, bpid); - - return qbman_swp_release(d->swp, &rd, buffers, num_buffers); -} -EXPORT_SYMBOL_GPL(dpaa2_io_service_release); - -/** - * dpaa2_io_service_acquire() - Acquire buffers from a buffer pool. - * @d: the given DPIO object. - * @bpid: the buffer pool id. - * @buffers: the buffer addresses for acquired buffers. - * @num_buffers: the expected number of the buffers to acquire. - * - * Return a negative error code if the command failed, otherwise it returns - * the number of buffers acquired, which may be less than the number requested. - * Eg. if the buffer pool is empty, this will return zero. - */ -int dpaa2_io_service_acquire(struct dpaa2_io *d, - u32 bpid, - u64 *buffers, - unsigned int num_buffers) -{ - unsigned long irqflags; - int err; - - d = service_select(d); - if (!d) - return -ENODEV; - - spin_lock_irqsave(&d->lock_mgmt_cmd, irqflags); - err = qbman_swp_acquire(d->swp, bpid, buffers, num_buffers); - spin_unlock_irqrestore(&d->lock_mgmt_cmd, irqflags); - - return err; -} -EXPORT_SYMBOL_GPL(dpaa2_io_service_acquire); - -/* - * 'Stores' are reusable memory blocks for holding dequeue results, and to - * assist with parsing those results. - */ - -/** - * dpaa2_io_store_create() - Create the dma memory storage for dequeue result. - * @max_frames: the maximum number of dequeued result for frames, must be <= 16. - * @dev: the device to allow mapping/unmapping the DMAable region. - * - * The size of the storage is "max_frames*sizeof(struct dpaa2_dq)". - * The 'dpaa2_io_store' returned is a DPIO service managed object. - * - * Return pointer to dpaa2_io_store struct for successfully created storage - * memory, or NULL on error. - */ -struct dpaa2_io_store *dpaa2_io_store_create(unsigned int max_frames, - struct device *dev) -{ - struct dpaa2_io_store *ret; - size_t size; - - if (!max_frames || (max_frames > 16)) - return NULL; - - ret = kmalloc(sizeof(*ret), GFP_KERNEL); - if (!ret) - return NULL; - - ret->max = max_frames; - size = max_frames * sizeof(struct dpaa2_dq) + 64; - ret->alloced_addr = kzalloc(size, GFP_KERNEL); - if (!ret->alloced_addr) { - kfree(ret); - return NULL; - } - - ret->vaddr = PTR_ALIGN(ret->alloced_addr, 64); - ret->paddr = dma_map_single(dev, ret->vaddr, - sizeof(struct dpaa2_dq) * max_frames, - DMA_FROM_DEVICE); - if (dma_mapping_error(dev, ret->paddr)) { - kfree(ret->alloced_addr); - kfree(ret); - return NULL; - } - - ret->idx = 0; - ret->dev = dev; - - return ret; -} -EXPORT_SYMBOL_GPL(dpaa2_io_store_create); - -/** - * dpaa2_io_store_destroy() - Frees the dma memory storage for dequeue - * result. - * @s: the storage memory to be destroyed. - */ -void dpaa2_io_store_destroy(struct dpaa2_io_store *s) -{ - dma_unmap_single(s->dev, s->paddr, sizeof(struct dpaa2_dq) * s->max, - DMA_FROM_DEVICE); - kfree(s->alloced_addr); - kfree(s); -} -EXPORT_SYMBOL_GPL(dpaa2_io_store_destroy); - -/** - * dpaa2_io_store_next() - Determine when the next dequeue result is available. - * @s: the dpaa2_io_store object. - * @is_last: indicate whether this is the last frame in the pull command. - * - * When an object driver performs dequeues to a dpaa2_io_store, this function - * can be used to determine when the next frame result is available. Once - * this function returns non-NULL, a subsequent call to it will try to find - * the next dequeue result. - * - * Note that if a pull-dequeue has a NULL result because the target FQ/channel - * was empty, then this function will also return NULL (rather than expecting - * the caller to always check for this. As such, "is_last" can be used to - * differentiate between "end-of-empty-dequeue" and "still-waiting". - * - * Return dequeue result for a valid dequeue result, or NULL for empty dequeue. - */ -struct dpaa2_dq *dpaa2_io_store_next(struct dpaa2_io_store *s, int *is_last) -{ - int match; - struct dpaa2_dq *ret = &s->vaddr[s->idx]; - - match = qbman_result_has_new_result(s->swp, ret); - if (!match) { - *is_last = 0; - return NULL; - } - - s->idx++; - - if (dpaa2_dq_is_pull_complete(ret)) { - *is_last = 1; - s->idx = 0; - /* - * If we get an empty dequeue result to terminate a zero-results - * vdqcr, return NULL to the caller rather than expecting him to - * check non-NULL results every time. - */ - if (!(dpaa2_dq_flags(ret) & DPAA2_DQ_STAT_VALIDFRAME)) - ret = NULL; - } else { - *is_last = 0; - } - - return ret; -} -EXPORT_SYMBOL_GPL(dpaa2_io_store_next); diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio.c b/drivers/staging/fsl-mc/bus/dpio/dpio.c deleted file mode 100644 index ff37c80e11a0..000000000000 --- a/drivers/staging/fsl-mc/bus/dpio/dpio.c +++ /dev/null @@ -1,198 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -/* - * Copyright 2013-2016 Freescale Semiconductor Inc. - * Copyright 2016 NXP - * - */ -#include -#include - -#include "dpio.h" -#include "dpio-cmd.h" - -/* - * Data Path I/O Portal API - * Contains initialization APIs and runtime control APIs for DPIO - */ - -/** - * dpio_open() - Open a control session for the specified object - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @dpio_id: DPIO unique ID - * @token: Returned token; use in subsequent API calls - * - * This function can be used to open a control session for an - * already created object; an object may have been declared in - * the DPL or by calling the dpio_create() function. - * This function returns a unique authentication token, - * associated with the specific object ID and the specific MC - * portal; this token must be used in all subsequent commands for - * this specific object. - * - * Return: '0' on Success; Error code otherwise. - */ -int dpio_open(struct fsl_mc_io *mc_io, - u32 cmd_flags, - int dpio_id, - u16 *token) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpio_cmd_open *dpio_cmd; - int err; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPIO_CMDID_OPEN, - cmd_flags, - 0); - dpio_cmd = (struct dpio_cmd_open *)cmd.params; - dpio_cmd->dpio_id = cpu_to_le32(dpio_id); - - err = mc_send_command(mc_io, &cmd); - if (err) - return err; - - /* retrieve response parameters */ - *token = mc_cmd_hdr_read_token(&cmd); - - return 0; -} - -/** - * dpio_close() - Close the control session of the object - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPIO object - * - * Return: '0' on Success; Error code otherwise. - */ -int dpio_close(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token) -{ - struct fsl_mc_command cmd = { 0 }; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPIO_CMDID_CLOSE, - cmd_flags, - token); - - return mc_send_command(mc_io, &cmd); -} - -/** - * dpio_enable() - Enable the DPIO, allow I/O portal operations. - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPIO object - * - * Return: '0' on Success; Error code otherwise - */ -int dpio_enable(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token) -{ - struct fsl_mc_command cmd = { 0 }; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPIO_CMDID_ENABLE, - cmd_flags, - token); - - return mc_send_command(mc_io, &cmd); -} - -/** - * dpio_disable() - Disable the DPIO, stop any I/O portal operation. - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPIO object - * - * Return: '0' on Success; Error code otherwise - */ -int dpio_disable(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token) -{ - struct fsl_mc_command cmd = { 0 }; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPIO_CMDID_DISABLE, - cmd_flags, - token); - - return mc_send_command(mc_io, &cmd); -} - -/** - * dpio_get_attributes() - Retrieve DPIO attributes - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPIO object - * @attr: Returned object's attributes - * - * Return: '0' on Success; Error code otherwise - */ -int dpio_get_attributes(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - struct dpio_attr *attr) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpio_rsp_get_attr *dpio_rsp; - int err; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_ATTR, - cmd_flags, - token); - - err = mc_send_command(mc_io, &cmd); - if (err) - return err; - - /* retrieve response parameters */ - dpio_rsp = (struct dpio_rsp_get_attr *)cmd.params; - attr->id = le32_to_cpu(dpio_rsp->id); - attr->qbman_portal_id = le16_to_cpu(dpio_rsp->qbman_portal_id); - attr->num_priorities = dpio_rsp->num_priorities; - attr->channel_mode = dpio_rsp->channel_mode & DPIO_CHANNEL_MODE_MASK; - attr->qbman_portal_ce_offset = - le64_to_cpu(dpio_rsp->qbman_portal_ce_addr); - attr->qbman_portal_ci_offset = - le64_to_cpu(dpio_rsp->qbman_portal_ci_addr); - attr->qbman_version = le32_to_cpu(dpio_rsp->qbman_version); - - return 0; -} - -/** - * dpio_get_api_version - Get Data Path I/O API version - * @mc_io: Pointer to MC portal's DPIO object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @major_ver: Major version of DPIO API - * @minor_ver: Minor version of DPIO API - * - * Return: '0' on Success; Error code otherwise - */ -int dpio_get_api_version(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 *major_ver, - u16 *minor_ver) -{ - struct fsl_mc_command cmd = { 0 }; - int err; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_API_VERSION, - cmd_flags, 0); - - err = mc_send_command(mc_io, &cmd); - if (err) - return err; - - /* retrieve response parameters */ - mc_cmd_read_api_version(&cmd, major_ver, minor_ver); - - return 0; -} diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio.h b/drivers/staging/fsl-mc/bus/dpio/dpio.h deleted file mode 100644 index 49194c8e45f1..000000000000 --- a/drivers/staging/fsl-mc/bus/dpio/dpio.h +++ /dev/null @@ -1,83 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ -/* - * Copyright 2013-2016 Freescale Semiconductor Inc. - * Copyright 2016 NXP - * - */ -#ifndef __FSL_DPIO_H -#define __FSL_DPIO_H - -struct fsl_mc_io; - -int dpio_open(struct fsl_mc_io *mc_io, - u32 cmd_flags, - int dpio_id, - u16 *token); - -int dpio_close(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token); - -/** - * enum dpio_channel_mode - DPIO notification channel mode - * @DPIO_NO_CHANNEL: No support for notification channel - * @DPIO_LOCAL_CHANNEL: Notifications on data availability can be received by a - * dedicated channel in the DPIO; user should point the queue's - * destination in the relevant interface to this DPIO - */ -enum dpio_channel_mode { - DPIO_NO_CHANNEL = 0, - DPIO_LOCAL_CHANNEL = 1, -}; - -/** - * struct dpio_cfg - Structure representing DPIO configuration - * @channel_mode: Notification channel mode - * @num_priorities: Number of priorities for the notification channel (1-8); - * relevant only if 'channel_mode = DPIO_LOCAL_CHANNEL' - */ -struct dpio_cfg { - enum dpio_channel_mode channel_mode; - u8 num_priorities; -}; - -int dpio_enable(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token); - -int dpio_disable(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token); - -/** - * struct dpio_attr - Structure representing DPIO attributes - * @id: DPIO object ID - * @qbman_portal_ce_offset: offset of the software portal cache-enabled area - * @qbman_portal_ci_offset: offset of the software portal cache-inhibited area - * @qbman_portal_id: Software portal ID - * @channel_mode: Notification channel mode - * @num_priorities: Number of priorities for the notification channel (1-8); - * relevant only if 'channel_mode = DPIO_LOCAL_CHANNEL' - * @qbman_version: QBMAN version - */ -struct dpio_attr { - int id; - u64 qbman_portal_ce_offset; - u64 qbman_portal_ci_offset; - u16 qbman_portal_id; - enum dpio_channel_mode channel_mode; - u8 num_priorities; - u32 qbman_version; -}; - -int dpio_get_attributes(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - struct dpio_attr *attr); - -int dpio_get_api_version(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 *major_ver, - u16 *minor_ver); - -#endif /* __FSL_DPIO_H */ diff --git a/drivers/staging/fsl-mc/bus/dpio/qbman-portal.c b/drivers/staging/fsl-mc/bus/dpio/qbman-portal.c deleted file mode 100644 index 116fafb28640..000000000000 --- a/drivers/staging/fsl-mc/bus/dpio/qbman-portal.c +++ /dev/null @@ -1,1005 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -/* - * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. - * Copyright 2016 NXP - * - */ - -#include -#include -#include -#include "../../include/dpaa2-global.h" - -#include "qbman-portal.h" - -#define QMAN_REV_4000 0x04000000 -#define QMAN_REV_4100 0x04010000 -#define QMAN_REV_4101 0x04010001 -#define QMAN_REV_MASK 0xffff0000 - -/* All QBMan command and result structures use this "valid bit" encoding */ -#define QB_VALID_BIT ((u32)0x80) - -/* QBMan portal management command codes */ -#define QBMAN_MC_ACQUIRE 0x30 -#define QBMAN_WQCHAN_CONFIGURE 0x46 - -/* CINH register offsets */ -#define QBMAN_CINH_SWP_EQAR 0x8c0 -#define QBMAN_CINH_SWP_DQPI 0xa00 -#define QBMAN_CINH_SWP_DCAP 0xac0 -#define QBMAN_CINH_SWP_SDQCR 0xb00 -#define QBMAN_CINH_SWP_RAR 0xcc0 -#define QBMAN_CINH_SWP_ISR 0xe00 -#define QBMAN_CINH_SWP_IER 0xe40 -#define QBMAN_CINH_SWP_ISDR 0xe80 -#define QBMAN_CINH_SWP_IIR 0xec0 - -/* CENA register offsets */ -#define QBMAN_CENA_SWP_EQCR(n) (0x000 + ((u32)(n) << 6)) -#define QBMAN_CENA_SWP_DQRR(n) (0x200 + ((u32)(n) << 6)) -#define QBMAN_CENA_SWP_RCR(n) (0x400 + ((u32)(n) << 6)) -#define QBMAN_CENA_SWP_CR 0x600 -#define QBMAN_CENA_SWP_RR(vb) (0x700 + ((u32)(vb) >> 1)) -#define QBMAN_CENA_SWP_VDQCR 0x780 - -/* Reverse mapping of QBMAN_CENA_SWP_DQRR() */ -#define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)(p) & 0x1ff) >> 6) - -/* Define token used to determine if response written to memory is valid */ -#define QMAN_DQ_TOKEN_VALID 1 - -/* SDQCR attribute codes */ -#define QB_SDQCR_FC_SHIFT 29 -#define QB_SDQCR_FC_MASK 0x1 -#define QB_SDQCR_DCT_SHIFT 24 -#define QB_SDQCR_DCT_MASK 0x3 -#define QB_SDQCR_TOK_SHIFT 16 -#define QB_SDQCR_TOK_MASK 0xff -#define QB_SDQCR_SRC_SHIFT 0 -#define QB_SDQCR_SRC_MASK 0xffff - -/* opaque token for static dequeues */ -#define QMAN_SDQCR_TOKEN 0xbb - -enum qbman_sdqcr_dct { - qbman_sdqcr_dct_null = 0, - qbman_sdqcr_dct_prio_ics, - qbman_sdqcr_dct_active_ics, - qbman_sdqcr_dct_active -}; - -enum qbman_sdqcr_fc { - qbman_sdqcr_fc_one = 0, - qbman_sdqcr_fc_up_to_3 = 1 -}; - -/* Portal Access */ - -static inline u32 qbman_read_register(struct qbman_swp *p, u32 offset) -{ - return readl_relaxed(p->addr_cinh + offset); -} - -static inline void qbman_write_register(struct qbman_swp *p, u32 offset, - u32 value) -{ - writel_relaxed(value, p->addr_cinh + offset); -} - -static inline void *qbman_get_cmd(struct qbman_swp *p, u32 offset) -{ - return p->addr_cena + offset; -} - -#define QBMAN_CINH_SWP_CFG 0xd00 - -#define SWP_CFG_DQRR_MF_SHIFT 20 -#define SWP_CFG_EST_SHIFT 16 -#define SWP_CFG_WN_SHIFT 14 -#define SWP_CFG_RPM_SHIFT 12 -#define SWP_CFG_DCM_SHIFT 10 -#define SWP_CFG_EPM_SHIFT 8 -#define SWP_CFG_SD_SHIFT 5 -#define SWP_CFG_SP_SHIFT 4 -#define SWP_CFG_SE_SHIFT 3 -#define SWP_CFG_DP_SHIFT 2 -#define SWP_CFG_DE_SHIFT 1 -#define SWP_CFG_EP_SHIFT 0 - -static inline u32 qbman_set_swp_cfg(u8 max_fill, u8 wn, u8 est, u8 rpm, u8 dcm, - u8 epm, int sd, int sp, int se, - int dp, int de, int ep) -{ - return (max_fill << SWP_CFG_DQRR_MF_SHIFT | - est << SWP_CFG_EST_SHIFT | - wn << SWP_CFG_WN_SHIFT | - rpm << SWP_CFG_RPM_SHIFT | - dcm << SWP_CFG_DCM_SHIFT | - epm << SWP_CFG_EPM_SHIFT | - sd << SWP_CFG_SD_SHIFT | - sp << SWP_CFG_SP_SHIFT | - se << SWP_CFG_SE_SHIFT | - dp << SWP_CFG_DP_SHIFT | - de << SWP_CFG_DE_SHIFT | - ep << SWP_CFG_EP_SHIFT); -} - -/** - * qbman_swp_init() - Create a functional object representing the given - * QBMan portal descriptor. - * @d: the given qbman swp descriptor - * - * Return qbman_swp portal for success, NULL if the object cannot - * be created. - */ -struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) -{ - struct qbman_swp *p = kmalloc(sizeof(*p), GFP_KERNEL); - u32 reg; - - if (!p) - return NULL; - p->desc = d; - p->mc.valid_bit = QB_VALID_BIT; - p->sdq = 0; - p->sdq |= qbman_sdqcr_dct_prio_ics << QB_SDQCR_DCT_SHIFT; - p->sdq |= qbman_sdqcr_fc_up_to_3 << QB_SDQCR_FC_SHIFT; - p->sdq |= QMAN_SDQCR_TOKEN << QB_SDQCR_TOK_SHIFT; - - atomic_set(&p->vdq.available, 1); - p->vdq.valid_bit = QB_VALID_BIT; - p->dqrr.next_idx = 0; - p->dqrr.valid_bit = QB_VALID_BIT; - - if ((p->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_4100) { - p->dqrr.dqrr_size = 4; - p->dqrr.reset_bug = 1; - } else { - p->dqrr.dqrr_size = 8; - p->dqrr.reset_bug = 0; - } - - p->addr_cena = d->cena_bar; - p->addr_cinh = d->cinh_bar; - - reg = qbman_set_swp_cfg(p->dqrr.dqrr_size, - 1, /* Writes Non-cacheable */ - 0, /* EQCR_CI stashing threshold */ - 3, /* RPM: Valid bit mode, RCR in array mode */ - 2, /* DCM: Discrete consumption ack mode */ - 3, /* EPM: Valid bit mode, EQCR in array mode */ - 0, /* mem stashing drop enable == FALSE */ - 1, /* mem stashing priority == TRUE */ - 0, /* mem stashing enable == FALSE */ - 1, /* dequeue stashing priority == TRUE */ - 0, /* dequeue stashing enable == FALSE */ - 0); /* EQCR_CI stashing priority == FALSE */ - - qbman_write_register(p, QBMAN_CINH_SWP_CFG, reg); - reg = qbman_read_register(p, QBMAN_CINH_SWP_CFG); - if (!reg) { - pr_err("qbman: the portal is not enabled!\n"); - return NULL; - } - - /* - * SDQCR needs to be initialized to 0 when no channels are - * being dequeued from or else the QMan HW will indicate an - * error. The values that were calculated above will be - * applied when dequeues from a specific channel are enabled. - */ - qbman_write_register(p, QBMAN_CINH_SWP_SDQCR, 0); - return p; -} - -/** - * qbman_swp_finish() - Create and destroy a functional object representing - * the given QBMan portal descriptor. - * @p: the qbman_swp object to be destroyed - */ -void qbman_swp_finish(struct qbman_swp *p) -{ - kfree(p); -} - -/** - * qbman_swp_interrupt_read_status() - * @p: the given software portal - * - * Return the value in the SWP_ISR register. - */ -u32 qbman_swp_interrupt_read_status(struct qbman_swp *p) -{ - return qbman_read_register(p, QBMAN_CINH_SWP_ISR); -} - -/** - * qbman_swp_interrupt_clear_status() - * @p: the given software portal - * @mask: The mask to clear in SWP_ISR register - */ -void qbman_swp_interrupt_clear_status(struct qbman_swp *p, u32 mask) -{ - qbman_write_register(p, QBMAN_CINH_SWP_ISR, mask); -} - -/** - * qbman_swp_interrupt_get_trigger() - read interrupt enable register - * @p: the given software portal - * - * Return the value in the SWP_IER register. - */ -u32 qbman_swp_interrupt_get_trigger(struct qbman_swp *p) -{ - return qbman_read_register(p, QBMAN_CINH_SWP_IER); -} - -/** - * qbman_swp_interrupt_set_trigger() - enable interrupts for a swp - * @p: the given software portal - * @mask: The mask of bits to enable in SWP_IER - */ -void qbman_swp_interrupt_set_trigger(struct qbman_swp *p, u32 mask) -{ - qbman_write_register(p, QBMAN_CINH_SWP_IER, mask); -} - -/** - * qbman_swp_interrupt_get_inhibit() - read interrupt mask register - * @p: the given software portal object - * - * Return the value in the SWP_IIR register. - */ -int qbman_swp_interrupt_get_inhibit(struct qbman_swp *p) -{ - return qbman_read_register(p, QBMAN_CINH_SWP_IIR); -} - -/** - * qbman_swp_interrupt_set_inhibit() - write interrupt mask register - * @p: the given software portal object - * @mask: The mask to set in SWP_IIR register - */ -void qbman_swp_interrupt_set_inhibit(struct qbman_swp *p, int inhibit) -{ - qbman_write_register(p, QBMAN_CINH_SWP_IIR, inhibit ? 0xffffffff : 0); -} - -/* - * Different management commands all use this common base layer of code to issue - * commands and poll for results. - */ - -/* - * Returns a pointer to where the caller should fill in their management command - * (caller should ignore the verb byte) - */ -void *qbman_swp_mc_start(struct qbman_swp *p) -{ - return qbman_get_cmd(p, QBMAN_CENA_SWP_CR); -} - -/* - * Commits merges in the caller-supplied command verb (which should not include - * the valid-bit) and submits the command to hardware - */ -void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, u8 cmd_verb) -{ - u8 *v = cmd; - - dma_wmb(); - *v = cmd_verb | p->mc.valid_bit; -} - -/* - * Checks for a completed response (returns non-NULL if only if the response - * is complete). - */ -void *qbman_swp_mc_result(struct qbman_swp *p) -{ - u32 *ret, verb; - - ret = qbman_get_cmd(p, QBMAN_CENA_SWP_RR(p->mc.valid_bit)); - - /* Remove the valid-bit - command completed if the rest is non-zero */ - verb = ret[0] & ~QB_VALID_BIT; - if (!verb) - return NULL; - p->mc.valid_bit ^= QB_VALID_BIT; - return ret; -} - -#define QB_ENQUEUE_CMD_OPTIONS_SHIFT 0 -enum qb_enqueue_commands { - enqueue_empty = 0, - enqueue_response_always = 1, - enqueue_rejects_to_fq = 2 -}; - -#define QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT 2 -#define QB_ENQUEUE_CMD_IRQ_ON_DISPATCH_SHIFT 3 -#define QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT 4 - -/** - * qbman_eq_desc_clear() - Clear the contents of a descriptor to - * default/starting state. - */ -void qbman_eq_desc_clear(struct qbman_eq_desc *d) -{ - memset(d, 0, sizeof(*d)); -} - -/** - * qbman_eq_desc_set_no_orp() - Set enqueue descriptor without orp - * @d: the enqueue descriptor. - * @response_success: 1 = enqueue with response always; 0 = enqueue with - * rejections returned on a FQ. - */ -void qbman_eq_desc_set_no_orp(struct qbman_eq_desc *d, int respond_success) -{ - d->verb &= ~(1 << QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT); - if (respond_success) - d->verb |= enqueue_response_always; - else - d->verb |= enqueue_rejects_to_fq; -} - -/* - * Exactly one of the following descriptor "targets" should be set. (Calling any - * one of these will replace the effect of any prior call to one of these.) - * -enqueue to a frame queue - * -enqueue to a queuing destination - */ - -/** - * qbman_eq_desc_set_fq() - set the FQ for the enqueue command - * @d: the enqueue descriptor - * @fqid: the id of the frame queue to be enqueued - */ -void qbman_eq_desc_set_fq(struct qbman_eq_desc *d, u32 fqid) -{ - d->verb &= ~(1 << QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT); - d->tgtid = cpu_to_le32(fqid); -} - -/** - * qbman_eq_desc_set_qd() - Set Queuing Destination for the enqueue command - * @d: the enqueue descriptor - * @qdid: the id of the queuing destination to be enqueued - * @qd_bin: the queuing destination bin - * @qd_prio: the queuing destination priority - */ -void qbman_eq_desc_set_qd(struct qbman_eq_desc *d, u32 qdid, - u32 qd_bin, u32 qd_prio) -{ - d->verb |= 1 << QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT; - d->tgtid = cpu_to_le32(qdid); - d->qdbin = cpu_to_le16(qd_bin); - d->qpri = qd_prio; -} - -#define EQAR_IDX(eqar) ((eqar) & 0x7) -#define EQAR_VB(eqar) ((eqar) & 0x80) -#define EQAR_SUCCESS(eqar) ((eqar) & 0x100) - -/** - * qbman_swp_enqueue() - Issue an enqueue command - * @s: the software portal used for enqueue - * @d: the enqueue descriptor - * @fd: the frame descriptor to be enqueued - * - * Please note that 'fd' should only be NULL if the "action" of the - * descriptor is "orp_hole" or "orp_nesn". - * - * Return 0 for successful enqueue, -EBUSY if the EQCR is not ready. - */ -int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d, - const struct dpaa2_fd *fd) -{ - struct qbman_eq_desc *p; - u32 eqar = qbman_read_register(s, QBMAN_CINH_SWP_EQAR); - - if (!EQAR_SUCCESS(eqar)) - return -EBUSY; - - p = qbman_get_cmd(s, QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar))); - memcpy(&p->dca, &d->dca, 31); - memcpy(&p->fd, fd, sizeof(*fd)); - - /* Set the verb byte, have to substitute in the valid-bit */ - dma_wmb(); - p->verb = d->verb | EQAR_VB(eqar); - - return 0; -} - -/* Static (push) dequeue */ - -/** - * qbman_swp_push_get() - Get the push dequeue setup - * @p: the software portal object - * @channel_idx: the channel index to query - * @enabled: returned boolean to show whether the push dequeue is enabled - * for the given channel - */ -void qbman_swp_push_get(struct qbman_swp *s, u8 channel_idx, int *enabled) -{ - u16 src = (s->sdq >> QB_SDQCR_SRC_SHIFT) & QB_SDQCR_SRC_MASK; - - WARN_ON(channel_idx > 15); - *enabled = src | (1 << channel_idx); -} - -/** - * qbman_swp_push_set() - Enable or disable push dequeue - * @p: the software portal object - * @channel_idx: the channel index (0 to 15) - * @enable: enable or disable push dequeue - */ -void qbman_swp_push_set(struct qbman_swp *s, u8 channel_idx, int enable) -{ - u16 dqsrc; - - WARN_ON(channel_idx > 15); - if (enable) - s->sdq |= 1 << channel_idx; - else - s->sdq &= ~(1 << channel_idx); - - /* Read make the complete src map. If no channels are enabled - * the SDQCR must be 0 or else QMan will assert errors - */ - dqsrc = (s->sdq >> QB_SDQCR_SRC_SHIFT) & QB_SDQCR_SRC_MASK; - if (dqsrc != 0) - qbman_write_register(s, QBMAN_CINH_SWP_SDQCR, s->sdq); - else - qbman_write_register(s, QBMAN_CINH_SWP_SDQCR, 0); -} - -#define QB_VDQCR_VERB_DCT_SHIFT 0 -#define QB_VDQCR_VERB_DT_SHIFT 2 -#define QB_VDQCR_VERB_RLS_SHIFT 4 -#define QB_VDQCR_VERB_WAE_SHIFT 5 - -enum qb_pull_dt_e { - qb_pull_dt_channel, - qb_pull_dt_workqueue, - qb_pull_dt_framequeue -}; - -/** - * qbman_pull_desc_clear() - Clear the contents of a descriptor to - * default/starting state - * @d: the pull dequeue descriptor to be cleared - */ -void qbman_pull_desc_clear(struct qbman_pull_desc *d) -{ - memset(d, 0, sizeof(*d)); -} - -/** - * qbman_pull_desc_set_storage()- Set the pull dequeue storage - * @d: the pull dequeue descriptor to be set - * @storage: the pointer of the memory to store the dequeue result - * @storage_phys: the physical address of the storage memory - * @stash: to indicate whether write allocate is enabled - * - * If not called, or if called with 'storage' as NULL, the result pull dequeues - * will produce results to DQRR. If 'storage' is non-NULL, then results are - * produced to the given memory location (using the DMA address which - * the caller provides in 'storage_phys'), and 'stash' controls whether or not - * those writes to main-memory express a cache-warming attribute. - */ -void qbman_pull_desc_set_storage(struct qbman_pull_desc *d, - struct dpaa2_dq *storage, - dma_addr_t storage_phys, - int stash) -{ - /* save the virtual address */ - d->rsp_addr_virt = (u64)(uintptr_t)storage; - - if (!storage) { - d->verb &= ~(1 << QB_VDQCR_VERB_RLS_SHIFT); - return; - } - d->verb |= 1 << QB_VDQCR_VERB_RLS_SHIFT; - if (stash) - d->verb |= 1 << QB_VDQCR_VERB_WAE_SHIFT; - else - d->verb &= ~(1 << QB_VDQCR_VERB_WAE_SHIFT); - - d->rsp_addr = cpu_to_le64(storage_phys); -} - -/** - * qbman_pull_desc_set_numframes() - Set the number of frames to be dequeued - * @d: the pull dequeue descriptor to be set - * @numframes: number of frames to be set, must be between 1 and 16, inclusive - */ -void qbman_pull_desc_set_numframes(struct qbman_pull_desc *d, u8 numframes) -{ - d->numf = numframes - 1; -} - -/* - * Exactly one of the following descriptor "actions" should be set. (Calling any - * one of these will replace the effect of any prior call to one of these.) - * - pull dequeue from the given frame queue (FQ) - * - pull dequeue from any FQ in the given work queue (WQ) - * - pull dequeue from any FQ in any WQ in the given channel - */ - -/** - * qbman_pull_desc_set_fq() - Set fqid from which the dequeue command dequeues - * @fqid: the frame queue index of the given FQ - */ -void qbman_pull_desc_set_fq(struct qbman_pull_desc *d, u32 fqid) -{ - d->verb |= 1 << QB_VDQCR_VERB_DCT_SHIFT; - d->verb |= qb_pull_dt_framequeue << QB_VDQCR_VERB_DT_SHIFT; - d->dq_src = cpu_to_le32(fqid); -} - -/** - * qbman_pull_desc_set_wq() - Set wqid from which the dequeue command dequeues - * @wqid: composed of channel id and wqid within the channel - * @dct: the dequeue command type - */ -void qbman_pull_desc_set_wq(struct qbman_pull_desc *d, u32 wqid, - enum qbman_pull_type_e dct) -{ - d->verb |= dct << QB_VDQCR_VERB_DCT_SHIFT; - d->verb |= qb_pull_dt_workqueue << QB_VDQCR_VERB_DT_SHIFT; - d->dq_src = cpu_to_le32(wqid); -} - -/** - * qbman_pull_desc_set_channel() - Set channelid from which the dequeue command - * dequeues - * @chid: the channel id to be dequeued - * @dct: the dequeue command type - */ -void qbman_pull_desc_set_channel(struct qbman_pull_desc *d, u32 chid, - enum qbman_pull_type_e dct) -{ - d->verb |= dct << QB_VDQCR_VERB_DCT_SHIFT; - d->verb |= qb_pull_dt_channel << QB_VDQCR_VERB_DT_SHIFT; - d->dq_src = cpu_to_le32(chid); -} - -/** - * qbman_swp_pull() - Issue the pull dequeue command - * @s: the software portal object - * @d: the software portal descriptor which has been configured with - * the set of qbman_pull_desc_set_*() calls - * - * Return 0 for success, and -EBUSY if the software portal is not ready - * to do pull dequeue. - */ -int qbman_swp_pull(struct qbman_swp *s, struct qbman_pull_desc *d) -{ - struct qbman_pull_desc *p; - - if (!atomic_dec_and_test(&s->vdq.available)) { - atomic_inc(&s->vdq.available); - return -EBUSY; - } - s->vdq.storage = (void *)(uintptr_t)d->rsp_addr_virt; - p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR); - p->numf = d->numf; - p->tok = QMAN_DQ_TOKEN_VALID; - p->dq_src = d->dq_src; - p->rsp_addr = d->rsp_addr; - p->rsp_addr_virt = d->rsp_addr_virt; - dma_wmb(); - - /* Set the verb byte, have to substitute in the valid-bit */ - p->verb = d->verb | s->vdq.valid_bit; - s->vdq.valid_bit ^= QB_VALID_BIT; - - return 0; -} - -#define QMAN_DQRR_PI_MASK 0xf - -/** - * qbman_swp_dqrr_next() - Get an valid DQRR entry - * @s: the software portal object - * - * Return NULL if there are no unconsumed DQRR entries. Return a DQRR entry - * only once, so repeated calls can return a sequence of DQRR entries, without - * requiring they be consumed immediately or in any particular order. - */ -const struct dpaa2_dq *qbman_swp_dqrr_next(struct qbman_swp *s) -{ - u32 verb; - u32 response_verb; - u32 flags; - struct dpaa2_dq *p; - - /* Before using valid-bit to detect if something is there, we have to - * handle the case of the DQRR reset bug... - */ - if (unlikely(s->dqrr.reset_bug)) { - /* - * We pick up new entries by cache-inhibited producer index, - * which means that a non-coherent mapping would require us to - * invalidate and read *only* once that PI has indicated that - * there's an entry here. The first trip around the DQRR ring - * will be much less efficient than all subsequent trips around - * it... - */ - u8 pi = qbman_read_register(s, QBMAN_CINH_SWP_DQPI) & - QMAN_DQRR_PI_MASK; - - /* there are new entries if pi != next_idx */ - if (pi == s->dqrr.next_idx) - return NULL; - - /* - * if next_idx is/was the last ring index, and 'pi' is - * different, we can disable the workaround as all the ring - * entries have now been DMA'd to so valid-bit checking is - * repaired. Note: this logic needs to be based on next_idx - * (which increments one at a time), rather than on pi (which - * can burst and wrap-around between our snapshots of it). - */ - if (s->dqrr.next_idx == (s->dqrr.dqrr_size - 1)) { - pr_debug("next_idx=%d, pi=%d, clear reset bug\n", - s->dqrr.next_idx, pi); - s->dqrr.reset_bug = 0; - } - prefetch(qbman_get_cmd(s, - QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx))); - } - - p = qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)); - verb = p->dq.verb; - - /* - * If the valid-bit isn't of the expected polarity, nothing there. Note, - * in the DQRR reset bug workaround, we shouldn't need to skip these - * check, because we've already determined that a new entry is available - * and we've invalidated the cacheline before reading it, so the - * valid-bit behaviour is repaired and should tell us what we already - * knew from reading PI. - */ - if ((verb & QB_VALID_BIT) != s->dqrr.valid_bit) { - prefetch(qbman_get_cmd(s, - QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx))); - return NULL; - } - /* - * There's something there. Move "next_idx" attention to the next ring - * entry (and prefetch it) before returning what we found. - */ - s->dqrr.next_idx++; - s->dqrr.next_idx &= s->dqrr.dqrr_size - 1; /* Wrap around */ - if (!s->dqrr.next_idx) - s->dqrr.valid_bit ^= QB_VALID_BIT; - - /* - * If this is the final response to a volatile dequeue command - * indicate that the vdq is available - */ - flags = p->dq.stat; - response_verb = verb & QBMAN_RESULT_MASK; - if ((response_verb == QBMAN_RESULT_DQ) && - (flags & DPAA2_DQ_STAT_VOLATILE) && - (flags & DPAA2_DQ_STAT_EXPIRED)) - atomic_inc(&s->vdq.available); - - prefetch(qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx))); - - return p; -} - -/** - * qbman_swp_dqrr_consume() - Consume DQRR entries previously returned from - * qbman_swp_dqrr_next(). - * @s: the software portal object - * @dq: the DQRR entry to be consumed - */ -void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct dpaa2_dq *dq) -{ - qbman_write_register(s, QBMAN_CINH_SWP_DCAP, QBMAN_IDX_FROM_DQRR(dq)); -} - -/** - * qbman_result_has_new_result() - Check and get the dequeue response from the - * dq storage memory set in pull dequeue command - * @s: the software portal object - * @dq: the dequeue result read from the memory - * - * Return 1 for getting a valid dequeue result, or 0 for not getting a valid - * dequeue result. - * - * Only used for user-provided storage of dequeue results, not DQRR. For - * efficiency purposes, the driver will perform any required endianness - * conversion to