Commit ab58a416 authored by Hariprasad Kelam's avatar Hariprasad Kelam Committed by David S. Miller

octeontx2-pf: cn10k: Get max mtu supported from admin function

CN10K supports max MTU of 16K on LMAC links and 64k on LBK
links and Octeontx2 silicon supports 9K mtu on both links.
Get the same from nix_get_hw_info mbox message in netdev probe.

This patch also calculates receive buffer size required based
on the MTU set.
Signed-off-by: default avatarHariprasad Kelam <hkelam@marvell.com>
Signed-off-by: default avatarSubbaraya Sundeep <sbhatta@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 6e54e1c5
......@@ -108,7 +108,7 @@ int cn10k_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura)
/* 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 = OTX2_MAX_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;
......
......@@ -230,7 +230,6 @@ int otx2_hw_set_mtu(struct otx2_nic *pfvf, int mtu)
return -ENOMEM;
}
pfvf->max_frs = mtu + OTX2_ETH_HLEN;
req->maxlen = pfvf->max_frs;
err = otx2_sync_mbox_msg(&pfvf->mbox);
......@@ -606,8 +605,8 @@ int otx2_txschq_config(struct otx2_nic *pfvf, int lvl)
/* Set topology e.t.c configuration */
if (lvl == NIX_TXSCH_LVL_SMQ) {
req->reg[0] = NIX_AF_SMQX_CFG(schq);
req->regval[0] = ((OTX2_MAX_MTU + OTX2_ETH_HLEN) << 8) |
OTX2_MIN_MTU;
req->regval[0] = ((pfvf->netdev->max_mtu + OTX2_ETH_HLEN) << 8)
| OTX2_MIN_MTU;
req->regval[0] |= (0x20ULL << 51) | (0x80ULL << 39) |
(0x2ULL << 36);
......@@ -1637,6 +1636,46 @@ void otx2_set_cints_affinity(struct otx2_nic *pfvf)
}
}
u16 otx2_get_max_mtu(struct otx2_nic *pfvf)
{
struct nix_hw_info *rsp;
struct msg_req *req;
u16 max_mtu;
int rc;
mutex_lock(&pfvf->mbox.lock);
req = otx2_mbox_alloc_msg_nix_get_hw_info(&pfvf->mbox);
if (!req) {
rc = -ENOMEM;
goto out;
}
rc = otx2_sync_mbox_msg(&pfvf->mbox);
if (!rc) {
rsp = (struct nix_hw_info *)
otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr);
/* HW counts VLAN insertion bytes (8 for double tag)
* irrespective of whether SQE is requesting to insert VLAN
* in the packet or not. Hence these 8 bytes have to be
* discounted from max packet size otherwise HW will throw
* SMQ errors
*/
max_mtu = rsp->max_mtu - 8 - OTX2_ETH_HLEN;
}
out:
mutex_unlock(&pfvf->mbox.lock);
if (rc) {
dev_warn(pfvf->dev,
"Failed to get MTU from hardware setting default value(1500)\n");
max_mtu = 1500;
}
return max_mtu;
}
EXPORT_SYMBOL(otx2_get_max_mtu);
#define M(_name, _id, _fn_name, _req_type, _rsp_type) \
int __weak \
otx2_mbox_up_handler_ ## _fn_name(struct otx2_nic *pfvf, \
......
......@@ -798,5 +798,5 @@ int otx2_del_macfilter(struct net_device *netdev, const u8 *mac);
int otx2_add_macfilter(struct net_device *netdev, const u8 *mac);
int otx2_enable_rxvlan(struct otx2_nic *pf, bool enable);
int otx2_install_rxvlan_offload_flow(struct otx2_nic *pfvf);
u16 otx2_get_max_mtu(struct otx2_nic *pfvf);
#endif /* OTX2_COMMON_H */
......@@ -1288,6 +1288,33 @@ static void otx2_free_sq_res(struct otx2_nic *pf)
}
}
static int otx2_get_rbuf_size(struct otx2_nic *pf, int mtu)
{
int frame_size;
int total_size;
int rbuf_size;
/* The data transferred by NIX to memory consists of actual packet
* plus additional data which has timestamp and/or EDSA/HIGIG2
* headers if interface is configured in corresponding modes.
* NIX transfers entire data using 6 segments/buffers and writes
* a CQE_RX descriptor with those segment addresses. First segment
* has additional data prepended to packet. Also software omits a
* headroom of 128 bytes and sizeof(struct skb_shared_info) in
* each segment. Hence the total size of memory needed
* to receive a packet with 'mtu' is:
* frame size = mtu + additional data;
* memory = frame_size + (headroom + struct skb_shared_info size) * 6;
* each receive buffer size = memory / 6;
*/
frame_size = mtu + OTX2_ETH_HLEN + OTX2_HW_TIMESTAMP_LEN;
total_size = frame_size + (OTX2_HEAD_ROOM +
OTX2_DATA_ALIGN(sizeof(struct skb_shared_info))) * 6;
rbuf_size = total_size / 6;
return ALIGN(rbuf_size, 2048);
}
static int otx2_init_hw_resources(struct otx2_nic *pf)
{
struct nix_lf_free_req *free_req;
......@@ -1304,9 +1331,9 @@ static int otx2_init_hw_resources(struct otx2_nic *pf)
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(OTX2_HW_TIMESTAMP_LEN + pf->netdev->mtu +
OTX2_ETH_HLEN);
pf->max_frs = pf->netdev->mtu + OTX2_ETH_HLEN + OTX2_HW_TIMESTAMP_LEN;
pf->rbsize = otx2_get_rbuf_size(pf, pf->netdev->mtu);
mutex_lock(&mbox->lock);
/* NPA init */
......@@ -2429,7 +2456,7 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* MTU range: 64 - 9190 */
netdev->min_mtu = OTX2_MIN_MTU;
netdev->max_mtu = OTX2_MAX_MTU;
netdev->max_mtu = otx2_get_max_mtu(pf);
err = register_netdev(netdev);
if (err) {
......
......@@ -257,12 +257,11 @@ static bool otx2_check_rcv_errors(struct otx2_nic *pfvf,
/* For now ignore all the NPC parser errors and
* pass the packets to stack.
*/
if (cqe->sg.segs == 1)
return false;
return false;
}
/* If RXALL is enabled pass on packets to stack. */
if (cqe->sg.segs == 1 && (pfvf->netdev->features & NETIF_F_RXALL))
if (pfvf->netdev->features & NETIF_F_RXALL)
return false;
/* Free buffer back to pool */
......@@ -277,9 +276,14 @@ static void otx2_rcv_pkt_handler(struct otx2_nic *pfvf,
struct nix_cqe_rx_s *cqe)
{
struct nix_rx_parse_s *parse = &cqe->parse;
struct nix_rx_sg_s *sg = &cqe->sg;
struct sk_buff *skb = NULL;
void *end, *start;
u64 *seg_addr;
u16 *seg_size;
int seg;
if (unlikely(parse->errlev || parse->errcode || cqe->sg.segs > 1)) {
if (unlikely(parse->errlev || parse->errcode)) {
if (otx2_check_rcv_errors(pfvf, cqe, cq->cq_idx))
return;
}
......@@ -288,9 +292,19 @@ static void otx2_rcv_pkt_handler(struct otx2_nic *pfvf,
if (unlikely(!skb))
return;
otx2_skb_add_frag(pfvf, skb, cqe->sg.seg_addr, cqe->sg.seg_size, parse);
cq->pool_ptrs++;
start = (void *)sg;
end = start + ((cqe->parse.desc_sizem1 + 1) * 16);
while (start < end) {
sg = (struct nix_rx_sg_s *)start;
seg_addr = &sg->seg_addr;
seg_size = (void *)sg;
for (seg = 0; seg < sg->segs; seg++, seg_addr++) {
otx2_skb_add_frag(pfvf, skb, *seg_addr, seg_size[seg],
parse);
cq->pool_ptrs++;
}
start += sizeof(*sg);
}
otx2_set_rxhash(pfvf, cqe, skb);
skb_record_rx_queue(skb, cq->cq_idx);
......
......@@ -24,7 +24,6 @@
#define OTX2_ETH_HLEN (VLAN_ETH_HLEN + VLAN_HLEN)
#define OTX2_MIN_MTU 64
#define OTX2_MAX_MTU (9212 - OTX2_ETH_HLEN)
#define OTX2_MAX_GSO_SEGS 255
#define OTX2_MAX_FRAGS_IN_SQE 9
......
......@@ -586,7 +586,7 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* MTU range: 68 - 9190 */
netdev->min_mtu = OTX2_MIN_MTU;
netdev->max_mtu = OTX2_MAX_MTU;
netdev->max_mtu = otx2_get_max_mtu(vf);
INIT_WORK(&vf->reset_task, otx2vf_reset_task);
......
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