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: Youri Querry <youri.querry_1@nxp.com>
Acked-by: Roy Pledge <roy.pledge@nxp.com>
Signed-off-by: Li Yang <leoyang.li@nxp.com>
This commit is contained in:
Youri Querry 2019-12-12 17:01:13 +00:00 committed by Li Yang
parent bb6d3fb354
commit 9d98809711
4 changed files with 165 additions and 17 deletions

View File

@ -1,7 +1,7 @@
// 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);

View File

@ -1,7 +1,7 @@
// 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 */
/**

View File

@ -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

View File

@ -1,7 +1,7 @@
/* 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,