mhi: core: Enable runtime PM on pcie device
Enable runtime PM on PCIe device to ensure sync with PCIe framework. Change-Id: Ied432440df0dc788642fe1a1a8d9195b6cc1cf7c Signed-off-by: Andrei Danaila <adanaila@codeaurora.org> Signed-off-by: Tony Truong <truong@codeaurora.org>
This commit is contained in:
parent
ba0558f8bb
commit
2d40f51ad5
5 changed files with 38 additions and 33 deletions
|
@ -608,8 +608,8 @@ enum MHI_STATUS mhi_init_state_transition(struct mhi_device_ctxt *mhi_dev_ctxt,
|
||||||
enum STATE_TRANSITION new_state);
|
enum STATE_TRANSITION new_state);
|
||||||
enum MHI_STATUS mhi_wait_for_mdm(struct mhi_device_ctxt *mhi_dev_ctxt);
|
enum MHI_STATUS mhi_wait_for_mdm(struct mhi_device_ctxt *mhi_dev_ctxt);
|
||||||
enum hrtimer_restart mhi_initiate_m1(struct hrtimer *timer);
|
enum hrtimer_restart mhi_initiate_m1(struct hrtimer *timer);
|
||||||
int mhi_pci_suspend(struct pci_dev *dev, pm_message_t state);
|
int mhi_pci_suspend(struct device *dev);
|
||||||
int mhi_pci_resume(struct pci_dev *dev);
|
int mhi_pci_resume(struct device *dev);
|
||||||
int mhi_init_pcie_device(struct mhi_pcie_dev_info *mhi_pcie_dev);
|
int mhi_init_pcie_device(struct mhi_pcie_dev_info *mhi_pcie_dev);
|
||||||
int mhi_init_pm_sysfs(struct device *dev);
|
int mhi_init_pm_sysfs(struct device *dev);
|
||||||
void mhi_rem_pm_sysfs(struct device *dev);
|
void mhi_rem_pm_sysfs(struct device *dev);
|
||||||
|
|
|
@ -208,17 +208,17 @@ msi_config_err:
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct dev_pm_ops pm_ops = {
|
static const struct dev_pm_ops pm_ops = {
|
||||||
.runtime_suspend = mhi_runtime_suspend,
|
SET_RUNTIME_PM_OPS(mhi_runtime_suspend, mhi_runtime_resume, NULL)
|
||||||
.runtime_resume = mhi_runtime_resume,
|
SET_SYSTEM_SLEEP_PM_OPS(mhi_pci_suspend, mhi_pci_resume)
|
||||||
.runtime_idle = NULL,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct pci_driver mhi_pcie_driver = {
|
static struct pci_driver mhi_pcie_driver = {
|
||||||
.name = "mhi_pcie_drv",
|
.name = "mhi_pcie_drv",
|
||||||
.id_table = mhi_pcie_device_id,
|
.id_table = mhi_pcie_device_id,
|
||||||
.probe = mhi_pci_probe,
|
.probe = mhi_pci_probe,
|
||||||
.suspend = mhi_pci_suspend,
|
.driver = {
|
||||||
.resume = mhi_pci_resume,
|
.pm = &pm_ops
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static int mhi_pci_probe(struct pci_dev *pcie_device,
|
static int mhi_pci_probe(struct pci_dev *pcie_device,
|
||||||
|
@ -239,6 +239,7 @@ static int mhi_pci_probe(struct pci_dev *pcie_device,
|
||||||
mhi_devices.nr_of_devices++;
|
mhi_devices.nr_of_devices++;
|
||||||
plat_dev = mhi_devices.device_list[nr_dev].plat_dev;
|
plat_dev = mhi_devices.device_list[nr_dev].plat_dev;
|
||||||
pcie_device->dev.of_node = plat_dev->dev.of_node;
|
pcie_device->dev.of_node = plat_dev->dev.of_node;
|
||||||
|
pm_runtime_put_noidle(&pcie_device->dev);
|
||||||
mhi_pcie_dev->pcie_device = pcie_device;
|
mhi_pcie_dev->pcie_device = pcie_device;
|
||||||
mhi_pcie_dev->mhi_pcie_driver = &mhi_pcie_driver;
|
mhi_pcie_dev->mhi_pcie_driver = &mhi_pcie_driver;
|
||||||
mhi_pcie_dev->mhi_pci_link_event.events =
|
mhi_pcie_dev->mhi_pci_link_event.events =
|
||||||
|
@ -272,7 +273,6 @@ static struct platform_driver mhi_plat_driver = {
|
||||||
.name = "mhi",
|
.name = "mhi",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.of_match_table = mhi_plat_match,
|
.of_match_table = mhi_plat_match,
|
||||||
.pm = &pm_ops,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -325,6 +325,7 @@ enum MHI_STATUS mhi_open_channel(struct mhi_client_handle *client_handle)
|
||||||
if (MHI_STATUS_SUCCESS != ret_val)
|
if (MHI_STATUS_SUCCESS != ret_val)
|
||||||
mhi_log(MHI_MSG_ERROR,
|
mhi_log(MHI_MSG_ERROR,
|
||||||
"Failed to start chan 0x%x\n", chan);
|
"Failed to start chan 0x%x\n", chan);
|
||||||
|
BUG_ON(ret_val);
|
||||||
client_handle->chan_status = 1;
|
client_handle->chan_status = 1;
|
||||||
mhi_log(MHI_MSG_INFO,
|
mhi_log(MHI_MSG_INFO,
|
||||||
"Exited chan 0x%x\n", chan);
|
"Exited chan 0x%x\n", chan);
|
||||||
|
@ -655,7 +656,8 @@ static enum MHI_STATUS mhi_queue_dma_xfer(
|
||||||
MHI_ASSERT(VALID_BUF(buf, buf_len, mhi_dev_ctxt),
|
MHI_ASSERT(VALID_BUF(buf, buf_len, mhi_dev_ctxt),
|
||||||
"Client buffer is of invalid length\n");
|
"Client buffer is of invalid length\n");
|
||||||
chan = client_handle->chan_info.chan_nr;
|
chan = client_handle->chan_info.chan_nr;
|
||||||
pm_runtime_get(&mhi_dev_ctxt->dev_info->plat_dev->dev);
|
mhi_log(MHI_MSG_INFO, "Getting Reference %d", chan);
|
||||||
|
pm_runtime_get(&mhi_dev_ctxt->dev_info->pcie_device->dev);
|
||||||
|
|
||||||
pkt_loc = mhi_dev_ctxt->mhi_local_chan_ctxt[chan].wp;
|
pkt_loc = mhi_dev_ctxt->mhi_local_chan_ctxt[chan].wp;
|
||||||
pkt_loc->data_tx_pkt.buffer_ptr = buf;
|
pkt_loc->data_tx_pkt.buffer_ptr = buf;
|
||||||
|
@ -697,8 +699,9 @@ static enum MHI_STATUS mhi_queue_dma_xfer(
|
||||||
read_unlock_irqrestore(&mhi_dev_ctxt->xfer_lock, flags);
|
read_unlock_irqrestore(&mhi_dev_ctxt->xfer_lock, flags);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
pm_runtime_mark_last_busy(&mhi_dev_ctxt->dev_info->plat_dev->dev);
|
pm_runtime_mark_last_busy(&mhi_dev_ctxt->dev_info->pcie_device->dev);
|
||||||
pm_runtime_put_noidle(&mhi_dev_ctxt->dev_info->plat_dev->dev);
|
mhi_log(MHI_MSG_INFO, "Putting Reference %d", chan);
|
||||||
|
pm_runtime_put_noidle(&mhi_dev_ctxt->dev_info->pcie_device->dev);
|
||||||
return ret_val;
|
return ret_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -769,8 +772,8 @@ enum MHI_STATUS mhi_send_cmd(struct mhi_device_ctxt *mhi_dev_ctxt,
|
||||||
mhi_dev_ctxt->mhi_state,
|
mhi_dev_ctxt->mhi_state,
|
||||||
mhi_dev_ctxt->dev_exec_env,
|
mhi_dev_ctxt->dev_exec_env,
|
||||||
chan, cmd);
|
chan, cmd);
|
||||||
|
mhi_log(MHI_MSG_INFO, "Getting Reference %d", chan);
|
||||||
pm_runtime_get(&mhi_dev_ctxt->dev_info->plat_dev->dev);
|
pm_runtime_get(&mhi_dev_ctxt->dev_info->pcie_device->dev);
|
||||||
/*
|
/*
|
||||||
* If there is a cmd pending a device confirmation,
|
* If there is a cmd pending a device confirmation,
|
||||||
* do not send anymore for this channel
|
* do not send anymore for this channel
|
||||||
|
@ -834,8 +837,9 @@ enum MHI_STATUS mhi_send_cmd(struct mhi_device_ctxt *mhi_dev_ctxt,
|
||||||
error_general:
|
error_general:
|
||||||
mutex_unlock(&mhi_dev_ctxt->mhi_cmd_mutex_list[PRIMARY_CMD_RING]);
|
mutex_unlock(&mhi_dev_ctxt->mhi_cmd_mutex_list[PRIMARY_CMD_RING]);
|
||||||
error_invalid:
|
error_invalid:
|
||||||
pm_runtime_mark_last_busy(&mhi_dev_ctxt->dev_info->plat_dev->dev);
|
pm_runtime_mark_last_busy(&mhi_dev_ctxt->dev_info->pcie_device->dev);
|
||||||
pm_runtime_put_noidle(&mhi_dev_ctxt->dev_info->plat_dev->dev);
|
mhi_log(MHI_MSG_INFO, "Putting Reference %d", chan);
|
||||||
|
pm_runtime_put_noidle(&mhi_dev_ctxt->dev_info->pcie_device->dev);
|
||||||
|
|
||||||
atomic_dec(&mhi_dev_ctxt->flags.data_pending);
|
atomic_dec(&mhi_dev_ctxt->flags.data_pending);
|
||||||
mhi_log(MHI_MSG_INFO, "Exited ret %d.\n", ret_val);
|
mhi_log(MHI_MSG_INFO, "Exited ret %d.\n", ret_val);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 and
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
@ -39,15 +39,15 @@ static struct attribute_group mhi_attribute_group = {
|
||||||
.attrs = mhi_attributes,
|
.attrs = mhi_attributes,
|
||||||
};
|
};
|
||||||
|
|
||||||
int mhi_pci_suspend(struct pci_dev *pcie_dev, pm_message_t state)
|
int mhi_pci_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
int r = 0;
|
int r = 0;
|
||||||
struct mhi_device_ctxt *mhi_dev_ctxt = pcie_dev->dev.platform_data;
|
struct mhi_device_ctxt *mhi_dev_ctxt = dev->platform_data;
|
||||||
|
|
||||||
if (NULL == mhi_dev_ctxt)
|
if (NULL == mhi_dev_ctxt)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
mhi_log(MHI_MSG_INFO, "Entered, sys state %d, MHI state %d\n",
|
mhi_log(MHI_MSG_INFO, "Entered, MHI state %d\n",
|
||||||
state.event, mhi_dev_ctxt->mhi_state);
|
mhi_dev_ctxt->mhi_state);
|
||||||
atomic_set(&mhi_dev_ctxt->flags.pending_resume, 1);
|
atomic_set(&mhi_dev_ctxt->flags.pending_resume, 1);
|
||||||
|
|
||||||
r = mhi_initiate_m3(mhi_dev_ctxt);
|
r = mhi_initiate_m3(mhi_dev_ctxt);
|
||||||
|
@ -84,11 +84,10 @@ int mhi_runtime_resume(struct device *dev)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mhi_pci_resume(struct pci_dev *pcie_dev)
|
int mhi_pci_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
int r = 0;
|
int r = 0;
|
||||||
struct mhi_device_ctxt *mhi_dev_ctxt = pcie_dev->dev.platform_data;
|
struct mhi_device_ctxt *mhi_dev_ctxt = dev->platform_data;
|
||||||
|
|
||||||
r = mhi_initiate_m0(mhi_dev_ctxt);
|
r = mhi_initiate_m0(mhi_dev_ctxt);
|
||||||
if (r)
|
if (r)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
|
@ -225,14 +225,14 @@ static enum MHI_STATUS process_m1_transition(
|
||||||
mhi_assert_device_wake(mhi_dev_ctxt);
|
mhi_assert_device_wake(mhi_dev_ctxt);
|
||||||
} else {
|
} else {
|
||||||
pm_runtime_mark_last_busy(
|
pm_runtime_mark_last_busy(
|
||||||
&mhi_dev_ctxt->dev_info->plat_dev->dev);
|
&mhi_dev_ctxt->dev_info->pcie_device->dev);
|
||||||
r = pm_request_autosuspend(
|
r = pm_request_autosuspend(
|
||||||
&mhi_dev_ctxt->dev_info->plat_dev->dev);
|
&mhi_dev_ctxt->dev_info->pcie_device->dev);
|
||||||
if (r) {
|
if (r) {
|
||||||
mhi_log(MHI_MSG_ERROR,
|
mhi_log(MHI_MSG_ERROR,
|
||||||
"Failed to remove counter ret %d\n", r);
|
"Failed to remove counter ret %d\n", r);
|
||||||
BUG_ON(mhi_dev_ctxt->dev_info->
|
BUG_ON(mhi_dev_ctxt->dev_info->
|
||||||
plat_dev->dev.power.runtime_error);
|
pcie_device->dev.power.runtime_error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
atomic_set(&mhi_dev_ctxt->flags.m2_transition, 0);
|
atomic_set(&mhi_dev_ctxt->flags.m2_transition, 0);
|
||||||
|
@ -329,7 +329,8 @@ static enum MHI_STATUS process_wake_transition(
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (mhi_dev_ctxt->flags.mhi_initialized) {
|
if (mhi_dev_ctxt->flags.mhi_initialized) {
|
||||||
r = pm_request_resume(&mhi_dev_ctxt->dev_info->plat_dev->dev);
|
r = pm_request_resume(
|
||||||
|
&mhi_dev_ctxt->dev_info->pcie_device->dev);
|
||||||
mhi_log(MHI_MSG_VERBOSE,
|
mhi_log(MHI_MSG_VERBOSE,
|
||||||
"MHI is initialized, transitioning to M0, ret %d\n", r);
|
"MHI is initialized, transitioning to M0, ret %d\n", r);
|
||||||
}
|
}
|
||||||
|
@ -560,16 +561,17 @@ static enum MHI_STATUS process_sbl_transition(
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
mhi_log(MHI_MSG_INFO, "Processing SBL state transition\n");
|
pm_runtime_set_autosuspend_delay(
|
||||||
pm_runtime_set_autosuspend_delay(&mhi_dev_ctxt->dev_info->plat_dev->dev,
|
&mhi_dev_ctxt->dev_info->pcie_device->dev,
|
||||||
MHI_RPM_AUTOSUSPEND_TMR_VAL_MS);
|
MHI_RPM_AUTOSUSPEND_TMR_VAL_MS);
|
||||||
pm_runtime_use_autosuspend(&mhi_dev_ctxt->dev_info->plat_dev->dev);
|
pm_runtime_use_autosuspend(&mhi_dev_ctxt->dev_info->pcie_device->dev);
|
||||||
r = pm_runtime_set_active(&mhi_dev_ctxt->dev_info->plat_dev->dev);
|
r = pm_runtime_set_active(&mhi_dev_ctxt->dev_info->pcie_device->dev);
|
||||||
if (r) {
|
if (r) {
|
||||||
mhi_log(MHI_MSG_ERROR,
|
mhi_log(MHI_MSG_ERROR,
|
||||||
"Failed to activate runtime pm ret %d\n", r);
|
"Failed to activate runtime pm ret %d\n", r);
|
||||||
}
|
}
|
||||||
pm_runtime_enable(&mhi_dev_ctxt->dev_info->plat_dev->dev);
|
pm_runtime_enable(&mhi_dev_ctxt->dev_info->pcie_device->dev);
|
||||||
|
pm_runtime_put_noidle(&mhi_dev_ctxt->dev_info->pcie_device->dev);
|
||||||
mhi_log(MHI_MSG_INFO, "Enabled runtime pm\n");
|
mhi_log(MHI_MSG_INFO, "Enabled runtime pm\n");
|
||||||
mhi_dev_ctxt->dev_exec_env = MHI_EXEC_ENV_SBL;
|
mhi_dev_ctxt->dev_exec_env = MHI_EXEC_ENV_SBL;
|
||||||
enable_clients(mhi_dev_ctxt, mhi_dev_ctxt->dev_exec_env);
|
enable_clients(mhi_dev_ctxt, mhi_dev_ctxt->dev_exec_env);
|
||||||
|
|
Loading…
Add table
Reference in a new issue