Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[linux-2.6-microblaze.git] / drivers / net / ethernet / mellanox / mlxsw / spectrum.c
index b65e274..7ee6d74 100644 (file)
@@ -1702,6 +1702,18 @@ static int mlxsw_sp_set_features(struct net_device *dev,
                                       mlxsw_sp_feature_hw_tc);
 }
 
+static int mlxsw_sp_port_get_port_parent_id(struct net_device *dev,
+                                           struct netdev_phys_item_id *ppid)
+{
+       struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
+       struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+
+       ppid->id_len = sizeof(mlxsw_sp->base_mac);
+       memcpy(&ppid->id, &mlxsw_sp->base_mac, ppid->id_len);
+
+       return 0;
+}
+
 static const struct net_device_ops mlxsw_sp_port_netdev_ops = {
        .ndo_open               = mlxsw_sp_port_open,
        .ndo_stop               = mlxsw_sp_port_stop,
@@ -1717,6 +1729,7 @@ static const struct net_device_ops mlxsw_sp_port_netdev_ops = {
        .ndo_vlan_rx_kill_vid   = mlxsw_sp_port_kill_vid,
        .ndo_get_phys_port_name = mlxsw_sp_port_get_phys_port_name,
        .ndo_set_features       = mlxsw_sp_set_features,
+       .ndo_get_port_parent_id = mlxsw_sp_port_get_port_parent_id,
 };
 
 static void mlxsw_sp_port_get_drvinfo(struct net_device *dev,
@@ -2712,23 +2725,23 @@ static int mlxsw_sp_query_module_eeprom(struct mlxsw_sp_port *mlxsw_sp_port,
                                        unsigned int *p_read_size)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
-       char eeprom_tmp[MLXSW_SP_REG_MCIA_EEPROM_SIZE];
+       char eeprom_tmp[MLXSW_REG_MCIA_EEPROM_SIZE];
        char mcia_pl[MLXSW_REG_MCIA_LEN];
        u16 i2c_addr;
        int status;
        int err;
 
-       size = min_t(u16, size, MLXSW_SP_REG_MCIA_EEPROM_SIZE);
+       size = min_t(u16, size, MLXSW_REG_MCIA_EEPROM_SIZE);
 
-       if (offset < MLXSW_SP_EEPROM_PAGE_LENGTH &&
-           offset + size > MLXSW_SP_EEPROM_PAGE_LENGTH)
+       if (offset < MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH &&
+           offset + size > MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH)
                /* Cross pages read, read until offset 256 in low page */
-               size = MLXSW_SP_EEPROM_PAGE_LENGTH - offset;
+               size = MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH - offset;
 
-       i2c_addr = MLXSW_SP_I2C_ADDR_LOW;
-       if (offset >= MLXSW_SP_EEPROM_PAGE_LENGTH) {
-               i2c_addr = MLXSW_SP_I2C_ADDR_HIGH;
-               offset -= MLXSW_SP_EEPROM_PAGE_LENGTH;
+       i2c_addr = MLXSW_REG_MCIA_I2C_ADDR_LOW;
+       if (offset >= MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH) {
+               i2c_addr = MLXSW_REG_MCIA_I2C_ADDR_HIGH;
+               offset -= MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH;
        }
 
        mlxsw_reg_mcia_pack(mcia_pl, mlxsw_sp_port->mapping.module,
@@ -2749,55 +2762,37 @@ static int mlxsw_sp_query_module_eeprom(struct mlxsw_sp_port *mlxsw_sp_port,
        return 0;
 }
 
-enum mlxsw_sp_eeprom_module_info_rev_id {
-       MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_UNSPC      = 0x00,
-       MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_8436       = 0x01,
-       MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_8636       = 0x03,
-};
-
-enum mlxsw_sp_eeprom_module_info_id {
-       MLXSW_SP_EEPROM_MODULE_INFO_ID_SFP              = 0x03,
-       MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP             = 0x0C,
-       MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP_PLUS        = 0x0D,
-       MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP28           = 0x11,
-};
-
-enum mlxsw_sp_eeprom_module_info {
-       MLXSW_SP_EEPROM_MODULE_INFO_ID,
-       MLXSW_SP_EEPROM_MODULE_INFO_REV_ID,
-       MLXSW_SP_EEPROM_MODULE_INFO_SIZE,
-};
-
 static int mlxsw_sp_get_module_info(struct net_device *netdev,
                                    struct ethtool_modinfo *modinfo)
 {
        struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev);
-       u8 module_info[MLXSW_SP_EEPROM_MODULE_INFO_SIZE];
+       u8 module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE];
+       u16 offset = MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE;
        u8 module_rev_id, module_id;
        unsigned int read_size;
        int err;
 
-       err = mlxsw_sp_query_module_eeprom(mlxsw_sp_port, 0,
-                                          MLXSW_SP_EEPROM_MODULE_INFO_SIZE,
+       err = mlxsw_sp_query_module_eeprom(mlxsw_sp_port, 0, offset,
                                           module_info, &read_size);
        if (err)
                return err;
 
-       if (read_size < MLXSW_SP_EEPROM_MODULE_INFO_SIZE)
+       if (read_size < offset)
                return -EIO;
 
-       module_rev_id = module_info[MLXSW_SP_EEPROM_MODULE_INFO_REV_ID];
-       module_id = module_info[MLXSW_SP_EEPROM_MODULE_INFO_ID];
+       module_rev_id = module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID];
+       module_id = module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID];
 
        switch (module_id) {
-       case MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP:
+       case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP:
                modinfo->type       = ETH_MODULE_SFF_8436;
                modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
                break;
-       case MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP_PLUS:
-       case MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP28:
-               if (module_id  == MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP28 ||
-                   module_rev_id >= MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_8636) {
+       case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_PLUS: /* fall-through */
+       case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28:
+               if (module_id == MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28 ||
+                   module_rev_id >=
+                   MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID_8636) {
                        modinfo->type       = ETH_MODULE_SFF_8636;
                        modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN;
                } else {
@@ -2805,7 +2800,7 @@ static int mlxsw_sp_get_module_info(struct net_device *netdev,
                        modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
                }
                break;
-       case MLXSW_SP_EEPROM_MODULE_INFO_ID_SFP:
+       case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_SFP:
                modinfo->type       = ETH_MODULE_SFF_8472;
                modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
                break;
@@ -3746,8 +3741,8 @@ static int mlxsw_sp_cpu_policers_set(struct mlxsw_core *mlxsw_core)
                        burst_size = 7;
                        break;
                case MLXSW_REG_HTGT_TRAP_GROUP_SP_IP2ME:
-                       rate = 4 * 1024;
-                       burst_size = 4;
+                       rate = 1024;
+                       burst_size = 7;
                        break;
                default:
                        continue;
@@ -4096,6 +4091,7 @@ static int mlxsw_sp1_init(struct mlxsw_core *mlxsw_core,
        mlxsw_sp->acl_tcam_ops = &mlxsw_sp1_acl_tcam_ops;
        mlxsw_sp->nve_ops_arr = mlxsw_sp1_nve_ops_arr;
        mlxsw_sp->mac_mask = mlxsw_sp1_mac_mask;
+       mlxsw_sp->rif_ops_arr = mlxsw_sp1_rif_ops_arr;
 
        return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info);
 }
@@ -4112,6 +4108,7 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core,
        mlxsw_sp->acl_tcam_ops = &mlxsw_sp2_acl_tcam_ops;
        mlxsw_sp->nve_ops_arr = mlxsw_sp2_nve_ops_arr;
        mlxsw_sp->mac_mask = mlxsw_sp2_mac_mask;
+       mlxsw_sp->rif_ops_arr = mlxsw_sp2_rif_ops_arr;
 
        return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info);
 }
@@ -4400,6 +4397,71 @@ static void mlxsw_sp_params_unregister(struct mlxsw_core *mlxsw_core)
                                  ARRAY_SIZE(mlxsw_sp_devlink_params));
 }
 
+static int
+mlxsw_sp_params_acl_region_rehash_intrvl_get(struct devlink *devlink, u32 id,
+                                            struct devlink_param_gset_ctx *ctx)
+{
+       struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
+       struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
+
+       ctx->val.vu32 = mlxsw_sp_acl_region_rehash_intrvl_get(mlxsw_sp);
+       return 0;
+}
+
+static int
+mlxsw_sp_params_acl_region_rehash_intrvl_set(struct devlink *devlink, u32 id,
+                                            struct devlink_param_gset_ctx *ctx)
+{
+       struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
+       struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
+
+       return mlxsw_sp_acl_region_rehash_intrvl_set(mlxsw_sp, ctx->val.vu32);
+}
+
+static const struct devlink_param mlxsw_sp2_devlink_params[] = {
+       DEVLINK_PARAM_DRIVER(MLXSW_DEVLINK_PARAM_ID_ACL_REGION_REHASH_INTERVAL,
+                            "acl_region_rehash_interval",
+                            DEVLINK_PARAM_TYPE_U32,
+                            BIT(DEVLINK_PARAM_CMODE_RUNTIME),
+                            mlxsw_sp_params_acl_region_rehash_intrvl_get,
+                            mlxsw_sp_params_acl_region_rehash_intrvl_set,
+                            NULL),
+};
+
+static int mlxsw_sp2_params_register(struct mlxsw_core *mlxsw_core)
+{
+       struct devlink *devlink = priv_to_devlink(mlxsw_core);
+       union devlink_param_value value;
+       int err;
+
+       err = mlxsw_sp_params_register(mlxsw_core);
+       if (err)
+               return err;
+
+       err = devlink_params_register(devlink, mlxsw_sp2_devlink_params,
+                                     ARRAY_SIZE(mlxsw_sp2_devlink_params));
+       if (err)
+               goto err_devlink_params_register;
+
+       value.vu32 = 0;
+       devlink_param_driverinit_value_set(devlink,
+                                          MLXSW_DEVLINK_PARAM_ID_ACL_REGION_REHASH_INTERVAL,
+                                          value);
+       return 0;
+
+err_devlink_params_register:
+       mlxsw_sp_params_unregister(mlxsw_core);
+       return err;
+}
+
+static void mlxsw_sp2_params_unregister(struct mlxsw_core *mlxsw_core)
+{
+       devlink_params_unregister(priv_to_devlink(mlxsw_core),
+                                 mlxsw_sp2_devlink_params,
+                                 ARRAY_SIZE(mlxsw_sp2_devlink_params));
+       mlxsw_sp_params_unregister(mlxsw_core);
+}
+
 static struct mlxsw_driver mlxsw_sp1_driver = {
        .kind                           = mlxsw_sp1_driver_name,
        .priv_size                      = sizeof(struct mlxsw_sp),
@@ -4448,8 +4510,8 @@ static struct mlxsw_driver mlxsw_sp2_driver = {
        .sb_occ_tc_port_bind_get        = mlxsw_sp_sb_occ_tc_port_bind_get,
        .txhdr_construct                = mlxsw_sp_txhdr_construct,
        .resources_register             = mlxsw_sp2_resources_register,
-       .params_register                = mlxsw_sp_params_register,
-       .params_unregister              = mlxsw_sp_params_unregister,
+       .params_register                = mlxsw_sp2_params_register,
+       .params_unregister              = mlxsw_sp2_params_unregister,
        .txhdr_len                      = MLXSW_TXHDR_LEN,
        .profile                        = &mlxsw_sp2_config_profile,
        .res_query_enabled              = true,
@@ -4693,9 +4755,6 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port,
        err = mlxsw_sp_lag_col_port_add(mlxsw_sp_port, lag_id, port_index);
        if (err)
                goto err_col_port_add;
-       err = mlxsw_sp_lag_col_port_enable(mlxsw_sp_port, lag_id);
-       if (err)
-               goto err_col_port_enable;
 
        mlxsw_core_lag_mapping_set(mlxsw_sp->core, lag_id, port_index,
                                   mlxsw_sp_port->local_port);
@@ -4709,8 +4768,6 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port,
 
        return 0;
 
-err_col_port_enable:
-       mlxsw_sp_lag_col_port_remove(mlxsw_sp_port, lag_id);
 err_col_port_add:
        if (!lag->ref_count)
                mlxsw_sp_lag_destroy(mlxsw_sp, lag_id);
@@ -4729,7 +4786,6 @@ static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port,
        lag = mlxsw_sp_lag_get(mlxsw_sp, lag_id);
        WARN_ON(lag->ref_count == 0);
 
-       mlxsw_sp_lag_col_port_disable(mlxsw_sp_port, lag_id);
        mlxsw_sp_lag_col_port_remove(mlxsw_sp_port, lag_id);
 
        /* Any VLANs configured on the port are no longer valid */
@@ -4774,21 +4830,56 @@ static int mlxsw_sp_lag_dist_port_remove(struct mlxsw_sp_port *mlxsw_sp_port,
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sldr), sldr_pl);
 }
 
-static int mlxsw_sp_port_lag_tx_en_set(struct mlxsw_sp_port *mlxsw_sp_port,
-                                      bool lag_tx_enabled)
+static int
+mlxsw_sp_port_lag_col_dist_enable(struct mlxsw_sp_port *mlxsw_sp_port)
 {
-       if (lag_tx_enabled)
-               return mlxsw_sp_lag_dist_port_add(mlxsw_sp_port,
-                                                 mlxsw_sp_port->lag_id);
-       else
-               return mlxsw_sp_lag_dist_port_remove(mlxsw_sp_port,
-                                                    mlxsw_sp_port->lag_id);
+       int err;
+
+       err = mlxsw_sp_lag_col_port_enable(mlxsw_sp_port,
+                                          mlxsw_sp_port->lag_id);
+       if (err)
+               return err;
+
+       err = mlxsw_sp_lag_dist_port_add(mlxsw_sp_port, mlxsw_sp_port->lag_id);
+       if (err)
+               goto err_dist_port_add;
+
+       return 0;
+
+err_dist_port_add:
+       mlxsw_sp_lag_col_port_disable(mlxsw_sp_port, mlxsw_sp_port->lag_id);
+       return err;
+}
+
+static int
+mlxsw_sp_port_lag_col_dist_disable(struct mlxsw_sp_port *mlxsw_sp_port)
+{
+       int err;
+
+       err = mlxsw_sp_lag_dist_port_remove(mlxsw_sp_port,
+                                           mlxsw_sp_port->lag_id);
+       if (err)
+               return err;
+
+       err = mlxsw_sp_lag_col_port_disable(mlxsw_sp_port,
+                                           mlxsw_sp_port->lag_id);
+       if (err)
+               goto err_col_port_disable;
+
+       return 0;
+
+err_col_port_disable:
+       mlxsw_sp_lag_dist_port_add(mlxsw_sp_port, mlxsw_sp_port->lag_id);
+       return err;
 }
 
 static int mlxsw_sp_port_lag_changed(struct mlxsw_sp_port *mlxsw_sp_port,
                                     struct netdev_lag_lower_state_info *info)
 {
-       return mlxsw_sp_port_lag_tx_en_set(mlxsw_sp_port, info->tx_enabled);
+       if (info->tx_enabled)
+               return mlxsw_sp_port_lag_col_dist_enable(mlxsw_sp_port);
+       else
+               return mlxsw_sp_port_lag_col_dist_disable(mlxsw_sp_port);
 }
 
 static int mlxsw_sp_port_stp_set(struct mlxsw_sp_port *mlxsw_sp_port,
@@ -5011,8 +5102,7 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev,
                                err = mlxsw_sp_port_lag_join(mlxsw_sp_port,
                                                             upper_dev);
                        } else {
-                               mlxsw_sp_port_lag_tx_en_set(mlxsw_sp_port,
-                                                           false);
+                               mlxsw_sp_port_lag_col_dist_disable(mlxsw_sp_port);
                                mlxsw_sp_port_lag_leave(mlxsw_sp_port,
                                                        upper_dev);
                        }