blob: 1834b3950b2f0eac41ad4e94d70f674c1415f42c [file] [log] [blame]
/*
* Copyright (c) 2017, The Linux Foundation. All rights reserved.
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* @defgroup
* @{
*/
#include "sw.h"
#include "hppe_rss_reg.h"
#include "hppe_rss.h"
#include "adpt.h"
sw_error_t
adpt_hppe_rss_hash_config_set(a_uint32_t dev_id, fal_rss_hash_mode_t mode,
fal_rss_hash_config_t * config)
{
a_uint32_t index;
union rss_hash_mask_reg_u rss_hash_mask_ipv6 = {0};
union rss_hash_seed_reg_u rss_hash_seed_ipv6 = {0};
union rss_hash_mix_reg_u rss_hash_mix_ipv6[11] = {0};
union rss_hash_fin_reg_u rss_hash_fin_ipv6[5] = {0};
union rss_hash_mask_ipv4_reg_u rss_hash_mask_ipv4 = {0};
union rss_hash_seed_ipv4_reg_u rss_hash_seed_ipv4 = {0};
union rss_hash_mix_ipv4_reg_u rss_hash_mix_ipv4[5] = {0};
union rss_hash_fin_ipv4_reg_u rss_hash_fin_ipv4[5] = {0};
ADPT_DEV_ID_CHECK(dev_id);
if (mode == FAL_RSS_HASH_IPV4V6 || mode == FAL_RSS_HASH_IPV4ONLY)
{
rss_hash_mask_ipv4.bf.mask = config->hash_mask & 0x1fffff;
rss_hash_mask_ipv4.bf.fragment = config->hash_fragment_mode;
rss_hash_seed_ipv4.bf.seed = config->hash_seed;
rss_hash_mix_ipv4[0].bf.hash_mix = config->hash_sip_mix & 0x1f;
rss_hash_mix_ipv4[1].bf.hash_mix = config->hash_dip_mix & 0x1f;
rss_hash_mix_ipv4[2].bf.hash_mix = config->hash_protocol_mix & 0x1f;
rss_hash_mix_ipv4[3].bf.hash_mix = config->hash_dport_mix & 0x1f;
rss_hash_mix_ipv4[4].bf.hash_mix = config->hash_sport_mix & 0x1f;
rss_hash_fin_ipv4[0].bf.fin_inner = config->hash_fin_inner & 0x1f;
rss_hash_fin_ipv4[0].bf.fin_outer = config->hash_fin_outer & 0x1f;
rss_hash_fin_ipv4[1].bf.fin_inner = (config->hash_fin_inner >> 0x5) & 0x1f;
rss_hash_fin_ipv4[1].bf.fin_outer = (config->hash_fin_outer >> 0x5) & 0x1f;
rss_hash_fin_ipv4[2].bf.fin_inner = (config->hash_fin_inner >> 0xa) & 0x1f;
rss_hash_fin_ipv4[2].bf.fin_outer = (config->hash_fin_outer >> 0xa) & 0x1f;
rss_hash_fin_ipv4[3].bf.fin_inner = (config->hash_fin_inner >> 0xf) & 0x1f;
rss_hash_fin_ipv4[3].bf.fin_outer = (config->hash_fin_outer >> 0xf) & 0x1f;
rss_hash_fin_ipv4[4].bf.fin_inner = (config->hash_fin_inner >> 0x14) & 0x1f;
rss_hash_fin_ipv4[4].bf.fin_outer = (config->hash_fin_outer >> 0x14) & 0x1f;
SW_RTN_ON_ERROR(hppe_rss_hash_mask_ipv4_reg_set(dev_id, &rss_hash_mask_ipv4));
SW_RTN_ON_ERROR(hppe_rss_hash_seed_ipv4_reg_set(dev_id, &rss_hash_seed_ipv4));
for (index = 0; index < 5; index++)
SW_RTN_ON_ERROR(hppe_rss_hash_mix_ipv4_reg_set(dev_id, index, &rss_hash_mix_ipv4[index]));
for (index = 0; index < 5; index++)
SW_RTN_ON_ERROR(hppe_rss_hash_fin_ipv4_reg_set(dev_id, index, &rss_hash_fin_ipv4[index]));
}
if (mode == FAL_RSS_HASH_IPV4V6 || mode == FAL_RSS_HASH_IPV6ONLY)
{
rss_hash_mask_ipv6.bf.mask = config->hash_mask & 0x1fffff;
rss_hash_mask_ipv6.bf.fragment = config->hash_fragment_mode;
rss_hash_seed_ipv6.bf.seed = config->hash_seed;
rss_hash_mix_ipv6[0].bf.hash_mix = config->hash_sip_mix & 0x1f;
rss_hash_mix_ipv6[1].bf.hash_mix = (config->hash_sip_mix >> 0x5) & 0x1f;
rss_hash_mix_ipv6[2].bf.hash_mix = (config->hash_sip_mix >> 0xa) & 0x1f;
rss_hash_mix_ipv6[3].bf.hash_mix = (config->hash_sip_mix >> 0xf) & 0x1f;
rss_hash_mix_ipv6[4].bf.hash_mix = config->hash_dip_mix & 0x1f;
rss_hash_mix_ipv6[5].bf.hash_mix = (config->hash_dip_mix >> 0x5) & 0x1f;
rss_hash_mix_ipv6[6].bf.hash_mix = (config->hash_dip_mix >> 0xa) & 0x1f;
rss_hash_mix_ipv6[7].bf.hash_mix = (config->hash_dip_mix >> 0xf) & 0x1f;
rss_hash_mix_ipv6[8].bf.hash_mix = config->hash_protocol_mix & 0x1f;
rss_hash_mix_ipv6[9].bf.hash_mix = config->hash_dport_mix & 0x1f;
rss_hash_mix_ipv6[10].bf.hash_mix = config->hash_sport_mix & 0x1f;
rss_hash_fin_ipv6[0].bf.fin_inner = config->hash_fin_inner & 0x1f;
rss_hash_fin_ipv6[0].bf.fin_outer = config->hash_fin_outer & 0x1f;
rss_hash_fin_ipv6[1].bf.fin_inner = (config->hash_fin_inner >> 0x5) & 0x1f;
rss_hash_fin_ipv6[1].bf.fin_outer = (config->hash_fin_outer >> 0x5) & 0x1f;
rss_hash_fin_ipv6[2].bf.fin_inner = (config->hash_fin_inner >> 0xa) & 0x1f;
rss_hash_fin_ipv6[2].bf.fin_outer = (config->hash_fin_outer >> 0xa) & 0x1f;
rss_hash_fin_ipv6[3].bf.fin_inner = (config->hash_fin_inner >> 0xf) & 0x1f;
rss_hash_fin_ipv6[3].bf.fin_outer = (config->hash_fin_outer >> 0xf) & 0x1f;
rss_hash_fin_ipv6[4].bf.fin_inner = (config->hash_fin_inner >> 0x14) & 0x1f;
rss_hash_fin_ipv6[4].bf.fin_outer = (config->hash_fin_outer >> 0x14) & 0x1f;
SW_RTN_ON_ERROR(hppe_rss_hash_mask_reg_set(dev_id, &rss_hash_mask_ipv6));
SW_RTN_ON_ERROR(hppe_rss_hash_seed_reg_set(dev_id, &rss_hash_seed_ipv6));
for (index = 0; index < 11; index++)
SW_RTN_ON_ERROR(hppe_rss_hash_mix_reg_set(dev_id, index, &rss_hash_mix_ipv6[index]));
for (index = 0; index < 5; index++)
SW_RTN_ON_ERROR(hppe_rss_hash_fin_reg_set(dev_id, index, &rss_hash_fin_ipv6[index]));
}
return SW_OK;
}
sw_error_t
adpt_hppe_rss_hash_config_get(a_uint32_t dev_id, fal_rss_hash_mode_t mode,
fal_rss_hash_config_t * config)
{
a_uint32_t index;
union rss_hash_mask_reg_u rss_hash_mask_ipv6 = {0};
union rss_hash_seed_reg_u rss_hash_seed_ipv6 = {0};
union rss_hash_mix_reg_u rss_hash_mix_ipv6[11] = {0};
union rss_hash_fin_reg_u rss_hash_fin_ipv6[5] = {0};
union rss_hash_mask_ipv4_reg_u rss_hash_mask_ipv4 = {0};
union rss_hash_seed_ipv4_reg_u rss_hash_seed_ipv4 = {0};
union rss_hash_mix_ipv4_reg_u rss_hash_mix_ipv4[5] = {0};
union rss_hash_fin_ipv4_reg_u rss_hash_fin_ipv4[5] = {0};
ADPT_DEV_ID_CHECK(dev_id);
SW_RTN_ON_ERROR(hppe_rss_hash_mask_ipv4_reg_get(dev_id, &rss_hash_mask_ipv4));
SW_RTN_ON_ERROR(hppe_rss_hash_seed_ipv4_reg_get(dev_id, &rss_hash_seed_ipv4));
for (index = 0; index < 5; index++)
SW_RTN_ON_ERROR(hppe_rss_hash_mix_ipv4_reg_get(dev_id, index, &rss_hash_mix_ipv4[index]));
for (index = 0; index < 5; index++)
SW_RTN_ON_ERROR(hppe_rss_hash_fin_ipv4_reg_get(dev_id, index, &rss_hash_fin_ipv4[index]));
SW_RTN_ON_ERROR(hppe_rss_hash_mask_reg_get(dev_id, &rss_hash_mask_ipv6));
SW_RTN_ON_ERROR(hppe_rss_hash_seed_reg_get(dev_id, &rss_hash_seed_ipv6));
for (index = 0; index < 11; index++)
SW_RTN_ON_ERROR(hppe_rss_hash_mix_reg_get(dev_id, index, &rss_hash_mix_ipv6[index]));
for (index = 0; index < 5; index++)
SW_RTN_ON_ERROR(hppe_rss_hash_fin_reg_get(dev_id, index, &rss_hash_fin_ipv6[index]));
if (mode == FAL_RSS_HASH_IPV4ONLY)
{
config->hash_mask = rss_hash_mask_ipv4.bf.mask;
config->hash_fragment_mode = rss_hash_mask_ipv4.bf.fragment;
config->hash_seed = rss_hash_seed_ipv4.bf.seed;
config->hash_sip_mix = rss_hash_mix_ipv4[0].bf.hash_mix;
config->hash_dip_mix = rss_hash_mix_ipv4[1].bf.hash_mix;
config->hash_protocol_mix = rss_hash_mix_ipv4[2].bf.hash_mix;
config->hash_dport_mix = rss_hash_mix_ipv4[3].bf.hash_mix;
config->hash_sport_mix = rss_hash_mix_ipv4[4].bf.hash_mix;
config->hash_fin_inner = rss_hash_fin_ipv4[0].bf.fin_inner +
(rss_hash_fin_ipv4[1].bf.fin_inner << 0x5) +
(rss_hash_fin_ipv4[2].bf.fin_inner << 0xa) +
(rss_hash_fin_ipv4[3].bf.fin_inner << 0xf) +
(rss_hash_fin_ipv4[4].bf.fin_inner << 0x14);
config->hash_fin_outer = rss_hash_fin_ipv4[0].bf.fin_outer +
(rss_hash_fin_ipv4[1].bf.fin_outer << 0x5) +
(rss_hash_fin_ipv4[2].bf.fin_outer << 0xa) +
(rss_hash_fin_ipv4[3].bf.fin_outer << 0xf) +
(rss_hash_fin_ipv4[4].bf.fin_outer << 0x14);
}
else if (mode == FAL_RSS_HASH_IPV6ONLY)
{
config->hash_mask = rss_hash_mask_ipv6.bf.mask;
config->hash_fragment_mode = rss_hash_mask_ipv6.bf.fragment;
config->hash_seed = rss_hash_seed_ipv6.bf.seed;
config->hash_sip_mix = rss_hash_mix_ipv6[0].bf.hash_mix +
(rss_hash_mix_ipv6[1].bf.hash_mix << 0x5) +
(rss_hash_mix_ipv6[2].bf.hash_mix << 0xa) +
(rss_hash_mix_ipv6[3].bf.hash_mix << 0xf);
config->hash_dip_mix = rss_hash_mix_ipv6[4].bf.hash_mix +
(rss_hash_mix_ipv6[5].bf.hash_mix << 0x5) +
(rss_hash_mix_ipv6[6].bf.hash_mix << 0xa) +
(rss_hash_mix_ipv6[7].bf.hash_mix << 0xf);
config->hash_protocol_mix = rss_hash_mix_ipv6[8].bf.hash_mix;
config->hash_dport_mix = rss_hash_mix_ipv6[9].bf.hash_mix;
config->hash_sport_mix = rss_hash_mix_ipv6[10].bf.hash_mix;
config->hash_fin_inner = rss_hash_fin_ipv6[0].bf.fin_inner +
(rss_hash_fin_ipv6[1].bf.fin_inner << 0x5) +
(rss_hash_fin_ipv6[2].bf.fin_inner << 0xa) +
(rss_hash_fin_ipv6[3].bf.fin_inner << 0xf) +
(rss_hash_fin_ipv6[4].bf.fin_inner << 0x14);
config->hash_fin_outer = rss_hash_fin_ipv6[0].bf.fin_outer +
(rss_hash_fin_ipv6[1].bf.fin_outer << 0x5) +
(rss_hash_fin_ipv6[2].bf.fin_outer << 0xa) +
(rss_hash_fin_ipv6[3].bf.fin_outer << 0xf) +
(rss_hash_fin_ipv6[4].bf.fin_outer << 0x14);
}
else
{
if ((rss_hash_mask_ipv4.bf.mask == rss_hash_mask_ipv6.bf.mask) &&
(rss_hash_mask_ipv4.bf.fragment == rss_hash_mask_ipv6.bf.fragment) &&
(rss_hash_seed_ipv4.bf.seed == rss_hash_seed_ipv6.bf.seed) &&
(rss_hash_mix_ipv4[0].bf.hash_mix == rss_hash_mix_ipv6[0].bf.hash_mix) &&
(rss_hash_mix_ipv4[1].bf.hash_mix == rss_hash_mix_ipv6[4].bf.hash_mix) &&
(rss_hash_mix_ipv4[2].bf.hash_mix == rss_hash_mix_ipv6[8].bf.hash_mix) &&
(rss_hash_mix_ipv4[3].bf.hash_mix == rss_hash_mix_ipv6[9].bf.hash_mix) &&
(rss_hash_mix_ipv4[4].bf.hash_mix == rss_hash_mix_ipv6[10].bf.hash_mix) &&
(rss_hash_fin_ipv4[0].bf.fin_inner == rss_hash_fin_ipv6[0].bf.fin_inner) &&
(rss_hash_fin_ipv4[1].bf.fin_inner == rss_hash_fin_ipv6[1].bf.fin_inner) &&
(rss_hash_fin_ipv4[2].bf.fin_inner == rss_hash_fin_ipv6[2].bf.fin_inner) &&
(rss_hash_fin_ipv4[3].bf.fin_inner == rss_hash_fin_ipv6[3].bf.fin_inner) &&
(rss_hash_fin_ipv4[4].bf.fin_inner == rss_hash_fin_ipv6[4].bf.fin_inner) &&
(rss_hash_fin_ipv4[0].bf.fin_outer == rss_hash_fin_ipv6[0].bf.fin_outer) &&
(rss_hash_fin_ipv4[1].bf.fin_outer == rss_hash_fin_ipv6[1].bf.fin_outer) &&
(rss_hash_fin_ipv4[2].bf.fin_outer == rss_hash_fin_ipv6[2].bf.fin_outer) &&
(rss_hash_fin_ipv4[3].bf.fin_outer == rss_hash_fin_ipv6[3].bf.fin_outer) &&
(rss_hash_fin_ipv4[4].bf.fin_outer == rss_hash_fin_ipv6[4].bf.fin_outer))
{
config->hash_mask = rss_hash_mask_ipv6.bf.mask;
config->hash_fragment_mode = rss_hash_mask_ipv6.bf.fragment;
config->hash_seed = rss_hash_seed_ipv6.bf.seed;
config->hash_sip_mix = rss_hash_mix_ipv6[0].bf.hash_mix +
(rss_hash_mix_ipv6[1].bf.hash_mix << 0x5) +
(rss_hash_mix_ipv6[2].bf.hash_mix << 0xa) +
(rss_hash_mix_ipv6[3].bf.hash_mix << 0xf);
config->hash_dip_mix = rss_hash_mix_ipv6[4].bf.hash_mix +
(rss_hash_mix_ipv6[5].bf.hash_mix << 0x5) +
(rss_hash_mix_ipv6[6].bf.hash_mix << 0xa) +
(rss_hash_mix_ipv6[7].bf.hash_mix << 0xf);
config->hash_protocol_mix = rss_hash_mix_ipv6[8].bf.hash_mix;
config->hash_dport_mix = rss_hash_mix_ipv6[9].bf.hash_mix;
config->hash_sport_mix = rss_hash_mix_ipv6[10].bf.hash_mix;
config->hash_fin_inner = rss_hash_fin_ipv6[0].bf.fin_inner +
(rss_hash_fin_ipv6[1].bf.fin_inner << 0x5) +
(rss_hash_fin_ipv6[2].bf.fin_inner << 0xa) +
(rss_hash_fin_ipv6[3].bf.fin_inner << 0xf) +
(rss_hash_fin_ipv6[4].bf.fin_inner << 0x14);
config->hash_fin_outer = rss_hash_fin_ipv6[0].bf.fin_outer +
(rss_hash_fin_ipv6[1].bf.fin_outer << 0x5) +
(rss_hash_fin_ipv6[2].bf.fin_outer << 0xa) +
(rss_hash_fin_ipv6[3].bf.fin_outer << 0xf) +
(rss_hash_fin_ipv6[4].bf.fin_outer << 0x14);
}
else
return SW_FAIL;
}
return SW_OK;
}
void adpt_hppe_rss_hash_func_bitmap_init(a_uint32_t dev_id)
{
adpt_api_t *p_adpt_api = NULL;
p_adpt_api = adpt_api_ptr_get(dev_id);
if(p_adpt_api == NULL)
return;
p_adpt_api->adpt_rss_hash_func_bitmap = ((1 << FUNC_RSS_HASH_CONFIG_SET) |
(1 << FUNC_RSS_HASH_CONFIG_GET));
return;
}
static void adpt_hppe_rss_hash_func_unregister(a_uint32_t dev_id, adpt_api_t *p_adpt_api)
{
if(p_adpt_api == NULL)
return;
p_adpt_api->adpt_rss_hash_config_set = NULL;
p_adpt_api->adpt_rss_hash_config_get = NULL;
return;
}
sw_error_t adpt_hppe_rss_hash_init(a_uint32_t dev_id)
{
adpt_api_t *p_adpt_api = NULL;
p_adpt_api = adpt_api_ptr_get(dev_id);
if(p_adpt_api == NULL)
return SW_FAIL;
adpt_hppe_rss_hash_func_unregister(dev_id, p_adpt_api);
if(p_adpt_api->adpt_rss_hash_func_bitmap & (1<<FUNC_RSS_HASH_CONFIG_SET))
p_adpt_api->adpt_rss_hash_config_set = adpt_hppe_rss_hash_config_set;
if(p_adpt_api->adpt_rss_hash_func_bitmap & (1<<FUNC_RSS_HASH_CONFIG_GET))
p_adpt_api->adpt_rss_hash_config_get = adpt_hppe_rss_hash_config_get;
return SW_OK;
}
/**
* @}
*/