Files
linux-nv-oot/drivers/net/ethernet/marvell/oak/oak_dpm.c
Sheetal Tigadoli 748fa9c699 marvell:Add compilation support to driver
- 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>
2023-03-21 02:27:20 -07:00

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