File Index
Files and directories
Sign in
FILE

rs.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wireless/intel/iwlwifi/fw/rs.c C
  1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
  2/*
  3 * Copyright (C) 2021-2022, 2025 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 * */
 17static 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 */
 33static 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
 49static const char * const ant_name[] = {
 50	[ANT_NONE] = "None",
 51	[ANT_A]    = "A",
 52	[ANT_B]    = "B",
 53	[ANT_AB]   = "AB",
 54};
 55
 56static const char * const pretty_bw[] = {
 57	"20Mhz",
 58	"40Mhz",
 59	"80Mhz",
 60	"160 Mhz",
 61	"320Mhz",
 62};
 63
 64u8 iwl_fw_rate_idx_to_plcp(int idx)
 65{
 66	return fw_rate_idx_to_plcp[idx];
 67}
 68IWL_EXPORT_SYMBOL(iwl_fw_rate_idx_to_plcp);
 69
 70const struct iwl_rate_mcs_info *iwl_rate_mcs(int idx)
 71{
 72	return &rate_mcs[idx];
 73}
 74IWL_EXPORT_SYMBOL(iwl_rate_mcs);
 75
 76const 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}
 83IWL_EXPORT_SYMBOL(iwl_rs_pretty_ant);
 84
 85const 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}
 92IWL_EXPORT_SYMBOL(iwl_rs_pretty_bw);
 93
 94int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate)
 95{
 96	char *type;
 97	u8 mcs = 0, nss = 0;
 98	u8 ant = (rate & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS;
 99	u32 bw = (rate & RATE_MCS_CHAN_WIDTH_MSK) >>
100		RATE_MCS_CHAN_WIDTH_POS;
101	u32 format = rate & RATE_MCS_MOD_TYPE_MSK;
102	int index = 0;
103	bool sgi;
104
105	switch (format) {
106	case RATE_MCS_MOD_TYPE_LEGACY_OFDM:
107		index = IWL_FIRST_OFDM_RATE;
108		fallthrough;
109	case RATE_MCS_MOD_TYPE_CCK:
110		index += rate & RATE_LEGACY_RATE_MSK;
111
112		return scnprintf(buf, bufsz, "Legacy | ANT: %s Rate: %s Mbps",
113				 iwl_rs_pretty_ant(ant),
114				 iwl_rate_mcs(index)->mbps);
115	case RATE_MCS_MOD_TYPE_VHT:
116		type = "VHT";
117		break;
118	case RATE_MCS_MOD_TYPE_HT:
119		type = "HT";
120		break;
121	case RATE_MCS_MOD_TYPE_HE:
122		type = "HE";
123		break;
124	case RATE_MCS_MOD_TYPE_EHT:
125		type = "EHT";
126		break;
127	default:
128		type = "Unknown"; /* shouldn't happen */
129	}
130
131	mcs = format == RATE_MCS_MOD_TYPE_HT ?
132		RATE_HT_MCS_INDEX(rate) :
133		rate & RATE_MCS_CODE_MSK;
134	nss = u32_get_bits(rate, RATE_MCS_NSS_MSK);
135	sgi = format == RATE_MCS_MOD_TYPE_HE ?
136		iwl_he_is_sgi(rate) :
137		rate & RATE_MCS_SGI_MSK;
138
139	return scnprintf(buf, bufsz,
140			 "0x%x: %s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s",
141			 rate, type, iwl_rs_pretty_ant(ant), iwl_rs_pretty_bw(bw), mcs, nss,
142			 (sgi) ? "SGI " : "NGI ",
143			 (rate & RATE_MCS_STBC_MSK) ? "STBC " : "",
144			 (rate & RATE_MCS_LDPC_MSK) ? "LDPC " : "",
145			 (rate & RATE_HE_DUAL_CARRIER_MODE_MSK) ? "DCM " : "",
146			 (rate & RATE_MCS_BF_MSK) ? "BF " : "");
147}
148IWL_EXPORT_SYMBOL(rs_pretty_print_rate);
149
150bool iwl_he_is_sgi(u32 rate_n_flags)
151{
152	u32 type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;
153	u32 ltf_gi = rate_n_flags & RATE_MCS_HE_GI_LTF_MSK;
154
155	if (type == RATE_MCS_HE_TYPE_SU ||
156	    type == RATE_MCS_HE_TYPE_EXT_SU)
157		return ltf_gi == RATE_MCS_HE_SU_4_LTF_08_GI;
158	return false;
159}
160IWL_EXPORT_SYMBOL(iwl_he_is_sgi);
161
~/ Read-only file preview.