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/ice/ice_vlan_mode.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 /* SPDX-License-Identifier: BSD-3-Clause */
    2 /*  Copyright (c) 2021, Intel Corporation
    3  *  All rights reserved.
    4  *
    5  *  Redistribution and use in source and binary forms, with or without
    6  *  modification, are permitted provided that the following conditions are met:
    7  *
    8  *   1. Redistributions of source code must retain the above copyright notice,
    9  *      this list of conditions and the following disclaimer.
   10  *
   11  *   2. Redistributions in binary form must reproduce the above copyright
   12  *      notice, this list of conditions and the following disclaimer in the
   13  *      documentation and/or other materials provided with the distribution.
   14  *
   15  *   3. Neither the name of the Intel Corporation nor the names of its
   16  *      contributors may be used to endorse or promote products derived from
   17  *      this software without specific prior written permission.
   18  *
   19  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   20  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   23  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  *  POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 /*$FreeBSD$*/
   32 
   33 #include "ice_common.h"
   34 
   35 /**
   36  * ice_pkg_get_supported_vlan_mode - chk if DDP supports Double VLAN mode (DVM)
   37  * @hw: pointer to the HW struct
   38  * @dvm: output variable to determine if DDP supports DVM(true) or SVM(false)
   39  */
   40 static enum ice_status
   41 ice_pkg_get_supported_vlan_mode(struct ice_hw *hw, bool *dvm)
   42 {
   43         u16 meta_init_size = sizeof(struct ice_meta_init_section);
   44         struct ice_meta_init_section *sect;
   45         struct ice_buf_build *bld;
   46         enum ice_status status;
   47 
   48         /* if anything fails, we assume there is no DVM support */
   49         *dvm = false;
   50 
   51         bld = ice_pkg_buf_alloc_single_section(hw,
   52                                                ICE_SID_RXPARSER_METADATA_INIT,
   53                                                meta_init_size, (void **)&sect);
   54         if (!bld)
   55                 return ICE_ERR_NO_MEMORY;
   56 
   57         /* only need to read a single section */
   58         sect->count = CPU_TO_LE16(1);
   59         sect->offset = CPU_TO_LE16(ICE_META_VLAN_MODE_ENTRY);
   60 
   61         status = ice_aq_upload_section(hw,
   62                                        (struct ice_buf_hdr *)ice_pkg_buf(bld),
   63                                        ICE_PKG_BUF_SIZE, NULL);
   64         if (!status) {
   65                 ice_declare_bitmap(entry, ICE_META_INIT_BITS);
   66                 u32 arr[ICE_META_INIT_DW_CNT];
   67                 u16 i;
   68 
   69                 /* convert to host bitmap format */
   70                 for (i = 0; i < ICE_META_INIT_DW_CNT; i++)
   71                         arr[i] = LE32_TO_CPU(sect->entry[0].bm[i]);
   72 
   73                 ice_bitmap_from_array32(entry, arr, (u16)ICE_META_INIT_BITS);
   74 
   75                 /* check if DVM is supported */
   76                 *dvm = ice_is_bit_set(entry, ICE_META_VLAN_MODE_BIT);
   77         }
   78 
   79         ice_pkg_buf_free(hw, bld);
   80 
   81         return status;
   82 }
   83 
   84 /**
   85  * ice_aq_get_vlan_mode - get the VLAN mode of the device
   86  * @hw: pointer to the HW structure
   87  * @get_params: structure FW fills in based on the current VLAN mode config
   88  *
   89  * Get VLAN Mode Parameters (0x020D)
   90  */
   91 static enum ice_status
   92 ice_aq_get_vlan_mode(struct ice_hw *hw,
   93                      struct ice_aqc_get_vlan_mode *get_params)
   94 {
   95         struct ice_aq_desc desc;
   96 
   97         if (!get_params)
   98                 return ICE_ERR_PARAM;
   99 
  100         ice_fill_dflt_direct_cmd_desc(&desc,
  101                                       ice_aqc_opc_get_vlan_mode_parameters);
  102 
  103         return ice_aq_send_cmd(hw, &desc, get_params, sizeof(*get_params),
  104                                NULL);
  105 }
  106 
  107 /**
  108  * ice_aq_is_dvm_ena - query FW to check if double VLAN mode is enabled
  109  * @hw: pointer to the HW structure
  110  *
  111  * Returns true if the hardware/firmware is configured in double VLAN mode,
  112  * else return false signaling that the hardware/firmware is configured in
  113  * single VLAN mode.
  114  *
  115  * Also, return false if this call fails for any reason (i.e. firmware doesn't
  116  * support this AQ call).
  117  */
  118 static bool ice_aq_is_dvm_ena(struct ice_hw *hw)
  119 {
  120         struct ice_aqc_get_vlan_mode get_params = { 0 };
  121         enum ice_status status;
  122 
  123         status = ice_aq_get_vlan_mode(hw, &get_params);
  124         if (status) {
  125                 ice_debug(hw, ICE_DBG_AQ, "Failed to get VLAN mode, status %d\n",
  126                           status);
  127                 return false;
  128         }
  129 
  130         return (get_params.vlan_mode & ICE_AQ_VLAN_MODE_DVM_ENA);
  131 }
  132 
  133 /**
  134  * ice_is_dvm_ena - check if double VLAN mode is enabled
  135  * @hw: pointer to the HW structure
  136  *
  137  * The device is configured in single or double VLAN mode on initialization and
  138  * this cannot be dynamically changed during runtime. Based on this there is no
  139  * need to make an AQ call every time the driver needs to know the VLAN mode.
  140  * Instead, use the cached VLAN mode.
  141  */
  142 bool ice_is_dvm_ena(struct ice_hw *hw)
  143 {
  144         return hw->dvm_ena;
  145 }
  146 
  147 /**
  148  * ice_cache_vlan_mode - cache VLAN mode after DDP is downloaded
  149  * @hw: pointer to the HW structure
  150  *
  151  * This is only called after downloading the DDP and after the global
  152  * configuration lock has been released because all ports on a device need to
  153  * cache the VLAN mode.
  154  */
  155 static void ice_cache_vlan_mode(struct ice_hw *hw)
  156 {
  157         hw->dvm_ena = ice_aq_is_dvm_ena(hw) ? true : false;
  158 }
  159 
  160 /**
  161  * ice_pkg_supports_dvm - find out if DDP supports DVM
  162  * @hw: pointer to the HW structure
  163  */
  164 static bool ice_pkg_supports_dvm(struct ice_hw *hw)
  165 {
  166         enum ice_status status;
  167         bool pkg_supports_dvm;
  168 
  169         status = ice_pkg_get_supported_vlan_mode(hw, &pkg_supports_dvm);
  170         if (status) {
  171                 ice_debug(hw, ICE_DBG_PKG, "Failed to get supported VLAN mode, status %d\n",
  172                           status);
  173                 return false;
  174         }
  175 
  176         return pkg_supports_dvm;
  177 }
  178 
  179 /**
  180  * ice_fw_supports_dvm - find out if FW supports DVM
  181  * @hw: pointer to the HW structure
  182  */
  183 static bool ice_fw_supports_dvm(struct ice_hw *hw)
  184 {
  185         struct ice_aqc_get_vlan_mode get_vlan_mode = { 0 };
  186         enum ice_status status;
  187 
  188         /* If firmware returns success, then it supports DVM, else it only
  189          * supports SVM
  190          */
  191         status = ice_aq_get_vlan_mode(hw, &get_vlan_mode);
  192         if (status) {
  193                 ice_debug(hw, ICE_DBG_NVM, "Failed to get VLAN mode, status %d\n",
  194                           status);
  195                 return false;
  196         }
  197 
  198         return true;
  199 }
  200 
  201 /**
  202  * ice_is_dvm_supported - check if Double VLAN Mode is supported
  203  * @hw: pointer to the hardware structure
  204  *
  205  * Returns true if Double VLAN Mode (DVM) is supported and false if only Single
  206  * VLAN Mode (SVM) is supported. In order for DVM to be supported the DDP and
  207  * firmware must support it, otherwise only SVM is supported. This function
  208  * should only be called while the global config lock is held and after the
  209  * package has been successfully downloaded.
  210  */
  211 static bool ice_is_dvm_supported(struct ice_hw *hw)
  212 {
  213         if (!ice_pkg_supports_dvm(hw)) {
  214                 ice_debug(hw, ICE_DBG_PKG, "DDP doesn't support DVM\n");
  215                 return false;
  216         }
  217 
  218         if (!ice_fw_supports_dvm(hw)) {
  219                 ice_debug(hw, ICE_DBG_PKG, "FW doesn't support DVM\n");
  220                 return false;
  221         }
  222 
  223         return true;
  224 }
  225 
  226 /**
  227  * ice_aq_set_vlan_mode - set the VLAN mode of the device
  228  * @hw: pointer to the HW structure
  229  * @set_params: requested VLAN mode configuration
  230  *
  231  * Set VLAN Mode Parameters (0x020C)
  232  */
  233 static enum ice_status
  234 ice_aq_set_vlan_mode(struct ice_hw *hw,
  235                      struct ice_aqc_set_vlan_mode *set_params)
  236 {
  237         u8 rdma_packet, mng_vlan_prot_id;
  238         struct ice_aq_desc desc;
  239 
  240         if (!set_params)
  241                 return ICE_ERR_PARAM;
  242 
  243         if (set_params->l2tag_prio_tagging > ICE_AQ_VLAN_PRIO_TAG_MAX)
  244                 return ICE_ERR_PARAM;
  245 
  246         rdma_packet = set_params->rdma_packet;
  247         if (rdma_packet != ICE_AQ_SVM_VLAN_RDMA_PKT_FLAG_SETTING &&
  248             rdma_packet != ICE_AQ_DVM_VLAN_RDMA_PKT_FLAG_SETTING)
  249                 return ICE_ERR_PARAM;
  250 
  251         mng_vlan_prot_id = set_params->mng_vlan_prot_id;
  252         if (mng_vlan_prot_id != ICE_AQ_VLAN_MNG_PROTOCOL_ID_OUTER &&
  253             mng_vlan_prot_id != ICE_AQ_VLAN_MNG_PROTOCOL_ID_INNER)
  254                 return ICE_ERR_PARAM;
  255 
  256         ice_fill_dflt_direct_cmd_desc(&desc,
  257                                       ice_aqc_opc_set_vlan_mode_parameters);
  258         desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
  259 
  260         return ice_aq_send_cmd(hw, &desc, set_params, sizeof(*set_params),
  261                                NULL);
  262 }
  263 
  264 /**
  265  * ice_set_svm - set single VLAN mode
  266  * @hw: pointer to the HW structure
  267  */
  268 static enum ice_status ice_set_svm(struct ice_hw *hw)
  269 {
  270         struct ice_aqc_set_vlan_mode *set_params;
  271         enum ice_status status;
  272 
  273         status = ice_aq_set_port_params(hw->port_info, 0, false, false, false, NULL);
  274         if (status) {
  275                 ice_debug(hw, ICE_DBG_INIT, "Failed to set port parameters for single VLAN mode\n");
  276                 return status;
  277         }
  278 
  279         set_params = (struct ice_aqc_set_vlan_mode *)
  280                 ice_malloc(hw, sizeof(*set_params));
  281         if (!set_params)
  282                 return ICE_ERR_NO_MEMORY;
  283 
  284         /* default configuration for SVM configurations */
  285         set_params->l2tag_prio_tagging = ICE_AQ_VLAN_PRIO_TAG_INNER_CTAG;
  286         set_params->rdma_packet = ICE_AQ_SVM_VLAN_RDMA_PKT_FLAG_SETTING;
  287         set_params->mng_vlan_prot_id = ICE_AQ_VLAN_MNG_PROTOCOL_ID_INNER;
  288 
  289         status = ice_aq_set_vlan_mode(hw, set_params);
  290         if (status)
  291                 ice_debug(hw, ICE_DBG_INIT, "Failed to configure port in single VLAN mode\n");
  292 
  293         ice_free(hw, set_params);
  294         return status;
  295 }
  296 
  297 /**
  298  * ice_set_vlan_mode
  299  * @hw: pointer to the HW structure
  300  */
  301 enum ice_status ice_set_vlan_mode(struct ice_hw *hw)
  302 {
  303         if (!ice_is_dvm_supported(hw))
  304                 return ICE_SUCCESS;
  305 
  306         return ice_set_svm(hw);
  307 }
  308 
  309 /**
  310  * ice_post_pkg_dwnld_vlan_mode_cfg - configure VLAN mode after DDP download
  311  * @hw: pointer to the HW structure
  312  *
  313  * This function is meant to configure any VLAN mode specific functionality
  314  * after the global configuration lock has been released and the DDP has been
  315  * downloaded.
  316  *
  317  * Since only one PF downloads the DDP and configures the VLAN mode there needs
  318  * to be a way to configure the other PFs after the DDP has been downloaded and
  319  * the global configuration lock has been released. All such code should go in
  320  * this function.
  321  */
  322 void ice_post_pkg_dwnld_vlan_mode_cfg(struct ice_hw *hw)
  323 {
  324         ice_cache_vlan_mode(hw);
  325 }

Cache object: b2c4d6c680651a804436fdf4c79b56b2


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