diff options
Diffstat (limited to 'net/dsa/slave.c')
-rw-r--r-- | net/dsa/slave.c | 293 |
1 files changed, 168 insertions, 125 deletions
diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 746ab428a17a..1e3b6a6d8a40 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/netdevice.h> | 13 | #include <linux/netdevice.h> |
14 | #include <linux/phy.h> | 14 | #include <linux/phy.h> |
15 | #include <linux/phy_fixed.h> | 15 | #include <linux/phy_fixed.h> |
16 | #include <linux/phylink.h> | ||
16 | #include <linux/of_net.h> | 17 | #include <linux/of_net.h> |
17 | #include <linux/of_mdio.h> | 18 | #include <linux/of_mdio.h> |
18 | #include <linux/mdio.h> | 19 | #include <linux/mdio.h> |
@@ -97,8 +98,7 @@ static int dsa_slave_open(struct net_device *dev) | |||
97 | if (err) | 98 | if (err) |
98 | goto clear_promisc; | 99 | goto clear_promisc; |
99 | 100 | ||
100 | if (dev->phydev) | 101 | phylink_start(dp->pl); |
101 | phy_start(dev->phydev); | ||
102 | 102 | ||
103 | return 0; | 103 | return 0; |
104 | 104 | ||
@@ -120,8 +120,7 @@ static int dsa_slave_close(struct net_device *dev) | |||
120 | struct net_device *master = dsa_slave_to_master(dev); | 120 | struct net_device *master = dsa_slave_to_master(dev); |
121 | struct dsa_port *dp = dsa_slave_to_port(dev); | 121 | struct dsa_port *dp = dsa_slave_to_port(dev); |
122 | 122 | ||
123 | if (dev->phydev) | 123 | phylink_stop(dp->pl); |
124 | phy_stop(dev->phydev); | ||
125 | 124 | ||
126 | dsa_port_disable(dp, dev->phydev); | 125 | dsa_port_disable(dp, dev->phydev); |
127 | 126 | ||
@@ -272,10 +271,7 @@ static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
272 | break; | 271 | break; |
273 | } | 272 | } |
274 | 273 | ||
275 | if (!dev->phydev) | 274 | return phylink_mii_ioctl(p->dp->pl, ifr, cmd); |
276 | return -ENODEV; | ||
277 | |||
278 | return phy_mii_ioctl(dev->phydev, ifr, cmd); | ||
279 | } | 275 | } |
280 | 276 | ||
281 | static int dsa_slave_port_attr_set(struct net_device *dev, | 277 | static int dsa_slave_port_attr_set(struct net_device *dev, |
@@ -498,14 +494,11 @@ dsa_slave_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *_p) | |||
498 | ds->ops->get_regs(ds, dp->index, regs, _p); | 494 | ds->ops->get_regs(ds, dp->index, regs, _p); |
499 | } | 495 | } |
500 | 496 | ||
501 | static u32 dsa_slave_get_link(struct net_device *dev) | 497 | static int dsa_slave_nway_reset(struct net_device *dev) |
502 | { | 498 | { |
503 | if (!dev->phydev) | 499 | struct dsa_port *dp = dsa_slave_to_port(dev); |
504 | return -ENODEV; | ||
505 | |||
506 | genphy_update_link(dev->phydev); | ||
507 | 500 | ||
508 | return dev->phydev->link; | 501 | return phylink_ethtool_nway_reset(dp->pl); |
509 | } | 502 | } |
510 | 503 | ||
511 | static int dsa_slave_get_eeprom_len(struct net_device *dev) | 504 | static int dsa_slave_get_eeprom_len(struct net_device *dev) |
@@ -619,6 +612,8 @@ static void dsa_slave_get_wol(struct net_device *dev, struct ethtool_wolinfo *w) | |||
619 | struct dsa_port *dp = dsa_slave_to_port(dev); | 612 | struct dsa_port *dp = dsa_slave_to_port(dev); |
620 | struct dsa_switch *ds = dp->ds; | 613 | struct dsa_switch *ds = dp->ds; |
621 | 614 | ||
615 | phylink_ethtool_get_wol(dp->pl, w); | ||
616 | |||
622 | if (ds->ops->get_wol) | 617 | if (ds->ops->get_wol) |
623 | ds->ops->get_wol(ds, dp->index, w); | 618 | ds->ops->get_wol(ds, dp->index, w); |
624 | } | 619 | } |
@@ -629,6 +624,8 @@ static int dsa_slave_set_wol(struct net_device *dev, struct ethtool_wolinfo *w) | |||
629 | struct dsa_switch *ds = dp->ds; | 624 | struct dsa_switch *ds = dp->ds; |
630 | int ret = -EOPNOTSUPP; | 625 | int ret = -EOPNOTSUPP; |
631 | 626 | ||
627 | phylink_ethtool_set_wol(dp->pl, w); | ||
628 | |||
632 | if (ds->ops->set_wol) | 629 | if (ds->ops->set_wol) |
633 | ret = ds->ops->set_wol(ds, dp->index, w); | 630 | ret = ds->ops->set_wol(ds, dp->index, w); |
634 | 631 | ||
@@ -652,13 +649,7 @@ static int dsa_slave_set_eee(struct net_device *dev, struct ethtool_eee *e) | |||
652 | if (ret) | 649 | if (ret) |
653 | return ret; | 650 | return ret; |
654 | 651 | ||
655 | if (e->eee_enabled) { | 652 | return phylink_ethtool_set_eee(dp->pl, e); |
656 | ret = phy_init_eee(dev->phydev, 0); | ||
657 | if (ret) | ||
658 | return ret; | ||
659 | } | ||
660 | |||
661 | return phy_ethtool_set_eee(dev->phydev, e); | ||
662 | } | 653 | } |
663 | 654 | ||
664 | static int dsa_slave_get_eee(struct net_device *dev, struct ethtool_eee *e) | 655 | static int dsa_slave_get_eee(struct net_device *dev, struct ethtool_eee *e) |
@@ -678,7 +669,23 @@ static int dsa_slave_get_eee(struct net_device *dev, struct ethtool_eee *e) | |||
678 | if (ret) | 669 | if (ret) |
679 | return ret; | 670 | return ret; |
680 | 671 | ||
681 | return phy_ethtool_get_eee(dev->phydev, e); | 672 | return phylink_ethtool_get_eee(dp->pl, e); |
673 | } | ||
674 | |||
675 | static int dsa_slave_get_link_ksettings(struct net_device *dev, | ||
676 | struct ethtool_link_ksettings *cmd) | ||
677 | { | ||
678 | struct dsa_port *dp = dsa_slave_to_port(dev); | ||
679 | |||
680 | return phylink_ethtool_ksettings_get(dp->pl, cmd); | ||
681 | } | ||
682 | |||
683 | static int dsa_slave_set_link_ksettings(struct net_device *dev, | ||
684 | const struct ethtool_link_ksettings *cmd) | ||
685 | { | ||
686 | struct dsa_port *dp = dsa_slave_to_port(dev); | ||
687 | |||
688 | return phylink_ethtool_ksettings_set(dp->pl, cmd); | ||
682 | } | 689 | } |
683 | 690 | ||
684 | #ifdef CONFIG_NET_POLL_CONTROLLER | 691 | #ifdef CONFIG_NET_POLL_CONTROLLER |
@@ -981,8 +988,8 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = { | |||
981 | .get_drvinfo = dsa_slave_get_drvinfo, | 988 | .get_drvinfo = dsa_slave_get_drvinfo, |
982 | .get_regs_len = dsa_slave_get_regs_len, | 989 | .get_regs_len = dsa_slave_get_regs_len, |
983 | .get_regs = dsa_slave_get_regs, | 990 | .get_regs = dsa_slave_get_regs, |
984 | .nway_reset = phy_ethtool_nway_reset, | 991 | .nway_reset = dsa_slave_nway_reset, |
985 | .get_link = dsa_slave_get_link, | 992 | .get_link = ethtool_op_get_link, |
986 | .get_eeprom_len = dsa_slave_get_eeprom_len, | 993 | .get_eeprom_len = dsa_slave_get_eeprom_len, |
987 | .get_eeprom = dsa_slave_get_eeprom, | 994 | .get_eeprom = dsa_slave_get_eeprom, |
988 | .set_eeprom = dsa_slave_set_eeprom, | 995 | .set_eeprom = dsa_slave_set_eeprom, |
@@ -993,8 +1000,8 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = { | |||
993 | .get_wol = dsa_slave_get_wol, | 1000 | .get_wol = dsa_slave_get_wol, |
994 | .set_eee = dsa_slave_set_eee, | 1001 | .set_eee = dsa_slave_set_eee, |
995 | .get_eee = dsa_slave_get_eee, | 1002 | .get_eee = dsa_slave_get_eee, |
996 | .get_link_ksettings = phy_ethtool_get_link_ksettings, | 1003 | .get_link_ksettings = dsa_slave_get_link_ksettings, |
997 | .set_link_ksettings = phy_ethtool_set_link_ksettings, | 1004 | .set_link_ksettings = dsa_slave_set_link_ksettings, |
998 | .get_rxnfc = dsa_slave_get_rxnfc, | 1005 | .get_rxnfc = dsa_slave_get_rxnfc, |
999 | .set_rxnfc = dsa_slave_set_rxnfc, | 1006 | .set_rxnfc = dsa_slave_set_rxnfc, |
1000 | .get_ts_info = dsa_slave_get_ts_info, | 1007 | .get_ts_info = dsa_slave_get_ts_info, |
@@ -1053,56 +1060,122 @@ static struct device_type dsa_type = { | |||
1053 | .name = "dsa", | 1060 | .name = "dsa", |
1054 | }; | 1061 | }; |
1055 | 1062 | ||
1056 | static void dsa_slave_adjust_link(struct net_device *dev) | 1063 | static void dsa_slave_phylink_validate(struct net_device *dev, |
1064 | unsigned long *supported, | ||
1065 | struct phylink_link_state *state) | ||
1057 | { | 1066 | { |
1058 | struct dsa_port *dp = dsa_slave_to_port(dev); | 1067 | struct dsa_port *dp = dsa_slave_to_port(dev); |
1059 | struct dsa_slave_priv *p = netdev_priv(dev); | ||
1060 | struct dsa_switch *ds = dp->ds; | 1068 | struct dsa_switch *ds = dp->ds; |
1061 | unsigned int status_changed = 0; | ||
1062 | 1069 | ||
1063 | if (p->old_link != dev->phydev->link) { | 1070 | if (!ds->ops->phylink_validate) |
1064 | status_changed = 1; | 1071 | return; |
1065 | p->old_link = dev->phydev->link; | ||
1066 | } | ||
1067 | 1072 | ||
1068 | if (p->old_duplex != dev->phydev->duplex) { | 1073 | ds->ops->phylink_validate(ds, dp->index, supported, state); |
1069 | status_changed = 1; | 1074 | } |
1070 | p->old_duplex = dev->phydev->duplex; | ||
1071 | } | ||
1072 | 1075 | ||
1073 | if (p->old_pause != dev->phydev->pause) { | 1076 | static int dsa_slave_phylink_mac_link_state(struct net_device *dev, |
1074 | status_changed = 1; | 1077 | struct phylink_link_state *state) |
1075 | p->old_pause = dev->phydev->pause; | 1078 | { |
1076 | } | 1079 | struct dsa_port *dp = dsa_slave_to_port(dev); |
1080 | struct dsa_switch *ds = dp->ds; | ||
1077 | 1081 | ||
1078 | if (ds->ops->adjust_link && status_changed) | 1082 | /* Only called for SGMII and 802.3z */ |
1079 | ds->ops->adjust_link(ds, dp->index, dev->phydev); | 1083 | if (!ds->ops->phylink_mac_link_state) |
1084 | return -EOPNOTSUPP; | ||
1080 | 1085 | ||
1081 | if (status_changed) | 1086 | return ds->ops->phylink_mac_link_state(ds, dp->index, state); |
1082 | phy_print_status(dev->phydev); | ||
1083 | } | 1087 | } |
1084 | 1088 | ||
1085 | static int dsa_slave_fixed_link_update(struct net_device *dev, | 1089 | static void dsa_slave_phylink_mac_config(struct net_device *dev, |
1086 | struct fixed_phy_status *status) | 1090 | unsigned int mode, |
1091 | const struct phylink_link_state *state) | ||
1087 | { | 1092 | { |
1088 | struct dsa_switch *ds; | 1093 | struct dsa_port *dp = dsa_slave_to_port(dev); |
1089 | struct dsa_port *dp; | 1094 | struct dsa_switch *ds = dp->ds; |
1090 | 1095 | ||
1091 | if (dev) { | 1096 | if (!ds->ops->phylink_mac_config) |
1092 | dp = dsa_slave_to_port(dev); | 1097 | return; |
1093 | ds = dp->ds; | 1098 | |
1094 | if (ds->ops->fixed_link_update) | 1099 | ds->ops->phylink_mac_config(ds, dp->index, mode, state); |
1095 | ds->ops->fixed_link_update(ds, dp->index, status); | 1100 | } |
1101 | |||
1102 | static void dsa_slave_phylink_mac_an_restart(struct net_device *dev) | ||
1103 | { | ||
1104 | struct dsa_port *dp = dsa_slave_to_port(dev); | ||
1105 | struct dsa_switch *ds = dp->ds; | ||
1106 | |||
1107 | if (!ds->ops->phylink_mac_an_restart) | ||
1108 | return; | ||
1109 | |||
1110 | ds->ops->phylink_mac_an_restart(ds, dp->index); | ||
1111 | } | ||
1112 | |||
1113 | static void dsa_slave_phylink_mac_link_down(struct net_device *dev, | ||
1114 | unsigned int mode, | ||
1115 | phy_interface_t interface) | ||
1116 | { | ||
1117 | struct dsa_port *dp = dsa_slave_to_port(dev); | ||
1118 | struct dsa_switch *ds = dp->ds; | ||
1119 | |||
1120 | if (!ds->ops->phylink_mac_link_down) { | ||
1121 | if (ds->ops->adjust_link && dev->phydev) | ||
1122 | ds->ops->adjust_link(ds, dp->index, dev->phydev); | ||
1123 | return; | ||
1096 | } | 1124 | } |
1097 | 1125 | ||
1098 | return 0; | 1126 | ds->ops->phylink_mac_link_down(ds, dp->index, mode, interface); |
1127 | } | ||
1128 | |||
1129 | static void dsa_slave_phylink_mac_link_up(struct net_device *dev, | ||
1130 | unsigned int mode, | ||
1131 | phy_interface_t interface, | ||
1132 | struct phy_device *phydev) | ||
1133 | { | ||
1134 | struct dsa_port *dp = dsa_slave_to_port(dev); | ||
1135 | struct dsa_switch *ds = dp->ds; | ||
1136 | |||
1137 | if (!ds->ops->phylink_mac_link_up) { | ||
1138 | if (ds->ops->adjust_link && dev->phydev) | ||
1139 | ds->ops->adjust_link(ds, dp->index, dev->phydev); | ||
1140 | return; | ||
1141 | } | ||
1142 | |||
1143 | ds->ops->phylink_mac_link_up(ds, dp->index, mode, interface, phydev); | ||
1144 | } | ||
1145 | |||
1146 | static const struct phylink_mac_ops dsa_slave_phylink_mac_ops = { | ||
1147 | .validate = dsa_slave_phylink_validate, | ||
1148 | .mac_link_state = dsa_slave_phylink_mac_link_state, | ||
1149 | .mac_config = dsa_slave_phylink_mac_config, | ||
1150 | .mac_an_restart = dsa_slave_phylink_mac_an_restart, | ||
1151 | .mac_link_down = dsa_slave_phylink_mac_link_down, | ||
1152 | .mac_link_up = dsa_slave_phylink_mac_link_up, | ||
1153 | }; | ||
1154 | |||
1155 | void dsa_port_phylink_mac_change(struct dsa_switch *ds, int port, bool up) | ||
1156 | { | ||
1157 | const struct dsa_port *dp = dsa_to_port(ds, port); | ||
1158 | |||
1159 | phylink_mac_change(dp->pl, up); | ||
1160 | } | ||
1161 | EXPORT_SYMBOL_GPL(dsa_port_phylink_mac_change); | ||
1162 | |||
1163 | static void dsa_slave_phylink_fixed_state(struct net_device *dev, | ||
1164 | struct phylink_link_state *state) | ||
1165 | { | ||
1166 | struct dsa_port *dp = dsa_slave_to_port(dev); | ||
1167 | struct dsa_switch *ds = dp->ds; | ||
1168 | |||
1169 | /* No need to check that this operation is valid, the callback would | ||
1170 | * not be called if it was not. | ||
1171 | */ | ||
1172 | ds->ops->phylink_fixed_state(ds, dp->index, state); | ||
1099 | } | 1173 | } |
1100 | 1174 | ||
1101 | /* slave device setup *******************************************************/ | 1175 | /* slave device setup *******************************************************/ |
1102 | static int dsa_slave_phy_connect(struct net_device *slave_dev, int addr) | 1176 | static int dsa_slave_phy_connect(struct net_device *slave_dev, int addr) |
1103 | { | 1177 | { |
1104 | struct dsa_port *dp = dsa_slave_to_port(slave_dev); | 1178 | struct dsa_port *dp = dsa_slave_to_port(slave_dev); |
1105 | struct dsa_slave_priv *p = netdev_priv(slave_dev); | ||
1106 | struct dsa_switch *ds = dp->ds; | 1179 | struct dsa_switch *ds = dp->ds; |
1107 | 1180 | ||
1108 | slave_dev->phydev = mdiobus_get_phy(ds->slave_mii_bus, addr); | 1181 | slave_dev->phydev = mdiobus_get_phy(ds->slave_mii_bus, addr); |
@@ -1111,75 +1184,54 @@ static int dsa_slave_phy_connect(struct net_device *slave_dev, int addr) | |||
1111 | return -ENODEV; | 1184 | return -ENODEV; |
1112 | } | 1185 | } |
1113 | 1186 | ||
1114 | /* Use already configured phy mode */ | 1187 | return phylink_connect_phy(dp->pl, slave_dev->phydev); |
1115 | if (p->phy_interface == PHY_INTERFACE_MODE_NA) | ||
1116 | p->phy_interface = slave_dev->phydev->interface; | ||
1117 | |||
1118 | return phy_connect_direct(slave_dev, slave_dev->phydev, | ||
1119 | dsa_slave_adjust_link, p->phy_interface); | ||
1120 | } | 1188 | } |
1121 | 1189 | ||
1122 | static int dsa_slave_phy_setup(struct net_device *slave_dev) | 1190 | static int dsa_slave_phy_setup(struct net_device *slave_dev) |
1123 | { | 1191 | { |
1124 | struct dsa_port *dp = dsa_slave_to_port(slave_dev); | 1192 | struct dsa_port *dp = dsa_slave_to_port(slave_dev); |
1125 | struct dsa_slave_priv *p = netdev_priv(slave_dev); | ||
1126 | struct device_node *port_dn = dp->dn; | 1193 | struct device_node *port_dn = dp->dn; |
1127 | struct dsa_switch *ds = dp->ds; | 1194 | struct dsa_switch *ds = dp->ds; |
1128 | struct device_node *phy_dn; | ||
1129 | bool phy_is_fixed = false; | ||
1130 | u32 phy_flags = 0; | 1195 | u32 phy_flags = 0; |
1131 | int mode, ret; | 1196 | int mode, ret; |
1132 | 1197 | ||
1133 | mode = of_get_phy_mode(port_dn); | 1198 | mode = of_get_phy_mode(port_dn); |
1134 | if (mode < 0) | 1199 | if (mode < 0) |
1135 | mode = PHY_INTERFACE_MODE_NA; | 1200 | mode = PHY_INTERFACE_MODE_NA; |
1136 | p->phy_interface = mode; | ||
1137 | 1201 | ||
1138 | phy_dn = of_parse_phandle(port_dn, "phy-handle", 0); | 1202 | dp->pl = phylink_create(slave_dev, of_fwnode_handle(port_dn), mode, |
1139 | if (!phy_dn && of_phy_is_fixed_link(port_dn)) { | 1203 | &dsa_slave_phylink_mac_ops); |
1140 | /* In the case of a fixed PHY, the DT node associated | 1204 | if (IS_ERR(dp->pl)) { |
1141 | * to the fixed PHY is the Port DT node | 1205 | netdev_err(slave_dev, |
1142 | */ | 1206 | "error creating PHYLINK: %ld\n", PTR_ERR(dp->pl)); |
1143 | ret = of_phy_register_fixed_link(port_dn); | 1207 | return PTR_ERR(dp->pl); |
1144 | if (ret) { | ||
1145 | netdev_err(slave_dev, "failed to register fixed PHY: %d\n", ret); | ||
1146 | return ret; | ||
1147 | } | ||
1148 | phy_is_fixed = true; | ||
1149 | phy_dn = of_node_get(port_dn); | ||
1150 | } | 1208 | } |
1151 | 1209 | ||
1210 | /* Register only if the switch provides such a callback, since this | ||
1211 | * callback takes precedence over polling the link GPIO in PHYLINK | ||
1212 | * (see phylink_get_fixed_state). | ||
1213 | */ | ||
1214 | if (ds->ops->phylink_fixed_state) | ||
1215 | phylink_fixed_state_cb(dp->pl, dsa_slave_phylink_fixed_state); | ||
1216 | |||
1152 | if (ds->ops->get_phy_flags) | 1217 | if (ds->ops->get_phy_flags) |
1153 | phy_flags = ds->ops->get_phy_flags(ds, dp->index); | 1218 | phy_flags = ds->ops->get_phy_flags(ds, dp->index); |
1154 | 1219 | ||
1155 | if (phy_dn) { | 1220 | ret = phylink_of_phy_connect(dp->pl, port_dn, phy_flags); |
1156 | slave_dev->phydev = of_phy_connect(slave_dev, phy_dn, | 1221 | if (ret == -ENODEV) { |
1157 | dsa_slave_adjust_link, | 1222 | /* We could not connect to a designated PHY or SFP, so use the |
1158 | phy_flags, | 1223 | * switch internal MDIO bus instead |
1159 | p->phy_interface); | 1224 | */ |
1160 | of_node_put(phy_dn); | ||
1161 | } | ||
1162 | |||
1163 | if (slave_dev->phydev && phy_is_fixed) | ||
1164 | fixed_phy_set_link_update(slave_dev->phydev, | ||
1165 | dsa_slave_fixed_link_update); | ||
1166 | |||
1167 | /* We could not connect to a designated PHY, so use the switch internal | ||
1168 | * MDIO bus instead | ||
1169 | */ | ||
1170 | if (!slave_dev->phydev) { | ||
1171 | ret = dsa_slave_phy_connect(slave_dev, dp->index); | 1225 | ret = dsa_slave_phy_connect(slave_dev, dp->index); |
1172 | if (ret) { | 1226 | if (ret) { |
1173 | netdev_err(slave_dev, "failed to connect to port %d: %d\n", | 1227 | netdev_err(slave_dev, |
1228 | "failed to connect to port %d: %d\n", | ||
1174 | dp->index, ret); | 1229 | dp->index, ret); |
1175 | if (phy_is_fixed) | 1230 | phylink_destroy(dp->pl); |
1176 | of_phy_deregister_fixed_link(port_dn); | ||
1177 | return ret; | 1231 | return ret; |
1178 | } | 1232 | } |
1179 | } | 1233 | } |
1180 | 1234 | ||
1181 | phy_attached_info(slave_dev->phydev); | ||
1182 | |||
1183 | return 0; | 1235 | return 0; |
1184 | } | 1236 | } |
1185 | 1237 | ||
@@ -1194,29 +1246,26 @@ static void dsa_slave_set_lockdep_class_one(struct net_device *dev, | |||
1194 | 1246 | ||
1195 | int dsa_slave_suspend(struct net_device *slave_dev) | 1247 | int dsa_slave_suspend(struct net_device *slave_dev) |
1196 | { | 1248 | { |
1197 | struct dsa_slave_priv *p = netdev_priv(slave_dev); | 1249 | struct dsa_port *dp = dsa_slave_to_port(slave_dev); |
1198 | 1250 | ||
1199 | netif_device_detach(slave_dev); | 1251 | netif_device_detach(slave_dev); |
1200 | 1252 | ||
1201 | if (slave_dev->phydev) { | 1253 | rtnl_lock(); |
1202 | phy_stop(slave_dev->phydev); | 1254 | phylink_stop(dp->pl); |
1203 | p->old_pause = -1; | 1255 | rtnl_unlock(); |
1204 | p->old_link = -1; | ||
1205 | p->old_duplex = -1; | ||
1206 | phy_suspend(slave_dev->phydev); | ||
1207 | } | ||
1208 | 1256 | ||
1209 | return 0; | 1257 | return 0; |
1210 | } | 1258 | } |
1211 | 1259 | ||
1212 | int dsa_slave_resume(struct net_device *slave_dev) | 1260 | int dsa_slave_resume(struct net_device *slave_dev) |
1213 | { | 1261 | { |
1262 | struct dsa_port *dp = dsa_slave_to_port(slave_dev); | ||
1263 | |||
1214 | netif_device_attach(slave_dev); | 1264 | netif_device_attach(slave_dev); |
1215 | 1265 | ||
1216 | if (slave_dev->phydev) { | 1266 | rtnl_lock(); |
1217 | phy_resume(slave_dev->phydev); | 1267 | phylink_start(dp->pl); |
1218 | phy_start(slave_dev->phydev); | 1268 | rtnl_unlock(); |
1219 | } | ||
1220 | 1269 | ||
1221 | return 0; | 1270 | return 0; |
1222 | } | 1271 | } |
@@ -1281,11 +1330,6 @@ int dsa_slave_create(struct dsa_port *port) | |||
1281 | p->dp = port; | 1330 | p->dp = port; |
1282 | INIT_LIST_HEAD(&p->mall_tc_list); | 1331 | INIT_LIST_HEAD(&p->mall_tc_list); |
1283 | p->xmit = cpu_dp->tag_ops->xmit; | 1332 | p->xmit = cpu_dp->tag_ops->xmit; |
1284 | |||
1285 | p->old_pause = -1; | ||
1286 | p->old_link = -1; | ||
1287 | p->old_duplex = -1; | ||
1288 | |||
1289 | port->slave = slave_dev; | 1333 | port->slave = slave_dev; |
1290 | 1334 | ||
1291 | netif_carrier_off(slave_dev); | 1335 | netif_carrier_off(slave_dev); |
@@ -1308,9 +1352,10 @@ int dsa_slave_create(struct dsa_port *port) | |||
1308 | return 0; | 1352 | return 0; |
1309 | 1353 | ||
1310 | out_phy: | 1354 | out_phy: |
1311 | phy_disconnect(slave_dev->phydev); | 1355 | rtnl_lock(); |
1312 | if (of_phy_is_fixed_link(port->dn)) | 1356 | phylink_disconnect_phy(p->dp->pl); |
1313 | of_phy_deregister_fixed_link(port->dn); | 1357 | rtnl_unlock(); |
1358 | phylink_destroy(p->dp->pl); | ||
1314 | out_free: | 1359 | out_free: |
1315 | free_percpu(p->stats64); | 1360 | free_percpu(p->stats64); |
1316 | free_netdev(slave_dev); | 1361 | free_netdev(slave_dev); |
@@ -1322,17 +1367,15 @@ void dsa_slave_destroy(struct net_device *slave_dev) | |||
1322 | { | 1367 | { |
1323 | struct dsa_port *dp = dsa_slave_to_port(slave_dev); | 1368 | struct dsa_port *dp = dsa_slave_to_port(slave_dev); |
1324 | struct dsa_slave_priv *p = netdev_priv(slave_dev); | 1369 | struct dsa_slave_priv *p = netdev_priv(slave_dev); |
1325 | struct device_node *port_dn = dp->dn; | ||
1326 | 1370 | ||
1327 | netif_carrier_off(slave_dev); | 1371 | netif_carrier_off(slave_dev); |
1328 | if (slave_dev->phydev) { | 1372 | rtnl_lock(); |
1329 | phy_disconnect(slave_dev->phydev); | 1373 | phylink_disconnect_phy(dp->pl); |
1374 | rtnl_unlock(); | ||
1330 | 1375 | ||
1331 | if (of_phy_is_fixed_link(port_dn)) | ||
1332 | of_phy_deregister_fixed_link(port_dn); | ||
1333 | } | ||
1334 | dsa_slave_notify(slave_dev, DSA_PORT_UNREGISTER); | 1376 | dsa_slave_notify(slave_dev, DSA_PORT_UNREGISTER); |
1335 | unregister_netdev(slave_dev); | 1377 | unregister_netdev(slave_dev); |
1378 | phylink_destroy(dp->pl); | ||
1336 | free_percpu(p->stats64); | 1379 | free_percpu(p->stats64); |
1337 | free_netdev(slave_dev); | 1380 | free_netdev(slave_dev); |
1338 | } | 1381 | } |