Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp1951972ybl; Sun, 19 Jan 2020 15:19:44 -0800 (PST) X-Google-Smtp-Source: APXvYqy5ont4DM+9aS1k6gkT/deemgd5v60/9f8AsVY1P7+I/35aN9sqO4W4QZd+lulPCuqMwhMh X-Received: by 2002:a9d:1d02:: with SMTP id m2mr13294623otm.45.1579475984264; Sun, 19 Jan 2020 15:19:44 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1579475984; cv=none; d=google.com; s=arc-20160816; b=xsA2wGLLFBBYtN7RJPEgZR5ieyEzBNyzt2FZFfddib+IwgnD2CpRGpdGMUOcc8UV+I DRg8FP/A8fj1YSMNIgSzRXMvo0KBfC+0bE/cFXpw7G5p9uQ/7G4BzXbW8A+wA0iUADcN SQjl5bauw2x5jd58q5MHfKi3reRVO/O0nVsszpxoklON/CJyqT5aPDbq+qnh3QpGKoiq wn681N/516o4tdaibryMQVPI3mwhHMZ0+ZLslyCqp/8n8s0lKnWgR6M3o7jAvCsnzp5Z KXmxwEthDDGowubSIPlSZiITfOkFZMeEMVZ3RvgCj3M0Tvvu5905LaalgS1sJook6+JR 5rnQ== 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=RmJKbvYJ+WEQrLKf4zzmyYQUVUb406RPALSF1IYaRv4=; b=ZT2Inh1jXeSzIkONQWP27ljnz8kmv0KZon4V+JGDEYj9I9NJh3XS8E9wj6BM92apGS wim1R+hAWT3w2fvnRO4gwZGVknE1q4cp0xtA2j2A8YJKSXvoV1Hly4vitt+8D4n0GHUN cOD7SfqtyrZyGM6pdoWy1G9/IHvE8SEW/2oS3fg3+XP+axv765LA1shFw+LAY6/RFjsw nAv+ohctq3eWbGi84sC4sadtsYCZf0IjtehnC2dt0EogJT1kAI1aI7tFiwmugYL2H4k5 24P4aVq0CagTMhW4AtaXuQPLJ35EUqLIT87dhFt8c/nAb6+lHj3XzufAddmCh45XE3Gt 2zqg== 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 y23si18604711oti.65.2020.01.19.15.19.32; Sun, 19 Jan 2020 15:19:44 -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 S1729578AbgASXSS (ORCPT + 99 others); Sun, 19 Jan 2020 18:18:18 -0500 Received: from kvm5.telegraphics.com.au ([98.124.60.144]:49754 "EHLO kvm5.telegraphics.com.au" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728896AbgASXQc (ORCPT ); Sun, 19 Jan 2020 18:16:32 -0500 Received: by kvm5.telegraphics.com.au (Postfix, from userid 502) id E112D2991F; Sun, 19 Jan 2020 18:16:30 -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 04/19] net/sonic: Add mutual exclusion for accessing shared state 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 netif_stop_queue() call in sonic_send_packet() races with the netif_wake_queue() call in sonic_interrupt(). This causes issues like "NETDEV WATCHDOG: eth0 (macsonic): transmit queue 0 timed out". Fix this by disabling interrupts when accessing tx_skb[] and next_tx. Update a comment to clarify the synchronization properties. Fixes: efcce839360f ("[PATCH] macsonic/jazzsonic network drivers update") Tested-by: Stan Johnson Signed-off-by: Finn Thain --- drivers/net/ethernet/natsemi/sonic.c | 38 +++++++++++++++++++--------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/natsemi/sonic.c b/drivers/net/ethernet/natsemi/sonic.c index 3cf84de8ad8e..dbbbc8bc72ff 100644 --- a/drivers/net/ethernet/natsemi/sonic.c +++ b/drivers/net/ethernet/natsemi/sonic.c @@ -242,7 +242,7 @@ static void sonic_tx_timeout(struct net_device *dev) * wake the tx queue * Concurrently with all of this, the SONIC is potentially writing to * the status flags of the TDs. - * Until some mutual exclusion is added, this code will not work with SMP. However, + * A spin lock is needed to make this work on SMP platforms. However, * MIPS Jazz machines and m68k Macs were all uni-processor machines. */ @@ -252,6 +252,7 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) dma_addr_t laddr; int length; int entry; + unsigned long flags; netif_dbg(lp, tx_queued, dev, "%s: skb=%p\n", __func__, skb); @@ -273,6 +274,8 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } + local_irq_save(flags); + entry = (lp->eol_tx + 1) & SONIC_TDS_MASK; sonic_tda_put(dev, entry, SONIC_TD_STATUS, 0); /* clear status */ @@ -284,10 +287,6 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) sonic_tda_put(dev, entry, SONIC_TD_LINK, sonic_tda_get(dev, entry, SONIC_TD_LINK) | SONIC_EOL); - /* - * Must set tx_skb[entry] only after clearing status, and - * before clearing EOL and before stopping queue - */ wmb(); lp->tx_len[entry] = length; lp->tx_laddr[entry] = laddr; @@ -310,6 +309,8 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) SONIC_WRITE(SONIC_CMD, SONIC_CR_TXP); + local_irq_restore(flags); + return NETDEV_TX_OK; } @@ -322,9 +323,16 @@ static irqreturn_t sonic_interrupt(int irq, void *dev_id) struct net_device *dev = dev_id; struct sonic_local *lp = netdev_priv(dev); int status; + unsigned long flags; + + local_irq_save(flags); + + status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT; + if (!status) { + local_irq_restore(flags); - if (!(status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT)) return IRQ_NONE; + } do { if (status & SONIC_INT_PKTRX) { @@ -338,11 +346,12 @@ static irqreturn_t sonic_interrupt(int irq, void *dev_id) int td_status; int freed_some = 0; - /* At this point, cur_tx is the index of a TD that is one of: - * unallocated/freed (status set & tx_skb[entry] clear) - * allocated and sent (status set & tx_skb[entry] set ) - * allocated and not yet sent (status clear & tx_skb[entry] set ) - * still being allocated by sonic_send_packet (status clear & tx_skb[entry] clear) + /* The state of a Transmit Descriptor may be inferred + * from { tx_skb[entry], td_status } as follows. + * { clear, clear } => the TD has never been used + * { set, clear } => the TD was handed to SONIC + * { set, set } => the TD was handed back + * { clear, set } => the TD is available for re-use */ netif_dbg(lp, intr, dev, "%s: tx done\n", __func__); @@ -444,7 +453,12 @@ static irqreturn_t sonic_interrupt(int irq, void *dev_id) /* load CAM done */ if (status & SONIC_INT_LCD) SONIC_WRITE(SONIC_ISR, SONIC_INT_LCD); /* clear the interrupt */ - } while((status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT)); + + status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT; + } while (status); + + local_irq_restore(flags); + return IRQ_HANDLED; } -- 2.24.1