From patchwork Thu Nov 13 07:05:00 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshihiro Kaneko X-Patchwork-Id: 5293921 X-Patchwork-Delegate: geert@linux-m68k.org Return-Path: X-Original-To: patchwork-linux-sh@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 0E86E9F440 for ; Thu, 13 Nov 2014 07:05:52 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2B5A3201C7 for ; Thu, 13 Nov 2014 07:05:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 202C2201E4 for ; Thu, 13 Nov 2014 07:05:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751467AbaKMHFo (ORCPT ); Thu, 13 Nov 2014 02:05:44 -0500 Received: from mail-pa0-f51.google.com ([209.85.220.51]:36007 "EHLO mail-pa0-f51.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753861AbaKMHFf (ORCPT ); Thu, 13 Nov 2014 02:05:35 -0500 Received: by mail-pa0-f51.google.com with SMTP id kq14so14810033pab.38 for ; Wed, 12 Nov 2014 23:05:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=KXV/tu3RqTGuwtdutWYWvq+KKQPBOvzrWtkosTI5rro=; b=lfNfEYu6b15Acn1fuMNdWvLfSwTRkB63bP0QiPk1KH8UX+PmOo5IdZRbEgP9XLmeqJ Rl6d9j6pS/SsEPYrePQ/hA4EsALhAsrGNtX/xevVhmH/d+265y8ZpMn0c53L+c4amGJ7 F1c4/UGatA4brSM0lqVmaqWm4HOFQPc8Kh/iKoeFKhysWkmA9fCJoPjhEgwkcUqf9s9w Rf4jEGnn95rn6hgzEomvKm2FpcTA7PKFuAwVujjNr2c/x8wcw8zh5qgB3FIzhF8CzBLK npYEb4iNc/LP8DkNugZcfJe4LopHrRMYCZMFZOQjmTqRUZrfkXU35lxxCQtminlf1SeI jnxA== X-Received: by 10.68.78.99 with SMTP id a3mr869319pbx.0.1415862335083; Wed, 12 Nov 2014 23:05:35 -0800 (PST) Received: from localhost.localdomain (p5095-ipngn6701marunouchi.tokyo.ocn.ne.jp. [153.174.4.95]) by mx.google.com with ESMTPSA id pv7sm6847309pdb.69.2014.11.12.23.05.33 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 12 Nov 2014 23:05:34 -0800 (PST) From: Yoshihiro Kaneko To: netdev@vger.kernel.org Cc: "David S. Miller" , Simon Horman , Magnus Damm , linux-sh@vger.kernel.org Subject: [PATCH 2/3] sh_eth: Fix skb alloc size and alignment adjust rule. Date: Thu, 13 Nov 2014 16:05:00 +0900 Message-Id: <1415862301-28032-3-git-send-email-ykaneko0929@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1415862301-28032-1-git-send-email-ykaneko0929@gmail.com> References: <1415862301-28032-1-git-send-email-ykaneko0929@gmail.com> Sender: linux-sh-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sh@vger.kernel.org X-Spam-Status: No, score=-7.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Mitsuhiro Kimura In the current driver, allocation size of skb does not care the alignment adjust after allocation. And also, in the current implementation, buffer alignment method by sh_eth_set_receive_align function has a bug that this function displace buffer start address forcedly when the alignment is corrected. In the result, tail of the skb will exceed allocated area and kernel panic will be occurred. This patch fix this issue. Signed-off-by: Mitsuhiro Kimura Signed-off-by: Yoshihiro Kaneko --- drivers/net/ethernet/renesas/sh_eth.c | 35 ++++++++++++++--------------------- drivers/net/ethernet/renesas/sh_eth.h | 2 ++ 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 49e963e..0e4a407 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -917,21 +917,12 @@ static int sh_eth_reset(struct net_device *ndev) return ret; } -#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) static void sh_eth_set_receive_align(struct sk_buff *skb) { - int reserve; - - reserve = SH4_SKB_RX_ALIGN - ((u32)skb->data & (SH4_SKB_RX_ALIGN - 1)); + u32 reserve = (u32)skb->data & (SH_ETH_RX_ALIGN - 1); if (reserve) - skb_reserve(skb, reserve); -} -#else -static void sh_eth_set_receive_align(struct sk_buff *skb) -{ - skb_reserve(skb, SH2_SH3_SKB_RX_ALIGN); + skb_reserve(skb, SH_ETH_RX_ALIGN - reserve); } -#endif /* CPU <-> EDMAC endian convert */ @@ -1119,6 +1110,7 @@ static void sh_eth_ring_format(struct net_device *ndev) struct sh_eth_txdesc *txdesc = NULL; int rx_ringsize = sizeof(*rxdesc) * mdp->num_rx_ring; int tx_ringsize = sizeof(*txdesc) * mdp->num_tx_ring; + int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN - 1; mdp->cur_rx = 0; mdp->cur_tx = 0; @@ -1131,21 +1123,21 @@ static void sh_eth_ring_format(struct net_device *ndev) for (i = 0; i < mdp->num_rx_ring; i++) { /* skb */ mdp->rx_skbuff[i] = NULL; - skb = netdev_alloc_skb(ndev, mdp->rx_buf_sz); + skb = netdev_alloc_skb(ndev, skbuff_size); mdp->rx_skbuff[i] = skb; if (skb == NULL) break; - dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz, - DMA_FROM_DEVICE); sh_eth_set_receive_align(skb); /* RX descriptor */ rxdesc = &mdp->rx_ring[i]; + /* The size of the buffer is 16 byte boundary. */ + rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16); + dma_map_single(&ndev->dev, skb->data, rxdesc->buffer_length, + DMA_FROM_DEVICE); rxdesc->addr = virt_to_phys(skb->data); rxdesc->status = cpu_to_edmac(mdp, RD_RACT | RD_RFP); - /* The size of the buffer is 16 byte boundary. */ - rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16); /* Rx descriptor address set */ if (i == 0) { sh_eth_write(ndev, mdp->rx_desc_dma, RDLAR); @@ -1397,6 +1389,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) struct sk_buff *skb; u16 pkt_len = 0; u32 desc_status; + int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN - 1; rxdesc = &mdp->rx_ring[entry]; while (!(rxdesc->status & cpu_to_edmac(mdp, RD_RACT))) { @@ -1448,8 +1441,8 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) if (mdp->cd->rpadir) skb_reserve(skb, NET_IP_ALIGN); dma_sync_single_for_cpu(&ndev->dev, rxdesc->addr, - mdp->rx_buf_sz, - DMA_FROM_DEVICE); + ALIGN(mdp->rx_buf_sz, 16), + DMA_FROM_DEVICE); skb_put(skb, pkt_len); skb->protocol = eth_type_trans(skb, ndev); netif_receive_skb(skb); @@ -1468,13 +1461,13 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16); if (mdp->rx_skbuff[entry] == NULL) { - skb = netdev_alloc_skb(ndev, mdp->rx_buf_sz); + skb = netdev_alloc_skb(ndev, skbuff_size); mdp->rx_skbuff[entry] = skb; if (skb == NULL) break; /* Better luck next round. */ - dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz, - DMA_FROM_DEVICE); sh_eth_set_receive_align(skb); + dma_map_single(&ndev->dev, skb->data, + rxdesc->buffer_length, DMA_FROM_DEVICE); skb_checksum_none_assert(skb); rxdesc->addr = virt_to_phys(skb->data); diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index b37c427..d138ebe 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -163,8 +163,10 @@ enum { /* Driver's parameters */ #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) #define SH4_SKB_RX_ALIGN 32 +#define SH_ETH_RX_ALIGN (SH4_SKB_RX_ALIGN) #else #define SH2_SH3_SKB_RX_ALIGN 2 +#define SH_ETH_RX_ALIGN (SH2_SH3_SKB_RX_ALIGN) #endif /* Register's bits