Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}