From patchwork Tue Mar 5 19:46:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan Whitehead X-Patchwork-Id: 1051968 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=microchip.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44DS9l4zsJz9s3q for ; Wed, 6 Mar 2019 06:48:11 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726851AbfCETsK (ORCPT ); Tue, 5 Mar 2019 14:48:10 -0500 Received: from esa3.microchip.iphmx.com ([68.232.153.233]:42242 "EHLO esa3.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726256AbfCETsJ (ORCPT ); Tue, 5 Mar 2019 14:48:09 -0500 X-IronPort-AV: E=Sophos;i="5.58,445,1544511600"; d="scan'208";a="27696430" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa3.microchip.iphmx.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 05 Mar 2019 12:48:08 -0700 Received: from BW-Ubuntu-tester.mchp-main.com (10.10.76.4) by chn-sv-exch07.mchp-main.com (10.10.76.108) with Microsoft SMTP Server id 14.3.352.0; Tue, 5 Mar 2019 12:48:08 -0700 From: Bryan Whitehead To: CC: , Subject: [PATCH v1 net] lan743x: Fix RX Kernel Panic Date: Tue, 5 Mar 2019 14:46:04 -0500 Message-ID: <1551815164-17277-1-git-send-email-Bryan.Whitehead@microchip.com> X-Mailer: git-send-email 2.7.4 MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org It has been noticed that running the speed test at www.speedtest.net occasionally causes a kernel panic. Investigation revealed that under this test RX buffer allocation sometimes fails and returns NULL. But the lan743x driver did not handle this case. This patch fixes this issue by attempting to allocate a buffer before sending the new rx packet to the OS. If the allocation fails then the new rx packet is dropped and the existing buffer is reused in the DMA ring. Fixes: 23f0703c125b ("lan743x: Add main source files for new lan743x driver") Signed-off-by: Bryan Whitehead --- drivers/net/ethernet/microchip/lan743x_main.c | 45 +++++++++++++++++++++------ 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c index 4d1b4a2..3d33eaf 100644 --- a/drivers/net/ethernet/microchip/lan743x_main.c +++ b/drivers/net/ethernet/microchip/lan743x_main.c @@ -1902,7 +1902,17 @@ static int lan743x_rx_next_index(struct lan743x_rx *rx, int index) return ((++index) % rx->ring_size); } -static int lan743x_rx_allocate_ring_element(struct lan743x_rx *rx, int index) +static struct sk_buff *lan743x_rx_allocate_skb(struct lan743x_rx *rx) +{ + int length = 0; + + length = (LAN743X_MAX_FRAME_SIZE + ETH_HLEN + 4 + RX_HEAD_PADDING); + return __netdev_alloc_skb(rx->adapter->netdev, + length, GFP_ATOMIC | GFP_DMA); +} + +static int lan743x_rx_init_ring_element(struct lan743x_rx *rx, int index, + struct sk_buff *skb) { struct lan743x_rx_buffer_info *buffer_info; struct lan743x_rx_descriptor *descriptor; @@ -1911,9 +1921,7 @@ static int lan743x_rx_allocate_ring_element(struct lan743x_rx *rx, int index) length = (LAN743X_MAX_FRAME_SIZE + ETH_HLEN + 4 + RX_HEAD_PADDING); descriptor = &rx->ring_cpu_ptr[index]; buffer_info = &rx->buffer_info[index]; - buffer_info->skb = __netdev_alloc_skb(rx->adapter->netdev, - length, - GFP_ATOMIC | GFP_DMA); + buffer_info->skb = skb; if (!(buffer_info->skb)) return -ENOMEM; buffer_info->dma_ptr = dma_map_single(&rx->adapter->pdev->dev, @@ -2060,8 +2068,19 @@ static int lan743x_rx_process_packet(struct lan743x_rx *rx) /* packet is available */ if (first_index == last_index) { /* single buffer packet */ + struct sk_buff *new_skb = NULL; int packet_length; + new_skb = lan743x_rx_allocate_skb(rx); + if (!new_skb) { + /* failed to allocate next skb. + * Memory is very low. + * Drop this packet and reuse buffer. + */ + lan743x_rx_reuse_ring_element(rx, first_index); + goto process_extension; + } + buffer_info = &rx->buffer_info[first_index]; skb = buffer_info->skb; descriptor = &rx->ring_cpu_ptr[first_index]; @@ -2081,8 +2100,9 @@ static int lan743x_rx_process_packet(struct lan743x_rx *rx) skb_put(skb, packet_length - 4); skb->protocol = eth_type_trans(skb, rx->adapter->netdev); - lan743x_rx_allocate_ring_element(rx, first_index); + lan743x_rx_init_ring_element(rx, first_index, new_skb); } else { + struct sk_buff *new_skb = NULL; int index = first_index; /* multi buffer packet not supported */ @@ -2096,8 +2116,9 @@ static int lan743x_rx_process_packet(struct lan743x_rx *rx) (index <= last_index)) { lan743x_rx_release_ring_element(rx, index); - lan743x_rx_allocate_ring_element(rx, - index); + new_skb = lan743x_rx_allocate_skb(rx); + lan743x_rx_init_ring_element(rx, index, + new_skb); index = lan743x_rx_next_index(rx, index); } @@ -2106,14 +2127,16 @@ static int lan743x_rx_process_packet(struct lan743x_rx *rx) (index <= last_index)) { lan743x_rx_release_ring_element(rx, index); - lan743x_rx_allocate_ring_element(rx, - index); + new_skb = lan743x_rx_allocate_skb(rx); + lan743x_rx_init_ring_element(rx, index, + new_skb); index = lan743x_rx_next_index(rx, index); } } } +process_extension: if (extension_index >= 0) { descriptor = &rx->ring_cpu_ptr[extension_index]; buffer_info = &rx->buffer_info[extension_index]; @@ -2290,7 +2313,9 @@ static int lan743x_rx_ring_init(struct lan743x_rx *rx) rx->last_head = 0; for (index = 0; index < rx->ring_size; index++) { - ret = lan743x_rx_allocate_ring_element(rx, index); + struct sk_buff *new_skb = lan743x_rx_allocate_skb(rx); + + ret = lan743x_rx_init_ring_element(rx, index, new_skb); if (ret) goto cleanup; }