diff options
author | Joakim Tjernlund <joakim.tjernlund@infinera.com> | 2018-12-14 09:17:05 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-12-17 14:24:32 -0500 |
commit | b3e5464e36c07dba70b544044a297d5819351765 (patch) | |
tree | ed694951dab275d9335067ea3e0cc64e2100fb78 | |
parent | 4beaacc6fea5a5ec43c55c22a6c83c03a5ecc775 (diff) |
Fixed PHY: Add fixed_phy_change_carrier()
Drivers can use this as .ndo_change_carrier() to change carrier
via /sys/class/net/ethX/carrier.
Signed-off-by: Joakim Tjernlund <joakim.tjernlund@infinera.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/phy/fixed_phy.c | 24 | ||||
-rw-r--r-- | include/linux/phy_fixed.h | 5 |
2 files changed, 28 insertions, 1 deletions
diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c index f7fb62712cd8..72d43c88e6ff 100644 --- a/drivers/net/phy/fixed_phy.c +++ b/drivers/net/phy/fixed_phy.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/gpio.h> | 25 | #include <linux/gpio.h> |
26 | #include <linux/seqlock.h> | 26 | #include <linux/seqlock.h> |
27 | #include <linux/idr.h> | 27 | #include <linux/idr.h> |
28 | #include <linux/netdevice.h> | ||
28 | 29 | ||
29 | #include "swphy.h" | 30 | #include "swphy.h" |
30 | 31 | ||
@@ -38,6 +39,7 @@ struct fixed_phy { | |||
38 | struct phy_device *phydev; | 39 | struct phy_device *phydev; |
39 | seqcount_t seqcount; | 40 | seqcount_t seqcount; |
40 | struct fixed_phy_status status; | 41 | struct fixed_phy_status status; |
42 | bool no_carrier; | ||
41 | int (*link_update)(struct net_device *, struct fixed_phy_status *); | 43 | int (*link_update)(struct net_device *, struct fixed_phy_status *); |
42 | struct list_head node; | 44 | struct list_head node; |
43 | int link_gpio; | 45 | int link_gpio; |
@@ -48,9 +50,28 @@ static struct fixed_mdio_bus platform_fmb = { | |||
48 | .phys = LIST_HEAD_INIT(platform_fmb.phys), | 50 | .phys = LIST_HEAD_INIT(platform_fmb.phys), |
49 | }; | 51 | }; |
50 | 52 | ||
53 | int fixed_phy_change_carrier(struct net_device *dev, bool new_carrier) | ||
54 | { | ||
55 | struct fixed_mdio_bus *fmb = &platform_fmb; | ||
56 | struct phy_device *phydev = dev->phydev; | ||
57 | struct fixed_phy *fp; | ||
58 | |||
59 | if (!phydev || !phydev->mdio.bus) | ||
60 | return -EINVAL; | ||
61 | |||
62 | list_for_each_entry(fp, &fmb->phys, node) { | ||
63 | if (fp->addr == phydev->mdio.addr) { | ||
64 | fp->no_carrier = !new_carrier; | ||
65 | return 0; | ||
66 | } | ||
67 | } | ||
68 | return -EINVAL; | ||
69 | } | ||
70 | EXPORT_SYMBOL_GPL(fixed_phy_change_carrier); | ||
71 | |||
51 | static void fixed_phy_update(struct fixed_phy *fp) | 72 | static void fixed_phy_update(struct fixed_phy *fp) |
52 | { | 73 | { |
53 | if (gpio_is_valid(fp->link_gpio)) | 74 | if (!fp->no_carrier && gpio_is_valid(fp->link_gpio)) |
54 | fp->status.link = !!gpio_get_value_cansleep(fp->link_gpio); | 75 | fp->status.link = !!gpio_get_value_cansleep(fp->link_gpio); |
55 | } | 76 | } |
56 | 77 | ||
@@ -66,6 +87,7 @@ static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num) | |||
66 | 87 | ||
67 | do { | 88 | do { |
68 | s = read_seqcount_begin(&fp->seqcount); | 89 | s = read_seqcount_begin(&fp->seqcount); |
90 | fp->status.link = !fp->no_carrier; | ||
69 | /* Issue callback if user registered it. */ | 91 | /* Issue callback if user registered it. */ |
70 | if (fp->link_update) { | 92 | if (fp->link_update) { |
71 | fp->link_update(fp->phydev->attached_dev, | 93 | fp->link_update(fp->phydev->attached_dev, |
diff --git a/include/linux/phy_fixed.h b/include/linux/phy_fixed.h index ee54453a40a0..9525567b1951 100644 --- a/include/linux/phy_fixed.h +++ b/include/linux/phy_fixed.h | |||
@@ -13,6 +13,7 @@ struct fixed_phy_status { | |||
13 | struct device_node; | 13 | struct device_node; |
14 | 14 | ||
15 | #if IS_ENABLED(CONFIG_FIXED_PHY) | 15 | #if IS_ENABLED(CONFIG_FIXED_PHY) |
16 | extern int fixed_phy_change_carrier(struct net_device *dev, bool new_carrier); | ||
16 | extern int fixed_phy_add(unsigned int irq, int phy_id, | 17 | extern int fixed_phy_add(unsigned int irq, int phy_id, |
17 | struct fixed_phy_status *status, | 18 | struct fixed_phy_status *status, |
18 | int link_gpio); | 19 | int link_gpio); |
@@ -47,6 +48,10 @@ static inline int fixed_phy_set_link_update(struct phy_device *phydev, | |||
47 | { | 48 | { |
48 | return -ENODEV; | 49 | return -ENODEV; |
49 | } | 50 | } |
51 | static inline int fixed_phy_change_carrier(struct net_device *dev, bool new_carrier) | ||
52 | { | ||
53 | return -EINVAL; | ||
54 | } | ||
50 | #endif /* CONFIG_FIXED_PHY */ | 55 | #endif /* CONFIG_FIXED_PHY */ |
51 | 56 | ||
52 | #endif /* __PHY_FIXED_H */ | 57 | #endif /* __PHY_FIXED_H */ |