From patchwork Sun May 17 00:33:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 219094 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6237BC433E0 for ; Sun, 17 May 2020 00:34:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4885F206D8 for ; Sun, 17 May 2020 00:34:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727001AbgEQAep (ORCPT ); Sat, 16 May 2020 20:34:45 -0400 Received: from mail-out.m-online.net ([212.18.0.10]:50861 "EHLO mail-out.m-online.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726946AbgEQAej (ORCPT ); Sat, 16 May 2020 20:34:39 -0400 Received: from frontend01.mail.m-online.net (unknown [192.168.8.182]) by mail-out.m-online.net (Postfix) with ESMTP id 49Pjp04q8tz1rqr6; Sun, 17 May 2020 02:34:25 +0200 (CEST) Received: from localhost (dynscan1.mnet-online.de [192.168.6.70]) by mail.m-online.net (Postfix) with ESMTP id 49Pjns2pM7z1shfs; Sun, 17 May 2020 02:34:25 +0200 (CEST) X-Virus-Scanned: amavisd-new at mnet-online.de Received: from mail.mnet-online.de ([192.168.8.182]) by localhost (dynscan1.mail.m-online.net [192.168.6.70]) (amavisd-new, port 10024) with ESMTP id MWoudioxiKIz; Sun, 17 May 2020 02:34:24 +0200 (CEST) X-Auth-Info: kOk8EHtrm0Ap5qSCGzXQMefNHUAONg8JWq3EK+XZBD4= Received: from desktop.lan (ip-86-49-35-8.net.upcbroadband.cz [86.49.35.8]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.mnet-online.de (Postfix) with ESMTPSA; Sun, 17 May 2020 02:34:24 +0200 (CEST) From: Marek Vasut To: netdev@vger.kernel.org Cc: Marek Vasut , Andrew Lunn , "David S . Miller" , Lukas Wunner , Petr Stetiar , YueHaibing Subject: [PATCH V6 02/20] net: ks8851: Rename ndev to netdev in probe Date: Sun, 17 May 2020 02:33:36 +0200 Message-Id: <20200517003354.233373-3-marex@denx.de> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200517003354.233373-1-marex@denx.de> References: <20200517003354.233373-1-marex@denx.de> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Rename ndev variable to netdev for the sake of consistency. No functional change. Reviewed-by: Andrew Lunn Signed-off-by: Marek Vasut Cc: David S. Miller Cc: Lukas Wunner Cc: Petr Stetiar Cc: YueHaibing --- V2: New patch V3: No change V4: No change V5: No change V6: No change --- drivers/net/ethernet/micrel/ks8851.c | 30 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c index e32ef9403803..2b85072993c5 100644 --- a/drivers/net/ethernet/micrel/ks8851.c +++ b/drivers/net/ethernet/micrel/ks8851.c @@ -1414,21 +1414,21 @@ static SIMPLE_DEV_PM_OPS(ks8851_pm_ops, ks8851_suspend, ks8851_resume); static int ks8851_probe(struct spi_device *spi) { struct device *dev = &spi->dev; - struct net_device *ndev; + struct net_device *netdev; struct ks8851_net *ks; int ret; unsigned cider; int gpio; - ndev = alloc_etherdev(sizeof(struct ks8851_net)); - if (!ndev) + netdev = alloc_etherdev(sizeof(struct ks8851_net)); + if (!netdev) return -ENOMEM; spi->bits_per_word = 8; - ks = netdev_priv(ndev); + ks = netdev_priv(netdev); - ks->netdev = ndev; + ks->netdev = netdev; ks->spidev = spi; ks->tx_space = 6144; @@ -1500,7 +1500,7 @@ static int ks8851_probe(struct spi_device *spi) ks->eeprom.register_write = ks8851_eeprom_regwrite; /* setup mii state */ - ks->mii.dev = ndev; + ks->mii.dev = netdev; ks->mii.phy_id = 1, ks->mii.phy_id_mask = 1; ks->mii.reg_num_mask = 0xf; @@ -1516,15 +1516,15 @@ static int ks8851_probe(struct spi_device *spi) skb_queue_head_init(&ks->txq); - ndev->ethtool_ops = &ks8851_ethtool_ops; - SET_NETDEV_DEV(ndev, dev); + netdev->ethtool_ops = &ks8851_ethtool_ops; + SET_NETDEV_DEV(netdev, dev); spi_set_drvdata(spi, ks); netif_carrier_off(ks->netdev); - ndev->if_port = IF_PORT_100BASET; - ndev->netdev_ops = &ks8851_netdev_ops; - ndev->irq = spi->irq; + netdev->if_port = IF_PORT_100BASET; + netdev->netdev_ops = &ks8851_netdev_ops; + netdev->irq = spi->irq; /* issue a global soft reset to reset the device. */ ks8851_soft_reset(ks, GRR_GSR); @@ -1543,14 +1543,14 @@ static int ks8851_probe(struct spi_device *spi) ks8851_read_selftest(ks); ks8851_init_mac(ks); - ret = register_netdev(ndev); + ret = register_netdev(netdev); if (ret) { dev_err(dev, "failed to register network device\n"); goto err_netdev; } - netdev_info(ndev, "revision %d, MAC %pM, IRQ %d, %s EEPROM\n", - CIDER_REV_GET(cider), ndev->dev_addr, ndev->irq, + netdev_info(netdev, "revision %d, MAC %pM, IRQ %d, %s EEPROM\n", + CIDER_REV_GET(cider), netdev->dev_addr, netdev->irq, ks->rc_ccr & CCR_EEPROM ? "has" : "no"); return 0; @@ -1564,7 +1564,7 @@ static int ks8851_probe(struct spi_device *spi) regulator_disable(ks->vdd_io); err_reg_io: err_gpio: - free_netdev(ndev); + free_netdev(netdev); return ret; } From patchwork Sun May 17 00:33:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 219095 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9E8F1C433DF for ; Sun, 17 May 2020 00:34:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 84D63206D8 for ; Sun, 17 May 2020 00:34:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726990AbgEQAek (ORCPT ); Sat, 16 May 2020 20:34:40 -0400 Received: from mail-out.m-online.net ([212.18.0.10]:45786 "EHLO mail-out.m-online.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726976AbgEQAeh (ORCPT ); Sat, 16 May 2020 20:34:37 -0400 Received: from frontend01.mail.m-online.net (unknown [192.168.8.182]) by mail-out.m-online.net (Postfix) with ESMTP id 49Pjp04Qr5z1rqqS; Sun, 17 May 2020 02:34:27 +0200 (CEST) Received: from localhost (dynscan1.mnet-online.de [192.168.6.70]) by mail.m-online.net (Postfix) with ESMTP id 49Pjnv5zFYz1shfq; Sun, 17 May 2020 02:34:27 +0200 (CEST) X-Virus-Scanned: amavisd-new at mnet-online.de Received: from mail.mnet-online.de ([192.168.8.182]) by localhost (dynscan1.mail.m-online.net [192.168.6.70]) (amavisd-new, port 10024) with ESMTP id SLIsk5wIoRZ3; Sun, 17 May 2020 02:34:26 +0200 (CEST) X-Auth-Info: DJM1rpAXtC2x9Ktf8PLqoWqw7HxXcSgR7ESWu3uO+7s= Received: from desktop.lan (ip-86-49-35-8.net.upcbroadband.cz [86.49.35.8]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.mnet-online.de (Postfix) with ESMTPSA; Sun, 17 May 2020 02:34:26 +0200 (CEST) From: Marek Vasut To: netdev@vger.kernel.org Cc: Marek Vasut , "David S . Miller" , Lukas Wunner , Petr Stetiar , YueHaibing Subject: [PATCH V6 04/20] net: ks8851: Pass device node into ks8851_init_mac() Date: Sun, 17 May 2020 02:33:38 +0200 Message-Id: <20200517003354.233373-5-marex@denx.de> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200517003354.233373-1-marex@denx.de> References: <20200517003354.233373-1-marex@denx.de> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Since the driver probe function already has a struct device *dev pointer and can easily derive of_node pointer from it, pass the of_node pointer as a parameter to ks8851_init_mac() to avoid fishing it out from ks->spidev. This is the only reference to spidev in the function, so get rid of it. This is done in preparation for unifying the KS8851 SPI and parallel bus drivers. No functional change. Signed-off-by: Marek Vasut Cc: David S. Miller Cc: Lukas Wunner Cc: Petr Stetiar Cc: YueHaibing --- V2: Pass in of_node instead of the entire device pointer V3: No change V4: No change V5: No change V6: Update the function kerneldoc to reflect the params --- drivers/net/ethernet/micrel/ks8851.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c index 0088df970ad6..582092a95afc 100644 --- a/drivers/net/ethernet/micrel/ks8851.c +++ b/drivers/net/ethernet/micrel/ks8851.c @@ -409,6 +409,7 @@ static void ks8851_read_mac_addr(struct net_device *dev) /** * ks8851_init_mac - initialise the mac address * @ks: The device structure + * @np: The device node pointer * * Get or create the initial mac address for the device and then set that * into the station address register. A mac address supplied in the device @@ -416,12 +417,12 @@ static void ks8851_read_mac_addr(struct net_device *dev) * we try that. If no valid mac address is found we use eth_random_addr() * to create a new one. */ -static void ks8851_init_mac(struct ks8851_net *ks) +static void ks8851_init_mac(struct ks8851_net *ks, struct device_node *np) { struct net_device *dev = ks->netdev; const u8 *mac_addr; - mac_addr = of_get_mac_address(ks->spidev->dev.of_node); + mac_addr = of_get_mac_address(np); if (!IS_ERR(mac_addr)) { ether_addr_copy(dev->dev_addr, mac_addr); ks8851_write_mac_addr(dev); @@ -1541,7 +1542,7 @@ static int ks8851_probe(struct spi_device *spi) ks->rc_ccr = ks8851_rdreg16(ks, KS_CCR); ks8851_read_selftest(ks); - ks8851_init_mac(ks); + ks8851_init_mac(ks, dev->of_node); ret = register_netdev(netdev); if (ret) { From patchwork Sun May 17 00:33:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 219097 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B4A50C433E1 for ; Sun, 17 May 2020 00:34:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8FE762075F for ; Sun, 17 May 2020 00:34:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726936AbgEQAec (ORCPT ); Sat, 16 May 2020 20:34:32 -0400 Received: from mail-out.m-online.net ([212.18.0.9]:34067 "EHLO mail-out.m-online.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726763AbgEQAeb (ORCPT ); Sat, 16 May 2020 20:34:31 -0400 Received: from frontend01.mail.m-online.net (unknown [192.168.8.182]) by mail-out.m-online.net (Postfix) with ESMTP id 49Pjnx1hhwz1qrMH; Sun, 17 May 2020 02:34:29 +0200 (CEST) Received: from localhost (dynscan1.mnet-online.de [192.168.6.70]) by mail.m-online.net (Postfix) with ESMTP id 49Pjnx1TxDz1shfr; Sun, 17 May 2020 02:34:29 +0200 (CEST) X-Virus-Scanned: amavisd-new at mnet-online.de Received: from mail.mnet-online.de ([192.168.8.182]) by localhost (dynscan1.mail.m-online.net [192.168.6.70]) (amavisd-new, port 10024) with ESMTP id vP8jPZUfyOiX; Sun, 17 May 2020 02:34:28 +0200 (CEST) X-Auth-Info: ICBcEC2kUp+DpHtXqWaBaMN+oGof4ra42mLjarvSuo4= Received: from desktop.lan (ip-86-49-35-8.net.upcbroadband.cz [86.49.35.8]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.mnet-online.de (Postfix) with ESMTPSA; Sun, 17 May 2020 02:34:27 +0200 (CEST) From: Marek Vasut To: netdev@vger.kernel.org Cc: Marek Vasut , Andrew Lunn , "David S . Miller" , Lukas Wunner , Petr Stetiar , YueHaibing Subject: [PATCH V6 05/20] net: ks8851: Use devm_alloc_etherdev() Date: Sun, 17 May 2020 02:33:39 +0200 Message-Id: <20200517003354.233373-6-marex@denx.de> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200517003354.233373-1-marex@denx.de> References: <20200517003354.233373-1-marex@denx.de> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Use device managed version of alloc_etherdev() to simplify the code. No functional change intended. Reviewed-by: Andrew Lunn Signed-off-by: Marek Vasut Cc: David S. Miller Cc: Lukas Wunner Cc: Petr Stetiar Cc: YueHaibing --- V2: Add RB from Andrew V3: No change V4: No change V5: No change V6: No change --- drivers/net/ethernet/micrel/ks8851.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c index 582092a95afc..86bfe55f346d 100644 --- a/drivers/net/ethernet/micrel/ks8851.c +++ b/drivers/net/ethernet/micrel/ks8851.c @@ -1421,7 +1421,7 @@ static int ks8851_probe(struct spi_device *spi) unsigned cider; int gpio; - netdev = alloc_etherdev(sizeof(struct ks8851_net)); + netdev = devm_alloc_etherdev(dev, sizeof(struct ks8851_net)); if (!netdev) return -ENOMEM; @@ -1434,10 +1434,8 @@ static int ks8851_probe(struct spi_device *spi) ks->tx_space = 6144; gpio = of_get_named_gpio_flags(dev->of_node, "reset-gpios", 0, NULL); - if (gpio == -EPROBE_DEFER) { - ret = gpio; - goto err_gpio; - } + if (gpio == -EPROBE_DEFER) + return gpio; ks->gpio = gpio; if (gpio_is_valid(gpio)) { @@ -1445,7 +1443,7 @@ static int ks8851_probe(struct spi_device *spi) GPIOF_OUT_INIT_LOW, "ks8851_rst_n"); if (ret) { dev_err(dev, "reset gpio request failed\n"); - goto err_gpio; + return ret; } } @@ -1564,8 +1562,6 @@ static int ks8851_probe(struct spi_device *spi) err_reg: regulator_disable(ks->vdd_io); err_reg_io: -err_gpio: - free_netdev(netdev); return ret; } @@ -1582,7 +1578,6 @@ static int ks8851_remove(struct spi_device *spi) gpio_set_value(priv->gpio, 0); regulator_disable(priv->vdd_reg); regulator_disable(priv->vdd_io); - free_netdev(priv->netdev); return 0; } From patchwork Sun May 17 00:33:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 219096 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B2D0EC433E3 for ; Sun, 17 May 2020 00:34:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9C20A206D8 for ; Sun, 17 May 2020 00:34:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726982AbgEQAeh (ORCPT ); Sat, 16 May 2020 20:34:37 -0400 Received: from mail-out.m-online.net ([212.18.0.9]:60827 "EHLO mail-out.m-online.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726946AbgEQAeg (ORCPT ); Sat, 16 May 2020 20:34:36 -0400 Received: from frontend01.mail.m-online.net (unknown [192.168.8.182]) by mail-out.m-online.net (Postfix) with ESMTP id 49Pjp242M3z1qrLN; Sun, 17 May 2020 02:34:34 +0200 (CEST) Received: from localhost (dynscan1.mnet-online.de [192.168.6.70]) by mail.m-online.net (Postfix) with ESMTP id 49Pjp23RFKz1shfq; Sun, 17 May 2020 02:34:34 +0200 (CEST) X-Virus-Scanned: amavisd-new at mnet-online.de Received: from mail.mnet-online.de ([192.168.8.182]) by localhost (dynscan1.mail.m-online.net [192.168.6.70]) (amavisd-new, port 10024) with ESMTP id WzxEyIqsC0qd; Sun, 17 May 2020 02:34:33 +0200 (CEST) X-Auth-Info: qd37Ykqs6SyfiVLKZhrLbvrUMlkMV5foq/wz/1T+6RE= Received: from desktop.lan (ip-86-49-35-8.net.upcbroadband.cz [86.49.35.8]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.mnet-online.de (Postfix) with ESMTPSA; Sun, 17 May 2020 02:34:33 +0200 (CEST) From: Marek Vasut To: netdev@vger.kernel.org Cc: Marek Vasut , "David S . Miller" , Lukas Wunner , Petr Stetiar , YueHaibing Subject: [PATCH V6 09/20] net: ks8851: Use 16-bit read of RXFC register Date: Sun, 17 May 2020 02:33:43 +0200 Message-Id: <20200517003354.233373-10-marex@denx.de> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200517003354.233373-1-marex@denx.de> References: <20200517003354.233373-1-marex@denx.de> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The RXFC register is the only one being read using 8-bit accessors. To make it easier to support the 16-bit accesses used by the parallel bus variant of KS8851, use 16-bit accessor to read RXFC register as well as neighboring RXFCTR register. Remove ks8851_rdreg8() as it is not used anywhere anymore. There should be no functional change. Signed-off-by: Marek Vasut Cc: David S. Miller Cc: Lukas Wunner Cc: Petr Stetiar Cc: YueHaibing --- V2: No change V3: No change V4: Drop the NOTE from the comment, the performance is OK V5: No change V6: No change --- drivers/net/ethernet/micrel/ks8851.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c index 1b81340e811f..e2e75041e931 100644 --- a/drivers/net/ethernet/micrel/ks8851.c +++ b/drivers/net/ethernet/micrel/ks8851.c @@ -236,21 +236,6 @@ static void ks8851_rdreg(struct ks8851_net *ks, unsigned op, memcpy(rxb, trx + 2, rxl); } -/** - * ks8851_rdreg8 - read 8 bit register from device - * @ks: The chip information - * @reg: The register address - * - * Read a 8bit register from the chip, returning the result -*/ -static unsigned ks8851_rdreg8(struct ks8851_net *ks, unsigned reg) -{ - u8 rxb[1]; - - ks8851_rdreg(ks, MK_OP(1 << (reg & 3), reg), rxb, 1); - return rxb[0]; -} - /** * ks8851_rdreg16 - read 16 bit register from device * @ks: The chip information @@ -470,7 +455,7 @@ static void ks8851_rx_pkts(struct ks8851_net *ks) unsigned rxstat; u8 *rxpkt; - rxfc = ks8851_rdreg8(ks, KS_RXFC); + rxfc = (ks8851_rdreg16(ks, KS_RXFCTR) >> 8) & 0xff; netif_dbg(ks, rx_status, ks->netdev, "%s: %d packets\n", __func__, rxfc); From patchwork Sun May 17 00:33:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 219088 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DAF85C433E0 for ; Sun, 17 May 2020 00:35:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BF3E1206F4 for ; Sun, 17 May 2020 00:35:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727010AbgEQAev (ORCPT ); Sat, 16 May 2020 20:34:51 -0400 Received: from mail-out.m-online.net ([212.18.0.10]:50861 "EHLO mail-out.m-online.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726987AbgEQAem (ORCPT ); Sat, 16 May 2020 20:34:42 -0400 Received: from frontend01.mail.m-online.net (unknown [192.168.8.182]) by mail-out.m-online.net (Postfix) with ESMTP id 49Pjp4222Fz1rrKs; Sun, 17 May 2020 02:34:36 +0200 (CEST) Received: from localhost (dynscan1.mnet-online.de [192.168.6.70]) by mail.m-online.net (Postfix) with ESMTP id 49Pjp41gPtz1shfq; Sun, 17 May 2020 02:34:36 +0200 (CEST) X-Virus-Scanned: amavisd-new at mnet-online.de Received: from mail.mnet-online.de ([192.168.8.182]) by localhost (dynscan1.mail.m-online.net [192.168.6.70]) (amavisd-new, port 10024) with ESMTP id V5x9evugT6r8; Sun, 17 May 2020 02:34:34 +0200 (CEST) X-Auth-Info: S9i3bATLU0MbVzIVU4rqvz+JKX9cvCm34ZzZRo1VHZM= Received: from desktop.lan (ip-86-49-35-8.net.upcbroadband.cz [86.49.35.8]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.mnet-online.de (Postfix) with ESMTPSA; Sun, 17 May 2020 02:34:34 +0200 (CEST) From: Marek Vasut To: netdev@vger.kernel.org Cc: Marek Vasut , Andrew Lunn , "David S . Miller" , Lukas Wunner , Petr Stetiar , YueHaibing Subject: [PATCH V6 10/20] net: ks8851: Factor out bus lock handling Date: Sun, 17 May 2020 02:33:44 +0200 Message-Id: <20200517003354.233373-11-marex@denx.de> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200517003354.233373-1-marex@denx.de> References: <20200517003354.233373-1-marex@denx.de> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Pull out bus access locking code into separate functions, this is done in preparation for unifying the driver with the parallel bus one. The parallel bus driver does not need heavy mutex locking of the bus and works better with spinlocks, hence prepare these locking functions to be overridden then. Reviewed-by: Andrew Lunn Signed-off-by: Marek Vasut Cc: David S. Miller Cc: Lukas Wunner Cc: Petr Stetiar Cc: YueHaibing --- V3: New patch V4: s@unsigned status@unsigned int status@ in ks8851_irq() V5: No change V6: No change --- drivers/net/ethernet/micrel/ks8851.c | 97 +++++++++++++++++++--------- 1 file changed, 68 insertions(+), 29 deletions(-) diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c index e2e75041e931..053d6d085539 100644 --- a/drivers/net/ethernet/micrel/ks8851.c +++ b/drivers/net/ethernet/micrel/ks8851.c @@ -151,6 +151,30 @@ static int msg_enable; /* turn register number and byte-enable mask into data for start of packet */ #define MK_OP(_byteen, _reg) (BYTE_EN(_byteen) | (_reg) << (8+2) | (_reg) >> 6) +/** + * ks8851_lock - register access lock + * @ks: The chip state + * @flags: Spinlock flags + * + * Claim chip register access lock + */ +static void ks8851_lock(struct ks8851_net *ks, unsigned long *flags) +{ + mutex_lock(&ks->lock); +} + +/** + * ks8851_unlock - register access unlock + * @ks: The chip state + * @flags: Spinlock flags + * + * Release chip register access lock + */ +static void ks8851_unlock(struct ks8851_net *ks, unsigned long *flags) +{ + mutex_unlock(&ks->lock); +} + /* SPI register read/write calls. * * All these calls issue SPI transactions to access the chip's registers. They @@ -304,10 +328,11 @@ static void ks8851_set_powermode(struct ks8851_net *ks, unsigned pwrmode) static int ks8851_write_mac_addr(struct net_device *dev) { struct ks8851_net *ks = netdev_priv(dev); + unsigned long flags; u16 val; int i; - mutex_lock(&ks->lock); + ks8851_lock(ks, &flags); /* * Wake up chip in case it was powered off when stopped; otherwise, @@ -323,7 +348,7 @@ static int ks8851_write_mac_addr(struct net_device *dev) if (!netif_running(dev)) ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN); - mutex_unlock(&ks->lock); + ks8851_unlock(ks, &flags); return 0; } @@ -337,10 +362,11 @@ static int ks8851_write_mac_addr(struct net_device *dev) static void ks8851_read_mac_addr(struct net_device *dev) { struct ks8851_net *ks = netdev_priv(dev); + unsigned long flags; u16 reg; int i; - mutex_lock(&ks->lock); + ks8851_lock(ks, &flags); for (i = 0; i < ETH_ALEN; i += 2) { reg = ks8851_rdreg16(ks, KS_MAR(i)); @@ -348,7 +374,7 @@ static void ks8851_read_mac_addr(struct net_device *dev) dev->dev_addr[i + 1] = reg & 0xff; } - mutex_unlock(&ks->lock); + ks8851_unlock(ks, &flags); } /** @@ -534,10 +560,11 @@ static void ks8851_rx_pkts(struct ks8851_net *ks) static irqreturn_t ks8851_irq(int irq, void *_ks) { struct ks8851_net *ks = _ks; - unsigned status; unsigned handled = 0; + unsigned long flags; + unsigned int status; - mutex_lock(&ks->lock); + ks8851_lock(ks, &flags); status = ks8851_rdreg16(ks, KS_ISR); @@ -606,7 +633,7 @@ static irqreturn_t ks8851_irq(int irq, void *_ks) ks8851_wrreg16(ks, KS_RXCR1, rxc->rxcr1); } - mutex_unlock(&ks->lock); + ks8851_unlock(ks, &flags); if (status & IRQ_LCI) mii_check_link(&ks->mii); @@ -700,10 +727,11 @@ static void ks8851_done_tx(struct ks8851_net *ks, struct sk_buff *txb) static void ks8851_tx_work(struct work_struct *work) { struct ks8851_net *ks = container_of(work, struct ks8851_net, tx_work); + unsigned long flags; struct sk_buff *txb; bool last = skb_queue_empty(&ks->txq); - mutex_lock(&ks->lock); + ks8851_lock(ks, &flags); while (!last) { txb = skb_dequeue(&ks->txq); @@ -719,7 +747,7 @@ static void ks8851_tx_work(struct work_struct *work) } } - mutex_unlock(&ks->lock); + ks8851_unlock(ks, &flags); } /** @@ -732,6 +760,7 @@ static void ks8851_tx_work(struct work_struct *work) static int ks8851_net_open(struct net_device *dev) { struct ks8851_net *ks = netdev_priv(dev); + unsigned long flags; int ret; ret = request_threaded_irq(dev->irq, NULL, ks8851_irq, @@ -744,7 +773,7 @@ static int ks8851_net_open(struct net_device *dev) /* lock the card, even if we may not actually be doing anything * else at the moment */ - mutex_lock(&ks->lock); + ks8851_lock(ks, &flags); netif_dbg(ks, ifup, ks->netdev, "opening\n"); @@ -804,7 +833,7 @@ static int ks8851_net_open(struct net_device *dev) netif_dbg(ks, ifup, ks->netdev, "network device up\n"); - mutex_unlock(&ks->lock); + ks8851_unlock(ks, &flags); mii_check_link(&ks->mii); return 0; } @@ -820,22 +849,23 @@ static int ks8851_net_open(struct net_device *dev) static int ks8851_net_stop(struct net_device *dev) { struct ks8851_net *ks = netdev_priv(dev); + unsigned long flags; netif_info(ks, ifdown, dev, "shutting down\n"); netif_stop_queue(dev); - mutex_lock(&ks->lock); + ks8851_lock(ks, &flags); /* turn off the IRQs and ack any outstanding */ ks8851_wrreg16(ks, KS_IER, 0x0000); ks8851_wrreg16(ks, KS_ISR, 0xffff); - mutex_unlock(&ks->lock); + ks8851_unlock(ks, &flags); /* stop any outstanding work */ flush_work(&ks->tx_work); flush_work(&ks->rxctrl_work); - mutex_lock(&ks->lock); + ks8851_lock(ks, &flags); /* shutdown RX process */ ks8851_wrreg16(ks, KS_RXCR1, 0x0000); @@ -844,7 +874,7 @@ static int ks8851_net_stop(struct net_device *dev) /* set powermode to soft power down to save power */ ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN); - mutex_unlock(&ks->lock); + ks8851_unlock(ks, &flags); /* ensure any queued tx buffers are dumped */ while (!skb_queue_empty(&ks->txq)) { @@ -916,13 +946,14 @@ static netdev_tx_t ks8851_start_xmit(struct sk_buff *skb, static void ks8851_rxctrl_work(struct work_struct *work) { struct ks8851_net *ks = container_of(work, struct ks8851_net, rxctrl_work); + unsigned long flags; - mutex_lock(&ks->lock); + ks8851_lock(ks, &flags); /* need to shutdown RXQ before modifying filter parameters */ ks8851_wrreg16(ks, KS_RXCR1, 0x00); - mutex_unlock(&ks->lock); + ks8851_unlock(ks, &flags); } static void ks8851_set_rx_mode(struct net_device *dev) @@ -1104,11 +1135,6 @@ static void ks8851_eeprom_regwrite(struct eeprom_93cx6 *ee) */ static int ks8851_eeprom_claim(struct ks8851_net *ks) { - if (!(ks->rc_ccr & CCR_EEPROM)) - return -ENOENT; - - mutex_lock(&ks->lock); - /* start with clock low, cs high */ ks8851_wrreg16(ks, KS_EEPCR, EEPCR_EESA | EEPCR_EECS); return 0; @@ -1125,7 +1151,6 @@ static void ks8851_eeprom_release(struct ks8851_net *ks) unsigned val = ks8851_rdreg16(ks, KS_EEPCR); ks8851_wrreg16(ks, KS_EEPCR, val & ~EEPCR_EESA); - mutex_unlock(&ks->lock); } #define KS_EEPROM_MAGIC (0x00008851) @@ -1135,6 +1160,7 @@ static int ks8851_set_eeprom(struct net_device *dev, { struct ks8851_net *ks = netdev_priv(dev); int offset = ee->offset; + unsigned long flags; int len = ee->len; u16 tmp; @@ -1145,9 +1171,13 @@ static int ks8851_set_eeprom(struct net_device *dev, if (ee->magic != KS_EEPROM_MAGIC) return -EINVAL; - if (ks8851_eeprom_claim(ks)) + if (!(ks->rc_ccr & CCR_EEPROM)) return -ENOENT; + ks8851_lock(ks, &flags); + + ks8851_eeprom_claim(ks); + eeprom_93cx6_wren(&ks->eeprom, true); /* ethtool currently only supports writing bytes, which means @@ -1167,6 +1197,7 @@ static int ks8851_set_eeprom(struct net_device *dev, eeprom_93cx6_wren(&ks->eeprom, false); ks8851_eeprom_release(ks); + ks8851_unlock(ks, &flags); return 0; } @@ -1176,19 +1207,25 @@ static int ks8851_get_eeprom(struct net_device *dev, { struct ks8851_net *ks = netdev_priv(dev); int offset = ee->offset; + unsigned long flags; int len = ee->len; /* must be 2 byte aligned */ if (len & 1 || offset & 1) return -EINVAL; - if (ks8851_eeprom_claim(ks)) + if (!(ks->rc_ccr & CCR_EEPROM)) return -ENOENT; + ks8851_lock(ks, &flags); + + ks8851_eeprom_claim(ks); + ee->magic = KS_EEPROM_MAGIC; eeprom_93cx6_multiread(&ks->eeprom, offset/2, (__le16 *)data, len/2); ks8851_eeprom_release(ks); + ks8851_unlock(ks, &flags); return 0; } @@ -1262,6 +1299,7 @@ static int ks8851_phy_reg(int reg) static int ks8851_phy_read(struct net_device *dev, int phy_addr, int reg) { struct ks8851_net *ks = netdev_priv(dev); + unsigned long flags; int ksreg; int result; @@ -1269,9 +1307,9 @@ static int ks8851_phy_read(struct net_device *dev, int phy_addr, int reg) if (!ksreg) return 0x0; /* no error return allowed, so use zero */ - mutex_lock(&ks->lock); + ks8851_lock(ks, &flags); result = ks8851_rdreg16(ks, ksreg); - mutex_unlock(&ks->lock); + ks8851_unlock(ks, &flags); return result; } @@ -1280,13 +1318,14 @@ static void ks8851_phy_write(struct net_device *dev, int phy, int reg, int value) { struct ks8851_net *ks = netdev_priv(dev); + unsigned long flags; int ksreg; ksreg = ks8851_phy_reg(reg); if (ksreg) { - mutex_lock(&ks->lock); + ks8851_lock(ks, &flags); ks8851_wrreg16(ks, ksreg, value); - mutex_unlock(&ks->lock); + ks8851_unlock(ks, &flags); } } From patchwork Sun May 17 00:33:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 219089 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F0CF4C433E1 for ; Sun, 17 May 2020 00:35:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D14A2206D8 for ; Sun, 17 May 2020 00:35:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727075AbgEQAfE (ORCPT ); Sat, 16 May 2020 20:35:04 -0400 Received: from mail-out.m-online.net ([212.18.0.10]:42298 "EHLO mail-out.m-online.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726952AbgEQAev (ORCPT ); Sat, 16 May 2020 20:34:51 -0400 Received: from frontend01.mail.m-online.net (unknown [192.168.8.182]) by mail-out.m-online.net (Postfix) with ESMTP id 49Pjp71MFnz1rrW3; Sun, 17 May 2020 02:34:39 +0200 (CEST) Received: from localhost (dynscan1.mnet-online.de [192.168.6.70]) by mail.m-online.net (Postfix) with ESMTP id 49Pjp718VBz1shfq; Sun, 17 May 2020 02:34:39 +0200 (CEST) X-Virus-Scanned: amavisd-new at mnet-online.de Received: from mail.mnet-online.de ([192.168.8.182]) by localhost (dynscan1.mail.m-online.net [192.168.6.70]) (amavisd-new, port 10024) with ESMTP id 7IUvnuXKNytS; Sun, 17 May 2020 02:34:37 +0200 (CEST) X-Auth-Info: 0bQ15MSCDmeYAxHVc7qXA6h/mQckzlcjcfJ0Hwv2R4M= Received: from desktop.lan (ip-86-49-35-8.net.upcbroadband.cz [86.49.35.8]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.mnet-online.de (Postfix) with ESMTPSA; Sun, 17 May 2020 02:34:37 +0200 (CEST) From: Marek Vasut To: netdev@vger.kernel.org Cc: Marek Vasut , Andrew Lunn , "David S . Miller" , Lukas Wunner , Petr Stetiar , YueHaibing Subject: [PATCH V6 12/20] net: ks8851: Split out SPI specific entries in struct ks8851_net Date: Sun, 17 May 2020 02:33:46 +0200 Message-Id: <20200517003354.233373-13-marex@denx.de> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200517003354.233373-1-marex@denx.de> References: <20200517003354.233373-1-marex@denx.de> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add a new struct ks8851_net_spi, which embeds the original struct ks8851_net and contains the entries specific only to the SPI variant of KS8851. There should be no functional change. Reviewed-by: Andrew Lunn Signed-off-by: Marek Vasut Cc: David S. Miller Cc: Lukas Wunner Cc: Petr Stetiar Cc: YueHaibing --- V2: - Drop 'must be first' comment on the embedded struct ks8851_net - Remove moved kerneldoc entries for struct ks8851_net V3: - Split out also tx_work and lock V4: No change V5: No change V6: No change --- drivers/net/ethernet/micrel/ks8851.c | 128 +++++++++++++++++---------- 1 file changed, 79 insertions(+), 49 deletions(-) diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c index 087d2a39cdce..482c65b1accf 100644 --- a/drivers/net/ethernet/micrel/ks8851.c +++ b/drivers/net/ethernet/micrel/ks8851.c @@ -64,16 +64,11 @@ union ks8851_tx_hdr { /** * struct ks8851_net - KS8851 driver private data * @netdev: The network device we're bound to - * @spidev: The spi device we're bound to. - * @lock: Lock to ensure that the device is not accessed when busy. * @statelock: Lock on this structure for tx list. * @mii: The MII state information for the mii calls. * @rxctrl: RX settings for @rxctrl_work. - * @tx_work: Work queue for tx packets * @rxctrl_work: Work queue for updating RX mode and multicast lists * @txq: Queue of packets for transmission. - * @spi_msg1: pre-setup SPI transfer with one message, @spi_xfer1. - * @spi_msg2: pre-setup SPI transfer with two messages, @spi_xfer2. * @txh: Space for generating packet TX header in DMA-able data * @rxd: Space for receiving SPI data, in DMA-able space. * @txd: Space for transmitting SPI data, in DMA-able space. @@ -87,11 +82,6 @@ union ks8851_tx_hdr { * @vdd_io: Optional digital power supply for IO * @gpio: Optional reset_n gpio * - * The @lock ensures that the chip is protected when certain operations are - * in progress. When the read or write packet transfer is in progress, most - * of the chip registers are not ccessible until the transfer is finished and - * the DMA has been de-asserted. - * * The @statelock is used to protect information in the structure which may * need to be accessed via several sources, such as the network driver layer * or one of the work queues. @@ -102,8 +92,6 @@ union ks8851_tx_hdr { */ struct ks8851_net { struct net_device *netdev; - struct spi_device *spidev; - struct mutex lock; spinlock_t statelock; union ks8851_tx_hdr txh ____cacheline_aligned; @@ -121,22 +109,43 @@ struct ks8851_net { struct mii_if_info mii; struct ks8851_rxctrl rxctrl; - struct work_struct tx_work; struct work_struct rxctrl_work; struct sk_buff_head txq; - struct spi_message spi_msg1; - struct spi_message spi_msg2; - struct spi_transfer spi_xfer1; - struct spi_transfer spi_xfer2[2]; - struct eeprom_93cx6 eeprom; struct regulator *vdd_reg; struct regulator *vdd_io; int gpio; }; +/** + * struct ks8851_net_spi - KS8851 SPI driver private data + * @ks8851: KS8851 driver common private data + * @lock: Lock to ensure that the device is not accessed when busy. + * @tx_work: Work queue for tx packets + * @spidev: The spi device we're bound to. + * @spi_msg1: pre-setup SPI transfer with one message, @spi_xfer1. + * @spi_msg2: pre-setup SPI transfer with two messages, @spi_xfer2. + * + * The @lock ensures that the chip is protected when certain operations are + * in progress. When the read or write packet transfer is in progress, most + * of the chip registers are not ccessible until the transfer is finished and + * the DMA has been de-asserted. + */ +struct ks8851_net_spi { + struct ks8851_net ks8851; + struct mutex lock; + struct work_struct tx_work; + struct spi_device *spidev; + struct spi_message spi_msg1; + struct spi_message spi_msg2; + struct spi_transfer spi_xfer1; + struct spi_transfer spi_xfer2[2]; +}; + +#define to_ks8851_spi(ks) container_of((ks), struct ks8851_net_spi, ks8851) + static int msg_enable; /* SPI frame opcodes */ @@ -160,7 +169,9 @@ static int msg_enable; */ static void ks8851_lock(struct ks8851_net *ks, unsigned long *flags) { - mutex_lock(&ks->lock); + struct ks8851_net_spi *kss = to_ks8851_spi(ks); + + mutex_lock(&kss->lock); } /** @@ -172,7 +183,9 @@ static void ks8851_lock(struct ks8851_net *ks, unsigned long *flags) */ static void ks8851_unlock(struct ks8851_net *ks, unsigned long *flags) { - mutex_unlock(&ks->lock); + struct ks8851_net_spi *kss = to_ks8851_spi(ks); + + mutex_unlock(&kss->lock); } /* SPI register read/write calls. @@ -192,8 +205,9 @@ static void ks8851_unlock(struct ks8851_net *ks, unsigned long *flags) */ static void ks8851_wrreg16(struct ks8851_net *ks, unsigned reg, unsigned val) { - struct spi_transfer *xfer = &ks->spi_xfer1; - struct spi_message *msg = &ks->spi_msg1; + struct ks8851_net_spi *kss = to_ks8851_spi(ks); + struct spi_transfer *xfer = &kss->spi_xfer1; + struct spi_message *msg = &kss->spi_msg1; __le16 txb[2]; int ret; @@ -204,7 +218,7 @@ static void ks8851_wrreg16(struct ks8851_net *ks, unsigned reg, unsigned val) xfer->rx_buf = NULL; xfer->len = 4; - ret = spi_sync(ks->spidev, msg); + ret = spi_sync(kss->spidev, msg); if (ret < 0) netdev_err(ks->netdev, "spi_sync() failed\n"); } @@ -222,6 +236,7 @@ static void ks8851_wrreg16(struct ks8851_net *ks, unsigned reg, unsigned val) static void ks8851_rdreg(struct ks8851_net *ks, unsigned op, u8 *rxb, unsigned rxl) { + struct ks8851_net_spi *kss = to_ks8851_spi(ks); struct spi_transfer *xfer; struct spi_message *msg; __le16 *txb = (__le16 *)ks->txd; @@ -230,9 +245,9 @@ static void ks8851_rdreg(struct ks8851_net *ks, unsigned op, txb[0] = cpu_to_le16(op | KS_SPIOP_RD); - if (ks->spidev->master->flags & SPI_MASTER_HALF_DUPLEX) { - msg = &ks->spi_msg2; - xfer = ks->spi_xfer2; + if (kss->spidev->master->flags & SPI_MASTER_HALF_DUPLEX) { + msg = &kss->spi_msg2; + xfer = kss->spi_xfer2; xfer->tx_buf = txb; xfer->rx_buf = NULL; @@ -243,18 +258,18 @@ static void ks8851_rdreg(struct ks8851_net *ks, unsigned op, xfer->rx_buf = trx; xfer->len = rxl; } else { - msg = &ks->spi_msg1; - xfer = &ks->spi_xfer1; + msg = &kss->spi_msg1; + xfer = &kss->spi_xfer1; xfer->tx_buf = txb; xfer->rx_buf = trx; xfer->len = rxl + 2; } - ret = spi_sync(ks->spidev, msg); + ret = spi_sync(kss->spidev, msg); if (ret < 0) netdev_err(ks->netdev, "read: spi_sync() failed\n"); - else if (ks->spidev->master->flags & SPI_MASTER_HALF_DUPLEX) + else if (kss->spidev->master->flags & SPI_MASTER_HALF_DUPLEX) memcpy(rxb, trx, rxl); else memcpy(rxb, trx + 2, rxl); @@ -424,8 +439,9 @@ static void ks8851_init_mac(struct ks8851_net *ks, struct device_node *np) */ static void ks8851_rdfifo(struct ks8851_net *ks, u8 *buff, unsigned len) { - struct spi_transfer *xfer = ks->spi_xfer2; - struct spi_message *msg = &ks->spi_msg2; + struct ks8851_net_spi *kss = to_ks8851_spi(ks); + struct spi_transfer *xfer = kss->spi_xfer2; + struct spi_message *msg = &kss->spi_msg2; u8 txb[1]; int ret; @@ -444,7 +460,7 @@ static void ks8851_rdfifo(struct ks8851_net *ks, u8 *buff, unsigned len) xfer->tx_buf = NULL; xfer->len = len; - ret = spi_sync(ks->spidev, msg); + ret = spi_sync(kss->spidev, msg); if (ret < 0) netdev_err(ks->netdev, "%s: spi_sync() failed\n", __func__); } @@ -678,8 +694,9 @@ static inline unsigned calc_txlen(unsigned len) */ static void ks8851_wrpkt(struct ks8851_net *ks, struct sk_buff *txp, bool irq) { - struct spi_transfer *xfer = ks->spi_xfer2; - struct spi_message *msg = &ks->spi_msg2; + struct ks8851_net_spi *kss = to_ks8851_spi(ks); + struct spi_transfer *xfer = kss->spi_xfer2; + struct spi_message *msg = &kss->spi_msg2; unsigned fid = 0; int ret; @@ -706,7 +723,7 @@ static void ks8851_wrpkt(struct ks8851_net *ks, struct sk_buff *txp, bool irq) xfer->rx_buf = NULL; xfer->len = ALIGN(txp->len, 4); - ret = spi_sync(ks->spidev, msg); + ret = spi_sync(kss->spidev, msg); if (ret < 0) netdev_err(ks->netdev, "%s: spi_sync() failed\n", __func__); } @@ -735,10 +752,15 @@ static void ks8851_done_tx(struct ks8851_net *ks, struct sk_buff *txb) */ static void ks8851_tx_work(struct work_struct *work) { - struct ks8851_net *ks = container_of(work, struct ks8851_net, tx_work); + struct ks8851_net_spi *kss; + struct ks8851_net *ks; unsigned long flags; struct sk_buff *txb; - bool last = skb_queue_empty(&ks->txq); + bool last; + + kss = container_of(work, struct ks8851_net_spi, tx_work); + ks = &kss->ks8851; + last = skb_queue_empty(&ks->txq); ks8851_lock(ks, &flags); @@ -858,8 +880,11 @@ static int ks8851_net_open(struct net_device *dev) static int ks8851_net_stop(struct net_device *dev) { struct ks8851_net *ks = netdev_priv(dev); + struct ks8851_net_spi *kss; unsigned long flags; + kss = to_ks8851_spi(ks); + netif_info(ks, ifdown, dev, "shutting down\n"); netif_stop_queue(dev); @@ -871,7 +896,7 @@ static int ks8851_net_stop(struct net_device *dev) ks8851_unlock(ks, &flags); /* stop any outstanding work */ - flush_work(&ks->tx_work); + flush_work(&kss->tx_work); flush_work(&ks->rxctrl_work); ks8851_lock(ks, &flags); @@ -919,6 +944,9 @@ static netdev_tx_t ks8851_start_xmit(struct sk_buff *skb, struct ks8851_net *ks = netdev_priv(dev); unsigned needed = calc_txlen(skb->len); netdev_tx_t ret = NETDEV_TX_OK; + struct ks8851_net_spi *kss; + + kss = to_ks8851_spi(ks); netif_dbg(ks, tx_queued, ks->netdev, "%s: skb %p, %d@%p\n", __func__, skb, skb->len, skb->data); @@ -934,7 +962,7 @@ static netdev_tx_t ks8851_start_xmit(struct sk_buff *skb, } spin_unlock(&ks->statelock); - schedule_work(&ks->tx_work); + schedule_work(&kss->tx_work); return ret; } @@ -1406,22 +1434,24 @@ static SIMPLE_DEV_PM_OPS(ks8851_pm_ops, ks8851_suspend, ks8851_resume); static int ks8851_probe(struct spi_device *spi) { struct device *dev = &spi->dev; + struct ks8851_net_spi *kss; struct net_device *netdev; struct ks8851_net *ks; int ret; unsigned cider; int gpio; - netdev = devm_alloc_etherdev(dev, sizeof(struct ks8851_net)); + netdev = devm_alloc_etherdev(dev, sizeof(struct ks8851_net_spi)); if (!netdev) return -ENOMEM; spi->bits_per_word = 8; ks = netdev_priv(netdev); + kss = to_ks8851_spi(ks); ks->netdev = netdev; - ks->spidev = spi; + kss->spidev = spi; ks->tx_space = 6144; gpio = of_get_named_gpio_flags(dev->of_node, "reset-gpios", 0, NULL); @@ -1467,20 +1497,20 @@ static int ks8851_probe(struct spi_device *spi) gpio_set_value(gpio, 1); } - mutex_init(&ks->lock); + mutex_init(&kss->lock); spin_lock_init(&ks->statelock); - INIT_WORK(&ks->tx_work, ks8851_tx_work); + INIT_WORK(&kss->tx_work, ks8851_tx_work); INIT_WORK(&ks->rxctrl_work, ks8851_rxctrl_work); /* initialise pre-made spi transfer messages */ - spi_message_init(&ks->spi_msg1); - spi_message_add_tail(&ks->spi_xfer1, &ks->spi_msg1); + spi_message_init(&kss->spi_msg1); + spi_message_add_tail(&kss->spi_xfer1, &kss->spi_msg1); - spi_message_init(&ks->spi_msg2); - spi_message_add_tail(&ks->spi_xfer2[0], &ks->spi_msg2); - spi_message_add_tail(&ks->spi_xfer2[1], &ks->spi_msg2); + spi_message_init(&kss->spi_msg2); + spi_message_add_tail(&kss->spi_xfer2[0], &kss->spi_msg2); + spi_message_add_tail(&kss->spi_xfer2[1], &kss->spi_msg2); /* setup EEPROM state */ From patchwork Sun May 17 00:33:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 219093 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0F23DC433E0 for ; Sun, 17 May 2020 00:34:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E0760206D8 for ; Sun, 17 May 2020 00:34:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727007AbgEQAet (ORCPT ); Sat, 16 May 2020 20:34:49 -0400 Received: from mail-out.m-online.net ([212.18.0.9]:46907 "EHLO mail-out.m-online.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726996AbgEQAen (ORCPT ); Sat, 16 May 2020 20:34:43 -0400 Received: from frontend01.mail.m-online.net (unknown [192.168.8.182]) by mail-out.m-online.net (Postfix) with ESMTP id 49Pjp96yH3z1qrLN; Sun, 17 May 2020 02:34:41 +0200 (CEST) Received: from localhost (dynscan1.mnet-online.de [192.168.6.70]) by mail.m-online.net (Postfix) with ESMTP id 49Pjp96mGZz1shfq; Sun, 17 May 2020 02:34:41 +0200 (CEST) X-Virus-Scanned: amavisd-new at mnet-online.de Received: from mail.mnet-online.de ([192.168.8.182]) by localhost (dynscan1.mail.m-online.net [192.168.6.70]) (amavisd-new, port 10024) with ESMTP id XYpGjIFhu4JC; Sun, 17 May 2020 02:34:40 +0200 (CEST) X-Auth-Info: M+G4F/lGEdZr8tOm22P+CVsT/T0M45wUD/StfiYX/MY= Received: from desktop.lan (ip-86-49-35-8.net.upcbroadband.cz [86.49.35.8]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.mnet-online.de (Postfix) with ESMTPSA; Sun, 17 May 2020 02:34:40 +0200 (CEST) From: Marek Vasut To: netdev@vger.kernel.org Cc: Marek Vasut , Andrew Lunn , "David S . Miller" , Lukas Wunner , Petr Stetiar , YueHaibing Subject: [PATCH V6 14/20] net: ks8851: Factor out TX work flush function Date: Sun, 17 May 2020 02:33:48 +0200 Message-Id: <20200517003354.233373-15-marex@denx.de> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200517003354.233373-1-marex@denx.de> References: <20200517003354.233373-1-marex@denx.de> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org While the SPI version of the KS8851 requires a TX worker thread to pump data via SPI, the parallel bus version can write data into the TX FIFO directly in .ndo_start_xmit, as the parallel bus access is much faster and does not sleep. Factor out this TX work flush part, so it can be overridden by the parallel bus driver. Reviewed-by: Andrew Lunn Signed-off-by: Marek Vasut Cc: David S. Miller Cc: Lukas Wunner Cc: Petr Stetiar Cc: YueHaibing --- V3: New patch V4: No change V5: No change V6: No change --- drivers/net/ethernet/micrel/ks8851.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c index 4283ba5bee81..458c86903ac0 100644 --- a/drivers/net/ethernet/micrel/ks8851.c +++ b/drivers/net/ethernet/micrel/ks8851.c @@ -781,6 +781,17 @@ static void ks8851_tx_work(struct work_struct *work) ks8851_unlock(ks, &flags); } +/** + * ks8851_flush_tx_work - flush outstanding TX work + * @ks: The device state + */ +static void ks8851_flush_tx_work(struct ks8851_net *ks) +{ + struct ks8851_net_spi *kss = to_ks8851_spi(ks); + + flush_work(&kss->tx_work); +} + /** * ks8851_net_open - open network device * @dev: The network device being opened. @@ -880,11 +891,8 @@ static int ks8851_net_open(struct net_device *dev) static int ks8851_net_stop(struct net_device *dev) { struct ks8851_net *ks = netdev_priv(dev); - struct ks8851_net_spi *kss; unsigned long flags; - kss = to_ks8851_spi(ks); - netif_info(ks, ifdown, dev, "shutting down\n"); netif_stop_queue(dev); @@ -896,7 +904,7 @@ static int ks8851_net_stop(struct net_device *dev) ks8851_unlock(ks, &flags); /* stop any outstanding work */ - flush_work(&kss->tx_work); + ks8851_flush_tx_work(ks); flush_work(&ks->rxctrl_work); ks8851_lock(ks, &flags); From patchwork Sun May 17 00:33:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 219092 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CB82BC433E0 for ; Sun, 17 May 2020 00:34:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AA16E2075F for ; Sun, 17 May 2020 00:34:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727034AbgEQAez (ORCPT ); Sat, 16 May 2020 20:34:55 -0400 Received: from mail-out.m-online.net ([212.18.0.10]:50861 "EHLO mail-out.m-online.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726895AbgEQAew (ORCPT ); Sat, 16 May 2020 20:34:52 -0400 Received: from frontend01.mail.m-online.net (unknown [192.168.8.182]) by mail-out.m-online.net (Postfix) with ESMTP id 49PjpC1SH4z1rryf; Sun, 17 May 2020 02:34:43 +0200 (CEST) Received: from localhost (dynscan1.mnet-online.de [192.168.6.70]) by mail.m-online.net (Postfix) with ESMTP id 49PjpC1DFKz1shfq; Sun, 17 May 2020 02:34:43 +0200 (CEST) X-Virus-Scanned: amavisd-new at mnet-online.de Received: from mail.mnet-online.de ([192.168.8.182]) by localhost (dynscan1.mail.m-online.net [192.168.6.70]) (amavisd-new, port 10024) with ESMTP id 6IO6tQzx1zb5; Sun, 17 May 2020 02:34:42 +0200 (CEST) X-Auth-Info: A9RR21z+A78JrceYjbjX1g3QQ6fzoJI3VshlnUgawy8= Received: from desktop.lan (ip-86-49-35-8.net.upcbroadband.cz [86.49.35.8]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.mnet-online.de (Postfix) with ESMTPSA; Sun, 17 May 2020 02:34:42 +0200 (CEST) From: Marek Vasut To: netdev@vger.kernel.org Cc: Marek Vasut , Andrew Lunn , "David S . Miller" , Lukas Wunner , Petr Stetiar , YueHaibing Subject: [PATCH V6 15/20] net: ks8851: Permit overridding interrupt enable register Date: Sun, 17 May 2020 02:33:49 +0200 Message-Id: <20200517003354.233373-16-marex@denx.de> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200517003354.233373-1-marex@denx.de> References: <20200517003354.233373-1-marex@denx.de> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The parallel bus variant does not need to use the TX interrupt at all as it writes the TX FIFO directly with in .ndo_start_xmit, permit the drivers to configure the interrupt enable bits. Reviewed-by: Andrew Lunn Signed-off-by: Marek Vasut Cc: David S. Miller Cc: Lukas Wunner Cc: Petr Stetiar Cc: YueHaibing --- V3: New patch V4: No change V5: No change V6: No change --- drivers/net/ethernet/micrel/ks8851.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c index 458c86903ac0..baf424f9893b 100644 --- a/drivers/net/ethernet/micrel/ks8851.c +++ b/drivers/net/ethernet/micrel/ks8851.c @@ -859,17 +859,8 @@ static int ks8851_net_open(struct net_device *dev) ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr); /* clear then enable interrupts */ - -#define STD_IRQ (IRQ_LCI | /* Link Change */ \ - IRQ_TXI | /* TX done */ \ - IRQ_RXI | /* RX done */ \ - IRQ_SPIBEI | /* SPI bus error */ \ - IRQ_TXPSI | /* TX process stop */ \ - IRQ_RXPSI) /* RX process stop */ - - ks->rc_ier = STD_IRQ; - ks8851_wrreg16(ks, KS_ISR, STD_IRQ); - ks8851_wrreg16(ks, KS_IER, STD_IRQ); + ks8851_wrreg16(ks, KS_ISR, ks->rc_ier); + ks8851_wrreg16(ks, KS_IER, ks->rc_ier); netif_start_queue(ks->netdev); @@ -1599,6 +1590,15 @@ static int ks8851_probe(struct spi_device *spi) spi->bits_per_word = 8; ks = netdev_priv(netdev); + +#define STD_IRQ (IRQ_LCI | /* Link Change */ \ + IRQ_TXI | /* TX done */ \ + IRQ_RXI | /* RX done */ \ + IRQ_SPIBEI | /* SPI bus error */ \ + IRQ_TXPSI | /* TX process stop */ \ + IRQ_RXPSI) /* RX process stop */ + ks->rc_ier = STD_IRQ; + kss = to_ks8851_spi(ks); kss->spidev = spi; From patchwork Sun May 17 00:33:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 219091 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 80712C433E1 for ; Sun, 17 May 2020 00:34:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 61640206D8 for ; Sun, 17 May 2020 00:34:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727048AbgEQAe6 (ORCPT ); Sat, 16 May 2020 20:34:58 -0400 Received: from mail-out.m-online.net ([212.18.0.10]:42298 "EHLO mail-out.m-online.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726986AbgEQAez (ORCPT ); Sat, 16 May 2020 20:34:55 -0400 Received: from frontend01.mail.m-online.net (unknown [192.168.8.182]) by mail-out.m-online.net (Postfix) with ESMTP id 49PjpF0DwTz1rs00; Sun, 17 May 2020 02:34:45 +0200 (CEST) Received: from localhost (dynscan1.mnet-online.de [192.168.6.70]) by mail.m-online.net (Postfix) with ESMTP id 49PjpF00RWz1shfq; Sun, 17 May 2020 02:34:44 +0200 (CEST) X-Virus-Scanned: amavisd-new at mnet-online.de Received: from mail.mnet-online.de ([192.168.8.182]) by localhost (dynscan1.mail.m-online.net [192.168.6.70]) (amavisd-new, port 10024) with ESMTP id d9zbeR-eIpk1; Sun, 17 May 2020 02:34:43 +0200 (CEST) X-Auth-Info: dxKEyQ5Wtxv2vYWLcN69K23v+AY4AWQ6NNlW9OkLXSI= Received: from desktop.lan (ip-86-49-35-8.net.upcbroadband.cz [86.49.35.8]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.mnet-online.de (Postfix) with ESMTPSA; Sun, 17 May 2020 02:34:43 +0200 (CEST) From: Marek Vasut To: netdev@vger.kernel.org Cc: Marek Vasut , Andrew Lunn , "David S . Miller" , Lukas Wunner , Petr Stetiar , YueHaibing Subject: [PATCH V6 16/20] net: ks8851: Implement register, FIFO, lock accessor callbacks Date: Sun, 17 May 2020 02:33:50 +0200 Message-Id: <20200517003354.233373-17-marex@denx.de> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200517003354.233373-1-marex@denx.de> References: <20200517003354.233373-1-marex@denx.de> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The register and FIFO accessors are bus specific, so is locking. Implement callbacks so that each variant of the KS8851 can implement matching accessors and locking, and use the rest of the common code. Reviewed-by: Andrew Lunn Signed-off-by: Marek Vasut Cc: David S. Miller Cc: Lukas Wunner Cc: Petr Stetiar Cc: YueHaibing --- V4: New patch V5: No change V6: No change --- drivers/net/ethernet/micrel/ks8851.c | 167 +++++++++++++++++++++++---- 1 file changed, 145 insertions(+), 22 deletions(-) diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c index baf424f9893b..0188fd5781d8 100644 --- a/drivers/net/ethernet/micrel/ks8851.c +++ b/drivers/net/ethernet/micrel/ks8851.c @@ -117,6 +117,24 @@ struct ks8851_net { struct regulator *vdd_reg; struct regulator *vdd_io; int gpio; + + void (*lock)(struct ks8851_net *ks, + unsigned long *flags); + void (*unlock)(struct ks8851_net *ks, + unsigned long *flags); + unsigned int (*rdreg16)(struct ks8851_net *ks, + unsigned int reg); + void (*wrreg16)(struct ks8851_net *ks, + unsigned int reg, unsigned int val); + void (*rdfifo)(struct ks8851_net *ks, u8 *buff, + unsigned int len); + void (*wrfifo)(struct ks8851_net *ks, + struct sk_buff *txp, bool irq); + netdev_tx_t (*start_xmit)(struct sk_buff *skb, + struct net_device *dev); + void (*rx_skb)(struct ks8851_net *ks, + struct sk_buff *skb); + void (*flush_tx_work)(struct ks8851_net *ks); }; /** @@ -161,13 +179,13 @@ static int msg_enable; #define MK_OP(_byteen, _reg) (BYTE_EN(_byteen) | (_reg) << (8+2) | (_reg) >> 6) /** - * ks8851_lock - register access lock + * ks8851_lock_spi - register access lock for SPI * @ks: The chip state * @flags: Spinlock flags * * Claim chip register access lock */ -static void ks8851_lock(struct ks8851_net *ks, unsigned long *flags) +static void ks8851_lock_spi(struct ks8851_net *ks, unsigned long *flags) { struct ks8851_net_spi *kss = to_ks8851_spi(ks); @@ -175,19 +193,43 @@ static void ks8851_lock(struct ks8851_net *ks, unsigned long *flags) } /** - * ks8851_unlock - register access unlock + * ks8851_unlock_spi - register access unlock for SPI * @ks: The chip state * @flags: Spinlock flags * * Release chip register access lock */ -static void ks8851_unlock(struct ks8851_net *ks, unsigned long *flags) +static void ks8851_unlock_spi(struct ks8851_net *ks, unsigned long *flags) { struct ks8851_net_spi *kss = to_ks8851_spi(ks); mutex_unlock(&kss->lock); } +/** + * ks8851_lock - register access lock + * @ks: The chip state + * @flags: Spinlock flags + * + * Claim chip register access lock + */ +static void ks8851_lock(struct ks8851_net *ks, unsigned long *flags) +{ + ks->lock(ks, flags); +} + +/** + * ks8851_unlock - register access unlock + * @ks: The chip state + * @flags: Spinlock flags + * + * Release chip register access lock + */ +static void ks8851_unlock(struct ks8851_net *ks, unsigned long *flags) +{ + ks->unlock(ks, flags); +} + /* SPI register read/write calls. * * All these calls issue SPI transactions to access the chip's registers. They @@ -196,14 +238,15 @@ static void ks8851_unlock(struct ks8851_net *ks, unsigned long *flags) */ /** - * ks8851_wrreg16 - write 16bit register value to chip + * ks8851_wrreg16_spi - write 16bit register value to chip via SPI * @ks: The chip state * @reg: The register address * @val: The value to write * * Issue a write to put the value @val into the register specified in @reg. */ -static void ks8851_wrreg16(struct ks8851_net *ks, unsigned reg, unsigned val) +static void ks8851_wrreg16_spi(struct ks8851_net *ks, unsigned int reg, + unsigned int val) { struct ks8851_net_spi *kss = to_ks8851_spi(ks); struct spi_transfer *xfer = &kss->spi_xfer1; @@ -223,6 +266,20 @@ static void ks8851_wrreg16(struct ks8851_net *ks, unsigned reg, unsigned val) netdev_err(ks->netdev, "spi_sync() failed\n"); } +/** + * ks8851_wrreg16 - write 16bit register value to chip + * @ks: The chip state + * @reg: The register address + * @val: The value to write + * + * Issue a write to put the value @val into the register specified in @reg. + */ +static void ks8851_wrreg16(struct ks8851_net *ks, unsigned int reg, + unsigned int val) +{ + ks->wrreg16(ks, reg, val); +} + /** * ks8851_rdreg - issue read register command and return the data * @ks: The device state @@ -276,13 +333,14 @@ static void ks8851_rdreg(struct ks8851_net *ks, unsigned op, } /** - * ks8851_rdreg16 - read 16 bit register from device + * ks8851_rdreg16_spi - read 16 bit register from device via SPI * @ks: The chip information * @reg: The register address * * Read a 16bit register from the chip, returning the result */ -static unsigned ks8851_rdreg16(struct ks8851_net *ks, unsigned reg) +static unsigned int ks8851_rdreg16_spi(struct ks8851_net *ks, + unsigned int reg) { __le16 rx = 0; @@ -290,6 +348,19 @@ static unsigned ks8851_rdreg16(struct ks8851_net *ks, unsigned reg) return le16_to_cpu(rx); } +/** + * ks8851_rdreg16 - read 16 bit register from device + * @ks: The chip information + * @reg: The register address + * + * Read a 16bit register from the chip, returning the result + */ +static unsigned int ks8851_rdreg16(struct ks8851_net *ks, + unsigned int reg) +{ + return ks->rdreg16(ks, reg); +} + /** * ks8851_soft_reset - issue one of the soft reset to the device * @ks: The device state. @@ -429,7 +500,7 @@ static void ks8851_init_mac(struct ks8851_net *ks, struct device_node *np) } /** - * ks8851_rdfifo - read data from the receive fifo + * ks8851_rdfifo_spi - read data from the receive fifo via SPI * @ks: The device state. * @buff: The buffer address * @len: The length of the data to read @@ -437,7 +508,8 @@ static void ks8851_init_mac(struct ks8851_net *ks, struct device_node *np) * Issue an RXQ FIFO read command and read the @len amount of data from * the FIFO into the buffer specified by @buff. */ -static void ks8851_rdfifo(struct ks8851_net *ks, u8 *buff, unsigned len) +static void ks8851_rdfifo_spi(struct ks8851_net *ks, u8 *buff, + unsigned int len) { struct ks8851_net_spi *kss = to_ks8851_spi(ks); struct spi_transfer *xfer = kss->spi_xfer2; @@ -482,14 +554,23 @@ static void ks8851_dbg_dumpkkt(struct ks8851_net *ks, u8 *rxpkt) } /** - * ks8851_rx_skb - receive skbuff + * ks8851_rx_skb_spi - receive skbuff for SPI * @skb: The skbuff */ -static void ks8851_rx_skb(struct sk_buff *skb) +static void ks8851_rx_skb_spi(struct ks8851_net *ks, struct sk_buff *skb) { netif_rx_ni(skb); } +/** + * ks8851_rx_skb - receive skbuff + * @skb: The skbuff + */ +static void ks8851_rx_skb(struct ks8851_net *ks, struct sk_buff *skb) +{ + ks->rx_skb(ks, skb); +} + /** * ks8851_rx_pkts - receive packets from the host * @ks: The device information. @@ -552,13 +633,13 @@ static void ks8851_rx_pkts(struct ks8851_net *ks) rxpkt = skb_put(skb, rxlen) - 8; - ks8851_rdfifo(ks, rxpkt, rxalign + 8); + ks->rdfifo(ks, rxpkt, rxalign + 8); if (netif_msg_pktdata(ks)) ks8851_dbg_dumpkkt(ks, rxpkt); skb->protocol = eth_type_trans(skb, ks->netdev); - ks8851_rx_skb(skb); + ks8851_rx_skb(ks, skb); ks->netdev->stats.rx_packets++; ks->netdev->stats.rx_bytes += rxlen; @@ -682,7 +763,7 @@ static inline unsigned calc_txlen(unsigned len) } /** - * ks8851_wrpkt - write packet to TX FIFO + * ks8851_wrpkt_spi - write packet to TX FIFO via SPI * @ks: The device state. * @txp: The sk_buff to transmit. * @irq: IRQ on completion of the packet. @@ -692,7 +773,8 @@ static inline unsigned calc_txlen(unsigned len) * needs, such as IRQ on completion. Send the header and the packet data to * the device. */ -static void ks8851_wrpkt(struct ks8851_net *ks, struct sk_buff *txp, bool irq) +static void ks8851_wrpkt_spi(struct ks8851_net *ks, struct sk_buff *txp, + bool irq) { struct ks8851_net_spi *kss = to_ks8851_spi(ks); struct spi_transfer *xfer = kss->spi_xfer2; @@ -770,7 +852,7 @@ static void ks8851_tx_work(struct work_struct *work) if (txb != NULL) { ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA); - ks8851_wrpkt(ks, txb, last); + ks->wrfifo(ks, txb, last); ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr); ks8851_wrreg16(ks, KS_TXQCR, TXQCR_METFE); @@ -782,16 +864,26 @@ static void ks8851_tx_work(struct work_struct *work) } /** - * ks8851_flush_tx_work - flush outstanding TX work + * ks8851_flush_tx_work_spi - flush outstanding TX work for SPI * @ks: The device state */ -static void ks8851_flush_tx_work(struct ks8851_net *ks) +static void ks8851_flush_tx_work_spi(struct ks8851_net *ks) { struct ks8851_net_spi *kss = to_ks8851_spi(ks); flush_work(&kss->tx_work); } +/** + * ks8851_flush_tx_work - flush outstanding TX work + * @ks: The device state + */ +static void ks8851_flush_tx_work(struct ks8851_net *ks) +{ + if (ks->flush_tx_work) + ks->flush_tx_work(ks); +} + /** * ks8851_net_open - open network device * @dev: The network device being opened. @@ -925,7 +1017,7 @@ static int ks8851_net_stop(struct net_device *dev) } /** - * ks8851_start_xmit - transmit packet + * ks8851_start_xmit_spi - transmit packet using SPI * @skb: The buffer to transmit * @dev: The device used to transmit the packet. * @@ -937,8 +1029,8 @@ static int ks8851_net_stop(struct net_device *dev) * and secondly so we can round up more than one packet to transmit which * means we can try and avoid generating too many transmit done interrupts. */ -static netdev_tx_t ks8851_start_xmit(struct sk_buff *skb, - struct net_device *dev) +static netdev_tx_t ks8851_start_xmit_spi(struct sk_buff *skb, + struct net_device *dev) { struct ks8851_net *ks = netdev_priv(dev); unsigned needed = calc_txlen(skb->len); @@ -966,6 +1058,27 @@ static netdev_tx_t ks8851_start_xmit(struct sk_buff *skb, return ret; } +/** + * ks8851_start_xmit - transmit packet + * @skb: The buffer to transmit + * @dev: The device used to transmit the packet. + * + * Called by the network layer to transmit the @skb. Queue the packet for + * the device and schedule the necessary work to transmit the packet when + * it is free. + * + * We do this to firstly avoid sleeping with the network device locked, + * and secondly so we can round up more than one packet to transmit which + * means we can try and avoid generating too many transmit done interrupts. + */ +static netdev_tx_t ks8851_start_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct ks8851_net *ks = netdev_priv(dev); + + return ks->start_xmit(skb, dev); +} + /** * ks8851_rxctrl_work - work handler to change rx mode * @work: The work structure this belongs to. @@ -1591,6 +1704,16 @@ static int ks8851_probe(struct spi_device *spi) ks = netdev_priv(netdev); + ks->lock = ks8851_lock_spi; + ks->unlock = ks8851_unlock_spi; + ks->rdreg16 = ks8851_rdreg16_spi; + ks->wrreg16 = ks8851_wrreg16_spi; + ks->rdfifo = ks8851_rdfifo_spi; + ks->wrfifo = ks8851_wrpkt_spi; + ks->start_xmit = ks8851_start_xmit_spi; + ks->rx_skb = ks8851_rx_skb_spi; + ks->flush_tx_work = ks8851_flush_tx_work_spi; + #define STD_IRQ (IRQ_LCI | /* Link Change */ \ IRQ_TXI | /* TX done */ \ IRQ_RXI | /* RX done */ \ From patchwork Sun May 17 00:33:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 219090 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F026AC433DF for ; Sun, 17 May 2020 00:35:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B0CAD2075F for ; Sun, 17 May 2020 00:35:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727083AbgEQAfF (ORCPT ); Sat, 16 May 2020 20:35:05 -0400 Received: from mail-out.m-online.net ([212.18.0.10]:42298 "EHLO mail-out.m-online.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727036AbgEQAfC (ORCPT ); Sat, 16 May 2020 20:35:02 -0400 Received: from frontend01.mail.m-online.net (unknown [192.168.8.182]) by mail-out.m-online.net (Postfix) with ESMTP id 49PjpQ2sJTz1rs2Q; Sun, 17 May 2020 02:34:54 +0200 (CEST) Received: from localhost (dynscan1.mnet-online.de [192.168.6.70]) by mail.m-online.net (Postfix) with ESMTP id 49PjpQ2fNhz1shfq; Sun, 17 May 2020 02:34:54 +0200 (CEST) X-Virus-Scanned: amavisd-new at mnet-online.de Received: from mail.mnet-online.de ([192.168.8.182]) by localhost (dynscan1.mail.m-online.net [192.168.6.70]) (amavisd-new, port 10024) with ESMTP id F97glkeIDeNJ; Sun, 17 May 2020 02:34:51 +0200 (CEST) X-Auth-Info: mPUxLTLpnyNsLHuu2IFcsTU0//WoGhDlyA3ypxrpgCg= Received: from desktop.lan (ip-86-49-35-8.net.upcbroadband.cz [86.49.35.8]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.mnet-online.de (Postfix) with ESMTPSA; Sun, 17 May 2020 02:34:51 +0200 (CEST) From: Marek Vasut To: netdev@vger.kernel.org Cc: Marek Vasut , "David S . Miller" , Lukas Wunner , Petr Stetiar , YueHaibing Subject: [PATCH V6 19/20] net: ks8851: Remove ks8851_mll.c Date: Sun, 17 May 2020 02:33:53 +0200 Message-Id: <20200517003354.233373-20-marex@denx.de> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200517003354.233373-1-marex@denx.de> References: <20200517003354.233373-1-marex@denx.de> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The ks8851_mll.c is replaced by ks8851_par.c, which is using common code from ks8851.c, just like ks8851_spi.c . Remove this old ad-hoc driver. Signed-off-by: Marek Vasut Cc: David S. Miller Cc: Lukas Wunner Cc: Petr Stetiar Cc: YueHaibing --- V2: No change V3: No change V4: No change V5: No change V6: No change --- drivers/net/ethernet/micrel/ks8851_mll.c | 1393 ---------------------- 1 file changed, 1393 deletions(-) delete mode 100644 drivers/net/ethernet/micrel/ks8851_mll.c diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c deleted file mode 100644 index 45cc840d8e2e..000000000000 --- a/drivers/net/ethernet/micrel/ks8851_mll.c +++ /dev/null @@ -1,1393 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/** - * drivers/net/ethernet/micrel/ks8851_mll.c - * Copyright (c) 2009 Micrel Inc. - */ - -/* Supports: - * KS8851 16bit MLL chip from Micrel Inc. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ks8851.h" - -#define DRV_NAME "ks8851_mll" - -static u8 KS_DEFAULT_MAC_ADDRESS[] = { 0x00, 0x10, 0xA1, 0x86, 0x95, 0x11 }; -#define MAX_RECV_FRAMES 255 -#define MAX_BUF_SIZE 2048 -#define TX_BUF_SIZE 2000 -#define RX_BUF_SIZE 2000 - -#define RXCR1_FILTER_MASK (RXCR1_RXINVF | RXCR1_RXAE | \ - RXCR1_RXMAFMA | RXCR1_RXPAFMA) -#define RXQCR_CMD_CNTL (RXQCR_RXFCTE|RXQCR_ADRFE) - -#define ENUM_BUS_NONE 0 -#define ENUM_BUS_8BIT 1 -#define ENUM_BUS_16BIT 2 -#define ENUM_BUS_32BIT 3 - -#define MAX_MCAST_LST 32 -#define HW_MCAST_SIZE 8 - -/** - * union ks_tx_hdr - tx header data - * @txb: The header as bytes - * @txw: The header as 16bit, little-endian words - * - * A dual representation of the tx header data to allow - * access to individual bytes, and to allow 16bit accesses - * with 16bit alignment. - */ -union ks_tx_hdr { - u8 txb[4]; - __le16 txw[2]; -}; - -/** - * struct ks_net - KS8851 driver private data - * @net_device : The network device we're bound to - * @hw_addr : start address of data register. - * @hw_addr_cmd : start address of command register. - * @txh : temporaly buffer to save status/length. - * @lock : Lock to ensure that the device is not accessed when busy. - * @pdev : Pointer to platform device. - * @mii : The MII state information for the mii calls. - * @frame_head_info : frame header information for multi-pkt rx. - * @statelock : Lock on this structure for tx list. - * @msg_enable : The message flags controlling driver output (see ethtool). - * @frame_cnt : number of frames received. - * @bus_width : i/o bus width. - * @rc_rxqcr : Cached copy of KS_RXQCR. - * @rc_txcr : Cached copy of KS_TXCR. - * @rc_ier : Cached copy of KS_IER. - * @sharedbus : Multipex(addr and data bus) mode indicator. - * @cmd_reg_cache : command register cached. - * @cmd_reg_cache_int : command register cached. Used in the irq handler. - * @promiscuous : promiscuous mode indicator. - * @all_mcast : mutlicast indicator. - * @mcast_lst_size : size of multicast list. - * @mcast_lst : multicast list. - * @mcast_bits : multicast enabed. - * @mac_addr : MAC address assigned to this device. - * @fid : frame id. - * @extra_byte : number of extra byte prepended rx pkt. - * @enabled : indicator this device works. - * - * The @lock ensures that the chip is protected when certain operations are - * in progress. When the read or write packet transfer is in progress, most - * of the chip registers are not accessible until the transfer is finished and - * the DMA has been de-asserted. - * - * The @statelock is used to protect information in the structure which may - * need to be accessed via several sources, such as the network driver layer - * or one of the work queues. - * - */ - -/* Receive multiplex framer header info */ -struct type_frame_head { - u16 sts; /* Frame status */ - u16 len; /* Byte count */ -}; - -struct ks_net { - struct net_device *netdev; - void __iomem *hw_addr; - void __iomem *hw_addr_cmd; - union ks_tx_hdr txh ____cacheline_aligned; - struct mutex lock; /* spinlock to be interrupt safe */ - struct platform_device *pdev; - struct mii_if_info mii; - struct type_frame_head *frame_head_info; - spinlock_t statelock; - u32 msg_enable; - u32 frame_cnt; - int bus_width; - - u16 rc_rxqcr; - u16 rc_txcr; - u16 rc_ier; - u16 sharedbus; - u16 cmd_reg_cache; - u16 cmd_reg_cache_int; - u16 promiscuous; - u16 all_mcast; - u16 mcast_lst_size; - u8 mcast_lst[MAX_MCAST_LST][ETH_ALEN]; - u8 mcast_bits[HW_MCAST_SIZE]; - u8 mac_addr[6]; - u8 fid; - u8 extra_byte; - u8 enabled; -}; - -static int msg_enable; - -#define BE3 0x8000 /* Byte Enable 3 */ -#define BE2 0x4000 /* Byte Enable 2 */ -#define BE1 0x2000 /* Byte Enable 1 */ -#define BE0 0x1000 /* Byte Enable 0 */ - -/* register read/write calls. - * - * All these calls issue transactions to access the chip's registers. They - * all require that the necessary lock is held to prevent accesses when the - * chip is busy transferring packet data (RX/TX FIFO accesses). - */ - -/** - * ks_check_endian - Check whether endianness of the bus is correct - * @ks : The chip information - * - * The KS8851-16MLL EESK pin allows selecting the endianness of the 16bit - * bus. To maintain optimum performance, the bus endianness should be set - * such that it matches the endianness of the CPU. - */ - -static int ks_check_endian(struct ks_net *ks) -{ - u16 cider; - - /* - * Read CIDER register first, however read it the "wrong" way around. - * If the endian strap on the KS8851-16MLL in incorrect and the chip - * is operating in different endianness than the CPU, then the meaning - * of BE[3:0] byte-enable bits is also swapped such that: - * BE[3,2,1,0] becomes BE[1,0,3,2] - * - * Luckily for us, the byte-enable bits are the top four MSbits of - * the address register and the CIDER register is at offset 0xc0. - * Hence, by reading address 0xc0c0, which is not impacted by endian - * swapping, we assert either BE[3:2] or BE[1:0] while reading the - * CIDER register. - * - * If the bus configuration is correct, reading 0xc0c0 asserts - * BE[3:2] and this read returns 0x0000, because to read register - * with bottom two LSbits of address set to 0, BE[1:0] must be - * asserted. - * - * If the bus configuration is NOT correct, reading 0xc0c0 asserts - * BE[1:0] and this read returns non-zero 0x8872 value. - */ - iowrite16(BE3 | BE2 | KS_CIDER, ks->hw_addr_cmd); - cider = ioread16(ks->hw_addr); - if (!cider) - return 0; - - netdev_err(ks->netdev, "incorrect EESK endian strap setting\n"); - - return -EINVAL; -} - -/** - * ks_rdreg16 - read 16 bit register from device - * @ks : The chip information - * @offset: The register address - * - * Read a 16bit register from the chip, returning the result - */ - -static u16 ks_rdreg16(struct ks_net *ks, int offset) -{ - ks->cmd_reg_cache = (u16)offset | ((BE1 | BE0) << (offset & 0x02)); - iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd); - return ioread16(ks->hw_addr); -} - -/** - * ks_wrreg16 - write 16bit register value to chip - * @ks: The chip information - * @offset: The register address - * @value: The value to write - * - */ - -static void ks_wrreg16(struct ks_net *ks, int offset, u16 value) -{ - ks->cmd_reg_cache = (u16)offset | ((BE1 | BE0) << (offset & 0x02)); - iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd); - iowrite16(value, ks->hw_addr); -} - -/** - * ks_inblk - read a block of data from QMU. This is called after sudo DMA mode enabled. - * @ks: The chip state - * @wptr: buffer address to save data - * @len: length in byte to read - * - */ -static inline void ks_inblk(struct ks_net *ks, u16 *wptr, u32 len) -{ - len >>= 1; - while (len--) - *wptr++ = (u16)ioread16(ks->hw_addr); -} - -/** - * ks_outblk - write data to QMU. This is called after sudo DMA mode enabled. - * @ks: The chip information - * @wptr: buffer address - * @len: length in byte to write - * - */ -static inline void ks_outblk(struct ks_net *ks, u16 *wptr, u32 len) -{ - len >>= 1; - while (len--) - iowrite16(*wptr++, ks->hw_addr); -} - -static void ks_disable_int(struct ks_net *ks) -{ - ks_wrreg16(ks, KS_IER, 0x0000); -} /* ks_disable_int */ - -static void ks_enable_int(struct ks_net *ks) -{ - ks_wrreg16(ks, KS_IER, ks->rc_ier); -} /* ks_enable_int */ - -/** - * ks_tx_fifo_space - return the available hardware buffer size. - * @ks: The chip information - * - */ -static inline u16 ks_tx_fifo_space(struct ks_net *ks) -{ - return ks_rdreg16(ks, KS_TXMIR) & 0x1fff; -} - -/** - * ks_save_cmd_reg - save the command register from the cache. - * @ks: The chip information - * - */ -static inline void ks_save_cmd_reg(struct ks_net *ks) -{ - /*ks8851 MLL has a bug to read back the command register. - * So rely on software to save the content of command register. - */ - ks->cmd_reg_cache_int = ks->cmd_reg_cache; -} - -/** - * ks_restore_cmd_reg - restore the command register from the cache and - * write to hardware register. - * @ks: The chip information - * - */ -static inline void ks_restore_cmd_reg(struct ks_net *ks) -{ - ks->cmd_reg_cache = ks->cmd_reg_cache_int; - iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd); -} - -/** - * ks_set_powermode - set power mode of the device - * @ks: The chip information - * @pwrmode: The power mode value to write to KS_PMECR. - * - * Change the power mode of the chip. - */ -static void ks_set_powermode(struct ks_net *ks, unsigned pwrmode) -{ - unsigned pmecr; - - netif_dbg(ks, hw, ks->netdev, "setting power mode %d\n", pwrmode); - - ks_rdreg16(ks, KS_GRR); - pmecr = ks_rdreg16(ks, KS_PMECR); - pmecr &= ~PMECR_PM_MASK; - pmecr |= pwrmode; - - ks_wrreg16(ks, KS_PMECR, pmecr); -} - -/** - * ks_read_config - read chip configuration of bus width. - * @ks: The chip information - * - */ -static void ks_read_config(struct ks_net *ks) -{ - u16 reg_data = 0; - - /* Regardless of bus width, 8 bit read should always work.*/ - reg_data = ks_rdreg16(ks, KS_CCR); - - /* addr/data bus are multiplexed */ - ks->sharedbus = (reg_data & CCR_SHARED) == CCR_SHARED; - - /* There are garbage data when reading data from QMU, - depending on bus-width. - */ - - if (reg_data & CCR_8BIT) { - ks->bus_width = ENUM_BUS_8BIT; - ks->extra_byte = 1; - } else if (reg_data & CCR_16BIT) { - ks->bus_width = ENUM_BUS_16BIT; - ks->extra_byte = 2; - } else { - ks->bus_width = ENUM_BUS_32BIT; - ks->extra_byte = 4; - } -} - -/** - * ks_soft_reset - issue one of the soft reset to the device - * @ks: The device state. - * @op: The bit(s) to set in the GRR - * - * Issue the relevant soft-reset command to the device's GRR register - * specified by @op. - * - * Note, the delays are in there as a caution to ensure that the reset - * has time to take effect and then complete. Since the datasheet does - * not currently specify the exact sequence, we have chosen something - * that seems to work with our device. - */ -static void ks_soft_reset(struct ks_net *ks, unsigned op) -{ - /* Disable interrupt first */ - ks_wrreg16(ks, KS_IER, 0x0000); - ks_wrreg16(ks, KS_GRR, op); - mdelay(10); /* wait a short time to effect reset */ - ks_wrreg16(ks, KS_GRR, 0); - mdelay(1); /* wait for condition to clear */ -} - - -static void ks_enable_qmu(struct ks_net *ks) -{ - u16 w; - - w = ks_rdreg16(ks, KS_TXCR); - /* Enables QMU Transmit (TXCR). */ - ks_wrreg16(ks, KS_TXCR, w | TXCR_TXE); - - /* - * RX Frame Count Threshold Enable and Auto-Dequeue RXQ Frame - * Enable - */ - - w = ks_rdreg16(ks, KS_RXQCR); - ks_wrreg16(ks, KS_RXQCR, w | RXQCR_RXFCTE); - - /* Enables QMU Receive (RXCR1). */ - w = ks_rdreg16(ks, KS_RXCR1); - ks_wrreg16(ks, KS_RXCR1, w | RXCR1_RXE); - ks->enabled = true; -} /* ks_enable_qmu */ - -static void ks_disable_qmu(struct ks_net *ks) -{ - u16 w; - - w = ks_rdreg16(ks, KS_TXCR); - - /* Disables QMU Transmit (TXCR). */ - w &= ~TXCR_TXE; - ks_wrreg16(ks, KS_TXCR, w); - - /* Disables QMU Receive (RXCR1). */ - w = ks_rdreg16(ks, KS_RXCR1); - w &= ~RXCR1_RXE ; - ks_wrreg16(ks, KS_RXCR1, w); - - ks->enabled = false; - -} /* ks_disable_qmu */ - -/** - * ks_read_qmu - read 1 pkt data from the QMU. - * @ks: The chip information - * @buf: buffer address to save 1 pkt - * @len: Pkt length - * Here is the sequence to read 1 pkt: - * 1. set sudo DMA mode - * 2. read prepend data - * 3. read pkt data - * 4. reset sudo DMA Mode - */ -static inline void ks_read_qmu(struct ks_net *ks, u16 *buf, u32 len) -{ - u32 r = ks->extra_byte & 0x1 ; - u32 w = ks->extra_byte - r; - - /* 1. set sudo DMA mode */ - ks_wrreg16(ks, KS_RXFDPR, RXFDPR_RXFPAI); - ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA); - - /* 2. read prepend data */ - /** - * read 4 + extra bytes and discard them. - * extra bytes for dummy, 2 for status, 2 for len - */ - - /* use likely(r) for 8 bit access for performance */ - if (unlikely(r)) - ioread8(ks->hw_addr); - ks_inblk(ks, buf, w + 2 + 2); - - /* 3. read pkt data */ - ks_inblk(ks, buf, ALIGN(len, 4)); - - /* 4. reset sudo DMA Mode */ - ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr); -} - -/** - * ks_rcv - read multiple pkts data from the QMU. - * @ks: The chip information - * @netdev: The network device being opened. - * - * Read all of header information before reading pkt content. - * It is not allowed only port of pkts in QMU after issuing - * interrupt ack. - */ -static void ks_rcv(struct ks_net *ks, struct net_device *netdev) -{ - u32 i; - struct type_frame_head *frame_hdr = ks->frame_head_info; - struct sk_buff *skb; - - ks->frame_cnt = ks_rdreg16(ks, KS_RXFCTR) >> 8; - - /* read all header information */ - for (i = 0; i < ks->frame_cnt; i++) { - /* Checking Received packet status */ - frame_hdr->sts = ks_rdreg16(ks, KS_RXFHSR); - /* Get packet len from hardware */ - frame_hdr->len = ks_rdreg16(ks, KS_RXFHBCR); - frame_hdr++; - } - - frame_hdr = ks->frame_head_info; - while (ks->frame_cnt--) { - if (unlikely(!(frame_hdr->sts & RXFSHR_RXFV) || - frame_hdr->len >= RX_BUF_SIZE || - frame_hdr->len <= 0)) { - - /* discard an invalid packet */ - ks_wrreg16(ks, KS_RXQCR, (ks->rc_rxqcr | RXQCR_RRXEF)); - netdev->stats.rx_dropped++; - if (!(frame_hdr->sts & RXFSHR_RXFV)) - netdev->stats.rx_frame_errors++; - else - netdev->stats.rx_length_errors++; - frame_hdr++; - continue; - } - - skb = netdev_alloc_skb(netdev, frame_hdr->len + 16); - if (likely(skb)) { - skb_reserve(skb, 2); - /* read data block including CRC 4 bytes */ - ks_read_qmu(ks, (u16 *)skb->data, frame_hdr->len); - skb_put(skb, frame_hdr->len - 4); - skb->protocol = eth_type_trans(skb, netdev); - netif_rx(skb); - /* exclude CRC size */ - netdev->stats.rx_bytes += frame_hdr->len - 4; - netdev->stats.rx_packets++; - } else { - ks_wrreg16(ks, KS_RXQCR, (ks->rc_rxqcr | RXQCR_RRXEF)); - netdev->stats.rx_dropped++; - } - frame_hdr++; - } -} - -/** - * ks_update_link_status - link status update. - * @netdev: The network device being opened. - * @ks: The chip information - * - */ - -static void ks_update_link_status(struct net_device *netdev, struct ks_net *ks) -{ - /* check the status of the link */ - u32 link_up_status; - if (ks_rdreg16(ks, KS_P1SR) & P1SR_LINK_GOOD) { - netif_carrier_on(netdev); - link_up_status = true; - } else { - netif_carrier_off(netdev); - link_up_status = false; - } - netif_dbg(ks, link, ks->netdev, - "%s: %s\n", __func__, link_up_status ? "UP" : "DOWN"); -} - -/** - * ks_irq - device interrupt handler - * @irq: Interrupt number passed from the IRQ handler. - * @pw: The private word passed to register_irq(), our struct ks_net. - * - * This is the handler invoked to find out what happened - * - * Read the interrupt status, work out what needs to be done and then clear - * any of the interrupts that are not needed. - */ - -static irqreturn_t ks_irq(int irq, void *pw) -{ - struct net_device *netdev = pw; - struct ks_net *ks = netdev_priv(netdev); - unsigned long flags; - u16 status; - - spin_lock_irqsave(&ks->statelock, flags); - /*this should be the first in IRQ handler */ - ks_save_cmd_reg(ks); - - status = ks_rdreg16(ks, KS_ISR); - if (unlikely(!status)) { - ks_restore_cmd_reg(ks); - spin_unlock_irqrestore(&ks->statelock, flags); - return IRQ_NONE; - } - - ks_wrreg16(ks, KS_ISR, status); - - if (likely(status & IRQ_RXI)) - ks_rcv(ks, netdev); - - if (unlikely(status & IRQ_LCI)) - ks_update_link_status(netdev, ks); - - if (unlikely(status & IRQ_TXI)) - netif_wake_queue(netdev); - - if (unlikely(status & IRQ_LDI)) { - - u16 pmecr = ks_rdreg16(ks, KS_PMECR); - pmecr &= ~PMECR_WKEVT_MASK; - ks_wrreg16(ks, KS_PMECR, pmecr | PMECR_WKEVT_LINK); - } - - if (unlikely(status & IRQ_RXOI)) - ks->netdev->stats.rx_over_errors++; - /* this should be the last in IRQ handler*/ - ks_restore_cmd_reg(ks); - spin_unlock_irqrestore(&ks->statelock, flags); - return IRQ_HANDLED; -} - - -/** - * ks_net_open - open network device - * @netdev: The network device being opened. - * - * Called when the network device is marked active, such as a user executing - * 'ifconfig up' on the device. - */ -static int ks_net_open(struct net_device *netdev) -{ - struct ks_net *ks = netdev_priv(netdev); - int err; - -#define KS_INT_FLAGS IRQF_TRIGGER_LOW - /* lock the card, even if we may not actually do anything - * else at the moment. - */ - - netif_dbg(ks, ifup, ks->netdev, "%s - entry\n", __func__); - - /* reset the HW */ - err = request_irq(netdev->irq, ks_irq, KS_INT_FLAGS, DRV_NAME, netdev); - - if (err) { - pr_err("Failed to request IRQ: %d: %d\n", netdev->irq, err); - return err; - } - - /* wake up powermode to normal mode */ - ks_set_powermode(ks, PMECR_PM_NORMAL); - mdelay(1); /* wait for normal mode to take effect */ - - ks_wrreg16(ks, KS_ISR, 0xffff); - ks_enable_int(ks); - ks_enable_qmu(ks); - netif_start_queue(ks->netdev); - - netif_dbg(ks, ifup, ks->netdev, "network device up\n"); - - return 0; -} - -/** - * ks_net_stop - close network device - * @netdev: The device being closed. - * - * Called to close down a network device which has been active. Cancell any - * work, shutdown the RX and TX process and then place the chip into a low - * power state whilst it is not being used. - */ -static int ks_net_stop(struct net_device *netdev) -{ - struct ks_net *ks = netdev_priv(netdev); - - netif_info(ks, ifdown, netdev, "shutting down\n"); - - netif_stop_queue(netdev); - - mutex_lock(&ks->lock); - - /* turn off the IRQs and ack any outstanding */ - ks_wrreg16(ks, KS_IER, 0x0000); - ks_wrreg16(ks, KS_ISR, 0xffff); - - /* shutdown RX/TX QMU */ - ks_disable_qmu(ks); - ks_disable_int(ks); - - /* set powermode to soft power down to save power */ - ks_set_powermode(ks, PMECR_PM_SOFTDOWN); - free_irq(netdev->irq, netdev); - mutex_unlock(&ks->lock); - return 0; -} - - -/** - * ks_write_qmu - write 1 pkt data to the QMU. - * @ks: The chip information - * @pdata: buffer address to save 1 pkt - * @len: Pkt length in byte - * Here is the sequence to write 1 pkt: - * 1. set sudo DMA mode - * 2. write status/length - * 3. write pkt data - * 4. reset sudo DMA Mode - * 5. reset sudo DMA mode - * 6. Wait until pkt is out - */ -static void ks_write_qmu(struct ks_net *ks, u8 *pdata, u16 len) -{ - /* start header at txb[0] to align txw entries */ - ks->txh.txw[0] = 0; - ks->txh.txw[1] = cpu_to_le16(len); - - /* 1. set sudo-DMA mode */ - ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA); - /* 2. write status/lenth info */ - ks_outblk(ks, ks->txh.txw, 4); - /* 3. write pkt data */ - ks_outblk(ks, (u16 *)pdata, ALIGN(len, 4)); - /* 4. reset sudo-DMA mode */ - ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr); - /* 5. Enqueue Tx(move the pkt from TX buffer into TXQ) */ - ks_wrreg16(ks, KS_TXQCR, TXQCR_METFE); - /* 6. wait until TXQCR_METFE is auto-cleared */ - while (ks_rdreg16(ks, KS_TXQCR) & TXQCR_METFE) - ; -} - -/** - * ks_start_xmit - transmit packet - * @skb : The buffer to transmit - * @netdev : The device used to transmit the packet. - * - * Called by the network layer to transmit the @skb. - * spin_lock_irqsave is required because tx and rx should be mutual exclusive. - * So while tx is in-progress, prevent IRQ interrupt from happenning. - */ -static netdev_tx_t ks_start_xmit(struct sk_buff *skb, struct net_device *netdev) -{ - netdev_tx_t retv = NETDEV_TX_OK; - struct ks_net *ks = netdev_priv(netdev); - unsigned long flags; - - spin_lock_irqsave(&ks->statelock, flags); - - /* Extra space are required: - * 4 byte for alignment, 4 for status/length, 4 for CRC - */ - - if (likely(ks_tx_fifo_space(ks) >= skb->len + 12)) { - ks_write_qmu(ks, skb->data, skb->len); - /* add tx statistics */ - netdev->stats.tx_bytes += skb->len; - netdev->stats.tx_packets++; - dev_kfree_skb(skb); - } else - retv = NETDEV_TX_BUSY; - spin_unlock_irqrestore(&ks->statelock, flags); - return retv; -} - -/** - * ks_start_rx - ready to serve pkts - * @ks : The chip information - * - */ -static void ks_start_rx(struct ks_net *ks) -{ - u16 cntl; - - /* Enables QMU Receive (RXCR1). */ - cntl = ks_rdreg16(ks, KS_RXCR1); - cntl |= RXCR1_RXE ; - ks_wrreg16(ks, KS_RXCR1, cntl); -} /* ks_start_rx */ - -/** - * ks_stop_rx - stop to serve pkts - * @ks : The chip information - * - */ -static void ks_stop_rx(struct ks_net *ks) -{ - u16 cntl; - - /* Disables QMU Receive (RXCR1). */ - cntl = ks_rdreg16(ks, KS_RXCR1); - cntl &= ~RXCR1_RXE ; - ks_wrreg16(ks, KS_RXCR1, cntl); - -} /* ks_stop_rx */ - -static unsigned long const ethernet_polynomial = CRC32_POLY_BE; - -static unsigned long ether_gen_crc(int length, u8 *data) -{ - long crc = -1; - while (--length >= 0) { - u8 current_octet = *data++; - int bit; - - for (bit = 0; bit < 8; bit++, current_octet >>= 1) { - crc = (crc << 1) ^ - ((crc < 0) ^ (current_octet & 1) ? - ethernet_polynomial : 0); - } - } - return (unsigned long)crc; -} /* ether_gen_crc */ - -/** -* ks_set_grpaddr - set multicast information -* @ks : The chip information -*/ - -static void ks_set_grpaddr(struct ks_net *ks) -{ - u8 i; - u32 index, position, value; - - memset(ks->mcast_bits, 0, sizeof(u8) * HW_MCAST_SIZE); - - for (i = 0; i < ks->mcast_lst_size; i++) { - position = (ether_gen_crc(6, ks->mcast_lst[i]) >> 26) & 0x3f; - index = position >> 3; - value = 1 << (position & 7); - ks->mcast_bits[index] |= (u8)value; - } - - for (i = 0; i < HW_MCAST_SIZE; i++) { - if (i & 1) { - ks_wrreg16(ks, (u16)((KS_MAHTR0 + i) & ~1), - (ks->mcast_bits[i] << 8) | - ks->mcast_bits[i - 1]); - } - } -} /* ks_set_grpaddr */ - -/** -* ks_clear_mcast - clear multicast information -* -* @ks : The chip information -* This routine removes all mcast addresses set in the hardware. -*/ - -static void ks_clear_mcast(struct ks_net *ks) -{ - u16 i, mcast_size; - for (i = 0; i < HW_MCAST_SIZE; i++) - ks->mcast_bits[i] = 0; - - mcast_size = HW_MCAST_SIZE >> 2; - for (i = 0; i < mcast_size; i++) - ks_wrreg16(ks, KS_MAHTR0 + (2*i), 0); -} - -static void ks_set_promis(struct ks_net *ks, u16 promiscuous_mode) -{ - u16 cntl; - ks->promiscuous = promiscuous_mode; - ks_stop_rx(ks); /* Stop receiving for reconfiguration */ - cntl = ks_rdreg16(ks, KS_RXCR1); - - cntl &= ~RXCR1_FILTER_MASK; - if (promiscuous_mode) - /* Enable Promiscuous mode */ - cntl |= RXCR1_RXAE | RXCR1_RXINVF; - else - /* Disable Promiscuous mode (default normal mode) */ - cntl |= RXCR1_RXPAFMA; - - ks_wrreg16(ks, KS_RXCR1, cntl); - - if (ks->enabled) - ks_start_rx(ks); - -} /* ks_set_promis */ - -static void ks_set_mcast(struct ks_net *ks, u16 mcast) -{ - u16 cntl; - - ks->all_mcast = mcast; - ks_stop_rx(ks); /* Stop receiving for reconfiguration */ - cntl = ks_rdreg16(ks, KS_RXCR1); - cntl &= ~RXCR1_FILTER_MASK; - if (mcast) - /* Enable "Perfect with Multicast address passed mode" */ - cntl |= (RXCR1_RXAE | RXCR1_RXMAFMA | RXCR1_RXPAFMA); - else - /** - * Disable "Perfect with Multicast address passed - * mode" (normal mode). - */ - cntl |= RXCR1_RXPAFMA; - - ks_wrreg16(ks, KS_RXCR1, cntl); - - if (ks->enabled) - ks_start_rx(ks); -} /* ks_set_mcast */ - -static void ks_set_rx_mode(struct net_device *netdev) -{ - struct ks_net *ks = netdev_priv(netdev); - struct netdev_hw_addr *ha; - - /* Turn on/off promiscuous mode. */ - if ((netdev->flags & IFF_PROMISC) == IFF_PROMISC) - ks_set_promis(ks, - (u16)((netdev->flags & IFF_PROMISC) == IFF_PROMISC)); - /* Turn on/off all mcast mode. */ - else if ((netdev->flags & IFF_ALLMULTI) == IFF_ALLMULTI) - ks_set_mcast(ks, - (u16)((netdev->flags & IFF_ALLMULTI) == IFF_ALLMULTI)); - else - ks_set_promis(ks, false); - - if ((netdev->flags & IFF_MULTICAST) && netdev_mc_count(netdev)) { - if (netdev_mc_count(netdev) <= MAX_MCAST_LST) { - int i = 0; - - netdev_for_each_mc_addr(ha, netdev) { - if (i >= MAX_MCAST_LST) - break; - memcpy(ks->mcast_lst[i++], ha->addr, ETH_ALEN); - } - ks->mcast_lst_size = (u8)i; - ks_set_grpaddr(ks); - } else { - /** - * List too big to support so - * turn on all mcast mode. - */ - ks->mcast_lst_size = MAX_MCAST_LST; - ks_set_mcast(ks, true); - } - } else { - ks->mcast_lst_size = 0; - ks_clear_mcast(ks); - } -} /* ks_set_rx_mode */ - -static void ks_set_mac(struct ks_net *ks, u8 *data) -{ - u16 *pw = (u16 *)data; - u16 w, u; - - ks_stop_rx(ks); /* Stop receiving for reconfiguration */ - - u = *pw++; - w = ((u & 0xFF) << 8) | ((u >> 8) & 0xFF); - ks_wrreg16(ks, KS_MARH, w); - - u = *pw++; - w = ((u & 0xFF) << 8) | ((u >> 8) & 0xFF); - ks_wrreg16(ks, KS_MARM, w); - - u = *pw; - w = ((u & 0xFF) << 8) | ((u >> 8) & 0xFF); - ks_wrreg16(ks, KS_MARL, w); - - memcpy(ks->mac_addr, data, ETH_ALEN); - - if (ks->enabled) - ks_start_rx(ks); -} - -static int ks_set_mac_address(struct net_device *netdev, void *paddr) -{ - struct ks_net *ks = netdev_priv(netdev); - struct sockaddr *addr = paddr; - u8 *da; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - - da = (u8 *)netdev->dev_addr; - - ks_set_mac(ks, da); - return 0; -} - -static int ks_net_ioctl(struct net_device *netdev, struct ifreq *req, int cmd) -{ - struct ks_net *ks = netdev_priv(netdev); - - if (!netif_running(netdev)) - return -EINVAL; - - return generic_mii_ioctl(&ks->mii, if_mii(req), cmd, NULL); -} - -static const struct net_device_ops ks_netdev_ops = { - .ndo_open = ks_net_open, - .ndo_stop = ks_net_stop, - .ndo_do_ioctl = ks_net_ioctl, - .ndo_start_xmit = ks_start_xmit, - .ndo_set_mac_address = ks_set_mac_address, - .ndo_set_rx_mode = ks_set_rx_mode, - .ndo_validate_addr = eth_validate_addr, -}; - -/* ethtool support */ - -static void ks_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *di) -{ - strlcpy(di->driver, DRV_NAME, sizeof(di->driver)); - strlcpy(di->version, "1.00", sizeof(di->version)); - strlcpy(di->bus_info, dev_name(netdev->dev.parent), - sizeof(di->bus_info)); -} - -static u32 ks_get_msglevel(struct net_device *netdev) -{ - struct ks_net *ks = netdev_priv(netdev); - return ks->msg_enable; -} - -static void ks_set_msglevel(struct net_device *netdev, u32 to) -{ - struct ks_net *ks = netdev_priv(netdev); - ks->msg_enable = to; -} - -static int ks_get_link_ksettings(struct net_device *netdev, - struct ethtool_link_ksettings *cmd) -{ - struct ks_net *ks = netdev_priv(netdev); - - mii_ethtool_get_link_ksettings(&ks->mii, cmd); - - return 0; -} - -static int ks_set_link_ksettings(struct net_device *netdev, - const struct ethtool_link_ksettings *cmd) -{ - struct ks_net *ks = netdev_priv(netdev); - return mii_ethtool_set_link_ksettings(&ks->mii, cmd); -} - -static u32 ks_get_link(struct net_device *netdev) -{ - struct ks_net *ks = netdev_priv(netdev); - return mii_link_ok(&ks->mii); -} - -static int ks_nway_reset(struct net_device *netdev) -{ - struct ks_net *ks = netdev_priv(netdev); - return mii_nway_restart(&ks->mii); -} - -static const struct ethtool_ops ks_ethtool_ops = { - .get_drvinfo = ks_get_drvinfo, - .get_msglevel = ks_get_msglevel, - .set_msglevel = ks_set_msglevel, - .get_link = ks_get_link, - .nway_reset = ks_nway_reset, - .get_link_ksettings = ks_get_link_ksettings, - .set_link_ksettings = ks_set_link_ksettings, -}; - -/* MII interface controls */ - -/** - * ks_phy_reg - convert MII register into a KS8851 register - * @reg: MII register number. - * - * Return the KS8851 register number for the corresponding MII PHY register - * if possible. Return zero if the MII register has no direct mapping to the - * KS8851 register set. - */ -static int ks_phy_reg(int reg) -{ - switch (reg) { - case MII_BMCR: - return KS_P1MBCR; - case MII_BMSR: - return KS_P1MBSR; - case MII_PHYSID1: - return KS_PHY1ILR; - case MII_PHYSID2: - return KS_PHY1IHR; - case MII_ADVERTISE: - return KS_P1ANAR; - case MII_LPA: - return KS_P1ANLPR; - } - - return 0x0; -} - -/** - * ks_phy_read - MII interface PHY register read. - * @netdev: The network device the PHY is on. - * @phy_addr: Address of PHY (ignored as we only have one) - * @reg: The register to read. - * - * This call reads data from the PHY register specified in @reg. Since the - * device does not support all the MII registers, the non-existent values - * are always returned as zero. - * - * We return zero for unsupported registers as the MII code does not check - * the value returned for any error status, and simply returns it to the - * caller. The mii-tool that the driver was tested with takes any -ve error - * as real PHY capabilities, thus displaying incorrect data to the user. - */ -static int ks_phy_read(struct net_device *netdev, int phy_addr, int reg) -{ - struct ks_net *ks = netdev_priv(netdev); - int ksreg; - int result; - - ksreg = ks_phy_reg(reg); - if (!ksreg) - return 0x0; /* no error return allowed, so use zero */ - - mutex_lock(&ks->lock); - result = ks_rdreg16(ks, ksreg); - mutex_unlock(&ks->lock); - - return result; -} - -static void ks_phy_write(struct net_device *netdev, - int phy, int reg, int value) -{ - struct ks_net *ks = netdev_priv(netdev); - int ksreg; - - ksreg = ks_phy_reg(reg); - if (ksreg) { - mutex_lock(&ks->lock); - ks_wrreg16(ks, ksreg, value); - mutex_unlock(&ks->lock); - } -} - -/** - * ks_read_selftest - read the selftest memory info. - * @ks: The device state - * - * Read and check the TX/RX memory selftest information. - */ -static int ks_read_selftest(struct ks_net *ks) -{ - unsigned both_done = MBIR_TXMBF | MBIR_RXMBF; - int ret = 0; - unsigned rd; - - rd = ks_rdreg16(ks, KS_MBIR); - - if ((rd & both_done) != both_done) { - netdev_warn(ks->netdev, "Memory selftest not finished\n"); - return 0; - } - - if (rd & MBIR_TXMBFA) { - netdev_err(ks->netdev, "TX memory selftest fails\n"); - ret |= 1; - } - - if (rd & MBIR_RXMBFA) { - netdev_err(ks->netdev, "RX memory selftest fails\n"); - ret |= 2; - } - - netdev_info(ks->netdev, "the selftest passes\n"); - return ret; -} - -static void ks_setup(struct ks_net *ks) -{ - u16 w; - - /** - * Configure QMU Transmit - */ - - /* Setup Transmit Frame Data Pointer Auto-Increment (TXFDPR) */ - ks_wrreg16(ks, KS_TXFDPR, TXFDPR_TXFPAI); - - /* Setup Receive Frame Data Pointer Auto-Increment */ - ks_wrreg16(ks, KS_RXFDPR, RXFDPR_RXFPAI); - - /* Setup Receive Frame Threshold - 1 frame (RXFCTFC) */ - ks_wrreg16(ks, KS_RXFCTR, 1 & RXFCTR_RXFCT_MASK); - - /* Setup RxQ Command Control (RXQCR) */ - ks->rc_rxqcr = RXQCR_CMD_CNTL; - ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr); - - /** - * set the force mode to half duplex, default is full duplex - * because if the auto-negotiation fails, most switch uses - * half-duplex. - */ - - w = ks_rdreg16(ks, KS_P1MBCR); - w &= ~BMCR_FULLDPLX; - ks_wrreg16(ks, KS_P1MBCR, w); - - w = TXCR_TXFCE | TXCR_TXPE | TXCR_TXCRC | TXCR_TCGIP; - ks_wrreg16(ks, KS_TXCR, w); - - w = RXCR1_RXFCE | RXCR1_RXBE | RXCR1_RXUE | RXCR1_RXME | RXCR1_RXIPFCC; - - if (ks->promiscuous) /* bPromiscuous */ - w |= (RXCR1_RXAE | RXCR1_RXINVF); - else if (ks->all_mcast) /* Multicast address passed mode */ - w |= (RXCR1_RXAE | RXCR1_RXMAFMA | RXCR1_RXPAFMA); - else /* Normal mode */ - w |= RXCR1_RXPAFMA; - - ks_wrreg16(ks, KS_RXCR1, w); -} /*ks_setup */ - - -static void ks_setup_int(struct ks_net *ks) -{ - ks->rc_ier = 0x00; - /* Clear the interrupts status of the hardware. */ - ks_wrreg16(ks, KS_ISR, 0xffff); - - /* Enables the interrupts of the hardware. */ - ks->rc_ier = (IRQ_LCI | IRQ_TXI | IRQ_RXI); -} /* ks_setup_int */ - -static int ks_hw_init(struct ks_net *ks) -{ -#define MHEADER_SIZE (sizeof(struct type_frame_head) * MAX_RECV_FRAMES) - ks->promiscuous = 0; - ks->all_mcast = 0; - ks->mcast_lst_size = 0; - - ks->frame_head_info = devm_kmalloc(&ks->pdev->dev, MHEADER_SIZE, - GFP_KERNEL); - if (!ks->frame_head_info) - return false; - - ks_set_mac(ks, KS_DEFAULT_MAC_ADDRESS); - return true; -} - -#if defined(CONFIG_OF) -static const struct of_device_id ks8851_ml_dt_ids[] = { - { .compatible = "micrel,ks8851-mll" }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, ks8851_ml_dt_ids); -#endif - -static int ks8851_probe(struct platform_device *pdev) -{ - int err; - struct net_device *netdev; - struct ks_net *ks; - u16 id, data; - const char *mac; - - netdev = alloc_etherdev(sizeof(struct ks_net)); - if (!netdev) - return -ENOMEM; - - SET_NETDEV_DEV(netdev, &pdev->dev); - - ks = netdev_priv(netdev); - ks->netdev = netdev; - - ks->hw_addr = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(ks->hw_addr)) { - err = PTR_ERR(ks->hw_addr); - goto err_free; - } - - ks->hw_addr_cmd = devm_platform_ioremap_resource(pdev, 1); - if (IS_ERR(ks->hw_addr_cmd)) { - err = PTR_ERR(ks->hw_addr_cmd); - goto err_free; - } - - err = ks_check_endian(ks); - if (err) - goto err_free; - - netdev->irq = platform_get_irq(pdev, 0); - - if ((int)netdev->irq < 0) { - err = netdev->irq; - goto err_free; - } - - ks->pdev = pdev; - - mutex_init(&ks->lock); - spin_lock_init(&ks->statelock); - - netdev->netdev_ops = &ks_netdev_ops; - netdev->ethtool_ops = &ks_ethtool_ops; - - /* setup mii state */ - ks->mii.dev = netdev; - ks->mii.phy_id = 1, - ks->mii.phy_id_mask = 1; - ks->mii.reg_num_mask = 0xf; - ks->mii.mdio_read = ks_phy_read; - ks->mii.mdio_write = ks_phy_write; - - netdev_info(netdev, "message enable is %d\n", msg_enable); - /* set the default message enable */ - ks->msg_enable = netif_msg_init(msg_enable, (NETIF_MSG_DRV | - NETIF_MSG_PROBE | - NETIF_MSG_LINK)); - ks_read_config(ks); - - /* simple check for a valid chip being connected to the bus */ - if ((ks_rdreg16(ks, KS_CIDER) & ~CIDER_REV_MASK) != CIDER_ID) { - netdev_err(netdev, "failed to read device ID\n"); - err = -ENODEV; - goto err_free; - } - - if (ks_read_selftest(ks)) { - netdev_err(netdev, "failed to read device ID\n"); - err = -ENODEV; - goto err_free; - } - - err = register_netdev(netdev); - if (err) - goto err_free; - - platform_set_drvdata(pdev, netdev); - - ks_soft_reset(ks, GRR_GSR); - ks_hw_init(ks); - ks_disable_qmu(ks); - ks_setup(ks); - ks_setup_int(ks); - - data = ks_rdreg16(ks, KS_OBCR); - ks_wrreg16(ks, KS_OBCR, data | OBCR_ODS_16mA); - - /* overwriting the default MAC address */ - if (pdev->dev.of_node) { - mac = of_get_mac_address(pdev->dev.of_node); - if (!IS_ERR(mac)) - ether_addr_copy(ks->mac_addr, mac); - } else { - struct ks8851_mll_platform_data *pdata; - - pdata = dev_get_platdata(&pdev->dev); - if (!pdata) { - netdev_err(netdev, "No platform data\n"); - err = -ENODEV; - goto err_pdata; - } - memcpy(ks->mac_addr, pdata->mac_addr, ETH_ALEN); - } - if (!is_valid_ether_addr(ks->mac_addr)) { - /* Use random MAC address if none passed */ - eth_random_addr(ks->mac_addr); - netdev_info(netdev, "Using random mac address\n"); - } - netdev_info(netdev, "Mac address is: %pM\n", ks->mac_addr); - - memcpy(netdev->dev_addr, ks->mac_addr, ETH_ALEN); - - ks_set_mac(ks, netdev->dev_addr); - - id = ks_rdreg16(ks, KS_CIDER); - - netdev_info(netdev, "Found chip, family: 0x%x, id: 0x%x, rev: 0x%x\n", - (id >> 8) & 0xff, (id >> 4) & 0xf, (id >> 1) & 0x7); - return 0; - -err_pdata: - unregister_netdev(netdev); -err_free: - free_netdev(netdev); - return err; -} - -static int ks8851_remove(struct platform_device *pdev) -{ - struct net_device *netdev = platform_get_drvdata(pdev); - - unregister_netdev(netdev); - free_netdev(netdev); - return 0; - -} - -static struct platform_driver ks8851_platform_driver = { - .driver = { - .name = DRV_NAME, - .of_match_table = of_match_ptr(ks8851_ml_dt_ids), - }, - .probe = ks8851_probe, - .remove = ks8851_remove, -}; - -module_platform_driver(ks8851_platform_driver); - -MODULE_DESCRIPTION("KS8851 MLL Network driver"); -MODULE_AUTHOR("David Choi "); -MODULE_LICENSE("GPL"); -module_param_named(message, msg_enable, int, 0); -MODULE_PARM_DESC(message, "Message verbosity level (0=none, 31=all)"); -