From patchwork Tue May 2 13:06:55 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sunil Kovvuri X-Patchwork-Id: 9707981 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id EA4AB60245 for ; Tue, 2 May 2017 13:08:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DA59C28448 for ; Tue, 2 May 2017 13:08:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CF0652844B; Tue, 2 May 2017 13:08:59 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, DKIM_VALID, FREEMAIL_FROM autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3220528448 for ; Tue, 2 May 2017 13:08:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=Fag6Pqks3SRbVNm/X8/vNt2Dm+/qIjoeU9yfBKmMJ9M=; b=fF+zZeAVIAdHUm5Dp3WW/LMZJA XwAA8831JowNXR1P4jdNXa4nM4fCPN4pZNHA+pTfrArLSeqZVPPImwqbt/qXEKNCKWGWXRbHdqJty kiXnDa9BHSM3fKU4+V/XoBDzKC0Oeol3js+QY7JschVyIJ+Je/Zr5r/f18Nty7uU2JAuElH+MobnK VpDEJ/ZfmMruYHmh7ObZkY3eDtyKnnAO47fDrBdaoH7ZhOzu9mFSU1ifp3RiGMz77YdPfuNbXCywH yHc/aGxzyD7nOWQsQAVpsd53VCflfA8Tr0cfutMyHWbTlNqiR+KKyqocirb5ZNlnLdGdQY2/ALQLH I5zeWnsA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1d5XY2-0006Jz-9N; Tue, 02 May 2017 13:08:58 +0000 Received: from mail-pg0-x242.google.com ([2607:f8b0:400e:c05::242]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1d5XXC-0005Kv-Og for linux-arm-kernel@lists.infradead.org; Tue, 02 May 2017 13:08:15 +0000 Received: by mail-pg0-x242.google.com with SMTP id t7so22175752pgt.1 for ; Tue, 02 May 2017 06:07:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=g2tNtrhYPZQPAbYmlvMYCaOLDv9EYzCM02fqg7OnHss=; b=sSFqd7/a3s3B7UlxbqWb6Qj1mWiJ5kN2NXoaa0ujUVywzPnnXkkV+D9SF1avEgXT1M su+TxolApuD48YNr4tnV53qlFU6N35qOiVNGpteqnnTr/ABiQBD82rqS4B9O5NK6Fboq RiycEEb3/qmbw3iDANsJhumJP3IB9c/4mRCF+eLbqAOO/dQpQBXHhestMwWC5trdBaYz zKOUQHE4di3ZS9TjffQLFiB3d3aRFYME00bNAgmw1jqj/utE8uw09dZMJd9G5Ar2gPXw mwTYz04NfcVHWaxN43CP1v3ZvmcJYEU1VIbs+PlrYjCsloW+yAHgCgWNPgu7w1GvBQeY joTQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=g2tNtrhYPZQPAbYmlvMYCaOLDv9EYzCM02fqg7OnHss=; b=Ojvkmb0j1D4OSrxZENENIsJ9la/ErVnJFl40VFxKmJk/JHZD+Sgg8gSElmYHKj7RtB XslTtqqAxDvt9jYFczWUJOKn56fUUoC2mE36/qwx/ESWXne9eobYzj25NzLYk3kTKpFl A/J6cCag7/+PKgHYdWXSbpq/X2Vj6x8R60HShKk1lT8vJkC/Bp2YEAGMZZSnkcL9zY9u J1Jqf/uyc+IOPoA0zYJFynupOEbhObkLr7M9DD5p6dTf8EIRtXeoiJDtz6BeXlcuI68r QBHhE3+BAN0kw+eNE6tbmjD6+JJTZrROT1jkJX/Q7vAIE9J29Vx5yyTAxAcCbEzQM1yg arvw== X-Gm-Message-State: AN3rC/7lsgLSFnsrDuo6E6KPbTiDnCGDjy6tyTFs8YZ9mV8yDVWNWyCp V6mAXGWNw+XG+eOY X-Received: by 10.84.175.67 with SMTP id s61mr41314232plb.43.1493730468134; Tue, 02 May 2017 06:07:48 -0700 (PDT) Received: from machine421.in.caveonetworks.com ([14.140.2.178]) by smtp.googlemail.com with ESMTPSA id k198sm24610689pga.54.2017.05.02.06.07.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 02 May 2017 06:07:47 -0700 (PDT) From: sunil.kovvuri@gmail.com To: netdev@vger.kernel.org Subject: [PATCH 6/9] net: thunderx: Add support for XDP_DROP Date: Tue, 2 May 2017 18:36:55 +0530 Message-Id: <1493730418-24606-7-git-send-email-sunil.kovvuri@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1493730418-24606-1-git-send-email-sunil.kovvuri@gmail.com> References: <1493730418-24606-1-git-send-email-sunil.kovvuri@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170502_060807_201710_C9B6A627 X-CRM114-Status: GOOD ( 22.89 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Sunil Goutham , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP From: Sunil Goutham Adds support for XDP_DROP. Also since in XDP mode there is just a single buffer per page, made changes to recycle DMA mapping info as well along with pages. Signed-off-by: Sunil Goutham --- drivers/net/ethernet/cavium/thunder/nicvf_main.c | 23 ++++++- drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 77 ++++++++++++++++------ drivers/net/ethernet/cavium/thunder/nicvf_queues.h | 4 +- 3 files changed, 79 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c index 9c48873..a58cc1e 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "nic_reg.h" @@ -505,6 +506,7 @@ static inline bool nicvf_xdp_rx(struct nicvf *nic, struct cqe_rx_t *cqe_rx) { struct xdp_buff xdp; + struct page *page; u32 action; u16 len; u64 dma_addr, cpu_addr; @@ -527,12 +529,27 @@ static inline bool nicvf_xdp_rx(struct nicvf *nic, switch (action) { case XDP_PASS: case XDP_TX: - case XDP_ABORTED: - case XDP_DROP: /* Pass on all packets to network stack */ return false; default: bpf_warn_invalid_xdp_action(action); + case XDP_ABORTED: + trace_xdp_exception(nic->netdev, prog, action); + case XDP_DROP: + page = virt_to_page(xdp.data); + /* Check if it's a recycled page, if not + * unmap the DMA mapping. + * + * Recycled page holds an extra reference. + */ + if (page_ref_count(page) == 1) { + dma_addr &= PAGE_MASK; + dma_unmap_page_attrs(&nic->pdev->dev, dma_addr, + RCV_FRAG_LEN, DMA_FROM_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC); + } + put_page(page); + return true; } return false; } @@ -645,7 +662,7 @@ static void nicvf_rcv_pkt_handler(struct net_device *netdev, if (nicvf_xdp_rx(snic, nic->xdp_prog, cqe_rx)) return; - skb = nicvf_get_rcv_skb(snic, cqe_rx); + skb = nicvf_get_rcv_skb(snic, cqe_rx, nic->xdp_prog ? true : false); if (!skb) { netdev_dbg(nic->netdev, "Packet not received\n"); return; diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c index 8c3c571..5009f49 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c @@ -117,6 +117,7 @@ static struct pgcache *nicvf_alloc_page(struct nicvf *nic, /* Save the page in page cache */ pgcache->page = page; + pgcache->dma_addr = 0; rbdr->pgalloc++; } @@ -144,7 +145,7 @@ static inline int nicvf_alloc_rcv_buffer(struct nicvf *nic, struct rbdr *rbdr, /* Check if request can be accomodated in previous allocated page. * But in XDP mode only one buffer per page is permitted. */ - if (!nic->pnicvf->xdp_prog && nic->rb_page && + if (!rbdr->is_xdp && nic->rb_page && ((nic->rb_page_offset + buf_len) <= PAGE_SIZE)) { nic->rb_pageref++; goto ret; @@ -165,18 +166,24 @@ static inline int nicvf_alloc_rcv_buffer(struct nicvf *nic, struct rbdr *rbdr, if (pgcache) nic->rb_page = pgcache->page; ret: - /* HW will ensure data coherency, CPU sync not required */ - *rbuf = (u64)dma_map_page_attrs(&nic->pdev->dev, nic->rb_page, - nic->rb_page_offset, buf_len, - DMA_FROM_DEVICE, - DMA_ATTR_SKIP_CPU_SYNC); - if (dma_mapping_error(&nic->pdev->dev, (dma_addr_t)*rbuf)) { - if (!nic->rb_page_offset) - __free_pages(nic->rb_page, 0); - nic->rb_page = NULL; - return -ENOMEM; + if (rbdr->is_xdp && pgcache && pgcache->dma_addr) { + *rbuf = pgcache->dma_addr; + } else { + /* HW will ensure data coherency, CPU sync not required */ + *rbuf = (u64)dma_map_page_attrs(&nic->pdev->dev, nic->rb_page, + nic->rb_page_offset, buf_len, + DMA_FROM_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC); + if (dma_mapping_error(&nic->pdev->dev, (dma_addr_t)*rbuf)) { + if (!nic->rb_page_offset) + __free_pages(nic->rb_page, 0); + nic->rb_page = NULL; + return -ENOMEM; + } + if (pgcache) + pgcache->dma_addr = *rbuf; + nic->rb_page_offset += buf_len; } - nic->rb_page_offset += buf_len; return 0; } @@ -230,8 +237,16 @@ static int nicvf_init_rbdr(struct nicvf *nic, struct rbdr *rbdr, * On embedded platforms i.e 81xx/83xx available memory itself * is low and minimum ring size of RBDR is 8K, that takes away * lots of memory. + * + * But for XDP it has to be a single buffer per page. */ - rbdr->pgcnt = ring_len / (PAGE_SIZE / buf_size); + if (!nic->pnicvf->xdp_prog) { + rbdr->pgcnt = ring_len / (PAGE_SIZE / buf_size); + rbdr->is_xdp = false; + } else { + rbdr->pgcnt = ring_len; + rbdr->is_xdp = true; + } rbdr->pgcnt = roundup_pow_of_two(rbdr->pgcnt); rbdr->pgcache = kzalloc(sizeof(*rbdr->pgcache) * rbdr->pgcnt, GFP_KERNEL); @@ -1454,8 +1469,31 @@ static inline unsigned frag_num(unsigned i) #endif } +static void nicvf_unmap_rcv_buffer(struct nicvf *nic, u64 dma_addr, + u64 buf_addr, bool xdp) +{ + struct page *page = NULL; + int len = RCV_FRAG_LEN; + + if (xdp) { + page = virt_to_page(phys_to_virt(buf_addr)); + /* Check if it's a recycled page, if not + * unmap the DMA mapping. + * + * Recycled page holds an extra reference. + */ + if (page_ref_count(page) != 1) + return; + /* Receive buffers in XDP mode are mapped from page start */ + dma_addr &= PAGE_MASK; + } + dma_unmap_page_attrs(&nic->pdev->dev, dma_addr, len, + DMA_FROM_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); +} + /* Returns SKB for a received packet */ -struct sk_buff *nicvf_get_rcv_skb(struct nicvf *nic, struct cqe_rx_t *cqe_rx) +struct sk_buff *nicvf_get_rcv_skb(struct nicvf *nic, + struct cqe_rx_t *cqe_rx, bool xdp) { int frag; int payload_len = 0; @@ -1490,10 +1528,9 @@ struct sk_buff *nicvf_get_rcv_skb(struct nicvf *nic, struct cqe_rx_t *cqe_rx) if (!frag) { /* First fragment */ - dma_unmap_page_attrs(&nic->pdev->dev, - *rb_ptrs - cqe_rx->align_pad, - RCV_FRAG_LEN, DMA_FROM_DEVICE, - DMA_ATTR_SKIP_CPU_SYNC); + nicvf_unmap_rcv_buffer(nic, + *rb_ptrs - cqe_rx->align_pad, + phys_addr, xdp); skb = nicvf_rb_ptr_to_skb(nic, phys_addr - cqe_rx->align_pad, payload_len); @@ -1503,9 +1540,7 @@ struct sk_buff *nicvf_get_rcv_skb(struct nicvf *nic, struct cqe_rx_t *cqe_rx) skb_put(skb, payload_len); } else { /* Add fragments */ - dma_unmap_page_attrs(&nic->pdev->dev, *rb_ptrs, - RCV_FRAG_LEN, DMA_FROM_DEVICE, - DMA_ATTR_SKIP_CPU_SYNC); + nicvf_unmap_rcv_buffer(nic, *rb_ptrs, phys_addr, xdp); page = virt_to_page(phys_to_virt(phys_addr)); offset = phys_to_virt(phys_addr) - page_address(page); skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h index 07136a2..db04c0e 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h @@ -228,6 +228,7 @@ struct rbdr { u32 head; u32 tail; struct q_desc_mem dmem; + bool is_xdp; /* For page recycling */ int pgidx; @@ -339,7 +340,8 @@ void nicvf_sq_free_used_descs(struct net_device *netdev, int nicvf_sq_append_skb(struct nicvf *nic, struct snd_queue *sq, struct sk_buff *skb, u8 sq_num); -struct sk_buff *nicvf_get_rcv_skb(struct nicvf *nic, struct cqe_rx_t *cqe_rx); +struct sk_buff *nicvf_get_rcv_skb(struct nicvf *nic, + struct cqe_rx_t *cqe_rx, bool xdp); void nicvf_rbdr_task(unsigned long data); void nicvf_rbdr_work(struct work_struct *work);