From patchwork Fri Mar 7 02:04:20 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marcelo Tosatti X-Patchwork-Id: 327724 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 5102B2C023F for ; Fri, 7 Mar 2014 13:05:50 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751457AbaCGCF2 (ORCPT ); Thu, 6 Mar 2014 21:05:28 -0500 Received: from mx1.redhat.com ([209.132.183.28]:21162 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750924AbaCGCF1 (ORCPT ); Thu, 6 Mar 2014 21:05:27 -0500 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s2725H34011746 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 6 Mar 2014 21:05:17 -0500 Received: from amt.cnet (vpn1-6-40.gru2.redhat.com [10.97.6.40]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id s2725GlK031014; Thu, 6 Mar 2014 21:05:16 -0500 Received: from amt.cnet (localhost [127.0.0.1]) by amt.cnet (Postfix) with ESMTP id 6FD35104AFB; Thu, 6 Mar 2014 23:04:24 -0300 (BRT) Received: (from marcelo@localhost) by amt.cnet (8.14.6/8.14.6/Submit) id s2724LIm011522; Thu, 6 Mar 2014 23:04:21 -0300 Date: Thu, 6 Mar 2014 23:04:20 -0300 From: Marcelo Tosatti To: Jeff Kirsher , Vladimir Davydov Cc: e1000-devel@lists.sourceforge.net, netdev@vger.kernel.org Subject: [PATCH] e1000: do not allow watchdog to reenable transmits on shutdown Message-ID: <20140307020420.GA10797@amt.cnet> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org There is a race on the shutdown path of the e1000 driver that allows the card to DMA into free'd memory. The symptoms are similar to those described at commit d5bc77a223b0e9b9dfb002048d2b34a79e7d0b48, "e1000: don't enable dma receives until after dma address has been setup", where memory corruption is visible due to E1000_RXD_STAT_DD being written to the DMA transfer descriptor. Fix by not allowing the watchdog and tx fifo stall detector to re-enable E1000_TCTL_EN. Signed-off-by: Marcelo Tosatti --- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/net/ethernet/intel/e1000/e1000.h b/drivers/net/ethernet/intel/e1000/e1000.h index 10a0f22..bb5dc1a 100644 --- a/drivers/net/ethernet/intel/e1000/e1000.h +++ b/drivers/net/ethernet/intel/e1000/e1000.h @@ -321,7 +321,8 @@ struct e1000_adapter { enum e1000_state_t { __E1000_TESTING, __E1000_RESETTING, - __E1000_DOWN + __E1000_DOWN, + __E1000_NOTX = 4, }; #undef pr_fmt diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index 46e6544..b20ce98 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -414,6 +414,7 @@ int e1000_up(struct e1000_adapter *adapter) e1000_configure(adapter); clear_bit(__E1000_DOWN, &adapter->flags); + clear_bit(__E1000_NOTX, &adapter->flags); napi_enable(&adapter->napi); @@ -524,6 +525,10 @@ void e1000_down(struct e1000_adapter *adapter) netif_tx_disable(netdev); + /* do not allow watchdog to reenable transmits between + clearing E1000_TCTL_EN below and setting E1000_DOWN */ + set_bit(__E1000_NOTX, &adapter->flags); + /* disable transmits in the hardware */ tctl = er32(TCTL); tctl &= ~E1000_TCTL_EN; @@ -2339,6 +2344,9 @@ static void e1000_82547_tx_fifo_stall_task(struct work_struct *work) struct net_device *netdev = adapter->netdev; u32 tctl; + if (test_bit(__E1000_NOTX, &adapter->flags)) + return; + if (atomic_read(&adapter->tx_fifo_stall)) { if ((er32(TDT) == er32(TDH)) && (er32(TDFT) == er32(TDFH)) && @@ -2412,6 +2420,9 @@ static void e1000_watchdog(struct work_struct *work) struct e1000_tx_ring *txdr = adapter->tx_ring; u32 link, tctl; + if (test_bit(__E1000_NOTX, &adapter->flags)) + return; + link = e1000_has_link(adapter); if ((netif_carrier_ok(netdev)) && link) goto link_up;