| .. | .. |
|---|
| 11 | 11 | #include <linux/device.h> |
|---|
| 12 | 12 | #include <linux/skbuff.h> |
|---|
| 13 | 13 | #include <linux/if_vlan.h> |
|---|
| 14 | | -#include <net/switchdev.h> |
|---|
| 15 | 14 | |
|---|
| 16 | 15 | #include "pci.h" |
|---|
| 17 | 16 | #include "core.h" |
|---|
| .. | .. |
|---|
| 181 | 180 | if (err) |
|---|
| 182 | 181 | return err; |
|---|
| 183 | 182 | oper_status = mlxsw_reg_paos_oper_status_get(paos_pl); |
|---|
| 184 | | - *p_is_up = oper_status == MLXSW_PORT_ADMIN_STATUS_UP ? true : false; |
|---|
| 183 | + *p_is_up = oper_status == MLXSW_PORT_ADMIN_STATUS_UP; |
|---|
| 185 | 184 | return 0; |
|---|
| 186 | 185 | } |
|---|
| 187 | 186 | |
|---|
| .. | .. |
|---|
| 300 | 299 | u64 len; |
|---|
| 301 | 300 | int err; |
|---|
| 302 | 301 | |
|---|
| 302 | + if (skb_cow_head(skb, MLXSW_TXHDR_LEN)) { |
|---|
| 303 | + this_cpu_inc(mlxsw_sx_port->pcpu_stats->tx_dropped); |
|---|
| 304 | + dev_kfree_skb_any(skb); |
|---|
| 305 | + return NETDEV_TX_OK; |
|---|
| 306 | + } |
|---|
| 307 | + |
|---|
| 308 | + memset(skb->cb, 0, sizeof(struct mlxsw_skb_cb)); |
|---|
| 309 | + |
|---|
| 303 | 310 | if (mlxsw_core_skb_transmit_busy(mlxsw_sx->core, &tx_info)) |
|---|
| 304 | 311 | return NETDEV_TX_BUSY; |
|---|
| 305 | 312 | |
|---|
| 306 | | - if (unlikely(skb_headroom(skb) < MLXSW_TXHDR_LEN)) { |
|---|
| 307 | | - struct sk_buff *skb_orig = skb; |
|---|
| 308 | | - |
|---|
| 309 | | - skb = skb_realloc_headroom(skb, MLXSW_TXHDR_LEN); |
|---|
| 310 | | - if (!skb) { |
|---|
| 311 | | - this_cpu_inc(mlxsw_sx_port->pcpu_stats->tx_dropped); |
|---|
| 312 | | - dev_kfree_skb_any(skb_orig); |
|---|
| 313 | | - return NETDEV_TX_OK; |
|---|
| 314 | | - } |
|---|
| 315 | | - dev_consume_skb_any(skb_orig); |
|---|
| 316 | | - } |
|---|
| 317 | 313 | mlxsw_sx_txhdr_construct(skb, &tx_info); |
|---|
| 318 | 314 | /* TX header is consumed by HW on the way so we shouldn't count its |
|---|
| 319 | 315 | * bytes as being sent. |
|---|
| .. | .. |
|---|
| 380 | 376 | stats->tx_dropped = tx_dropped; |
|---|
| 381 | 377 | } |
|---|
| 382 | 378 | |
|---|
| 383 | | -static int mlxsw_sx_port_get_phys_port_name(struct net_device *dev, char *name, |
|---|
| 384 | | - size_t len) |
|---|
| 379 | +static struct devlink_port * |
|---|
| 380 | +mlxsw_sx_port_get_devlink_port(struct net_device *dev) |
|---|
| 385 | 381 | { |
|---|
| 386 | 382 | struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev); |
|---|
| 383 | + struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; |
|---|
| 387 | 384 | |
|---|
| 388 | | - return mlxsw_core_port_get_phys_port_name(mlxsw_sx_port->mlxsw_sx->core, |
|---|
| 389 | | - mlxsw_sx_port->local_port, |
|---|
| 390 | | - name, len); |
|---|
| 385 | + return mlxsw_core_port_devlink_port_get(mlxsw_sx->core, |
|---|
| 386 | + mlxsw_sx_port->local_port); |
|---|
| 391 | 387 | } |
|---|
| 392 | 388 | |
|---|
| 393 | 389 | static const struct net_device_ops mlxsw_sx_port_netdev_ops = { |
|---|
| .. | .. |
|---|
| 396 | 392 | .ndo_start_xmit = mlxsw_sx_port_xmit, |
|---|
| 397 | 393 | .ndo_change_mtu = mlxsw_sx_port_change_mtu, |
|---|
| 398 | 394 | .ndo_get_stats64 = mlxsw_sx_port_get_stats64, |
|---|
| 399 | | - .ndo_get_phys_port_name = mlxsw_sx_port_get_phys_port_name, |
|---|
| 395 | + .ndo_get_devlink_port = mlxsw_sx_port_get_devlink_port, |
|---|
| 400 | 396 | }; |
|---|
| 401 | 397 | |
|---|
| 402 | 398 | static void mlxsw_sx_port_get_drvinfo(struct net_device *dev, |
|---|
| .. | .. |
|---|
| 555 | 551 | |
|---|
| 556 | 552 | static const struct mlxsw_sx_port_link_mode mlxsw_sx_port_link_mode[] = { |
|---|
| 557 | 553 | { |
|---|
| 558 | | - .mask = MLXSW_REG_PTYS_ETH_SPEED_100BASE_T, |
|---|
| 559 | | - .supported = SUPPORTED_100baseT_Full, |
|---|
| 560 | | - .advertised = ADVERTISED_100baseT_Full, |
|---|
| 561 | | - .speed = 100, |
|---|
| 562 | | - }, |
|---|
| 563 | | - { |
|---|
| 564 | | - .mask = MLXSW_REG_PTYS_ETH_SPEED_100BASE_TX, |
|---|
| 565 | | - .speed = 100, |
|---|
| 566 | | - }, |
|---|
| 567 | | - { |
|---|
| 568 | 554 | .mask = MLXSW_REG_PTYS_ETH_SPEED_SGMII | |
|---|
| 569 | 555 | MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX, |
|---|
| 570 | 556 | .supported = SUPPORTED_1000baseKX_Full, |
|---|
| 571 | 557 | .advertised = ADVERTISED_1000baseKX_Full, |
|---|
| 572 | 558 | .speed = 1000, |
|---|
| 573 | | - }, |
|---|
| 574 | | - { |
|---|
| 575 | | - .mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_T, |
|---|
| 576 | | - .supported = SUPPORTED_10000baseT_Full, |
|---|
| 577 | | - .advertised = ADVERTISED_10000baseT_Full, |
|---|
| 578 | | - .speed = 10000, |
|---|
| 579 | 559 | }, |
|---|
| 580 | 560 | { |
|---|
| 581 | 561 | .mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CX4 | |
|---|
| .. | .. |
|---|
| 592 | 572 | .supported = SUPPORTED_10000baseKR_Full, |
|---|
| 593 | 573 | .advertised = ADVERTISED_10000baseKR_Full, |
|---|
| 594 | 574 | .speed = 10000, |
|---|
| 595 | | - }, |
|---|
| 596 | | - { |
|---|
| 597 | | - .mask = MLXSW_REG_PTYS_ETH_SPEED_20GBASE_KR2, |
|---|
| 598 | | - .supported = SUPPORTED_20000baseKR2_Full, |
|---|
| 599 | | - .advertised = ADVERTISED_20000baseKR2_Full, |
|---|
| 600 | | - .speed = 20000, |
|---|
| 601 | 575 | }, |
|---|
| 602 | 576 | { |
|---|
| 603 | 577 | .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4, |
|---|
| .. | .. |
|---|
| 634 | 608 | MLXSW_REG_PTYS_ETH_SPEED_50GBASE_CR2 | |
|---|
| 635 | 609 | MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR2, |
|---|
| 636 | 610 | .speed = 50000, |
|---|
| 637 | | - }, |
|---|
| 638 | | - { |
|---|
| 639 | | - .mask = MLXSW_REG_PTYS_ETH_SPEED_56GBASE_R4, |
|---|
| 640 | | - .supported = SUPPORTED_56000baseKR4_Full, |
|---|
| 641 | | - .advertised = ADVERTISED_56000baseKR4_Full, |
|---|
| 642 | | - .speed = 56000, |
|---|
| 643 | 611 | }, |
|---|
| 644 | 612 | { |
|---|
| 645 | 613 | .mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4 | |
|---|
| .. | .. |
|---|
| 901 | 869 | .set_link_ksettings = mlxsw_sx_port_set_link_ksettings, |
|---|
| 902 | 870 | }; |
|---|
| 903 | 871 | |
|---|
| 904 | | -static int mlxsw_sx_port_attr_get(struct net_device *dev, |
|---|
| 905 | | - struct switchdev_attr *attr) |
|---|
| 906 | | -{ |
|---|
| 907 | | - struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev); |
|---|
| 908 | | - struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; |
|---|
| 909 | | - |
|---|
| 910 | | - switch (attr->id) { |
|---|
| 911 | | - case SWITCHDEV_ATTR_ID_PORT_PARENT_ID: |
|---|
| 912 | | - attr->u.ppid.id_len = sizeof(mlxsw_sx->hw_id); |
|---|
| 913 | | - memcpy(&attr->u.ppid.id, &mlxsw_sx->hw_id, attr->u.ppid.id_len); |
|---|
| 914 | | - break; |
|---|
| 915 | | - default: |
|---|
| 916 | | - return -EOPNOTSUPP; |
|---|
| 917 | | - } |
|---|
| 918 | | - |
|---|
| 919 | | - return 0; |
|---|
| 920 | | -} |
|---|
| 921 | | - |
|---|
| 922 | | -static const struct switchdev_ops mlxsw_sx_port_switchdev_ops = { |
|---|
| 923 | | - .switchdev_port_attr_get = mlxsw_sx_port_attr_get, |
|---|
| 924 | | -}; |
|---|
| 925 | | - |
|---|
| 926 | 872 | static int mlxsw_sx_hw_id_get(struct mlxsw_sx *mlxsw_sx) |
|---|
| 927 | 873 | { |
|---|
| 928 | 874 | char spad_pl[MLXSW_REG_SPAD_LEN] = {0}; |
|---|
| .. | .. |
|---|
| 1019 | 965 | if (!dev) |
|---|
| 1020 | 966 | return -ENOMEM; |
|---|
| 1021 | 967 | SET_NETDEV_DEV(dev, mlxsw_sx->bus_info->dev); |
|---|
| 968 | + dev_net_set(dev, mlxsw_core_net(mlxsw_sx->core)); |
|---|
| 1022 | 969 | mlxsw_sx_port = netdev_priv(dev); |
|---|
| 1023 | 970 | mlxsw_sx_port->dev = dev; |
|---|
| 1024 | 971 | mlxsw_sx_port->mlxsw_sx = mlxsw_sx; |
|---|
| .. | .. |
|---|
| 1034 | 981 | |
|---|
| 1035 | 982 | dev->netdev_ops = &mlxsw_sx_port_netdev_ops; |
|---|
| 1036 | 983 | dev->ethtool_ops = &mlxsw_sx_port_ethtool_ops; |
|---|
| 1037 | | - dev->switchdev_ops = &mlxsw_sx_port_switchdev_ops; |
|---|
| 1038 | 984 | |
|---|
| 1039 | 985 | err = mlxsw_sx_port_dev_addr_get(mlxsw_sx_port); |
|---|
| 1040 | 986 | if (err) { |
|---|
| .. | .. |
|---|
| 1113 | 1059 | } |
|---|
| 1114 | 1060 | |
|---|
| 1115 | 1061 | mlxsw_core_port_eth_set(mlxsw_sx->core, mlxsw_sx_port->local_port, |
|---|
| 1116 | | - mlxsw_sx_port, dev, module + 1, false, 0); |
|---|
| 1062 | + mlxsw_sx_port, dev); |
|---|
| 1117 | 1063 | mlxsw_sx->ports[local_port] = mlxsw_sx_port; |
|---|
| 1118 | 1064 | return 0; |
|---|
| 1119 | 1065 | |
|---|
| .. | .. |
|---|
| 1138 | 1084 | { |
|---|
| 1139 | 1085 | int err; |
|---|
| 1140 | 1086 | |
|---|
| 1141 | | - err = mlxsw_core_port_init(mlxsw_sx->core, local_port); |
|---|
| 1087 | + err = mlxsw_core_port_init(mlxsw_sx->core, local_port, |
|---|
| 1088 | + module + 1, false, 0, false, 0, |
|---|
| 1089 | + mlxsw_sx->hw_id, sizeof(mlxsw_sx->hw_id)); |
|---|
| 1142 | 1090 | if (err) { |
|---|
| 1143 | 1091 | dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to init core port\n", |
|---|
| 1144 | 1092 | local_port); |
|---|
| .. | .. |
|---|
| 1434 | 1382 | return err; |
|---|
| 1435 | 1383 | } |
|---|
| 1436 | 1384 | |
|---|
| 1385 | +enum { |
|---|
| 1386 | + MLXSW_REG_HTGT_TRAP_GROUP_SX2_RX = 1, |
|---|
| 1387 | + MLXSW_REG_HTGT_TRAP_GROUP_SX2_CTRL = 2, |
|---|
| 1388 | +}; |
|---|
| 1389 | + |
|---|
| 1437 | 1390 | #define MLXSW_SX_RXL(_trap_id) \ |
|---|
| 1438 | 1391 | MLXSW_RXL(mlxsw_sx_rx_listener_func, _trap_id, TRAP_TO_CPU, \ |
|---|
| 1439 | 1392 | false, SX2_RX, FORWARD) |
|---|
| .. | .. |
|---|
| 1597 | 1550 | } |
|---|
| 1598 | 1551 | |
|---|
| 1599 | 1552 | static int mlxsw_sx_init(struct mlxsw_core *mlxsw_core, |
|---|
| 1600 | | - const struct mlxsw_bus_info *mlxsw_bus_info) |
|---|
| 1553 | + const struct mlxsw_bus_info *mlxsw_bus_info, |
|---|
| 1554 | + struct netlink_ext_ack *extack) |
|---|
| 1601 | 1555 | { |
|---|
| 1602 | 1556 | struct mlxsw_sx *mlxsw_sx = mlxsw_core_driver_priv(mlxsw_core); |
|---|
| 1603 | 1557 | int err; |
|---|