From patchwork Thu Jul 7 00:35:04 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iyappan Subramanian X-Patchwork-Id: 9217467 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 D298A607D9 for ; Thu, 7 Jul 2016 00:37:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C2FD528578 for ; Thu, 7 Jul 2016 00:37:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B754528590; Thu, 7 Jul 2016 00:37:37 +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 21EB728578 for ; Thu, 7 Jul 2016 00:37:37 +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 1bKxIY-0000EP-O1; Thu, 07 Jul 2016 00:36:10 +0000 Received: from mail-pa0-x230.google.com ([2607:f8b0:400e:c03::230]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1bKxI5-0008Cx-QN for linux-arm-kernel@lists.infradead.org; Thu, 07 Jul 2016 00:35:44 +0000 Received: by mail-pa0-x230.google.com with SMTP id dx3so1017436pab.2 for ; Wed, 06 Jul 2016 17:35:21 -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=lREfGar7TgXZdcCNJIF5vZwqwooGgiYlEQylujYw3r+KYAHFCcOPSRreLXdS4+JYJr CprSrzidEZskNrE9GjT8FxMl80ZWCFnTkBh5iminLu03m9+3KAI31+kUFL5OAJiUuaAL nu56j/Qx98NIVyTIu6Ht5wXbM3GOEthBwUzyU= 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=mgKeos7F46pvn2XCkx/SzN9rPZ1eHMkF4AUXuXrccsb8tQEXkMrvoUprkQRMx7JqBU L65Gj1VHAWeXp0tMD3qbsQCF8NnO3eMlZHBC/DELdWQbi6U3rKI7Pd4qMMDW1ZQhuFTL H9Zf4WcC3tNqc01tmhOl1yLbji6Oik5kbZxv7TddzQcWLV7ku/4dP0/j1jv39TlDrlQ8 vBLz9iSVrCEd75uJOpqWp6DT9oFGyBDPFAC1/z2WykEfUL/erKNC0pn8cE+v6Dtoaxc2 2roAx5k86tlhd80X1ZrPAxuc9CPRcLvARkZTmcUuz/Y4GMrj5hvH7tY1dhQfapKSJa2i 6fIA== X-Gm-Message-State: ALyK8tLmptQJzVbUytqHmgHeg/m6aG1LiuqduYdEuYMYDtFww+mnz9leuIfzkee7pbx/Wdfy X-Received: by 10.67.7.199 with SMTP id de7mr46595984pad.94.1467851720823; Wed, 06 Jul 2016 17:35:20 -0700 (PDT) Received: from isubrama-dev.amcc.com ([206.80.4.98]) by smtp.gmail.com with ESMTPSA id p63sm6769956pfp.65.2016.07.06.17.35.19 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 06 Jul 2016 17:35:20 -0700 (PDT) From: Iyappan Subramanian To: davem@davemloft.net, netdev@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v4 03/11] drivers: net: xgene: Fix module unload crash - change sw sequence Date: Wed, 6 Jul 2016 17:35:04 -0700 Message-Id: <1467851712-24780-4-git-send-email-isubramanian@apm.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1467851712-24780-1-git-send-email-isubramanian@apm.com> References: <1467851712-24780-1-git-send-email-isubramanian@apm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160706_173542_119577_2C02D287 X-CRM114-Status: GOOD ( 19.12 ) 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: matthias.bgg@gmail.com, andrew@lunn.ch, patches@apm.com, linux-arm-kernel@lists.infradead.org, Iyappan Subramanian 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);