From 03eb3eb4d4d56414efbe05a5521b2fc4ce175cb7 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Fri, 23 Jun 2017 14:33:28 -0500 Subject: [PATCH 1/3] net: qcom/emac: add shutdown function The shutdown function halts all DMA and interrupts, so that all operations are discontinued when the system shuts down, e.g. via kexec or a forced reboot. Tested-by: Tyler Baicar Signed-off-by: Timur Tabi Signed-off-by: David S. Miller --- drivers/net/ethernet/qualcomm/emac/emac.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c index 98a326faea29..77c5c929f141 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac.c +++ b/drivers/net/ethernet/qualcomm/emac/emac.c @@ -762,6 +762,19 @@ static int emac_remove(struct platform_device *pdev) return 0; } +static void emac_shutdown(struct platform_device *pdev) +{ + struct net_device *netdev = dev_get_drvdata(&pdev->dev); + struct emac_adapter *adpt = netdev_priv(netdev); + struct emac_sgmii *sgmii = &adpt->phy; + + /* Closing the SGMII turns off its interrupts */ + sgmii->close(adpt); + + /* Resetting the MAC turns off all DMA and its interrupts */ + emac_mac_reset(adpt); +} + static struct platform_driver emac_platform_driver = { .probe = emac_probe, .remove = emac_remove, @@ -770,6 +783,7 @@ static struct platform_driver emac_platform_driver = { .of_match_table = emac_dt_match, .acpi_match_table = ACPI_PTR(emac_acpi_match), }, + .shutdown = emac_shutdown, }; module_platform_driver(emac_platform_driver); From 867ae6abc24967188db0914de170512e36592eb3 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Fri, 23 Jun 2017 14:33:29 -0500 Subject: [PATCH 2/3] net: qcom/emac: do not reset the EMAC during initialization On ACPI systems, the driver depends on firmware pre-initializing the EMAC because we don't have access to the clocks, and the EMAC has specific clock programming requirements. Therefore, we don't want to reset the EMAC while we are completing the initialization. Tested-by: Richard Ruigrok Signed-off-by: Timur Tabi Signed-off-by: David S. Miller --- drivers/net/ethernet/qualcomm/emac/emac.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c index 77c5c929f141..746d94e28470 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac.c +++ b/drivers/net/ethernet/qualcomm/emac/emac.c @@ -683,8 +683,6 @@ static int emac_probe(struct platform_device *pdev) goto err_undo_mdiobus; } - emac_mac_reset(adpt); - /* set hw features */ netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_HW_VLAN_CTAG_RX | From ceef551faacb1783040d9c1a10d4baad9548f37e Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Fri, 23 Jun 2017 14:33:30 -0500 Subject: [PATCH 3/3] net: qcom/emac: add support for emulation systems On emulation systems, the EMAC's internal PHY ("SGMII") is not present, but is not needed for network functionality. So just display a warning message and ignore the SGMII. Tested-by: Philip Elcan Tested-by: Adam Wallis Signed-off-by: Timur Tabi Signed-off-by: David S. Miller --- .../net/ethernet/qualcomm/emac/emac-sgmii.c | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c b/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c index 18c184ee1f3c..29ba37a08372 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c +++ b/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c @@ -297,6 +297,14 @@ static const struct of_device_id emac_sgmii_dt_match[] = { {} }; +/* Dummy function for systems without an internal PHY. This avoids having + * to check for NULL pointers before calling the functions. + */ +static int emac_sgmii_dummy(struct emac_adapter *adpt) +{ + return 0; +} + int emac_sgmii_config(struct platform_device *pdev, struct emac_adapter *adpt) { struct platform_device *sgmii_pdev = NULL; @@ -311,8 +319,19 @@ int emac_sgmii_config(struct platform_device *pdev, struct emac_adapter *adpt) emac_sgmii_acpi_match); if (!dev) { - dev_err(&pdev->dev, "cannot find internal phy node\n"); - return -ENODEV; + dev_warn(&pdev->dev, "cannot find internal phy node\n"); + /* There is typically no internal PHY on emulation + * systems, so if we can't find the node, assume + * we are on an emulation system and stub-out + * support for the internal PHY. These systems only + * use ACPI. + */ + phy->open = emac_sgmii_dummy; + phy->close = emac_sgmii_dummy; + phy->link_up = emac_sgmii_dummy; + phy->link_down = emac_sgmii_dummy; + + return 0; } sgmii_pdev = to_platform_device(dev);