From 6fc9bd51472241ee71e3db45818233b5a641c732 Mon Sep 17 00:00:00 2001 From: Srinivas Ramachandran Date: Sun, 22 Dec 2019 21:58:32 -0800 Subject: [PATCH] nvethernet: Invoke API to backup/restore registers Issue: During SOC suspend, the MAC is placed in reset. This causes all dynamic configurations done by SW on the MAC core registers is lost. When SOC resumes, MAC is initialized to power-on-default configuration, while other SW components still have previously set configuration. This results in mismatch between HW/SW configuration. Fix: Invoke APIs osi_save_registers(), osi_restore_registers() to backup and restore the MAC core configuration registers before suspend and after resume respectively. Bug 200561046 Change-Id: I22183ba86fe9e7a7d8f9efb6a90c265182c5c68a Signed-off-by: Srinivas Ramachandran Reviewed-on: https://git-master.nvidia.com/r/2267402 Reviewed-by: mobile promotions Tested-by: mobile promotions --- .../ethernet/nvidia/nvethernet/ether_linux.c | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c index 7e3b5765..9eade3a4 100644 --- a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c +++ b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -3924,6 +3924,17 @@ static int ether_suspend_noirq(struct device *dev) if (!netif_running(ndev)) return 0; + /* Since MAC is placed in reset during suspend, take a backup of + * current configuration so that SW view of HW is maintained across + * suspend/resume. + */ + if (osi_core->backup_config) { + if (osi_save_registers(osi_core)) { + dev_err(dev, "Failed to backup MAC core registers\n"); + return -EBUSY; + } + } + /* Stop workqueue while DUT is going to suspend state */ ether_stats_work_queue_stop(pdata); @@ -4061,6 +4072,7 @@ static int ether_resume_noirq(struct device *dev) { struct net_device *ndev = dev_get_drvdata(dev); struct ether_priv_data *pdata = netdev_priv(ndev); + struct osi_core_priv_data *osi_core = pdata->osi_core; int ret = 0; if (!netif_running(ndev)) @@ -4081,6 +4093,18 @@ static int ether_resume_noirq(struct device *dev) return ret; } + /* Since MAC is brought of reset, all the SW configuration done before + * suspend/resume will be overwritten by power-on-default values. + * Restore the backup of the MAC configuration to maintain consistency + * between SW/HW state. + */ + if (osi_core->backup_config) { + if (osi_restore_registers(osi_core)) { + //TODO: Ideally, undo MAC init/resume & return. + dev_err(dev, "Failed to restore MAC core registers\n"); + } + } + return 0; }