diff options
Diffstat (limited to 'drivers/net/ethernet/mellanox')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 69 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 40 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/qp.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/vport.c | 38 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 203 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 5 |
8 files changed, 227 insertions, 138 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index fd4392999eee..f5c8d5db25a8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -3192,10 +3192,7 @@ static void mlx5e_destroy_netdev(struct mlx5_core_dev *mdev, void *vpriv) flush_workqueue(priv->wq); if (test_bit(MLX5_INTERFACE_STATE_SHUTDOWN, &mdev->intf_state)) { netif_device_detach(netdev); - mutex_lock(&priv->state_lock); - if (test_bit(MLX5E_STATE_OPENED, &priv->state)) - mlx5e_close_locked(netdev); - mutex_unlock(&priv->state_lock); + mlx5e_close(netdev); } else { unregister_netdev(netdev); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index 229ab16fb8d3..b000ddc29553 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -317,7 +317,8 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb) while ((sq->pc & wq->sz_m1) > sq->edge) mlx5e_send_nop(sq, false); - sq->bf_budget = bf ? sq->bf_budget - 1 : 0; + if (bf) + sq->bf_budget--; sq->stats.packets++; sq->stats.bytes += num_bytes; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index b84a6918a700..aebbd6ccb9fe 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -383,7 +383,7 @@ __esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u32 vport, bool rx_rule, match_v, MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, 0, &dest); - if (IS_ERR_OR_NULL(flow_rule)) { + if (IS_ERR(flow_rule)) { pr_warn( "FDB: Failed to add flow rule: dmac_v(%pM) dmac_c(%pM) -> vport(%d), err(%ld)\n", dmac_v, dmac_c, vport, PTR_ERR(flow_rule)); @@ -457,7 +457,7 @@ static int esw_create_fdb_table(struct mlx5_eswitch *esw, int nvports) table_size = BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size)); fdb = mlx5_create_flow_table(root_ns, 0, table_size, 0); - if (IS_ERR_OR_NULL(fdb)) { + if (IS_ERR(fdb)) { err = PTR_ERR(fdb); esw_warn(dev, "Failed to create FDB Table err %d\n", err); goto out; @@ -474,7 +474,7 @@ static int esw_create_fdb_table(struct mlx5_eswitch *esw, int nvports) MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 3); eth_broadcast_addr(dmac); g = mlx5_create_flow_group(fdb, flow_group_in); - if (IS_ERR_OR_NULL(g)) { + if (IS_ERR(g)) { err = PTR_ERR(g); esw_warn(dev, "Failed to create flow group err(%d)\n", err); goto out; @@ -489,7 +489,7 @@ static int esw_create_fdb_table(struct mlx5_eswitch *esw, int nvports) eth_zero_addr(dmac); dmac[0] = 0x01; g = mlx5_create_flow_group(fdb, flow_group_in); - if (IS_ERR_OR_NULL(g)) { + if (IS_ERR(g)) { err = PTR_ERR(g); esw_warn(dev, "Failed to create allmulti flow group err(%d)\n", err); goto out; @@ -506,7 +506,7 @@ static int esw_create_fdb_table(struct mlx5_eswitch *esw, int nvports) MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 1); MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 1); g = mlx5_create_flow_group(fdb, flow_group_in); - if (IS_ERR_OR_NULL(g)) { + if (IS_ERR(g)) { err = PTR_ERR(g); esw_warn(dev, "Failed to create promisc flow group err(%d)\n", err); goto out; @@ -529,7 +529,7 @@ out: } } - kfree(flow_group_in); + kvfree(flow_group_in); return err; } @@ -651,6 +651,7 @@ static void update_allmulti_vports(struct mlx5_eswitch *esw, esw_fdb_set_vport_rule(esw, mac, vport_idx); + iter_vaddr->mc_promisc = true; break; case MLX5_ACTION_DEL: if (!iter_vaddr) @@ -1060,7 +1061,7 @@ static void esw_vport_enable_egress_acl(struct mlx5_eswitch *esw, return; acl = mlx5_create_vport_flow_table(root_ns, 0, table_size, 0, vport->vport); - if (IS_ERR_OR_NULL(acl)) { + if (IS_ERR(acl)) { err = PTR_ERR(acl); esw_warn(dev, "Failed to create E-Switch vport[%d] egress flow Table, err(%d)\n", vport->vport, err); @@ -1075,7 +1076,7 @@ static void esw_vport_enable_egress_acl(struct mlx5_eswitch *esw, MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0); vlan_grp = mlx5_create_flow_group(acl, flow_group_in); - if (IS_ERR_OR_NULL(vlan_grp)) { + if (IS_ERR(vlan_grp)) { err = PTR_ERR(vlan_grp); esw_warn(dev, "Failed to create E-Switch vport[%d] egress allowed vlans flow group, err(%d)\n", vport->vport, err); @@ -1086,7 +1087,7 @@ static void esw_vport_enable_egress_acl(struct mlx5_eswitch *esw, MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 1); MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 1); drop_grp = mlx5_create_flow_group(acl, flow_group_in); - if (IS_ERR_OR_NULL(drop_grp)) { + if (IS_ERR(drop_grp)) { err = PTR_ERR(drop_grp); esw_warn(dev, "Failed to create E-Switch vport[%d] egress drop flow group, err(%d)\n", vport->vport, err); @@ -1097,7 +1098,7 @@ static void esw_vport_enable_egress_acl(struct mlx5_eswitch *esw, vport->egress.drop_grp = drop_grp; vport->egress.allowed_vlans_grp = vlan_grp; out: - kfree(flow_group_in); + kvfree(flow_group_in); if (err && !IS_ERR_OR_NULL(vlan_grp)) mlx5_destroy_flow_group(vlan_grp); if (err && !IS_ERR_OR_NULL(acl)) @@ -1174,7 +1175,7 @@ static void esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw, return; acl = mlx5_create_vport_flow_table(root_ns, 0, table_size, 0, vport->vport); - if (IS_ERR_OR_NULL(acl)) { + if (IS_ERR(acl)) { err = PTR_ERR(acl); esw_warn(dev, "Failed to create E-Switch vport[%d] ingress flow Table, err(%d)\n", vport->vport, err); @@ -1192,7 +1193,7 @@ static void esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw, MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0); g = mlx5_create_flow_group(acl, flow_group_in); - if (IS_ERR_OR_NULL(g)) { + if (IS_ERR(g)) { err = PTR_ERR(g); esw_warn(dev, "Failed to create E-Switch vport[%d] ingress untagged spoofchk flow group, err(%d)\n", vport->vport, err); @@ -1207,7 +1208,7 @@ static void esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw, MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 1); g = mlx5_create_flow_group(acl, flow_group_in); - if (IS_ERR_OR_NULL(g)) { + if (IS_ERR(g)) { err = PTR_ERR(g); esw_warn(dev, "Failed to create E-Switch vport[%d] ingress untagged flow group, err(%d)\n", vport->vport, err); @@ -1223,7 +1224,7 @@ static void esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw, MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 2); g = mlx5_create_flow_group(acl, flow_group_in); - if (IS_ERR_OR_NULL(g)) { + if (IS_ERR(g)) { err = PTR_ERR(g); esw_warn(dev, "Failed to create E-Switch vport[%d] ingress spoofchk flow group, err(%d)\n", vport->vport, err); @@ -1236,7 +1237,7 @@ static void esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw, MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 3); g = mlx5_create_flow_group(acl, flow_group_in); - if (IS_ERR_OR_NULL(g)) { + if (IS_ERR(g)) { err = PTR_ERR(g); esw_warn(dev, "Failed to create E-Switch vport[%d] ingress drop flow group, err(%d)\n", vport->vport, err); @@ -1259,7 +1260,7 @@ out: mlx5_destroy_flow_table(vport->ingress.acl); } - kfree(flow_group_in); + kvfree(flow_group_in); } static void esw_vport_cleanup_ingress_rules(struct mlx5_eswitch *esw, @@ -1363,7 +1364,7 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw, match_v, MLX5_FLOW_CONTEXT_ACTION_ALLOW, 0, NULL); - if (IS_ERR_OR_NULL(vport->ingress.allow_rule)) { + if (IS_ERR(vport->ingress.allow_rule)) { err = PTR_ERR(vport->ingress.allow_rule); pr_warn("vport[%d] configure ingress allow rule, err(%d)\n", vport->vport, err); @@ -1380,7 +1381,7 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw, match_v, MLX5_FLOW_CONTEXT_ACTION_DROP, 0, NULL); - if (IS_ERR_OR_NULL(vport->ingress.drop_rule)) { + if (IS_ERR(vport->ingress.drop_rule)) { err = PTR_ERR(vport->ingress.drop_rule); pr_warn("vport[%d] configure ingress drop rule, err(%d)\n", vport->vport, err); @@ -1439,7 +1440,7 @@ static int esw_vport_egress_config(struct mlx5_eswitch *esw, match_v, MLX5_FLOW_CONTEXT_ACTION_ALLOW, 0, NULL); - if (IS_ERR_OR_NULL(vport->egress.allowed_vlan)) { + if (IS_ERR(vport->egress.allowed_vlan)) { err = PTR_ERR(vport->egress.allowed_vlan); pr_warn("vport[%d] configure egress allowed vlan rule failed, err(%d)\n", vport->vport, err); @@ -1457,7 +1458,7 @@ static int esw_vport_egress_config(struct mlx5_eswitch *esw, match_v, MLX5_FLOW_CONTEXT_ACTION_DROP, 0, NULL); - if (IS_ERR_OR_NULL(vport->egress.drop_rule)) { + if (IS_ERR(vport->egress.drop_rule)) { err = PTR_ERR(vport->egress.drop_rule); pr_warn("vport[%d] configure egress drop rule failed, err(%d)\n", vport->vport, err); @@ -1491,14 +1492,11 @@ static void esw_enable_vport(struct mlx5_eswitch *esw, int vport_num, /* Sync with current vport context */ vport->enabled_events = enable_events; - esw_vport_change_handle_locked(vport); - vport->enabled = true; /* only PF is trusted by default */ vport->trusted = (vport_num) ? false : true; - - arm_vport_context_events_cmd(esw->dev, vport_num, enable_events); + esw_vport_change_handle_locked(vport); esw->enabled_vports++; esw_debug(esw->dev, "Enabled VPORT(%d)\n", vport_num); @@ -1728,11 +1726,24 @@ void mlx5_eswitch_vport_event(struct mlx5_eswitch *esw, struct mlx5_eqe *eqe) (esw && MLX5_CAP_GEN(esw->dev, vport_group_manager) && mlx5_core_is_pf(esw->dev)) #define LEGAL_VPORT(esw, vport) (vport >= 0 && vport < esw->total_vports) +static void node_guid_gen_from_mac(u64 *node_guid, u8 mac[ETH_ALEN]) +{ + ((u8 *)node_guid)[7] = mac[0]; + ((u8 *)node_guid)[6] = mac[1]; + ((u8 *)node_guid)[5] = mac[2]; + ((u8 *)node_guid)[4] = 0xff; + ((u8 *)node_guid)[3] = 0xfe; + ((u8 *)node_guid)[2] = mac[3]; + ((u8 *)node_guid)[1] = mac[4]; + ((u8 *)node_guid)[0] = mac[5]; +} + int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw, int vport, u8 mac[ETH_ALEN]) { - int err = 0; struct mlx5_vport *evport; + u64 node_guid; + int err = 0; if (!ESW_ALLOWED(esw)) return -EPERM; @@ -1756,11 +1767,17 @@ int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw, return err; } + node_guid_gen_from_mac(&node_guid, mac); + err = mlx5_modify_nic_vport_node_guid(esw->dev, vport, node_guid); + if (err) + mlx5_core_warn(esw->dev, + "Failed to set vport %d node guid, err = %d. RDMA_CM will not function properly for this VF.\n", + vport, err); + mutex_lock(&esw->state_lock); if (evport->enabled) err = esw_vport_ingress_config(esw, evport); mutex_unlock(&esw->state_lock); - return err; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index 8b5f0b2c0d5c..e912a3d2505e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -1292,8 +1292,8 @@ static int update_root_ft_destroy(struct mlx5_flow_table *ft) ft->id); return err; } - root->root_ft = new_root_ft; } + root->root_ft = new_root_ft; return 0; } @@ -1767,6 +1767,9 @@ static void cleanup_root_ns(struct mlx5_core_dev *dev) void mlx5_cleanup_fs(struct mlx5_core_dev *dev) { + if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH) + return; + cleanup_root_ns(dev); cleanup_single_prio_root_ns(dev, dev->priv.fdb_root_ns); cleanup_single_prio_root_ns(dev, dev->priv.esw_egress_root_ns); @@ -1828,29 +1831,36 @@ int mlx5_init_fs(struct mlx5_core_dev *dev) { int err = 0; + if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH) + return 0; + err = mlx5_init_fc_stats(dev); if (err) return err; - if (MLX5_CAP_GEN(dev, nic_flow_table)) { + if (MLX5_CAP_GEN(dev, nic_flow_table) && + MLX5_CAP_FLOWTABLE_NIC_RX(dev, ft_support)) { err = init_root_ns(dev); if (err) goto err; } + if (MLX5_CAP_GEN(dev, eswitch_flow_table)) { - err = init_fdb_root_ns(dev); - if (err) - goto err; - } - if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) { - err = init_egress_acl_root_ns(dev); - if (err) - goto err; - } - if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) { - err = init_ingress_acl_root_ns(dev); - if (err) - goto err; + if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, ft_support)) { + err = init_fdb_root_ns(dev); + if (err) + goto err; + } + if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) { + err = init_egress_acl_root_ns(dev); + if (err) + goto err; + } + if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) { + err = init_ingress_acl_root_ns(dev); + if (err) + goto err; + } } return 0; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/qp.c b/drivers/net/ethernet/mellanox/mlx5/core/qp.c index b720a274220d..b82d65802d96 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/qp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/qp.c @@ -418,7 +418,7 @@ int mlx5_core_xrcd_alloc(struct mlx5_core_dev *dev, u32 *xrcdn) if (out.hdr.status) err = mlx5_cmd_status_to_err(&out.hdr); else - *xrcdn = be32_to_cpu(out.xrcdn); + *xrcdn = be32_to_cpu(out.xrcdn) & 0xffffff; return err; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vport.c b/drivers/net/ethernet/mellanox/mlx5/core/vport.c index b69dadcfb897..daf44cd4c566 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/vport.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/vport.c @@ -508,6 +508,44 @@ int mlx5_query_nic_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid) } EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_node_guid); +int mlx5_modify_nic_vport_node_guid(struct mlx5_core_dev *mdev, + u32 vport, u64 node_guid) +{ + int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); + void *nic_vport_context; + u8 *guid; + void *in; + int err; + + if (!vport) + return -EINVAL; + if (!MLX5_CAP_GEN(mdev, vport_group_manager)) + return -EACCES; + if (!MLX5_CAP_ESW(mdev, nic_vport_node_guid_modify)) + return -ENOTSUPP; + + in = mlx5_vzalloc(inlen); + if (!in) + return -ENOMEM; + + MLX5_SET(modify_nic_vport_context_in, in, + field_select.node_guid, 1); + MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); + MLX5_SET(modify_nic_vport_context_in, in, other_vport, !!vport); + + nic_vport_context = MLX5_ADDR_OF(modify_nic_vport_context_in, + in, nic_vport_context); + guid = MLX5_ADDR_OF(nic_vport_context, nic_vport_context, + node_guid); + MLX5_SET64(nic_vport_context, nic_vport_context, node_guid, node_guid); + + err = mlx5_modify_nic_vport_context(mdev, in, inlen); + + kvfree(in); + + return err; +} + int mlx5_query_nic_vport_qkey_viol_cntr(struct mlx5_core_dev *mdev, u16 *qkey_viol_cntr) { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 4a7273771028..6f9e3ddff4a8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -247,15 +247,23 @@ static int mlxsw_sp_port_mtu_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 mtu) return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pmtu), pmtu_pl); } -static int mlxsw_sp_port_swid_set(struct mlxsw_sp_port *mlxsw_sp_port, u8 swid) +static int __mlxsw_sp_port_swid_set(struct mlxsw_sp *mlxsw_sp, u8 local_port, + u8 swid) { - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; char pspa_pl[MLXSW_REG_PSPA_LEN]; - mlxsw_reg_pspa_pack(pspa_pl, swid, mlxsw_sp_port->local_port); + mlxsw_reg_pspa_pack(pspa_pl, swid, local_port); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pspa), pspa_pl); } +static int mlxsw_sp_port_swid_set(struct mlxsw_sp_port *mlxsw_sp_port, u8 swid) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + + return __mlxsw_sp_port_swid_set(mlxsw_sp, mlxsw_sp_port->local_port, + swid); +} + static int mlxsw_sp_port_vp_mode_set(struct mlxsw_sp_port *mlxsw_sp_port, bool enable) { @@ -305,9 +313,9 @@ mlxsw_sp_port_system_port_mapping_set(struct mlxsw_sp_port *mlxsw_sp_port) return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sspr), sspr_pl); } -static int __mlxsw_sp_port_module_info_get(struct mlxsw_sp *mlxsw_sp, - u8 local_port, u8 *p_module, - u8 *p_width, u8 *p_lane) +static int mlxsw_sp_port_module_info_get(struct mlxsw_sp *mlxsw_sp, + u8 local_port, u8 *p_module, + u8 *p_width, u8 *p_lane) { char pmlp_pl[MLXSW_REG_PMLP_LEN]; int err; @@ -322,16 +330,6 @@ static int __mlxsw_sp_port_module_info_get(struct mlxsw_sp *mlxsw_sp, return 0; } -static int mlxsw_sp_port_module_info_get(struct mlxsw_sp *mlxsw_sp, - u8 local_port, u8 *p_module, - u8 *p_width) -{ - u8 lane; - - return __mlxsw_sp_port_module_info_get(mlxsw_sp, local_port, p_module, - p_width, &lane); -} - static int mlxsw_sp_port_module_map(struct mlxsw_sp *mlxsw_sp, u8 local_port, u8 module, u8 width, u8 lane) { @@ -949,17 +947,11 @@ static int mlxsw_sp_port_get_phys_port_name(struct net_device *dev, char *name, size_t len) { struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); - u8 module, width, lane; + u8 module = mlxsw_sp_port->mapping.module; + u8 width = mlxsw_sp_port->mapping.width; + u8 lane = mlxsw_sp_port->mapping.lane; int err; - err = __mlxsw_sp_port_module_info_get(mlxsw_sp_port->mlxsw_sp, - mlxsw_sp_port->local_port, - &module, &width, &lane); - if (err) { - netdev_err(dev, "Failed to retrieve module information\n"); - return err; - } - if (!mlxsw_sp_port->split) err = snprintf(name, len, "p%d", module + 1); else @@ -1681,8 +1673,8 @@ static int mlxsw_sp_port_ets_init(struct mlxsw_sp_port *mlxsw_sp_port) return 0; } -static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, - bool split, u8 module, u8 width) +static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, + bool split, u8 module, u8 width, u8 lane) { struct mlxsw_sp_port *mlxsw_sp_port; struct net_device *dev; @@ -1697,6 +1689,9 @@ static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, mlxsw_sp_port->mlxsw_sp = mlxsw_sp; mlxsw_sp_port->local_port = local_port; mlxsw_sp_port->split = split; + mlxsw_sp_port->mapping.module = module; + mlxsw_sp_port->mapping.width = width; + mlxsw_sp_port->mapping.lane = lane; bytes = DIV_ROUND_UP(VLAN_N_VID, BITS_PER_BYTE); mlxsw_sp_port->active_vlans = kzalloc(bytes, GFP_KERNEL); if (!mlxsw_sp_port->active_vlans) { @@ -1839,28 +1834,6 @@ err_port_active_vlans_alloc: return err; } -static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, - bool split, u8 module, u8 width, u8 lane) -{ - int err; - - err = mlxsw_sp_port_module_map(mlxsw_sp, local_port, module, width, - lane); - if (err) - return err; - - err = __mlxsw_sp_port_create(mlxsw_sp, local_port, split, module, - width); - if (err) - goto err_port_create; - - return 0; - -err_port_create: - mlxsw_sp_port_module_unmap(mlxsw_sp, local_port); - return err; -} - static void mlxsw_sp_port_vports_fini(struct mlxsw_sp_port *mlxsw_sp_port) { struct net_device *dev = mlxsw_sp_port->dev; @@ -1909,8 +1882,8 @@ static void mlxsw_sp_ports_remove(struct mlxsw_sp *mlxsw_sp) static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp) { + u8 module, width, lane; size_t alloc_size; - u8 module, width; int i; int err; @@ -1921,13 +1894,14 @@ static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp) for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++) { err = mlxsw_sp_port_module_info_get(mlxsw_sp, i, &module, - &width); + &width, &lane); if (err) goto err_port_module_info_get; if (!width) continue; mlxsw_sp->port_to_module[i] = module; - err = __mlxsw_sp_port_create(mlxsw_sp, i, false, module, width); + err = mlxsw_sp_port_create(mlxsw_sp, i, false, module, width, + lane); if (err) goto err_port_create; } @@ -1948,12 +1922,85 @@ static u8 mlxsw_sp_cluster_base_port_get(u8 local_port) return local_port - offset; } +static int mlxsw_sp_port_split_create(struct mlxsw_sp *mlxsw_sp, u8 base_port, + u8 module, unsigned int count) +{ + u8 width = MLXSW_PORT_MODULE_MAX_WIDTH / count; + int err, i; + + for (i = 0; i < count; i++) { + err = mlxsw_sp_port_module_map(mlxsw_sp, base_port + i, module, + width, i * width); + if (err) + goto err_port_module_map; + } + + for (i = 0; i < count; i++) { + err = __mlxsw_sp_port_swid_set(mlxsw_sp, base_port + i, 0); + if (err) + goto err_port_swid_set; + } + + for (i = 0; i < count; i++) { + err = mlxsw_sp_port_create(mlxsw_sp, base_port + i, true, + module, width, i * width); + if (err) + goto err_port_create; + } + + return 0; + +err_port_create: + for (i--; i >= 0; i--) + mlxsw_sp_port_remove(mlxsw_sp, base_port + i); + i = count; +err_port_swid_set: + for (i--; i >= 0; i--) + __mlxsw_sp_port_swid_set(mlxsw_sp, base_port + i, + MLXSW_PORT_SWID_DISABLED_PORT); + i = count; +err_port_module_map: + for (i--; i >= 0; i--) + mlxsw_sp_port_module_unmap(mlxsw_sp, base_port + i); + return err; +} + +static void mlxsw_sp_port_unsplit_create(struct mlxsw_sp *mlxsw_sp, + u8 base_port, unsigned int count) +{ + u8 local_port, module, width = MLXSW_PORT_MODULE_MAX_WIDTH; + int i; + + /* Split by four means we need to re-create two ports, otherwise + * only one. + */ + count = count / 2; + + for (i = 0; i < count; i++) { + local_port = base_port + i * 2; + module = mlxsw_sp->port_to_module[local_port]; + + mlxsw_sp_port_module_map(mlxsw_sp, local_port, module, width, + 0); + } + + for (i = 0; i < count; i++) + __mlxsw_sp_port_swid_set(mlxsw_sp, base_port + i * 2, 0); + + for (i = 0; i < count; i++) { + local_port = base_port + i * 2; + module = mlxsw_sp->port_to_module[local_port]; + + mlxsw_sp_port_create(mlxsw_sp, local_port, false, module, + width, 0); + } +} + static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port, unsigned int count) { struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); struct mlxsw_sp_port *mlxsw_sp_port; - u8 width = MLXSW_PORT_MODULE_MAX_WIDTH / count; u8 module, cur_width, base_port; int i; int err; @@ -1965,18 +2012,14 @@ static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port, return -EINVAL; } + module = mlxsw_sp_port->mapping.module; + cur_width = mlxsw_sp_port->mapping.width; + if (count != 2 && count != 4) { netdev_err(mlxsw_sp_port->dev, "Port can only be split into 2 or 4 ports\n"); return -EINVAL; } - err = mlxsw_sp_port_module_info_get(mlxsw_sp, local_port, &module, - &cur_width); - if (err) { - netdev_err(mlxsw_sp_port->dev, "Failed to get port's width\n"); - return err; - } - if (cur_width != MLXSW_PORT_MODULE_MAX_WIDTH) { netdev_err(mlxsw_sp_port->dev, "Port cannot be split further\n"); return -EINVAL; @@ -2001,25 +2044,16 @@ static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port, for (i = 0; i < count; i++) mlxsw_sp_port_remove(mlxsw_sp, base_port + i); - for (i = 0; i < count; i++) { - err = mlxsw_sp_port_create(mlxsw_sp, base_port + i, true, - module, width, i * width); - if (err) { - dev_err(mlxsw_sp->bus_info->dev, "Failed to create split port\n"); - goto err_port_create; - } + err = mlxsw_sp_port_split_create(mlxsw_sp, base_port, module, count); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Failed to create split ports\n"); + goto err_port_split_create; } return 0; -err_port_create: - for (i--; i >= 0; i--) - mlxsw_sp_port_remove(mlxsw_sp, base_port + i); - for (i = 0; i < count / 2; i++) { - module = mlxsw_sp->port_to_module[base_port + i * 2]; - mlxsw_sp_port_create(mlxsw_sp, base_port + i * 2, false, - module, MLXSW_PORT_MODULE_MAX_WIDTH, 0); - } +err_port_split_create: + mlxsw_sp_port_unsplit_create(mlxsw_sp, base_port, count); return err; } @@ -2027,10 +2061,9 @@ static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port) { struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); struct mlxsw_sp_port *mlxsw_sp_port; - u8 module, cur_width, base_port; + u8 cur_width, base_port; unsigned int count; int i; - int err; mlxsw_sp_port = mlxsw_sp->ports[local_port]; if (!mlxsw_sp_port) { @@ -2044,12 +2077,7 @@ static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port) return -EINVAL; } - err = mlxsw_sp_port_module_info_get(mlxsw_sp, local_port, &module, - &cur_width); - if (err) { - netdev_err(mlxsw_sp_port->dev, "Failed to get port's width\n"); - return err; - } + cur_width = mlxsw_sp_port->mapping.width; count = cur_width == 1 ? 4 : 2; base_port = mlxsw_sp_cluster_base_port_get(local_port); @@ -2061,14 +2089,7 @@ static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port) for (i = 0; i < count; i++) mlxsw_sp_port_remove(mlxsw_sp, base_port + i); - for (i = 0; i < count / 2; i++) { - module = mlxsw_sp->port_to_module[base_port + i * 2]; - err = mlxsw_sp_port_create(mlxsw_sp, base_port + i * 2, false, - module, MLXSW_PORT_MODULE_MAX_WIDTH, - 0); - if (err) - dev_err(mlxsw_sp->bus_info->dev, "Failed to reinstantiate port\n"); - } + mlxsw_sp_port_unsplit_create(mlxsw_sp, base_port, count); return 0; } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index e2c022d3e2f3..13b30eaa13d4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -229,6 +229,11 @@ struct mlxsw_sp_port { struct ieee_maxrate *maxrate; struct ieee_pfc *pfc; } dcb; + struct { + u8 module; + u8 width; + u8 lane; + } mapping; /* 802.1Q bridge VLANs */ unsigned long *active_vlans; unsigned long *untagged_vlans; |