From patchwork Thu Jul 7 23:02:51 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iyappan Subramanian X-Patchwork-Id: 9219849 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 6D67C6048B for ; Thu, 7 Jul 2016 23:05:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5B80323B3C for ; Thu, 7 Jul 2016 23:05:06 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4F58C27BF7; Thu, 7 Jul 2016 23:05:06 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 8D61023B3C for ; Thu, 7 Jul 2016 23:05:05 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1bLIKW-0001rO-Bu; Thu, 07 Jul 2016 23:03:36 +0000 Received: from mail-pf0-x229.google.com ([2607:f8b0:400e:c00::229]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1bLIKB-0001fy-Gq for linux-arm-kernel@lists.infradead.org; Thu, 07 Jul 2016 23:03:18 +0000 Received: by mail-pf0-x229.google.com with SMTP id t190so9971095pfb.3 for ; Thu, 07 Jul 2016 16:02:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=apm.com; s=apm; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=GseT/tQQUIIu+vIGH4eha8YAqU1LaPJtnqi9LVo2Nmg=; b=omlumyIbOrUm4J5iutTOQsNXNP4MO8wi6/wX1nXPotW+hksfg9v2LdTPqWusgCbXVk oFjLBwJHVODrpKCT6rap7xRyjOtOQUj9EN8JJnd/ixV1PnEG8Cz15UnvluA9jOVliIzh n5yd+0Yv8+SZZgLvWxLVjXbPQR9R/v6yfj3o4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=GseT/tQQUIIu+vIGH4eha8YAqU1LaPJtnqi9LVo2Nmg=; b=c3yKVVadjstrFKgQzpyUdVKMQXax3B92vZrxaj+IwXv1XgzxZi7iDBL+LKXp0Q6AOX AfFwJ2ynjOXBRxfr6o9NC+LOM2Ygpk78NMsHRm0ApEUlBfTIXlDBMVtlZxwFKs1bmywx vLWXI/x9q+e5QJHUgRnNZOP0nyTzGgqkq1UFOpYTRBoAUjyx4MJYhkXVM+3+OGcid8rO yqxITKEQbPknRA8zAnlqLDu6FVeUajAX7VOx3X2yxEC+Y39fbGTZYNlcuzuVZZcVXVr1 6z0yJaGbYDYKQk20Bew+3eOAvLAk6rPfdux/lUZYvNBnqJAxT+F+7IC+V/lqTmaXLRC+ lmWw== X-Gm-Message-State: ALyK8tKYh3b28yfPL0BJjHNoJMyjOrsq3nYZjPsJJr7LVZxYuNAsLb8PSndKw7VSqrP0KzZg X-Received: by 10.98.106.133 with SMTP id f127mr4374172pfc.139.1467932576872; Thu, 07 Jul 2016 16:02:56 -0700 (PDT) Received: from isubrama-dev.amcc.com ([206.80.4.98]) by smtp.gmail.com with ESMTPSA id r67sm4637090pfb.16.2016.07.07.16.02.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 07 Jul 2016 16:02:56 -0700 (PDT) From: Iyappan Subramanian To: davem@davemloft.net, netdev@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v5 03/11] drivers: net: xgene: Fix module unload crash - change sw sequence Date: Thu, 7 Jul 2016 16:02:51 -0700 Message-Id: <1467932579-14320-4-git-send-email-isubramanian@apm.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1467932579-14320-1-git-send-email-isubramanian@apm.com> References: <1467932579-14320-1-git-send-email-isubramanian@apm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160707_160315_680537_B8B4EF67 X-CRM114-Status: GOOD ( 18.23 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: andrew@lunn.ch, patches@apm.com, linux@armlinux.org.uk, Iyappan Subramanian , matthias.bgg@gmail.com, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP When the driver is configured as kernel module and when it gets unloaded and reloaded, kernel crash was observed. This patch addresses the software cleanup by doing the following, - Moved register_netdev call after hardware is ready - Since ndev is not ready, added set_irq_name to set irq name - Since ndev is not ready, changed mdio_bus->parent to pdev->dev - Replaced netif_start(stop)_queue by netif_tx_start(stop)_queues - Removed napi_del call since it's called by free_netdev - Added dev_close call, within remove - Added shutdown callback - Changed to use dmam_ APIs Signed-off-by: Iyappan Subramanian Tested-by: Fushen Chen Tested-by: Toan Le Tested-by: Matthias Brugger --- drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 2 +- drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 120 ++++++++++++++--------- 2 files changed, 73 insertions(+), 49 deletions(-) diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c index 009fb8e..4f98749 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c @@ -901,7 +901,7 @@ int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata) ndev->name); mdio_bus->priv = pdata; - mdio_bus->parent = &ndev->dev; + mdio_bus->parent = &pdata->pdev->dev; ret = xgene_mdiobus_register(pdata, mdio_bus); if (ret) { diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c index f79950a..87e5929 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c @@ -608,6 +608,30 @@ static void xgene_enet_timeout(struct net_device *ndev) } } +static void xgene_enet_set_irq_name(struct net_device *ndev) +{ + struct xgene_enet_pdata *pdata = netdev_priv(ndev); + struct xgene_enet_desc_ring *ring; + int i; + + for (i = 0; i < pdata->rxq_cnt; i++) { + ring = pdata->rx_ring[i]; + if (!pdata->cq_cnt) { + snprintf(ring->irq_name, IRQ_ID_SIZE, "%s-rx-txc", + ndev->name); + } else { + snprintf(ring->irq_name, IRQ_ID_SIZE, "%s-rx-%d", + ndev->name, i); + } + } + + for (i = 0; i < pdata->cq_cnt; i++) { + ring = pdata->tx_ring[i]->cp_ring; + snprintf(ring->irq_name, IRQ_ID_SIZE, "%s-txc-%d", + ndev->name, i); + } +} + static int xgene_enet_register_irq(struct net_device *ndev) { struct xgene_enet_pdata *pdata = netdev_priv(ndev); @@ -615,6 +639,7 @@ static int xgene_enet_register_irq(struct net_device *ndev) struct xgene_enet_desc_ring *ring; int ret = 0, i; + xgene_enet_set_irq_name(ndev); for (i = 0; i < pdata->rxq_cnt; i++) { ring = pdata->rx_ring[i]; irq_set_status_flags(ring->irq, IRQ_DISABLE_UNLAZY); @@ -723,7 +748,7 @@ static int xgene_enet_open(struct net_device *ndev) mac_ops->tx_enable(pdata); mac_ops->rx_enable(pdata); - netif_start_queue(ndev); + netif_tx_start_all_queues(ndev); return ret; } @@ -734,7 +759,7 @@ static int xgene_enet_close(struct net_device *ndev) const struct xgene_mac_ops *mac_ops = pdata->mac_ops; int i; - netif_stop_queue(ndev); + netif_tx_stop_all_queues(ndev); mac_ops->tx_disable(pdata); mac_ops->rx_disable(pdata); @@ -759,7 +784,7 @@ static void xgene_enet_delete_ring(struct xgene_enet_desc_ring *ring) dev = ndev_to_dev(ring->ndev); pdata->ring_ops->clear(ring); - dma_free_coherent(dev, ring->size, ring->desc_addr, ring->dma); + dmam_free_coherent(dev, ring->size, ring->desc_addr, ring->dma); } static void xgene_enet_delete_desc_rings(struct xgene_enet_pdata *pdata) @@ -834,7 +859,7 @@ static void xgene_enet_free_desc_ring(struct xgene_enet_desc_ring *ring) if (ring->desc_addr) { pdata->ring_ops->clear(ring); - dma_free_coherent(dev, ring->size, ring->desc_addr, ring->dma); + dmam_free_coherent(dev, ring->size, ring->desc_addr, ring->dma); } devm_kfree(dev, ring); } @@ -892,9 +917,10 @@ static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring( struct net_device *ndev, u32 ring_num, enum xgene_enet_ring_cfgsize cfgsize, u32 ring_id) { - struct xgene_enet_desc_ring *ring; struct xgene_enet_pdata *pdata = netdev_priv(ndev); struct device *dev = ndev_to_dev(ndev); + struct xgene_enet_desc_ring *ring; + void *irq_mbox_addr; int size; size = xgene_enet_get_ring_size(dev, cfgsize); @@ -911,8 +937,8 @@ static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring( ring->cfgsize = cfgsize; ring->id = ring_id; - ring->desc_addr = dma_zalloc_coherent(dev, size, &ring->dma, - GFP_KERNEL); + ring->desc_addr = dmam_alloc_coherent(dev, size, &ring->dma, + GFP_KERNEL | __GFP_ZERO); if (!ring->desc_addr) { devm_kfree(dev, ring); return NULL; @@ -920,14 +946,16 @@ static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring( ring->size = size; if (is_irq_mbox_required(pdata, ring)) { - ring->irq_mbox_addr = dma_zalloc_coherent(dev, INTR_MBOX_SIZE, - &ring->irq_mbox_dma, GFP_KERNEL); - if (!ring->irq_mbox_addr) { - dma_free_coherent(dev, size, ring->desc_addr, - ring->dma); + irq_mbox_addr = dmam_alloc_coherent(dev, INTR_MBOX_SIZE, + &ring->irq_mbox_dma, + GFP_KERNEL | __GFP_ZERO); + if (!irq_mbox_addr) { + dmam_free_coherent(dev, size, ring->desc_addr, + ring->dma); devm_kfree(dev, ring); return NULL; } + ring->irq_mbox_addr = irq_mbox_addr; } ring->cmd_base = xgene_enet_ring_cmd_base(pdata, ring); @@ -988,6 +1016,7 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev) u8 eth_bufnum = pdata->eth_bufnum; u8 bp_bufnum = pdata->bp_bufnum; u16 ring_num = pdata->ring_num; + __le64 *exp_bufs; u16 ring_id; int i, ret, size; @@ -1019,13 +1048,6 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev) rx_ring->nbufpool = NUM_BUFPOOL; rx_ring->buf_pool = buf_pool; rx_ring->irq = pdata->irqs[i]; - if (!pdata->cq_cnt) { - snprintf(rx_ring->irq_name, IRQ_ID_SIZE, "%s-rx-txc", - ndev->name); - } else { - snprintf(rx_ring->irq_name, IRQ_ID_SIZE, "%s-rx%d", - ndev->name, i); - } buf_pool->rx_skb = devm_kcalloc(dev, buf_pool->slots, sizeof(struct sk_buff *), GFP_KERNEL); @@ -1052,13 +1074,13 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev) } size = (tx_ring->slots / 2) * sizeof(__le64) * MAX_EXP_BUFFS; - tx_ring->exp_bufs = dma_zalloc_coherent(dev, size, - &dma_exp_bufs, - GFP_KERNEL); - if (!tx_ring->exp_bufs) { + exp_bufs = dmam_alloc_coherent(dev, size, &dma_exp_bufs, + GFP_KERNEL | __GFP_ZERO); + if (!exp_bufs) { ret = -ENOMEM; goto err; } + tx_ring->exp_bufs = exp_bufs; pdata->tx_ring[i] = tx_ring; @@ -1078,8 +1100,6 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev) cp_ring->irq = pdata->irqs[pdata->rxq_cnt + i]; cp_ring->index = i; - snprintf(cp_ring->irq_name, IRQ_ID_SIZE, "%s-txc%d", - ndev->name, i); } cp_ring->cp_skb = devm_kcalloc(dev, tx_ring->slots, @@ -1549,22 +1569,6 @@ static void xgene_enet_napi_add(struct xgene_enet_pdata *pdata) } } -static void xgene_enet_napi_del(struct xgene_enet_pdata *pdata) -{ - struct napi_struct *napi; - int i; - - for (i = 0; i < pdata->rxq_cnt; i++) { - napi = &pdata->rx_ring[i]->napi; - netif_napi_del(napi); - } - - for (i = 0; i < pdata->cq_cnt; i++) { - napi = &pdata->tx_ring[i]->cp_ring->napi; - netif_napi_del(napi); - } -} - static int xgene_enet_probe(struct platform_device *pdev) { struct net_device *ndev; @@ -1628,12 +1632,6 @@ static int xgene_enet_probe(struct platform_device *pdev) goto err; } - ret = register_netdev(ndev); - if (ret) { - netdev_err(ndev, "Failed to register netdev\n"); - goto err; - } - ret = xgene_enet_init_hw(pdata); if (ret) goto err_netdev; @@ -1648,7 +1646,14 @@ static int xgene_enet_probe(struct platform_device *pdev) } xgene_enet_napi_add(pdata); + ret = register_netdev(ndev); + if (ret) { + netdev_err(ndev, "Failed to register netdev\n"); + goto err; + } + return 0; + err_netdev: unregister_netdev(ndev); err: @@ -1666,10 +1671,14 @@ static int xgene_enet_remove(struct platform_device *pdev) mac_ops = pdata->mac_ops; ndev = pdata->ndev; + rtnl_lock(); + if (netif_running(ndev)) + dev_close(ndev); + rtnl_unlock(); + mac_ops->rx_disable(pdata); mac_ops->tx_disable(pdata); - xgene_enet_napi_del(pdata); if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) xgene_enet_mdio_remove(pdata); unregister_netdev(ndev); @@ -1680,6 +1689,20 @@ static int xgene_enet_remove(struct platform_device *pdev) return 0; } +static void xgene_enet_shutdown(struct platform_device *pdev) +{ + struct xgene_enet_pdata *pdata; + + pdata = platform_get_drvdata(pdev); + if (!pdata) + return; + + if (!pdata->ndev) + return; + + xgene_enet_remove(pdev); +} + #ifdef CONFIG_ACPI static const struct acpi_device_id xgene_enet_acpi_match[] = { { "APMC0D05", XGENE_ENET1}, @@ -1714,6 +1737,7 @@ static struct platform_driver xgene_enet_driver = { }, .probe = xgene_enet_probe, .remove = xgene_enet_remove, + .shutdown = xgene_enet_shutdown, }; module_platform_driver(xgene_enet_driver);