static void _rhea_tcam_channel_register_set(struct rhea_channel *channel, unsigned tcam_bits) { u64 reg = 0x0ULL; struct rhea_pport *pport; struct rhea_pport_bpfc *bpfc; if (NULL == channel) return; /* always get pport from channel */ pport = _rhea_pport_get(channel->pport_nr); if (NULL == pport) { rhea_error("Invalid pport number"); return; } bpfc = &pport->pport_regs->bpfc; /* reset number of used hash bits for all channels */ switch (channel->type) { case HEA_UC_PORT: reg = in_be64(&bpfc->p_rcu); reg = hea_set_u64_bits(reg, tcam_bits, 9, 11); out_be64(&bpfc->p_rcu, reg); break; case HEA_MC_PORT: reg = in_be64(&bpfc->p_rcm); reg = hea_set_u64_bits(reg, tcam_bits, 9, 11); out_be64(&bpfc->p_rcm, reg); break; case HEA_BC_PORT: reg = in_be64(&bpfc->p_rcb); reg = hea_set_u64_bits(reg, tcam_bits, 9, 11); out_be64(&bpfc->p_rcb, reg); break; default: if (is_hea_lport(channel->type)) { int lport_index = hea_lport_index_get(channel->type); reg = in_be64(&bpfc->pl_rc[lport_index]); reg = hea_set_u64_bits(reg, tcam_bits, 9, 11); out_be64(&bpfc->pl_rc[lport_index], reg); } break; } return; }
struct rhea_hasher *rhea_hasher_alloc(struct rhea_channel *channel) { struct rhea_pport *pport; struct rhea_hasher *hasher; if (NULL == channel) return NULL; if (!is_hea_lport(channel->type) && HEA_DEFAULT_CHANNEL_SHARE == channel->channel_cfg.dc.channel_usuage) { rhea_warning("Shared channel is not allowed to hasher"); return NULL; } /* always get pport from channel */ pport = _rhea_pport_get(channel->pport_nr); if (NULL == pport) { rhea_error("Invalid pport number"); return NULL; } spin_lock(&pport->lock); if (pport->hasher) { spin_unlock(&pport->lock); rhea_error("Hasher is already allocated"); return NULL; } pport->hasher = rhea_align_alloc(sizeof(*pport->hasher), 8, GFP_KERNEL); if (NULL == pport->hasher) { spin_unlock(&pport->lock); rhea_error("Was not able to allocate hasher"); return NULL; } /* there can only be one --> identifies channel which is using it! */ pport->hasher->id = channel->id; /* pass id back to caller */ hasher = pport->hasher; /* mark that this channel is using the hasher */ channel->hasher_used = 1; rhea_info("Allocated HASHER for channel: %u of pport: %u", channel->type, channel->pport_nr + 1); spin_unlock(&pport->lock); return hasher; }
int rhea_tcam_alloc(struct rhea_channel *channel, struct hea_tcam_cfg *tcam_cfg, unsigned *slot_base) { int rc = 0; unsigned slot_decr; struct rhea_pport *pport; if (NULL == channel || NULL == slot_base || NULL == tcam_cfg) return -EINVAL; if (NULL == channel->qpn) { rhea_error("QPN has not been initialised"); return -EINVAL; } if (NULL == channel->tcam) { /* make sure it can be used by somebody */ rc = _rhea_channel_map_init(&channel->tcam); if (rc) { rhea_error("Was not able to free TCAM map"); return rc; } } if (channel->qpn->alloced < tcam_cfg->slot_count) { rhea_error("Number of requested TCAM slots exceeds " "allocated QPN slots!"); return -EINVAL; } slot_decr = tcam_cfg->slot_count; if (!is_hea_lport(channel->type) && HEA_DEFAULT_CHANNEL_SHARE == channel->channel_cfg.dc.channel_usuage) { rhea_info("Shared channel is not allowed to allocate " "TCAM slots"); return -EINVAL; } /* always get pport from channel */ pport = _rhea_pport_get(channel->pport_nr); if (NULL == pport) { rhea_error("Invalid pport number"); return -EINVAL; } if (pport->hasher) { rhea_error("Hasher is enabled for this port"); return -EINVAL; } if (ARRAY_SIZE(pport->pport_regs->bpfc.pg_tcampr) < tcam_cfg->slot_count) { rhea_error("Number of requested slots is too high!"); return -EINVAL; } spin_lock(&pport->lock); if (0 == slot_decr) { /* allocate the whole QPN array */ slot_decr = pport->tcam.alloced_max; } rc = _rhea_channel_resource_alloc(&pport->tcam, channel->tcam, slot_decr, slot_base); if (rc) { spin_unlock(&pport->lock); rhea_error("Error when allocating resource for channel"); return rc; } rhea_info("Allocated %u TCAM slots from base: %u and channel: " "%u of pport: %u", channel->tcam->alloced, *slot_base, channel->type, channel->pport_nr + 1); spin_unlock(&pport->lock); return rc; }