Skip to content

Commit

Permalink
octeontx2-pf: Add packet transmission support
Browse files Browse the repository at this point in the history
This patch adds the packet transmission support.
For a given skb prepares send queue descriptors (SQEs) and pushes them
to HW. Here driver doesn't maintain it's own SQ rings, SQEs are pushed
to HW using a silicon specific operations called LMTST. From the
instuction HW derives the transmit queue number and queues the SQE to
that queue. These LMTST instructions are designed to avoid queue
maintenance in SW and lockless behavior ie when multiple cores are trying
to add SQEs to same queue then HW will takecare of serialization, no need
for SW to hold locks.

Also supports scatter/gather.

Co-developed-by: Geetha sowjanya <gakula@marvell.com>
Signed-off-by: Geetha sowjanya <gakula@marvell.com>
Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Sunil Goutham authored and David S. Miller committed Jan 27, 2020
1 parent abe0254 commit 3ca6c4c
Showing 6 changed files with 470 additions and 2 deletions.
7 changes: 7 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
Original file line number Diff line number Diff line change
@@ -287,9 +287,15 @@ static int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura)
return err;

sq->sqe_base = sq->sqe->base;
sq->sg = kcalloc(qset->sqe_cnt, sizeof(struct sg_list), GFP_KERNEL);
if (!sq->sg)
return -ENOMEM;

sq->head = 0;
sq->sqe_per_sqb = (pfvf->hw.sqb_size / sq->sqe_size) - 1;
sq->num_sqbs = (qset->sqe_cnt + sq->sqe_per_sqb) / sq->sqe_per_sqb;
/* Set SQE threshold to 10% of total SQEs */
sq->sqe_thresh = ((sq->num_sqbs * sq->sqe_per_sqb) * 10) / 100;
sq->aura_id = sqb_aura;
sq->aura_fc_addr = pool->fc_addr->base;
sq->lmt_addr = (__force u64 *)(pfvf->reg_base + LMT_LF_LMTLINEX(qidx));
@@ -338,6 +344,7 @@ static int otx2_cq_init(struct otx2_nic *pfvf, u16 qidx)
cq->cqe_cnt = qset->rqe_cnt;
} else {
cq->cq_type = CQ_TX;
cq->cint_idx = qidx - pfvf->hw.rx_queues;
cq->cqe_cnt = qset->sqe_cnt;
}
cq->cqe_size = pfvf->qset.xqe_size;
13 changes: 13 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
Original file line number Diff line number Diff line change
@@ -300,9 +300,21 @@ static inline u64 otx2_atomic64_add(u64 incr, u64 *ptr)
return result;
}

static inline u64 otx2_lmt_flush(uint64_t addr)
{
u64 result = 0;

__asm__ volatile(".cpu generic+lse\n"
"ldeor xzr,%x[rf],[%[rs]]"
: [rf]"=r"(result)
: [rs]"r"(addr));
return result;
}

#else
#define otx2_write128(lo, hi, addr)
#define otx2_atomic64_add(incr, ptr) ({ *ptr += incr; })
#define otx2_lmt_flush(addr) ({ 0; })
#endif

/* Alloc pointer from pool/aura */
@@ -475,6 +487,7 @@ 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);
void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq);
void otx2_cleanup_tx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq);

/* Mbox handlers */
void mbox_handler_msix_offset(struct otx2_nic *pfvf,
38 changes: 37 additions & 1 deletion drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
Original file line number Diff line number Diff line change
@@ -445,6 +445,7 @@ static void otx2_free_sq_res(struct otx2_nic *pf)
for (qidx = 0; qidx < pf->hw.tx_queues; qidx++) {
sq = &qset->sq[qidx];
qmem_free(pf->dev, sq->sqe);
kfree(sq->sg);
kfree(sq->sqb_ptrs);
}
}
@@ -569,6 +570,8 @@ static void otx2_free_hw_resources(struct otx2_nic *pf)
cq = &qset->cq[qidx];
if (cq->cq_type == CQ_RX)
otx2_cleanup_rx_cqes(pf, cq);
else
otx2_cleanup_tx_cqes(pf, cq);
}

otx2_free_sq_res(pf);
@@ -741,9 +744,41 @@ static int otx2_stop(struct net_device *netdev)
return 0;
}

static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev)
{
struct otx2_nic *pf = netdev_priv(netdev);
int qidx = skb_get_queue_mapping(skb);
struct otx2_snd_queue *sq;
struct netdev_queue *txq;

/* Check for minimum packet length */
if (skb->len <= ETH_HLEN) {
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}

sq = &pf->qset.sq[qidx];
txq = netdev_get_tx_queue(netdev, qidx);

if (!otx2_sq_append_skb(netdev, sq, skb, qidx)) {
netif_tx_stop_queue(txq);

/* Check again, incase SQBs got freed up */
smp_mb();
if (((sq->num_sqbs - *sq->aura_fc_addr) * sq->sqe_per_sqb)
> sq->sqe_thresh)
netif_tx_wake_queue(txq);

return NETDEV_TX_BUSY;
}

return NETDEV_TX_OK;
}

static const struct net_device_ops otx2_netdev_ops = {
.ndo_open = otx2_open,
.ndo_stop = otx2_stop,
.ndo_start_xmit = otx2_xmit,
};

static int otx2_check_pf_usable(struct otx2_nic *nic)
@@ -910,7 +945,8 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
*/
pf->iommu_domain = iommu_get_domain_for_dev(dev);

netdev->hw_features = NETIF_F_RXCSUM;
netdev->hw_features = (NETIF_F_RXCSUM | NETIF_F_IP_CSUM |
NETIF_F_IPV6_CSUM | NETIF_F_SG);
netdev->features |= netdev->hw_features;

netdev->hw_features |= NETIF_F_RXALL;
109 changes: 109 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/nic/otx2_struct.h
Original file line number Diff line number Diff line change
@@ -28,6 +28,21 @@ enum nix_send_ldtype {
NIX_SEND_LDTYPE_LDWB = 0x2,
};

/* CSUM offload */
enum nix_sendl3type {
NIX_SENDL3TYPE_NONE = 0x0,
NIX_SENDL3TYPE_IP4 = 0x2,
NIX_SENDL3TYPE_IP4_CKSUM = 0x3,
NIX_SENDL3TYPE_IP6 = 0x4,
};

enum nix_sendl4type {
NIX_SENDL4TYPE_NONE,
NIX_SENDL4TYPE_TCP_CKSUM,
NIX_SENDL4TYPE_SCTP_CKSUM,
NIX_SENDL4TYPE_UDP_CKSUM,
};

/* NIX wqe/cqe types */
enum nix_xqe_type {
NIX_XQE_TYPE_INVALID = 0x0,
@@ -51,6 +66,20 @@ enum nix_subdc {
NIX_SUBDC_SOD = 0xf,
};

/* Algorithm for nix_sqe_mem_s header (value of the `alg` field) */
enum nix_sendmemalg {
NIX_SENDMEMALG_E_SET = 0x0,
NIX_SENDMEMALG_E_SETTSTMP = 0x1,
NIX_SENDMEMALG_E_SETRSLT = 0x2,
NIX_SENDMEMALG_E_ADD = 0x8,
NIX_SENDMEMALG_E_SUB = 0x9,
NIX_SENDMEMALG_E_ADDLEN = 0xa,
NIX_SENDMEMALG_E_SUBLEN = 0xb,
NIX_SENDMEMALG_E_ADDMBUF = 0xc,
NIX_SENDMEMALG_E_SUBMBUF = 0xd,
NIX_SENDMEMALG_E_ENUM_LAST = 0xe,
};

/* NIX CQE header structure */
struct nix_cqe_hdr_s {
u64 flow_tag : 32;
@@ -130,10 +159,90 @@ struct nix_rx_sg_s {
u64 seg3_addr;
};

struct nix_send_comp_s {
u64 status : 8;
u64 sqe_id : 16;
u64 rsvd_24_63 : 40;
};

struct nix_cqe_rx_s {
struct nix_cqe_hdr_s hdr;
struct nix_rx_parse_s parse;
struct nix_rx_sg_s sg;
};

struct nix_cqe_tx_s {
struct nix_cqe_hdr_s hdr;
struct nix_send_comp_s comp;
};

/* NIX SQE header structure */
struct nix_sqe_hdr_s {
u64 total : 18; /* W0 */
u64 reserved_18 : 1;
u64 df : 1;
u64 aura : 20;
u64 sizem1 : 3;
u64 pnc : 1;
u64 sq : 20;
u64 ol3ptr : 8; /* W1 */
u64 ol4ptr : 8;
u64 il3ptr : 8;
u64 il4ptr : 8;
u64 ol3type : 4;
u64 ol4type : 4;
u64 il3type : 4;
u64 il4type : 4;
u64 sqe_id : 16;

};

/* NIX send extended header subdescriptor structure */
struct nix_sqe_ext_s {
u64 lso_mps : 14; /* W0 */
u64 lso : 1;
u64 tstmp : 1;
u64 lso_sb : 8;
u64 lso_format : 5;
u64 rsvd_31_29 : 3;
u64 shp_chg : 9;
u64 shp_dis : 1;
u64 shp_ra : 2;
u64 markptr : 8;
u64 markform : 7;
u64 mark_en : 1;
u64 subdc : 4;
u64 vlan0_ins_ptr : 8; /* W1 */
u64 vlan0_ins_tci : 16;
u64 vlan1_ins_ptr : 8;
u64 vlan1_ins_tci : 16;
u64 vlan0_ins_ena : 1;
u64 vlan1_ins_ena : 1;
u64 rsvd_127_114 : 14;
};

struct nix_sqe_sg_s {
u64 seg1_size : 16;
u64 seg2_size : 16;
u64 seg3_size : 16;
u64 segs : 2;
u64 rsvd_54_50 : 5;
u64 i1 : 1;
u64 i2 : 1;
u64 i3 : 1;
u64 ld_type : 2;
u64 subdc : 4;
};

/* NIX send memory subdescriptor structure */
struct nix_sqe_mem_s {
u64 offset : 16; /* W0 */
u64 rsvd_52_16 : 37;
u64 wmem : 1;
u64 dsz : 2;
u64 alg : 4;
u64 subdc : 4;
u64 addr; /* W1 */
};

#endif /* OTX2_STRUCT_H */
Loading

0 comments on commit 3ca6c4c

Please sign in to comment.