From patchwork Sat Dec 14 01:25:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Finn Thain X-Patchwork-Id: 1209593 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=telegraphics.com.au Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47ZVTP0mfTz9sPW for ; Sat, 14 Dec 2019 12:35:03 +1100 (AEDT) Received: from localhost ([::1]:55022 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ifwKj-0002pI-3X for incoming@patchwork.ozlabs.org; Fri, 13 Dec 2019 20:35:01 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:41595) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ifwEe-00041w-Bp for qemu-devel@nongnu.org; Fri, 13 Dec 2019 20:28:45 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ifwEc-00019J-On for qemu-devel@nongnu.org; Fri, 13 Dec 2019 20:28:44 -0500 Received: from kvm5.telegraphics.com.au ([98.124.60.144]:47410) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ifwEc-00016t-8z; Fri, 13 Dec 2019 20:28:42 -0500 Received: by kvm5.telegraphics.com.au (Postfix, from userid 502) id 70CAB27DAC; Fri, 13 Dec 2019 20:28:41 -0500 (EST) To: Jason Wang , qemu-devel@nongnu.org Message-Id: In-Reply-To: References: From: Finn Thain Subject: [PATCH 09/10] dp8393x: Don't stop reception upon RBE interrupt assertion Date: Sat, 14 Dec 2019 12:25:57 +1100 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 98.124.60.144 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Aleksandar Rikalo , Herve Poussineau , Laurent Vivier , qemu-stable@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Section 5.4.7 of the datasheet explains that the RBE interrupt is an "early warning". It indicates that the last RBA is still available to receive a packet. It doesn't imply actual receive buffer exhaustion. This is an important distinction because Linux will not check and clear the RBE interrupt until it receives another packet. But that won't happen if can_receive returns false. So the SONIC becomes deaf (until reset). Fix this with a new flag to indicate actual receive buffer exhaustion. Signed-off-by: Finn Thain --- hw/net/dp8393x.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c index 24f2e19f07..8e66b1f5de 100644 --- a/hw/net/dp8393x.c +++ b/hw/net/dp8393x.c @@ -157,6 +157,7 @@ typedef struct dp8393xState { /* Hardware */ uint8_t it_shift; bool big_endian; + bool last_rba_is_full; qemu_irq irq; #ifdef DEBUG_SONIC int irq_level; @@ -311,6 +312,12 @@ static void dp8393x_do_read_rra(dp8393xState *s) { int width, size; + /* Already on the last RBA? */ + s->last_rba_is_full = s->regs[SONIC_ISR] & SONIC_ISR_RBE; + if (s->last_rba_is_full) { + return; + } + /* Read memory */ width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1; size = sizeof(uint16_t) * 4 * width; @@ -334,7 +341,7 @@ static void dp8393x_do_read_rra(dp8393xState *s) s->regs[SONIC_RRP] = s->regs[SONIC_RSA]; } - /* Check resource exhaustion */ + /* Warn the host if this entry is the last one */ if (s->regs[SONIC_RRP] == s->regs[SONIC_RWP]) { s->regs[SONIC_ISR] |= SONIC_ISR_RBE; @@ -703,8 +710,9 @@ static int dp8393x_can_receive(NetClientState *nc) if (!(s->regs[SONIC_CR] & SONIC_CR_RXEN)) return 0; - if (s->regs[SONIC_ISR] & SONIC_ISR_RBE) + if (s->last_rba_is_full) { return 0; + } return 1; }