static int mlxsw_sp_sb_cm_write(struct mlxsw_sp *mlxsw_sp, u8 local_port, u8 pg_buff, u32 min_buff, u32 max_buff, bool infi_max, u16 pool_index) { const struct mlxsw_sp_sb_pool_des *des = &mlxsw_sp->sb_vals->pool_dess[pool_index]; char sbcm_pl[MLXSW_REG_SBCM_LEN]; struct mlxsw_sp_sb_cm *cm; int err; mlxsw_reg_sbcm_pack(sbcm_pl, local_port, pg_buff, des->dir, min_buff, max_buff, infi_max, des->pool); err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbcm), sbcm_pl); if (err) return err; if (mlxsw_sp_sb_cm_exists(pg_buff, des->dir)) { if (infi_max) max_buff = mlxsw_sp_bytes_cells(mlxsw_sp, mlxsw_sp->sb->sb_size); cm = mlxsw_sp_sb_cm_get(mlxsw_sp, local_port, pg_buff, des->dir); cm->min_buff = min_buff; cm->max_buff = max_buff; cm->pool_index = pool_index; } return 0; }
int mlxsw_sp_sb_occ_max_clear(struct mlxsw_core *mlxsw_core, unsigned int sb_index) { struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); LIST_HEAD(bulk_list); char *sbsr_pl; unsigned int masked_count; u8 local_port = 0; int i; int err; int err2; sbsr_pl = kmalloc(MLXSW_REG_SBSR_LEN, GFP_KERNEL); if (!sbsr_pl) return -ENOMEM; next_batch: local_port++; masked_count = 0; mlxsw_reg_sbsr_pack(sbsr_pl, true); for (i = 0; i < MLXSW_SP_SB_TC_COUNT; i++) { mlxsw_reg_sbsr_pg_buff_mask_set(sbsr_pl, i, 1); mlxsw_reg_sbsr_tclass_mask_set(sbsr_pl, i, 1); } for (; local_port < MLXSW_PORT_MAX_PORTS; local_port++) { if (!mlxsw_sp->ports[local_port]) continue; mlxsw_reg_sbsr_ingress_port_mask_set(sbsr_pl, local_port, 1); mlxsw_reg_sbsr_egress_port_mask_set(sbsr_pl, local_port, 1); for (i = 0; i < MLXSW_SP_SB_POOL_COUNT; i++) { err = mlxsw_sp_sb_pm_occ_clear(mlxsw_sp, local_port, i, MLXSW_REG_SBXX_DIR_INGRESS, &bulk_list); if (err) goto out; err = mlxsw_sp_sb_pm_occ_clear(mlxsw_sp, local_port, i, MLXSW_REG_SBXX_DIR_EGRESS, &bulk_list); if (err) goto out; } if (++masked_count == MASKED_COUNT_MAX) goto do_query; } do_query: err = mlxsw_reg_trans_query(mlxsw_core, MLXSW_REG(sbsr), sbsr_pl, &bulk_list, NULL, 0); if (err) goto out; if (local_port < MLXSW_PORT_MAX_PORTS) goto next_batch; out: err2 = mlxsw_reg_trans_bulk_wait(&bulk_list); if (!err) err = err2; kfree(sbsr_pl); return err; }
static void __mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp) { char rgcr_pl[MLXSW_REG_RGCR_LEN]; mlxsw_reg_rgcr_pack(rgcr_pl, false); mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl); }
static int mlxsw_sp_sb_mms_init(struct mlxsw_sp *mlxsw_sp) { char sbmm_pl[MLXSW_REG_SBMM_LEN]; int i; int err; for (i = 0; i < mlxsw_sp->sb_vals->mms_count; i++) { const struct mlxsw_sp_sb_pool_des *des; const struct mlxsw_sp_sb_mm *mc; u32 min_buff; mc = &mlxsw_sp->sb_vals->mms[i]; des = &mlxsw_sp->sb_vals->pool_dess[mc->pool_index]; /* All pools used by sb_mm's are initialized using dynamic * thresholds, therefore 'max_buff' isn't specified in cells. */ min_buff = mlxsw_sp_bytes_cells(mlxsw_sp, mc->min_buff); mlxsw_reg_sbmm_pack(sbmm_pl, i, min_buff, mc->max_buff, des->pool); err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbmm), sbmm_pl); if (err) return err; } return 0; }
static int __mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp) { char rgcr_pl[MLXSW_REG_RGCR_LEN]; mlxsw_reg_rgcr_pack(rgcr_pl, true); mlxsw_reg_rgcr_max_router_interfaces_set(rgcr_pl, MLXSW_SP_RIF_MAX); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl); }
static int mlxsw_sx_port_swid_set(struct mlxsw_sx_port *mlxsw_sx_port, u8 swid) { struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; char pspa_pl[MLXSW_REG_PSPA_LEN]; mlxsw_reg_pspa_pack(pspa_pl, swid, mlxsw_sx_port->local_port); return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(pspa), pspa_pl); }
static int mlxsw_sx_port_system_port_mapping_set(struct mlxsw_sx_port *mlxsw_sx_port) { struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; char sspr_pl[MLXSW_REG_SSPR_LEN]; mlxsw_reg_sspr_pack(sspr_pl, mlxsw_sx_port->local_port); return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sspr), sspr_pl); }
static int mlxsw_sp_sb_pm_occ_clear(struct mlxsw_sp *mlxsw_sp, u8 local_port, u8 pool, enum mlxsw_reg_sbxx_dir dir, struct list_head *bulk_list) { char sbpm_pl[MLXSW_REG_SBPM_LEN]; mlxsw_reg_sbpm_pack(sbpm_pl, local_port, pool, dir, true, 0, 0); return mlxsw_reg_trans_query(mlxsw_sp->core, MLXSW_REG(sbpm), sbpm_pl, bulk_list, NULL, 0); }
static int mlxsw_sib_port_speed_set(struct mlxsw_sib_port *mlxsw_sib_port, u16 speed, u16 width) { struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib; char ptys_pl[MLXSW_REG_PTYS_LEN]; mlxsw_reg_ptys_ib_pack(ptys_pl, mlxsw_sib_port->local_port, speed, width); return mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(ptys), ptys_pl); }
static int mlxsw_sx_port_admin_status_set(struct mlxsw_sx_port *mlxsw_sx_port, bool is_up) { struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; char paos_pl[MLXSW_REG_PAOS_LEN]; mlxsw_reg_paos_pack(paos_pl, mlxsw_sx_port->local_port, is_up ? MLXSW_PORT_ADMIN_STATUS_UP : MLXSW_PORT_ADMIN_STATUS_DOWN); return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(paos), paos_pl); }
static int mlxsw_sp_port_pb_prio_init(struct mlxsw_sp_port *mlxsw_sp_port) { char pptb_pl[MLXSW_REG_PPTB_LEN]; int i; mlxsw_reg_pptb_pack(pptb_pl, mlxsw_sp_port->local_port); for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) mlxsw_reg_pptb_prio_to_buff_pack(pptb_pl, i, 0); return mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core, MLXSW_REG(pptb), pptb_pl); }
static int mlxsw_sib_port_mtu_set(struct mlxsw_sib_port *mlxsw_sib_port, u16 mtu) { struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib; char pmtu_pl[MLXSW_REG_PMTU_LEN]; int max_mtu; int err; mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sib_port->local_port, 0); err = mlxsw_reg_query(mlxsw_sib->core, MLXSW_REG(pmtu), pmtu_pl); if (err) return err; max_mtu = mlxsw_reg_pmtu_max_mtu_get(pmtu_pl); if (mtu > max_mtu) return -EINVAL; mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sib_port->local_port, mtu); return mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(pmtu), pmtu_pl); }
static int mlxsw_sib_port_set(struct mlxsw_sib_port *mlxsw_sib_port, u8 port) { struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib; char plib_pl[MLXSW_REG_PLIB_LEN] = {0}; int err; mlxsw_reg_plib_local_port_set(plib_pl, mlxsw_sib_port->local_port); mlxsw_reg_plib_ib_port_set(plib_pl, port); err = mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(plib), plib_pl); return err; }
static int mlxsw_sp_sb_pm_occ_clear(struct mlxsw_sp *mlxsw_sp, u8 local_port, u16 pool_index, struct list_head *bulk_list) { const struct mlxsw_sp_sb_pool_des *des = &mlxsw_sp->sb_vals->pool_dess[pool_index]; char sbpm_pl[MLXSW_REG_SBPM_LEN]; mlxsw_reg_sbpm_pack(sbpm_pl, local_port, des->pool, des->dir, true, 0, 0); return mlxsw_reg_trans_query(mlxsw_sp->core, MLXSW_REG(sbpm), sbpm_pl, bulk_list, NULL, 0); }
static int mlxsw_sp2_mr_tcam_bind_group(struct mlxsw_sp *mlxsw_sp, enum mlxsw_reg_pemrbt_protocol protocol, struct mlxsw_sp_acl_ruleset *ruleset) { char pemrbt_pl[MLXSW_REG_PEMRBT_LEN]; u16 group_id; group_id = mlxsw_sp_acl_ruleset_group_id(ruleset); mlxsw_reg_pemrbt_pack(pemrbt_pl, protocol, group_id); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pemrbt), pemrbt_pl); }
static void mlxsw_sp_acl_ctcam_region_move(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_region *region, u16 src_offset, u16 dst_offset, u16 size) { char prcr_pl[MLXSW_REG_PRCR_LEN]; mlxsw_reg_prcr_pack(prcr_pl, MLXSW_REG_PRCR_OP_MOVE, region->tcam_region_info, src_offset, region->tcam_region_info, dst_offset, size); mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(prcr), prcr_pl); }
static int mlxsw_sp_acl_ctcam_region_resize(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_region *region, u16 new_size) { char ptar_pl[MLXSW_REG_PTAR_LEN]; mlxsw_reg_ptar_pack(ptar_pl, MLXSW_REG_PTAR_OP_RESIZE, region->key_type, new_size, region->id, region->tcam_region_info); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptar), ptar_pl); }
static int mlxsw_sib_basic_trap_groups_set(struct mlxsw_core *mlxsw_core) { char htgt_pl[MLXSW_REG_HTGT_LEN]; mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD, MLXSW_REG_HTGT_INVALID_POLICER, MLXSW_REG_HTGT_DEFAULT_PRIORITY, MLXSW_REG_HTGT_DEFAULT_TC); mlxsw_reg_htgt_swid_set(htgt_pl, MLXSW_PORT_SWID_ALL_SWIDS); mlxsw_reg_htgt_local_path_rdq_set(htgt_pl, MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SIB_EMAD); return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl); }
static void mlxsw_sp_acl_ctcam_region_entry_remove(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_ctcam_region *cregion, struct mlxsw_sp_acl_ctcam_entry *centry) { char ptce2_pl[MLXSW_REG_PTCE2_LEN]; mlxsw_reg_ptce2_pack(ptce2_pl, false, MLXSW_REG_PTCE2_OP_WRITE_WRITE, cregion->region->tcam_region_info, centry->parman_item.index, 0); mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl); cregion->ops->entry_remove(cregion, centry); }
static int mlxsw_sp_sb_pm_occ_query(struct mlxsw_sp *mlxsw_sp, u8 local_port, u8 pool, enum mlxsw_reg_sbxx_dir dir, struct list_head *bulk_list) { char sbpm_pl[MLXSW_REG_SBPM_LEN]; struct mlxsw_sp_sb_pm *pm; pm = mlxsw_sp_sb_pm_get(mlxsw_sp, local_port, pool, dir); mlxsw_reg_sbpm_pack(sbpm_pl, local_port, pool, dir, false, 0, 0); return mlxsw_reg_trans_query(mlxsw_sp->core, MLXSW_REG(sbpm), sbpm_pl, bulk_list, mlxsw_sp_sb_pm_occ_query_cb, (unsigned long) pm); }
static void mlxsw_sx_port_get_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) { struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev); struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; char ppcnt_pl[MLXSW_REG_PPCNT_LEN]; int i; int err; mlxsw_reg_ppcnt_pack(ppcnt_pl, mlxsw_sx_port->local_port); err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(ppcnt), ppcnt_pl); for (i = 0; i < MLXSW_SX_PORT_HW_STATS_LEN; i++) data[i] = !err ? mlxsw_sx_port_hw_stats[i].getter(ppcnt_pl) : 0; }
static int mlxsw_sx_port_module_check(struct mlxsw_sx_port *mlxsw_sx_port, bool *p_usable) { struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; char pmlp_pl[MLXSW_REG_PMLP_LEN]; int err; mlxsw_reg_pmlp_pack(pmlp_pl, mlxsw_sx_port->local_port); err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(pmlp), pmlp_pl); if (err) return err; *p_usable = mlxsw_reg_pmlp_width_get(pmlp_pl) ? true : false; return 0; }
static int mlxsw_sib_port_module_info_get(struct mlxsw_sib *mlxsw_sib, u8 local_port, u8 *p_module, u8 *p_width) { char pmlp_pl[MLXSW_REG_PMLP_LEN]; int err; mlxsw_reg_pmlp_pack(pmlp_pl, local_port); err = mlxsw_reg_query(mlxsw_sib->core, MLXSW_REG(pmlp), pmlp_pl); if (err) return err; *p_module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0); *p_width = mlxsw_reg_pmlp_width_get(pmlp_pl); return 0; }
static int mlxsw_sp_sb_pm_occ_query(struct mlxsw_sp *mlxsw_sp, u8 local_port, u16 pool_index, struct list_head *bulk_list) { const struct mlxsw_sp_sb_pool_des *des = &mlxsw_sp->sb_vals->pool_dess[pool_index]; char sbpm_pl[MLXSW_REG_SBPM_LEN]; struct mlxsw_sp_sb_pm *pm; pm = mlxsw_sp_sb_pm_get(mlxsw_sp, local_port, pool_index); mlxsw_reg_sbpm_pack(sbpm_pl, local_port, des->pool, des->dir, false, 0, 0); return mlxsw_reg_trans_query(mlxsw_sp->core, MLXSW_REG(sbpm), sbpm_pl, bulk_list, mlxsw_sp_sb_pm_occ_query_cb, (unsigned long) pm); }
static int mlxsw_sp2_kvdl_rec_del(struct mlxsw_sp *mlxsw_sp, u8 res_type, u16 size, u32 kvdl_index) { char *iedr_pl; int err; iedr_pl = kmalloc(MLXSW_REG_IEDR_LEN, GFP_KERNEL); if (!iedr_pl) return -ENOMEM; mlxsw_reg_iedr_pack(iedr_pl); mlxsw_reg_iedr_rec_pack(iedr_pl, 0, res_type, size, kvdl_index); err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(iedr), iedr_pl); kfree(iedr_pl); return err; }
static int mlxsw_sx_port_oper_status_get(struct mlxsw_sx_port *mlxsw_sx_port, bool *p_is_up) { struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; char paos_pl[MLXSW_REG_PAOS_LEN]; u8 oper_status; int err; mlxsw_reg_paos_pack(paos_pl, mlxsw_sx_port->local_port, 0); err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(paos), paos_pl); if (err) return err; oper_status = mlxsw_reg_paos_oper_status_get(paos_pl); *p_is_up = oper_status == MLXSW_PORT_ADMIN_STATUS_UP ? true : false; return 0; }
static int mlxsw_sp_port_pb_init(struct mlxsw_sp_port *mlxsw_sp_port) { char pbmc_pl[MLXSW_REG_PBMC_LEN]; int i; mlxsw_reg_pbmc_pack(pbmc_pl, mlxsw_sp_port->local_port, 0xffff, 0xffff / 2); for (i = 0; i < MLXSW_SP_PBS_LEN; i++) { if (i == MLXSW_SP_PB_UNUSED) continue; mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, i, mlxsw_sp_pbs[i]); } mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, MLXSW_REG_PBMC_PORT_SHARED_BUF_IDX, 0); return mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core, MLXSW_REG(pbmc), pbmc_pl); }
static int mlxsw_sp_sb_mms_init(struct mlxsw_sp *mlxsw_sp) { char sbmm_pl[MLXSW_REG_SBMM_LEN]; int i; int err; for (i = 0; i < MLXSW_SP_SB_MMS_LEN; i++) { const struct mlxsw_sp_sb_mm *mc; mc = &mlxsw_sp_sb_mms[i]; mlxsw_reg_sbmm_pack(sbmm_pl, i, mc->min_buff, mc->max_buff, mc->pool); err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbmm), sbmm_pl); if (err) return err; } return 0; }
static int mlxsw_sp_sb_pr_write(struct mlxsw_sp *mlxsw_sp, u8 pool, enum mlxsw_reg_sbxx_dir dir, enum mlxsw_reg_sbpr_mode mode, u32 size) { char sbpr_pl[MLXSW_REG_SBPR_LEN]; struct mlxsw_sp_sb_pr *pr; int err; mlxsw_reg_sbpr_pack(sbpr_pl, pool, dir, mode, size); err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbpr), sbpr_pl); if (err) return err; pr = mlxsw_sp_sb_pr_get(mlxsw_sp, pool, dir); pr->mode = mode; pr->size = size; return 0; }
static int mlxsw_sp_acl_ctcam_region_entry_action_replace(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_ctcam_region *cregion, struct mlxsw_sp_acl_ctcam_entry *centry, struct mlxsw_afa_block *afa_block, unsigned int priority) { char ptce2_pl[MLXSW_REG_PTCE2_LEN]; char *act_set; mlxsw_reg_ptce2_pack(ptce2_pl, true, MLXSW_REG_PTCE2_OP_WRITE_UPDATE, cregion->region->tcam_region_info, centry->parman_item.index, priority); act_set = mlxsw_afa_block_first_set(afa_block); mlxsw_reg_ptce2_flex_action_set_memcpy_to(ptce2_pl, act_set); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl); }