Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp1950759ybl; Sun, 19 Jan 2020 15:18:03 -0800 (PST) X-Google-Smtp-Source: APXvYqx5xlHMjTxcz8gSAQ8dAkzyuwcoVYEKxpweAK15zjC24Fmf4IaS9Md0SX/4MoGU7QSn9Egy X-Received: by 2002:aca:d0b:: with SMTP id 11mr10992158oin.71.1579475882841; Sun, 19 Jan 2020 15:18:02 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1579475882; cv=none; d=google.com; s=arc-20160816; b=oyge1VeWEgZ6xaUi3aH3IKOYgnvJ5GEGYHp8h5ooPRhBnOAFx5cVRhjPM+b317dahi A+Ko/B6A2nSGa1xTx5arD8iwPok7uSZ/FdSzPHNiL6hq3+8On2AtQFlg7ogHZFIe0WV8 SfRlarOf+6Sdwl3sDEJynTf82Z9Vw1uyWTxdc1TJ9WDmW/iJ9rDrEVVXzdoAlZWoTi9T mI41nlmAKoE5mM7Shy4vCsEgmnALHr/GCupAg2ir9IbFIVlpv2qGpNjO53XglqxlzsC+ rvb0S+Ed7F3vELvJXdFiH3mVUAGwxeWPBhNW+oQjglfAZZGNM+hNA3mSrKeoKR12AQTT ZNZA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:date:subject:from:references:in-reply-to :message-id:cc:to; bh=cR6z7GVjiie8ElQVUZ2HzbtNGD20+0QLYAg+No93epQ=; b=ZWDMBik4OiUnbq9PomJfnEDiQsg5wwGbTg7New+9oLCfYvIk4MFkno9MTfu1QiE6EL L3qiVlrR3p9daOg7KSlnz24Zs5soaBajw171Tv1PWNCWSJBU34rs5fBVrDZ5WZQs1+jj OQLhqUfD3hWt/Rpi57UP6xLr/bTRa++n1JehNq+o+HPgxlVR/ty2If+0HC6UKHV7fJOO 2q67RTtDd4BBMf0XE/13pGVEmLshj6GjtZwZUk2qEY/xsrUZtsJloF8P6HzIxzMF0SZi q2Tv7RoUTFHzWF3u44Z5NUBOpBQFAtogbJc8/ThS7gMsn2qIx9AXsRaQvJ5WMJ2l+nFP aqmg== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id w1si17378596oia.169.2020.01.19.15.17.50; Sun, 19 Jan 2020 15:18:02 -0800 (PST) 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; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729180AbgASXQr (ORCPT + 99 others); Sun, 19 Jan 2020 18:16:47 -0500 Received: from kvm5.telegraphics.com.au ([98.124.60.144]:49808 "EHLO kvm5.telegraphics.com.au" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729011AbgASXQd (ORCPT ); Sun, 19 Jan 2020 18:16:33 -0500 Received: by kvm5.telegraphics.com.au (Postfix, from userid 502) id 588212997B; Sun, 19 Jan 2020 18:16:31 -0500 (EST) To: "David S. Miller" Cc: Thomas Bogendoerfer , Chris Zankel , Laurent Vivier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org Message-Id: In-Reply-To: References: From: Finn Thain Subject: [PATCH net 12/19] net/sonic: Fix receive buffer handling Date: Mon, 20 Jan 2020 09:56:09 +1100 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The SONIC can sometimes advance its rx buffer pointer (RRP register) without advancing its rx descriptor pointer (CRDA register). As a result the index of the current rx descriptor may not equal that of the current rx buffer. The driver mistakenly assumes that they are always equal. This assumption leads to incorrect packet lengths and possible packet duplication. Avoid this by calling a new function to locate the buffer corresponding to a given descriptor. Fixes: efcce839360f ("[PATCH] macsonic/jazzsonic network drivers update") Tested-by: Stan Johnson Signed-off-by: Finn Thain --- drivers/net/ethernet/natsemi/sonic.c | 36 ++++++++++++++++++++++++---- drivers/net/ethernet/natsemi/sonic.h | 5 ++-- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/natsemi/sonic.c b/drivers/net/ethernet/natsemi/sonic.c index ea74c3c2c501..23740fde6c02 100644 --- a/drivers/net/ethernet/natsemi/sonic.c +++ b/drivers/net/ethernet/natsemi/sonic.c @@ -443,6 +443,22 @@ static irqreturn_t sonic_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } +/* Return the array index corresponding to a given Receive Buffer pointer. */ + +static inline int index_from_addr(struct sonic_local *lp, dma_addr_t addr, + unsigned int last) +{ + unsigned int i = last; + + do { + i = (i + 1) & SONIC_RRS_MASK; + if (addr == lp->rx_laddr[i]) + return i; + } while (i != last); + + return -ENOENT; +} + /* * We have a good packet(s), pass it/them up the network stack. */ @@ -462,6 +478,16 @@ static void sonic_rx(struct net_device *dev) status = sonic_rda_get(dev, entry, SONIC_RD_STATUS); if (status & SONIC_RCR_PRX) { + u32 addr = (sonic_rda_get(dev, entry, + SONIC_RD_PKTPTR_H) << 16) | + sonic_rda_get(dev, entry, SONIC_RD_PKTPTR_L); + int i = index_from_addr(lp, addr, entry); + + if (i < 0) { + WARN_ONCE(1, "failed to find buffer!\n"); + break; + } + /* Malloc up new buffer. */ new_skb = netdev_alloc_skb(dev, SONIC_RBSIZE + 2); if (new_skb == NULL) { @@ -483,7 +509,7 @@ static void sonic_rx(struct net_device *dev) /* now we have a new skb to replace it, pass the used one up the stack */ dma_unmap_single(lp->device, lp->rx_laddr[entry], SONIC_RBSIZE, DMA_FROM_DEVICE); - used_skb = lp->rx_skb[entry]; + used_skb = lp->rx_skb[i]; pkt_len = sonic_rda_get(dev, entry, SONIC_RD_PKTLEN); skb_trim(used_skb, pkt_len); used_skb->protocol = eth_type_trans(used_skb, dev); @@ -492,13 +518,13 @@ static void sonic_rx(struct net_device *dev) lp->stats.rx_bytes += pkt_len; /* and insert the new skb */ - lp->rx_laddr[entry] = new_laddr; - lp->rx_skb[entry] = new_skb; + lp->rx_laddr[i] = new_laddr; + lp->rx_skb[i] = new_skb; bufadr_l = (unsigned long)new_laddr & 0xffff; bufadr_h = (unsigned long)new_laddr >> 16; - sonic_rra_put(dev, entry, SONIC_RR_BUFADR_L, bufadr_l); - sonic_rra_put(dev, entry, SONIC_RR_BUFADR_H, bufadr_h); + sonic_rra_put(dev, i, SONIC_RR_BUFADR_L, bufadr_l); + sonic_rra_put(dev, i, SONIC_RR_BUFADR_H, bufadr_h); } else { /* This should only happen, if we enable accepting broken packets. */ } diff --git a/drivers/net/ethernet/natsemi/sonic.h b/drivers/net/ethernet/natsemi/sonic.h index 227975eb4cb8..46052a0cfe22 100644 --- a/drivers/net/ethernet/natsemi/sonic.h +++ b/drivers/net/ethernet/natsemi/sonic.h @@ -275,8 +275,9 @@ #define SONIC_NUM_RDS SONIC_NUM_RRS /* number of receive descriptors */ #define SONIC_NUM_TDS 16 /* number of transmit descriptors */ -#define SONIC_RDS_MASK (SONIC_NUM_RDS-1) -#define SONIC_TDS_MASK (SONIC_NUM_TDS-1) +#define SONIC_RRS_MASK (SONIC_NUM_RRS - 1) +#define SONIC_RDS_MASK (SONIC_NUM_RDS - 1) +#define SONIC_TDS_MASK (SONIC_NUM_TDS - 1) #define SONIC_RBSIZE 1520 /* size of one resource buffer */ -- 2.24.1