Received: by 2002:a25:8b12:0:0:0:0:0 with SMTP id i18csp3571154ybl; Mon, 12 Aug 2019 02:46:51 -0700 (PDT) X-Google-Smtp-Source: APXvYqwXY2GsA0NYwul/DwFWMM1d48bxdI8KQFGxgWvkb8cvYHybL03sha2zL3awV/JCvXhGj7fZ X-Received: by 2002:a17:902:d20a:: with SMTP id t10mr31319329ply.226.1565603211219; Mon, 12 Aug 2019 02:46:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1565603211; cv=none; d=google.com; s=arc-20160816; b=ODi2JIKFvNzfwNpoei0KPPR2tbXgpKLRlnQrLnpOLLMI3uX4CXmCECnKqGZhDc928Z 6mcvkAmZ/JIqJxAvJoV4NP8+WeQTTsdKHHlrOtJYGW7t51CthbZK3gmb0nwHMwFHUYgj LJwU44wWHhiHEyL7mRkO7Kb0dr0zCOUH0zV759R5nh9FVfLPG75PxFJ/iviM86vxPTuz kxPFDMLQczdKCfYIwNkwNhTeaN0snxsihkpBhamSocs70S2m9r/QOMjqa78nfMDBmFAa EI3dFwluibntILPwHCgZtHD6EV5am9pDaYixNZoUzkofnsmOyRh/O1PsB1wq4HM7bmqK ofww== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature; bh=aAxNQ2O1orckHOvwFrBOyNgYLiO2w/FyyOFLyutavAA=; b=1CQwlz+tSfwwnk2qJ958wLyVC/mnxvldvRuXl/9r6AVDrxQr8Mfbwl0yOWlJeGSVl3 EQtfDmS9vNyQBm9M0iBnccwn2GQRvJOpuwmJl7LI/dy+SuLk0ptDqLocNWHggzCWwYmB L0ZSMg5eJKLqw0mnpJkGXNzb1mPbqKomDgKKn7BndHaTLTy4IigPRiAKF/f5VdMzbylw +IyPccqmXC1tf1PVv1vLb6GAv5LJcngnI3hdB9tu1Vajkm26oI7WvTaO46AeC4tvH9wY u/xaGjR4xeoBAE1BBTmpfc9TJcFdXlZkJvlxWaXsxjyoEcw6xRE1IjoYyEXdQsBR3ARm /OPA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@synopsys.com header.s=mail header.b=gWG4SDn1; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=synopsys.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e33si6634120pld.436.2019.08.12.02.46.35; Mon, 12 Aug 2019 02:46:51 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@synopsys.com header.s=mail header.b=gWG4SDn1; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=synopsys.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727746AbfHLJpJ (ORCPT + 99 others); Mon, 12 Aug 2019 05:45:09 -0400 Received: from smtprelay-out1.synopsys.com ([198.182.61.142]:50932 "EHLO smtprelay-out1.synopsys.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1727567AbfHLJo1 (ORCPT ); Mon, 12 Aug 2019 05:44:27 -0400 Received: from mailhost.synopsys.com (mdc-mailhost1.synopsys.com [10.225.0.209]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by smtprelay-out1.synopsys.com (Postfix) with ESMTPS id 552C0C2173; Mon, 12 Aug 2019 09:44:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=synopsys.com; s=mail; t=1565603066; bh=ow6p6jwrXh56WCp0knNr8AIf4GNn22Dq9KX2g2HFolw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:In-Reply-To: References:From; b=gWG4SDn1qEUSS6quM64GC+LjR14ENkEuWVXcweUXg0BvPjtHZDF61z0Sl338kztOD tGwotsTlNW9XGOrtdrcdskNjSEXzMUGJE3BBGn1klA/zN+EJTzNC69ZSR/cFtE7v0c KV3qVkwJs21SdMosFNvY3QAzQ6NSbO+expVSGCjxnjLKeBuJXh+qkloASp3/aTAC9p G7QJqK/ofCef07nyIpyNBU287oiREW/zoJnRXCQMN2xs2OILPNVWyYoGS54SdTjHM0 vvT1vBNWDQl8/gBwVQjNq+IwciKASzrykGLqXChNRejSWqBjtQ5UA06aorNoxYdyJR JKxkc9vdyPVAA== Received: from de02dwia024.internal.synopsys.com (de02dwia024.internal.synopsys.com [10.225.19.81]) by mailhost.synopsys.com (Postfix) with ESMTP id E8314A005F; Mon, 12 Aug 2019 09:44:22 +0000 (UTC) From: Jose Abreu To: netdev@vger.kernel.org Cc: Joao Pinto , Jose Abreu , Giuseppe Cavallaro , Alexandre Torgue , "David S. Miller" , Maxime Coquelin , linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next v2 02/12] net: stmmac: Prepare to add Split Header support Date: Mon, 12 Aug 2019 11:44:01 +0200 Message-Id: <342007d6ac2b44db03d113e7e8bf0310caa77ea0.1565602974.git.joabreu@synopsys.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org In order to add Split Header support, stmmac_rx() needs to take into account that packet may be split accross multiple descriptors. Refactor the logic of this function in order to support this scenario. Signed-off-by: Jose Abreu --- Cc: Giuseppe Cavallaro Cc: Alexandre Torgue Cc: Jose Abreu Cc: "David S. Miller" Cc: Maxime Coquelin Cc: netdev@vger.kernel.org Cc: linux-stm32@st-md-mailman.stormreply.com Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 6 + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 149 +++++++++++++--------- 2 files changed, 95 insertions(+), 60 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 80276587048a..56158e1448ac 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -74,6 +74,12 @@ struct stmmac_rx_queue { u32 rx_zeroc_thresh; dma_addr_t dma_rx_phy; u32 rx_tail_addr; + unsigned int state_saved; + struct { + struct sk_buff *skb; + unsigned int len; + unsigned int error; + } state; }; struct stmmac_channel { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index b2e5f4ecd551..a093eb4ec275 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -3353,9 +3353,10 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) { struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; struct stmmac_channel *ch = &priv->channel[queue]; + unsigned int count = 0, error = 0, len = 0; + int status = 0, coe = priv->hw->rx_csum; unsigned int next_entry = rx_q->cur_rx; - int coe = priv->hw->rx_csum; - unsigned int count = 0; + struct sk_buff *skb = NULL; if (netif_msg_rx_status(priv)) { void *rx_head; @@ -3369,9 +3370,27 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) stmmac_display_ring(priv, rx_head, DMA_RX_SIZE, true); } while (count < limit) { + enum pkt_hash_types hash_type; struct stmmac_rx_buffer *buf; + unsigned int prev_len = 0; struct dma_desc *np, *p; - int entry, status; + int entry; + u32 hash; + + if (!count && rx_q->state_saved) { + skb = rx_q->state.skb; + error = rx_q->state.error; + len = rx_q->state.len; + } else { + rx_q->state_saved = false; + skb = NULL; + error = 0; + len = 0; + } + +read_again: + if (count >= limit) + break; entry = next_entry; buf = &rx_q->buf_pool[entry]; @@ -3407,28 +3426,24 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) page_pool_recycle_direct(rx_q->page_pool, buf->page); priv->dev->stats.rx_errors++; buf->page = NULL; + error = 1; + } + + if (unlikely(error & (status & rx_not_ls))) + goto read_again; + if (unlikely(error)) { + if (skb) + dev_kfree_skb(skb); + continue; + } + + /* Buffer is good. Go on. */ + + if (likely(status & rx_not_ls)) { + len += priv->dma_buf_sz; } else { - enum pkt_hash_types hash_type; - struct sk_buff *skb; - unsigned int des; - int frame_len; - u32 hash; - - stmmac_get_desc_addr(priv, p, &des); - frame_len = stmmac_get_rx_frame_len(priv, p, coe); - - /* If frame length is greater than skb buffer size - * (preallocated during init) then the packet is - * ignored - */ - if (frame_len > priv->dma_buf_sz) { - if (net_ratelimit()) - netdev_err(priv->dev, - "len %d larger than size (%d)\n", - frame_len, priv->dma_buf_sz); - priv->dev->stats.rx_length_errors++; - continue; - } + prev_len = len; + len = stmmac_get_rx_frame_len(priv, p, coe); /* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3 * Type frames (LLC/LLC-SNAP) @@ -3439,57 +3454,71 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) */ if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00) || unlikely(status != llc_snap)) - frame_len -= ETH_FCS_LEN; - - if (netif_msg_rx_status(priv)) { - netdev_dbg(priv->dev, "\tdesc: %p [entry %d] buff=0x%x\n", - p, entry, des); - netdev_dbg(priv->dev, "frame size %d, COE: %d\n", - frame_len, status); - } + len -= ETH_FCS_LEN; + } - skb = netdev_alloc_skb_ip_align(priv->dev, frame_len); - if (unlikely(!skb)) { + if (!skb) { + skb = netdev_alloc_skb_ip_align(priv->dev, len); + if (!skb) { priv->dev->stats.rx_dropped++; continue; } - dma_sync_single_for_cpu(priv->device, buf->addr, - frame_len, DMA_FROM_DEVICE); + dma_sync_single_for_cpu(priv->device, buf->addr, len, + DMA_FROM_DEVICE); skb_copy_to_linear_data(skb, page_address(buf->page), - frame_len); - skb_put(skb, frame_len); + len); + skb_put(skb, len); - if (netif_msg_pktdata(priv)) { - netdev_dbg(priv->dev, "frame received (%dbytes)", - frame_len); - print_pkt(skb->data, frame_len); - } + /* Data payload copied into SKB, page ready for recycle */ + page_pool_recycle_direct(rx_q->page_pool, buf->page); + buf->page = NULL; + } else { + unsigned int buf_len = len - prev_len; - stmmac_get_rx_hwtstamp(priv, p, np, skb); + if (likely(status & rx_not_ls)) + buf_len = priv->dma_buf_sz; - stmmac_rx_vlan(priv->dev, skb); + dma_sync_single_for_cpu(priv->device, buf->addr, + buf_len, DMA_FROM_DEVICE); + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, + buf->page, 0, buf_len, + priv->dma_buf_sz); - skb->protocol = eth_type_trans(skb, priv->dev); + /* Data payload appended into SKB */ + page_pool_release_page(rx_q->page_pool, buf->page); + buf->page = NULL; + } - if (unlikely(!coe)) - skb_checksum_none_assert(skb); - else - skb->ip_summed = CHECKSUM_UNNECESSARY; + if (likely(status & rx_not_ls)) + goto read_again; - if (!stmmac_get_rx_hash(priv, p, &hash, &hash_type)) - skb_set_hash(skb, hash, hash_type); + /* Got entire packet into SKB. Finish it. */ - skb_record_rx_queue(skb, queue); - napi_gro_receive(&ch->rx_napi, skb); + stmmac_get_rx_hwtstamp(priv, p, np, skb); + stmmac_rx_vlan(priv->dev, skb); + skb->protocol = eth_type_trans(skb, priv->dev); - /* Data payload copied into SKB, page ready for recycle */ - page_pool_recycle_direct(rx_q->page_pool, buf->page); - buf->page = NULL; + if (unlikely(!coe)) + skb_checksum_none_assert(skb); + else + skb->ip_summed = CHECKSUM_UNNECESSARY; - priv->dev->stats.rx_packets++; - priv->dev->stats.rx_bytes += frame_len; - } + if (!stmmac_get_rx_hash(priv, p, &hash, &hash_type)) + skb_set_hash(skb, hash, hash_type); + + skb_record_rx_queue(skb, queue); + napi_gro_receive(&ch->rx_napi, skb); + + priv->dev->stats.rx_packets++; + priv->dev->stats.rx_bytes += len; + } + + if (status & rx_not_ls) { + rx_q->state_saved = true; + rx_q->state.skb = skb; + rx_q->state.error = error; + rx_q->state.len = len; } stmmac_rx_refill(priv, queue); -- 2.7.4