static void _rhea_hasher_channel_register_set(struct rhea_channel *channel, unsigned hash_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; } if (NULL == channel->qpn) { rhea_error("Only the main channel ID can set the hasher"); 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, hash_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, hash_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, hash_bits, 9, 11); out_be64(&bpfc->p_rcb, reg); break; default: if (0 <= channel->type - HEA_LPORT_0) { int lport_index = hea_lport_index_get(channel->type); reg = in_be64(&bpfc->pl_rc[lport_index]); reg = hea_set_u64_bits(reg, hash_bits, 9, 11); out_be64(&bpfc->pl_rc[lport_index], reg); } break; } }
static int _rhea_tcam_register_set_status(struct rhea_channel *channel, unsigned tcam_base, unsigned tcam_offset, unsigned enable) { int rc = 0; unsigned tcam_index; struct rhea_pport *pport; u64 reg_pattern; 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->qpn || NULL == channel->tcam) { rhea_error("TCAM or QPN are not initialised"); return -EINVAL; } /* get the real index in the TCAM array */ rc = _rhea_channel_resource_index_get(channel->tcam, tcam_base, tcam_offset, &tcam_index); if (rc) { rhea_error("Was not able to find index in TCAM map"); return -EINVAL; } reg_pattern = in_be64(&pport->pport_regs->bpfc.pg_tcampr[tcam_index]); /* enable/disable TCAM slot */ reg_pattern = hea_set_u64_bits(reg_pattern, enable ? 1 : 0, 47, 47); out_be64(&pport->pport_regs->bpfc.pg_tcampr[tcam_index], reg_pattern); return rc; }
static int _rhea_tcam_register_set(struct rhea_channel *channel, unsigned tcam_base, unsigned tcam_offset, unsigned qpn_offset, unsigned pattern, unsigned mask) { int rc = 0; unsigned tcam_index; unsigned qpn_index; u64 reg_pattern; u64 reg_mask; struct rhea_pport *pport; if (NULL == channel) return -EINVAL; if (NULL == channel->tcam || NULL == channel->qpn) { rhea_error("TCAM or QPN is not allocated"); return -EINVAL; } pport = _rhea_pport_get(channel->pport_nr); if (NULL == pport) { rhea_error("Invalid pport number"); return -EINVAL; } /* get the real index in the TCAM array */ rc = _rhea_channel_resource_index_get(channel->tcam, tcam_base, tcam_offset, &tcam_index); if (rc) { rhea_error("Was not able to find index in TCAM map"); return -EINVAL; } /* check if the offset is valid for this channel */ rc = _rhea_channel_resource_index_get(channel->qpn, channel->qpn_base, qpn_offset, &qpn_index); if (rc) { rhea_error("Was not able to find index in QPN map"); return -EINVAL; } reg_pattern = in_be64(&pport->pport_regs->bpfc.pg_tcampr[tcam_index]); reg_mask = in_be64(&pport->pport_regs->bpfc.pg_tcamm[tcam_index]); /* set pattern and mask */ reg_pattern = hea_set_u64_bits(reg_pattern, pattern, 0, 31); reg_mask = hea_set_u64_bits(reg_mask, mask, 0, 31); /* configure LPORT or PPORT */ switch (channel->type) { case HEA_BC_PORT: case HEA_MC_PORT: case HEA_UC_PORT: /* case UC_MC_HEA_BC_PORT: */ /* is physical port */ reg_pattern = hea_set_u64_bits(reg_pattern, 0, 48, 48); reg_mask = hea_set_u64_bits(reg_mask, 1, 48, 48); break; default: /* is logical port */ reg_pattern = hea_set_u64_bits(reg_pattern, 1, 48, 48); reg_mask = hea_set_u64_bits(reg_mask, 1, 48, 48); break; } /* configure which channel type is using this TCAM */ switch (channel->type) { case HEA_BC_PORT: reg_pattern = hea_set_u64_bits(reg_pattern, 1, 54, 55); reg_mask = hea_set_u64_bits(reg_mask, 3, 54, 55); break; case HEA_MC_PORT: reg_pattern = hea_set_u64_bits(reg_pattern, 2, 54, 55); reg_mask = hea_set_u64_bits(reg_mask, 3, 54, 55); break; case HEA_UC_PORT: reg_pattern = hea_set_u64_bits(reg_pattern, 3, 54, 55); reg_mask = hea_set_u64_bits(reg_mask, 3, 54, 55); break; default: { int lport_index = hea_lport_index_get(channel->type); /* only allow one logical port at a time * --> not all combinations are possible */ reg_pattern = hea_set_u64_bits(reg_pattern, lport_index, 54, 55); reg_mask = hea_set_u64_bits(reg_mask, 3, 54, 55); } break; } /* This is the offset from the QPN base to be used * if the packet data matches the pattern */ reg_pattern = hea_set_u64_bits(reg_pattern, qpn_offset, 59, 63); /* write back registers */ out_be64(&pport->pport_regs->bpfc.pg_tcampr[tcam_index], reg_pattern); out_be64(&pport->pport_regs->bpfc.pg_tcamm[tcam_index], reg_mask); return rc; }