// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2013 - 2018 Intel Corporation. */
#include "i40e.h"
#include "i40e_osdep.h"
#include "i40e_register.h"
#include "i40e_type.h"
#include "i40e_hmc.h"
#include "i40e_lan_hmc.h"
#include "i40e_prototype.h"
/* lan specific interface functions */
/**
* i40e_align_l2obj_base - aligns base object pointer to 512 bytes
* @offset: base address offset needing alignment
*
* Aligns the layer 2 function private memory so it's 512-byte aligned.
**/
static u64 i40e_align_l2obj_base(u64 offset)
{
u64 aligned_offset = offset;
if ((offset % I40E_HMC_L2OBJ_BASE_ALIGNMENT) > 0)
aligned_offset += (I40E_HMC_L2OBJ_BASE_ALIGNMENT -
(offset % I40E_HMC_L2OBJ_BASE_ALIGNMENT));
return aligned_offset;
}
/**
* i40e_calculate_l2fpm_size - calculates layer 2 FPM memory size
* @txq_num: number of Tx queues needing backing context
* @rxq_num: number of Rx queues needing backing context
* @fcoe_cntx_num: amount of FCoE statefull contexts needing backing context
* @fcoe_filt_num: number of FCoE filters needing backing context
*
* Calculates the maximum amount of memory for the function required, based
* on the number of resources it must provide context for.
**/
static u64 i40e_calculate_l2fpm_size(u32 txq_num, u32 rxq_num,
u32 fcoe_cntx_num, u32 fcoe_filt_num)
{
u64 fpm_size = 0;
fpm_size = txq_num * I40E_HMC_OBJ_SIZE_TXQ;
fpm_size = i40e_align_l2obj_base(fpm_size);
fpm_size += (rxq_num * I40E_HMC_OBJ_SIZE_RXQ);
fpm_size = i40e_align_l2obj_base(fpm_size);
fpm_size += (fcoe_cntx_num * I40E_HMC_OBJ_SIZE_FCOE_CNTX);
fpm_size = i40e_align_l2obj_base(fpm_size);
fpm_size += (fcoe_filt_num * I40E_HMC_OBJ_SIZE_FCOE_FILT);
fpm_size = i40e_align_l2obj_base(fpm_size);
return fpm_size;
}
/**
* i40e_init_lan_hmc - initialize i40e_hmc_info struct
* @hw: pointer to the HW structure
* @txq_num: number of Tx queues needing backing context
* @rxq_num: number of Rx queues needing backing context
* @fcoe_cntx_num: amount of FCoE statefull contexts needing backing context
* @fcoe_filt_num: number of FCoE filters needing backing context
*
* This function will be called once per physical function initialization.
* It will fill out the i40e_hmc_obj_info structure for LAN objects based on
* the driver's provided input, as well as information from the HMC itself
* loaded from NVRAM.
*
* Assumptions:
* - HMC Resource Profile has been selected before calling this function.
**/
i40e_status i40e_init_lan_hmc(struct i40e_hw *hw, u32 txq_num,
u32 rxq_num, u32 fcoe_cntx_num,
u32 fcoe_filt_num)
{
struct i40e_hmc_obj_info *obj, *full_obj;
i40e_status ret_code = 0;
u64 l2fpm_size;
u32 size_exp;
hw->hmc.signature = I40E_HMC_INFO_SIGNATURE;
hw->hmc.hmc_fn_id = hw->pf_id;
/* allocate memory for hmc_obj */
ret_code = i40e_allocate_virt_mem(hw, &hw->hmc.hmc_obj_virt_mem,
sizeof(struct i40e_hmc_obj_info) * I40E_HMC_LAN_MAX);
if (ret_code)
goto init_lan_hmc_out;
hw->hmc.hmc_obj = (struct i40e_hmc_obj_info *)
hw->hmc.hmc_obj_virt_mem.va;
/* The full object will be used to create the LAN HMC SD */
full_obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_FULL];
full_obj->max_cnt = 0;
full_obj->cnt = 0;
full_obj->base = 0;
full_obj->size = 0;
/* Tx queue context information */
obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_TX];
obj->max_cnt = rd32(hw, I40E_GLHMC_LANQMAX);
obj->cnt = txq_num;
obj->base = 0;
size_exp = rd32(hw, I40E_GLHMC_LANTXOBJSZ);
obj->size = BIT_ULL(size_exp);
/* validate values requested by driver don't exceed HMC capacity */
if (txq_num > obj->max_cnt) {
ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT;
hw_dbg(hw, "i40e_init_lan_hmc: Tx context: asks for 0x%x but max allowed is 0x%x, returns error %d\n",
txq_num, obj->max_cnt, ret_code);
goto init_lan_hmc_out;
}
/* aggregate values into the full LAN object for later */
full_obj->max_cnt += obj->max_cnt;
full_obj->cnt += obj->cnt;
/* Rx queue context information */
obj = &hw->