mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-23 01:31:30 +03:00
- Renamed the directory to oak - Updated the make files to compile the source - Removed unused script ESDP-16549 Bug 3882239 Bug 3824037 Change-Id: I1dee5def85b6e25f88dff999f1051bfe62d5613b Signed-off-by: Sheetal Tigadoli <stigadoli@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2856988 Reviewed-by: Sumeet Gupta <sumeetg@nvidia.com> GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
223 lines
6.1 KiB
C
223 lines
6.1 KiB
C
/*
|
|
*
|
|
* If you received this File from Marvell, you may opt to use, redistribute and/or
|
|
* modify this File in accordance with the terms and conditions of the General
|
|
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
|
|
* available along with the File in the license.txt file or by writing to the Free
|
|
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
|
|
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
|
|
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
|
|
* DISCLAIMED. The GPL License provides additional details about this warranty
|
|
* disclaimer.
|
|
*
|
|
*/
|
|
|
|
#ifdef CONFIG_PM
|
|
|
|
#include "oak_dpm.h"
|
|
#include "oak_net.h"
|
|
|
|
/* Name : oak_dpm_set_power_state
|
|
* Returns : void
|
|
* Parameters : struct device *dev, pci_power_t state
|
|
* Description : This function set the device power state
|
|
*/
|
|
void oak_dpm_set_power_state(struct device *dev, pci_power_t state)
|
|
{
|
|
int retval;
|
|
pci_power_t D0 = 0;
|
|
struct net_device *ndev = dev_get_drvdata(dev);
|
|
|
|
oak_t *np = netdev_priv(ndev);
|
|
|
|
/* If user input state is D0 and current_state not D0
|
|
* i.e. current state is D3hot (D1, D2, D3) then
|
|
* we call resume operation
|
|
*/
|
|
if (state == PCI_D0 && np->pdev->current_state != D0) {
|
|
retval = oak_dpm_resume(dev);
|
|
if (retval)
|
|
pr_info("oak_dpm_resume: failed.\n");
|
|
}
|
|
/* If user input state is D1 or D2 or D3 and current_state D0
|
|
* then we do the suspend operation
|
|
*/
|
|
else if (((state == PCI_D1) ||
|
|
(state == PCI_D2) ||
|
|
(state == PCI_D3hot)) && (np->pdev->current_state == D0)) {
|
|
retval = oak_dpm_suspend(dev);
|
|
if (retval != 0)
|
|
pr_info("oak_dpm_suspend: failed\n");
|
|
}
|
|
}
|
|
|
|
/* Name : oak_dpm_state_store
|
|
* Returns : ssize_t
|
|
* Parameters : struct device *dev, struct device_attribute *attr,
|
|
* const char *buf, size_t count
|
|
* Description : This function store the sysfs entry
|
|
*/
|
|
static ssize_t oak_dpm_state_store(struct device *dev,
|
|
struct device_attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
pci_power_t pwr;
|
|
bool d0, d1, d2, d3;
|
|
|
|
/* Validate user input */
|
|
d0 = sysfs_streq(buf, "D0");
|
|
d1 = sysfs_streq(buf, "D1");
|
|
d2 = sysfs_streq(buf, "D2");
|
|
d3 = sysfs_streq(buf, "D3");
|
|
|
|
/* D0 as input, set device as D0
|
|
* D1, D2, and D3 as input, set the device as D3
|
|
* For any other input, error message is triggered.
|
|
*/
|
|
if (d0) {
|
|
pwr = PCI_D0;
|
|
oak_dpm_set_power_state(dev, pwr);
|
|
} else if (d1 || d2 || d3) {
|
|
pwr = PCI_D3hot;
|
|
oak_dpm_set_power_state(dev, pwr);
|
|
} else {
|
|
pr_err("oak: Wrong input, Device power states are D0, D1, D2 or D3\n");
|
|
}
|
|
|
|
/* With the current sysfs implementation the kobject reference count is
|
|
* only modified directly by the function sysfs_schedule_callback().
|
|
*/
|
|
return count;
|
|
}
|
|
|
|
/* The sysfs kernel object device attribute file oak_dpm_state
|
|
* is wrtite only. Hence only oak_dpm_state_store function is
|
|
* called by kernel when a user does input to oak_dpm_state file
|
|
*/
|
|
static DEVICE_ATTR_WO(oak_dpm_state);
|
|
|
|
/* Name : oak_dpm_create_sysfs
|
|
* Returns : void
|
|
* Parameters : oak_t *np
|
|
* Description : This function creates sysfs entry for setting device power
|
|
* states D0, D1, D2 and D3.
|
|
*/
|
|
void oak_dpm_create_sysfs(oak_t *np)
|
|
{
|
|
int status;
|
|
|
|
status = sysfs_create_file(&np->pdev->dev.kobj,
|
|
&dev_attr_oak_dpm_state.attr);
|
|
if (status)
|
|
pr_err("oak: Failed to create sysfs entry\n");
|
|
}
|
|
|
|
/* Name : oak_dpm_remove_sysfs
|
|
* Returns : void
|
|
* Parameters : oak_t *np
|
|
* Description : This function removes sysfs entry of device power states
|
|
*/
|
|
void oak_dpm_remove_sysfs(oak_t *np)
|
|
{
|
|
sysfs_remove_file(&np->pdev->dev.kobj, &dev_attr_oak_dpm_state.attr);
|
|
}
|
|
|
|
#ifdef CONFIG_PM_SLEEP
|
|
|
|
/* Name : oak_dpm_suspend
|
|
* Returns : int
|
|
* Parameters : struct device *dev
|
|
* Description : This function is called when system goes into suspend state
|
|
* and put the device into sleep state
|
|
*/
|
|
int __maybe_unused oak_dpm_suspend(struct device *dev)
|
|
{
|
|
struct net_device *ndev = dev_get_drvdata(dev);
|
|
oak_t *np = netdev_priv(ndev);
|
|
int retval = 0;
|
|
|
|
/* If interface is up then, do driver specific operations
|
|
* gracefully close the interface
|
|
*/
|
|
retval = netif_running(ndev);
|
|
if (retval)
|
|
oak_net_close(ndev);
|
|
|
|
/* Inform to PCI core, wake me up from D3hot when event triggers */
|
|
pci_enable_wake(np->pdev, PCI_D3hot, true);
|
|
|
|
/* Release the oak hardware */
|
|
oak_release_hardware(np->pdev);
|
|
|
|
/* To synchronize changes hold rtnl lock */
|
|
rtnl_lock();
|
|
|
|
/* Save the PCI state and prepare to go for sleep */
|
|
pci_save_state(np->pdev);
|
|
pci_prepare_to_sleep(np->pdev);
|
|
|
|
/* Set the device power state as D3hot */
|
|
retval = pci_set_power_state(np->pdev, PCI_D3hot);
|
|
if (retval == 0)
|
|
pr_info("%s: dpm state=D%d\n", __func__,
|
|
np->pdev->current_state);
|
|
else
|
|
pr_err("%s: Failed to set the device power state err: %d\n",
|
|
__func__, retval);
|
|
|
|
/* Release the rtnl lock */
|
|
rtnl_unlock();
|
|
|
|
return retval;
|
|
}
|
|
|
|
/* Name : oak_dpm_resume
|
|
* Returns : int
|
|
* Parameters : struct device *dev
|
|
* Description : This function called when system goes into resume state and put
|
|
* the device into active state
|
|
*/
|
|
int __maybe_unused oak_dpm_resume(struct device *dev)
|
|
{
|
|
struct net_device *ndev = dev_get_drvdata(dev);
|
|
oak_t *np = netdev_priv(ndev);
|
|
int retval = 0;
|
|
|
|
/* To synchronize changes hold rtnl lock */
|
|
rtnl_lock();
|
|
|
|
/* Set the device power state as D0 */
|
|
retval = pci_set_power_state(np->pdev, PCI_D0);
|
|
if (retval == 0)
|
|
pr_info("%s: dpm state=D%d\n", __func__,
|
|
np->pdev->current_state);
|
|
|
|
/* Restore the PCI state */
|
|
pci_restore_state(np->pdev);
|
|
|
|
/* The driver specific operations
|
|
* Initialize the oak hardware
|
|
* If interface is up, then call oak net open
|
|
*/
|
|
retval = oak_init_hardware(np->pdev);
|
|
if (retval) {
|
|
pr_err("%s: oak init hardware Not Successful %d\n", __func__,
|
|
retval);
|
|
} else {
|
|
retval = netif_running(ndev);
|
|
if (retval) {
|
|
retval = oak_net_open(ndev);
|
|
if (retval)
|
|
pr_err("%s: oak net open failed\n", __func__);
|
|
}
|
|
}
|
|
|
|
/* Release the rtnl lock */
|
|
rtnl_unlock();
|
|
|
|
return retval;
|
|
}
|
|
#endif
|
|
#endif
|