The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ixl/i40e_lan_hmc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /******************************************************************************
    2 
    3   Copyright (c) 2013-2018, Intel Corporation
    4   All rights reserved.
    5   
    6   Redistribution and use in source and binary forms, with or without 
    7   modification, are permitted provided that the following conditions are met:
    8   
    9    1. Redistributions of source code must retain the above copyright notice, 
   10       this list of conditions and the following disclaimer.
   11   
   12    2. Redistributions in binary form must reproduce the above copyright 
   13       notice, this list of conditions and the following disclaimer in the 
   14       documentation and/or other materials provided with the distribution.
   15   
   16    3. Neither the name of the Intel Corporation nor the names of its 
   17       contributors may be used to endorse or promote products derived from 
   18       this software without specific prior written permission.
   19   
   20   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   21   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   22   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   23   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
   24   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   25   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   26   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   27   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   28   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   29   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   30   POSSIBILITY OF SUCH DAMAGE.
   31 
   32 ******************************************************************************/
   33 /*$FreeBSD$*/
   34 
   35 #include "i40e_osdep.h"
   36 #include "i40e_register.h"
   37 #include "i40e_type.h"
   38 #include "i40e_hmc.h"
   39 #include "i40e_lan_hmc.h"
   40 #include "i40e_prototype.h"
   41 
   42 /* lan specific interface functions */
   43 
   44 /**
   45  * i40e_align_l2obj_base - aligns base object pointer to 512 bytes
   46  * @offset: base address offset needing alignment
   47  *
   48  * Aligns the layer 2 function private memory so it's 512-byte aligned.
   49  **/
   50 static u64 i40e_align_l2obj_base(u64 offset)
   51 {
   52         u64 aligned_offset = offset;
   53 
   54         if ((offset % I40E_HMC_L2OBJ_BASE_ALIGNMENT) > 0)
   55                 aligned_offset += (I40E_HMC_L2OBJ_BASE_ALIGNMENT -
   56                                    (offset % I40E_HMC_L2OBJ_BASE_ALIGNMENT));
   57 
   58         return aligned_offset;
   59 }
   60 
   61 /**
   62  * i40e_calculate_l2fpm_size - calculates layer 2 FPM memory size
   63  * @txq_num: number of Tx queues needing backing context
   64  * @rxq_num: number of Rx queues needing backing context
   65  * @fcoe_cntx_num: amount of FCoE statefull contexts needing backing context
   66  * @fcoe_filt_num: number of FCoE filters needing backing context
   67  *
   68  * Calculates the maximum amount of memory for the function required, based
   69  * on the number of resources it must provide context for.
   70  **/
   71 u64 i40e_calculate_l2fpm_size(u32 txq_num, u32 rxq_num,
   72                               u32 fcoe_cntx_num, u32 fcoe_filt_num)
   73 {
   74         u64 fpm_size = 0;
   75 
   76         fpm_size = txq_num * I40E_HMC_OBJ_SIZE_TXQ;
   77         fpm_size = i40e_align_l2obj_base(fpm_size);
   78 
   79         fpm_size += (rxq_num * I40E_HMC_OBJ_SIZE_RXQ);
   80         fpm_size = i40e_align_l2obj_base(fpm_size);
   81 
   82         fpm_size += (fcoe_cntx_num * I40E_HMC_OBJ_SIZE_FCOE_CNTX);
   83         fpm_size = i40e_align_l2obj_base(fpm_size);
   84 
   85         fpm_size += (fcoe_filt_num * I40E_HMC_OBJ_SIZE_FCOE_FILT);
   86         fpm_size = i40e_align_l2obj_base(fpm_size);
   87 
   88         return fpm_size;
   89 }
   90 
   91 /**
   92  * i40e_init_lan_hmc - initialize i40e_hmc_info struct
   93  * @hw: pointer to the HW structure
   94  * @txq_num: number of Tx queues needing backing context
   95  * @rxq_num: number of Rx queues needing backing context
   96  * @fcoe_cntx_num: amount of FCoE statefull contexts needing backing context
   97  * @fcoe_filt_num: number of FCoE filters needing backing context
   98  *
   99  * This function will be called once per physical function initialization.
  100  * It will fill out the i40e_hmc_obj_info structure for LAN objects based on
  101  * the driver's provided input, as well as information from the HMC itself
  102  * loaded from NVRAM.
  103  *
  104  * Assumptions:
  105  *   - HMC Resource Profile has been selected before calling this function.
  106  **/
  107 enum i40e_status_code i40e_init_lan_hmc(struct i40e_hw *hw, u32 txq_num,
  108                                         u32 rxq_num, u32 fcoe_cntx_num,
  109                                         u32 fcoe_filt_num)
  110 {
  111         struct i40e_hmc_obj_info *obj, *full_obj;
  112         enum i40e_status_code ret_code = I40E_SUCCESS;
  113         u64 l2fpm_size;
  114         u32 size_exp;
  115 
  116         hw->hmc.signature = I40E_HMC_INFO_SIGNATURE;
  117         hw->hmc.hmc_fn_id = hw->pf_id;
  118 
  119         /* allocate memory for hmc_obj */
  120         ret_code = i40e_allocate_virt_mem(hw, &hw->hmc.hmc_obj_virt_mem,
  121                         sizeof(struct i40e_hmc_obj_info) * I40E_HMC_LAN_MAX);
  122         if (ret_code)
  123                 goto init_lan_hmc_out;
  124         hw->hmc.hmc_obj = (struct i40e_hmc_obj_info *)
  125                           hw->hmc.hmc_obj_virt_mem.va;
  126 
  127         /* The full object will be used to create the LAN HMC SD */
  128         full_obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_FULL];
  129         full_obj->max_cnt = 0;
  130         full_obj->cnt = 0;
  131         full_obj->base = 0;
  132         full_obj->size = 0;
  133 
  134         /* Tx queue context information */
  135         obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_TX];
  136         obj->max_cnt = rd32(hw, I40E_GLHMC_LANQMAX);
  137         obj->cnt = txq_num;
  138         obj->base = 0;
  139         size_exp = rd32(hw, I40E_GLHMC_LANTXOBJSZ);
  140         obj->size = BIT_ULL(size_exp);
  141 
  142         /* validate values requested by driver don't exceed HMC capacity */
  143         if (txq_num > obj->max_cnt) {
  144                 ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT;
  145                 DEBUGOUT3("i40e_init_lan_hmc: Tx context: asks for 0x%x but max allowed is 0x%x, returns error %d\n",
  146                           txq_num, obj->max_cnt, ret_code);
  147                 goto free_hmc_out;
  148         }
  149 
  150         /* aggregate values into the full LAN object for later */
  151         full_obj->max_cnt += obj->max_cnt;
  152         full_obj->cnt += obj->cnt;
  153 
  154         /* Rx queue context information */
  155         obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_RX];
  156         obj->max_cnt = rd32(hw, I40E_GLHMC_LANQMAX);
  157         obj->cnt = rxq_num;
  158         obj->base = hw->hmc.hmc_obj[I40E_HMC_LAN_TX].base +
  159                     (hw->hmc.hmc_obj[I40E_HMC_LAN_TX].cnt *
  160                      hw->hmc.hmc_obj[I40E_HMC_LAN_TX].size);
  161         obj->base = i40e_align_l2obj_base(obj->base);
  162         size_exp = rd32(hw, I40E_GLHMC_LANRXOBJSZ);
  163         obj->size = BIT_ULL(size_exp);
  164 
  165         /* validate values requested by driver don't exceed HMC capacity */
  166         if (rxq_num > obj->max_cnt) {
  167                 ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT;
  168                 DEBUGOUT3("i40e_init_lan_hmc: Rx context: asks for 0x%x but max allowed is 0x%x, returns error %d\n",
  169                           rxq_num, obj->max_cnt, ret_code);
  170                 goto free_hmc_out;
  171         }
  172 
  173         /* aggregate values into the full LAN object for later */
  174         full_obj->max_cnt += obj->max_cnt;
  175         full_obj->cnt += obj->cnt;
  176 
  177         /* FCoE context information */
  178         obj = &hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX];
  179         obj->max_cnt = rd32(hw, I40E_GLHMC_FCOEMAX);
  180         obj->cnt = fcoe_cntx_num;
  181         obj->base = hw->hmc.hmc_obj[I40E_HMC_LAN_RX].base +
  182                     (hw->hmc.hmc_obj[I40E_HMC_LAN_RX].cnt *
  183                      hw->hmc.hmc_obj[I40E_HMC_LAN_RX].size);
  184         obj->base = i40e_align_l2obj_base(obj->base);
  185         size_exp = rd32(hw, I40E_GLHMC_FCOEDDPOBJSZ);
  186         obj->size = BIT_ULL(size_exp);
  187 
  188         /* validate values requested by driver don't exceed HMC capacity */
  189         if (fcoe_cntx_num > obj->max_cnt) {
  190                 ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT;
  191                 DEBUGOUT3("i40e_init_lan_hmc: FCoE context: asks for 0x%x but max allowed is 0x%x, returns error %d\n",
  192                           fcoe_cntx_num, obj->max_cnt, ret_code);
  193                 goto free_hmc_out;
  194         }
  195 
  196         /* aggregate values into the full LAN object for later */
  197         full_obj->max_cnt += obj->max_cnt;
  198         full_obj->cnt += obj->cnt;
  199 
  200         /* FCoE filter information */
  201         obj = &hw->hmc.hmc_obj[I40E_HMC_FCOE_FILT];
  202         obj->max_cnt = rd32(hw, I40E_GLHMC_FCOEFMAX);
  203         obj->cnt = fcoe_filt_num;
  204         obj->base = hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX].base +
  205                     (hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX].cnt *
  206                      hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX].size);
  207         obj->base = i40e_align_l2obj_base(obj->base);
  208         size_exp = rd32(hw, I40E_GLHMC_FCOEFOBJSZ);
  209         obj->size = BIT_ULL(size_exp);
  210 
  211         /* validate values requested by driver don't exceed HMC capacity */
  212         if (fcoe_filt_num > obj->max_cnt) {
  213                 ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT;
  214                 DEBUGOUT3("i40e_init_lan_hmc: FCoE filter: asks for 0x%x but max allowed is 0x%x, returns error %d\n",
  215                           fcoe_filt_num, obj->max_cnt, ret_code);
  216                 goto free_hmc_out;
  217         }
  218 
  219         /* aggregate values into the full LAN object for later */
  220         full_obj->max_cnt += obj->max_cnt;
  221         full_obj->cnt += obj->cnt;
  222 
  223         hw->hmc.first_sd_index = 0;
  224         hw->hmc.sd_table.ref_cnt = 0;
  225         l2fpm_size = i40e_calculate_l2fpm_size(txq_num, rxq_num, fcoe_cntx_num,
  226                                                fcoe_filt_num);
  227         if (NULL == hw->hmc.sd_table.sd_entry) {
  228                 hw->hmc.sd_table.sd_cnt = (u32)
  229                                    (l2fpm_size + I40E_HMC_DIRECT_BP_SIZE - 1) /
  230                                    I40E_HMC_DIRECT_BP_SIZE;
  231 
  232                 /* allocate the sd_entry members in the sd_table */
  233                 ret_code = i40e_allocate_virt_mem(hw, &hw->hmc.sd_table.addr,
  234                                           (sizeof(struct i40e_hmc_sd_entry) *
  235                                           hw->hmc.sd_table.sd_cnt));
  236                 if (ret_code)
  237                         goto free_hmc_out;
  238                 hw->hmc.sd_table.sd_entry =
  239                         (struct i40e_hmc_sd_entry *)hw->hmc.sd_table.addr.va;
  240         }
  241         /* store in the LAN full object for later */
  242         full_obj->size = l2fpm_size;
  243 
  244 init_lan_hmc_out:
  245         return ret_code;
  246 free_hmc_out:
  247         if (hw->hmc.hmc_obj_virt_mem.va)
  248                 i40e_free_virt_mem(hw, &hw->hmc.hmc_obj_virt_mem);
  249 
  250         return ret_code;
  251 }
  252 
  253 /**
  254  * i40e_remove_pd_page - Remove a page from the page descriptor table
  255  * @hw: pointer to the HW structure
  256  * @hmc_info: pointer to the HMC configuration information structure
  257  * @idx: segment descriptor index to find the relevant page descriptor
  258  *
  259  * This function:
  260  *      1. Marks the entry in pd table (for paged address mode) invalid
  261  *      2. write to register PMPDINV to invalidate the backing page in FV cache
  262  *      3. Decrement the ref count for  pd_entry
  263  * assumptions:
  264  *      1. caller can deallocate the memory used by pd after this function
  265  *         returns.
  266  **/
  267 static enum i40e_status_code i40e_remove_pd_page(struct i40e_hw *hw,
  268                                                  struct i40e_hmc_info *hmc_info,
  269                                                  u32 idx)
  270 {
  271         enum i40e_status_code ret_code = I40E_SUCCESS;
  272 
  273         if (i40e_prep_remove_pd_page(hmc_info, idx) == I40E_SUCCESS)
  274                 ret_code = i40e_remove_pd_page_new(hw, hmc_info, idx, TRUE);
  275 
  276         return ret_code;
  277 }
  278 
  279 /**
  280  * i40e_remove_sd_bp - remove a backing page from a segment descriptor
  281  * @hw: pointer to our HW structure
  282  * @hmc_info: pointer to the HMC configuration information structure
  283  * @idx: the page index
  284  *
  285  * This function:
  286  *      1. Marks the entry in sd table (for direct address mode) invalid
  287  *      2. write to register PMSDCMD, PMSDDATALOW(PMSDDATALOW.PMSDVALID set
  288  *         to 0) and PMSDDATAHIGH to invalidate the sd page
  289  *      3. Decrement the ref count for the sd_entry
  290  * assumptions:
  291  *      1. caller can deallocate the memory used by backing storage after this
  292  *         function returns.
  293  **/
  294 static enum i40e_status_code i40e_remove_sd_bp(struct i40e_hw *hw,
  295                                                struct i40e_hmc_info *hmc_info,
  296                                                u32 idx)
  297 {
  298         enum i40e_status_code ret_code = I40E_SUCCESS;
  299 
  300         if (i40e_prep_remove_sd_bp(hmc_info, idx) == I40E_SUCCESS)
  301                 ret_code = i40e_remove_sd_bp_new(hw, hmc_info, idx, TRUE);
  302 
  303         return ret_code;
  304 }
  305 
  306 /**
  307  * i40e_create_lan_hmc_object - allocate backing store for hmc objects
  308  * @hw: pointer to the HW structure
  309  * @info: pointer to i40e_hmc_create_obj_info struct
  310  *
  311  * This will allocate memory for PDs and backing pages and populate
  312  * the sd and pd entries.
  313  **/
  314 enum i40e_status_code i40e_create_lan_hmc_object(struct i40e_hw *hw,
  315                                 struct i40e_hmc_lan_create_obj_info *info)
  316 {
  317         enum i40e_status_code ret_code = I40E_SUCCESS;
  318         struct i40e_hmc_sd_entry *sd_entry;
  319         u32 pd_idx1 = 0, pd_lmt1 = 0;
  320         u32 pd_idx = 0, pd_lmt = 0;
  321         bool pd_error = FALSE;
  322         u32 sd_idx, sd_lmt;
  323         u64 sd_size;
  324         u32 i, j;
  325 
  326         if (NULL == info) {
  327                 ret_code = I40E_ERR_BAD_PTR;
  328                 DEBUGOUT("i40e_create_lan_hmc_object: bad info ptr\n");
  329                 goto exit;
  330         }
  331         if (NULL == info->hmc_info) {
  332                 ret_code = I40E_ERR_BAD_PTR;
  333                 DEBUGOUT("i40e_create_lan_hmc_object: bad hmc_info ptr\n");
  334                 goto exit;
  335         }
  336         if (I40E_HMC_INFO_SIGNATURE != info->hmc_info->signature) {
  337                 ret_code = I40E_ERR_BAD_PTR;
  338                 DEBUGOUT("i40e_create_lan_hmc_object: bad signature\n");
  339                 goto exit;
  340         }
  341 
  342         if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt) {
  343                 ret_code = I40E_ERR_INVALID_HMC_OBJ_INDEX;
  344                 DEBUGOUT1("i40e_create_lan_hmc_object: returns error %d\n",
  345                           ret_code);
  346                 goto exit;
  347         }
  348         if ((info->start_idx + info->count) >
  349             info->hmc_info->hmc_obj[info->rsrc_type].cnt) {
  350                 ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT;
  351                 DEBUGOUT1("i40e_create_lan_hmc_object: returns error %d\n",
  352                           ret_code);
  353                 goto exit;
  354         }
  355 
  356         /* find sd index and limit */
  357         I40E_FIND_SD_INDEX_LIMIT(info->hmc_info, info->rsrc_type,
  358                                  info->start_idx, info->count,
  359                                  &sd_idx, &sd_lmt);
  360         if (sd_idx >= info->hmc_info->sd_table.sd_cnt ||
  361             sd_lmt > info->hmc_info->sd_table.sd_cnt) {
  362                         ret_code = I40E_ERR_INVALID_SD_INDEX;
  363                         goto exit;
  364         }
  365         /* find pd index */
  366         I40E_FIND_PD_INDEX_LIMIT(info->hmc_info, info->rsrc_type,
  367                                  info->start_idx, info->count, &pd_idx,
  368                                  &pd_lmt);
  369 
  370         /* This is to cover for cases where you may not want to have an SD with
  371          * the full 2M memory but something smaller. By not filling out any
  372          * size, the function will default the SD size to be 2M.
  373          */
  374         if (info->direct_mode_sz == 0)
  375                 sd_size = I40E_HMC_DIRECT_BP_SIZE;
  376         else
  377                 sd_size = info->direct_mode_sz;
  378 
  379         /* check if all the sds are valid. If not, allocate a page and
  380          * initialize it.
  381          */
  382         for (j = sd_idx; j < sd_lmt; j++) {
  383                 /* update the sd table entry */
  384                 ret_code = i40e_add_sd_table_entry(hw, info->hmc_info, j,
  385                                                    info->entry_type,
  386                                                    sd_size);
  387                 if (I40E_SUCCESS != ret_code)
  388                         goto exit_sd_error;
  389                 sd_entry = &info->hmc_info->sd_table.sd_entry[j];
  390                 if (I40E_SD_TYPE_PAGED == sd_entry->entry_type) {
  391                         /* check if all the pds in this sd are valid. If not,
  392                          * allocate a page and initialize it.
  393                          */
  394 
  395                         /* find pd_idx and pd_lmt in this sd */
  396                         pd_idx1 = max(pd_idx, (j * I40E_HMC_MAX_BP_COUNT));
  397                         pd_lmt1 = min(pd_lmt,
  398                                       ((j + 1) * I40E_HMC_MAX_BP_COUNT));
  399                         for (i = pd_idx1; i < pd_lmt1; i++) {
  400                                 /* update the pd table entry */
  401                                 ret_code = i40e_add_pd_table_entry(hw,
  402                                                                 info->hmc_info,
  403                                                                 i, NULL);
  404                                 if (I40E_SUCCESS != ret_code) {
  405                                         pd_error = TRUE;
  406                                         break;
  407                                 }
  408                         }
  409                         if (pd_error) {
  410                                 /* remove the backing pages from pd_idx1 to i */
  411                                 while (i && (i > pd_idx1)) {
  412                                         i40e_remove_pd_bp(hw, info->hmc_info,
  413                                                           (i - 1));
  414                                         i--;
  415                                 }
  416                         }
  417                 }
  418                 if (!sd_entry->valid) {
  419                         sd_entry->valid = TRUE;
  420                         switch (sd_entry->entry_type) {
  421                         case I40E_SD_TYPE_PAGED:
  422                                 I40E_SET_PF_SD_ENTRY(hw,
  423                                         sd_entry->u.pd_table.pd_page_addr.pa,
  424                                         j, sd_entry->entry_type);
  425                                 break;
  426                         case I40E_SD_TYPE_DIRECT:
  427                                 I40E_SET_PF_SD_ENTRY(hw, sd_entry->u.bp.addr.pa,
  428                                                      j, sd_entry->entry_type);
  429                                 break;
  430                         default:
  431                                 ret_code = I40E_ERR_INVALID_SD_TYPE;
  432                                 goto exit;
  433                         }
  434                 }
  435         }
  436         goto exit;
  437 
  438 exit_sd_error:
  439         /* cleanup for sd entries from j to sd_idx */
  440         while (j && (j > sd_idx)) {
  441                 sd_entry = &info->hmc_info->sd_table.sd_entry[j - 1];
  442                 switch (sd_entry->entry_type) {
  443                 case I40E_SD_TYPE_PAGED:
  444                         pd_idx1 = max(pd_idx,
  445                                       ((j - 1) * I40E_HMC_MAX_BP_COUNT));
  446                         pd_lmt1 = min(pd_lmt, (j * I40E_HMC_MAX_BP_COUNT));
  447                         for (i = pd_idx1; i < pd_lmt1; i++)
  448                                 i40e_remove_pd_bp(hw, info->hmc_info, i);
  449                         i40e_remove_pd_page(hw, info->hmc_info, (j - 1));
  450                         break;
  451                 case I40E_SD_TYPE_DIRECT:
  452                         i40e_remove_sd_bp(hw, info->hmc_info, (j - 1));
  453                         break;
  454                 default:
  455                         ret_code = I40E_ERR_INVALID_SD_TYPE;
  456                         break;
  457                 }
  458                 j--;
  459         }
  460 exit:
  461         return ret_code;
  462 }
  463 
  464 /**
  465  * i40e_configure_lan_hmc - prepare the HMC backing store
  466  * @hw: pointer to the hw structure
  467  * @model: the model for the layout of the SD/PD tables
  468  *
  469  * - This function will be called once per physical function initialization.
  470  * - This function will be called after i40e_init_lan_hmc() and before
  471  *   any LAN/FCoE HMC objects can be created.
  472  **/
  473 enum i40e_status_code i40e_configure_lan_hmc(struct i40e_hw *hw,
  474                                              enum i40e_hmc_model model)
  475 {
  476         struct i40e_hmc_lan_create_obj_info info;
  477         u8 hmc_fn_id = hw->hmc.hmc_fn_id;
  478         struct i40e_hmc_obj_info *obj;
  479         enum i40e_status_code ret_code = I40E_SUCCESS;
  480 
  481         /* Initialize part of the create object info struct */
  482         info.hmc_info = &hw->hmc;
  483         info.rsrc_type = I40E_HMC_LAN_FULL;
  484         info.start_idx = 0;
  485         info.direct_mode_sz = hw->hmc.hmc_obj[I40E_HMC_LAN_FULL].size;
  486 
  487         /* Build the SD entry for the LAN objects */
  488         switch (model) {
  489         case I40E_HMC_MODEL_DIRECT_PREFERRED:
  490         case I40E_HMC_MODEL_DIRECT_ONLY:
  491                 info.entry_type = I40E_SD_TYPE_DIRECT;
  492                 /* Make one big object, a single SD */
  493                 info.count = 1;
  494                 ret_code = i40e_create_lan_hmc_object(hw, &info);
  495                 if ((ret_code != I40E_SUCCESS) && (model == I40E_HMC_MODEL_DIRECT_PREFERRED))
  496                         goto try_type_paged;
  497                 else if (ret_code != I40E_SUCCESS)
  498                         goto configure_lan_hmc_out;
  499                 /* else clause falls through the break */
  500                 break;
  501         case I40E_HMC_MODEL_PAGED_ONLY:
  502 try_type_paged:
  503                 info.entry_type = I40E_SD_TYPE_PAGED;
  504                 /* Make one big object in the PD table */
  505                 info.count = 1;
  506                 ret_code = i40e_create_lan_hmc_object(hw, &info);
  507                 if (ret_code != I40E_SUCCESS)
  508                         goto configure_lan_hmc_out;
  509                 break;
  510         default:
  511                 /* unsupported type */
  512                 ret_code = I40E_ERR_INVALID_SD_TYPE;
  513                 DEBUGOUT1("i40e_configure_lan_hmc: Unknown SD type: %d\n",
  514                           ret_code);
  515                 goto configure_lan_hmc_out;
  516         }
  517 
  518         /* Configure and program the FPM registers so objects can be created */
  519 
  520         /* Tx contexts */
  521         obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_TX];
  522         wr32(hw, I40E_GLHMC_LANTXBASE(hmc_fn_id),
  523              (u32)((obj->base & I40E_GLHMC_LANTXBASE_FPMLANTXBASE_MASK) / 512));
  524         wr32(hw, I40E_GLHMC_LANTXCNT(hmc_fn_id), obj->cnt);
  525 
  526         /* Rx contexts */
  527         obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_RX];
  528         wr32(hw, I40E_GLHMC_LANRXBASE(hmc_fn_id),
  529              (u32)((obj->base & I40E_GLHMC_LANRXBASE_FPMLANRXBASE_MASK) / 512));
  530         wr32(hw, I40E_GLHMC_LANRXCNT(hmc_fn_id), obj->cnt);
  531 
  532         /* FCoE contexts */
  533         obj = &hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX];
  534         wr32(hw, I40E_GLHMC_FCOEDDPBASE(hmc_fn_id),
  535          (u32)((obj->base & I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_MASK) / 512));
  536         wr32(hw, I40E_GLHMC_FCOEDDPCNT(hmc_fn_id), obj->cnt);
  537 
  538         /* FCoE filters */
  539         obj = &hw->hmc.hmc_obj[I40E_HMC_FCOE_FILT];
  540         wr32(hw, I40E_GLHMC_FCOEFBASE(hmc_fn_id),
  541              (u32)((obj->base & I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_MASK) / 512));
  542         wr32(hw, I40E_GLHMC_FCOEFCNT(hmc_fn_id), obj->cnt);
  543 
  544 configure_lan_hmc_out:
  545         return ret_code;
  546 }
  547 
  548 /**
  549  * i40e_delete_lan_hmc_object - remove hmc objects
  550  * @hw: pointer to the HW structure
  551  * @info: pointer to i40e_hmc_delete_obj_info struct
  552  *
  553  * This will de-populate the SDs and PDs.  It frees
  554  * the memory for PDS and backing storage.  After this function is returned,
  555  * caller should deallocate memory allocated previously for
  556  * book-keeping information about PDs and backing storage.
  557  **/
  558 enum i40e_status_code i40e_delete_lan_hmc_object(struct i40e_hw *hw,
  559                                 struct i40e_hmc_lan_delete_obj_info *info)
  560 {
  561         enum i40e_status_code ret_code = I40E_SUCCESS;
  562         struct i40e_hmc_pd_table *pd_table;
  563         u32 pd_idx, pd_lmt, rel_pd_idx;
  564         u32 sd_idx, sd_lmt;
  565         u32 i, j;
  566 
  567         if (NULL == info) {
  568                 ret_code = I40E_ERR_BAD_PTR;
  569                 DEBUGOUT("i40e_delete_hmc_object: bad info ptr\n");
  570                 goto exit;
  571         }
  572         if (NULL == info->hmc_info) {
  573                 ret_code = I40E_ERR_BAD_PTR;
  574                 DEBUGOUT("i40e_delete_hmc_object: bad info->hmc_info ptr\n");
  575                 goto exit;
  576         }
  577         if (I40E_HMC_INFO_SIGNATURE != info->hmc_info->signature) {
  578                 ret_code = I40E_ERR_BAD_PTR;
  579                 DEBUGOUT("i40e_delete_hmc_object: bad hmc_info->signature\n");
  580                 goto exit;
  581         }
  582 
  583         if (NULL == info->hmc_info->sd_table.sd_entry) {
  584                 ret_code = I40E_ERR_BAD_PTR;
  585                 DEBUGOUT("i40e_delete_hmc_object: bad sd_entry\n");
  586                 goto exit;
  587         }
  588 
  589         if (NULL == info->hmc_info->hmc_obj) {
  590                 ret_code = I40E_ERR_BAD_PTR;
  591                 DEBUGOUT("i40e_delete_hmc_object: bad hmc_info->hmc_obj\n");
  592                 goto exit;
  593         }
  594         if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt) {
  595                 ret_code = I40E_ERR_INVALID_HMC_OBJ_INDEX;
  596                 DEBUGOUT1("i40e_delete_hmc_object: returns error %d\n",
  597                           ret_code);
  598                 goto exit;
  599         }
  600 
  601         if ((info->start_idx + info->count) >
  602             info->hmc_info->hmc_obj[info->rsrc_type].cnt) {
  603                 ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT;
  604                 DEBUGOUT1("i40e_delete_hmc_object: returns error %d\n",
  605                           ret_code);
  606                 goto exit;
  607         }
  608 
  609         I40E_FIND_PD_INDEX_LIMIT(info->hmc_info, info->rsrc_type,
  610                                  info->start_idx, info->count, &pd_idx,
  611                                  &pd_lmt);
  612 
  613         for (j = pd_idx; j < pd_lmt; j++) {
  614                 sd_idx = j / I40E_HMC_PD_CNT_IN_SD;
  615 
  616                 if (I40E_SD_TYPE_PAGED !=
  617                     info->hmc_info->sd_table.sd_entry[sd_idx].entry_type)
  618                         continue;
  619 
  620                 rel_pd_idx = j % I40E_HMC_PD_CNT_IN_SD;
  621 
  622                 pd_table =
  623                         &info->hmc_info->sd_table.sd_entry[sd_idx].u.pd_table;
  624                 if (pd_table->pd_entry[rel_pd_idx].valid) {
  625                         ret_code = i40e_remove_pd_bp(hw, info->hmc_info, j);
  626                         if (I40E_SUCCESS != ret_code)
  627                                 goto exit;
  628                 }
  629         }
  630 
  631         /* find sd index and limit */
  632         I40E_FIND_SD_INDEX_LIMIT(info->hmc_info, info->rsrc_type,
  633                                  info->start_idx, info->count,
  634                                  &sd_idx, &sd_lmt);
  635         if (sd_idx >= info->hmc_info->sd_table.sd_cnt ||
  636             sd_lmt > info->hmc_info->sd_table.sd_cnt) {
  637                 ret_code = I40E_ERR_INVALID_SD_INDEX;
  638                 goto exit;
  639         }
  640 
  641         for (i = sd_idx; i < sd_lmt; i++) {
  642                 if (!info->hmc_info->sd_table.sd_entry[i].valid)
  643                         continue;
  644                 switch (info->hmc_info->sd_table.sd_entry[i].entry_type) {
  645                 case I40E_SD_TYPE_DIRECT:
  646                         ret_code = i40e_remove_sd_bp(hw, info->hmc_info, i);
  647                         if (I40E_SUCCESS != ret_code)
  648                                 goto exit;
  649                         break;
  650                 case I40E_SD_TYPE_PAGED:
  651                         ret_code = i40e_remove_pd_page(hw, info->hmc_info, i);
  652                         if (I40E_SUCCESS != ret_code)
  653                                 goto exit;
  654                         break;
  655                 default:
  656                         break;
  657                 }
  658         }
  659 exit:
  660         return ret_code;
  661 }
  662 
  663 /**
  664  * i40e_shutdown_lan_hmc - Remove HMC backing store, free allocated memory
  665  * @hw: pointer to the hw structure
  666  *
  667  * This must be called by drivers as they are shutting down and being
  668  * removed from the OS.
  669  **/
  670 enum i40e_status_code i40e_shutdown_lan_hmc(struct i40e_hw *hw)
  671 {
  672         struct i40e_hmc_lan_delete_obj_info info;
  673         enum i40e_status_code ret_code;
  674 
  675         info.hmc_info = &hw->hmc;
  676         info.rsrc_type = I40E_HMC_LAN_FULL;
  677         info.start_idx = 0;
  678         info.count = 1;
  679 
  680         /* delete the object */
  681         ret_code = i40e_delete_lan_hmc_object(hw, &info);
  682 
  683         /* free the SD table entry for LAN */
  684         i40e_free_virt_mem(hw, &hw->hmc.sd_table.addr);
  685         hw->hmc.sd_table.sd_cnt = 0;
  686         hw->hmc.sd_table.sd_entry = NULL;
  687 
  688         /* free memory used for hmc_obj */
  689         i40e_free_virt_mem(hw, &hw->hmc.hmc_obj_virt_mem);
  690         hw->hmc.hmc_obj = NULL;
  691 
  692         return ret_code;
  693 }
  694 
  695 #define I40E_HMC_STORE(_struct, _ele)           \
  696         offsetof(struct _struct, _ele),         \
  697         FIELD_SIZEOF(struct _struct, _ele)
  698 
  699 struct i40e_context_ele {
  700         u16 offset;
  701         u16 size_of;
  702         u16 width;
  703         u16 lsb;
  704 };
  705 
  706 /* LAN Tx Queue Context */
  707 static struct i40e_context_ele i40e_hmc_txq_ce_info[] = {
  708                                              /* Field      Width    LSB */
  709         {I40E_HMC_STORE(i40e_hmc_obj_txq, head),           13,      0 },
  710         {I40E_HMC_STORE(i40e_hmc_obj_txq, new_context),     1,     30 },
  711         {I40E_HMC_STORE(i40e_hmc_obj_txq, base),           57,     32 },
  712         {I40E_HMC_STORE(i40e_hmc_obj_txq, fc_ena),          1,     89 },
  713         {I40E_HMC_STORE(i40e_hmc_obj_txq, timesync_ena),    1,     90 },
  714         {I40E_HMC_STORE(i40e_hmc_obj_txq, fd_ena),          1,     91 },
  715         {I40E_HMC_STORE(i40e_hmc_obj_txq, alt_vlan_ena),    1,     92 },
  716         {I40E_HMC_STORE(i40e_hmc_obj_txq, cpuid),           8,     96 },
  717 /* line 1 */
  718         {I40E_HMC_STORE(i40e_hmc_obj_txq, thead_wb),       13,  0 + 128 },
  719         {I40E_HMC_STORE(i40e_hmc_obj_txq, head_wb_ena),     1, 32 + 128 },
  720         {I40E_HMC_STORE(i40e_hmc_obj_txq, qlen),           13, 33 + 128 },
  721         {I40E_HMC_STORE(i40e_hmc_obj_txq, tphrdesc_ena),    1, 46 + 128 },
  722         {I40E_HMC_STORE(i40e_hmc_obj_txq, tphrpacket_ena),  1, 47 + 128 },
  723         {I40E_HMC_STORE(i40e_hmc_obj_txq, tphwdesc_ena),    1, 48 + 128 },
  724         {I40E_HMC_STORE(i40e_hmc_obj_txq, head_wb_addr),   64, 64 + 128 },
  725 /* line 7 */
  726         {I40E_HMC_STORE(i40e_hmc_obj_txq, crc),            32,  0 + (7 * 128) },
  727         {I40E_HMC_STORE(i40e_hmc_obj_txq, rdylist),        10, 84 + (7 * 128) },
  728         {I40E_HMC_STORE(i40e_hmc_obj_txq, rdylist_act),     1, 94 + (7 * 128) },
  729         { 0 }
  730 };
  731 
  732 /* LAN Rx Queue Context */
  733 static struct i40e_context_ele i40e_hmc_rxq_ce_info[] = {
  734                                          /* Field      Width    LSB */
  735         { I40E_HMC_STORE(i40e_hmc_obj_rxq, head),        13,    0   },
  736         { I40E_HMC_STORE(i40e_hmc_obj_rxq, cpuid),        8,    13  },
  737         { I40E_HMC_STORE(i40e_hmc_obj_rxq, base),        57,    32  },
  738         { I40E_HMC_STORE(i40e_hmc_obj_rxq, qlen),        13,    89  },
  739         { I40E_HMC_STORE(i40e_hmc_obj_rxq, dbuff),        7,    102 },
  740         { I40E_HMC_STORE(i40e_hmc_obj_rxq, hbuff),        5,    109 },
  741         { I40E_HMC_STORE(i40e_hmc_obj_rxq, dtype),        2,    114 },
  742         { I40E_HMC_STORE(i40e_hmc_obj_rxq, dsize),        1,    116 },
  743         { I40E_HMC_STORE(i40e_hmc_obj_rxq, crcstrip),     1,    117 },
  744         { I40E_HMC_STORE(i40e_hmc_obj_rxq, fc_ena),       1,    118 },
  745         { I40E_HMC_STORE(i40e_hmc_obj_rxq, l2tsel),       1,    119 },
  746         { I40E_HMC_STORE(i40e_hmc_obj_rxq, hsplit_0),     4,    120 },
  747         { I40E_HMC_STORE(i40e_hmc_obj_rxq, hsplit_1),     2,    124 },
  748         { I40E_HMC_STORE(i40e_hmc_obj_rxq, showiv),       1,    127 },
  749         { I40E_HMC_STORE(i40e_hmc_obj_rxq, rxmax),       14,    174 },
  750         { I40E_HMC_STORE(i40e_hmc_obj_rxq, tphrdesc_ena), 1,    193 },
  751         { I40E_HMC_STORE(i40e_hmc_obj_rxq, tphwdesc_ena), 1,    194 },
  752         { I40E_HMC_STORE(i40e_hmc_obj_rxq, tphdata_ena),  1,    195 },
  753         { I40E_HMC_STORE(i40e_hmc_obj_rxq, tphhead_ena),  1,    196 },
  754         { I40E_HMC_STORE(i40e_hmc_obj_rxq, lrxqthresh),   3,    198 },
  755         { I40E_HMC_STORE(i40e_hmc_obj_rxq, prefena),      1,    201 },
  756         { 0 }
  757 };
  758 
  759 /**
  760  * i40e_write_byte - replace HMC context byte
  761  * @hmc_bits: pointer to the HMC memory
  762  * @ce_info: a description of the struct to be read from
  763  * @src: the struct to be read from
  764  **/
  765 static void i40e_write_byte(u8 *hmc_bits,
  766                             struct i40e_context_ele *ce_info,
  767                             u8 *src)
  768 {
  769         u8 src_byte, dest_byte, mask;
  770         u8 *from, *dest;
  771         u16 shift_width;
  772 
  773         /* copy from the next struct field */
  774         from = src + ce_info->offset;
  775 
  776         /* prepare the bits and mask */
  777         shift_width = ce_info->lsb % 8;
  778         mask = (u8)(BIT(ce_info->width) - 1);
  779 
  780         src_byte = *from;
  781         src_byte &= mask;
  782 
  783         /* shift to correct alignment */
  784         mask <<= shift_width;
  785         src_byte <<= shift_width;
  786 
  787         /* get the current bits from the target bit string */
  788         dest = hmc_bits + (ce_info->lsb / 8);
  789 
  790         i40e_memcpy(&dest_byte, dest, sizeof(dest_byte), I40E_DMA_TO_NONDMA);
  791 
  792         dest_byte &= ~mask;     /* get the bits not changing */
  793         dest_byte |= src_byte;  /* add in the new bits */
  794 
  795         /* put it all back */
  796         i40e_memcpy(dest, &dest_byte, sizeof(dest_byte), I40E_NONDMA_TO_DMA);
  797 }
  798 
  799 /**
  800  * i40e_write_word - replace HMC context word
  801  * @hmc_bits: pointer to the HMC memory
  802  * @ce_info: a description of the struct to be read from
  803  * @src: the struct to be read from
  804  **/
  805 static void i40e_write_word(u8 *hmc_bits,
  806                             struct i40e_context_ele *ce_info,
  807                             u8 *src)
  808 {
  809         u16 src_word, mask;
  810         u8 *from, *dest;
  811         u16 shift_width;
  812         __le16 dest_word;
  813 
  814         /* copy from the next struct field */
  815         from = src + ce_info->offset;
  816 
  817         /* prepare the bits and mask */
  818         shift_width = ce_info->lsb % 8;
  819         mask = BIT(ce_info->width) - 1;
  820 
  821         /* don't swizzle the bits until after the mask because the mask bits
  822          * will be in a different bit position on big endian machines
  823          */
  824         src_word = *(u16 *)from;
  825         src_word &= mask;
  826 
  827         /* shift to correct alignment */
  828         mask <<= shift_width;
  829         src_word <<= shift_width;
  830 
  831         /* get the current bits from the target bit string */
  832         dest = hmc_bits + (ce_info->lsb / 8);
  833 
  834         i40e_memcpy(&dest_word, dest, sizeof(dest_word), I40E_DMA_TO_NONDMA);
  835 
  836         dest_word &= ~(CPU_TO_LE16(mask));      /* get the bits not changing */
  837         dest_word |= CPU_TO_LE16(src_word);     /* add in the new bits */
  838 
  839         /* put it all back */
  840         i40e_memcpy(dest, &dest_word, sizeof(dest_word), I40E_NONDMA_TO_DMA);
  841 }
  842 
  843 /**
  844  * i40e_write_dword - replace HMC context dword
  845  * @hmc_bits: pointer to the HMC memory
  846  * @ce_info: a description of the struct to be read from
  847  * @src: the struct to be read from
  848  **/
  849 static void i40e_write_dword(u8 *hmc_bits,
  850                              struct i40e_context_ele *ce_info,
  851                              u8 *src)
  852 {
  853         u32 src_dword, mask;
  854         u8 *from, *dest;
  855         u16 shift_width;
  856         __le32 dest_dword;
  857 
  858         /* copy from the next struct field */
  859         from = src + ce_info->offset;
  860 
  861         /* prepare the bits and mask */
  862         shift_width = ce_info->lsb % 8;
  863 
  864         /* if the field width is exactly 32 on an x86 machine, then the shift
  865          * operation will not work because the SHL instructions count is masked
  866          * to 5 bits so the shift will do nothing
  867          */
  868         if (ce_info->width < 32)
  869                 mask = BIT(ce_info->width) - 1;
  870         else
  871                 mask = ~(u32)0;
  872 
  873         /* don't swizzle the bits until after the mask because the mask bits
  874          * will be in a different bit position on big endian machines
  875          */
  876         src_dword = *(u32 *)from;
  877         src_dword &= mask;
  878 
  879         /* shift to correct alignment */
  880         mask <<= shift_width;
  881         src_dword <<= shift_width;
  882 
  883         /* get the current bits from the target bit string */
  884         dest = hmc_bits + (ce_info->lsb / 8);
  885 
  886         i40e_memcpy(&dest_dword, dest, sizeof(dest_dword), I40E_DMA_TO_NONDMA);
  887 
  888         dest_dword &= ~(CPU_TO_LE32(mask));     /* get the bits not changing */
  889         dest_dword |= CPU_TO_LE32(src_dword);   /* add in the new bits */
  890 
  891         /* put it all back */
  892         i40e_memcpy(dest, &dest_dword, sizeof(dest_dword), I40E_NONDMA_TO_DMA);
  893 }
  894 
  895 /**
  896  * i40e_write_qword - replace HMC context qword
  897  * @hmc_bits: pointer to the HMC memory
  898  * @ce_info: a description of the struct to be read from
  899  * @src: the struct to be read from
  900  **/
  901 static void i40e_write_qword(u8 *hmc_bits,
  902                              struct i40e_context_ele *ce_info,
  903                              u8 *src)
  904 {
  905         u64 src_qword, mask;
  906         u8 *from, *dest;
  907         u16 shift_width;
  908         __le64 dest_qword;
  909 
  910         /* copy from the next struct field */
  911         from = src + ce_info->offset;
  912 
  913         /* prepare the bits and mask */
  914         shift_width = ce_info->lsb % 8;
  915 
  916         /* if the field width is exactly 64 on an x86 machine, then the shift
  917          * operation will not work because the SHL instructions count is masked
  918          * to 6 bits so the shift will do nothing
  919          */
  920         if (ce_info->width < 64)
  921                 mask = BIT_ULL(ce_info->width) - 1;
  922         else
  923                 mask = ~(u64)0;
  924 
  925         /* don't swizzle the bits until after the mask because the mask bits
  926          * will be in a different bit position on big endian machines
  927          */
  928         src_qword = *(u64 *)from;
  929         src_qword &= mask;
  930 
  931         /* shift to correct alignment */
  932         mask <<= shift_width;
  933         src_qword <<= shift_width;
  934 
  935         /* get the current bits from the target bit string */
  936         dest = hmc_bits + (ce_info->lsb / 8);
  937 
  938         i40e_memcpy(&dest_qword, dest, sizeof(dest_qword), I40E_DMA_TO_NONDMA);
  939 
  940         dest_qword &= ~(CPU_TO_LE64(mask));     /* get the bits not changing */
  941         dest_qword |= CPU_TO_LE64(src_qword);   /* add in the new bits */
  942 
  943         /* put it all back */
  944         i40e_memcpy(dest, &dest_qword, sizeof(dest_qword), I40E_NONDMA_TO_DMA);
  945 }
  946 
  947 /**
  948  * i40e_read_byte - read HMC context byte into struct
  949  * @hmc_bits: pointer to the HMC memory
  950  * @ce_info: a description of the struct to be filled
  951  * @dest: the struct to be filled
  952  **/
  953 static void i40e_read_byte(u8 *hmc_bits,
  954                            struct i40e_context_ele *ce_info,
  955                            u8 *dest)
  956 {
  957         u8 dest_byte, mask;
  958         u8 *src, *target;
  959         u16 shift_width;
  960 
  961         /* prepare the bits and mask */
  962         shift_width = ce_info->lsb % 8;
  963         mask = (u8)(BIT(ce_info->width) - 1);
  964 
  965         /* shift to correct alignment */
  966         mask <<= shift_width;
  967 
  968         /* get the current bits from the src bit string */
  969         src = hmc_bits + (ce_info->lsb / 8);
  970 
  971         i40e_memcpy(&dest_byte, src, sizeof(dest_byte), I40E_DMA_TO_NONDMA);
  972 
  973         dest_byte &= ~(mask);
  974 
  975         dest_byte >>= shift_width;
  976 
  977         /* get the address from the struct field */
  978         target = dest + ce_info->offset;
  979 
  980         /* put it back in the struct */
  981         i40e_memcpy(target, &dest_byte, sizeof(dest_byte), I40E_NONDMA_TO_DMA);
  982 }
  983 
  984 /**
  985  * i40e_read_word - read HMC context word into struct
  986  * @hmc_bits: pointer to the HMC memory
  987  * @ce_info: a description of the struct to be filled
  988  * @dest: the struct to be filled
  989  **/
  990 static void i40e_read_word(u8 *hmc_bits,
  991                            struct i40e_context_ele *ce_info,
  992                            u8 *dest)
  993 {
  994         u16 dest_word, mask;
  995         u8 *src, *target;
  996         u16 shift_width;
  997         __le16 src_word;
  998 
  999         /* prepare the bits and mask */
 1000         shift_width = ce_info->lsb % 8;
 1001         mask = BIT(ce_info->width) - 1;
 1002 
 1003         /* shift to correct alignment */
 1004         mask <<= shift_width;
 1005 
 1006         /* get the current bits from the src bit string */
 1007         src = hmc_bits + (ce_info->lsb / 8);
 1008 
 1009         i40e_memcpy(&src_word, src, sizeof(src_word), I40E_DMA_TO_NONDMA);
 1010 
 1011         /* the data in the memory is stored as little endian so mask it
 1012          * correctly
 1013          */
 1014         src_word &= ~(CPU_TO_LE16(mask));
 1015 
 1016         /* get the data back into host order before shifting */
 1017         dest_word = LE16_TO_CPU(src_word);
 1018 
 1019         dest_word >>= shift_width;
 1020 
 1021         /* get the address from the struct field */
 1022         target = dest + ce_info->offset;
 1023 
 1024         /* put it back in the struct */
 1025         i40e_memcpy(target, &dest_word, sizeof(dest_word), I40E_NONDMA_TO_DMA);
 1026 }
 1027 
 1028 /**
 1029  * i40e_read_dword - read HMC context dword into struct
 1030  * @hmc_bits: pointer to the HMC memory
 1031  * @ce_info: a description of the struct to be filled
 1032  * @dest: the struct to be filled
 1033  **/
 1034 static void i40e_read_dword(u8 *hmc_bits,
 1035                             struct i40e_context_ele *ce_info,
 1036                             u8 *dest)
 1037 {
 1038         u32 dest_dword, mask;
 1039         u8 *src, *target;
 1040         u16 shift_width;
 1041         __le32 src_dword;
 1042 
 1043         /* prepare the bits and mask */
 1044         shift_width = ce_info->lsb % 8;
 1045 
 1046         /* if the field width is exactly 32 on an x86 machine, then the shift
 1047          * operation will not work because the SHL instructions count is masked
 1048          * to 5 bits so the shift will do nothing
 1049          */
 1050         if (ce_info->width < 32)
 1051                 mask = BIT(ce_info->width) - 1;
 1052         else
 1053                 mask = ~(u32)0;
 1054 
 1055         /* shift to correct alignment */
 1056         mask <<= shift_width;
 1057 
 1058         /* get the current bits from the src bit string */
 1059         src = hmc_bits + (ce_info->lsb / 8);
 1060 
 1061         i40e_memcpy(&src_dword, src, sizeof(src_dword), I40E_DMA_TO_NONDMA);
 1062 
 1063         /* the data in the memory is stored as little endian so mask it
 1064          * correctly
 1065          */
 1066         src_dword &= ~(CPU_TO_LE32(mask));
 1067 
 1068         /* get the data back into host order before shifting */
 1069         dest_dword = LE32_TO_CPU(src_dword);
 1070 
 1071         dest_dword >>= shift_width;
 1072 
 1073         /* get the address from the struct field */
 1074         target = dest + ce_info->offset;
 1075 
 1076         /* put it back in the struct */
 1077         i40e_memcpy(target, &dest_dword, sizeof(dest_dword),
 1078                     I40E_NONDMA_TO_DMA);
 1079 }
 1080 
 1081 /**
 1082  * i40e_read_qword - read HMC context qword into struct
 1083  * @hmc_bits: pointer to the HMC memory
 1084  * @ce_info: a description of the struct to be filled
 1085  * @dest: the struct to be filled
 1086  **/
 1087 static void i40e_read_qword(u8 *hmc_bits,
 1088                             struct i40e_context_ele *ce_info,
 1089                             u8 *dest)
 1090 {
 1091         u64 dest_qword, mask;
 1092         u8 *src, *target;
 1093         u16 shift_width;
 1094         __le64 src_qword;
 1095 
 1096         /* prepare the bits and mask */
 1097         shift_width = ce_info->lsb % 8;
 1098 
 1099         /* if the field width is exactly 64 on an x86 machine, then the shift
 1100          * operation will not work because the SHL instructions count is masked
 1101          * to 6 bits so the shift will do nothing
 1102          */
 1103         if (ce_info->width < 64)
 1104                 mask = BIT_ULL(ce_info->width) - 1;
 1105         else
 1106                 mask = ~(u64)0;
 1107 
 1108         /* shift to correct alignment */
 1109         mask <<= shift_width;
 1110 
 1111         /* get the current bits from the src bit string */
 1112         src = hmc_bits + (ce_info->lsb / 8);
 1113 
 1114         i40e_memcpy(&src_qword, src, sizeof(src_qword), I40E_DMA_TO_NONDMA);
 1115 
 1116         /* the data in the memory is stored as little endian so mask it
 1117          * correctly
 1118          */
 1119         src_qword &= ~(CPU_TO_LE64(mask));
 1120 
 1121         /* get the data back into host order before shifting */
 1122         dest_qword = LE64_TO_CPU(src_qword);
 1123 
 1124         dest_qword >>= shift_width;
 1125 
 1126         /* get the address from the struct field */
 1127         target = dest + ce_info->offset;
 1128 
 1129         /* put it back in the struct */
 1130         i40e_memcpy(target, &dest_qword, sizeof(dest_qword),
 1131                     I40E_NONDMA_TO_DMA);
 1132 }
 1133 
 1134 /**
 1135  * i40e_get_hmc_context - extract HMC context bits
 1136  * @context_bytes: pointer to the context bit array
 1137  * @ce_info: a description of the struct to be filled
 1138  * @dest: the struct to be filled
 1139  **/
 1140 static enum i40e_status_code i40e_get_hmc_context(u8 *context_bytes,
 1141                                         struct i40e_context_ele *ce_info,
 1142                                         u8 *dest)
 1143 {
 1144         int f;
 1145 
 1146         for (f = 0; ce_info[f].width != 0; f++) {
 1147                 switch (ce_info[f].size_of) {
 1148                 case 1:
 1149                         i40e_read_byte(context_bytes, &ce_info[f], dest);
 1150                         break;
 1151                 case 2:
 1152                         i40e_read_word(context_bytes, &ce_info[f], dest);
 1153                         break;
 1154                 case 4:
 1155                         i40e_read_dword(context_bytes, &ce_info[f], dest);
 1156                         break;
 1157                 case 8:
 1158                         i40e_read_qword(context_bytes, &ce_info[f], dest);
 1159                         break;
 1160                 default:
 1161                         /* nothing to do, just keep going */
 1162                         break;
 1163                 }
 1164         }
 1165 
 1166         return I40E_SUCCESS;
 1167 }
 1168 
 1169 /**
 1170  * i40e_clear_hmc_context - zero out the HMC context bits
 1171  * @hw:       the hardware struct
 1172  * @context_bytes: pointer to the context bit array (DMA memory)
 1173  * @hmc_type: the type of HMC resource
 1174  **/
 1175 static enum i40e_status_code i40e_clear_hmc_context(struct i40e_hw *hw,
 1176                                         u8 *context_bytes,
 1177                                         enum i40e_hmc_lan_rsrc_type hmc_type)
 1178 {
 1179         /* clean the bit array */
 1180         i40e_memset(context_bytes, 0, (u32)hw->hmc.hmc_obj[hmc_type].size,
 1181                     I40E_DMA_MEM);
 1182 
 1183         return I40E_SUCCESS;
 1184 }
 1185 
 1186 /**
 1187  * i40e_set_hmc_context - replace HMC context bits
 1188  * @context_bytes: pointer to the context bit array
 1189  * @ce_info:  a description of the struct to be filled
 1190  * @dest:     the struct to be filled
 1191  **/
 1192 static enum i40e_status_code i40e_set_hmc_context(u8 *context_bytes,
 1193                                         struct i40e_context_ele *ce_info,
 1194                                         u8 *dest)
 1195 {
 1196         int f;
 1197 
 1198         for (f = 0; ce_info[f].width != 0; f++) {
 1199 
 1200                 /* we have to deal with each element of the HMC using the
 1201                  * correct size so that we are correct regardless of the
 1202                  * endianness of the machine
 1203                  */
 1204                 switch (ce_info[f].size_of) {
 1205                 case 1:
 1206                         i40e_write_byte(context_bytes, &ce_info[f], dest);
 1207                         break;
 1208                 case 2:
 1209                         i40e_write_word(context_bytes, &ce_info[f], dest);
 1210                         break;
 1211                 case 4:
 1212                         i40e_write_dword(context_bytes, &ce_info[f], dest);
 1213                         break;
 1214                 case 8:
 1215                         i40e_write_qword(context_bytes, &ce_info[f], dest);
 1216                         break;
 1217                 }
 1218         }
 1219 
 1220         return I40E_SUCCESS;
 1221 }
 1222 
 1223 /**
 1224  * i40e_hmc_get_object_va - retrieves an object's virtual address
 1225  * @hw: pointer to the hw structure
 1226  * @object_base: pointer to u64 to get the va
 1227  * @rsrc_type: the hmc resource type
 1228  * @obj_idx: hmc object index
 1229  *
 1230  * This function retrieves the object's virtual address from the object
 1231  * base pointer.  This function is used for LAN Queue contexts.
 1232  **/
 1233 static
 1234 enum i40e_status_code i40e_hmc_get_object_va(struct i40e_hw *hw,
 1235                                         u8 **object_base,
 1236                                         enum i40e_hmc_lan_rsrc_type rsrc_type,
 1237                                         u32 obj_idx)
 1238 {
 1239         u32 obj_offset_in_sd, obj_offset_in_pd;
 1240         struct i40e_hmc_info     *hmc_info = &hw->hmc;
 1241         struct i40e_hmc_sd_entry *sd_entry;
 1242         struct i40e_hmc_pd_entry *pd_entry;
 1243         u32 pd_idx, pd_lmt, rel_pd_idx;
 1244         enum i40e_status_code ret_code = I40E_SUCCESS;
 1245         u64 obj_offset_in_fpm;
 1246         u32 sd_idx, sd_lmt;
 1247 
 1248         if (NULL == hmc_info->hmc_obj) {
 1249                 ret_code = I40E_ERR_BAD_PTR;
 1250                 DEBUGOUT("i40e_hmc_get_object_va: bad hmc_info->hmc_obj ptr\n");
 1251                 goto exit;
 1252         }
 1253         if (NULL == object_base) {
 1254                 ret_code = I40E_ERR_BAD_PTR;
 1255                 DEBUGOUT("i40e_hmc_get_object_va: bad object_base ptr\n");
 1256                 goto exit;
 1257         }
 1258         if (I40E_HMC_INFO_SIGNATURE != hmc_info->signature) {
 1259                 ret_code = I40E_ERR_BAD_PTR;
 1260                 DEBUGOUT("i40e_hmc_get_object_va: bad hmc_info->signature\n");
 1261                 goto exit;
 1262         }
 1263         if (obj_idx >= hmc_info->hmc_obj[rsrc_type].cnt) {
 1264                 DEBUGOUT1("i40e_hmc_get_object_va: returns error %d\n",
 1265                           ret_code);
 1266                 ret_code = I40E_ERR_INVALID_HMC_OBJ_INDEX;
 1267                 goto exit;
 1268         }
 1269         /* find sd index and limit */
 1270         I40E_FIND_SD_INDEX_LIMIT(hmc_info, rsrc_type, obj_idx, 1,
 1271                                  &sd_idx, &sd_lmt);
 1272 
 1273         sd_entry = &hmc_info->sd_table.sd_entry[sd_idx];
 1274         obj_offset_in_fpm = hmc_info->hmc_obj[rsrc_type].base +
 1275                             hmc_info->hmc_obj[rsrc_type].size * obj_idx;
 1276 
 1277         if (I40E_SD_TYPE_PAGED == sd_entry->entry_type) {
 1278                 I40E_FIND_PD_INDEX_LIMIT(hmc_info, rsrc_type, obj_idx, 1,
 1279                                          &pd_idx, &pd_lmt);
 1280                 rel_pd_idx = pd_idx % I40E_HMC_PD_CNT_IN_SD;
 1281                 pd_entry = &sd_entry->u.pd_table.pd_entry[rel_pd_idx];
 1282                 obj_offset_in_pd = (u32)(obj_offset_in_fpm %
 1283                                          I40E_HMC_PAGED_BP_SIZE);
 1284                 *object_base = (u8 *)pd_entry->bp.addr.va + obj_offset_in_pd;
 1285         } else {
 1286                 obj_offset_in_sd = (u32)(obj_offset_in_fpm %
 1287                                          I40E_HMC_DIRECT_BP_SIZE);
 1288                 *object_base = (u8 *)sd_entry->u.bp.addr.va + obj_offset_in_sd;
 1289         }
 1290 exit:
 1291         return ret_code;
 1292 }
 1293 
 1294 /**
 1295  * i40e_get_lan_tx_queue_context - return the HMC context for the queue
 1296  * @hw:    the hardware struct
 1297  * @queue: the queue we care about
 1298  * @s:     the struct to be filled
 1299  **/
 1300 enum i40e_status_code i40e_get_lan_tx_queue_context(struct i40e_hw *hw,
 1301                                                     u16 queue,
 1302                                                     struct i40e_hmc_obj_txq *s)
 1303 {
 1304         enum i40e_status_code err;
 1305         u8 *context_bytes;
 1306 
 1307         err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_TX, queue);
 1308         if (err < 0)
 1309                 return err;
 1310 
 1311         return i40e_get_hmc_context(context_bytes,
 1312                                     i40e_hmc_txq_ce_info, (u8 *)s);
 1313 }
 1314 
 1315 /**
 1316  * i40e_clear_lan_tx_queue_context - clear the HMC context for the queue
 1317  * @hw:    the hardware struct
 1318  * @queue: the queue we care about
 1319  **/
 1320 enum i40e_status_code i40e_clear_lan_tx_queue_context(struct i40e_hw *hw,
 1321                                                       u16 queue)
 1322 {
 1323         enum i40e_status_code err;
 1324         u8 *context_bytes;
 1325 
 1326         err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_TX, queue);
 1327         if (err < 0)
 1328                 return err;
 1329 
 1330         return i40e_clear_hmc_context(hw, context_bytes, I40E_HMC_LAN_TX);
 1331 }
 1332 
 1333 /**
 1334  * i40e_set_lan_tx_queue_context - set the HMC context for the queue
 1335  * @hw:    the hardware struct
 1336  * @queue: the queue we care about
 1337  * @s:     the struct to be filled
 1338  **/
 1339 enum i40e_status_code i40e_set_lan_tx_queue_context(struct i40e_hw *hw,
 1340                                                     u16 queue,
 1341                                                     struct i40e_hmc_obj_txq *s)
 1342 {
 1343         enum i40e_status_code err;
 1344         u8 *context_bytes;
 1345 
 1346         err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_TX, queue);
 1347         if (err < 0)
 1348                 return err;
 1349 
 1350         return i40e_set_hmc_context(context_bytes,
 1351                                     i40e_hmc_txq_ce_info, (u8 *)s);
 1352 }
 1353 
 1354 /**
 1355  * i40e_get_lan_rx_queue_context - return the HMC context for the queue
 1356  * @hw:    the hardware struct
 1357  * @queue: the queue we care about
 1358  * @s:     the struct to be filled
 1359  **/
 1360 enum i40e_status_code i40e_get_lan_rx_queue_context(struct i40e_hw *hw,
 1361                                                     u16 queue,
 1362                                                     struct i40e_hmc_obj_rxq *s)
 1363 {
 1364         enum i40e_status_code err;
 1365         u8 *context_bytes;
 1366 
 1367         err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_RX, queue);
 1368         if (err < 0)
 1369                 return err;
 1370 
 1371         return i40e_get_hmc_context(context_bytes,
 1372                                     i40e_hmc_rxq_ce_info, (u8 *)s);
 1373 }
 1374 
 1375 /**
 1376  * i40e_clear_lan_rx_queue_context - clear the HMC context for the queue
 1377  * @hw:    the hardware struct
 1378  * @queue: the queue we care about
 1379  **/
 1380 enum i40e_status_code i40e_clear_lan_rx_queue_context(struct i40e_hw *hw,
 1381                                                       u16 queue)
 1382 {
 1383         enum i40e_status_code err;
 1384         u8 *context_bytes;
 1385 
 1386         err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_RX, queue);
 1387         if (err < 0)
 1388                 return err;
 1389 
 1390         return i40e_clear_hmc_context(hw, context_bytes, I40E_HMC_LAN_RX);
 1391 }
 1392 
 1393 /**
 1394  * i40e_set_lan_rx_queue_context - set the HMC context for the queue
 1395  * @hw:    the hardware struct
 1396  * @queue: the queue we care about
 1397  * @s:     the struct to be filled
 1398  **/
 1399 enum i40e_status_code i40e_set_lan_rx_queue_context(struct i40e_hw *hw,
 1400                                                     u16 queue,
 1401                                                     struct i40e_hmc_obj_rxq *s)
 1402 {
 1403         enum i40e_status_code err;
 1404         u8 *context_bytes;
 1405 
 1406         err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_RX, queue);
 1407         if (err < 0)
 1408                 return err;
 1409 
 1410         return i40e_set_hmc_context(context_bytes,
 1411                                     i40e_hmc_rxq_ce_info, (u8 *)s);
 1412 }

Cache object: 1fc1b766c0dad3d7625947c7c77324f6


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.