aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/ath9k/rc.h
blob: 268e67dc5fb2d945a26a332081b32167d9e133dc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
/*
 * Copyright (c) 2004 Sam Leffler, Errno Consulting
 * Copyright (c) 2004 Video54 Technologies, Inc.
 * Copyright (c) 2008-2011 Atheros Communications Inc.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef RC_H
#define RC_H

#include "hw.h"

struct ath_softc;

#define ATH_RATE_MAX     30
#define RATE_TABLE_SIZE  72

#define RC_INVALID	0x0000
#define RC_LEGACY	0x0001
#define RC_SS		0x0002
#define RC_DS		0x0004
#define RC_TS		0x0008
#define RC_HT_20	0x0010
#define RC_HT_40	0x0020

#define RC_STREAM_MASK	0xe
#define RC_DS_OR_LATER(f)	((((f) & RC_STREAM_MASK) == RC_DS) || \
				(((f) & RC_STREAM_MASK) == (RC_DS | RC_TS)))
#define RC_TS_ONLY(f)		(((f) & RC_STREAM_MASK) == RC_TS)
#define RC_SS_OR_LEGACY(f)	((f) & (RC_SS | RC_LEGACY))

#define RC_HT_2040		(RC_HT_20 | RC_HT_40)
#define RC_ALL_STREAM		(RC_SS | RC_DS | RC_TS)
#define RC_L_SD			(RC_LEGACY | RC_SS | RC_DS)
#define RC_L_SDT		(RC_LEGACY | RC_SS | RC_DS | RC_TS)
#define RC_HT_S_20		(RC_HT_20 | RC_SS)
#define RC_HT_D_20		(RC_HT_20 | RC_DS)
#define RC_HT_T_20		(RC_HT_20 | RC_TS)
#define RC_HT_S_40		(RC_HT_40 | RC_SS)
#define RC_HT_D_40		(RC_HT_40 | RC_DS)
#define RC_HT_T_40		(RC_HT_40 | RC_TS)

#define RC_HT_SD_20		(RC_HT_20 | RC_SS | RC_DS)
#define RC_HT_DT_20		(RC_HT_20 | RC_DS | RC_TS)
#define RC_HT_SD_40		(RC_HT_40 | RC_SS | RC_DS)
#define RC_HT_DT_40		(RC_HT_40 | RC_DS | RC_TS)

#define RC_HT_SD_2040		(RC_HT_2040 | RC_SS | RC_DS)
#define RC_HT_SDT_2040		(RC_HT_2040 | RC_SS | RC_DS | RC_TS)

#define RC_HT_SDT_20		(RC_HT_20 | RC_SS | RC_DS | RC_TS)
#define RC_HT_SDT_40		(RC_HT_40 | RC_SS | RC_DS | RC_TS)

#define RC_ALL			(RC_LEGACY | RC_HT_2040 | RC_ALL_STREAM)

enum {
	WLAN_RC_PHY_OFDM,
	WLAN_RC_PHY_CCK,
	WLAN_RC_PHY_HT_20_SS,
	WLAN_RC_PHY_HT_20_DS,
	WLAN_RC_PHY_HT_20_TS,
	WLAN_RC_PHY_HT_40_SS,
	WLAN_RC_PHY_HT_40_DS,
	WLAN_RC_PHY_HT_40_TS,
	WLAN_RC_PHY_HT_20_SS_HGI,
	WLAN_RC_PHY_HT_20_DS_HGI,
	WLAN_RC_PHY_HT_20_TS_HGI,
	WLAN_RC_PHY_HT_40_SS_HGI,
	WLAN_RC_PHY_HT_40_DS_HGI,
	WLAN_RC_PHY_HT_40_TS_HGI,
	WLAN_RC_PHY_MAX
};

#define WLAN_RC_PHY_DS(_phy)   ((_phy == WLAN_RC_PHY_HT_20_DS)		\
				|| (_phy == WLAN_RC_PHY_HT_40_DS)	\
				|| (_phy == WLAN_RC_PHY_HT_20_DS_HGI)	\
				|| (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
#define WLAN_RC_PHY_TS(_phy)   ((_phy == WLAN_RC_PHY_HT_20_TS)		\
				|| (_phy == WLAN_RC_PHY_HT_40_TS)	\
				|| (_phy == WLAN_RC_PHY_HT_20_TS_HGI)	\
				|| (_phy == WLAN_RC_PHY_HT_40_TS_HGI))
#define WLAN_RC_PHY_20(_phy)   ((_phy == WLAN_RC_PHY_HT_20_SS)		\
				|| (_phy == WLAN_RC_PHY_HT_20_DS)	\
				|| (_phy == WLAN_RC_PHY_HT_20_TS)	\
				|| (_phy == WLAN_RC_PHY_HT_20_SS_HGI)	\
				|| (_phy == WLAN_RC_PHY_HT_20_DS_HGI)	\
				|| (_phy == WLAN_RC_PHY_HT_20_TS_HGI))
#define WLAN_RC_PHY_40(_phy)   ((_phy == WLAN_RC_PHY_HT_40_SS)		\
				|| (_phy == WLAN_RC_PHY_HT_40_DS)	\
				|| (_phy == WLAN_RC_PHY_HT_40_TS)	\
				|| (_phy == WLAN_RC_PHY_HT_40_SS_HGI)	\
				|| (_phy == WLAN_RC_PHY_HT_40_DS_HGI)	\
				|| (_phy == WLAN_RC_PHY_HT_40_TS_HGI))
#define WLAN_RC_PHY_SGI(_phy)  ((_phy == WLAN_RC_PHY_HT_20_SS_HGI)      \
				|| (_phy == WLAN_RC_PHY_HT_20_DS_HGI)   \
				|| (_phy == WLAN_RC_PHY_HT_20_TS_HGI)   \
				|| (_phy == WLAN_RC_PHY_HT_40_SS_HGI)   \
				|| (_phy == WLAN_RC_PHY_HT_40_DS_HGI)   \
				|| (_phy == WLAN_RC_PHY_HT_40_TS_HGI))

#define WLAN_RC_PHY_HT(_phy)    (_phy >= WLAN_RC_PHY_HT_20_SS)

#define WLAN_RC_CAP_MODE(capflag) (((capflag & WLAN_RC_HT_FLAG) ?	\
	((capflag & WLAN_RC_40_FLAG) ? RC_HT_40 : RC_HT_20) : RC_LEGACY))

#define WLAN_RC_CAP_STREAM(capflag) (((capflag & WLAN_RC_TS_FLAG) ?	\
	(RC_TS) : ((capflag & WLAN_RC_DS_FLAG) ? RC_DS : RC_SS)))

/* Return TRUE if flag supports HT20 && client supports HT20 or
 * return TRUE if flag supports HT40 && client supports HT40.
 * This is used becos some rates overlap between HT20/HT40.
 */
#define WLAN_RC_PHY_HT_VALID(flag, capflag)			\
	(((flag & RC_HT_20) && !(capflag & WLAN_RC_40_FLAG)) || \
	 ((flag & RC_HT_40) && (capflag & WLAN_RC_40_FLAG)))

#define WLAN_RC_DS_FLAG         (0x01)
#define WLAN_RC_TS_FLAG         (0x02)
#define WLAN_RC_40_FLAG         (0x04)
#define WLAN_RC_SGI_FLAG        (0x08)
#define WLAN_RC_HT_FLAG         (0x10)

/**
 * struct ath_rate_table - Rate Control table
 * @rate_cnt: total number of rates for the given wireless mode
 * @mcs_start: MCS rate index offset
 * @rate_flags: Rate Control flags
 * @phy: CCK/OFDM/HT20/HT40
 * @ratekbps: rate in Kbits per second
 * @user_ratekbps: user rate in Kbits per second
 * @ratecode: rate that goes into HW descriptors
 * @dot11rate: value that goes into supported
 * 	rates info element of MLME
 * @ctrl_rate: Index of next lower basic rate, used for duration computation
 * @cw40index: Index of rates having 40MHz channel width
 * @sgi_index: Index of rates having Short Guard Interval
 * @ht_index: high throughput rates having 40MHz channel width and
 * 	Short Guard Interval
 * @probe_interval: interval for rate control to probe for other rates
 * @initial_ratemax: initial ratemax value
 */
struct ath_rate_table {
	int rate_cnt;
	int mcs_start;
	struct {
		u16 rate_flags;
		u8 phy;
		u32 ratekbps;
		u32 user_ratekbps;
		u8 ratecode;
		u8 dot11rate;
	} info[RATE_TABLE_SIZE];
	u32 probe_interval;
	u8 initial_ratemax;
};

struct ath_rateset {
	u8 rs_nrates;
	u8 rs_rates[ATH_RATE_MAX];
};

struct ath_rc_stats {
	u32 success;
	u32 retries;
	u32 xretries;
	u8 per;
};

/**
 * struct ath_rate_priv - Rate Control priv data
 * @state: RC state
 * @probe_rate: rate we are probing at
 * @probe_time: msec timestamp for last probe
 * @hw_maxretry_pktcnt: num of packets since we got HW max retry error
 * @max_valid_rate: maximum number of valid rate
 * @per_down_time: msec timestamp for last PER down step
 * @valid_phy_ratecnt: valid rate count
 * @rate_max_phy: phy index for the max rate
 * @per: PER for every valid rate in %
 * @probe_interval: interval for ratectrl to probe for other rates
 * @ht_cap: HT capabilities
 * @neg_rates: Negotatied rates
 * @neg_ht_rates: Negotiated HT rates
 */
struct ath_rate_priv {
	u8 rate_table_size;
	u8 probe_rate;
	u8 hw_maxretry_pktcnt;
	u8 max_valid_rate;
	u8 valid_rate_index[RATE_TABLE_SIZE];
	u8 ht_cap;
	u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX];
	u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE];
	u8 rate_max_phy;
	u8 per[RATE_TABLE_SIZE];
	u32 probe_time;
	u32 per_down_time;
	u32 probe_interval;
	struct ath_rateset neg_rates;
	struct ath_rateset neg_ht_rates;
	const struct ath_rate_table *rate_table;

	struct dentry *debugfs_rcstats;
	struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
};

#ifdef CONFIG_ATH9K_RATE_CONTROL
int ath_rate_control_register(void);
void ath_rate_control_unregister(void);
#else
static inline int ath_rate_control_register(void)
{
	return 0;
}

static inline void ath_rate_control_unregister(void)
{
}
#endif

#endif /* RC_H */