Commit caa2da34 authored by Sunil Goutham's avatar Sunil Goutham Committed by David S. Miller

octeontx2-pf: Initialize and config queues

This patch does the initialization of all queues ie the
receive buffer pools, receive and transmit queues, completion
or notification queues etc. Allocates all required resources
(eg transmit schedulers, receive buffers etc) and configures
them for proper functioning of queues. Also sets up receive
queue's RED dropping levels.
Co-developed-by: default avatarGeetha sowjanya <gakula@marvell.com>
Signed-off-by: default avatarGeetha sowjanya <gakula@marvell.com>
Signed-off-by: default avatarSunil Goutham <sgoutham@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 05fcc9e0
......@@ -143,8 +143,13 @@ enum nix_scheduler {
NIX_TXSCH_LVL_CNT = 0x5,
};
#define TXSCH_TL1_DFLT_RR_QTM ((1 << 24) - 1)
#define TXSCH_TL1_DFLT_RR_PRIO (0x1ull)
#define TXSCH_RR_QTM_MAX ((1 << 24) - 1)
#define TXSCH_TL1_DFLT_RR_QTM TXSCH_RR_QTM_MAX
#define TXSCH_TL1_DFLT_RR_PRIO (0x1ull)
#define MAX_SCHED_WEIGHT 0xFF
#define DFLT_RR_WEIGHT 71
#define DFLT_RR_QTM ((DFLT_RR_WEIGHT * TXSCH_RR_QTM_MAX) \
/ MAX_SCHED_WEIGHT)
/* Min/Max packet sizes, excluding FCS */
#define NIC_HW_MIN_FRS 40
......
......@@ -12,9 +12,11 @@
#define OTX2_COMMON_H
#include <linux/pci.h>
#include <linux/iommu.h>
#include <mbox.h>
#include "otx2_reg.h"
#include "otx2_txrx.h"
/* PCI device IDs */
#define PCI_DEVID_OCTEONTX2_RVU_PF 0xA063
......@@ -25,15 +27,9 @@
#define NAME_SIZE 32
struct otx2_pool {
struct qmem *stack;
};
struct otx2_qset {
#define OTX2_MAX_CQ_CNT 64
u16 cq_cnt;
u16 xqe_size; /* Size of CQE i.e 128 or 512 bytes */
struct otx2_pool *pool;
enum arua_mapped_qtypes {
AURA_NIX_RQ,
AURA_NIX_SQ,
};
struct mbox {
......@@ -54,14 +50,21 @@ struct otx2_hw {
u16 tx_queues;
u16 max_queues;
u16 pool_cnt;
u16 rqpool_cnt;
u16 sqpool_cnt;
/* NPA */
u32 stack_pg_ptrs; /* No of ptrs per stack page */
u32 stack_pg_bytes; /* Size of stack page */
u16 sqb_size;
/* NIX */
u16 txschq_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC];
/* HW settings, coalescing etc */
u16 rx_chan_base;
u16 tx_chan_base;
u16 rq_skid;
/* MSI-X */
u16 npa_msixoff; /* Offset of NPA vectors */
......@@ -73,6 +76,8 @@ struct otx2_hw {
struct otx2_nic {
void __iomem *reg_base;
struct net_device *netdev;
void *iommu_domain;
u16 rbsize; /* Receive buffer size */
struct otx2_qset qset;
struct otx2_hw hw;
......@@ -84,6 +89,9 @@ struct otx2_nic {
struct workqueue_struct *mbox_wq;
u16 pcifunc; /* RVU PF_FUNC */
/* Block address of NIX either BLKADDR_NIX0 or BLKADDR_NIX1 */
int nix_blkaddr;
};
/* Register read/write APIs */
......@@ -93,7 +101,7 @@ static inline void __iomem *otx2_get_regaddr(struct otx2_nic *nic, u64 offset)
switch ((offset >> RVU_FUNC_BLKADDR_SHIFT) & RVU_FUNC_BLKADDR_MASK) {
case BLKTYPE_NIX:
blkaddr = BLKADDR_NIX0;
blkaddr = nic->nix_blkaddr;
break;
case BLKTYPE_NPA:
blkaddr = BLKADDR_NPA;
......@@ -184,6 +192,72 @@ static inline void otx2_mbox_unlock(struct mbox *mbox)
mutex_unlock(&mbox->lock);
}
/* With the absence of API for 128-bit IO memory access for arm64,
* implement required operations at place.
*/
#if defined(CONFIG_ARM64)
static inline void otx2_write128(u64 lo, u64 hi, void __iomem *addr)
{
__asm__ volatile("stp %x[x0], %x[x1], [%x[p1],#0]!"
::[x0]"r"(lo), [x1]"r"(hi), [p1]"r"(addr));
}
static inline u64 otx2_atomic64_add(u64 incr, u64 *ptr)
{
u64 result;
__asm__ volatile(".cpu generic+lse\n"
"ldadd %x[i], %x[r], [%[b]]"
: [r]"=r"(result), "+m"(*ptr)
: [i]"r"(incr), [b]"r"(ptr)
: "memory");
return result;
}
#else
#define otx2_write128(lo, hi, addr)
#define otx2_atomic64_add(incr, ptr) ({ *ptr += incr; })
#endif
/* Alloc pointer from pool/aura */
static inline u64 otx2_aura_allocptr(struct otx2_nic *pfvf, int aura)
{
u64 *ptr = (u64 *)otx2_get_regaddr(pfvf,
NPA_LF_AURA_OP_ALLOCX(0));
u64 incr = (u64)aura | BIT_ULL(63);
return otx2_atomic64_add(incr, ptr);
}
/* Free pointer to a pool/aura */
static inline void otx2_aura_freeptr(struct otx2_nic *pfvf,
int aura, s64 buf)
{
otx2_write128((u64)buf, (u64)aura | BIT_ULL(63),
otx2_get_regaddr(pfvf, NPA_LF_AURA_OP_FREE0));
}
/* Update page ref count */
static inline void otx2_get_page(struct otx2_pool *pool)
{
if (!pool->page)
return;
if (pool->pageref)
page_ref_add(pool->page, pool->pageref);
pool->pageref = 0;
pool->page = NULL;
}
static inline int otx2_get_pool_idx(struct otx2_nic *pfvf, int type, int idx)
{
if (type == AURA_NIX_SQ)
return pfvf->hw.rqpool_cnt + idx;
/* AURA_NIX_RQ */
return idx;
}
/* Mbox APIs */
static inline int otx2_sync_mbox_msg(struct mbox *mbox)
{
......@@ -263,11 +337,46 @@ MBOX_UP_CGX_MESSAGES
#define RVU_PFVF_FUNC_SHIFT 0
#define RVU_PFVF_FUNC_MASK 0x3FF
static inline dma_addr_t otx2_dma_map_page(struct otx2_nic *pfvf,
struct page *page,
size_t offset, size_t size,
enum dma_data_direction dir)
{
dma_addr_t iova;
iova = dma_map_page_attrs(pfvf->dev, page,
offset, size, dir, DMA_ATTR_SKIP_CPU_SYNC);
if (unlikely(dma_mapping_error(pfvf->dev, iova)))
return (dma_addr_t)NULL;
return iova;
}
static inline void otx2_dma_unmap_page(struct otx2_nic *pfvf,
dma_addr_t addr, size_t size,
enum dma_data_direction dir)
{
dma_unmap_page_attrs(pfvf->dev, addr, size,
dir, DMA_ATTR_SKIP_CPU_SYNC);
}
/* RVU block related APIs */
int otx2_attach_npa_nix(struct otx2_nic *pfvf);
int otx2_detach_resources(struct mbox *mbox);
int otx2_config_npa(struct otx2_nic *pfvf);
int otx2_sq_aura_pool_init(struct otx2_nic *pfvf);
int otx2_rq_aura_pool_init(struct otx2_nic *pfvf);
void otx2_aura_pool_free(struct otx2_nic *pfvf);
void otx2_free_aura_ptr(struct otx2_nic *pfvf, int type);
void otx2_sq_free_sqbs(struct otx2_nic *pfvf);
int otx2_config_nix(struct otx2_nic *pfvf);
int otx2_config_nix_queues(struct otx2_nic *pfvf);
int otx2_txschq_config(struct otx2_nic *pfvf, int lvl);
int otx2_txsch_alloc(struct otx2_nic *pfvf);
int otx2_txschq_stop(struct otx2_nic *pfvf);
void otx2_sqb_flush(struct otx2_nic *pfvf);
dma_addr_t otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
gfp_t gfp);
void otx2_ctx_disable(struct mbox *mbox, int type, bool npa);
/* Mbox handlers */
void mbox_handler_msix_offset(struct otx2_nic *pfvf,
......@@ -276,4 +385,6 @@ void mbox_handler_npa_lf_alloc(struct otx2_nic *pfvf,
struct npa_lf_alloc_rsp *rsp);
void mbox_handler_nix_lf_alloc(struct otx2_nic *pfvf,
struct nix_lf_alloc_rsp *rsp);
void mbox_handler_nix_txsch_alloc(struct otx2_nic *pf,
struct nix_txsch_alloc_rsp *rsp);
#endif /* OTX2_COMMON_H */
......@@ -17,7 +17,10 @@
#include <linux/iommu.h>
#include <net/ip.h>
#include "otx2_reg.h"
#include "otx2_common.h"
#include "otx2_txrx.h"
#include "otx2_struct.h"
#define DRV_NAME "octeontx2-nicpf"
#define DRV_STRING "Marvell OcteonTX2 NIC Physical Function Driver"
......@@ -123,6 +126,10 @@ static void otx2_process_pfaf_mbox_msg(struct otx2_nic *pf,
case MBOX_MSG_NIX_LF_ALLOC:
mbox_handler_nix_lf_alloc(pf, (struct nix_lf_alloc_rsp *)msg);
break;
case MBOX_MSG_NIX_TXSCH_ALLOC:
mbox_handler_nix_txsch_alloc(pf,
(struct nix_txsch_alloc_rsp *)msg);
break;
default:
if (msg->rc)
dev_err(pf->dev,
......@@ -379,26 +386,231 @@ static int otx2_set_real_num_queues(struct net_device *netdev,
return err;
}
static void otx2_free_cq_res(struct otx2_nic *pf)
{
struct otx2_qset *qset = &pf->qset;
struct otx2_cq_queue *cq;
int qidx;
/* Disable CQs */
otx2_ctx_disable(&pf->mbox, NIX_AQ_CTYPE_CQ, false);
for (qidx = 0; qidx < qset->cq_cnt; qidx++) {
cq = &qset->cq[qidx];
qmem_free(pf->dev, cq->cqe);
}
}
static void otx2_free_sq_res(struct otx2_nic *pf)
{
struct otx2_qset *qset = &pf->qset;
struct otx2_snd_queue *sq;
int qidx;
/* Disable SQs */
otx2_ctx_disable(&pf->mbox, NIX_AQ_CTYPE_SQ, false);
/* Free SQB pointers */
otx2_sq_free_sqbs(pf);
for (qidx = 0; qidx < pf->hw.tx_queues; qidx++) {
sq = &qset->sq[qidx];
qmem_free(pf->dev, sq->sqe);
kfree(sq->sqb_ptrs);
}
}
static int otx2_init_hw_resources(struct otx2_nic *pf)
{
struct mbox *mbox = &pf->mbox;
struct otx2_hw *hw = &pf->hw;
struct msg_req *req;
int err = 0, lvl;
/* Set required NPA LF's pool counts
* Auras and Pools are used in a 1:1 mapping,
* so, aura count = pool count.
*/
hw->rqpool_cnt = hw->rx_queues;
hw->sqpool_cnt = hw->tx_queues;
hw->pool_cnt = hw->rqpool_cnt + hw->sqpool_cnt;
/* Get the size of receive buffers to allocate */
pf->rbsize = RCV_FRAG_LEN(pf->netdev->mtu);
otx2_mbox_lock(mbox);
/* NPA init */
err = otx2_config_npa(pf);
if (err)
goto exit;
/* NIX init */
err = otx2_config_nix(pf);
if (err)
goto err_free_npa_lf;
/* Init Auras and pools used by NIX RQ, for free buffer ptrs */
err = otx2_rq_aura_pool_init(pf);
if (err) {
otx2_mbox_unlock(mbox);
goto err_free_nix_lf;
}
/* Init Auras and pools used by NIX SQ, for queueing SQEs */
err = otx2_sq_aura_pool_init(pf);
if (err) {
otx2_mbox_unlock(mbox);
goto err_free_rq_ptrs;
}
err = otx2_txsch_alloc(pf);
if (err) {
otx2_mbox_unlock(mbox);
goto err_free_sq_ptrs;
}
err = otx2_config_nix_queues(pf);
if (err) {
otx2_mbox_unlock(mbox);
goto err_free_txsch;
}
for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
err = otx2_txschq_config(pf, lvl);
if (err) {
otx2_mbox_unlock(mbox);
goto err_free_nix_queues;
}
}
otx2_mbox_unlock(mbox);
return err;
err_free_nix_queues:
otx2_free_sq_res(pf);
otx2_free_cq_res(pf);
otx2_ctx_disable(mbox, NIX_AQ_CTYPE_RQ, false);
err_free_txsch:
if (otx2_txschq_stop(pf))
dev_err(pf->dev, "%s failed to stop TX schedulers\n", __func__);
err_free_sq_ptrs:
otx2_sq_free_sqbs(pf);
err_free_rq_ptrs:
otx2_free_aura_ptr(pf, AURA_NIX_RQ);
otx2_ctx_disable(mbox, NPA_AQ_CTYPE_POOL, true);
otx2_ctx_disable(mbox, NPA_AQ_CTYPE_AURA, true);
otx2_aura_pool_free(pf);
err_free_nix_lf:
otx2_mbox_lock(mbox);
req = otx2_mbox_alloc_msg_nix_lf_free(mbox);
if (req) {
if (otx2_sync_mbox_msg(mbox))
dev_err(pf->dev, "%s failed to free nixlf\n", __func__);
}
err_free_npa_lf:
/* Reset NPA LF */
req = otx2_mbox_alloc_msg_npa_lf_free(mbox);
if (req) {
if (otx2_sync_mbox_msg(mbox))
dev_err(pf->dev, "%s failed to free npalf\n", __func__);
}
exit:
otx2_mbox_unlock(mbox);
return err;
}
static void otx2_free_hw_resources(struct otx2_nic *pf)
{
struct mbox *mbox = &pf->mbox;
struct msg_req *req;
int err;
/* Ensure all SQE are processed */
otx2_sqb_flush(pf);
/* Stop transmission */
err = otx2_txschq_stop(pf);
if (err)
dev_err(pf->dev, "RVUPF: Failed to stop/free TX schedulers\n");
/* Disable RQs */
otx2_ctx_disable(mbox, NIX_AQ_CTYPE_RQ, false);
otx2_free_sq_res(pf);
/* Free RQ buffer pointers*/
otx2_free_aura_ptr(pf, AURA_NIX_RQ);
otx2_free_cq_res(pf);
otx2_mbox_lock(mbox);
/* Reset NIX LF */
req = otx2_mbox_alloc_msg_nix_lf_free(mbox);
if (req) {
if (otx2_sync_mbox_msg(mbox))
dev_err(pf->dev, "%s failed to free nixlf\n", __func__);
}
otx2_mbox_unlock(mbox);
/* Disable NPA Pool and Aura hw context */
otx2_ctx_disable(mbox, NPA_AQ_CTYPE_POOL, true);
otx2_ctx_disable(mbox, NPA_AQ_CTYPE_AURA, true);
otx2_aura_pool_free(pf);
otx2_mbox_lock(mbox);
/* Reset NPA LF */
req = otx2_mbox_alloc_msg_npa_lf_free(mbox);
if (req) {
if (otx2_sync_mbox_msg(mbox))
dev_err(pf->dev, "%s failed to free npalf\n", __func__);
}
otx2_mbox_unlock(mbox);
}
static int otx2_open(struct net_device *netdev)
{
struct otx2_nic *pf = netdev_priv(netdev);
struct otx2_qset *qset = &pf->qset;
int err = 0;
netif_carrier_off(netdev);
pf->qset.cq_cnt = pf->hw.rx_queues + pf->hw.tx_queues;
/* NPA init */
err = otx2_config_npa(pf);
/* CQ size of RQ */
qset->rqe_cnt = qset->rqe_cnt ? qset->rqe_cnt : Q_COUNT(Q_SIZE_256);
/* CQ size of SQ */
qset->sqe_cnt = qset->sqe_cnt ? qset->sqe_cnt : Q_COUNT(Q_SIZE_4K);
err = -ENOMEM;
qset->cq = kcalloc(pf->qset.cq_cnt,
sizeof(struct otx2_cq_queue), GFP_KERNEL);
if (!qset->cq)
goto err_free_mem;
qset->sq = kcalloc(pf->hw.tx_queues,
sizeof(struct otx2_snd_queue), GFP_KERNEL);
if (!qset->sq)
goto err_free_mem;
err = otx2_init_hw_resources(pf);
if (err)
return err;
goto err_free_mem;
/* NIX init */
return otx2_config_nix(pf);
return 0;
err_free_mem:
kfree(qset->sq);
kfree(qset->cq);
return err;
}
static int otx2_stop(struct net_device *netdev)
{
struct otx2_nic *pf = netdev_priv(netdev);
struct otx2_qset *qset = &pf->qset;
otx2_free_hw_resources(pf);
kfree(qset->sq);
kfree(qset->cq);
/* Do not clear RQ/SQ ringsize settings */
memset((void *)qset + offsetof(struct otx2_qset, sqe_cnt), 0,
sizeof(*qset) - offsetof(struct otx2_qset, sqe_cnt));
return 0;
}
......@@ -557,6 +769,19 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (err)
goto err_detach_rsrc;
/* NPA's pool is a stack to which SW frees buffer pointers via Aura.
* HW allocates buffer pointer from stack and uses it for DMA'ing
* ingress packet. In some scenarios HW can free back allocated buffer
* pointers to pool. This makes it impossible for SW to maintain a
* parallel list where physical addresses of buffer pointers (IOVAs)
* given to HW can be saved for later reference.
*
* So the only way to convert Rx packet's buffer address is to use
* IOMMU's iova_to_phys() handler which translates the address by
* walking through the translation tables.
*/
pf->iommu_domain = iommu_get_domain_for_dev(dev);
netdev->netdev_ops = &otx2_netdev_ops;
err = register_netdev(netdev);
......
......@@ -48,4 +48,100 @@
#define RVU_FUNC_BLKADDR_SHIFT 20
#define RVU_FUNC_BLKADDR_MASK 0x1FULL
/* NPA LF registers */
#define NPA_LFBASE (BLKTYPE_NPA << RVU_FUNC_BLKADDR_SHIFT)
#define NPA_LF_AURA_OP_ALLOCX(a) (NPA_LFBASE | 0x10 | (a) << 3)
#define NPA_LF_AURA_OP_FREE0 (NPA_LFBASE | 0x20)
#define NPA_LF_AURA_OP_FREE1 (NPA_LFBASE | 0x28)
#define NPA_LF_AURA_OP_CNT (NPA_LFBASE | 0x30)
#define NPA_LF_AURA_OP_LIMIT (NPA_LFBASE | 0x50)
#define NPA_LF_AURA_OP_INT (NPA_LFBASE | 0x60)
#define NPA_LF_AURA_OP_THRESH (NPA_LFBASE | 0x70)
#define NPA_LF_POOL_OP_PC (NPA_LFBASE | 0x100)
#define NPA_LF_POOL_OP_AVAILABLE (NPA_LFBASE | 0x110)
#define NPA_LF_POOL_OP_PTR_START0 (NPA_LFBASE | 0x120)
#define NPA_LF_POOL_OP_PTR_START1 (NPA_LFBASE | 0x128)
#define NPA_LF_POOL_OP_PTR_END0 (NPA_LFBASE | 0x130)
#define NPA_LF_POOL_OP_PTR_END1 (NPA_LFBASE | 0x138)
#define NPA_LF_POOL_OP_INT (NPA_LFBASE | 0x160)
#define NPA_LF_POOL_OP_THRESH (NPA_LFBASE | 0x170)
#define NPA_LF_ERR_INT (NPA_LFBASE | 0x200)
#define NPA_LF_ERR_INT_W1S (NPA_LFBASE | 0x208)
#define NPA_LF_ERR_INT_ENA_W1C (NPA_LFBASE | 0x210)
#define NPA_LF_ERR_INT_ENA_W1S (NPA_LFBASE | 0x218)
#define NPA_LF_RAS (NPA_LFBASE | 0x220)
#define NPA_LF_RAS_W1S (NPA_LFBASE | 0x228)
#define NPA_LF_RAS_ENA_W1C (NPA_LFBASE | 0x230)
#define NPA_LF_RAS_ENA_W1S (NPA_LFBASE | 0x238)
#define NPA_LF_QINTX_CNT(a) (NPA_LFBASE | 0x300 | (a) << 12)
#define NPA_LF_QINTX_INT(a) (NPA_LFBASE | 0x310 | (a) << 12)
#define NPA_LF_QINTX_INT_W1S(a) (NPA_LFBASE | 0x318 | (a) << 12)
#define NPA_LF_QINTX_ENA_W1S(a) (NPA_LFBASE | 0x320 | (a) << 12)
#define NPA_LF_QINTX_ENA_W1C(a) (NPA_LFBASE | 0x330 | (a) << 12)
/* NIX LF registers */
#define NIX_LFBASE (BLKTYPE_NIX << RVU_FUNC_BLKADDR_SHIFT)
#define NIX_LF_RX_SECRETX(a) (NIX_LFBASE | 0x0 | (a) << 3)
#define NIX_LF_CFG (NIX_LFBASE | 0x100)
#define NIX_LF_GINT (NIX_LFBASE | 0x200)
#define NIX_LF_GINT_W1S (NIX_LFBASE | 0x208)
#define NIX_LF_GINT_ENA_W1C (NIX_LFBASE | 0x210)
#define NIX_LF_GINT_ENA_W1S (NIX_LFBASE | 0x218)
#define NIX_LF_ERR_INT (NIX_LFBASE | 0x220)
#define NIX_LF_ERR_INT_W1S (NIX_LFBASE | 0x228)
#define NIX_LF_ERR_INT_ENA_W1C (NIX_LFBASE | 0x230)
#define NIX_LF_ERR_INT_ENA_W1S (NIX_LFBASE | 0x238)
#define NIX_LF_RAS (NIX_LFBASE | 0x240)
#define NIX_LF_RAS_W1S (NIX_LFBASE | 0x248)
#define NIX_LF_RAS_ENA_W1C (NIX_LFBASE | 0x250)
#define NIX_LF_RAS_ENA_W1S (NIX_LFBASE | 0x258)
#define NIX_LF_SQ_OP_ERR_DBG (NIX_LFBASE | 0x260)
#define NIX_LF_MNQ_ERR_DBG (NIX_LFBASE | 0x270)
#define NIX_LF_SEND_ERR_DBG (NIX_LFBASE | 0x280)
#define NIX_LF_TX_STATX(a) (NIX_LFBASE | 0x300 | (a) << 3)
#define NIX_LF_RX_STATX(a) (NIX_LFBASE | 0x400 | (a) << 3)
#define NIX_LF_OP_SENDX(a) (NIX_LFBASE | 0x800 | (a) << 3)
#define NIX_LF_RQ_OP_INT (NIX_LFBASE | 0x900)
#define NIX_LF_RQ_OP_OCTS (NIX_LFBASE | 0x910)
#define NIX_LF_RQ_OP_PKTS (NIX_LFBASE | 0x920)
#define NIX_LF_OP_IPSEC_DYNO_CN (NIX_LFBASE | 0x980)
#define NIX_LF_SQ_OP_INT (NIX_LFBASE | 0xa00)
#define NIX_LF_SQ_OP_OCTS (NIX_LFBASE | 0xa10)
#define NIX_LF_SQ_OP_PKTS (NIX_LFBASE | 0xa20)
#define NIX_LF_SQ_OP_STATUS (NIX_LFBASE | 0xa30)
#define NIX_LF_CQ_OP_INT (NIX_LFBASE | 0xb00)
#define NIX_LF_CQ_OP_DOOR (NIX_LFBASE | 0xb30)
#define NIX_LF_CQ_OP_STATUS (NIX_LFBASE | 0xb40)
#define NIX_LF_QINTX_CNT(a) (NIX_LFBASE | 0xC00 | (a) << 12)
#define NIX_LF_QINTX_INT(a) (NIX_LFBASE | 0xC10 | (a) << 12)
#define NIX_LF_QINTX_INT_W1S(a) (NIX_LFBASE | 0xC18 | (a) << 12)
#define NIX_LF_QINTX_ENA_W1S(a) (NIX_LFBASE | 0xC20 | (a) << 12)
#define NIX_LF_QINTX_ENA_W1C(a) (NIX_LFBASE | 0xC30 | (a) << 12)
#define NIX_LF_CINTX_CNT(a) (NIX_LFBASE | 0xD00 | (a) << 12)
#define NIX_LF_CINTX_WAIT(a) (NIX_LFBASE | 0xD10 | (a) << 12)
#define NIX_LF_CINTX_INT(a) (NIX_LFBASE | 0xD20 | (a) << 12)
#define NIX_LF_CINTX_INT_W1S(a) (NIX_LFBASE | 0xD30 | (a) << 12)
#define NIX_LF_CINTX_ENA_W1S(a) (NIX_LFBASE | 0xD40 | (a) << 12)
#define NIX_LF_CINTX_ENA_W1C(a) (NIX_LFBASE | 0xD50 | (a) << 12)
/* NIX AF transmit scheduler registers */
#define NIX_AF_SMQX_CFG(a) (0x700 | (a) << 16)
#define NIX_AF_TL1X_SCHEDULE(a) (0xC00 | (a) << 16)
#define NIX_AF_TL1X_CIR(a) (0xC20 | (a) << 16)
#define NIX_AF_TL1X_TOPOLOGY(a) (0xC80 | (a) << 16)
#define NIX_AF_TL2X_PARENT(a) (0xE88 | (a) << 16)
#define NIX_AF_TL2X_SCHEDULE(a) (0xE00 | (a) << 16)
#define NIX_AF_TL3X_PARENT(a) (0x1088 | (a) << 16)
#define NIX_AF_TL3X_SCHEDULE(a) (0x1000 | (a) << 16)
#define NIX_AF_TL4X_PARENT(a) (0x1288 | (a) << 16)
#define NIX_AF_TL4X_SCHEDULE(a) (0x1200 | (a) << 16)
#define NIX_AF_MDQX_SCHEDULE(a) (0x1400 | (a) << 16)
#define NIX_AF_MDQX_PARENT(a) (0x1480 | (a) << 16)
#define NIX_AF_TL3_TL2X_LINKX_CFG(a, b) (0x1700 | (a) << 16 | (b) << 3)
/* LMT LF registers */
#define LMT_LFBASE BIT_ULL(RVU_FUNC_BLKADDR_SHIFT)
#define LMT_LF_LMTLINEX(a) (LMT_LFBASE | 0x000 | (a) << 12)
#define LMT_LF_LMTCANCEL (LMT_LFBASE | 0x400)
#endif /* OTX2_REG_H */
......@@ -17,4 +17,15 @@ enum nix_cqesz_e {
NIX_XQESZ_W16 = 0x1,
};
enum nix_sqes_e {
NIX_SQESZ_W16 = 0x0,
NIX_SQESZ_W8 = 0x1,
};
enum nix_send_ldtype {
NIX_SEND_LDTYPE_LDD = 0x0,
NIX_SEND_LDTYPE_LDT = 0x1,
NIX_SEND_LDTYPE_LDWB = 0x2,
};
#endif /* OTX2_STRUCT_H */
/* SPDX-License-Identifier: GPL-2.0 */
/* Marvell OcteonTx2 RVU Ethernet driver
*
* Copyright (C) 2020 Marvell International Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef OTX2_TXRX_H
#define OTX2_TXRX_H
#include <linux/etherdevice.h>
#include <linux/iommu.h>
#include <linux/if_vlan.h>
#define LBK_CHAN_BASE 0x000
#define SDP_CHAN_BASE 0x700
#define CGX_CHAN_BASE 0x800
#define OTX2_DATA_ALIGN(X) ALIGN(X, OTX2_ALIGN)
#define OTX2_HEAD_ROOM OTX2_ALIGN
/* Rx buffer size should be in multiples of 128bytes */
#define RCV_FRAG_LEN1(x) \
((OTX2_HEAD_ROOM + OTX2_DATA_ALIGN(x)) + \
OTX2_DATA_ALIGN(sizeof(struct skb_shared_info)))
/* Prefer 2048 byte buffers for better last level cache
* utilization or data distribution across regions.
*/
#define RCV_FRAG_LEN(x) \
((RCV_FRAG_LEN1(x) < 2048) ? 2048 : RCV_FRAG_LEN1(x))
#define DMA_BUFFER_LEN(x) \
((x) - OTX2_HEAD_ROOM - \
OTX2_DATA_ALIGN(sizeof(struct skb_shared_info)))
struct otx2_snd_queue {
u8 aura_id;
u16 sqe_size;
u32 sqe_cnt;
u16 num_sqbs;
u8 sqe_per_sqb;
u64 io_addr;
u64 *aura_fc_addr;
u64 *lmt_addr;
void *sqe_base;
struct qmem *sqe;
u16 sqb_count;
u64 *sqb_ptrs;
} ____cacheline_aligned_in_smp;
struct otx2_pool {
struct qmem *stack;
struct qmem *fc_addr;
u8 rbpage_order;
u16 rbsize;
u32 page_offset;
u16 pageref;
struct page *page;
};
enum cq_type {
CQ_RX,
CQ_TX,
CQS_PER_CINT = 2, /* RQ + SQ */
};
struct otx2_cq_queue {
u8 cq_idx;
u8 cq_type;
u16 cqe_size;
u16 pool_ptrs;
u32 cqe_cnt;
void *cqe_base;
struct qmem *cqe;
struct otx2_pool *rbpool;
} ____cacheline_aligned_in_smp;
struct otx2_qset {
u32 rqe_cnt;
u32 sqe_cnt; /* Keep these two at top */
#define OTX2_MAX_CQ_CNT 64
u16 cq_cnt;
u16 xqe_size;
struct otx2_pool *pool;
struct otx2_cq_queue *cq;
struct otx2_snd_queue *sq;
};
/* Translate IOVA to physical address */
static inline u64 otx2_iova_to_phys(void *iommu_domain, dma_addr_t dma_addr)
{
/* Translation is installed only when IOMMU is present */
if (likely(iommu_domain))
return iommu_iova_to_phys(iommu_domain, dma_addr);
return dma_addr;
}
#endif /* OTX2_TXRX_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment