forked from Qortal/Brooklyn
182 lines
4.8 KiB
C
182 lines
4.8 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/* Marvell OcteonTx2 RVU Physcial Function ethernet driver
|
|
*
|
|
* Copyright (C) 2020 Marvell.
|
|
*/
|
|
|
|
#include "cn10k.h"
|
|
#include "otx2_reg.h"
|
|
#include "otx2_struct.h"
|
|
|
|
static struct dev_hw_ops otx2_hw_ops = {
|
|
.sq_aq_init = otx2_sq_aq_init,
|
|
.sqe_flush = otx2_sqe_flush,
|
|
.aura_freeptr = otx2_aura_freeptr,
|
|
.refill_pool_ptrs = otx2_refill_pool_ptrs,
|
|
};
|
|
|
|
static struct dev_hw_ops cn10k_hw_ops = {
|
|
.sq_aq_init = cn10k_sq_aq_init,
|
|
.sqe_flush = cn10k_sqe_flush,
|
|
.aura_freeptr = cn10k_aura_freeptr,
|
|
.refill_pool_ptrs = cn10k_refill_pool_ptrs,
|
|
};
|
|
|
|
int cn10k_pf_lmtst_init(struct otx2_nic *pf)
|
|
{
|
|
int size, num_lines;
|
|
u64 base;
|
|
|
|
if (!test_bit(CN10K_LMTST, &pf->hw.cap_flag)) {
|
|
pf->hw_ops = &otx2_hw_ops;
|
|
return 0;
|
|
}
|
|
|
|
pf->hw_ops = &cn10k_hw_ops;
|
|
base = pci_resource_start(pf->pdev, PCI_MBOX_BAR_NUM) +
|
|
(MBOX_SIZE * (pf->total_vfs + 1));
|
|
|
|
size = pci_resource_len(pf->pdev, PCI_MBOX_BAR_NUM) -
|
|
(MBOX_SIZE * (pf->total_vfs + 1));
|
|
|
|
pf->hw.lmt_base = ioremap(base, size);
|
|
|
|
if (!pf->hw.lmt_base) {
|
|
dev_err(pf->dev, "Unable to map PF LMTST region\n");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
/* FIXME: Get the num of LMTST lines from LMT table */
|
|
pf->tot_lmt_lines = size / LMT_LINE_SIZE;
|
|
num_lines = (pf->tot_lmt_lines - NIX_LMTID_BASE) /
|
|
pf->hw.tx_queues;
|
|
/* Number of LMT lines per SQ queues */
|
|
pf->nix_lmt_lines = num_lines > 32 ? 32 : num_lines;
|
|
|
|
pf->nix_lmt_size = pf->nix_lmt_lines * LMT_LINE_SIZE;
|
|
return 0;
|
|
}
|
|
|
|
int cn10k_vf_lmtst_init(struct otx2_nic *vf)
|
|
{
|
|
int size, num_lines;
|
|
|
|
if (!test_bit(CN10K_LMTST, &vf->hw.cap_flag)) {
|
|
vf->hw_ops = &otx2_hw_ops;
|
|
return 0;
|
|
}
|
|
|
|
vf->hw_ops = &cn10k_hw_ops;
|
|
size = pci_resource_len(vf->pdev, PCI_MBOX_BAR_NUM);
|
|
vf->hw.lmt_base = ioremap_wc(pci_resource_start(vf->pdev,
|
|
PCI_MBOX_BAR_NUM),
|
|
size);
|
|
if (!vf->hw.lmt_base) {
|
|
dev_err(vf->dev, "Unable to map VF LMTST region\n");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
vf->tot_lmt_lines = size / LMT_LINE_SIZE;
|
|
/* LMTST lines per SQ */
|
|
num_lines = (vf->tot_lmt_lines - NIX_LMTID_BASE) /
|
|
vf->hw.tx_queues;
|
|
vf->nix_lmt_lines = num_lines > 32 ? 32 : num_lines;
|
|
vf->nix_lmt_size = vf->nix_lmt_lines * LMT_LINE_SIZE;
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(cn10k_vf_lmtst_init);
|
|
|
|
int cn10k_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura)
|
|
{
|
|
struct nix_cn10k_aq_enq_req *aq;
|
|
struct otx2_nic *pfvf = dev;
|
|
struct otx2_snd_queue *sq;
|
|
|
|
sq = &pfvf->qset.sq[qidx];
|
|
sq->lmt_addr = (__force u64 *)((u64)pfvf->hw.nix_lmt_base +
|
|
(qidx * pfvf->nix_lmt_size));
|
|
|
|
/* Get memory to put this msg */
|
|
aq = otx2_mbox_alloc_msg_nix_cn10k_aq_enq(&pfvf->mbox);
|
|
if (!aq)
|
|
return -ENOMEM;
|
|
|
|
aq->sq.cq = pfvf->hw.rx_queues + qidx;
|
|
aq->sq.max_sqe_size = NIX_MAXSQESZ_W16; /* 128 byte */
|
|
aq->sq.cq_ena = 1;
|
|
aq->sq.ena = 1;
|
|
/* Only one SMQ is allocated, map all SQ's to that SMQ */
|
|
aq->sq.smq = pfvf->hw.txschq_list[NIX_TXSCH_LVL_SMQ][0];
|
|
/* FIXME: set based on NIX_AF_DWRR_RPM_MTU*/
|
|
aq->sq.smq_rr_weight = pfvf->netdev->mtu;
|
|
aq->sq.default_chan = pfvf->hw.tx_chan_base;
|
|
aq->sq.sqe_stype = NIX_STYPE_STF; /* Cache SQB */
|
|
aq->sq.sqb_aura = sqb_aura;
|
|
aq->sq.sq_int_ena = NIX_SQINT_BITS;
|
|
aq->sq.qint_idx = 0;
|
|
/* Due pipelining impact minimum 2000 unused SQ CQE's
|
|
* need to maintain to avoid CQ overflow.
|
|
*/
|
|
aq->sq.cq_limit = ((SEND_CQ_SKID * 256) / (pfvf->qset.sqe_cnt));
|
|
|
|
/* Fill AQ info */
|
|
aq->qidx = qidx;
|
|
aq->ctype = NIX_AQ_CTYPE_SQ;
|
|
aq->op = NIX_AQ_INSTOP_INIT;
|
|
|
|
return otx2_sync_mbox_msg(&pfvf->mbox);
|
|
}
|
|
|
|
#define NPA_MAX_BURST 16
|
|
void cn10k_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq)
|
|
{
|
|
struct otx2_nic *pfvf = dev;
|
|
u64 ptrs[NPA_MAX_BURST];
|
|
int num_ptrs = 1;
|
|
dma_addr_t bufptr;
|
|
|
|
/* Refill pool with new buffers */
|
|
while (cq->pool_ptrs) {
|
|
if (otx2_alloc_buffer(pfvf, cq, &bufptr)) {
|
|
if (num_ptrs--)
|
|
__cn10k_aura_freeptr(pfvf, cq->cq_idx, ptrs,
|
|
num_ptrs,
|
|
cq->rbpool->lmt_addr);
|
|
break;
|
|
}
|
|
cq->pool_ptrs--;
|
|
ptrs[num_ptrs] = (u64)bufptr + OTX2_HEAD_ROOM;
|
|
num_ptrs++;
|
|
if (num_ptrs == NPA_MAX_BURST || cq->pool_ptrs == 0) {
|
|
__cn10k_aura_freeptr(pfvf, cq->cq_idx, ptrs,
|
|
num_ptrs,
|
|
cq->rbpool->lmt_addr);
|
|
num_ptrs = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
void cn10k_sqe_flush(void *dev, struct otx2_snd_queue *sq, int size, int qidx)
|
|
{
|
|
struct otx2_nic *pfvf = dev;
|
|
int lmt_id = NIX_LMTID_BASE + (qidx * pfvf->nix_lmt_lines);
|
|
u64 val = 0, tar_addr = 0;
|
|
|
|
/* FIXME: val[0:10] LMT_ID.
|
|
* [12:15] no of LMTST - 1 in the burst.
|
|
* [19:63] data size of each LMTST in the burst except first.
|
|
*/
|
|
val = (lmt_id & 0x7FF);
|
|
/* Target address for LMTST flush tells HW how many 128bit
|
|
* words are present.
|
|
* tar_addr[6:4] size of first LMTST - 1 in units of 128b.
|
|
*/
|
|
tar_addr |= sq->io_addr | (((size / 16) - 1) & 0x7) << 4;
|
|
dma_wmb();
|
|
memcpy(sq->lmt_addr, sq->sqe_base, size);
|
|
cn10k_lmt_flush(val, tar_addr);
|
|
|
|
sq->head++;
|
|
sq->head &= (sq->sqe_cnt - 1);
|
|
}
|