Adds runtime pm support for 7560.
As part of probe procedure auto suspend is enabled and auto suspend
delay is set to 5000 ms for runtime pm use. Later auto flag is set
to power manage the device at run time.
On successful communication establishment between host and device the
device usage counter is dropped and request to put the device into
sleep state (suspend).
In TX path, the device usage counter is raised and device is moved out
of sleep(resume) for data transmission. In RX path, if the device has
some data to be sent it request host platform to change the power state
by giving PCI PME message.
Signed-off-by: M Chetan Kumar <m.chetan.kumar@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
*/
#include <linux/delay.h>
+#include <linux/pm_runtime.h>
#include "iosm_ipc_chnl_cfg.h"
#include "iosm_ipc_devlink.h"
/* Complete all memory stores after setting bit */
smp_mb__after_atomic();
+ if (ipc_imem->pcie->pci->device == INTEL_CP_DEVICE_7560_ID) {
+ pm_runtime_mark_last_busy(ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_imem->dev);
+ }
+
return;
err_ipc_mux_deinit:
/* forward MDM_NOT_READY to listeners */
ipc_uevent_send(ipc_imem->dev, UEVENT_MDM_NOT_READY);
+ pm_runtime_get_sync(ipc_imem->dev);
hrtimer_cancel(&ipc_imem->td_alloc_timer);
hrtimer_cancel(&ipc_imem->tdupdate_timer);
set_bit(IOSM_DEVLINK_INIT, &ipc_imem->flag);
}
+
+ if (!pm_runtime_enabled(ipc_imem->dev))
+ pm_runtime_enable(ipc_imem->dev);
+
+ pm_runtime_set_autosuspend_delay(ipc_imem->dev,
+ IPC_MEM_AUTO_SUSPEND_DELAY_MS);
+ pm_runtime_use_autosuspend(ipc_imem->dev);
+ pm_runtime_allow(ipc_imem->dev);
+ pm_runtime_mark_last_busy(ipc_imem->dev);
+
return ipc_imem;
devlink_channel_fail:
ipc_devlink_deinit(ipc_imem->ipc_devlink);
#define FULLY_FUNCTIONAL 0
#define IOSM_DEVLINK_INIT 1
+#define IPC_MEM_AUTO_SUSPEND_DELAY_MS 5000
+
/* List of the supported UL/DL pipes. */
enum ipc_mem_pipes {
IPC_MEM_PIPE_0 = 0,
#include <linux/acpi.h>
#include <linux/bitfield.h>
#include <linux/module.h>
+#include <linux/pm_runtime.h>
#include <net/rtnetlink.h>
#include "iosm_ipc_imem.h"
return 0;
}
-static SIMPLE_DEV_PM_OPS(iosm_ipc_pm, ipc_pcie_suspend_cb, ipc_pcie_resume_cb);
+static DEFINE_RUNTIME_DEV_PM_OPS(iosm_ipc_pm, ipc_pcie_suspend_cb,
+ ipc_pcie_resume_cb, NULL);
static struct pci_driver iosm_ipc_driver = {
.name = KBUILD_MODNAME,
* Copyright (C) 2020-21 Intel Corporation.
*/
+#include <linux/pm_runtime.h>
+
#include "iosm_ipc_chnl_cfg.h"
#include "iosm_ipc_imem_ops.h"
#include "iosm_ipc_port.h"
struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port);
int ret = 0;
+ pm_runtime_get_sync(ipc_port->ipc_imem->dev);
ipc_port->channel = ipc_imem_sys_port_open(ipc_port->ipc_imem,
ipc_port->chl_id,
IPC_HP_CDEV_OPEN);
if (!ipc_port->channel)
ret = -EIO;
+ pm_runtime_mark_last_busy(ipc_port->ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_port->ipc_imem->dev);
+
return ret;
}
{
struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port);
+ pm_runtime_get_sync(ipc_port->ipc_imem->dev);
ipc_imem_sys_port_close(ipc_port->ipc_imem, ipc_port->channel);
+ pm_runtime_mark_last_busy(ipc_port->ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_port->ipc_imem->dev);
}
/* transfer control data to modem */
static int ipc_port_ctrl_tx(struct wwan_port *port, struct sk_buff *skb)
{
struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port);
+ int ret;
- return ipc_imem_sys_cdev_write(ipc_port, skb);
+ pm_runtime_get_sync(ipc_port->ipc_imem->dev);
+ ret = ipc_imem_sys_cdev_write(ipc_port, skb);
+ pm_runtime_mark_last_busy(ipc_port->ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_port->ipc_imem->dev);
+
+ return ret;
}
static const struct wwan_port_ops ipc_wwan_ctrl_ops = {
* Copyright (C) 2020-2021 Intel Corporation.
*/
+#include <linux/pm_runtime.h>
#include <linux/wwan.h>
+
#include "iosm_ipc_trace.h"
/* sub buffer size and number of sub buffer */
if (ret)
return ret;
+ pm_runtime_get_sync(ipc_trace->ipc_imem->dev);
+
mutex_lock(&ipc_trace->trc_mutex);
if (val == TRACE_ENABLE && ipc_trace->mode != TRACE_ENABLE) {
ipc_trace->channel = ipc_imem_sys_port_open(ipc_trace->ipc_imem,
ret = count;
unlock:
mutex_unlock(&ipc_trace->trc_mutex);
+
+ pm_runtime_mark_last_busy(ipc_trace->ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_trace->ipc_imem->dev);
+
return ret;
}
#include <linux/etherdevice.h>
#include <linux/if_arp.h>
#include <linux/if_link.h>
+#include <linux/pm_runtime.h>
#include <linux/rtnetlink.h>
#include <linux/wwan.h>
#include <net/pkt_sched.h>
struct iosm_netdev_priv *priv = wwan_netdev_drvpriv(netdev);
struct iosm_wwan *ipc_wwan = priv->ipc_wwan;
int if_id = priv->if_id;
+ int ret = 0;
if (if_id < IP_MUX_SESSION_START ||
if_id >= ARRAY_SIZE(ipc_wwan->sub_netlist))
return -EINVAL;
+ pm_runtime_get_sync(ipc_wwan->ipc_imem->dev);
/* get channel id */
priv->ch_id = ipc_imem_sys_wwan_open(ipc_wwan->ipc_imem, if_id);
dev_err(ipc_wwan->dev,
"cannot connect wwan0 & id %d to the IPC mem layer",
if_id);
- return -ENODEV;
+ ret = -ENODEV;
+ goto err_out;
}
/* enable tx path, DL data may follow */
dev_dbg(ipc_wwan->dev, "Channel id %d allocated to if_id %d",
priv->ch_id, priv->if_id);
- return 0;
+err_out:
+ pm_runtime_mark_last_busy(ipc_wwan->ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_wwan->ipc_imem->dev);
+
+ return ret;
}
/* Bring-down the wwan net link */
netif_stop_queue(netdev);
+ pm_runtime_get_sync(priv->ipc_wwan->ipc_imem->dev);
ipc_imem_sys_wwan_close(priv->ipc_wwan->ipc_imem, priv->if_id,
priv->ch_id);
priv->ch_id = -1;
+ pm_runtime_mark_last_busy(priv->ipc_wwan->ipc_imem->dev);
+ pm_runtime_put_autosuspend(priv->ipc_wwan->ipc_imem->dev);
return 0;
}
if_id >= ARRAY_SIZE(ipc_wwan->sub_netlist))
return -EINVAL;
+ pm_runtime_get(ipc_wwan->ipc_imem->dev);
/* Send the SKB to device for transmission */
ret = ipc_imem_sys_wwan_transmit(ipc_wwan->ipc_imem,
if_id, priv->ch_id, skb);
ret = NETDEV_TX_BUSY;
dev_err(ipc_wwan->dev, "unable to push packets");
} else {
+ pm_runtime_mark_last_busy(ipc_wwan->ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_wwan->ipc_imem->dev);
goto exit;
}
+ pm_runtime_mark_last_busy(ipc_wwan->ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_wwan->ipc_imem->dev);
+
return ret;
exit: