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_free(struct rhea_channel *channel, unsigned base) { int rc = 0; unsigned tcam_offset; struct rhea_pport *pport; struct rhea_channel_resource_map *tcam_base; if (NULL == channel) return -EINVAL; pport = _rhea_pport_get(channel->pport_nr); if (NULL == pport) { rhea_error("Invalid pport number"); return -EINVAL; } if (NULL == channel->tcam) { rhea_error("TCAM was not allocated"); return -EINVAL; } if (NULL == channel->qpn) { rhea_error("QPN was not allocated"); return -EINVAL; } tcam_base = _rhea_channel_resource_map_get(channel->tcam, base); if (NULL == tcam_base) { rhea_error("Did not find this tcam base"); return -EINVAL; } rhea_info("Free %u TCAM slots from base: %u and channel: " "%u of pport: %u", tcam_base->alloced, base, channel->type, channel->pport_nr + 1); /* make sure that the tcam is reset */ for (tcam_offset = 0; tcam_offset < tcam_base->alloced; ++tcam_offset) { unsigned int qpn_offset = 0; unsigned int pattern = 0; unsigned int mask = 0; /* get current tcam configuration */ rc = _rhea_tcam_register_get(channel, base, tcam_offset, &qpn_offset, &pattern, &mask); if (rc) { rhea_error("Was not able to obtain tcam information"); return rc; } /* reset the registers */ rc = _rhea_tcam_set(channel, base, tcam_offset, qpn_offset, 0, 0); if (rc) { rhea_error("Was not able to reset tcam!"); return rc; } /* disable this tcam */ rc = _rhea_tcam_register_set_status(channel, base, tcam_offset, 0); if (rc) { rhea_error("Was not able to disable tcam"); return rc; } } /* mark block as free */ rc = _rhea_channel_resource_free(&pport->tcam, channel->tcam, base); if (rc) { rhea_error("Was not able to free resources"); return rc; } return rc; }
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; }