Commit 9d988097 authored by Youri Querry's avatar Youri Querry Committed by Li Yang
Browse files

soc: fsl: dpio: Adding QMAN multiple enqueue interface



Update of QMAN the interface to enqueue frame. We now support multiple
enqueue (qbman_swp_enqueue_multiple) and multiple enqueue with
a table of descriptor (qbman_swp_enqueue_multiple_desc).

Signed-off-by: default avatarYouri Querry <youri.querry_1@nxp.com>
Acked-by: default avatarRoy Pledge <roy.pledge@nxp.com>
Signed-off-by: default avatarLi Yang <leoyang.li@nxp.com>
parent bb6d3fb3
Loading
Loading
Loading
Loading
+66 −3
Original line number Diff line number Diff line
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/*
 * Copyright 2014-2016 Freescale Semiconductor Inc.
 * Copyright 2016 NXP
 * Copyright 2016-2019 NXP
 *
 */
#include <linux/types.h>
@@ -432,6 +432,69 @@ int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d,
}
EXPORT_SYMBOL(dpaa2_io_service_enqueue_fq);

/**
 * dpaa2_io_service_enqueue_multiple_fq() - Enqueue multiple frames
 * to a frame queue using one fqid.
 * @d: the given DPIO service.
 * @fqid: the given frame queue id.
 * @fd: the frame descriptor which is enqueued.
 * @nb: number of frames to be enqueud
 *
 * Return 0 for successful enqueue, -EBUSY if the enqueue ring is not ready,
 * or -ENODEV if there is no dpio service.
 */
int dpaa2_io_service_enqueue_multiple_fq(struct dpaa2_io *d,
				u32 fqid,
				const struct dpaa2_fd *fd,
				int nb)
{
	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_fq(&ed, fqid);

	return qbman_swp_enqueue_multiple(d->swp, &ed, fd, 0, nb);
}
EXPORT_SYMBOL(dpaa2_io_service_enqueue_multiple_fq);

/**
 * dpaa2_io_service_enqueue_multiple_desc_fq() - Enqueue multiple frames
 * to different frame queue using a list of fqids.
 * @d: the given DPIO service.
 * @fqid: the given list of frame queue ids.
 * @fd: the frame descriptor which is enqueued.
 * @nb: number of frames to be enqueud
 *
 * Return 0 for successful enqueue, -EBUSY if the enqueue ring is not ready,
 * or -ENODEV if there is no dpio service.
 */
int dpaa2_io_service_enqueue_multiple_desc_fq(struct dpaa2_io *d,
				u32 *fqid,
				const struct dpaa2_fd *fd,
				int nb)
{
	int i;
	struct qbman_eq_desc ed[32];

	d = service_select(d);
	if (!d)
		return -ENODEV;

	for (i = 0; i < nb; i++) {
		qbman_eq_desc_clear(&ed[i]);
		qbman_eq_desc_set_no_orp(&ed[i], 0);
		qbman_eq_desc_set_fq(&ed[i], fqid[i]);
	}

	return qbman_swp_enqueue_multiple_desc(d->swp, &ed[0], fd, nb);
}
EXPORT_SYMBOL(dpaa2_io_service_enqueue_multiple_desc_fq);

/**
 * dpaa2_io_service_enqueue_qd() - Enqueue a frame to a QD.
 * @d: the given DPIO service.
@@ -526,7 +589,7 @@ EXPORT_SYMBOL_GPL(dpaa2_io_service_acquire);

/**
 * 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.
 * @max_frames: the maximum number of dequeued result for frames, must be <= 32.
 * @dev:        the device to allow mapping/unmapping the DMAable region.
 *
 * The size of the storage is "max_frames*sizeof(struct dpaa2_dq)".
@@ -541,7 +604,7 @@ struct dpaa2_io_store *dpaa2_io_store_create(unsigned int max_frames,
	struct dpaa2_io_store *ret;
	size_t size;

	if (!max_frames || (max_frames > 16))
	if (!max_frames || (max_frames > 32))
		return NULL;

	ret = kmalloc(sizeof(*ret), GFP_KERNEL);
+70 −13
Original line number Diff line number Diff line
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/*
 * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
 * Copyright 2016 NXP
 * Copyright 2016-2019 NXP
 *
 */

@@ -12,13 +12,6 @@

#include "qbman-portal.h"

#define QMAN_REV_4000   0x04000000
#define QMAN_REV_4100   0x04010000
#define QMAN_REV_4101   0x04010001
#define QMAN_REV_5000   0x05000000

#define QMAN_REV_MASK   0xffff0000

/* All QBMan command and result structures use this "valid bit" encoding */
#define QB_VALID_BIT ((u32)0x80)

@@ -156,7 +149,7 @@ static inline u32 qbman_set_swp_cfg(u8 max_fill, u8 wn, u8 est, u8 rpm, u8 dcm,
 */
struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d)
{
	struct qbman_swp *p = kmalloc(sizeof(*p), GFP_KERNEL);
	struct qbman_swp *p = kzalloc(sizeof(*p), GFP_KERNEL);
	u32 reg;

	if (!p)
@@ -467,22 +460,32 @@ static inline void qbman_write_eqcr_am_rt_register(struct qbman_swp *p,
int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d,
		      const struct dpaa2_fd *fd)
{
	struct qbman_eq_desc *p;
	struct qbman_eq_desc_with_fd *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);
	/* This is mapped as DEVICE type memory, writes are
	 * with address alignment:
	 * desc.dca address alignment = 1
	 * desc.seqnum address alignment = 2
	 * desc.orpid address alignment = 4
	 * desc.tgtid address alignment = 8
	 */
	p->desc.dca = d->dca;
	p->desc.seqnum = d->seqnum;
	p->desc.orpid = d->orpid;
	memcpy(&p->desc.tgtid, &d->tgtid, 24);
	memcpy(&p->fd, fd, sizeof(*fd));

	if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) {
		/* Set the verb byte, have to substitute in the valid-bit */
		dma_wmb();
		p->verb = d->verb | EQAR_VB(eqar);
		p->desc.verb = d->verb | EQAR_VB(eqar);
	} else {
		p->verb = d->verb | EQAR_VB(eqar);
		p->desc.verb = d->verb | EQAR_VB(eqar);
		dma_wmb();
		qbman_write_eqcr_am_rt_register(s, EQAR_IDX(eqar));
	}
@@ -490,6 +493,60 @@ int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d,
	return 0;
}

/**
 * qbman_swp_enqueue_multiple() - Issue a multi enqueue command
 * using one enqueue descriptor
 * @s:  the software portal used for enqueue
 * @d:  the enqueue descriptor
 * @fd: table pointer of frame descriptor table to be enqueued
 * @flags: table pointer of flags, not used for the moment
 * @num_frames: number of fd to be enqueued
 *
 * Return the number of fd enqueued, or a negative error number.
 */
int qbman_swp_enqueue_multiple(struct qbman_swp *s,
			       const struct qbman_eq_desc *d,
			       const struct dpaa2_fd *fd,
			       uint32_t *flags,
			       int num_frames)
{
	int count = 0;

	while (count < num_frames) {
		if (qbman_swp_enqueue(s, d, fd) != 0)
			break;
		count++;
	}

	return count;
}

/**
 * qbman_swp_enqueue_multiple_desc() - Issue a multi enqueue command
 * using multiple enqueue descriptor
 * @s:  the software portal used for enqueue
 * @d:  table of minimal enqueue descriptor
 * @fd: table pointer of frame descriptor table to be enqueued
 * @num_frames: number of fd to be enqueued
 *
 * Return the number of fd enqueued, or a negative error number.
 */
int qbman_swp_enqueue_multiple_desc(struct qbman_swp *s,
				    const struct qbman_eq_desc *d,
				    const struct dpaa2_fd *fd,
				    int num_frames)
{
	int count = 0;

	while (count < num_frames) {
		if (qbman_swp_enqueue(s, &(d[count]), fd) != 0)
			break;
		count++;
	}

	return count;
}

/* Static (push) dequeue */

/**
+24 −0
Original line number Diff line number Diff line
@@ -9,6 +9,13 @@

#include <soc/fsl/dpaa2-fd.h>

#define QMAN_REV_4000   0x04000000
#define QMAN_REV_4100   0x04010000
#define QMAN_REV_4101   0x04010001
#define QMAN_REV_5000   0x05000000

#define QMAN_REV_MASK   0xffff0000

struct dpaa2_dq;
struct qbman_swp;

@@ -81,6 +88,10 @@ struct qbman_eq_desc {
	u8 wae;
	u8 rspid;
	__le64 rsp_addr;
};

struct qbman_eq_desc_with_fd {
	struct qbman_eq_desc desc;
	u8 fd[32];
};

@@ -193,6 +204,19 @@ void *qbman_swp_mc_start(struct qbman_swp *p);
void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, u8 cmd_verb);
void *qbman_swp_mc_result(struct qbman_swp *p);

int
qbman_swp_enqueue_multiple(struct qbman_swp *s,
			   const struct qbman_eq_desc *d,
			   const struct dpaa2_fd *fd,
			   uint32_t *flags,
			   int num_frames);

int
qbman_swp_enqueue_multiple_desc(struct qbman_swp *s,
				const struct qbman_eq_desc *d,
				const struct dpaa2_fd *fd,
				int num_frames);

/**
 * qbman_result_is_DQ() - check if the dequeue result is a dequeue response
 * @dq: the dequeue result to be checked
+5 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
/*
 * Copyright 2014-2016 Freescale Semiconductor Inc.
 * Copyright NXP
 * Copyright 2017-2019 NXP
 *
 */
#ifndef __FSL_DPAA2_IO_H
@@ -109,6 +109,10 @@ int dpaa2_io_service_pull_channel(struct dpaa2_io *d, u32 channelid,

int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d, u32 fqid,
				const struct dpaa2_fd *fd);
int dpaa2_io_service_enqueue_multiple_fq(struct dpaa2_io *d, u32 fqid,
				const struct dpaa2_fd *fd, int number_of_frame);
int dpaa2_io_service_enqueue_multiple_desc_fq(struct dpaa2_io *d, u32 *fqid,
				const struct dpaa2_fd *fd, int number_of_frame);
int dpaa2_io_service_enqueue_qd(struct dpaa2_io *d, u32 qdid, u8 prio,
				u16 qdbin, const struct dpaa2_fd *fd);
int dpaa2_io_service_release(struct dpaa2_io *d, u16 bpid,