18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. 48c2ecf20Sopenharmony_ci * Copyright 2016-2019 NXP 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <asm/cacheflush.h> 98c2ecf20Sopenharmony_ci#include <linux/io.h> 108c2ecf20Sopenharmony_ci#include <linux/slab.h> 118c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 128c2ecf20Sopenharmony_ci#include <soc/fsl/dpaa2-global.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include "qbman-portal.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci/* All QBMan command and result structures use this "valid bit" encoding */ 178c2ecf20Sopenharmony_ci#define QB_VALID_BIT ((u32)0x80) 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci/* QBMan portal management command codes */ 208c2ecf20Sopenharmony_ci#define QBMAN_MC_ACQUIRE 0x30 218c2ecf20Sopenharmony_ci#define QBMAN_WQCHAN_CONFIGURE 0x46 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci/* CINH register offsets */ 248c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_EQCR_PI 0x800 258c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_EQCR_CI 0x840 268c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_EQAR 0x8c0 278c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_CR_RT 0x900 288c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_VDQCR_RT 0x940 298c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_EQCR_AM_RT 0x980 308c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_RCR_AM_RT 0x9c0 318c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_DQPI 0xa00 328c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_DCAP 0xac0 338c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_SDQCR 0xb00 348c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_EQCR_AM_RT2 0xb40 358c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_RCR_PI 0xc00 368c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_RAR 0xcc0 378c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_ISR 0xe00 388c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_IER 0xe40 398c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_ISDR 0xe80 408c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_IIR 0xec0 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* CENA register offsets */ 438c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_EQCR(n) (0x000 + ((u32)(n) << 6)) 448c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_DQRR(n) (0x200 + ((u32)(n) << 6)) 458c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_RCR(n) (0x400 + ((u32)(n) << 6)) 468c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_CR 0x600 478c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_RR(vb) (0x700 + ((u32)(vb) >> 1)) 488c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_VDQCR 0x780 498c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_EQCR_CI 0x840 508c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_EQCR_CI_MEMBACK 0x1840 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci/* CENA register offsets in memory-backed mode */ 538c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_DQRR_MEM(n) (0x800 + ((u32)(n) << 6)) 548c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_RCR_MEM(n) (0x1400 + ((u32)(n) << 6)) 558c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_CR_MEM 0x1600 568c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_RR_MEM 0x1680 578c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_VDQCR_MEM 0x1780 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci/* Reverse mapping of QBMAN_CENA_SWP_DQRR() */ 608c2ecf20Sopenharmony_ci#define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)(p) & 0x1ff) >> 6) 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci/* Define token used to determine if response written to memory is valid */ 638c2ecf20Sopenharmony_ci#define QMAN_DQ_TOKEN_VALID 1 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci/* SDQCR attribute codes */ 668c2ecf20Sopenharmony_ci#define QB_SDQCR_FC_SHIFT 29 678c2ecf20Sopenharmony_ci#define QB_SDQCR_FC_MASK 0x1 688c2ecf20Sopenharmony_ci#define QB_SDQCR_DCT_SHIFT 24 698c2ecf20Sopenharmony_ci#define QB_SDQCR_DCT_MASK 0x3 708c2ecf20Sopenharmony_ci#define QB_SDQCR_TOK_SHIFT 16 718c2ecf20Sopenharmony_ci#define QB_SDQCR_TOK_MASK 0xff 728c2ecf20Sopenharmony_ci#define QB_SDQCR_SRC_SHIFT 0 738c2ecf20Sopenharmony_ci#define QB_SDQCR_SRC_MASK 0xffff 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci/* opaque token for static dequeues */ 768c2ecf20Sopenharmony_ci#define QMAN_SDQCR_TOKEN 0xbb 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci#define QBMAN_EQCR_DCA_IDXMASK 0x0f 798c2ecf20Sopenharmony_ci#define QBMAN_ENQUEUE_FLAG_DCA (1ULL << 31) 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci#define EQ_DESC_SIZE_WITHOUT_FD 29 828c2ecf20Sopenharmony_ci#define EQ_DESC_SIZE_FD_START 32 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cienum qbman_sdqcr_dct { 858c2ecf20Sopenharmony_ci qbman_sdqcr_dct_null = 0, 868c2ecf20Sopenharmony_ci qbman_sdqcr_dct_prio_ics, 878c2ecf20Sopenharmony_ci qbman_sdqcr_dct_active_ics, 888c2ecf20Sopenharmony_ci qbman_sdqcr_dct_active 898c2ecf20Sopenharmony_ci}; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cienum qbman_sdqcr_fc { 928c2ecf20Sopenharmony_ci qbman_sdqcr_fc_one = 0, 938c2ecf20Sopenharmony_ci qbman_sdqcr_fc_up_to_3 = 1 948c2ecf20Sopenharmony_ci}; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci/* Internal Function declaration */ 978c2ecf20Sopenharmony_cistatic int qbman_swp_enqueue_direct(struct qbman_swp *s, 988c2ecf20Sopenharmony_ci const struct qbman_eq_desc *d, 998c2ecf20Sopenharmony_ci const struct dpaa2_fd *fd); 1008c2ecf20Sopenharmony_cistatic int qbman_swp_enqueue_mem_back(struct qbman_swp *s, 1018c2ecf20Sopenharmony_ci const struct qbman_eq_desc *d, 1028c2ecf20Sopenharmony_ci const struct dpaa2_fd *fd); 1038c2ecf20Sopenharmony_cistatic int qbman_swp_enqueue_multiple_direct(struct qbman_swp *s, 1048c2ecf20Sopenharmony_ci const struct qbman_eq_desc *d, 1058c2ecf20Sopenharmony_ci const struct dpaa2_fd *fd, 1068c2ecf20Sopenharmony_ci uint32_t *flags, 1078c2ecf20Sopenharmony_ci int num_frames); 1088c2ecf20Sopenharmony_cistatic int qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s, 1098c2ecf20Sopenharmony_ci const struct qbman_eq_desc *d, 1108c2ecf20Sopenharmony_ci const struct dpaa2_fd *fd, 1118c2ecf20Sopenharmony_ci uint32_t *flags, 1128c2ecf20Sopenharmony_ci int num_frames); 1138c2ecf20Sopenharmony_cistatic int 1148c2ecf20Sopenharmony_ciqbman_swp_enqueue_multiple_desc_direct(struct qbman_swp *s, 1158c2ecf20Sopenharmony_ci const struct qbman_eq_desc *d, 1168c2ecf20Sopenharmony_ci const struct dpaa2_fd *fd, 1178c2ecf20Sopenharmony_ci int num_frames); 1188c2ecf20Sopenharmony_cistatic 1198c2ecf20Sopenharmony_ciint qbman_swp_enqueue_multiple_desc_mem_back(struct qbman_swp *s, 1208c2ecf20Sopenharmony_ci const struct qbman_eq_desc *d, 1218c2ecf20Sopenharmony_ci const struct dpaa2_fd *fd, 1228c2ecf20Sopenharmony_ci int num_frames); 1238c2ecf20Sopenharmony_cistatic int qbman_swp_pull_direct(struct qbman_swp *s, 1248c2ecf20Sopenharmony_ci struct qbman_pull_desc *d); 1258c2ecf20Sopenharmony_cistatic int qbman_swp_pull_mem_back(struct qbman_swp *s, 1268c2ecf20Sopenharmony_ci struct qbman_pull_desc *d); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ciconst struct dpaa2_dq *qbman_swp_dqrr_next_direct(struct qbman_swp *s); 1298c2ecf20Sopenharmony_ciconst struct dpaa2_dq *qbman_swp_dqrr_next_mem_back(struct qbman_swp *s); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cistatic int qbman_swp_release_direct(struct qbman_swp *s, 1328c2ecf20Sopenharmony_ci const struct qbman_release_desc *d, 1338c2ecf20Sopenharmony_ci const u64 *buffers, 1348c2ecf20Sopenharmony_ci unsigned int num_buffers); 1358c2ecf20Sopenharmony_cistatic int qbman_swp_release_mem_back(struct qbman_swp *s, 1368c2ecf20Sopenharmony_ci const struct qbman_release_desc *d, 1378c2ecf20Sopenharmony_ci const u64 *buffers, 1388c2ecf20Sopenharmony_ci unsigned int num_buffers); 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci/* Function pointers */ 1418c2ecf20Sopenharmony_ciint (*qbman_swp_enqueue_ptr)(struct qbman_swp *s, 1428c2ecf20Sopenharmony_ci const struct qbman_eq_desc *d, 1438c2ecf20Sopenharmony_ci const struct dpaa2_fd *fd) 1448c2ecf20Sopenharmony_ci = qbman_swp_enqueue_direct; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ciint (*qbman_swp_enqueue_multiple_ptr)(struct qbman_swp *s, 1478c2ecf20Sopenharmony_ci const struct qbman_eq_desc *d, 1488c2ecf20Sopenharmony_ci const struct dpaa2_fd *fd, 1498c2ecf20Sopenharmony_ci uint32_t *flags, 1508c2ecf20Sopenharmony_ci int num_frames) 1518c2ecf20Sopenharmony_ci = qbman_swp_enqueue_multiple_direct; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ciint 1548c2ecf20Sopenharmony_ci(*qbman_swp_enqueue_multiple_desc_ptr)(struct qbman_swp *s, 1558c2ecf20Sopenharmony_ci const struct qbman_eq_desc *d, 1568c2ecf20Sopenharmony_ci const struct dpaa2_fd *fd, 1578c2ecf20Sopenharmony_ci int num_frames) 1588c2ecf20Sopenharmony_ci = qbman_swp_enqueue_multiple_desc_direct; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ciint (*qbman_swp_pull_ptr)(struct qbman_swp *s, struct qbman_pull_desc *d) 1618c2ecf20Sopenharmony_ci = qbman_swp_pull_direct; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ciconst struct dpaa2_dq *(*qbman_swp_dqrr_next_ptr)(struct qbman_swp *s) 1648c2ecf20Sopenharmony_ci = qbman_swp_dqrr_next_direct; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ciint (*qbman_swp_release_ptr)(struct qbman_swp *s, 1678c2ecf20Sopenharmony_ci const struct qbman_release_desc *d, 1688c2ecf20Sopenharmony_ci const u64 *buffers, 1698c2ecf20Sopenharmony_ci unsigned int num_buffers) 1708c2ecf20Sopenharmony_ci = qbman_swp_release_direct; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci/* Portal Access */ 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_cistatic inline u32 qbman_read_register(struct qbman_swp *p, u32 offset) 1758c2ecf20Sopenharmony_ci{ 1768c2ecf20Sopenharmony_ci return readl_relaxed(p->addr_cinh + offset); 1778c2ecf20Sopenharmony_ci} 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_cistatic inline void qbman_write_register(struct qbman_swp *p, u32 offset, 1808c2ecf20Sopenharmony_ci u32 value) 1818c2ecf20Sopenharmony_ci{ 1828c2ecf20Sopenharmony_ci writel_relaxed(value, p->addr_cinh + offset); 1838c2ecf20Sopenharmony_ci} 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_cistatic inline void *qbman_get_cmd(struct qbman_swp *p, u32 offset) 1868c2ecf20Sopenharmony_ci{ 1878c2ecf20Sopenharmony_ci return p->addr_cena + offset; 1888c2ecf20Sopenharmony_ci} 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_CFG 0xd00 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci#define SWP_CFG_DQRR_MF_SHIFT 20 1938c2ecf20Sopenharmony_ci#define SWP_CFG_EST_SHIFT 16 1948c2ecf20Sopenharmony_ci#define SWP_CFG_CPBS_SHIFT 15 1958c2ecf20Sopenharmony_ci#define SWP_CFG_WN_SHIFT 14 1968c2ecf20Sopenharmony_ci#define SWP_CFG_RPM_SHIFT 12 1978c2ecf20Sopenharmony_ci#define SWP_CFG_DCM_SHIFT 10 1988c2ecf20Sopenharmony_ci#define SWP_CFG_EPM_SHIFT 8 1998c2ecf20Sopenharmony_ci#define SWP_CFG_VPM_SHIFT 7 2008c2ecf20Sopenharmony_ci#define SWP_CFG_CPM_SHIFT 6 2018c2ecf20Sopenharmony_ci#define SWP_CFG_SD_SHIFT 5 2028c2ecf20Sopenharmony_ci#define SWP_CFG_SP_SHIFT 4 2038c2ecf20Sopenharmony_ci#define SWP_CFG_SE_SHIFT 3 2048c2ecf20Sopenharmony_ci#define SWP_CFG_DP_SHIFT 2 2058c2ecf20Sopenharmony_ci#define SWP_CFG_DE_SHIFT 1 2068c2ecf20Sopenharmony_ci#define SWP_CFG_EP_SHIFT 0 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_cistatic inline u32 qbman_set_swp_cfg(u8 max_fill, u8 wn, u8 est, u8 rpm, u8 dcm, 2098c2ecf20Sopenharmony_ci u8 epm, int sd, int sp, int se, 2108c2ecf20Sopenharmony_ci int dp, int de, int ep) 2118c2ecf20Sopenharmony_ci{ 2128c2ecf20Sopenharmony_ci return (max_fill << SWP_CFG_DQRR_MF_SHIFT | 2138c2ecf20Sopenharmony_ci est << SWP_CFG_EST_SHIFT | 2148c2ecf20Sopenharmony_ci wn << SWP_CFG_WN_SHIFT | 2158c2ecf20Sopenharmony_ci rpm << SWP_CFG_RPM_SHIFT | 2168c2ecf20Sopenharmony_ci dcm << SWP_CFG_DCM_SHIFT | 2178c2ecf20Sopenharmony_ci epm << SWP_CFG_EPM_SHIFT | 2188c2ecf20Sopenharmony_ci sd << SWP_CFG_SD_SHIFT | 2198c2ecf20Sopenharmony_ci sp << SWP_CFG_SP_SHIFT | 2208c2ecf20Sopenharmony_ci se << SWP_CFG_SE_SHIFT | 2218c2ecf20Sopenharmony_ci dp << SWP_CFG_DP_SHIFT | 2228c2ecf20Sopenharmony_ci de << SWP_CFG_DE_SHIFT | 2238c2ecf20Sopenharmony_ci ep << SWP_CFG_EP_SHIFT); 2248c2ecf20Sopenharmony_ci} 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci#define QMAN_RT_MODE 0x00000100 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_cistatic inline u8 qm_cyc_diff(u8 ringsize, u8 first, u8 last) 2298c2ecf20Sopenharmony_ci{ 2308c2ecf20Sopenharmony_ci /* 'first' is included, 'last' is excluded */ 2318c2ecf20Sopenharmony_ci if (first <= last) 2328c2ecf20Sopenharmony_ci return last - first; 2338c2ecf20Sopenharmony_ci else 2348c2ecf20Sopenharmony_ci return (2 * ringsize) - (first - last); 2358c2ecf20Sopenharmony_ci} 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci/** 2388c2ecf20Sopenharmony_ci * qbman_swp_init() - Create a functional object representing the given 2398c2ecf20Sopenharmony_ci * QBMan portal descriptor. 2408c2ecf20Sopenharmony_ci * @d: the given qbman swp descriptor 2418c2ecf20Sopenharmony_ci * 2428c2ecf20Sopenharmony_ci * Return qbman_swp portal for success, NULL if the object cannot 2438c2ecf20Sopenharmony_ci * be created. 2448c2ecf20Sopenharmony_ci */ 2458c2ecf20Sopenharmony_cistruct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) 2468c2ecf20Sopenharmony_ci{ 2478c2ecf20Sopenharmony_ci struct qbman_swp *p = kzalloc(sizeof(*p), GFP_KERNEL); 2488c2ecf20Sopenharmony_ci u32 reg; 2498c2ecf20Sopenharmony_ci u32 mask_size; 2508c2ecf20Sopenharmony_ci u32 eqcr_pi; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci if (!p) 2538c2ecf20Sopenharmony_ci return NULL; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci spin_lock_init(&p->access_spinlock); 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci p->desc = d; 2588c2ecf20Sopenharmony_ci p->mc.valid_bit = QB_VALID_BIT; 2598c2ecf20Sopenharmony_ci p->sdq = 0; 2608c2ecf20Sopenharmony_ci p->sdq |= qbman_sdqcr_dct_prio_ics << QB_SDQCR_DCT_SHIFT; 2618c2ecf20Sopenharmony_ci p->sdq |= qbman_sdqcr_fc_up_to_3 << QB_SDQCR_FC_SHIFT; 2628c2ecf20Sopenharmony_ci p->sdq |= QMAN_SDQCR_TOKEN << QB_SDQCR_TOK_SHIFT; 2638c2ecf20Sopenharmony_ci if ((p->desc->qman_version & QMAN_REV_MASK) >= QMAN_REV_5000) 2648c2ecf20Sopenharmony_ci p->mr.valid_bit = QB_VALID_BIT; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci atomic_set(&p->vdq.available, 1); 2678c2ecf20Sopenharmony_ci p->vdq.valid_bit = QB_VALID_BIT; 2688c2ecf20Sopenharmony_ci p->dqrr.next_idx = 0; 2698c2ecf20Sopenharmony_ci p->dqrr.valid_bit = QB_VALID_BIT; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci if ((p->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_4100) { 2728c2ecf20Sopenharmony_ci p->dqrr.dqrr_size = 4; 2738c2ecf20Sopenharmony_ci p->dqrr.reset_bug = 1; 2748c2ecf20Sopenharmony_ci } else { 2758c2ecf20Sopenharmony_ci p->dqrr.dqrr_size = 8; 2768c2ecf20Sopenharmony_ci p->dqrr.reset_bug = 0; 2778c2ecf20Sopenharmony_ci } 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci p->addr_cena = d->cena_bar; 2808c2ecf20Sopenharmony_ci p->addr_cinh = d->cinh_bar; 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci if ((p->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) { 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci reg = qbman_set_swp_cfg(p->dqrr.dqrr_size, 2858c2ecf20Sopenharmony_ci 1, /* Writes Non-cacheable */ 2868c2ecf20Sopenharmony_ci 0, /* EQCR_CI stashing threshold */ 2878c2ecf20Sopenharmony_ci 3, /* RPM: RCR in array mode */ 2888c2ecf20Sopenharmony_ci 2, /* DCM: Discrete consumption ack */ 2898c2ecf20Sopenharmony_ci 2, /* EPM: EQCR in ring mode */ 2908c2ecf20Sopenharmony_ci 1, /* mem stashing drop enable enable */ 2918c2ecf20Sopenharmony_ci 1, /* mem stashing priority enable */ 2928c2ecf20Sopenharmony_ci 1, /* mem stashing enable */ 2938c2ecf20Sopenharmony_ci 1, /* dequeue stashing priority enable */ 2948c2ecf20Sopenharmony_ci 0, /* dequeue stashing enable enable */ 2958c2ecf20Sopenharmony_ci 0); /* EQCR_CI stashing priority enable */ 2968c2ecf20Sopenharmony_ci } else { 2978c2ecf20Sopenharmony_ci memset(p->addr_cena, 0, 64 * 1024); 2988c2ecf20Sopenharmony_ci reg = qbman_set_swp_cfg(p->dqrr.dqrr_size, 2998c2ecf20Sopenharmony_ci 1, /* Writes Non-cacheable */ 3008c2ecf20Sopenharmony_ci 1, /* EQCR_CI stashing threshold */ 3018c2ecf20Sopenharmony_ci 3, /* RPM: RCR in array mode */ 3028c2ecf20Sopenharmony_ci 2, /* DCM: Discrete consumption ack */ 3038c2ecf20Sopenharmony_ci 0, /* EPM: EQCR in ring mode */ 3048c2ecf20Sopenharmony_ci 1, /* mem stashing drop enable */ 3058c2ecf20Sopenharmony_ci 1, /* mem stashing priority enable */ 3068c2ecf20Sopenharmony_ci 1, /* mem stashing enable */ 3078c2ecf20Sopenharmony_ci 1, /* dequeue stashing priority enable */ 3088c2ecf20Sopenharmony_ci 0, /* dequeue stashing enable */ 3098c2ecf20Sopenharmony_ci 0); /* EQCR_CI stashing priority enable */ 3108c2ecf20Sopenharmony_ci reg |= 1 << SWP_CFG_CPBS_SHIFT | /* memory-backed mode */ 3118c2ecf20Sopenharmony_ci 1 << SWP_CFG_VPM_SHIFT | /* VDQCR read triggered mode */ 3128c2ecf20Sopenharmony_ci 1 << SWP_CFG_CPM_SHIFT; /* CR read triggered mode */ 3138c2ecf20Sopenharmony_ci } 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci qbman_write_register(p, QBMAN_CINH_SWP_CFG, reg); 3168c2ecf20Sopenharmony_ci reg = qbman_read_register(p, QBMAN_CINH_SWP_CFG); 3178c2ecf20Sopenharmony_ci if (!reg) { 3188c2ecf20Sopenharmony_ci pr_err("qbman: the portal is not enabled!\n"); 3198c2ecf20Sopenharmony_ci kfree(p); 3208c2ecf20Sopenharmony_ci return NULL; 3218c2ecf20Sopenharmony_ci } 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci if ((p->desc->qman_version & QMAN_REV_MASK) >= QMAN_REV_5000) { 3248c2ecf20Sopenharmony_ci qbman_write_register(p, QBMAN_CINH_SWP_EQCR_PI, QMAN_RT_MODE); 3258c2ecf20Sopenharmony_ci qbman_write_register(p, QBMAN_CINH_SWP_RCR_PI, QMAN_RT_MODE); 3268c2ecf20Sopenharmony_ci } 3278c2ecf20Sopenharmony_ci /* 3288c2ecf20Sopenharmony_ci * SDQCR needs to be initialized to 0 when no channels are 3298c2ecf20Sopenharmony_ci * being dequeued from or else the QMan HW will indicate an 3308c2ecf20Sopenharmony_ci * error. The values that were calculated above will be 3318c2ecf20Sopenharmony_ci * applied when dequeues from a specific channel are enabled. 3328c2ecf20Sopenharmony_ci */ 3338c2ecf20Sopenharmony_ci qbman_write_register(p, QBMAN_CINH_SWP_SDQCR, 0); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci p->eqcr.pi_ring_size = 8; 3368c2ecf20Sopenharmony_ci if ((p->desc->qman_version & QMAN_REV_MASK) >= QMAN_REV_5000) { 3378c2ecf20Sopenharmony_ci p->eqcr.pi_ring_size = 32; 3388c2ecf20Sopenharmony_ci qbman_swp_enqueue_ptr = 3398c2ecf20Sopenharmony_ci qbman_swp_enqueue_mem_back; 3408c2ecf20Sopenharmony_ci qbman_swp_enqueue_multiple_ptr = 3418c2ecf20Sopenharmony_ci qbman_swp_enqueue_multiple_mem_back; 3428c2ecf20Sopenharmony_ci qbman_swp_enqueue_multiple_desc_ptr = 3438c2ecf20Sopenharmony_ci qbman_swp_enqueue_multiple_desc_mem_back; 3448c2ecf20Sopenharmony_ci qbman_swp_pull_ptr = qbman_swp_pull_mem_back; 3458c2ecf20Sopenharmony_ci qbman_swp_dqrr_next_ptr = qbman_swp_dqrr_next_mem_back; 3468c2ecf20Sopenharmony_ci qbman_swp_release_ptr = qbman_swp_release_mem_back; 3478c2ecf20Sopenharmony_ci } 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci for (mask_size = p->eqcr.pi_ring_size; mask_size > 0; mask_size >>= 1) 3508c2ecf20Sopenharmony_ci p->eqcr.pi_ci_mask = (p->eqcr.pi_ci_mask << 1) + 1; 3518c2ecf20Sopenharmony_ci eqcr_pi = qbman_read_register(p, QBMAN_CINH_SWP_EQCR_PI); 3528c2ecf20Sopenharmony_ci p->eqcr.pi = eqcr_pi & p->eqcr.pi_ci_mask; 3538c2ecf20Sopenharmony_ci p->eqcr.pi_vb = eqcr_pi & QB_VALID_BIT; 3548c2ecf20Sopenharmony_ci p->eqcr.ci = qbman_read_register(p, QBMAN_CINH_SWP_EQCR_CI) 3558c2ecf20Sopenharmony_ci & p->eqcr.pi_ci_mask; 3568c2ecf20Sopenharmony_ci p->eqcr.available = p->eqcr.pi_ring_size; 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci return p; 3598c2ecf20Sopenharmony_ci} 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci/** 3628c2ecf20Sopenharmony_ci * qbman_swp_finish() - Create and destroy a functional object representing 3638c2ecf20Sopenharmony_ci * the given QBMan portal descriptor. 3648c2ecf20Sopenharmony_ci * @p: the qbman_swp object to be destroyed 3658c2ecf20Sopenharmony_ci */ 3668c2ecf20Sopenharmony_civoid qbman_swp_finish(struct qbman_swp *p) 3678c2ecf20Sopenharmony_ci{ 3688c2ecf20Sopenharmony_ci kfree(p); 3698c2ecf20Sopenharmony_ci} 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci/** 3728c2ecf20Sopenharmony_ci * qbman_swp_interrupt_read_status() 3738c2ecf20Sopenharmony_ci * @p: the given software portal 3748c2ecf20Sopenharmony_ci * 3758c2ecf20Sopenharmony_ci * Return the value in the SWP_ISR register. 3768c2ecf20Sopenharmony_ci */ 3778c2ecf20Sopenharmony_ciu32 qbman_swp_interrupt_read_status(struct qbman_swp *p) 3788c2ecf20Sopenharmony_ci{ 3798c2ecf20Sopenharmony_ci return qbman_read_register(p, QBMAN_CINH_SWP_ISR); 3808c2ecf20Sopenharmony_ci} 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci/** 3838c2ecf20Sopenharmony_ci * qbman_swp_interrupt_clear_status() 3848c2ecf20Sopenharmony_ci * @p: the given software portal 3858c2ecf20Sopenharmony_ci * @mask: The mask to clear in SWP_ISR register 3868c2ecf20Sopenharmony_ci */ 3878c2ecf20Sopenharmony_civoid qbman_swp_interrupt_clear_status(struct qbman_swp *p, u32 mask) 3888c2ecf20Sopenharmony_ci{ 3898c2ecf20Sopenharmony_ci qbman_write_register(p, QBMAN_CINH_SWP_ISR, mask); 3908c2ecf20Sopenharmony_ci} 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci/** 3938c2ecf20Sopenharmony_ci * qbman_swp_interrupt_get_trigger() - read interrupt enable register 3948c2ecf20Sopenharmony_ci * @p: the given software portal 3958c2ecf20Sopenharmony_ci * 3968c2ecf20Sopenharmony_ci * Return the value in the SWP_IER register. 3978c2ecf20Sopenharmony_ci */ 3988c2ecf20Sopenharmony_ciu32 qbman_swp_interrupt_get_trigger(struct qbman_swp *p) 3998c2ecf20Sopenharmony_ci{ 4008c2ecf20Sopenharmony_ci return qbman_read_register(p, QBMAN_CINH_SWP_IER); 4018c2ecf20Sopenharmony_ci} 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci/** 4048c2ecf20Sopenharmony_ci * qbman_swp_interrupt_set_trigger() - enable interrupts for a swp 4058c2ecf20Sopenharmony_ci * @p: the given software portal 4068c2ecf20Sopenharmony_ci * @mask: The mask of bits to enable in SWP_IER 4078c2ecf20Sopenharmony_ci */ 4088c2ecf20Sopenharmony_civoid qbman_swp_interrupt_set_trigger(struct qbman_swp *p, u32 mask) 4098c2ecf20Sopenharmony_ci{ 4108c2ecf20Sopenharmony_ci qbman_write_register(p, QBMAN_CINH_SWP_IER, mask); 4118c2ecf20Sopenharmony_ci} 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci/** 4148c2ecf20Sopenharmony_ci * qbman_swp_interrupt_get_inhibit() - read interrupt mask register 4158c2ecf20Sopenharmony_ci * @p: the given software portal object 4168c2ecf20Sopenharmony_ci * 4178c2ecf20Sopenharmony_ci * Return the value in the SWP_IIR register. 4188c2ecf20Sopenharmony_ci */ 4198c2ecf20Sopenharmony_ciint qbman_swp_interrupt_get_inhibit(struct qbman_swp *p) 4208c2ecf20Sopenharmony_ci{ 4218c2ecf20Sopenharmony_ci return qbman_read_register(p, QBMAN_CINH_SWP_IIR); 4228c2ecf20Sopenharmony_ci} 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci/** 4258c2ecf20Sopenharmony_ci * qbman_swp_interrupt_set_inhibit() - write interrupt mask register 4268c2ecf20Sopenharmony_ci * @p: the given software portal object 4278c2ecf20Sopenharmony_ci * @mask: The mask to set in SWP_IIR register 4288c2ecf20Sopenharmony_ci */ 4298c2ecf20Sopenharmony_civoid qbman_swp_interrupt_set_inhibit(struct qbman_swp *p, int inhibit) 4308c2ecf20Sopenharmony_ci{ 4318c2ecf20Sopenharmony_ci qbman_write_register(p, QBMAN_CINH_SWP_IIR, inhibit ? 0xffffffff : 0); 4328c2ecf20Sopenharmony_ci} 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci/* 4358c2ecf20Sopenharmony_ci * Different management commands all use this common base layer of code to issue 4368c2ecf20Sopenharmony_ci * commands and poll for results. 4378c2ecf20Sopenharmony_ci */ 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci/* 4408c2ecf20Sopenharmony_ci * Returns a pointer to where the caller should fill in their management command 4418c2ecf20Sopenharmony_ci * (caller should ignore the verb byte) 4428c2ecf20Sopenharmony_ci */ 4438c2ecf20Sopenharmony_civoid *qbman_swp_mc_start(struct qbman_swp *p) 4448c2ecf20Sopenharmony_ci{ 4458c2ecf20Sopenharmony_ci if ((p->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) 4468c2ecf20Sopenharmony_ci return qbman_get_cmd(p, QBMAN_CENA_SWP_CR); 4478c2ecf20Sopenharmony_ci else 4488c2ecf20Sopenharmony_ci return qbman_get_cmd(p, QBMAN_CENA_SWP_CR_MEM); 4498c2ecf20Sopenharmony_ci} 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci/* 4528c2ecf20Sopenharmony_ci * Commits merges in the caller-supplied command verb (which should not include 4538c2ecf20Sopenharmony_ci * the valid-bit) and submits the command to hardware 4548c2ecf20Sopenharmony_ci */ 4558c2ecf20Sopenharmony_civoid qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, u8 cmd_verb) 4568c2ecf20Sopenharmony_ci{ 4578c2ecf20Sopenharmony_ci u8 *v = cmd; 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci if ((p->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) { 4608c2ecf20Sopenharmony_ci dma_wmb(); 4618c2ecf20Sopenharmony_ci *v = cmd_verb | p->mc.valid_bit; 4628c2ecf20Sopenharmony_ci } else { 4638c2ecf20Sopenharmony_ci *v = cmd_verb | p->mc.valid_bit; 4648c2ecf20Sopenharmony_ci dma_wmb(); 4658c2ecf20Sopenharmony_ci qbman_write_register(p, QBMAN_CINH_SWP_CR_RT, QMAN_RT_MODE); 4668c2ecf20Sopenharmony_ci } 4678c2ecf20Sopenharmony_ci} 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci/* 4708c2ecf20Sopenharmony_ci * Checks for a completed response (returns non-NULL if only if the response 4718c2ecf20Sopenharmony_ci * is complete). 4728c2ecf20Sopenharmony_ci */ 4738c2ecf20Sopenharmony_civoid *qbman_swp_mc_result(struct qbman_swp *p) 4748c2ecf20Sopenharmony_ci{ 4758c2ecf20Sopenharmony_ci u32 *ret, verb; 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci if ((p->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) { 4788c2ecf20Sopenharmony_ci ret = qbman_get_cmd(p, QBMAN_CENA_SWP_RR(p->mc.valid_bit)); 4798c2ecf20Sopenharmony_ci /* Remove the valid-bit - command completed if the rest 4808c2ecf20Sopenharmony_ci * is non-zero. 4818c2ecf20Sopenharmony_ci */ 4828c2ecf20Sopenharmony_ci verb = ret[0] & ~QB_VALID_BIT; 4838c2ecf20Sopenharmony_ci if (!verb) 4848c2ecf20Sopenharmony_ci return NULL; 4858c2ecf20Sopenharmony_ci p->mc.valid_bit ^= QB_VALID_BIT; 4868c2ecf20Sopenharmony_ci } else { 4878c2ecf20Sopenharmony_ci ret = qbman_get_cmd(p, QBMAN_CENA_SWP_RR_MEM); 4888c2ecf20Sopenharmony_ci /* Command completed if the valid bit is toggled */ 4898c2ecf20Sopenharmony_ci if (p->mr.valid_bit != (ret[0] & QB_VALID_BIT)) 4908c2ecf20Sopenharmony_ci return NULL; 4918c2ecf20Sopenharmony_ci /* Command completed if the rest is non-zero */ 4928c2ecf20Sopenharmony_ci verb = ret[0] & ~QB_VALID_BIT; 4938c2ecf20Sopenharmony_ci if (!verb) 4948c2ecf20Sopenharmony_ci return NULL; 4958c2ecf20Sopenharmony_ci p->mr.valid_bit ^= QB_VALID_BIT; 4968c2ecf20Sopenharmony_ci } 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci return ret; 4998c2ecf20Sopenharmony_ci} 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci#define QB_ENQUEUE_CMD_OPTIONS_SHIFT 0 5028c2ecf20Sopenharmony_cienum qb_enqueue_commands { 5038c2ecf20Sopenharmony_ci enqueue_empty = 0, 5048c2ecf20Sopenharmony_ci enqueue_response_always = 1, 5058c2ecf20Sopenharmony_ci enqueue_rejects_to_fq = 2 5068c2ecf20Sopenharmony_ci}; 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci#define QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT 2 5098c2ecf20Sopenharmony_ci#define QB_ENQUEUE_CMD_IRQ_ON_DISPATCH_SHIFT 3 5108c2ecf20Sopenharmony_ci#define QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT 4 5118c2ecf20Sopenharmony_ci#define QB_ENQUEUE_CMD_DCA_EN_SHIFT 7 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci/** 5148c2ecf20Sopenharmony_ci * qbman_eq_desc_clear() - Clear the contents of a descriptor to 5158c2ecf20Sopenharmony_ci * default/starting state. 5168c2ecf20Sopenharmony_ci */ 5178c2ecf20Sopenharmony_civoid qbman_eq_desc_clear(struct qbman_eq_desc *d) 5188c2ecf20Sopenharmony_ci{ 5198c2ecf20Sopenharmony_ci memset(d, 0, sizeof(*d)); 5208c2ecf20Sopenharmony_ci} 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci/** 5238c2ecf20Sopenharmony_ci * qbman_eq_desc_set_no_orp() - Set enqueue descriptor without orp 5248c2ecf20Sopenharmony_ci * @d: the enqueue descriptor. 5258c2ecf20Sopenharmony_ci * @response_success: 1 = enqueue with response always; 0 = enqueue with 5268c2ecf20Sopenharmony_ci * rejections returned on a FQ. 5278c2ecf20Sopenharmony_ci */ 5288c2ecf20Sopenharmony_civoid qbman_eq_desc_set_no_orp(struct qbman_eq_desc *d, int respond_success) 5298c2ecf20Sopenharmony_ci{ 5308c2ecf20Sopenharmony_ci d->verb &= ~(1 << QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT); 5318c2ecf20Sopenharmony_ci if (respond_success) 5328c2ecf20Sopenharmony_ci d->verb |= enqueue_response_always; 5338c2ecf20Sopenharmony_ci else 5348c2ecf20Sopenharmony_ci d->verb |= enqueue_rejects_to_fq; 5358c2ecf20Sopenharmony_ci} 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci/* 5388c2ecf20Sopenharmony_ci * Exactly one of the following descriptor "targets" should be set. (Calling any 5398c2ecf20Sopenharmony_ci * one of these will replace the effect of any prior call to one of these.) 5408c2ecf20Sopenharmony_ci * -enqueue to a frame queue 5418c2ecf20Sopenharmony_ci * -enqueue to a queuing destination 5428c2ecf20Sopenharmony_ci */ 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci/** 5458c2ecf20Sopenharmony_ci * qbman_eq_desc_set_fq() - set the FQ for the enqueue command 5468c2ecf20Sopenharmony_ci * @d: the enqueue descriptor 5478c2ecf20Sopenharmony_ci * @fqid: the id of the frame queue to be enqueued 5488c2ecf20Sopenharmony_ci */ 5498c2ecf20Sopenharmony_civoid qbman_eq_desc_set_fq(struct qbman_eq_desc *d, u32 fqid) 5508c2ecf20Sopenharmony_ci{ 5518c2ecf20Sopenharmony_ci d->verb &= ~(1 << QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT); 5528c2ecf20Sopenharmony_ci d->tgtid = cpu_to_le32(fqid); 5538c2ecf20Sopenharmony_ci} 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci/** 5568c2ecf20Sopenharmony_ci * qbman_eq_desc_set_qd() - Set Queuing Destination for the enqueue command 5578c2ecf20Sopenharmony_ci * @d: the enqueue descriptor 5588c2ecf20Sopenharmony_ci * @qdid: the id of the queuing destination to be enqueued 5598c2ecf20Sopenharmony_ci * @qd_bin: the queuing destination bin 5608c2ecf20Sopenharmony_ci * @qd_prio: the queuing destination priority 5618c2ecf20Sopenharmony_ci */ 5628c2ecf20Sopenharmony_civoid qbman_eq_desc_set_qd(struct qbman_eq_desc *d, u32 qdid, 5638c2ecf20Sopenharmony_ci u32 qd_bin, u32 qd_prio) 5648c2ecf20Sopenharmony_ci{ 5658c2ecf20Sopenharmony_ci d->verb |= 1 << QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT; 5668c2ecf20Sopenharmony_ci d->tgtid = cpu_to_le32(qdid); 5678c2ecf20Sopenharmony_ci d->qdbin = cpu_to_le16(qd_bin); 5688c2ecf20Sopenharmony_ci d->qpri = qd_prio; 5698c2ecf20Sopenharmony_ci} 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci#define EQAR_IDX(eqar) ((eqar) & 0x7) 5728c2ecf20Sopenharmony_ci#define EQAR_VB(eqar) ((eqar) & 0x80) 5738c2ecf20Sopenharmony_ci#define EQAR_SUCCESS(eqar) ((eqar) & 0x100) 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci#define QB_RT_BIT ((u32)0x100) 5768c2ecf20Sopenharmony_ci/** 5778c2ecf20Sopenharmony_ci * qbman_swp_enqueue_direct() - Issue an enqueue command 5788c2ecf20Sopenharmony_ci * @s: the software portal used for enqueue 5798c2ecf20Sopenharmony_ci * @d: the enqueue descriptor 5808c2ecf20Sopenharmony_ci * @fd: the frame descriptor to be enqueued 5818c2ecf20Sopenharmony_ci * 5828c2ecf20Sopenharmony_ci * Please note that 'fd' should only be NULL if the "action" of the 5838c2ecf20Sopenharmony_ci * descriptor is "orp_hole" or "orp_nesn". 5848c2ecf20Sopenharmony_ci * 5858c2ecf20Sopenharmony_ci * Return 0 for successful enqueue, -EBUSY if the EQCR is not ready. 5868c2ecf20Sopenharmony_ci */ 5878c2ecf20Sopenharmony_cistatic 5888c2ecf20Sopenharmony_ciint qbman_swp_enqueue_direct(struct qbman_swp *s, 5898c2ecf20Sopenharmony_ci const struct qbman_eq_desc *d, 5908c2ecf20Sopenharmony_ci const struct dpaa2_fd *fd) 5918c2ecf20Sopenharmony_ci{ 5928c2ecf20Sopenharmony_ci int flags = 0; 5938c2ecf20Sopenharmony_ci int ret = qbman_swp_enqueue_multiple_direct(s, d, fd, &flags, 1); 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci if (ret >= 0) 5968c2ecf20Sopenharmony_ci ret = 0; 5978c2ecf20Sopenharmony_ci else 5988c2ecf20Sopenharmony_ci ret = -EBUSY; 5998c2ecf20Sopenharmony_ci return ret; 6008c2ecf20Sopenharmony_ci} 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci/** 6038c2ecf20Sopenharmony_ci * qbman_swp_enqueue_mem_back() - Issue an enqueue command 6048c2ecf20Sopenharmony_ci * @s: the software portal used for enqueue 6058c2ecf20Sopenharmony_ci * @d: the enqueue descriptor 6068c2ecf20Sopenharmony_ci * @fd: the frame descriptor to be enqueued 6078c2ecf20Sopenharmony_ci * 6088c2ecf20Sopenharmony_ci * Please note that 'fd' should only be NULL if the "action" of the 6098c2ecf20Sopenharmony_ci * descriptor is "orp_hole" or "orp_nesn". 6108c2ecf20Sopenharmony_ci * 6118c2ecf20Sopenharmony_ci * Return 0 for successful enqueue, -EBUSY if the EQCR is not ready. 6128c2ecf20Sopenharmony_ci */ 6138c2ecf20Sopenharmony_cistatic 6148c2ecf20Sopenharmony_ciint qbman_swp_enqueue_mem_back(struct qbman_swp *s, 6158c2ecf20Sopenharmony_ci const struct qbman_eq_desc *d, 6168c2ecf20Sopenharmony_ci const struct dpaa2_fd *fd) 6178c2ecf20Sopenharmony_ci{ 6188c2ecf20Sopenharmony_ci int flags = 0; 6198c2ecf20Sopenharmony_ci int ret = qbman_swp_enqueue_multiple_mem_back(s, d, fd, &flags, 1); 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci if (ret >= 0) 6228c2ecf20Sopenharmony_ci ret = 0; 6238c2ecf20Sopenharmony_ci else 6248c2ecf20Sopenharmony_ci ret = -EBUSY; 6258c2ecf20Sopenharmony_ci return ret; 6268c2ecf20Sopenharmony_ci} 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci/** 6298c2ecf20Sopenharmony_ci * qbman_swp_enqueue_multiple_direct() - Issue a multi enqueue command 6308c2ecf20Sopenharmony_ci * using one enqueue descriptor 6318c2ecf20Sopenharmony_ci * @s: the software portal used for enqueue 6328c2ecf20Sopenharmony_ci * @d: the enqueue descriptor 6338c2ecf20Sopenharmony_ci * @fd: table pointer of frame descriptor table to be enqueued 6348c2ecf20Sopenharmony_ci * @flags: table pointer of QBMAN_ENQUEUE_FLAG_DCA flags, not used if NULL 6358c2ecf20Sopenharmony_ci * @num_frames: number of fd to be enqueued 6368c2ecf20Sopenharmony_ci * 6378c2ecf20Sopenharmony_ci * Return the number of fd enqueued, or a negative error number. 6388c2ecf20Sopenharmony_ci */ 6398c2ecf20Sopenharmony_cistatic 6408c2ecf20Sopenharmony_ciint qbman_swp_enqueue_multiple_direct(struct qbman_swp *s, 6418c2ecf20Sopenharmony_ci const struct qbman_eq_desc *d, 6428c2ecf20Sopenharmony_ci const struct dpaa2_fd *fd, 6438c2ecf20Sopenharmony_ci uint32_t *flags, 6448c2ecf20Sopenharmony_ci int num_frames) 6458c2ecf20Sopenharmony_ci{ 6468c2ecf20Sopenharmony_ci uint32_t *p = NULL; 6478c2ecf20Sopenharmony_ci const uint32_t *cl = (uint32_t *)d; 6488c2ecf20Sopenharmony_ci uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask; 6498c2ecf20Sopenharmony_ci int i, num_enqueued = 0; 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci spin_lock(&s->access_spinlock); 6528c2ecf20Sopenharmony_ci half_mask = (s->eqcr.pi_ci_mask>>1); 6538c2ecf20Sopenharmony_ci full_mask = s->eqcr.pi_ci_mask; 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci if (!s->eqcr.available) { 6568c2ecf20Sopenharmony_ci eqcr_ci = s->eqcr.ci; 6578c2ecf20Sopenharmony_ci p = s->addr_cena + QBMAN_CENA_SWP_EQCR_CI; 6588c2ecf20Sopenharmony_ci s->eqcr.ci = qbman_read_register(s, QBMAN_CINH_SWP_EQCR_CI); 6598c2ecf20Sopenharmony_ci s->eqcr.ci &= full_mask; 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size, 6628c2ecf20Sopenharmony_ci eqcr_ci, s->eqcr.ci); 6638c2ecf20Sopenharmony_ci if (!s->eqcr.available) { 6648c2ecf20Sopenharmony_ci spin_unlock(&s->access_spinlock); 6658c2ecf20Sopenharmony_ci return 0; 6668c2ecf20Sopenharmony_ci } 6678c2ecf20Sopenharmony_ci } 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci eqcr_pi = s->eqcr.pi; 6708c2ecf20Sopenharmony_ci num_enqueued = (s->eqcr.available < num_frames) ? 6718c2ecf20Sopenharmony_ci s->eqcr.available : num_frames; 6728c2ecf20Sopenharmony_ci s->eqcr.available -= num_enqueued; 6738c2ecf20Sopenharmony_ci /* Fill in the EQCR ring */ 6748c2ecf20Sopenharmony_ci for (i = 0; i < num_enqueued; i++) { 6758c2ecf20Sopenharmony_ci p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask)); 6768c2ecf20Sopenharmony_ci /* Skip copying the verb */ 6778c2ecf20Sopenharmony_ci memcpy(&p[1], &cl[1], EQ_DESC_SIZE_WITHOUT_FD - 1); 6788c2ecf20Sopenharmony_ci memcpy(&p[EQ_DESC_SIZE_FD_START/sizeof(uint32_t)], 6798c2ecf20Sopenharmony_ci &fd[i], sizeof(*fd)); 6808c2ecf20Sopenharmony_ci eqcr_pi++; 6818c2ecf20Sopenharmony_ci } 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci dma_wmb(); 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci /* Set the verb byte, have to substitute in the valid-bit */ 6868c2ecf20Sopenharmony_ci eqcr_pi = s->eqcr.pi; 6878c2ecf20Sopenharmony_ci for (i = 0; i < num_enqueued; i++) { 6888c2ecf20Sopenharmony_ci p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask)); 6898c2ecf20Sopenharmony_ci p[0] = cl[0] | s->eqcr.pi_vb; 6908c2ecf20Sopenharmony_ci if (flags && (flags[i] & QBMAN_ENQUEUE_FLAG_DCA)) { 6918c2ecf20Sopenharmony_ci struct qbman_eq_desc *d = (struct qbman_eq_desc *)p; 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci d->dca = (1 << QB_ENQUEUE_CMD_DCA_EN_SHIFT) | 6948c2ecf20Sopenharmony_ci ((flags[i]) & QBMAN_EQCR_DCA_IDXMASK); 6958c2ecf20Sopenharmony_ci } 6968c2ecf20Sopenharmony_ci eqcr_pi++; 6978c2ecf20Sopenharmony_ci if (!(eqcr_pi & half_mask)) 6988c2ecf20Sopenharmony_ci s->eqcr.pi_vb ^= QB_VALID_BIT; 6998c2ecf20Sopenharmony_ci } 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci /* Flush all the cacheline without load/store in between */ 7028c2ecf20Sopenharmony_ci eqcr_pi = s->eqcr.pi; 7038c2ecf20Sopenharmony_ci for (i = 0; i < num_enqueued; i++) 7048c2ecf20Sopenharmony_ci eqcr_pi++; 7058c2ecf20Sopenharmony_ci s->eqcr.pi = eqcr_pi & full_mask; 7068c2ecf20Sopenharmony_ci spin_unlock(&s->access_spinlock); 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci return num_enqueued; 7098c2ecf20Sopenharmony_ci} 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci/** 7128c2ecf20Sopenharmony_ci * qbman_swp_enqueue_multiple_mem_back() - Issue a multi enqueue command 7138c2ecf20Sopenharmony_ci * using one enqueue descriptor 7148c2ecf20Sopenharmony_ci * @s: the software portal used for enqueue 7158c2ecf20Sopenharmony_ci * @d: the enqueue descriptor 7168c2ecf20Sopenharmony_ci * @fd: table pointer of frame descriptor table to be enqueued 7178c2ecf20Sopenharmony_ci * @flags: table pointer of QBMAN_ENQUEUE_FLAG_DCA flags, not used if NULL 7188c2ecf20Sopenharmony_ci * @num_frames: number of fd to be enqueued 7198c2ecf20Sopenharmony_ci * 7208c2ecf20Sopenharmony_ci * Return the number of fd enqueued, or a negative error number. 7218c2ecf20Sopenharmony_ci */ 7228c2ecf20Sopenharmony_cistatic 7238c2ecf20Sopenharmony_ciint qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s, 7248c2ecf20Sopenharmony_ci const struct qbman_eq_desc *d, 7258c2ecf20Sopenharmony_ci const struct dpaa2_fd *fd, 7268c2ecf20Sopenharmony_ci uint32_t *flags, 7278c2ecf20Sopenharmony_ci int num_frames) 7288c2ecf20Sopenharmony_ci{ 7298c2ecf20Sopenharmony_ci uint32_t *p = NULL; 7308c2ecf20Sopenharmony_ci const uint32_t *cl = (uint32_t *)(d); 7318c2ecf20Sopenharmony_ci uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask; 7328c2ecf20Sopenharmony_ci int i, num_enqueued = 0; 7338c2ecf20Sopenharmony_ci unsigned long irq_flags; 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ci spin_lock_irqsave(&s->access_spinlock, irq_flags); 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci half_mask = (s->eqcr.pi_ci_mask>>1); 7388c2ecf20Sopenharmony_ci full_mask = s->eqcr.pi_ci_mask; 7398c2ecf20Sopenharmony_ci if (!s->eqcr.available) { 7408c2ecf20Sopenharmony_ci eqcr_ci = s->eqcr.ci; 7418c2ecf20Sopenharmony_ci p = s->addr_cena + QBMAN_CENA_SWP_EQCR_CI_MEMBACK; 7428c2ecf20Sopenharmony_ci s->eqcr.ci = *p & full_mask; 7438c2ecf20Sopenharmony_ci s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size, 7448c2ecf20Sopenharmony_ci eqcr_ci, s->eqcr.ci); 7458c2ecf20Sopenharmony_ci if (!s->eqcr.available) { 7468c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&s->access_spinlock, irq_flags); 7478c2ecf20Sopenharmony_ci return 0; 7488c2ecf20Sopenharmony_ci } 7498c2ecf20Sopenharmony_ci } 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci eqcr_pi = s->eqcr.pi; 7528c2ecf20Sopenharmony_ci num_enqueued = (s->eqcr.available < num_frames) ? 7538c2ecf20Sopenharmony_ci s->eqcr.available : num_frames; 7548c2ecf20Sopenharmony_ci s->eqcr.available -= num_enqueued; 7558c2ecf20Sopenharmony_ci /* Fill in the EQCR ring */ 7568c2ecf20Sopenharmony_ci for (i = 0; i < num_enqueued; i++) { 7578c2ecf20Sopenharmony_ci p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask)); 7588c2ecf20Sopenharmony_ci /* Skip copying the verb */ 7598c2ecf20Sopenharmony_ci memcpy(&p[1], &cl[1], EQ_DESC_SIZE_WITHOUT_FD - 1); 7608c2ecf20Sopenharmony_ci memcpy(&p[EQ_DESC_SIZE_FD_START/sizeof(uint32_t)], 7618c2ecf20Sopenharmony_ci &fd[i], sizeof(*fd)); 7628c2ecf20Sopenharmony_ci eqcr_pi++; 7638c2ecf20Sopenharmony_ci } 7648c2ecf20Sopenharmony_ci 7658c2ecf20Sopenharmony_ci /* Set the verb byte, have to substitute in the valid-bit */ 7668c2ecf20Sopenharmony_ci eqcr_pi = s->eqcr.pi; 7678c2ecf20Sopenharmony_ci for (i = 0; i < num_enqueued; i++) { 7688c2ecf20Sopenharmony_ci p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask)); 7698c2ecf20Sopenharmony_ci p[0] = cl[0] | s->eqcr.pi_vb; 7708c2ecf20Sopenharmony_ci if (flags && (flags[i] & QBMAN_ENQUEUE_FLAG_DCA)) { 7718c2ecf20Sopenharmony_ci struct qbman_eq_desc *d = (struct qbman_eq_desc *)p; 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci d->dca = (1 << QB_ENQUEUE_CMD_DCA_EN_SHIFT) | 7748c2ecf20Sopenharmony_ci ((flags[i]) & QBMAN_EQCR_DCA_IDXMASK); 7758c2ecf20Sopenharmony_ci } 7768c2ecf20Sopenharmony_ci eqcr_pi++; 7778c2ecf20Sopenharmony_ci if (!(eqcr_pi & half_mask)) 7788c2ecf20Sopenharmony_ci s->eqcr.pi_vb ^= QB_VALID_BIT; 7798c2ecf20Sopenharmony_ci } 7808c2ecf20Sopenharmony_ci s->eqcr.pi = eqcr_pi & full_mask; 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci dma_wmb(); 7838c2ecf20Sopenharmony_ci qbman_write_register(s, QBMAN_CINH_SWP_EQCR_PI, 7848c2ecf20Sopenharmony_ci (QB_RT_BIT)|(s->eqcr.pi)|s->eqcr.pi_vb); 7858c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&s->access_spinlock, irq_flags); 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci return num_enqueued; 7888c2ecf20Sopenharmony_ci} 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci/** 7918c2ecf20Sopenharmony_ci * qbman_swp_enqueue_multiple_desc_direct() - Issue a multi enqueue command 7928c2ecf20Sopenharmony_ci * using multiple enqueue descriptor 7938c2ecf20Sopenharmony_ci * @s: the software portal used for enqueue 7948c2ecf20Sopenharmony_ci * @d: table of minimal enqueue descriptor 7958c2ecf20Sopenharmony_ci * @fd: table pointer of frame descriptor table to be enqueued 7968c2ecf20Sopenharmony_ci * @num_frames: number of fd to be enqueued 7978c2ecf20Sopenharmony_ci * 7988c2ecf20Sopenharmony_ci * Return the number of fd enqueued, or a negative error number. 7998c2ecf20Sopenharmony_ci */ 8008c2ecf20Sopenharmony_cistatic 8018c2ecf20Sopenharmony_ciint qbman_swp_enqueue_multiple_desc_direct(struct qbman_swp *s, 8028c2ecf20Sopenharmony_ci const struct qbman_eq_desc *d, 8038c2ecf20Sopenharmony_ci const struct dpaa2_fd *fd, 8048c2ecf20Sopenharmony_ci int num_frames) 8058c2ecf20Sopenharmony_ci{ 8068c2ecf20Sopenharmony_ci uint32_t *p; 8078c2ecf20Sopenharmony_ci const uint32_t *cl; 8088c2ecf20Sopenharmony_ci uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask; 8098c2ecf20Sopenharmony_ci int i, num_enqueued = 0; 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci half_mask = (s->eqcr.pi_ci_mask>>1); 8128c2ecf20Sopenharmony_ci full_mask = s->eqcr.pi_ci_mask; 8138c2ecf20Sopenharmony_ci if (!s->eqcr.available) { 8148c2ecf20Sopenharmony_ci eqcr_ci = s->eqcr.ci; 8158c2ecf20Sopenharmony_ci p = s->addr_cena + QBMAN_CENA_SWP_EQCR_CI; 8168c2ecf20Sopenharmony_ci s->eqcr.ci = qbman_read_register(s, QBMAN_CINH_SWP_EQCR_CI); 8178c2ecf20Sopenharmony_ci s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size, 8188c2ecf20Sopenharmony_ci eqcr_ci, s->eqcr.ci); 8198c2ecf20Sopenharmony_ci if (!s->eqcr.available) 8208c2ecf20Sopenharmony_ci return 0; 8218c2ecf20Sopenharmony_ci } 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci eqcr_pi = s->eqcr.pi; 8248c2ecf20Sopenharmony_ci num_enqueued = (s->eqcr.available < num_frames) ? 8258c2ecf20Sopenharmony_ci s->eqcr.available : num_frames; 8268c2ecf20Sopenharmony_ci s->eqcr.available -= num_enqueued; 8278c2ecf20Sopenharmony_ci /* Fill in the EQCR ring */ 8288c2ecf20Sopenharmony_ci for (i = 0; i < num_enqueued; i++) { 8298c2ecf20Sopenharmony_ci p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask)); 8308c2ecf20Sopenharmony_ci cl = (uint32_t *)(&d[i]); 8318c2ecf20Sopenharmony_ci /* Skip copying the verb */ 8328c2ecf20Sopenharmony_ci memcpy(&p[1], &cl[1], EQ_DESC_SIZE_WITHOUT_FD - 1); 8338c2ecf20Sopenharmony_ci memcpy(&p[EQ_DESC_SIZE_FD_START/sizeof(uint32_t)], 8348c2ecf20Sopenharmony_ci &fd[i], sizeof(*fd)); 8358c2ecf20Sopenharmony_ci eqcr_pi++; 8368c2ecf20Sopenharmony_ci } 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci dma_wmb(); 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci /* Set the verb byte, have to substitute in the valid-bit */ 8418c2ecf20Sopenharmony_ci eqcr_pi = s->eqcr.pi; 8428c2ecf20Sopenharmony_ci for (i = 0; i < num_enqueued; i++) { 8438c2ecf20Sopenharmony_ci p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask)); 8448c2ecf20Sopenharmony_ci cl = (uint32_t *)(&d[i]); 8458c2ecf20Sopenharmony_ci p[0] = cl[0] | s->eqcr.pi_vb; 8468c2ecf20Sopenharmony_ci eqcr_pi++; 8478c2ecf20Sopenharmony_ci if (!(eqcr_pi & half_mask)) 8488c2ecf20Sopenharmony_ci s->eqcr.pi_vb ^= QB_VALID_BIT; 8498c2ecf20Sopenharmony_ci } 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci /* Flush all the cacheline without load/store in between */ 8528c2ecf20Sopenharmony_ci eqcr_pi = s->eqcr.pi; 8538c2ecf20Sopenharmony_ci for (i = 0; i < num_enqueued; i++) 8548c2ecf20Sopenharmony_ci eqcr_pi++; 8558c2ecf20Sopenharmony_ci s->eqcr.pi = eqcr_pi & full_mask; 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci return num_enqueued; 8588c2ecf20Sopenharmony_ci} 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_ci/** 8618c2ecf20Sopenharmony_ci * qbman_swp_enqueue_multiple_desc_mem_back() - Issue a multi enqueue command 8628c2ecf20Sopenharmony_ci * using multiple enqueue descriptor 8638c2ecf20Sopenharmony_ci * @s: the software portal used for enqueue 8648c2ecf20Sopenharmony_ci * @d: table of minimal enqueue descriptor 8658c2ecf20Sopenharmony_ci * @fd: table pointer of frame descriptor table to be enqueued 8668c2ecf20Sopenharmony_ci * @num_frames: number of fd to be enqueued 8678c2ecf20Sopenharmony_ci * 8688c2ecf20Sopenharmony_ci * Return the number of fd enqueued, or a negative error number. 8698c2ecf20Sopenharmony_ci */ 8708c2ecf20Sopenharmony_cistatic 8718c2ecf20Sopenharmony_ciint qbman_swp_enqueue_multiple_desc_mem_back(struct qbman_swp *s, 8728c2ecf20Sopenharmony_ci const struct qbman_eq_desc *d, 8738c2ecf20Sopenharmony_ci const struct dpaa2_fd *fd, 8748c2ecf20Sopenharmony_ci int num_frames) 8758c2ecf20Sopenharmony_ci{ 8768c2ecf20Sopenharmony_ci uint32_t *p; 8778c2ecf20Sopenharmony_ci const uint32_t *cl; 8788c2ecf20Sopenharmony_ci uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask; 8798c2ecf20Sopenharmony_ci int i, num_enqueued = 0; 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci half_mask = (s->eqcr.pi_ci_mask>>1); 8828c2ecf20Sopenharmony_ci full_mask = s->eqcr.pi_ci_mask; 8838c2ecf20Sopenharmony_ci if (!s->eqcr.available) { 8848c2ecf20Sopenharmony_ci eqcr_ci = s->eqcr.ci; 8858c2ecf20Sopenharmony_ci p = s->addr_cena + QBMAN_CENA_SWP_EQCR_CI_MEMBACK; 8868c2ecf20Sopenharmony_ci s->eqcr.ci = *p & full_mask; 8878c2ecf20Sopenharmony_ci s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size, 8888c2ecf20Sopenharmony_ci eqcr_ci, s->eqcr.ci); 8898c2ecf20Sopenharmony_ci if (!s->eqcr.available) 8908c2ecf20Sopenharmony_ci return 0; 8918c2ecf20Sopenharmony_ci } 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci eqcr_pi = s->eqcr.pi; 8948c2ecf20Sopenharmony_ci num_enqueued = (s->eqcr.available < num_frames) ? 8958c2ecf20Sopenharmony_ci s->eqcr.available : num_frames; 8968c2ecf20Sopenharmony_ci s->eqcr.available -= num_enqueued; 8978c2ecf20Sopenharmony_ci /* Fill in the EQCR ring */ 8988c2ecf20Sopenharmony_ci for (i = 0; i < num_enqueued; i++) { 8998c2ecf20Sopenharmony_ci p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask)); 9008c2ecf20Sopenharmony_ci cl = (uint32_t *)(&d[i]); 9018c2ecf20Sopenharmony_ci /* Skip copying the verb */ 9028c2ecf20Sopenharmony_ci memcpy(&p[1], &cl[1], EQ_DESC_SIZE_WITHOUT_FD - 1); 9038c2ecf20Sopenharmony_ci memcpy(&p[EQ_DESC_SIZE_FD_START/sizeof(uint32_t)], 9048c2ecf20Sopenharmony_ci &fd[i], sizeof(*fd)); 9058c2ecf20Sopenharmony_ci eqcr_pi++; 9068c2ecf20Sopenharmony_ci } 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci /* Set the verb byte, have to substitute in the valid-bit */ 9098c2ecf20Sopenharmony_ci eqcr_pi = s->eqcr.pi; 9108c2ecf20Sopenharmony_ci for (i = 0; i < num_enqueued; i++) { 9118c2ecf20Sopenharmony_ci p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask)); 9128c2ecf20Sopenharmony_ci cl = (uint32_t *)(&d[i]); 9138c2ecf20Sopenharmony_ci p[0] = cl[0] | s->eqcr.pi_vb; 9148c2ecf20Sopenharmony_ci eqcr_pi++; 9158c2ecf20Sopenharmony_ci if (!(eqcr_pi & half_mask)) 9168c2ecf20Sopenharmony_ci s->eqcr.pi_vb ^= QB_VALID_BIT; 9178c2ecf20Sopenharmony_ci } 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci s->eqcr.pi = eqcr_pi & full_mask; 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci dma_wmb(); 9228c2ecf20Sopenharmony_ci qbman_write_register(s, QBMAN_CINH_SWP_EQCR_PI, 9238c2ecf20Sopenharmony_ci (QB_RT_BIT)|(s->eqcr.pi)|s->eqcr.pi_vb); 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_ci return num_enqueued; 9268c2ecf20Sopenharmony_ci} 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci/* Static (push) dequeue */ 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_ci/** 9318c2ecf20Sopenharmony_ci * qbman_swp_push_get() - Get the push dequeue setup 9328c2ecf20Sopenharmony_ci * @p: the software portal object 9338c2ecf20Sopenharmony_ci * @channel_idx: the channel index to query 9348c2ecf20Sopenharmony_ci * @enabled: returned boolean to show whether the push dequeue is enabled 9358c2ecf20Sopenharmony_ci * for the given channel 9368c2ecf20Sopenharmony_ci */ 9378c2ecf20Sopenharmony_civoid qbman_swp_push_get(struct qbman_swp *s, u8 channel_idx, int *enabled) 9388c2ecf20Sopenharmony_ci{ 9398c2ecf20Sopenharmony_ci u16 src = (s->sdq >> QB_SDQCR_SRC_SHIFT) & QB_SDQCR_SRC_MASK; 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci WARN_ON(channel_idx > 15); 9428c2ecf20Sopenharmony_ci *enabled = src | (1 << channel_idx); 9438c2ecf20Sopenharmony_ci} 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci/** 9468c2ecf20Sopenharmony_ci * qbman_swp_push_set() - Enable or disable push dequeue 9478c2ecf20Sopenharmony_ci * @p: the software portal object 9488c2ecf20Sopenharmony_ci * @channel_idx: the channel index (0 to 15) 9498c2ecf20Sopenharmony_ci * @enable: enable or disable push dequeue 9508c2ecf20Sopenharmony_ci */ 9518c2ecf20Sopenharmony_civoid qbman_swp_push_set(struct qbman_swp *s, u8 channel_idx, int enable) 9528c2ecf20Sopenharmony_ci{ 9538c2ecf20Sopenharmony_ci u16 dqsrc; 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_ci WARN_ON(channel_idx > 15); 9568c2ecf20Sopenharmony_ci if (enable) 9578c2ecf20Sopenharmony_ci s->sdq |= 1 << channel_idx; 9588c2ecf20Sopenharmony_ci else 9598c2ecf20Sopenharmony_ci s->sdq &= ~(1 << channel_idx); 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci /* Read make the complete src map. If no channels are enabled 9628c2ecf20Sopenharmony_ci * the SDQCR must be 0 or else QMan will assert errors 9638c2ecf20Sopenharmony_ci */ 9648c2ecf20Sopenharmony_ci dqsrc = (s->sdq >> QB_SDQCR_SRC_SHIFT) & QB_SDQCR_SRC_MASK; 9658c2ecf20Sopenharmony_ci if (dqsrc != 0) 9668c2ecf20Sopenharmony_ci qbman_write_register(s, QBMAN_CINH_SWP_SDQCR, s->sdq); 9678c2ecf20Sopenharmony_ci else 9688c2ecf20Sopenharmony_ci qbman_write_register(s, QBMAN_CINH_SWP_SDQCR, 0); 9698c2ecf20Sopenharmony_ci} 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_ci#define QB_VDQCR_VERB_DCT_SHIFT 0 9728c2ecf20Sopenharmony_ci#define QB_VDQCR_VERB_DT_SHIFT 2 9738c2ecf20Sopenharmony_ci#define QB_VDQCR_VERB_RLS_SHIFT 4 9748c2ecf20Sopenharmony_ci#define QB_VDQCR_VERB_WAE_SHIFT 5 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_cienum qb_pull_dt_e { 9778c2ecf20Sopenharmony_ci qb_pull_dt_channel, 9788c2ecf20Sopenharmony_ci qb_pull_dt_workqueue, 9798c2ecf20Sopenharmony_ci qb_pull_dt_framequeue 9808c2ecf20Sopenharmony_ci}; 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci/** 9838c2ecf20Sopenharmony_ci * qbman_pull_desc_clear() - Clear the contents of a descriptor to 9848c2ecf20Sopenharmony_ci * default/starting state 9858c2ecf20Sopenharmony_ci * @d: the pull dequeue descriptor to be cleared 9868c2ecf20Sopenharmony_ci */ 9878c2ecf20Sopenharmony_civoid qbman_pull_desc_clear(struct qbman_pull_desc *d) 9888c2ecf20Sopenharmony_ci{ 9898c2ecf20Sopenharmony_ci memset(d, 0, sizeof(*d)); 9908c2ecf20Sopenharmony_ci} 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci/** 9938c2ecf20Sopenharmony_ci * qbman_pull_desc_set_storage()- Set the pull dequeue storage 9948c2ecf20Sopenharmony_ci * @d: the pull dequeue descriptor to be set 9958c2ecf20Sopenharmony_ci * @storage: the pointer of the memory to store the dequeue result 9968c2ecf20Sopenharmony_ci * @storage_phys: the physical address of the storage memory 9978c2ecf20Sopenharmony_ci * @stash: to indicate whether write allocate is enabled 9988c2ecf20Sopenharmony_ci * 9998c2ecf20Sopenharmony_ci * If not called, or if called with 'storage' as NULL, the result pull dequeues 10008c2ecf20Sopenharmony_ci * will produce results to DQRR. If 'storage' is non-NULL, then results are 10018c2ecf20Sopenharmony_ci * produced to the given memory location (using the DMA address which 10028c2ecf20Sopenharmony_ci * the caller provides in 'storage_phys'), and 'stash' controls whether or not 10038c2ecf20Sopenharmony_ci * those writes to main-memory express a cache-warming attribute. 10048c2ecf20Sopenharmony_ci */ 10058c2ecf20Sopenharmony_civoid qbman_pull_desc_set_storage(struct qbman_pull_desc *d, 10068c2ecf20Sopenharmony_ci struct dpaa2_dq *storage, 10078c2ecf20Sopenharmony_ci dma_addr_t storage_phys, 10088c2ecf20Sopenharmony_ci int stash) 10098c2ecf20Sopenharmony_ci{ 10108c2ecf20Sopenharmony_ci /* save the virtual address */ 10118c2ecf20Sopenharmony_ci d->rsp_addr_virt = (u64)(uintptr_t)storage; 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci if (!storage) { 10148c2ecf20Sopenharmony_ci d->verb &= ~(1 << QB_VDQCR_VERB_RLS_SHIFT); 10158c2ecf20Sopenharmony_ci return; 10168c2ecf20Sopenharmony_ci } 10178c2ecf20Sopenharmony_ci d->verb |= 1 << QB_VDQCR_VERB_RLS_SHIFT; 10188c2ecf20Sopenharmony_ci if (stash) 10198c2ecf20Sopenharmony_ci d->verb |= 1 << QB_VDQCR_VERB_WAE_SHIFT; 10208c2ecf20Sopenharmony_ci else 10218c2ecf20Sopenharmony_ci d->verb &= ~(1 << QB_VDQCR_VERB_WAE_SHIFT); 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci d->rsp_addr = cpu_to_le64(storage_phys); 10248c2ecf20Sopenharmony_ci} 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci/** 10278c2ecf20Sopenharmony_ci * qbman_pull_desc_set_numframes() - Set the number of frames to be dequeued 10288c2ecf20Sopenharmony_ci * @d: the pull dequeue descriptor to be set 10298c2ecf20Sopenharmony_ci * @numframes: number of frames to be set, must be between 1 and 16, inclusive 10308c2ecf20Sopenharmony_ci */ 10318c2ecf20Sopenharmony_civoid qbman_pull_desc_set_numframes(struct qbman_pull_desc *d, u8 numframes) 10328c2ecf20Sopenharmony_ci{ 10338c2ecf20Sopenharmony_ci d->numf = numframes - 1; 10348c2ecf20Sopenharmony_ci} 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci/* 10378c2ecf20Sopenharmony_ci * Exactly one of the following descriptor "actions" should be set. (Calling any 10388c2ecf20Sopenharmony_ci * one of these will replace the effect of any prior call to one of these.) 10398c2ecf20Sopenharmony_ci * - pull dequeue from the given frame queue (FQ) 10408c2ecf20Sopenharmony_ci * - pull dequeue from any FQ in the given work queue (WQ) 10418c2ecf20Sopenharmony_ci * - pull dequeue from any FQ in any WQ in the given channel 10428c2ecf20Sopenharmony_ci */ 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_ci/** 10458c2ecf20Sopenharmony_ci * qbman_pull_desc_set_fq() - Set fqid from which the dequeue command dequeues 10468c2ecf20Sopenharmony_ci * @fqid: the frame queue index of the given FQ 10478c2ecf20Sopenharmony_ci */ 10488c2ecf20Sopenharmony_civoid qbman_pull_desc_set_fq(struct qbman_pull_desc *d, u32 fqid) 10498c2ecf20Sopenharmony_ci{ 10508c2ecf20Sopenharmony_ci d->verb |= 1 << QB_VDQCR_VERB_DCT_SHIFT; 10518c2ecf20Sopenharmony_ci d->verb |= qb_pull_dt_framequeue << QB_VDQCR_VERB_DT_SHIFT; 10528c2ecf20Sopenharmony_ci d->dq_src = cpu_to_le32(fqid); 10538c2ecf20Sopenharmony_ci} 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci/** 10568c2ecf20Sopenharmony_ci * qbman_pull_desc_set_wq() - Set wqid from which the dequeue command dequeues 10578c2ecf20Sopenharmony_ci * @wqid: composed of channel id and wqid within the channel 10588c2ecf20Sopenharmony_ci * @dct: the dequeue command type 10598c2ecf20Sopenharmony_ci */ 10608c2ecf20Sopenharmony_civoid qbman_pull_desc_set_wq(struct qbman_pull_desc *d, u32 wqid, 10618c2ecf20Sopenharmony_ci enum qbman_pull_type_e dct) 10628c2ecf20Sopenharmony_ci{ 10638c2ecf20Sopenharmony_ci d->verb |= dct << QB_VDQCR_VERB_DCT_SHIFT; 10648c2ecf20Sopenharmony_ci d->verb |= qb_pull_dt_workqueue << QB_VDQCR_VERB_DT_SHIFT; 10658c2ecf20Sopenharmony_ci d->dq_src = cpu_to_le32(wqid); 10668c2ecf20Sopenharmony_ci} 10678c2ecf20Sopenharmony_ci 10688c2ecf20Sopenharmony_ci/** 10698c2ecf20Sopenharmony_ci * qbman_pull_desc_set_channel() - Set channelid from which the dequeue command 10708c2ecf20Sopenharmony_ci * dequeues 10718c2ecf20Sopenharmony_ci * @chid: the channel id to be dequeued 10728c2ecf20Sopenharmony_ci * @dct: the dequeue command type 10738c2ecf20Sopenharmony_ci */ 10748c2ecf20Sopenharmony_civoid qbman_pull_desc_set_channel(struct qbman_pull_desc *d, u32 chid, 10758c2ecf20Sopenharmony_ci enum qbman_pull_type_e dct) 10768c2ecf20Sopenharmony_ci{ 10778c2ecf20Sopenharmony_ci d->verb |= dct << QB_VDQCR_VERB_DCT_SHIFT; 10788c2ecf20Sopenharmony_ci d->verb |= qb_pull_dt_channel << QB_VDQCR_VERB_DT_SHIFT; 10798c2ecf20Sopenharmony_ci d->dq_src = cpu_to_le32(chid); 10808c2ecf20Sopenharmony_ci} 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ci/** 10838c2ecf20Sopenharmony_ci * qbman_swp_pull_direct() - Issue the pull dequeue command 10848c2ecf20Sopenharmony_ci * @s: the software portal object 10858c2ecf20Sopenharmony_ci * @d: the software portal descriptor which has been configured with 10868c2ecf20Sopenharmony_ci * the set of qbman_pull_desc_set_*() calls 10878c2ecf20Sopenharmony_ci * 10888c2ecf20Sopenharmony_ci * Return 0 for success, and -EBUSY if the software portal is not ready 10898c2ecf20Sopenharmony_ci * to do pull dequeue. 10908c2ecf20Sopenharmony_ci */ 10918c2ecf20Sopenharmony_cistatic 10928c2ecf20Sopenharmony_ciint qbman_swp_pull_direct(struct qbman_swp *s, struct qbman_pull_desc *d) 10938c2ecf20Sopenharmony_ci{ 10948c2ecf20Sopenharmony_ci struct qbman_pull_desc *p; 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_ci if (!atomic_dec_and_test(&s->vdq.available)) { 10978c2ecf20Sopenharmony_ci atomic_inc(&s->vdq.available); 10988c2ecf20Sopenharmony_ci return -EBUSY; 10998c2ecf20Sopenharmony_ci } 11008c2ecf20Sopenharmony_ci s->vdq.storage = (void *)(uintptr_t)d->rsp_addr_virt; 11018c2ecf20Sopenharmony_ci if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) 11028c2ecf20Sopenharmony_ci p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR); 11038c2ecf20Sopenharmony_ci else 11048c2ecf20Sopenharmony_ci p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR_MEM); 11058c2ecf20Sopenharmony_ci p->numf = d->numf; 11068c2ecf20Sopenharmony_ci p->tok = QMAN_DQ_TOKEN_VALID; 11078c2ecf20Sopenharmony_ci p->dq_src = d->dq_src; 11088c2ecf20Sopenharmony_ci p->rsp_addr = d->rsp_addr; 11098c2ecf20Sopenharmony_ci p->rsp_addr_virt = d->rsp_addr_virt; 11108c2ecf20Sopenharmony_ci dma_wmb(); 11118c2ecf20Sopenharmony_ci /* Set the verb byte, have to substitute in the valid-bit */ 11128c2ecf20Sopenharmony_ci p->verb = d->verb | s->vdq.valid_bit; 11138c2ecf20Sopenharmony_ci s->vdq.valid_bit ^= QB_VALID_BIT; 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci return 0; 11168c2ecf20Sopenharmony_ci} 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_ci/** 11198c2ecf20Sopenharmony_ci * qbman_swp_pull_mem_back() - Issue the pull dequeue command 11208c2ecf20Sopenharmony_ci * @s: the software portal object 11218c2ecf20Sopenharmony_ci * @d: the software portal descriptor which has been configured with 11228c2ecf20Sopenharmony_ci * the set of qbman_pull_desc_set_*() calls 11238c2ecf20Sopenharmony_ci * 11248c2ecf20Sopenharmony_ci * Return 0 for success, and -EBUSY if the software portal is not ready 11258c2ecf20Sopenharmony_ci * to do pull dequeue. 11268c2ecf20Sopenharmony_ci */ 11278c2ecf20Sopenharmony_cistatic 11288c2ecf20Sopenharmony_ciint qbman_swp_pull_mem_back(struct qbman_swp *s, struct qbman_pull_desc *d) 11298c2ecf20Sopenharmony_ci{ 11308c2ecf20Sopenharmony_ci struct qbman_pull_desc *p; 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci if (!atomic_dec_and_test(&s->vdq.available)) { 11338c2ecf20Sopenharmony_ci atomic_inc(&s->vdq.available); 11348c2ecf20Sopenharmony_ci return -EBUSY; 11358c2ecf20Sopenharmony_ci } 11368c2ecf20Sopenharmony_ci s->vdq.storage = (void *)(uintptr_t)d->rsp_addr_virt; 11378c2ecf20Sopenharmony_ci if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) 11388c2ecf20Sopenharmony_ci p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR); 11398c2ecf20Sopenharmony_ci else 11408c2ecf20Sopenharmony_ci p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR_MEM); 11418c2ecf20Sopenharmony_ci p->numf = d->numf; 11428c2ecf20Sopenharmony_ci p->tok = QMAN_DQ_TOKEN_VALID; 11438c2ecf20Sopenharmony_ci p->dq_src = d->dq_src; 11448c2ecf20Sopenharmony_ci p->rsp_addr = d->rsp_addr; 11458c2ecf20Sopenharmony_ci p->rsp_addr_virt = d->rsp_addr_virt; 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_ci /* Set the verb byte, have to substitute in the valid-bit */ 11488c2ecf20Sopenharmony_ci p->verb = d->verb | s->vdq.valid_bit; 11498c2ecf20Sopenharmony_ci s->vdq.valid_bit ^= QB_VALID_BIT; 11508c2ecf20Sopenharmony_ci dma_wmb(); 11518c2ecf20Sopenharmony_ci qbman_write_register(s, QBMAN_CINH_SWP_VDQCR_RT, QMAN_RT_MODE); 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_ci return 0; 11548c2ecf20Sopenharmony_ci} 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci#define QMAN_DQRR_PI_MASK 0xf 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_ci/** 11598c2ecf20Sopenharmony_ci * qbman_swp_dqrr_next_direct() - Get an valid DQRR entry 11608c2ecf20Sopenharmony_ci * @s: the software portal object 11618c2ecf20Sopenharmony_ci * 11628c2ecf20Sopenharmony_ci * Return NULL if there are no unconsumed DQRR entries. Return a DQRR entry 11638c2ecf20Sopenharmony_ci * only once, so repeated calls can return a sequence of DQRR entries, without 11648c2ecf20Sopenharmony_ci * requiring they be consumed immediately or in any particular order. 11658c2ecf20Sopenharmony_ci */ 11668c2ecf20Sopenharmony_ciconst struct dpaa2_dq *qbman_swp_dqrr_next_direct(struct qbman_swp *s) 11678c2ecf20Sopenharmony_ci{ 11688c2ecf20Sopenharmony_ci u32 verb; 11698c2ecf20Sopenharmony_ci u32 response_verb; 11708c2ecf20Sopenharmony_ci u32 flags; 11718c2ecf20Sopenharmony_ci struct dpaa2_dq *p; 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci /* Before using valid-bit to detect if something is there, we have to 11748c2ecf20Sopenharmony_ci * handle the case of the DQRR reset bug... 11758c2ecf20Sopenharmony_ci */ 11768c2ecf20Sopenharmony_ci if (unlikely(s->dqrr.reset_bug)) { 11778c2ecf20Sopenharmony_ci /* 11788c2ecf20Sopenharmony_ci * We pick up new entries by cache-inhibited producer index, 11798c2ecf20Sopenharmony_ci * which means that a non-coherent mapping would require us to 11808c2ecf20Sopenharmony_ci * invalidate and read *only* once that PI has indicated that 11818c2ecf20Sopenharmony_ci * there's an entry here. The first trip around the DQRR ring 11828c2ecf20Sopenharmony_ci * will be much less efficient than all subsequent trips around 11838c2ecf20Sopenharmony_ci * it... 11848c2ecf20Sopenharmony_ci */ 11858c2ecf20Sopenharmony_ci u8 pi = qbman_read_register(s, QBMAN_CINH_SWP_DQPI) & 11868c2ecf20Sopenharmony_ci QMAN_DQRR_PI_MASK; 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_ci /* there are new entries if pi != next_idx */ 11898c2ecf20Sopenharmony_ci if (pi == s->dqrr.next_idx) 11908c2ecf20Sopenharmony_ci return NULL; 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_ci /* 11938c2ecf20Sopenharmony_ci * if next_idx is/was the last ring index, and 'pi' is 11948c2ecf20Sopenharmony_ci * different, we can disable the workaround as all the ring 11958c2ecf20Sopenharmony_ci * entries have now been DMA'd to so valid-bit checking is 11968c2ecf20Sopenharmony_ci * repaired. Note: this logic needs to be based on next_idx 11978c2ecf20Sopenharmony_ci * (which increments one at a time), rather than on pi (which 11988c2ecf20Sopenharmony_ci * can burst and wrap-around between our snapshots of it). 11998c2ecf20Sopenharmony_ci */ 12008c2ecf20Sopenharmony_ci if (s->dqrr.next_idx == (s->dqrr.dqrr_size - 1)) { 12018c2ecf20Sopenharmony_ci pr_debug("next_idx=%d, pi=%d, clear reset bug\n", 12028c2ecf20Sopenharmony_ci s->dqrr.next_idx, pi); 12038c2ecf20Sopenharmony_ci s->dqrr.reset_bug = 0; 12048c2ecf20Sopenharmony_ci } 12058c2ecf20Sopenharmony_ci prefetch(qbman_get_cmd(s, 12068c2ecf20Sopenharmony_ci QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx))); 12078c2ecf20Sopenharmony_ci } 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ci p = qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)); 12108c2ecf20Sopenharmony_ci verb = p->dq.verb; 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci /* 12138c2ecf20Sopenharmony_ci * If the valid-bit isn't of the expected polarity, nothing there. Note, 12148c2ecf20Sopenharmony_ci * in the DQRR reset bug workaround, we shouldn't need to skip these 12158c2ecf20Sopenharmony_ci * check, because we've already determined that a new entry is available 12168c2ecf20Sopenharmony_ci * and we've invalidated the cacheline before reading it, so the 12178c2ecf20Sopenharmony_ci * valid-bit behaviour is repaired and should tell us what we already 12188c2ecf20Sopenharmony_ci * knew from reading PI. 12198c2ecf20Sopenharmony_ci */ 12208c2ecf20Sopenharmony_ci if ((verb & QB_VALID_BIT) != s->dqrr.valid_bit) { 12218c2ecf20Sopenharmony_ci prefetch(qbman_get_cmd(s, 12228c2ecf20Sopenharmony_ci QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx))); 12238c2ecf20Sopenharmony_ci return NULL; 12248c2ecf20Sopenharmony_ci } 12258c2ecf20Sopenharmony_ci /* 12268c2ecf20Sopenharmony_ci * There's something there. Move "next_idx" attention to the next ring 12278c2ecf20Sopenharmony_ci * entry (and prefetch it) before returning what we found. 12288c2ecf20Sopenharmony_ci */ 12298c2ecf20Sopenharmony_ci s->dqrr.next_idx++; 12308c2ecf20Sopenharmony_ci s->dqrr.next_idx &= s->dqrr.dqrr_size - 1; /* Wrap around */ 12318c2ecf20Sopenharmony_ci if (!s->dqrr.next_idx) 12328c2ecf20Sopenharmony_ci s->dqrr.valid_bit ^= QB_VALID_BIT; 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci /* 12358c2ecf20Sopenharmony_ci * If this is the final response to a volatile dequeue command 12368c2ecf20Sopenharmony_ci * indicate that the vdq is available 12378c2ecf20Sopenharmony_ci */ 12388c2ecf20Sopenharmony_ci flags = p->dq.stat; 12398c2ecf20Sopenharmony_ci response_verb = verb & QBMAN_RESULT_MASK; 12408c2ecf20Sopenharmony_ci if ((response_verb == QBMAN_RESULT_DQ) && 12418c2ecf20Sopenharmony_ci (flags & DPAA2_DQ_STAT_VOLATILE) && 12428c2ecf20Sopenharmony_ci (flags & DPAA2_DQ_STAT_EXPIRED)) 12438c2ecf20Sopenharmony_ci atomic_inc(&s->vdq.available); 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_ci prefetch(qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx))); 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_ci return p; 12488c2ecf20Sopenharmony_ci} 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_ci/** 12518c2ecf20Sopenharmony_ci * qbman_swp_dqrr_next_mem_back() - Get an valid DQRR entry 12528c2ecf20Sopenharmony_ci * @s: the software portal object 12538c2ecf20Sopenharmony_ci * 12548c2ecf20Sopenharmony_ci * Return NULL if there are no unconsumed DQRR entries. Return a DQRR entry 12558c2ecf20Sopenharmony_ci * only once, so repeated calls can return a sequence of DQRR entries, without 12568c2ecf20Sopenharmony_ci * requiring they be consumed immediately or in any particular order. 12578c2ecf20Sopenharmony_ci */ 12588c2ecf20Sopenharmony_ciconst struct dpaa2_dq *qbman_swp_dqrr_next_mem_back(struct qbman_swp *s) 12598c2ecf20Sopenharmony_ci{ 12608c2ecf20Sopenharmony_ci u32 verb; 12618c2ecf20Sopenharmony_ci u32 response_verb; 12628c2ecf20Sopenharmony_ci u32 flags; 12638c2ecf20Sopenharmony_ci struct dpaa2_dq *p; 12648c2ecf20Sopenharmony_ci 12658c2ecf20Sopenharmony_ci /* Before using valid-bit to detect if something is there, we have to 12668c2ecf20Sopenharmony_ci * handle the case of the DQRR reset bug... 12678c2ecf20Sopenharmony_ci */ 12688c2ecf20Sopenharmony_ci if (unlikely(s->dqrr.reset_bug)) { 12698c2ecf20Sopenharmony_ci /* 12708c2ecf20Sopenharmony_ci * We pick up new entries by cache-inhibited producer index, 12718c2ecf20Sopenharmony_ci * which means that a non-coherent mapping would require us to 12728c2ecf20Sopenharmony_ci * invalidate and read *only* once that PI has indicated that 12738c2ecf20Sopenharmony_ci * there's an entry here. The first trip around the DQRR ring 12748c2ecf20Sopenharmony_ci * will be much less efficient than all subsequent trips around 12758c2ecf20Sopenharmony_ci * it... 12768c2ecf20Sopenharmony_ci */ 12778c2ecf20Sopenharmony_ci u8 pi = qbman_read_register(s, QBMAN_CINH_SWP_DQPI) & 12788c2ecf20Sopenharmony_ci QMAN_DQRR_PI_MASK; 12798c2ecf20Sopenharmony_ci 12808c2ecf20Sopenharmony_ci /* there are new entries if pi != next_idx */ 12818c2ecf20Sopenharmony_ci if (pi == s->dqrr.next_idx) 12828c2ecf20Sopenharmony_ci return NULL; 12838c2ecf20Sopenharmony_ci 12848c2ecf20Sopenharmony_ci /* 12858c2ecf20Sopenharmony_ci * if next_idx is/was the last ring index, and 'pi' is 12868c2ecf20Sopenharmony_ci * different, we can disable the workaround as all the ring 12878c2ecf20Sopenharmony_ci * entries have now been DMA'd to so valid-bit checking is 12888c2ecf20Sopenharmony_ci * repaired. Note: this logic needs to be based on next_idx 12898c2ecf20Sopenharmony_ci * (which increments one at a time), rather than on pi (which 12908c2ecf20Sopenharmony_ci * can burst and wrap-around between our snapshots of it). 12918c2ecf20Sopenharmony_ci */ 12928c2ecf20Sopenharmony_ci if (s->dqrr.next_idx == (s->dqrr.dqrr_size - 1)) { 12938c2ecf20Sopenharmony_ci pr_debug("next_idx=%d, pi=%d, clear reset bug\n", 12948c2ecf20Sopenharmony_ci s->dqrr.next_idx, pi); 12958c2ecf20Sopenharmony_ci s->dqrr.reset_bug = 0; 12968c2ecf20Sopenharmony_ci } 12978c2ecf20Sopenharmony_ci prefetch(qbman_get_cmd(s, 12988c2ecf20Sopenharmony_ci QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx))); 12998c2ecf20Sopenharmony_ci } 13008c2ecf20Sopenharmony_ci 13018c2ecf20Sopenharmony_ci p = qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR_MEM(s->dqrr.next_idx)); 13028c2ecf20Sopenharmony_ci verb = p->dq.verb; 13038c2ecf20Sopenharmony_ci 13048c2ecf20Sopenharmony_ci /* 13058c2ecf20Sopenharmony_ci * If the valid-bit isn't of the expected polarity, nothing there. Note, 13068c2ecf20Sopenharmony_ci * in the DQRR reset bug workaround, we shouldn't need to skip these 13078c2ecf20Sopenharmony_ci * check, because we've already determined that a new entry is available 13088c2ecf20Sopenharmony_ci * and we've invalidated the cacheline before reading it, so the 13098c2ecf20Sopenharmony_ci * valid-bit behaviour is repaired and should tell us what we already 13108c2ecf20Sopenharmony_ci * knew from reading PI. 13118c2ecf20Sopenharmony_ci */ 13128c2ecf20Sopenharmony_ci if ((verb & QB_VALID_BIT) != s->dqrr.valid_bit) { 13138c2ecf20Sopenharmony_ci prefetch(qbman_get_cmd(s, 13148c2ecf20Sopenharmony_ci QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx))); 13158c2ecf20Sopenharmony_ci return NULL; 13168c2ecf20Sopenharmony_ci } 13178c2ecf20Sopenharmony_ci /* 13188c2ecf20Sopenharmony_ci * There's something there. Move "next_idx" attention to the next ring 13198c2ecf20Sopenharmony_ci * entry (and prefetch it) before returning what we found. 13208c2ecf20Sopenharmony_ci */ 13218c2ecf20Sopenharmony_ci s->dqrr.next_idx++; 13228c2ecf20Sopenharmony_ci s->dqrr.next_idx &= s->dqrr.dqrr_size - 1; /* Wrap around */ 13238c2ecf20Sopenharmony_ci if (!s->dqrr.next_idx) 13248c2ecf20Sopenharmony_ci s->dqrr.valid_bit ^= QB_VALID_BIT; 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_ci /* 13278c2ecf20Sopenharmony_ci * If this is the final response to a volatile dequeue command 13288c2ecf20Sopenharmony_ci * indicate that the vdq is available 13298c2ecf20Sopenharmony_ci */ 13308c2ecf20Sopenharmony_ci flags = p->dq.stat; 13318c2ecf20Sopenharmony_ci response_verb = verb & QBMAN_RESULT_MASK; 13328c2ecf20Sopenharmony_ci if ((response_verb == QBMAN_RESULT_DQ) && 13338c2ecf20Sopenharmony_ci (flags & DPAA2_DQ_STAT_VOLATILE) && 13348c2ecf20Sopenharmony_ci (flags & DPAA2_DQ_STAT_EXPIRED)) 13358c2ecf20Sopenharmony_ci atomic_inc(&s->vdq.available); 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_ci prefetch(qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx))); 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_ci return p; 13408c2ecf20Sopenharmony_ci} 13418c2ecf20Sopenharmony_ci 13428c2ecf20Sopenharmony_ci/** 13438c2ecf20Sopenharmony_ci * qbman_swp_dqrr_consume() - Consume DQRR entries previously returned from 13448c2ecf20Sopenharmony_ci * qbman_swp_dqrr_next(). 13458c2ecf20Sopenharmony_ci * @s: the software portal object 13468c2ecf20Sopenharmony_ci * @dq: the DQRR entry to be consumed 13478c2ecf20Sopenharmony_ci */ 13488c2ecf20Sopenharmony_civoid qbman_swp_dqrr_consume(struct qbman_swp *s, const struct dpaa2_dq *dq) 13498c2ecf20Sopenharmony_ci{ 13508c2ecf20Sopenharmony_ci qbman_write_register(s, QBMAN_CINH_SWP_DCAP, QBMAN_IDX_FROM_DQRR(dq)); 13518c2ecf20Sopenharmony_ci} 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_ci/** 13548c2ecf20Sopenharmony_ci * qbman_result_has_new_result() - Check and get the dequeue response from the 13558c2ecf20Sopenharmony_ci * dq storage memory set in pull dequeue command 13568c2ecf20Sopenharmony_ci * @s: the software portal object 13578c2ecf20Sopenharmony_ci * @dq: the dequeue result read from the memory 13588c2ecf20Sopenharmony_ci * 13598c2ecf20Sopenharmony_ci * Return 1 for getting a valid dequeue result, or 0 for not getting a valid 13608c2ecf20Sopenharmony_ci * dequeue result. 13618c2ecf20Sopenharmony_ci * 13628c2ecf20Sopenharmony_ci * Only used for user-provided storage of dequeue results, not DQRR. For 13638c2ecf20Sopenharmony_ci * efficiency purposes, the driver will perform any required endianness 13648c2ecf20Sopenharmony_ci * conversion to ensure that the user's dequeue result storage is in host-endian 13658c2ecf20Sopenharmony_ci * format. As such, once the user has called qbman_result_has_new_result() and 13668c2ecf20Sopenharmony_ci * been returned a valid dequeue result, they should not call it again on 13678c2ecf20Sopenharmony_ci * the same memory location (except of course if another dequeue command has 13688c2ecf20Sopenharmony_ci * been executed to produce a new result to that location). 13698c2ecf20Sopenharmony_ci */ 13708c2ecf20Sopenharmony_ciint qbman_result_has_new_result(struct qbman_swp *s, const struct dpaa2_dq *dq) 13718c2ecf20Sopenharmony_ci{ 13728c2ecf20Sopenharmony_ci if (dq->dq.tok != QMAN_DQ_TOKEN_VALID) 13738c2ecf20Sopenharmony_ci return 0; 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_ci /* 13768c2ecf20Sopenharmony_ci * Set token to be 0 so we will detect change back to 1 13778c2ecf20Sopenharmony_ci * next time the looping is traversed. Const is cast away here 13788c2ecf20Sopenharmony_ci * as we want users to treat the dequeue responses as read only. 13798c2ecf20Sopenharmony_ci */ 13808c2ecf20Sopenharmony_ci ((struct dpaa2_dq *)dq)->dq.tok = 0; 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_ci /* 13838c2ecf20Sopenharmony_ci * Determine whether VDQCR is available based on whether the 13848c2ecf20Sopenharmony_ci * current result is sitting in the first storage location of 13858c2ecf20Sopenharmony_ci * the busy command. 13868c2ecf20Sopenharmony_ci */ 13878c2ecf20Sopenharmony_ci if (s->vdq.storage == dq) { 13888c2ecf20Sopenharmony_ci s->vdq.storage = NULL; 13898c2ecf20Sopenharmony_ci atomic_inc(&s->vdq.available); 13908c2ecf20Sopenharmony_ci } 13918c2ecf20Sopenharmony_ci 13928c2ecf20Sopenharmony_ci return 1; 13938c2ecf20Sopenharmony_ci} 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci/** 13968c2ecf20Sopenharmony_ci * qbman_release_desc_clear() - Clear the contents of a descriptor to 13978c2ecf20Sopenharmony_ci * default/starting state. 13988c2ecf20Sopenharmony_ci */ 13998c2ecf20Sopenharmony_civoid qbman_release_desc_clear(struct qbman_release_desc *d) 14008c2ecf20Sopenharmony_ci{ 14018c2ecf20Sopenharmony_ci memset(d, 0, sizeof(*d)); 14028c2ecf20Sopenharmony_ci d->verb = 1 << 5; /* Release Command Valid */ 14038c2ecf20Sopenharmony_ci} 14048c2ecf20Sopenharmony_ci 14058c2ecf20Sopenharmony_ci/** 14068c2ecf20Sopenharmony_ci * qbman_release_desc_set_bpid() - Set the ID of the buffer pool to release to 14078c2ecf20Sopenharmony_ci */ 14088c2ecf20Sopenharmony_civoid qbman_release_desc_set_bpid(struct qbman_release_desc *d, u16 bpid) 14098c2ecf20Sopenharmony_ci{ 14108c2ecf20Sopenharmony_ci d->bpid = cpu_to_le16(bpid); 14118c2ecf20Sopenharmony_ci} 14128c2ecf20Sopenharmony_ci 14138c2ecf20Sopenharmony_ci/** 14148c2ecf20Sopenharmony_ci * qbman_release_desc_set_rcdi() - Determines whether or not the portal's RCDI 14158c2ecf20Sopenharmony_ci * interrupt source should be asserted after the release command is completed. 14168c2ecf20Sopenharmony_ci */ 14178c2ecf20Sopenharmony_civoid qbman_release_desc_set_rcdi(struct qbman_release_desc *d, int enable) 14188c2ecf20Sopenharmony_ci{ 14198c2ecf20Sopenharmony_ci if (enable) 14208c2ecf20Sopenharmony_ci d->verb |= 1 << 6; 14218c2ecf20Sopenharmony_ci else 14228c2ecf20Sopenharmony_ci d->verb &= ~(1 << 6); 14238c2ecf20Sopenharmony_ci} 14248c2ecf20Sopenharmony_ci 14258c2ecf20Sopenharmony_ci#define RAR_IDX(rar) ((rar) & 0x7) 14268c2ecf20Sopenharmony_ci#define RAR_VB(rar) ((rar) & 0x80) 14278c2ecf20Sopenharmony_ci#define RAR_SUCCESS(rar) ((rar) & 0x100) 14288c2ecf20Sopenharmony_ci 14298c2ecf20Sopenharmony_ci/** 14308c2ecf20Sopenharmony_ci * qbman_swp_release_direct() - Issue a buffer release command 14318c2ecf20Sopenharmony_ci * @s: the software portal object 14328c2ecf20Sopenharmony_ci * @d: the release descriptor 14338c2ecf20Sopenharmony_ci * @buffers: a pointer pointing to the buffer address to be released 14348c2ecf20Sopenharmony_ci * @num_buffers: number of buffers to be released, must be less than 8 14358c2ecf20Sopenharmony_ci * 14368c2ecf20Sopenharmony_ci * Return 0 for success, -EBUSY if the release command ring is not ready. 14378c2ecf20Sopenharmony_ci */ 14388c2ecf20Sopenharmony_ciint qbman_swp_release_direct(struct qbman_swp *s, 14398c2ecf20Sopenharmony_ci const struct qbman_release_desc *d, 14408c2ecf20Sopenharmony_ci const u64 *buffers, unsigned int num_buffers) 14418c2ecf20Sopenharmony_ci{ 14428c2ecf20Sopenharmony_ci int i; 14438c2ecf20Sopenharmony_ci struct qbman_release_desc *p; 14448c2ecf20Sopenharmony_ci u32 rar; 14458c2ecf20Sopenharmony_ci 14468c2ecf20Sopenharmony_ci if (!num_buffers || (num_buffers > 7)) 14478c2ecf20Sopenharmony_ci return -EINVAL; 14488c2ecf20Sopenharmony_ci 14498c2ecf20Sopenharmony_ci rar = qbman_read_register(s, QBMAN_CINH_SWP_RAR); 14508c2ecf20Sopenharmony_ci if (!RAR_SUCCESS(rar)) 14518c2ecf20Sopenharmony_ci return -EBUSY; 14528c2ecf20Sopenharmony_ci 14538c2ecf20Sopenharmony_ci /* Start the release command */ 14548c2ecf20Sopenharmony_ci p = qbman_get_cmd(s, QBMAN_CENA_SWP_RCR(RAR_IDX(rar))); 14558c2ecf20Sopenharmony_ci 14568c2ecf20Sopenharmony_ci /* Copy the caller's buffer pointers to the command */ 14578c2ecf20Sopenharmony_ci for (i = 0; i < num_buffers; i++) 14588c2ecf20Sopenharmony_ci p->buf[i] = cpu_to_le64(buffers[i]); 14598c2ecf20Sopenharmony_ci p->bpid = d->bpid; 14608c2ecf20Sopenharmony_ci 14618c2ecf20Sopenharmony_ci /* 14628c2ecf20Sopenharmony_ci * Set the verb byte, have to substitute in the valid-bit 14638c2ecf20Sopenharmony_ci * and the number of buffers. 14648c2ecf20Sopenharmony_ci */ 14658c2ecf20Sopenharmony_ci dma_wmb(); 14668c2ecf20Sopenharmony_ci p->verb = d->verb | RAR_VB(rar) | num_buffers; 14678c2ecf20Sopenharmony_ci 14688c2ecf20Sopenharmony_ci return 0; 14698c2ecf20Sopenharmony_ci} 14708c2ecf20Sopenharmony_ci 14718c2ecf20Sopenharmony_ci/** 14728c2ecf20Sopenharmony_ci * qbman_swp_release_mem_back() - Issue a buffer release command 14738c2ecf20Sopenharmony_ci * @s: the software portal object 14748c2ecf20Sopenharmony_ci * @d: the release descriptor 14758c2ecf20Sopenharmony_ci * @buffers: a pointer pointing to the buffer address to be released 14768c2ecf20Sopenharmony_ci * @num_buffers: number of buffers to be released, must be less than 8 14778c2ecf20Sopenharmony_ci * 14788c2ecf20Sopenharmony_ci * Return 0 for success, -EBUSY if the release command ring is not ready. 14798c2ecf20Sopenharmony_ci */ 14808c2ecf20Sopenharmony_ciint qbman_swp_release_mem_back(struct qbman_swp *s, 14818c2ecf20Sopenharmony_ci const struct qbman_release_desc *d, 14828c2ecf20Sopenharmony_ci const u64 *buffers, unsigned int num_buffers) 14838c2ecf20Sopenharmony_ci{ 14848c2ecf20Sopenharmony_ci int i; 14858c2ecf20Sopenharmony_ci struct qbman_release_desc *p; 14868c2ecf20Sopenharmony_ci u32 rar; 14878c2ecf20Sopenharmony_ci 14888c2ecf20Sopenharmony_ci if (!num_buffers || (num_buffers > 7)) 14898c2ecf20Sopenharmony_ci return -EINVAL; 14908c2ecf20Sopenharmony_ci 14918c2ecf20Sopenharmony_ci rar = qbman_read_register(s, QBMAN_CINH_SWP_RAR); 14928c2ecf20Sopenharmony_ci if (!RAR_SUCCESS(rar)) 14938c2ecf20Sopenharmony_ci return -EBUSY; 14948c2ecf20Sopenharmony_ci 14958c2ecf20Sopenharmony_ci /* Start the release command */ 14968c2ecf20Sopenharmony_ci p = qbman_get_cmd(s, QBMAN_CENA_SWP_RCR_MEM(RAR_IDX(rar))); 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci /* Copy the caller's buffer pointers to the command */ 14998c2ecf20Sopenharmony_ci for (i = 0; i < num_buffers; i++) 15008c2ecf20Sopenharmony_ci p->buf[i] = cpu_to_le64(buffers[i]); 15018c2ecf20Sopenharmony_ci p->bpid = d->bpid; 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_ci p->verb = d->verb | RAR_VB(rar) | num_buffers; 15048c2ecf20Sopenharmony_ci dma_wmb(); 15058c2ecf20Sopenharmony_ci qbman_write_register(s, QBMAN_CINH_SWP_RCR_AM_RT + 15068c2ecf20Sopenharmony_ci RAR_IDX(rar) * 4, QMAN_RT_MODE); 15078c2ecf20Sopenharmony_ci 15088c2ecf20Sopenharmony_ci return 0; 15098c2ecf20Sopenharmony_ci} 15108c2ecf20Sopenharmony_ci 15118c2ecf20Sopenharmony_cistruct qbman_acquire_desc { 15128c2ecf20Sopenharmony_ci u8 verb; 15138c2ecf20Sopenharmony_ci u8 reserved; 15148c2ecf20Sopenharmony_ci __le16 bpid; 15158c2ecf20Sopenharmony_ci u8 num; 15168c2ecf20Sopenharmony_ci u8 reserved2[59]; 15178c2ecf20Sopenharmony_ci}; 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_cistruct qbman_acquire_rslt { 15208c2ecf20Sopenharmony_ci u8 verb; 15218c2ecf20Sopenharmony_ci u8 rslt; 15228c2ecf20Sopenharmony_ci __le16 reserved; 15238c2ecf20Sopenharmony_ci u8 num; 15248c2ecf20Sopenharmony_ci u8 reserved2[3]; 15258c2ecf20Sopenharmony_ci __le64 buf[7]; 15268c2ecf20Sopenharmony_ci}; 15278c2ecf20Sopenharmony_ci 15288c2ecf20Sopenharmony_ci/** 15298c2ecf20Sopenharmony_ci * qbman_swp_acquire() - Issue a buffer acquire command 15308c2ecf20Sopenharmony_ci * @s: the software portal object 15318c2ecf20Sopenharmony_ci * @bpid: the buffer pool index 15328c2ecf20Sopenharmony_ci * @buffers: a pointer pointing to the acquired buffer addresses 15338c2ecf20Sopenharmony_ci * @num_buffers: number of buffers to be acquired, must be less than 8 15348c2ecf20Sopenharmony_ci * 15358c2ecf20Sopenharmony_ci * Return 0 for success, or negative error code if the acquire command 15368c2ecf20Sopenharmony_ci * fails. 15378c2ecf20Sopenharmony_ci */ 15388c2ecf20Sopenharmony_ciint qbman_swp_acquire(struct qbman_swp *s, u16 bpid, u64 *buffers, 15398c2ecf20Sopenharmony_ci unsigned int num_buffers) 15408c2ecf20Sopenharmony_ci{ 15418c2ecf20Sopenharmony_ci struct qbman_acquire_desc *p; 15428c2ecf20Sopenharmony_ci struct qbman_acquire_rslt *r; 15438c2ecf20Sopenharmony_ci int i; 15448c2ecf20Sopenharmony_ci 15458c2ecf20Sopenharmony_ci if (!num_buffers || (num_buffers > 7)) 15468c2ecf20Sopenharmony_ci return -EINVAL; 15478c2ecf20Sopenharmony_ci 15488c2ecf20Sopenharmony_ci /* Start the management command */ 15498c2ecf20Sopenharmony_ci p = qbman_swp_mc_start(s); 15508c2ecf20Sopenharmony_ci 15518c2ecf20Sopenharmony_ci if (!p) 15528c2ecf20Sopenharmony_ci return -EBUSY; 15538c2ecf20Sopenharmony_ci 15548c2ecf20Sopenharmony_ci /* Encode the caller-provided attributes */ 15558c2ecf20Sopenharmony_ci p->bpid = cpu_to_le16(bpid); 15568c2ecf20Sopenharmony_ci p->num = num_buffers; 15578c2ecf20Sopenharmony_ci 15588c2ecf20Sopenharmony_ci /* Complete the management command */ 15598c2ecf20Sopenharmony_ci r = qbman_swp_mc_complete(s, p, QBMAN_MC_ACQUIRE); 15608c2ecf20Sopenharmony_ci if (unlikely(!r)) { 15618c2ecf20Sopenharmony_ci pr_err("qbman: acquire from BPID %d failed, no response\n", 15628c2ecf20Sopenharmony_ci bpid); 15638c2ecf20Sopenharmony_ci return -EIO; 15648c2ecf20Sopenharmony_ci } 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_ci /* Decode the outcome */ 15678c2ecf20Sopenharmony_ci WARN_ON((r->verb & 0x7f) != QBMAN_MC_ACQUIRE); 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_ci /* Determine success or failure */ 15708c2ecf20Sopenharmony_ci if (unlikely(r->rslt != QBMAN_MC_RSLT_OK)) { 15718c2ecf20Sopenharmony_ci pr_err("qbman: acquire from BPID 0x%x failed, code=0x%02x\n", 15728c2ecf20Sopenharmony_ci bpid, r->rslt); 15738c2ecf20Sopenharmony_ci return -EIO; 15748c2ecf20Sopenharmony_ci } 15758c2ecf20Sopenharmony_ci 15768c2ecf20Sopenharmony_ci WARN_ON(r->num > num_buffers); 15778c2ecf20Sopenharmony_ci 15788c2ecf20Sopenharmony_ci /* Copy the acquired buffers to the caller's array */ 15798c2ecf20Sopenharmony_ci for (i = 0; i < r->num; i++) 15808c2ecf20Sopenharmony_ci buffers[i] = le64_to_cpu(r->buf[i]); 15818c2ecf20Sopenharmony_ci 15828c2ecf20Sopenharmony_ci return (int)r->num; 15838c2ecf20Sopenharmony_ci} 15848c2ecf20Sopenharmony_ci 15858c2ecf20Sopenharmony_cistruct qbman_alt_fq_state_desc { 15868c2ecf20Sopenharmony_ci u8 verb; 15878c2ecf20Sopenharmony_ci u8 reserved[3]; 15888c2ecf20Sopenharmony_ci __le32 fqid; 15898c2ecf20Sopenharmony_ci u8 reserved2[56]; 15908c2ecf20Sopenharmony_ci}; 15918c2ecf20Sopenharmony_ci 15928c2ecf20Sopenharmony_cistruct qbman_alt_fq_state_rslt { 15938c2ecf20Sopenharmony_ci u8 verb; 15948c2ecf20Sopenharmony_ci u8 rslt; 15958c2ecf20Sopenharmony_ci u8 reserved[62]; 15968c2ecf20Sopenharmony_ci}; 15978c2ecf20Sopenharmony_ci 15988c2ecf20Sopenharmony_ci#define ALT_FQ_FQID_MASK 0x00FFFFFF 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_ciint qbman_swp_alt_fq_state(struct qbman_swp *s, u32 fqid, 16018c2ecf20Sopenharmony_ci u8 alt_fq_verb) 16028c2ecf20Sopenharmony_ci{ 16038c2ecf20Sopenharmony_ci struct qbman_alt_fq_state_desc *p; 16048c2ecf20Sopenharmony_ci struct qbman_alt_fq_state_rslt *r; 16058c2ecf20Sopenharmony_ci 16068c2ecf20Sopenharmony_ci /* Start the management command */ 16078c2ecf20Sopenharmony_ci p = qbman_swp_mc_start(s); 16088c2ecf20Sopenharmony_ci if (!p) 16098c2ecf20Sopenharmony_ci return -EBUSY; 16108c2ecf20Sopenharmony_ci 16118c2ecf20Sopenharmony_ci p->fqid = cpu_to_le32(fqid & ALT_FQ_FQID_MASK); 16128c2ecf20Sopenharmony_ci 16138c2ecf20Sopenharmony_ci /* Complete the management command */ 16148c2ecf20Sopenharmony_ci r = qbman_swp_mc_complete(s, p, alt_fq_verb); 16158c2ecf20Sopenharmony_ci if (unlikely(!r)) { 16168c2ecf20Sopenharmony_ci pr_err("qbman: mgmt cmd failed, no response (verb=0x%x)\n", 16178c2ecf20Sopenharmony_ci alt_fq_verb); 16188c2ecf20Sopenharmony_ci return -EIO; 16198c2ecf20Sopenharmony_ci } 16208c2ecf20Sopenharmony_ci 16218c2ecf20Sopenharmony_ci /* Decode the outcome */ 16228c2ecf20Sopenharmony_ci WARN_ON((r->verb & QBMAN_RESULT_MASK) != alt_fq_verb); 16238c2ecf20Sopenharmony_ci 16248c2ecf20Sopenharmony_ci /* Determine success or failure */ 16258c2ecf20Sopenharmony_ci if (unlikely(r->rslt != QBMAN_MC_RSLT_OK)) { 16268c2ecf20Sopenharmony_ci pr_err("qbman: ALT FQID %d failed: verb = 0x%08x code = 0x%02x\n", 16278c2ecf20Sopenharmony_ci fqid, r->verb, r->rslt); 16288c2ecf20Sopenharmony_ci return -EIO; 16298c2ecf20Sopenharmony_ci } 16308c2ecf20Sopenharmony_ci 16318c2ecf20Sopenharmony_ci return 0; 16328c2ecf20Sopenharmony_ci} 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_cistruct qbman_cdan_ctrl_desc { 16358c2ecf20Sopenharmony_ci u8 verb; 16368c2ecf20Sopenharmony_ci u8 reserved; 16378c2ecf20Sopenharmony_ci __le16 ch; 16388c2ecf20Sopenharmony_ci u8 we; 16398c2ecf20Sopenharmony_ci u8 ctrl; 16408c2ecf20Sopenharmony_ci __le16 reserved2; 16418c2ecf20Sopenharmony_ci __le64 cdan_ctx; 16428c2ecf20Sopenharmony_ci u8 reserved3[48]; 16438c2ecf20Sopenharmony_ci 16448c2ecf20Sopenharmony_ci}; 16458c2ecf20Sopenharmony_ci 16468c2ecf20Sopenharmony_cistruct qbman_cdan_ctrl_rslt { 16478c2ecf20Sopenharmony_ci u8 verb; 16488c2ecf20Sopenharmony_ci u8 rslt; 16498c2ecf20Sopenharmony_ci __le16 ch; 16508c2ecf20Sopenharmony_ci u8 reserved[60]; 16518c2ecf20Sopenharmony_ci}; 16528c2ecf20Sopenharmony_ci 16538c2ecf20Sopenharmony_ciint qbman_swp_CDAN_set(struct qbman_swp *s, u16 channelid, 16548c2ecf20Sopenharmony_ci u8 we_mask, u8 cdan_en, 16558c2ecf20Sopenharmony_ci u64 ctx) 16568c2ecf20Sopenharmony_ci{ 16578c2ecf20Sopenharmony_ci struct qbman_cdan_ctrl_desc *p = NULL; 16588c2ecf20Sopenharmony_ci struct qbman_cdan_ctrl_rslt *r = NULL; 16598c2ecf20Sopenharmony_ci 16608c2ecf20Sopenharmony_ci /* Start the management command */ 16618c2ecf20Sopenharmony_ci p = qbman_swp_mc_start(s); 16628c2ecf20Sopenharmony_ci if (!p) 16638c2ecf20Sopenharmony_ci return -EBUSY; 16648c2ecf20Sopenharmony_ci 16658c2ecf20Sopenharmony_ci /* Encode the caller-provided attributes */ 16668c2ecf20Sopenharmony_ci p->ch = cpu_to_le16(channelid); 16678c2ecf20Sopenharmony_ci p->we = we_mask; 16688c2ecf20Sopenharmony_ci if (cdan_en) 16698c2ecf20Sopenharmony_ci p->ctrl = 1; 16708c2ecf20Sopenharmony_ci else 16718c2ecf20Sopenharmony_ci p->ctrl = 0; 16728c2ecf20Sopenharmony_ci p->cdan_ctx = cpu_to_le64(ctx); 16738c2ecf20Sopenharmony_ci 16748c2ecf20Sopenharmony_ci /* Complete the management command */ 16758c2ecf20Sopenharmony_ci r = qbman_swp_mc_complete(s, p, QBMAN_WQCHAN_CONFIGURE); 16768c2ecf20Sopenharmony_ci if (unlikely(!r)) { 16778c2ecf20Sopenharmony_ci pr_err("qbman: wqchan config failed, no response\n"); 16788c2ecf20Sopenharmony_ci return -EIO; 16798c2ecf20Sopenharmony_ci } 16808c2ecf20Sopenharmony_ci 16818c2ecf20Sopenharmony_ci WARN_ON((r->verb & 0x7f) != QBMAN_WQCHAN_CONFIGURE); 16828c2ecf20Sopenharmony_ci 16838c2ecf20Sopenharmony_ci /* Determine success or failure */ 16848c2ecf20Sopenharmony_ci if (unlikely(r->rslt != QBMAN_MC_RSLT_OK)) { 16858c2ecf20Sopenharmony_ci pr_err("qbman: CDAN cQID %d failed: code = 0x%02x\n", 16868c2ecf20Sopenharmony_ci channelid, r->rslt); 16878c2ecf20Sopenharmony_ci return -EIO; 16888c2ecf20Sopenharmony_ci } 16898c2ecf20Sopenharmony_ci 16908c2ecf20Sopenharmony_ci return 0; 16918c2ecf20Sopenharmony_ci} 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci#define QBMAN_RESPONSE_VERB_MASK 0x7f 16948c2ecf20Sopenharmony_ci#define QBMAN_FQ_QUERY_NP 0x45 16958c2ecf20Sopenharmony_ci#define QBMAN_BP_QUERY 0x32 16968c2ecf20Sopenharmony_ci 16978c2ecf20Sopenharmony_cistruct qbman_fq_query_desc { 16988c2ecf20Sopenharmony_ci u8 verb; 16998c2ecf20Sopenharmony_ci u8 reserved[3]; 17008c2ecf20Sopenharmony_ci __le32 fqid; 17018c2ecf20Sopenharmony_ci u8 reserved2[56]; 17028c2ecf20Sopenharmony_ci}; 17038c2ecf20Sopenharmony_ci 17048c2ecf20Sopenharmony_ciint qbman_fq_query_state(struct qbman_swp *s, u32 fqid, 17058c2ecf20Sopenharmony_ci struct qbman_fq_query_np_rslt *r) 17068c2ecf20Sopenharmony_ci{ 17078c2ecf20Sopenharmony_ci struct qbman_fq_query_desc *p; 17088c2ecf20Sopenharmony_ci void *resp; 17098c2ecf20Sopenharmony_ci 17108c2ecf20Sopenharmony_ci p = (struct qbman_fq_query_desc *)qbman_swp_mc_start(s); 17118c2ecf20Sopenharmony_ci if (!p) 17128c2ecf20Sopenharmony_ci return -EBUSY; 17138c2ecf20Sopenharmony_ci 17148c2ecf20Sopenharmony_ci /* FQID is a 24 bit value */ 17158c2ecf20Sopenharmony_ci p->fqid = cpu_to_le32(fqid & 0x00FFFFFF); 17168c2ecf20Sopenharmony_ci resp = qbman_swp_mc_complete(s, p, QBMAN_FQ_QUERY_NP); 17178c2ecf20Sopenharmony_ci if (!resp) { 17188c2ecf20Sopenharmony_ci pr_err("qbman: Query FQID %d NP fields failed, no response\n", 17198c2ecf20Sopenharmony_ci fqid); 17208c2ecf20Sopenharmony_ci return -EIO; 17218c2ecf20Sopenharmony_ci } 17228c2ecf20Sopenharmony_ci *r = *(struct qbman_fq_query_np_rslt *)resp; 17238c2ecf20Sopenharmony_ci /* Decode the outcome */ 17248c2ecf20Sopenharmony_ci WARN_ON((r->verb & QBMAN_RESPONSE_VERB_MASK) != QBMAN_FQ_QUERY_NP); 17258c2ecf20Sopenharmony_ci 17268c2ecf20Sopenharmony_ci /* Determine success or failure */ 17278c2ecf20Sopenharmony_ci if (r->rslt != QBMAN_MC_RSLT_OK) { 17288c2ecf20Sopenharmony_ci pr_err("Query NP fields of FQID 0x%x failed, code=0x%02x\n", 17298c2ecf20Sopenharmony_ci p->fqid, r->rslt); 17308c2ecf20Sopenharmony_ci return -EIO; 17318c2ecf20Sopenharmony_ci } 17328c2ecf20Sopenharmony_ci 17338c2ecf20Sopenharmony_ci return 0; 17348c2ecf20Sopenharmony_ci} 17358c2ecf20Sopenharmony_ci 17368c2ecf20Sopenharmony_ciu32 qbman_fq_state_frame_count(const struct qbman_fq_query_np_rslt *r) 17378c2ecf20Sopenharmony_ci{ 17388c2ecf20Sopenharmony_ci return (le32_to_cpu(r->frm_cnt) & 0x00FFFFFF); 17398c2ecf20Sopenharmony_ci} 17408c2ecf20Sopenharmony_ci 17418c2ecf20Sopenharmony_ciu32 qbman_fq_state_byte_count(const struct qbman_fq_query_np_rslt *r) 17428c2ecf20Sopenharmony_ci{ 17438c2ecf20Sopenharmony_ci return le32_to_cpu(r->byte_cnt); 17448c2ecf20Sopenharmony_ci} 17458c2ecf20Sopenharmony_ci 17468c2ecf20Sopenharmony_cistruct qbman_bp_query_desc { 17478c2ecf20Sopenharmony_ci u8 verb; 17488c2ecf20Sopenharmony_ci u8 reserved; 17498c2ecf20Sopenharmony_ci __le16 bpid; 17508c2ecf20Sopenharmony_ci u8 reserved2[60]; 17518c2ecf20Sopenharmony_ci}; 17528c2ecf20Sopenharmony_ci 17538c2ecf20Sopenharmony_ciint qbman_bp_query(struct qbman_swp *s, u16 bpid, 17548c2ecf20Sopenharmony_ci struct qbman_bp_query_rslt *r) 17558c2ecf20Sopenharmony_ci{ 17568c2ecf20Sopenharmony_ci struct qbman_bp_query_desc *p; 17578c2ecf20Sopenharmony_ci void *resp; 17588c2ecf20Sopenharmony_ci 17598c2ecf20Sopenharmony_ci p = (struct qbman_bp_query_desc *)qbman_swp_mc_start(s); 17608c2ecf20Sopenharmony_ci if (!p) 17618c2ecf20Sopenharmony_ci return -EBUSY; 17628c2ecf20Sopenharmony_ci 17638c2ecf20Sopenharmony_ci p->bpid = cpu_to_le16(bpid); 17648c2ecf20Sopenharmony_ci resp = qbman_swp_mc_complete(s, p, QBMAN_BP_QUERY); 17658c2ecf20Sopenharmony_ci if (!resp) { 17668c2ecf20Sopenharmony_ci pr_err("qbman: Query BPID %d fields failed, no response\n", 17678c2ecf20Sopenharmony_ci bpid); 17688c2ecf20Sopenharmony_ci return -EIO; 17698c2ecf20Sopenharmony_ci } 17708c2ecf20Sopenharmony_ci *r = *(struct qbman_bp_query_rslt *)resp; 17718c2ecf20Sopenharmony_ci /* Decode the outcome */ 17728c2ecf20Sopenharmony_ci WARN_ON((r->verb & QBMAN_RESPONSE_VERB_MASK) != QBMAN_BP_QUERY); 17738c2ecf20Sopenharmony_ci 17748c2ecf20Sopenharmony_ci /* Determine success or failure */ 17758c2ecf20Sopenharmony_ci if (r->rslt != QBMAN_MC_RSLT_OK) { 17768c2ecf20Sopenharmony_ci pr_err("Query fields of BPID 0x%x failed, code=0x%02x\n", 17778c2ecf20Sopenharmony_ci bpid, r->rslt); 17788c2ecf20Sopenharmony_ci return -EIO; 17798c2ecf20Sopenharmony_ci } 17808c2ecf20Sopenharmony_ci 17818c2ecf20Sopenharmony_ci return 0; 17828c2ecf20Sopenharmony_ci} 17838c2ecf20Sopenharmony_ci 17848c2ecf20Sopenharmony_ciu32 qbman_bp_info_num_free_bufs(struct qbman_bp_query_rslt *a) 17858c2ecf20Sopenharmony_ci{ 17868c2ecf20Sopenharmony_ci return le32_to_cpu(a->fill); 17878c2ecf20Sopenharmony_ci} 1788