Commit 3a3052f1 authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

Merge tag 'soc-fsl-next-v5.7' of...

Merge tag 'soc-fsl-next-v5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/leo/linux into arm/drivers

NXP/FSL SoC driver updates for v5.7

DPAA2 DPIO driver performance optimization
- Add and use QMAN multiple enqueue interface
- Use function pointer indirection to replace checks in hotpath

QUICC Engine drivers
- Fix sparse warnings and exposed endian issues

* tag 'soc-fsl-next-v5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/leo/linux:
  soc: fsl: qe: fix sparse warnings for ucc_slow.c
  soc: fsl: qe: ucc_slow: remove 0 assignment for kzalloc'ed structure
  soc: fsl: qe: fix sparse warnings for ucc_fast.c
  soc: fsl: qe: fix sparse warnings for qe_ic.c
  soc: fsl: qe: fix sparse warnings for ucc.c
  soc: fsl: qe: fix sparse warning for qe_common.c
  soc: fsl: qe: fix sparse warnings for qe.c
  soc: fsl: dpio: fix dereference of pointer p before null check
  soc: fsl: dpio: Replace QMAN array mode with ring mode enqueue
  soc: fsl: dpio: QMAN performance improvement with function pointer indirection
  soc: fsl: dpio: Adding QMAN multiple enqueue interface

Link: https://lore.kernel.org/r/20200326001257.22696-1-leoyang.li@nxp.com


Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents 575c809a 461c3ac0
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);
+686 −81

File changed.

Preview size limit exceeded, changes collapsed.

+151 −7
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];
};

@@ -132,8 +143,48 @@ struct qbman_swp {
		u8 dqrr_size;
		int reset_bug; /* indicates dqrr reset workaround is needed */
	} dqrr;

	struct {
		u32 pi;
		u32 pi_vb;
		u32 pi_ring_size;
		u32 pi_ci_mask;
		u32 ci;
		int available;
		u32 pend;
		u32 no_pfdr;
	} eqcr;

	spinlock_t access_spinlock;
};

/* Function pointers */
extern
int (*qbman_swp_enqueue_ptr)(struct qbman_swp *s,
			     const struct qbman_eq_desc *d,
			     const struct dpaa2_fd *fd);
extern
int (*qbman_swp_enqueue_multiple_ptr)(struct qbman_swp *s,
				      const struct qbman_eq_desc *d,
				      const struct dpaa2_fd *fd,
				      uint32_t *flags,
				      int num_frames);
extern
int (*qbman_swp_enqueue_multiple_desc_ptr)(struct qbman_swp *s,
					   const struct qbman_eq_desc *d,
					   const struct dpaa2_fd *fd,
					   int num_frames);
extern
int (*qbman_swp_pull_ptr)(struct qbman_swp *s, struct qbman_pull_desc *d);
extern
const struct dpaa2_dq *(*qbman_swp_dqrr_next_ptr)(struct qbman_swp *s);
extern
int (*qbman_swp_release_ptr)(struct qbman_swp *s,
			     const struct qbman_release_desc *d,
			     const u64 *buffers,
			     unsigned int num_buffers);

/* Functions */
struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d);
void qbman_swp_finish(struct qbman_swp *p);
u32 qbman_swp_interrupt_read_status(struct qbman_swp *p);
@@ -158,9 +209,6 @@ void qbman_pull_desc_set_wq(struct qbman_pull_desc *d, u32 wqid,
void qbman_pull_desc_set_channel(struct qbman_pull_desc *d, u32 chid,
				 enum qbman_pull_type_e dct);

int qbman_swp_pull(struct qbman_swp *p, struct qbman_pull_desc *d);

const struct dpaa2_dq *qbman_swp_dqrr_next(struct qbman_swp *s);
void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct dpaa2_dq *dq);

int qbman_result_has_new_result(struct qbman_swp *p, const struct dpaa2_dq *dq);
@@ -172,15 +220,11 @@ void qbman_eq_desc_set_fq(struct qbman_eq_desc *d, u32 fqid);
void qbman_eq_desc_set_qd(struct qbman_eq_desc *d, u32 qdid,
			  u32 qd_bin, u32 qd_prio);

int qbman_swp_enqueue(struct qbman_swp *p, const struct qbman_eq_desc *d,
		      const struct dpaa2_fd *fd);

void qbman_release_desc_clear(struct qbman_release_desc *d);
void qbman_release_desc_set_bpid(struct qbman_release_desc *d, u16 bpid);
void qbman_release_desc_set_rcdi(struct qbman_release_desc *d, int enable);

int qbman_swp_release(struct qbman_swp *s, const struct qbman_release_desc *d,
		      const u64 *buffers, unsigned int num_buffers);
int qbman_swp_acquire(struct qbman_swp *s, u16 bpid, u64 *buffers,
		      unsigned int num_buffers);
int qbman_swp_alt_fq_state(struct qbman_swp *s, u32 fqid,
@@ -193,6 +237,61 @@ 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);

/**
 * 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
 *
 * Return 0 for successful enqueue, -EBUSY if the EQCR is not ready.
 */
static inline int
qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d,
		  const struct dpaa2_fd *fd)
{
	return qbman_swp_enqueue_ptr(s, d, fd);
}

/**
 * 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 QBMAN_ENQUEUE_FLAG_DCA flags, not used if NULL
 * @num_frames: number of fd to be enqueued
 *
 * Return the number of fd enqueued, or a negative error number.
 */
static inline 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)
{
	return qbman_swp_enqueue_multiple_ptr(s, d, fd, flags, num_frames);
}

/**
 * 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.
 */
static inline int
qbman_swp_enqueue_multiple_desc(struct qbman_swp *s,
				const struct qbman_eq_desc *d,
				const struct dpaa2_fd *fd,
				int num_frames)
{
	return qbman_swp_enqueue_multiple_desc_ptr(s, d, fd, num_frames);
}

/**
 * qbman_result_is_DQ() - check if the dequeue result is a dequeue response
 * @dq: the dequeue result to be checked
@@ -504,4 +603,49 @@ int qbman_bp_query(struct qbman_swp *s, u16 bpid,

u32 qbman_bp_info_num_free_bufs(struct qbman_bp_query_rslt *a);

/**
 * qbman_swp_release() - Issue a buffer release command
 * @s:           the software portal object
 * @d:           the release descriptor
 * @buffers:     a pointer pointing to the buffer address to be released
 * @num_buffers: number of buffers to be released,  must be less than 8
 *
 * Return 0 for success, -EBUSY if the release command ring is not ready.
 */
static inline int qbman_swp_release(struct qbman_swp *s,
				    const struct qbman_release_desc *d,
				    const u64 *buffers,
				    unsigned int num_buffers)
{
	return qbman_swp_release_ptr(s, d, buffers, num_buffers);
}

/**
 * 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.
 */
static inline int qbman_swp_pull(struct qbman_swp *s,
				 struct qbman_pull_desc *d)
{
	return qbman_swp_pull_ptr(s, d);
}

/**
 * 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.
 */
static inline const struct dpaa2_dq *qbman_swp_dqrr_next(struct qbman_swp *s)
{
	return qbman_swp_dqrr_next_ptr(s);
}

#endif /* __FSL_QBMAN_PORTAL_H */
+2 −2
Original line number Diff line number Diff line
@@ -423,7 +423,7 @@ static void qe_upload_microcode(const void *base,
		qe_iowrite32be(be32_to_cpu(code[i]), &qe_immr->iram.idata);
	
	/* Set I-RAM Ready Register */
	qe_iowrite32be(be32_to_cpu(QE_IRAM_READY), &qe_immr->iram.iready);
	qe_iowrite32be(QE_IRAM_READY, &qe_immr->iram.iready);
}

/*
@@ -525,7 +525,7 @@ int qe_upload_firmware(const struct qe_firmware *firmware)
	 */
	memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
	strlcpy(qe_firmware_info.id, firmware->id, sizeof(qe_firmware_info.id));
	qe_firmware_info.extended_modes = firmware->extended_modes;
	qe_firmware_info.extended_modes = be64_to_cpu(firmware->extended_modes);
	memcpy(qe_firmware_info.vtraps, firmware->vtraps,
		sizeof(firmware->vtraps));

+1 −1
Original line number Diff line number Diff line
@@ -46,7 +46,7 @@ int cpm_muram_init(void)
{
	struct device_node *np;
	struct resource r;
	u32 zero[OF_MAX_ADDR_CELLS] = {};
	__be32 zero[OF_MAX_ADDR_CELLS] = {};
	resource_size_t max = 0;
	int i = 0;
	int ret = 0;
Loading