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_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_status.h"
   38 #include "i40e_alloc.h"
   39 #include "i40e_hmc.h"
   40 #include "i40e_type.h"
   41 
   42 /**
   43  * i40e_add_sd_table_entry - Adds a segment descriptor to the table
   44  * @hw: pointer to our hw struct
   45  * @hmc_info: pointer to the HMC configuration information struct
   46  * @sd_index: segment descriptor index to manipulate
   47  * @type: what type of segment descriptor we're manipulating
   48  * @direct_mode_sz: size to alloc in direct mode
   49  **/
   50 enum i40e_status_code i40e_add_sd_table_entry(struct i40e_hw *hw,
   51                                               struct i40e_hmc_info *hmc_info,
   52                                               u32 sd_index,
   53                                               enum i40e_sd_entry_type type,
   54                                               u64 direct_mode_sz)
   55 {
   56         enum i40e_status_code ret_code = I40E_SUCCESS;
   57         struct i40e_hmc_sd_entry *sd_entry;
   58         enum   i40e_memory_type mem_type;
   59         bool dma_mem_alloc_done = FALSE;
   60         struct i40e_dma_mem mem;
   61         u64 alloc_len;
   62 
   63         if (NULL == hmc_info->sd_table.sd_entry) {
   64                 ret_code = I40E_ERR_BAD_PTR;
   65                 DEBUGOUT("i40e_add_sd_table_entry: bad sd_entry\n");
   66                 goto exit;
   67         }
   68 
   69         if (sd_index >= hmc_info->sd_table.sd_cnt) {
   70                 ret_code = I40E_ERR_INVALID_SD_INDEX;
   71                 DEBUGOUT("i40e_add_sd_table_entry: bad sd_index\n");
   72                 goto exit;
   73         }
   74 
   75         sd_entry = &hmc_info->sd_table.sd_entry[sd_index];
   76         if (!sd_entry->valid) {
   77                 if (I40E_SD_TYPE_PAGED == type) {
   78                         mem_type = i40e_mem_pd;
   79                         alloc_len = I40E_HMC_PAGED_BP_SIZE;
   80                 } else {
   81                         mem_type = i40e_mem_bp_jumbo;
   82                         alloc_len = direct_mode_sz;
   83                 }
   84 
   85                 /* allocate a 4K pd page or 2M backing page */
   86                 ret_code = i40e_allocate_dma_mem(hw, &mem, mem_type, alloc_len,
   87                                                  I40E_HMC_PD_BP_BUF_ALIGNMENT);
   88                 if (ret_code)
   89                         goto exit;
   90                 dma_mem_alloc_done = TRUE;
   91                 if (I40E_SD_TYPE_PAGED == type) {
   92                         ret_code = i40e_allocate_virt_mem(hw,
   93                                         &sd_entry->u.pd_table.pd_entry_virt_mem,
   94                                         sizeof(struct i40e_hmc_pd_entry) * 512);
   95                         if (ret_code)
   96                                 goto exit;
   97                         sd_entry->u.pd_table.pd_entry =
   98                                 (struct i40e_hmc_pd_entry *)
   99                                 sd_entry->u.pd_table.pd_entry_virt_mem.va;
  100                         i40e_memcpy(&sd_entry->u.pd_table.pd_page_addr,
  101                                     &mem, sizeof(struct i40e_dma_mem),
  102                                     I40E_NONDMA_TO_NONDMA);
  103                 } else {
  104                         i40e_memcpy(&sd_entry->u.bp.addr,
  105                                     &mem, sizeof(struct i40e_dma_mem),
  106                                     I40E_NONDMA_TO_NONDMA);
  107                         sd_entry->u.bp.sd_pd_index = sd_index;
  108                 }
  109                 /* initialize the sd entry */
  110                 hmc_info->sd_table.sd_entry[sd_index].entry_type = type;
  111 
  112                 /* increment the ref count */
  113                 I40E_INC_SD_REFCNT(&hmc_info->sd_table);
  114         }
  115         /* Increment backing page reference count */
  116         if (I40E_SD_TYPE_DIRECT == sd_entry->entry_type)
  117                 I40E_INC_BP_REFCNT(&sd_entry->u.bp);
  118 exit:
  119         if (I40E_SUCCESS != ret_code)
  120                 if (dma_mem_alloc_done)
  121                         i40e_free_dma_mem(hw, &mem);
  122 
  123         return ret_code;
  124 }
  125 
  126 /**
  127  * i40e_add_pd_table_entry - Adds page descriptor to the specified table
  128  * @hw: pointer to our HW structure
  129  * @hmc_info: pointer to the HMC configuration information structure
  130  * @pd_index: which page descriptor index to manipulate
  131  * @rsrc_pg: if not NULL, use preallocated page instead of allocating new one.
  132  *
  133  * This function:
  134  *      1. Initializes the pd entry
  135  *      2. Adds pd_entry in the pd_table
  136  *      3. Mark the entry valid in i40e_hmc_pd_entry structure
  137  *      4. Initializes the pd_entry's ref count to 1
  138  * assumptions:
  139  *      1. The memory for pd should be pinned down, physically contiguous and
  140  *         aligned on 4K boundary and zeroed memory.
  141  *      2. It should be 4K in size.
  142  **/
  143 enum i40e_status_code i40e_add_pd_table_entry(struct i40e_hw *hw,
  144                                               struct i40e_hmc_info *hmc_info,
  145                                               u32 pd_index,
  146                                               struct i40e_dma_mem *rsrc_pg)
  147 {
  148         enum i40e_status_code ret_code = I40E_SUCCESS;
  149         struct i40e_hmc_pd_table *pd_table;
  150         struct i40e_hmc_pd_entry *pd_entry;
  151         struct i40e_dma_mem mem;
  152         struct i40e_dma_mem *page = &mem;
  153         u32 sd_idx, rel_pd_idx;
  154         u64 *pd_addr;
  155         u64 page_desc;
  156 
  157         if (pd_index / I40E_HMC_PD_CNT_IN_SD >= hmc_info->sd_table.sd_cnt) {
  158                 ret_code = I40E_ERR_INVALID_PAGE_DESC_INDEX;
  159                 DEBUGOUT("i40e_add_pd_table_entry: bad pd_index\n");
  160                 goto exit;
  161         }
  162 
  163         /* find corresponding sd */
  164         sd_idx = (pd_index / I40E_HMC_PD_CNT_IN_SD);
  165         if (I40E_SD_TYPE_PAGED !=
  166             hmc_info->sd_table.sd_entry[sd_idx].entry_type)
  167                 goto exit;
  168 
  169         rel_pd_idx = (pd_index % I40E_HMC_PD_CNT_IN_SD);
  170         pd_table = &hmc_info->sd_table.sd_entry[sd_idx].u.pd_table;
  171         pd_entry = &pd_table->pd_entry[rel_pd_idx];
  172         if (!pd_entry->valid) {
  173                 if (rsrc_pg) {
  174                         pd_entry->rsrc_pg = TRUE;
  175                         page = rsrc_pg;
  176                 } else {
  177                         /* allocate a 4K backing page */
  178                         ret_code = i40e_allocate_dma_mem(hw, page, i40e_mem_bp,
  179                                                 I40E_HMC_PAGED_BP_SIZE,
  180                                                 I40E_HMC_PD_BP_BUF_ALIGNMENT);
  181                         if (ret_code)
  182                                 goto exit;
  183                         pd_entry->rsrc_pg = FALSE;
  184                 }
  185 
  186                 i40e_memcpy(&pd_entry->bp.addr, page,
  187                             sizeof(struct i40e_dma_mem), I40E_NONDMA_TO_NONDMA);
  188                 pd_entry->bp.sd_pd_index = pd_index;
  189                 pd_entry->bp.entry_type = I40E_SD_TYPE_PAGED;
  190                 /* Set page address and valid bit */
  191                 page_desc = page->pa | 0x1;
  192 
  193                 pd_addr = (u64 *)pd_table->pd_page_addr.va;
  194                 pd_addr += rel_pd_idx;
  195 
  196                 /* Add the backing page physical address in the pd entry */
  197                 i40e_memcpy(pd_addr, &page_desc, sizeof(u64),
  198                             I40E_NONDMA_TO_DMA);
  199 
  200                 pd_entry->sd_index = sd_idx;
  201                 pd_entry->valid = TRUE;
  202                 I40E_INC_PD_REFCNT(pd_table);
  203         }
  204         I40E_INC_BP_REFCNT(&pd_entry->bp);
  205 exit:
  206         return ret_code;
  207 }
  208 
  209 /**
  210  * i40e_remove_pd_bp - remove a backing page from a page descriptor
  211  * @hw: pointer to our HW structure
  212  * @hmc_info: pointer to the HMC configuration information structure
  213  * @idx: the page index
  214  *
  215  * This function:
  216  *      1. Marks the entry in pd tabe (for paged address mode) or in sd table
  217  *         (for direct address mode) invalid.
  218  *      2. Write to register PMPDINV to invalidate the backing page in FV cache
  219  *      3. Decrement the ref count for the pd _entry
  220  * assumptions:
  221  *      1. Caller can deallocate the memory used by backing storage after this
  222  *         function returns.
  223  **/
  224 enum i40e_status_code i40e_remove_pd_bp(struct i40e_hw *hw,
  225                                         struct i40e_hmc_info *hmc_info,
  226                                         u32 idx)
  227 {
  228         enum i40e_status_code ret_code = I40E_SUCCESS;
  229         struct i40e_hmc_pd_entry *pd_entry;
  230         struct i40e_hmc_pd_table *pd_table;
  231         struct i40e_hmc_sd_entry *sd_entry;
  232         u32 sd_idx, rel_pd_idx;
  233         u64 *pd_addr;
  234 
  235         /* calculate index */
  236         sd_idx = idx / I40E_HMC_PD_CNT_IN_SD;
  237         rel_pd_idx = idx % I40E_HMC_PD_CNT_IN_SD;
  238         if (sd_idx >= hmc_info->sd_table.sd_cnt) {
  239                 ret_code = I40E_ERR_INVALID_PAGE_DESC_INDEX;
  240                 DEBUGOUT("i40e_remove_pd_bp: bad idx\n");
  241                 goto exit;
  242         }
  243         sd_entry = &hmc_info->sd_table.sd_entry[sd_idx];
  244         if (I40E_SD_TYPE_PAGED != sd_entry->entry_type) {
  245                 ret_code = I40E_ERR_INVALID_SD_TYPE;
  246                 DEBUGOUT("i40e_remove_pd_bp: wrong sd_entry type\n");
  247                 goto exit;
  248         }
  249         /* get the entry and decrease its ref counter */
  250         pd_table = &hmc_info->sd_table.sd_entry[sd_idx].u.pd_table;
  251         pd_entry = &pd_table->pd_entry[rel_pd_idx];
  252         I40E_DEC_BP_REFCNT(&pd_entry->bp);
  253         if (pd_entry->bp.ref_cnt)
  254                 goto exit;
  255 
  256         /* mark the entry invalid */
  257         pd_entry->valid = FALSE;
  258         I40E_DEC_PD_REFCNT(pd_table);
  259         pd_addr = (u64 *)pd_table->pd_page_addr.va;
  260         pd_addr += rel_pd_idx;
  261         i40e_memset(pd_addr, 0, sizeof(u64), I40E_DMA_MEM);
  262         I40E_INVALIDATE_PF_HMC_PD(hw, sd_idx, idx);
  263 
  264         /* free memory here */
  265         if (!pd_entry->rsrc_pg)
  266                 ret_code = i40e_free_dma_mem(hw, &(pd_entry->bp.addr));
  267         if (I40E_SUCCESS != ret_code)
  268                 goto exit;
  269         if (!pd_table->ref_cnt)
  270                 i40e_free_virt_mem(hw, &pd_table->pd_entry_virt_mem);
  271 exit:
  272         return ret_code;
  273 }
  274 
  275 /**
  276  * i40e_prep_remove_sd_bp - Prepares to remove a backing page from a sd entry
  277  * @hmc_info: pointer to the HMC configuration information structure
  278  * @idx: the page index
  279  **/
  280 enum i40e_status_code i40e_prep_remove_sd_bp(struct i40e_hmc_info *hmc_info,
  281                                              u32 idx)
  282 {
  283         enum i40e_status_code ret_code = I40E_SUCCESS;
  284         struct i40e_hmc_sd_entry *sd_entry;
  285 
  286         /* get the entry and decrease its ref counter */
  287         sd_entry = &hmc_info->sd_table.sd_entry[idx];
  288         I40E_DEC_BP_REFCNT(&sd_entry->u.bp);
  289         if (sd_entry->u.bp.ref_cnt) {
  290                 ret_code = I40E_ERR_NOT_READY;
  291                 goto exit;
  292         }
  293         I40E_DEC_SD_REFCNT(&hmc_info->sd_table);
  294 
  295         /* mark the entry invalid */
  296         sd_entry->valid = FALSE;
  297 exit:
  298         return ret_code;
  299 }
  300 
  301 /**
  302  * i40e_remove_sd_bp_new - Removes a backing page from a segment descriptor
  303  * @hw: pointer to our hw struct
  304  * @hmc_info: pointer to the HMC configuration information structure
  305  * @idx: the page index
  306  * @is_pf: used to distinguish between VF and PF
  307  **/
  308 enum i40e_status_code i40e_remove_sd_bp_new(struct i40e_hw *hw,
  309                                             struct i40e_hmc_info *hmc_info,
  310                                             u32 idx, bool is_pf)
  311 {
  312         struct i40e_hmc_sd_entry *sd_entry;
  313 
  314         if (!is_pf)
  315                 return I40E_NOT_SUPPORTED;
  316 
  317         /* get the entry and decrease its ref counter */
  318         sd_entry = &hmc_info->sd_table.sd_entry[idx];
  319         I40E_CLEAR_PF_SD_ENTRY(hw, idx, I40E_SD_TYPE_DIRECT);
  320 
  321         return i40e_free_dma_mem(hw, &(sd_entry->u.bp.addr));
  322 }
  323 
  324 /**
  325  * i40e_prep_remove_pd_page - Prepares to remove a PD page from sd entry.
  326  * @hmc_info: pointer to the HMC configuration information structure
  327  * @idx: segment descriptor index to find the relevant page descriptor
  328  **/
  329 enum i40e_status_code i40e_prep_remove_pd_page(struct i40e_hmc_info *hmc_info,
  330                                                u32 idx)
  331 {
  332         enum i40e_status_code ret_code = I40E_SUCCESS;
  333         struct i40e_hmc_sd_entry *sd_entry;
  334 
  335         sd_entry = &hmc_info->sd_table.sd_entry[idx];
  336 
  337         if (sd_entry->u.pd_table.ref_cnt) {
  338                 ret_code = I40E_ERR_NOT_READY;
  339                 goto exit;
  340         }
  341 
  342         /* mark the entry invalid */
  343         sd_entry->valid = FALSE;
  344 
  345         I40E_DEC_SD_REFCNT(&hmc_info->sd_table);
  346 exit:
  347         return ret_code;
  348 }
  349 
  350 /**
  351  * i40e_remove_pd_page_new - Removes a PD page from sd entry.
  352  * @hw: pointer to our hw struct
  353  * @hmc_info: pointer to the HMC configuration information structure
  354  * @idx: segment descriptor index to find the relevant page descriptor
  355  * @is_pf: used to distinguish between VF and PF
  356  **/
  357 enum i40e_status_code i40e_remove_pd_page_new(struct i40e_hw *hw,
  358                                               struct i40e_hmc_info *hmc_info,
  359                                               u32 idx, bool is_pf)
  360 {
  361         struct i40e_hmc_sd_entry *sd_entry;
  362 
  363         if (!is_pf)
  364                 return I40E_NOT_SUPPORTED;
  365 
  366         sd_entry = &hmc_info->sd_table.sd_entry[idx];
  367         I40E_CLEAR_PF_SD_ENTRY(hw, idx, I40E_SD_TYPE_PAGED);
  368 
  369         return i40e_free_dma_mem(hw, &(sd_entry->u.pd_table.pd_page_addr));
  370 }

Cache object: d7aa432ef2128dc7e066d594a524ddd6


[ 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.