/* Hard-coded configuration: * These values are used as hard-coded values for KeyGen configuration * and they replace user selections for this hard-coded version
*/
/* Hash distribution shift */ #define DEFAULT_HASH_DIST_FQID_SHIFT 0
/* Hash shift */ #define DEFAULT_HASH_SHIFT 0
/* Symmetric hash usage: * Warning: * - the value for symmetric hash usage must be in accordance with hash * key defined below * - according to tests performed, spreading is not working if symmetric * hash is set on true * So ultimately symmetric hash functionality should be always disabled:
*/ #define DEFAULT_SYMMETRIC_HASH false
/* Default values to be used as hash key in case IPv4 or L4 (TCP, UDP) * don't exist in the frame
*/ /* Default IPv4 address */ #define DEFAULT_HASH_KEY_IPv4_ADDR 0x0A0A0A0A /* Default L4 port */ #define DEFAULT_HASH_KEY_L4_PORT 0x0B0B0B0B
/* KeyGen Scheme data */ struct keygen_scheme { bool used; /* Specifies if this scheme is used */
u8 hw_port_id; /* Hardware port ID * schemes sharing between multiple ports is not * currently supported * so we have only one port id bound to a scheme
*/
u32 base_fqid; /* Base FQID: * Must be between 1 and 2^24-1 * If hash is used and an even distribution is * expected according to hash_fqid_count, * base_fqid must be aligned to hash_fqid_count
*/
u32 hash_fqid_count; /* FQ range for hash distribution: * Must be a power of 2 * Represents the range of queues for spreading
*/ bool use_hashing; /* Usage of Hashing and spreading over FQ */ bool symmetric_hash; /* Symmetric Hash option usage */
u8 hashShift; /* Hash result right shift. * Select the 24 bits out of the 64 hash result. * 0 means using the 24 LSB's, otherwise * use the 24 LSB's after shifting right
*/
u32 match_vector; /* Match Vector */
};
/* keygen_write_ar_wait * * Write Action Register with specified value, wait for GO bit field to be * idle and then read the error * * regs: KeyGen registers * fmkg_ar: Action Register value * * Return: Zero for success or error code in case of failure
*/ staticint keygen_write_ar_wait(struct fman_kg_regs __iomem *regs, u32 fmkg_ar)
{
iowrite32be(fmkg_ar, ®s->fmkg_ar);
/* Wait for GO bit field to be idle */ while (fmkg_ar & FM_KG_KGAR_GO)
fmkg_ar = ioread32be(®s->fmkg_ar);
if (fmkg_ar & FM_KG_KGAR_ERR) return -EINVAL;
return 0;
}
/* build_ar_scheme * * Build Action Register value for scheme settings * * scheme_id: Scheme ID * update_counter: update scheme counter * write: true for action to write the scheme or false for read action * * Return: AR value
*/ static u32 build_ar_scheme(u8 scheme_id, bool update_counter, bool write)
{
u32 rw = (u32)(write ? FM_KG_KGAR_WRITE : FM_KG_KGAR_READ);
/* build_ar_bind_scheme * * Build Action Register value for port binding to schemes * * hwport_id: HW Port ID * write: true for action to write the bind or false for read action * * Return: AR value
*/ static u32 build_ar_bind_scheme(u8 hwport_id, bool write)
{
u32 rw = write ? (u32)FM_KG_KGAR_WRITE : (u32)FM_KG_KGAR_READ;
/* keygen_write_sp * * Write Scheme Partition Register with specified value * * regs: KeyGen Registers * sp: Scheme Partition register value * add: true to add a scheme partition or false to clear * * Return: none
*/ staticvoid keygen_write_sp(struct fman_kg_regs __iomem *regs, u32 sp, bool add)
{
u32 tmp;
tmp = ioread32be(®s->fmkg_pe.fmkg_pe_sp);
if (add)
tmp |= sp; else
tmp &= ~sp;
iowrite32be(tmp, ®s->fmkg_pe.fmkg_pe_sp);
}
/* build_ar_bind_cls_plan * * Build Action Register value for Classification Plan * * hwport_id: HW Port ID * write: true for action to write the CP or false for read action * * Return: AR value
*/ static u32 build_ar_bind_cls_plan(u8 hwport_id, bool write)
{
u32 rw = write ? (u32)FM_KG_KGAR_WRITE : (u32)FM_KG_KGAR_READ;
/* get_free_scheme_id * * Find the first free scheme available to be used * * keygen: KeyGen handle * scheme_id: pointer to scheme id * * Return: 0 on success, -EINVAL when the are no available free schemes
*/ staticint get_free_scheme_id(struct fman_keygen *keygen, u8 *scheme_id)
{
u8 i;
for (i = 0; i < FM_KG_MAX_NUM_OF_SCHEMES; i++) if (!keygen->schemes[i].used) {
*scheme_id = i; return 0;
}
return -EINVAL;
}
/* get_scheme * * Provides the scheme for specified ID * * keygen: KeyGen handle * scheme_id: Scheme ID * * Return: handle to required scheme
*/ staticstruct keygen_scheme *get_scheme(struct fman_keygen *keygen,
u8 scheme_id)
{ if (scheme_id >= FM_KG_MAX_NUM_OF_SCHEMES) return NULL; return &keygen->schemes[scheme_id];
}
/* keygen_bind_port_to_schemes * * Bind the port to schemes * * keygen: KeyGen handle * scheme_id: id of the scheme to bind to * bind: true to bind the port or false to unbind it * * Return: Zero for success or error code in case of failure
*/ staticint keygen_bind_port_to_schemes(struct fman_keygen *keygen,
u8 scheme_id, bool bind)
{ struct fman_kg_regs __iomem *keygen_regs = keygen->keygen_regs; struct keygen_scheme *scheme;
u32 ar_reg;
u32 schemes_vector = 0; int err;
scheme = get_scheme(keygen, scheme_id); if (!scheme) {
pr_err("Requested Scheme does not exist\n"); return -EINVAL;
} if (!scheme->used) {
pr_err("Cannot bind port to an invalid scheme\n"); return -EINVAL;
}
/* keygen_scheme_setup * * Setup the scheme according to required configuration * * keygen: KeyGen handle * scheme_id: scheme ID * enable: true to enable scheme or false to disable it * * Return: Zero for success or error code in case of failure
*/ staticint keygen_scheme_setup(struct fman_keygen *keygen, u8 scheme_id, bool enable)
{ struct fman_kg_regs __iomem *keygen_regs = keygen->keygen_regs; struct fman_kg_scheme_regs scheme_regs; struct keygen_scheme *scheme;
u32 tmp_reg; int err;
scheme = get_scheme(keygen, scheme_id); if (!scheme) {
pr_err("Requested Scheme does not exist\n"); return -EINVAL;
} if (enable && scheme->used) {
pr_err("The requested Scheme is already used\n"); return -EINVAL;
}
if (scheme->symmetric_hash) { /* Normally extraction key should be verified if * complies with symmetric hash * But because extraction is hard-coded, we are sure * the key is symmetric
*/
tmp_reg |= KG_SCH_HASH_CONFIG_SYM;
}
scheme_regs.kgse_hc = tmp_reg;
} else {
scheme_regs.kgse_ekfc = 0;
scheme_regs.kgse_hc = 0;
scheme_regs.kgse_ekdv = 0;
scheme_regs.kgse_dv0 = 0;
scheme_regs.kgse_dv1 = 0;
}
/* Clear binding between ports to schemes and classification plans * so that all ports are not bound to any scheme/classification plan
*/ for (i = 0; i < FMAN_MAX_NUM_OF_HW_PORTS; i++) { /* Clear all pe sp schemes registers */
keygen_write_sp(keygen_regs, 0xffffffff, false);
ar = build_ar_bind_scheme(i, true);
keygen_write_ar_wait(keygen_regs, ar);
/* Clear all pe cpp classification plans registers */
keygen_write_cpp(keygen_regs, 0);
ar = build_ar_bind_cls_plan(i, true);
keygen_write_ar_wait(keygen_regs, ar);
}
/* Enable all scheme interrupts */
iowrite32be(0xFFFFFFFF, &keygen_regs->fmkg_seer);
iowrite32be(0xFFFFFFFF, &keygen_regs->fmkg_seeer);
/* keygen_port_hashing_init * * Initializes a port for Rx Hashing with specified configuration parameters * * keygen: KeyGen handle * hw_port_id: HW Port ID * hash_base_fqid: Hashing Base FQID used for spreading * hash_size: Hashing size * * Return: Zero for success or error code in case of failure
*/ int keygen_port_hashing_init(struct fman_keygen *keygen, u8 hw_port_id,
u32 hash_base_fqid, u32 hash_size)
{ struct keygen_scheme *scheme;
u8 scheme_id; int err;
/* Validate Scheme configuration parameters */ if (hash_base_fqid == 0 || (hash_base_fqid & ~0x00FFFFFF)) {
pr_err("Base FQID must be between 1 and 2^24-1\n"); return -EINVAL;
} if (hash_size == 0 || (hash_size & (hash_size - 1)) != 0) {
pr_err("Hash size must be power of two\n"); return -EINVAL;
}
/* Find a free scheme */
err = get_free_scheme_id(keygen, &scheme_id); if (err) {
pr_err("The maximum number of available Schemes has been exceeded\n"); return -EINVAL;
}
/* Create and configure Hard-Coded Scheme: */
scheme = get_scheme(keygen, scheme_id); if (!scheme) {
pr_err("Requested Scheme does not exist\n"); return -EINVAL;
} if (scheme->used) {
pr_err("The requested Scheme is already used\n"); return -EINVAL;
}
/* Clear all scheme fields because the scheme may have been * previously used
*/
memset(scheme, 0, sizeof(struct keygen_scheme));
/* Bind Rx port to Scheme */
err = keygen_bind_port_to_schemes(keygen, scheme_id, true); if (err != 0) {
pr_err("Binding port to schemes failed\n"); return err;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.