Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: marvell: prestera: add phylink support

For SFP port prestera driver will use kernel
phylink infrastucture to configure port mode based on
the module that has beed inserted

Co-developed-by: Yevhen Orlov <yevhen.orlov@plvision.eu>
Signed-off-by: Yevhen Orlov <yevhen.orlov@plvision.eu>
Co-developed-by: Taras Chornyi <taras.chornyi@plvision.eu>
Signed-off-by: Taras Chornyi <taras.chornyi@plvision.eu>
Signed-off-by: Oleksandr Mazur <oleksandr.mazur@plvision.eu>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Oleksandr Mazur and committed by
David S. Miller
52323ef7 ffcdd119

+334 -62
+1
drivers/net/ethernet/marvell/prestera/Kconfig
··· 8 8 depends on NET_SWITCHDEV && VLAN_8021Q 9 9 depends on BRIDGE || BRIDGE=n 10 10 select NET_DEVLINK 11 + select PHYLINK 11 12 help 12 13 This driver supports Marvell Prestera Switch ASICs family. 13 14
+10
drivers/net/ethernet/marvell/prestera/prestera.h
··· 7 7 #include <linux/notifier.h> 8 8 #include <linux/skbuff.h> 9 9 #include <linux/workqueue.h> 10 + #include <linux/phylink.h> 10 11 #include <net/devlink.h> 11 12 #include <uapi/linux/if_ether.h> 12 13 ··· 93 92 struct prestera_flow_block; 94 93 95 94 struct prestera_port_mac_state { 95 + bool valid; 96 96 u32 mode; 97 97 u32 speed; 98 98 bool oper; ··· 153 151 struct prestera_port_phy_config cfg_phy; 154 152 struct prestera_port_mac_state state_mac; 155 153 struct prestera_port_phy_state state_phy; 154 + 155 + struct phylink_config phy_config; 156 + struct phylink *phy_link; 157 + struct phylink_pcs phylink_pcs; 158 + 159 + /* protects state_mac */ 160 + spinlock_t state_mac_lock; 156 161 }; 157 162 158 163 struct prestera_device { ··· 300 291 u32 mtu_min; 301 292 u32 mtu_max; 302 293 u8 id; 294 + struct device_node *np; 303 295 struct prestera_router *router; 304 296 struct prestera_lag *lags; 305 297 struct prestera_counter *counter;
+6 -22
drivers/net/ethernet/marvell/prestera/prestera_ethtool.c
··· 521 521 ecmd->base.speed = SPEED_UNKNOWN; 522 522 ecmd->base.duplex = DUPLEX_UNKNOWN; 523 523 524 + if (port->phy_link) 525 + return phylink_ethtool_ksettings_get(port->phy_link, ecmd); 526 + 524 527 ecmd->base.autoneg = port->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE; 525 528 526 529 if (port->caps.type == PRESTERA_PORT_TYPE_TP) { ··· 650 647 u64 adver_modes; 651 648 u8 adver_fec; 652 649 int err; 650 + 651 + if (port->phy_link) 652 + return phylink_ethtool_ksettings_set(port->phy_link, ecmd); 653 653 654 654 err = prestera_port_type_set(ecmd, port); 655 655 if (err) ··· 786 780 return prestera_hw_port_autoneg_restart(port); 787 781 788 782 return -EINVAL; 789 - } 790 - 791 - void prestera_ethtool_port_state_changed(struct prestera_port *port, 792 - struct prestera_port_event *evt) 793 - { 794 - struct prestera_port_mac_state *smac = &port->state_mac; 795 - 796 - smac->oper = evt->data.mac.oper; 797 - 798 - if (smac->oper) { 799 - smac->mode = evt->data.mac.mode; 800 - smac->speed = evt->data.mac.speed; 801 - smac->duplex = evt->data.mac.duplex; 802 - smac->fc = evt->data.mac.fc; 803 - smac->fec = evt->data.mac.fec; 804 - } else { 805 - smac->mode = PRESTERA_MAC_MODE_MAX; 806 - smac->speed = SPEED_UNKNOWN; 807 - smac->duplex = DUPLEX_UNKNOWN; 808 - smac->fc = 0; 809 - smac->fec = 0; 810 - } 811 783 } 812 784 813 785 const struct ethtool_ops prestera_ethtool_ops = {
-3
drivers/net/ethernet/marvell/prestera/prestera_ethtool.h
··· 11 11 12 12 extern const struct ethtool_ops prestera_ethtool_ops; 13 13 14 - void prestera_ethtool_port_state_changed(struct prestera_port *port, 15 - struct prestera_port_event *evt); 16 - 17 14 #endif /* _PRESTERA_ETHTOOL_H_ */
+317 -37
drivers/net/ethernet/marvell/prestera/prestera_main.c
··· 9 9 #include <linux/of.h> 10 10 #include <linux/of_net.h> 11 11 #include <linux/if_vlan.h> 12 + #include <linux/phylink.h> 12 13 13 14 #include "prestera.h" 14 15 #include "prestera_hw.h" ··· 143 142 struct prestera_port_mac_config cfg_mac; 144 143 int err = 0; 145 144 146 - if (port->caps.transceiver == PRESTERA_PORT_TCVR_SFP) { 147 - err = prestera_port_cfg_mac_read(port, &cfg_mac); 148 - if (!err) { 149 - cfg_mac.admin = true; 150 - err = prestera_port_cfg_mac_write(port, &cfg_mac); 151 - } 145 + if (port->phy_link) { 146 + phylink_start(port->phy_link); 152 147 } else { 153 - port->cfg_phy.admin = true; 154 - err = prestera_hw_port_phy_mode_set(port, true, port->autoneg, 155 - port->cfg_phy.mode, 156 - port->adver_link_modes, 157 - port->cfg_phy.mdix); 148 + if (port->caps.transceiver == PRESTERA_PORT_TCVR_SFP) { 149 + err = prestera_port_cfg_mac_read(port, &cfg_mac); 150 + if (!err) { 151 + cfg_mac.admin = true; 152 + err = prestera_port_cfg_mac_write(port, 153 + &cfg_mac); 154 + } 155 + } else { 156 + port->cfg_phy.admin = true; 157 + err = prestera_hw_port_phy_mode_set(port, true, 158 + port->autoneg, 159 + port->cfg_phy.mode, 160 + port->adver_link_modes, 161 + port->cfg_phy.mdix); 162 + } 158 163 } 159 164 160 165 netif_start_queue(dev); ··· 176 169 177 170 netif_stop_queue(dev); 178 171 179 - if (port->caps.transceiver == PRESTERA_PORT_TCVR_SFP) { 172 + if (port->phy_link) { 173 + phylink_stop(port->phy_link); 174 + phylink_disconnect_phy(port->phy_link); 180 175 err = prestera_port_cfg_mac_read(port, &cfg_mac); 181 176 if (!err) { 182 177 cfg_mac.admin = false; 183 178 prestera_port_cfg_mac_write(port, &cfg_mac); 184 179 } 185 180 } else { 186 - port->cfg_phy.admin = false; 187 - err = prestera_hw_port_phy_mode_set(port, false, port->autoneg, 188 - port->cfg_phy.mode, 189 - port->adver_link_modes, 190 - port->cfg_phy.mdix); 181 + if (port->caps.transceiver == PRESTERA_PORT_TCVR_SFP) { 182 + err = prestera_port_cfg_mac_read(port, &cfg_mac); 183 + if (!err) { 184 + cfg_mac.admin = false; 185 + prestera_port_cfg_mac_write(port, &cfg_mac); 186 + } 187 + } else { 188 + port->cfg_phy.admin = false; 189 + err = prestera_hw_port_phy_mode_set(port, false, port->autoneg, 190 + port->cfg_phy.mode, 191 + port->adver_link_modes, 192 + port->cfg_phy.mdix); 193 + } 191 194 } 192 195 193 196 return err; 197 + } 198 + 199 + static void 200 + prestera_port_mac_state_cache_read(struct prestera_port *port, 201 + struct prestera_port_mac_state *state) 202 + { 203 + spin_lock(&port->state_mac_lock); 204 + *state = port->state_mac; 205 + spin_unlock(&port->state_mac_lock); 206 + } 207 + 208 + static void 209 + prestera_port_mac_state_cache_write(struct prestera_port *port, 210 + struct prestera_port_mac_state *state) 211 + { 212 + spin_lock(&port->state_mac_lock); 213 + port->state_mac = *state; 214 + spin_unlock(&port->state_mac_lock); 215 + } 216 + 217 + static struct prestera_port *prestera_pcs_to_port(struct phylink_pcs *pcs) 218 + { 219 + return container_of(pcs, struct prestera_port, phylink_pcs); 220 + } 221 + 222 + static void prestera_mac_config(struct phylink_config *config, 223 + unsigned int an_mode, 224 + const struct phylink_link_state *state) 225 + { 226 + } 227 + 228 + static void prestera_mac_link_down(struct phylink_config *config, 229 + unsigned int mode, phy_interface_t interface) 230 + { 231 + struct net_device *ndev = to_net_dev(config->dev); 232 + struct prestera_port *port = netdev_priv(ndev); 233 + struct prestera_port_mac_state state_mac; 234 + 235 + /* Invalidate. Parameters will update on next link event. */ 236 + memset(&state_mac, 0, sizeof(state_mac)); 237 + state_mac.valid = false; 238 + prestera_port_mac_state_cache_write(port, &state_mac); 239 + } 240 + 241 + static void prestera_mac_link_up(struct phylink_config *config, 242 + struct phy_device *phy, 243 + unsigned int mode, phy_interface_t interface, 244 + int speed, int duplex, 245 + bool tx_pause, bool rx_pause) 246 + { 247 + } 248 + 249 + static struct phylink_pcs * 250 + prestera_mac_select_pcs(struct phylink_config *config, 251 + phy_interface_t interface) 252 + { 253 + struct net_device *dev = to_net_dev(config->dev); 254 + struct prestera_port *port = netdev_priv(dev); 255 + 256 + return &port->phylink_pcs; 257 + } 258 + 259 + static void prestera_pcs_get_state(struct phylink_pcs *pcs, 260 + struct phylink_link_state *state) 261 + { 262 + struct prestera_port *port = container_of(pcs, struct prestera_port, 263 + phylink_pcs); 264 + struct prestera_port_mac_state smac; 265 + 266 + prestera_port_mac_state_cache_read(port, &smac); 267 + 268 + if (smac.valid) { 269 + state->link = smac.oper ? 1 : 0; 270 + /* AN is completed, when port is up */ 271 + state->an_complete = (smac.oper && port->autoneg) ? 1 : 0; 272 + state->speed = smac.speed; 273 + state->duplex = smac.duplex; 274 + } else { 275 + state->link = 0; 276 + state->an_complete = 0; 277 + } 278 + } 279 + 280 + static int prestera_pcs_config(struct phylink_pcs *pcs, 281 + unsigned int mode, 282 + phy_interface_t interface, 283 + const unsigned long *advertising, 284 + bool permit_pause_to_mac) 285 + { 286 + struct prestera_port *port = port = prestera_pcs_to_port(pcs); 287 + struct prestera_port_mac_config cfg_mac; 288 + int err; 289 + 290 + err = prestera_port_cfg_mac_read(port, &cfg_mac); 291 + if (err) 292 + return err; 293 + 294 + cfg_mac.admin = true; 295 + cfg_mac.fec = PRESTERA_PORT_FEC_OFF; 296 + 297 + switch (interface) { 298 + case PHY_INTERFACE_MODE_10GBASER: 299 + cfg_mac.speed = SPEED_10000; 300 + cfg_mac.inband = 0; 301 + cfg_mac.mode = PRESTERA_MAC_MODE_SR_LR; 302 + break; 303 + case PHY_INTERFACE_MODE_2500BASEX: 304 + cfg_mac.speed = SPEED_2500; 305 + cfg_mac.duplex = DUPLEX_FULL; 306 + cfg_mac.inband = test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, 307 + advertising); 308 + cfg_mac.mode = PRESTERA_MAC_MODE_SGMII; 309 + break; 310 + case PHY_INTERFACE_MODE_SGMII: 311 + cfg_mac.inband = 1; 312 + cfg_mac.mode = PRESTERA_MAC_MODE_SGMII; 313 + break; 314 + case PHY_INTERFACE_MODE_1000BASEX: 315 + default: 316 + cfg_mac.speed = SPEED_1000; 317 + cfg_mac.duplex = DUPLEX_FULL; 318 + cfg_mac.inband = test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, 319 + advertising); 320 + cfg_mac.mode = PRESTERA_MAC_MODE_1000BASE_X; 321 + break; 322 + } 323 + 324 + err = prestera_port_cfg_mac_write(port, &cfg_mac); 325 + if (err) 326 + return err; 327 + 328 + return 0; 329 + } 330 + 331 + static void prestera_pcs_an_restart(struct phylink_pcs *pcs) 332 + { 333 + /* TODO: add 1000basex AN restart support 334 + * (Currently FW has no support for 1000baseX AN restart, but it will in the future, 335 + * so as for now the function would stay empty.) 336 + */ 337 + } 338 + 339 + static const struct phylink_mac_ops prestera_mac_ops = { 340 + .validate = phylink_generic_validate, 341 + .mac_select_pcs = prestera_mac_select_pcs, 342 + .mac_config = prestera_mac_config, 343 + .mac_link_down = prestera_mac_link_down, 344 + .mac_link_up = prestera_mac_link_up, 345 + }; 346 + 347 + static const struct phylink_pcs_ops prestera_pcs_ops = { 348 + .pcs_get_state = prestera_pcs_get_state, 349 + .pcs_config = prestera_pcs_config, 350 + .pcs_an_restart = prestera_pcs_an_restart, 351 + }; 352 + 353 + static int prestera_port_sfp_bind(struct prestera_port *port) 354 + { 355 + struct prestera_switch *sw = port->sw; 356 + struct device_node *ports, *node; 357 + struct fwnode_handle *fwnode; 358 + struct phylink *phy_link; 359 + int err; 360 + 361 + if (!sw->np) 362 + return 0; 363 + 364 + ports = of_find_node_by_name(sw->np, "ports"); 365 + 366 + for_each_child_of_node(ports, node) { 367 + int num; 368 + 369 + err = of_property_read_u32(node, "prestera,port-num", &num); 370 + if (err) { 371 + dev_err(sw->dev->dev, 372 + "device node %pOF has no valid reg property: %d\n", 373 + node, err); 374 + goto out; 375 + } 376 + 377 + if (port->fp_id != num) 378 + continue; 379 + 380 + port->phylink_pcs.ops = &prestera_pcs_ops; 381 + 382 + port->phy_config.dev = &port->dev->dev; 383 + port->phy_config.type = PHYLINK_NETDEV; 384 + 385 + fwnode = of_fwnode_handle(node); 386 + 387 + __set_bit(PHY_INTERFACE_MODE_10GBASER, 388 + port->phy_config.supported_interfaces); 389 + __set_bit(PHY_INTERFACE_MODE_2500BASEX, 390 + port->phy_config.supported_interfaces); 391 + __set_bit(PHY_INTERFACE_MODE_SGMII, 392 + port->phy_config.supported_interfaces); 393 + __set_bit(PHY_INTERFACE_MODE_1000BASEX, 394 + port->phy_config.supported_interfaces); 395 + 396 + port->phy_config.mac_capabilities = 397 + MAC_1000 | MAC_2500FD | MAC_10000FD; 398 + 399 + phy_link = phylink_create(&port->phy_config, fwnode, 400 + PHY_INTERFACE_MODE_INTERNAL, 401 + &prestera_mac_ops); 402 + if (IS_ERR(phy_link)) { 403 + netdev_err(port->dev, "failed to create phylink\n"); 404 + err = PTR_ERR(phy_link); 405 + goto out; 406 + } 407 + 408 + port->phy_link = phy_link; 409 + break; 410 + } 411 + 412 + out: 413 + of_node_put(ports); 414 + return err; 415 + } 416 + 417 + static int prestera_port_sfp_unbind(struct prestera_port *port) 418 + { 419 + if (port->phy_link) 420 + phylink_destroy(port->phy_link); 421 + 422 + return 0; 194 423 } 195 424 196 425 static netdev_tx_t prestera_port_xmit(struct sk_buff *skb, ··· 609 366 port->id = id; 610 367 port->sw = sw; 611 368 369 + spin_lock_init(&port->state_mac_lock); 370 + 612 371 err = prestera_hw_port_info_get(port, &port->dev_id, &port->hw_id, 613 372 &port->fp_id); 614 373 if (err) { ··· 625 380 dev->features |= NETIF_F_NETNS_LOCAL | NETIF_F_HW_TC; 626 381 dev->netdev_ops = &prestera_netdev_ops; 627 382 dev->ethtool_ops = &prestera_ethtool_ops; 383 + SET_NETDEV_DEV(dev, sw->dev->dev); 628 384 629 - netif_carrier_off(dev); 385 + if (port->caps.transceiver != PRESTERA_PORT_TCVR_SFP) 386 + netif_carrier_off(dev); 630 387 631 388 dev->mtu = min_t(unsigned int, sw->mtu_max, PRESTERA_MTU_DEFAULT); 632 389 dev->min_mtu = sw->mtu_min; ··· 679 432 cfg_mac.admin = false; 680 433 cfg_mac.mode = PRESTERA_MAC_MODE_MAX; 681 434 } 682 - cfg_mac.inband = false; 435 + cfg_mac.inband = 0; 683 436 cfg_mac.speed = 0; 684 437 cfg_mac.duplex = DUPLEX_UNKNOWN; 685 438 cfg_mac.fec = PRESTERA_PORT_FEC_OFF; ··· 721 474 722 475 prestera_devlink_port_set(port); 723 476 477 + err = prestera_port_sfp_bind(port); 478 + if (err) 479 + goto err_sfp_bind; 480 + 724 481 return 0; 725 482 483 + err_sfp_bind: 726 484 err_register_netdev: 727 485 prestera_port_list_del(port); 728 486 err_port_init: ··· 773 521 return 0; 774 522 775 523 err_port_create: 776 - list_for_each_entry_safe(port, tmp, &sw->port_list, list) 524 + list_for_each_entry_safe(port, tmp, &sw->port_list, list) { 525 + prestera_port_sfp_unbind(port); 777 526 prestera_port_destroy(port); 527 + } 778 528 779 529 return err; 780 530 } ··· 784 530 static void prestera_port_handle_event(struct prestera_switch *sw, 785 531 struct prestera_event *evt, void *arg) 786 532 { 533 + struct prestera_port_mac_state smac; 534 + struct prestera_port_event *pevt; 787 535 struct delayed_work *caching_dw; 788 536 struct prestera_port *port; 789 537 790 - port = prestera_find_port(sw, evt->port_evt.port_id); 791 - if (!port || !port->dev) 792 - return; 793 - 794 - caching_dw = &port->cached_hw_stats.caching_dw; 795 - 796 - prestera_ethtool_port_state_changed(port, &evt->port_evt); 797 - 798 538 if (evt->id == PRESTERA_PORT_EVENT_MAC_STATE_CHANGED) { 539 + pevt = &evt->port_evt; 540 + port = prestera_find_port(sw, pevt->port_id); 541 + if (!port || !port->dev) 542 + return; 543 + 544 + caching_dw = &port->cached_hw_stats.caching_dw; 545 + 546 + if (port->phy_link) { 547 + memset(&smac, 0, sizeof(smac)); 548 + smac.valid = true; 549 + smac.oper = pevt->data.mac.oper; 550 + if (smac.oper) { 551 + smac.mode = pevt->data.mac.mode; 552 + smac.speed = pevt->data.mac.speed; 553 + smac.duplex = pevt->data.mac.duplex; 554 + smac.fc = pevt->data.mac.fc; 555 + smac.fec = pevt->data.mac.fec; 556 + phylink_mac_change(port->phy_link, true); 557 + } else { 558 + phylink_mac_change(port->phy_link, false); 559 + } 560 + prestera_port_mac_state_cache_write(port, &smac); 561 + } 562 + 799 563 if (port->state_mac.oper) { 800 - netif_carrier_on(port->dev); 564 + if (!port->phy_link) 565 + netif_carrier_on(port->dev); 566 + 801 567 if (!delayed_work_pending(caching_dw)) 802 568 queue_delayed_work(prestera_wq, caching_dw, 0); 803 569 } else if (netif_running(port->dev) && 804 570 netif_carrier_ok(port->dev)) { 805 - netif_carrier_off(port->dev); 571 + if (!port->phy_link) 572 + netif_carrier_off(port->dev); 573 + 806 574 if (delayed_work_pending(caching_dw)) 807 575 cancel_delayed_work(caching_dw); 808 576 } ··· 847 571 static int prestera_switch_set_base_mac_addr(struct prestera_switch *sw) 848 572 { 849 573 struct device_node *base_mac_np; 850 - struct device_node *np; 851 574 int ret; 852 575 853 - np = of_find_compatible_node(NULL, NULL, "marvell,prestera"); 854 - base_mac_np = of_parse_phandle(np, "base-mac-provider", 0); 576 + if (sw->np) { 577 + base_mac_np = of_parse_phandle(sw->np, "base-mac-provider", 0); 578 + if (base_mac_np) { 579 + ret = of_get_mac_address(base_mac_np, sw->base_mac); 580 + of_node_put(base_mac_np); 581 + } 582 + } 855 583 856 - ret = of_get_mac_address(base_mac_np, sw->base_mac); 857 - if (ret) { 584 + if (!is_valid_ether_addr(sw->base_mac) || ret) { 858 585 eth_random_addr(sw->base_mac); 859 586 dev_info(prestera_dev(sw), "using random base mac address\n"); 860 587 } 861 - of_node_put(base_mac_np); 862 - of_node_put(np); 863 588 864 589 return prestera_hw_switch_mac_set(sw, sw->base_mac); 865 590 } ··· 1360 1083 { 1361 1084 int err; 1362 1085 1086 + sw->np = of_find_compatible_node(NULL, NULL, "marvell,prestera"); 1087 + 1363 1088 err = prestera_hw_switch_init(sw); 1364 1089 if (err) { 1365 1090 dev_err(prestera_dev(sw), "Failed to init Switch device\n"); ··· 1462 1183 prestera_router_fini(sw); 1463 1184 prestera_netdev_event_handler_unregister(sw); 1464 1185 prestera_hw_switch_fini(sw); 1186 + of_node_put(sw->np); 1465 1187 } 1466 1188 1467 1189 int prestera_device_register(struct prestera_device *dev)