Skip to content

Commit

Permalink
Merge branch 'r8169-clk-fixes'
Browse files Browse the repository at this point in the history
Hans de Goede says:

====================
r8169 (x86) clk fixes to fix S0ix not being reached

This series adds code to the r8169 ethernet driver to get and enable an
external clock if present, avoiding the need for a hack in the
clk-pmc-atom driver where that clock was left on continuesly causing x86
some devices to not reach deep power saving states (S0ix) when suspended
causing to them to quickly drain their battery while suspended.

The 3 commits in this series need to be merged in order to avoid
regressions while bisecting. The clk-pmc-atom driver does not see much
changes (it was last touched over a year ago). So the clk maintainers
have agreed with merging all 3 patches through the net tree.
All 3 patches have Stephen Boyd's Acked-by for this purpose.

This v2 of the series only had some minor tweaks done to the commit
messages and is ready for merging through the net tree now.
====================

Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
davem330 committed Sep 18, 2018
2 parents 0866cd1 + 648e921 commit 89bfd48
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 7 deletions.
18 changes: 11 additions & 7 deletions drivers/clk/x86/clk-pmc-atom.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ struct clk_plt_data {
u8 nparents;
struct clk_plt *clks[PMC_CLK_NUM];
struct clk_lookup *mclk_lookup;
struct clk_lookup *ether_clk_lookup;
};

/* Return an index in parent table */
Expand Down Expand Up @@ -186,13 +187,6 @@ static struct clk_plt *plt_clk_register(struct platform_device *pdev, int id,
pclk->reg = base + PMC_CLK_CTL_OFFSET + id * PMC_CLK_CTL_SIZE;
spin_lock_init(&pclk->lock);

/*
* If the clock was already enabled by the firmware mark it as critical
* to avoid it being gated by the clock framework if no driver owns it.
*/
if (plt_clk_is_enabled(&pclk->hw))
init.flags |= CLK_IS_CRITICAL;

ret = devm_clk_hw_register(&pdev->dev, &pclk->hw);
if (ret) {
pclk = ERR_PTR(ret);
Expand Down Expand Up @@ -351,11 +345,20 @@ static int plt_clk_probe(struct platform_device *pdev)
goto err_unreg_clk_plt;
}

data->ether_clk_lookup = clkdev_hw_create(&data->clks[4]->hw,
"ether_clk", NULL);
if (!data->ether_clk_lookup) {
err = -ENOMEM;
goto err_drop_mclk;
}

plt_clk_free_parent_names_loop(parent_names, data->nparents);

platform_set_drvdata(pdev, data);
return 0;

err_drop_mclk:
clkdev_drop(data->mclk_lookup);
err_unreg_clk_plt:
plt_clk_unregister_loop(data, i);
plt_clk_unregister_parents(data);
Expand All @@ -369,6 +372,7 @@ static int plt_clk_remove(struct platform_device *pdev)

data = platform_get_drvdata(pdev);

clkdev_drop(data->ether_clk_lookup);
clkdev_drop(data->mclk_lookup);
plt_clk_unregister_loop(data, PMC_CLK_NUM);
plt_clk_unregister_parents(data);
Expand Down
33 changes: 33 additions & 0 deletions drivers/net/ethernet/realtek/r8169.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/ethtool.h>
#include <linux/phy.h>
Expand Down Expand Up @@ -665,6 +666,7 @@ struct rtl8169_private {

u16 event_slow;
const struct rtl_coalesce_info *coalesce_info;
struct clk *clk;

struct mdio_ops {
void (*write)(struct rtl8169_private *, int, int);
Expand Down Expand Up @@ -7262,6 +7264,11 @@ static int rtl_jumbo_max(struct rtl8169_private *tp)
}
}

static void rtl_disable_clk(void *data)
{
clk_disable_unprepare(data);
}

static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
Expand All @@ -7282,6 +7289,32 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT);
tp->supports_gmii = cfg->has_gmii;

/* Get the *optional* external "ether_clk" used on some boards */
tp->clk = devm_clk_get(&pdev->dev, "ether_clk");
if (IS_ERR(tp->clk)) {
rc = PTR_ERR(tp->clk);
if (rc == -ENOENT) {
/* clk-core allows NULL (for suspend / resume) */
tp->clk = NULL;
} else if (rc == -EPROBE_DEFER) {
return rc;
} else {
dev_err(&pdev->dev, "failed to get clk: %d\n", rc);
return rc;
}
} else {
rc = clk_prepare_enable(tp->clk);
if (rc) {
dev_err(&pdev->dev, "failed to enable clk: %d\n", rc);
return rc;
}

rc = devm_add_action_or_reset(&pdev->dev, rtl_disable_clk,
tp->clk);
if (rc)
return rc;
}

/* enable device (incl. PCI PM wakeup and hotplug setup) */
rc = pcim_enable_device(pdev);
if (rc < 0) {
Expand Down

0 comments on commit 89bfd48

Please sign in to comment.