Exemplo n.º 1
0
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;
}
Exemplo n.º 2
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;
}
Exemplo 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;
}