Skip to content

Commit

Permalink
wil6210: run-time PM when interface down
Browse files Browse the repository at this point in the history
Allow run-time suspend when interface is down, keep card alive when
interface is up.
If driver is in wmi only or debug_fw mode run-time PM won't suspend.

Signed-off-by: Lazar Alexei <qca_ailizaro@qca.qualcomm.com>
Signed-off-by: Maya Erez <qca_merez@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
  • Loading branch information
Lazar Alexei authored and Kalle Valo committed Dec 2, 2017
1 parent 8ed05ed commit 9416266
Show file tree
Hide file tree
Showing 6 changed files with 237 additions and 20 deletions.
96 changes: 88 additions & 8 deletions drivers/net/wireless/ath/wil6210/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,19 @@ static void wil_print_ring(struct seq_file *s, const char *prefix,
static int wil_mbox_debugfs_show(struct seq_file *s, void *data)
{
struct wil6210_priv *wil = s->private;
int ret;

ret = wil_pm_runtime_get(wil);
if (ret < 0)
return ret;

wil_print_ring(s, "tx", wil->csr + HOST_MBOX +
offsetof(struct wil6210_mbox_ctl, tx));
wil_print_ring(s, "rx", wil->csr + HOST_MBOX +
offsetof(struct wil6210_mbox_ctl, rx));

wil_pm_runtime_put(wil);

return 0;
}

Expand All @@ -265,15 +272,37 @@ static const struct file_operations fops_mbox = {

static int wil_debugfs_iomem_x32_set(void *data, u64 val)
{
writel(val, (void __iomem *)data);
struct wil_debugfs_iomem_data *d = (struct
wil_debugfs_iomem_data *)data;
struct wil6210_priv *wil = d->wil;
int ret;

ret = wil_pm_runtime_get(wil);
if (ret < 0)
return ret;

writel(val, (void __iomem *)d->offset);
wmb(); /* make sure write propagated to HW */

wil_pm_runtime_put(wil);

return 0;
}

static int wil_debugfs_iomem_x32_get(void *data, u64 *val)
{
*val = readl((void __iomem *)data);
struct wil_debugfs_iomem_data *d = (struct
wil_debugfs_iomem_data *)data;
struct wil6210_priv *wil = d->wil;
int ret;

ret = wil_pm_runtime_get(wil);
if (ret < 0)
return ret;

*val = readl((void __iomem *)d->offset);

wil_pm_runtime_put(wil);

return 0;
}
Expand All @@ -284,10 +313,21 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_iomem_x32, wil_debugfs_iomem_x32_get,
static struct dentry *wil_debugfs_create_iomem_x32(const char *name,
umode_t mode,
struct dentry *parent,
void *value)
void *value,
struct wil6210_priv *wil)
{
return debugfs_create_file(name, mode, parent, value,
&fops_iomem_x32);
struct dentry *file;
struct wil_debugfs_iomem_data *data = &wil->dbg_data.data_arr[
wil->dbg_data.iomem_data_count];

data->wil = wil;
data->offset = value;

file = debugfs_create_file(name, mode, parent, data, &fops_iomem_x32);
if (!IS_ERR_OR_NULL(file))
wil->dbg_data.iomem_data_count++;

return file;
}

static int wil_debugfs_ulong_set(void *data, u64 val)
Expand Down Expand Up @@ -346,7 +386,8 @@ static void wil6210_debugfs_init_offset(struct wil6210_priv *wil,
case doff_io32:
f = wil_debugfs_create_iomem_x32(tbl[i].name,
tbl[i].mode, dbg,
base + tbl[i].off);
base + tbl[i].off,
wil);
break;
case doff_u8:
f = debugfs_create_u8(tbl[i].name, tbl[i].mode, dbg,
Expand Down Expand Up @@ -475,13 +516,22 @@ static int wil6210_debugfs_create_ITR_CNT(struct wil6210_priv *wil,
static int wil_memread_debugfs_show(struct seq_file *s, void *data)
{
struct wil6210_priv *wil = s->private;
void __iomem *a = wmi_buffer(wil, cpu_to_le32(mem_addr));
void __iomem *a;
int ret;

ret = wil_pm_runtime_get(wil);
if (ret < 0)
return ret;

a = wmi_buffer(wil, cpu_to_le32(mem_addr));

if (a)
seq_printf(s, "[0x%08x] = 0x%08x\n", mem_addr, readl(a));
else
seq_printf(s, "[0x%08x] = INVALID\n", mem_addr);

wil_pm_runtime_put(wil);

return 0;
}

Expand All @@ -502,10 +552,12 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf,
{
enum { max_count = 4096 };
struct wil_blob_wrapper *wil_blob = file->private_data;
struct wil6210_priv *wil = wil_blob->wil;
loff_t pos = *ppos;
size_t available = wil_blob->blob.size;
void *buf;
size_t ret;
int rc;

if (test_bit(wil_status_suspending, wil_blob->wil->status) ||
test_bit(wil_status_suspended, wil_blob->wil->status))
Expand All @@ -526,10 +578,19 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf,
if (!buf)
return -ENOMEM;

rc = wil_pm_runtime_get(wil);
if (rc < 0) {
kfree(buf);
return rc;
}

wil_memcpy_fromio_32(buf, (const void __iomem *)
wil_blob->blob.data + pos, count);

ret = copy_to_user(user_buf, buf, count);

wil_pm_runtime_put(wil);

kfree(buf);
if (ret == count)
return -EFAULT;
Expand Down Expand Up @@ -1736,14 +1797,31 @@ static const struct dbg_off dbg_statics[] = {
{},
};

static const int dbg_off_count = 4 * (ARRAY_SIZE(isr_off) - 1) +
ARRAY_SIZE(dbg_wil_regs) - 1 +
ARRAY_SIZE(pseudo_isr_off) - 1 +
ARRAY_SIZE(lgc_itr_cnt_off) - 1 +
ARRAY_SIZE(tx_itr_cnt_off) - 1 +
ARRAY_SIZE(rx_itr_cnt_off) - 1;

int wil6210_debugfs_init(struct wil6210_priv *wil)
{
struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME,
wil_to_wiphy(wil)->debugfsdir);

if (IS_ERR_OR_NULL(dbg))
return -ENODEV;

wil->dbg_data.data_arr = kcalloc(dbg_off_count,
sizeof(struct wil_debugfs_iomem_data),
GFP_KERNEL);
if (!wil->dbg_data.data_arr) {
debugfs_remove_recursive(dbg);
wil->debug = NULL;
return -ENOMEM;
}

wil->dbg_data.iomem_data_count = 0;

wil_pmc_init(wil);

wil6210_debugfs_init_files(wil, dbg);
Expand All @@ -1768,6 +1846,8 @@ void wil6210_debugfs_remove(struct wil6210_priv *wil)
debugfs_remove_recursive(wil->debug);
wil->debug = NULL;

kfree(wil->dbg_data.data_arr);

/* free pmc memory without sending command to fw, as it will
* be reset on the way down anyway
*/
Expand Down
15 changes: 15 additions & 0 deletions drivers/net/wireless/ath/wil6210/ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,14 @@ static int wil_ethtoolops_get_coalesce(struct net_device *ndev,
struct wil6210_priv *wil = ndev_to_wil(ndev);
u32 tx_itr_en, tx_itr_val = 0;
u32 rx_itr_en, rx_itr_val = 0;
int ret;

wil_dbg_misc(wil, "ethtoolops_get_coalesce\n");

ret = wil_pm_runtime_get(wil);
if (ret < 0)
return ret;

tx_itr_en = wil_r(wil, RGF_DMA_ITR_TX_CNT_CTL);
if (tx_itr_en & BIT_DMA_ITR_TX_CNT_CTL_EN)
tx_itr_val = wil_r(wil, RGF_DMA_ITR_TX_CNT_TRSH);
Expand All @@ -58,6 +63,8 @@ static int wil_ethtoolops_get_coalesce(struct net_device *ndev,
if (rx_itr_en & BIT_DMA_ITR_RX_CNT_CTL_EN)
rx_itr_val = wil_r(wil, RGF_DMA_ITR_RX_CNT_TRSH);

wil_pm_runtime_put(wil);

cp->tx_coalesce_usecs = tx_itr_val;
cp->rx_coalesce_usecs = rx_itr_val;
return 0;
Expand All @@ -67,6 +74,7 @@ static int wil_ethtoolops_set_coalesce(struct net_device *ndev,
struct ethtool_coalesce *cp)
{
struct wil6210_priv *wil = ndev_to_wil(ndev);
int ret;

wil_dbg_misc(wil, "ethtoolops_set_coalesce: rx %d usec, tx %d usec\n",
cp->rx_coalesce_usecs, cp->tx_coalesce_usecs);
Expand All @@ -86,8 +94,15 @@ static int wil_ethtoolops_set_coalesce(struct net_device *ndev,

wil->tx_max_burst_duration = cp->tx_coalesce_usecs;
wil->rx_max_burst_duration = cp->rx_coalesce_usecs;

ret = wil_pm_runtime_get(wil);
if (ret < 0)
return ret;

wil_configure_interrupt_moderation(wil);

wil_pm_runtime_put(wil);

return 0;

out_bad:
Expand Down
18 changes: 16 additions & 2 deletions drivers/net/wireless/ath/wil6210/netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
static int wil_open(struct net_device *ndev)
{
struct wil6210_priv *wil = ndev_to_wil(ndev);
int rc;

wil_dbg_misc(wil, "open\n");

Expand All @@ -30,16 +31,29 @@ static int wil_open(struct net_device *ndev)
return -EINVAL;
}

return wil_up(wil);
rc = wil_pm_runtime_get(wil);
if (rc < 0)
return rc;

rc = wil_up(wil);
if (rc)
wil_pm_runtime_put(wil);

return rc;
}

static int wil_stop(struct net_device *ndev)
{
struct wil6210_priv *wil = ndev_to_wil(ndev);
int rc;

wil_dbg_misc(wil, "stop\n");

return wil_down(wil);
rc = wil_down(wil);
if (!rc)
wil_pm_runtime_put(wil);

return rc;
}

static const struct net_device_ops wil_netdev_ops = {
Expand Down
44 changes: 36 additions & 8 deletions drivers/net/wireless/ath/wil6210/pcie_bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <linux/suspend.h>
#include "wil6210.h"
#include <linux/rtnetlink.h>
#include <linux/pm_runtime.h>

static bool use_msi = true;
module_param(use_msi, bool, 0444);
Expand All @@ -31,10 +32,8 @@ module_param(ftm_mode, bool, 0444);
MODULE_PARM_DESC(ftm_mode, " Set factory test mode, default - false");

#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
static int wil6210_pm_notify(struct notifier_block *notify_block,
unsigned long mode, void *unused);
#endif /* CONFIG_PM_SLEEP */
#endif /* CONFIG_PM */

static
Expand Down Expand Up @@ -320,19 +319,18 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}

#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
wil->pm_notify.notifier_call = wil6210_pm_notify;
rc = register_pm_notifier(&wil->pm_notify);
if (rc)
/* Do not fail the driver initialization, as suspend can
* be prevented in a later phase if needed
*/
wil_err(wil, "register_pm_notifier failed: %d\n", rc);
#endif /* CONFIG_PM_SLEEP */
#endif /* CONFIG_PM */

wil6210_debugfs_init(wil);

wil_pm_runtime_allow(wil);

return 0;

Expand Down Expand Up @@ -360,11 +358,11 @@ static void wil_pcie_remove(struct pci_dev *pdev)
wil_dbg_misc(wil, "pcie_remove\n");

#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
unregister_pm_notifier(&wil->pm_notify);
#endif /* CONFIG_PM_SLEEP */
#endif /* CONFIG_PM */

wil_pm_runtime_forbid(wil);

wil6210_debugfs_remove(wil);
rtnl_lock();
wil_p2p_wdev_free(wil);
Expand All @@ -386,7 +384,6 @@ static const struct pci_device_id wil6210_pcie_ids[] = {
MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids);

#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP

static int wil6210_suspend(struct device *dev, bool is_runtime)
{
Expand Down Expand Up @@ -490,12 +487,43 @@ static int wil6210_pm_resume(struct device *dev)
{
return wil6210_resume(dev, false);
}
#endif /* CONFIG_PM_SLEEP */

static int wil6210_pm_runtime_idle(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct wil6210_priv *wil = pci_get_drvdata(pdev);

wil_dbg_pm(wil, "Runtime idle\n");

return wil_can_suspend(wil, true);
}

static int wil6210_pm_runtime_resume(struct device *dev)
{
return wil6210_resume(dev, true);
}

static int wil6210_pm_runtime_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct wil6210_priv *wil = pci_get_drvdata(pdev);

if (test_bit(wil_status_suspended, wil->status)) {
wil_dbg_pm(wil, "trying to suspend while suspended\n");
return 1;
}

return wil6210_suspend(dev, true);
}
#endif /* CONFIG_PM */

static const struct dev_pm_ops wil6210_pm_ops = {
#ifdef CONFIG_PM
SET_SYSTEM_SLEEP_PM_OPS(wil6210_pm_suspend, wil6210_pm_resume)
SET_RUNTIME_PM_OPS(wil6210_pm_runtime_suspend,
wil6210_pm_runtime_resume,
wil6210_pm_runtime_idle)
#endif /* CONFIG_PM */
};

static struct pci_driver wil6210_driver = {
Expand Down
Loading

0 comments on commit 9416266

Please sign in to comment.