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/contrib/dev/iwlwifi/fw/rs.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: GPL-2.0 OR BSD-3-Clause
    2 /*
    3  * Copyright (C) 2021 Intel Corporation
    4  */
    5 
    6 #include <net/mac80211.h>
    7 #include "fw/api/rs.h"
    8 #include "iwl-drv.h"
    9 #include "iwl-config.h"
   10 
   11 #define IWL_DECLARE_RATE_INFO(r) \
   12         [IWL_RATE_##r##M_INDEX] = IWL_RATE_##r##M_PLCP
   13 
   14 /*
   15  * Translate from fw_rate_index (IWL_RATE_XXM_INDEX) to PLCP
   16  * */
   17 static const u8 fw_rate_idx_to_plcp[IWL_RATE_COUNT] = {
   18         IWL_DECLARE_RATE_INFO(1),
   19         IWL_DECLARE_RATE_INFO(2),
   20         IWL_DECLARE_RATE_INFO(5),
   21         IWL_DECLARE_RATE_INFO(11),
   22         IWL_DECLARE_RATE_INFO(6),
   23         IWL_DECLARE_RATE_INFO(9),
   24         IWL_DECLARE_RATE_INFO(12),
   25         IWL_DECLARE_RATE_INFO(18),
   26         IWL_DECLARE_RATE_INFO(24),
   27         IWL_DECLARE_RATE_INFO(36),
   28         IWL_DECLARE_RATE_INFO(48),
   29         IWL_DECLARE_RATE_INFO(54),
   30 };
   31 
   32 /* mbps, mcs */
   33 static const struct iwl_rate_mcs_info rate_mcs[IWL_RATE_COUNT] = {
   34         {  "1", "BPSK DSSS"},
   35         {  "2", "QPSK DSSS"},
   36         {"5.5", "BPSK CCK"},
   37         { "11", "QPSK CCK"},
   38         {  "6", "BPSK 1/2"},
   39         {  "9", "BPSK 1/2"},
   40         { "12", "QPSK 1/2"},
   41         { "18", "QPSK 3/4"},
   42         { "24", "16QAM 1/2"},
   43         { "36", "16QAM 3/4"},
   44         { "48", "64QAM 2/3"},
   45         { "54", "64QAM 3/4"},
   46         { "60", "64QAM 5/6"},
   47 };
   48 
   49 static const char * const ant_name[] = {
   50         [ANT_NONE] = "None",
   51         [ANT_A]    = "A",
   52         [ANT_B]    = "B",
   53         [ANT_AB]   = "AB",
   54 };
   55 
   56 static const char * const pretty_bw[] = {
   57         "20Mhz",
   58         "40Mhz",
   59         "80Mhz",
   60         "160 Mhz",
   61         "320Mhz",
   62 };
   63 
   64 u8 iwl_fw_rate_idx_to_plcp(int idx)
   65 {
   66         return fw_rate_idx_to_plcp[idx];
   67 }
   68 IWL_EXPORT_SYMBOL(iwl_fw_rate_idx_to_plcp);
   69 
   70 const struct iwl_rate_mcs_info *iwl_rate_mcs(int idx)
   71 {
   72         return &rate_mcs[idx];
   73 }
   74 IWL_EXPORT_SYMBOL(iwl_rate_mcs);
   75 
   76 const char *iwl_rs_pretty_ant(u8 ant)
   77 {
   78         if (ant >= ARRAY_SIZE(ant_name))
   79                 return "UNKNOWN";
   80 
   81         return ant_name[ant];
   82 }
   83 IWL_EXPORT_SYMBOL(iwl_rs_pretty_ant);
   84 
   85 const char *iwl_rs_pretty_bw(int bw)
   86 {
   87         if (bw >= ARRAY_SIZE(pretty_bw))
   88                 return "unknown bw";
   89 
   90         return pretty_bw[bw];
   91 }
   92 IWL_EXPORT_SYMBOL(iwl_rs_pretty_bw);
   93 
   94 static u32 iwl_legacy_rate_to_fw_idx(u32 rate_n_flags)
   95 {
   96         int rate = rate_n_flags & RATE_LEGACY_RATE_MSK_V1;
   97         int idx;
   98         bool ofdm = !(rate_n_flags & RATE_MCS_CCK_MSK_V1);
   99         int offset = ofdm ? IWL_FIRST_OFDM_RATE : 0;
  100         int last = ofdm ? IWL_RATE_COUNT_LEGACY : IWL_FIRST_OFDM_RATE;
  101 
  102         for (idx = offset; idx < last; idx++)
  103                 if (iwl_fw_rate_idx_to_plcp(idx) == rate)
  104                         return idx - offset;
  105         return IWL_RATE_INVALID;
  106 }
  107 
  108 u32 iwl_new_rate_from_v1(u32 rate_v1)
  109 {
  110         u32 rate_v2 = 0;
  111         u32 dup = 0;
  112 
  113         if (rate_v1 == 0)
  114                 return rate_v1;
  115         /* convert rate */
  116         if (rate_v1 & RATE_MCS_HT_MSK_V1) {
  117                 u32 nss = 0;
  118 
  119                 rate_v2 |= RATE_MCS_HT_MSK;
  120                 rate_v2 |=
  121                         rate_v1 & RATE_HT_MCS_RATE_CODE_MSK_V1;
  122                 nss = (rate_v1 & RATE_HT_MCS_MIMO2_MSK) >>
  123                         RATE_HT_MCS_NSS_POS_V1;
  124                 rate_v2 |= nss << RATE_MCS_NSS_POS;
  125         } else if (rate_v1 & RATE_MCS_VHT_MSK_V1 ||
  126                    rate_v1 & RATE_MCS_HE_MSK_V1) {
  127                 rate_v2 |= rate_v1 & RATE_VHT_MCS_RATE_CODE_MSK;
  128 
  129                 rate_v2 |= rate_v1 & RATE_VHT_MCS_MIMO2_MSK;
  130 
  131                 if (rate_v1 & RATE_MCS_HE_MSK_V1) {
  132                         u32 he_type_bits = rate_v1 & RATE_MCS_HE_TYPE_MSK_V1;
  133                         u32 he_type = he_type_bits >> RATE_MCS_HE_TYPE_POS_V1;
  134                         u32 he_106t = (rate_v1 & RATE_MCS_HE_106T_MSK_V1) >>
  135                                 RATE_MCS_HE_106T_POS_V1;
  136                         u32 he_gi_ltf = (rate_v1 & RATE_MCS_HE_GI_LTF_MSK_V1) >>
  137                                 RATE_MCS_HE_GI_LTF_POS;
  138 
  139                         if ((he_type_bits == RATE_MCS_HE_TYPE_SU ||
  140                              he_type_bits == RATE_MCS_HE_TYPE_EXT_SU) &&
  141                             he_gi_ltf == RATE_MCS_HE_SU_4_LTF)
  142                                 /* the new rate have an additional bit to
  143                                  * represent the value 4 rather then using SGI
  144                                  * bit for this purpose - as it was done in the old
  145                                  * rate */
  146                                 he_gi_ltf += (rate_v1 & RATE_MCS_SGI_MSK_V1) >>
  147                                         RATE_MCS_SGI_POS_V1;
  148 
  149                         rate_v2 |= he_gi_ltf << RATE_MCS_HE_GI_LTF_POS;
  150                         rate_v2 |= he_type << RATE_MCS_HE_TYPE_POS;
  151                         rate_v2 |= he_106t << RATE_MCS_HE_106T_POS;
  152                         rate_v2 |= rate_v1 & RATE_HE_DUAL_CARRIER_MODE_MSK;
  153                         rate_v2 |= RATE_MCS_HE_MSK;
  154                 } else {
  155                         rate_v2 |= RATE_MCS_VHT_MSK;
  156                 }
  157         /* if legacy format */
  158         } else {
  159                 u32 legacy_rate = iwl_legacy_rate_to_fw_idx(rate_v1);
  160 
  161                 if (WARN_ON_ONCE(legacy_rate == IWL_RATE_INVALID))
  162                         legacy_rate = (rate_v1 & RATE_MCS_CCK_MSK_V1) ?
  163                                 IWL_FIRST_CCK_RATE : IWL_FIRST_OFDM_RATE;
  164 
  165                 rate_v2 |= legacy_rate;
  166                 if (!(rate_v1 & RATE_MCS_CCK_MSK_V1))
  167                         rate_v2 |= RATE_MCS_LEGACY_OFDM_MSK;
  168         }
  169 
  170         /* convert flags */
  171         if (rate_v1 & RATE_MCS_LDPC_MSK_V1)
  172                 rate_v2 |= RATE_MCS_LDPC_MSK;
  173         rate_v2 |= (rate_v1 & RATE_MCS_CHAN_WIDTH_MSK_V1) |
  174                 (rate_v1 & RATE_MCS_ANT_AB_MSK) |
  175                 (rate_v1 & RATE_MCS_STBC_MSK) |
  176                 (rate_v1 & RATE_MCS_BF_MSK);
  177 
  178         dup = (rate_v1 & RATE_MCS_DUP_MSK_V1) >> RATE_MCS_DUP_POS_V1;
  179         if (dup) {
  180                 rate_v2 |= RATE_MCS_DUP_MSK;
  181                 rate_v2 |= dup << RATE_MCS_CHAN_WIDTH_POS;
  182         }
  183 
  184         if ((!(rate_v1 & RATE_MCS_HE_MSK_V1)) &&
  185             (rate_v1 & RATE_MCS_SGI_MSK_V1))
  186                 rate_v2 |= RATE_MCS_SGI_MSK;
  187 
  188         return rate_v2;
  189 }
  190 IWL_EXPORT_SYMBOL(iwl_new_rate_from_v1);
  191 
  192 int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate)
  193 {
  194         char *type;
  195         u8 mcs = 0, nss = 0;
  196         u8 ant = (rate & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS;
  197         u32 bw = (rate & RATE_MCS_CHAN_WIDTH_MSK) >>
  198                 RATE_MCS_CHAN_WIDTH_POS;
  199         u32 format = rate & RATE_MCS_MOD_TYPE_MSK;
  200         bool sgi;
  201 
  202         if (format == RATE_MCS_CCK_MSK ||
  203             format == RATE_MCS_LEGACY_OFDM_MSK) {
  204                 int legacy_rate = rate & RATE_LEGACY_RATE_MSK;
  205                 int index = format == RATE_MCS_CCK_MSK ?
  206                         legacy_rate :
  207                         legacy_rate + IWL_FIRST_OFDM_RATE;
  208 
  209                 return scnprintf(buf, bufsz, "Legacy | ANT: %s Rate: %s Mbps",
  210                                  iwl_rs_pretty_ant(ant),
  211                                  index == IWL_RATE_INVALID ? "BAD" :
  212                                  iwl_rate_mcs(index)->mbps);
  213         }
  214 
  215         if (format ==  RATE_MCS_VHT_MSK)
  216                 type = "VHT";
  217         else if (format ==  RATE_MCS_HT_MSK)
  218                 type = "HT";
  219         else if (format == RATE_MCS_HE_MSK)
  220                 type = "HE";
  221         else
  222                 type = "Unknown"; /* shouldn't happen */
  223 
  224         mcs = format == RATE_MCS_HT_MSK ?
  225                 RATE_HT_MCS_INDEX(rate) :
  226                 rate & RATE_MCS_CODE_MSK;
  227         nss = ((rate & RATE_MCS_NSS_MSK)
  228                >> RATE_MCS_NSS_POS) + 1;
  229         sgi = format == RATE_MCS_HE_MSK ?
  230                 iwl_he_is_sgi(rate) :
  231                 rate & RATE_MCS_SGI_MSK;
  232 
  233         return scnprintf(buf, bufsz,
  234                          "0x%x: %s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s",
  235                          rate, type, iwl_rs_pretty_ant(ant), iwl_rs_pretty_bw(bw), mcs, nss,
  236                          (sgi) ? "SGI " : "NGI ",
  237                          (rate & RATE_MCS_STBC_MSK) ? "STBC " : "",
  238                          (rate & RATE_MCS_LDPC_MSK) ? "LDPC " : "",
  239                          (rate & RATE_HE_DUAL_CARRIER_MODE_MSK) ? "DCM " : "",
  240                          (rate & RATE_MCS_BF_MSK) ? "BF " : "");
  241 }
  242 IWL_EXPORT_SYMBOL(rs_pretty_print_rate);
  243 
  244 bool iwl_he_is_sgi(u32 rate_n_flags)
  245 {
  246         u32 type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;
  247         u32 ltf_gi = rate_n_flags & RATE_MCS_HE_GI_LTF_MSK;
  248 
  249         if (type == RATE_MCS_HE_TYPE_SU ||
  250             type == RATE_MCS_HE_TYPE_EXT_SU)
  251                 return ltf_gi == RATE_MCS_HE_SU_4_LTF_08_GI;
  252         return false;
  253 }
  254 IWL_EXPORT_SYMBOL(iwl_he_is_sgi);
  255 

Cache object: 5c2aed809344e2378f2a5e4c7e19eea9


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