aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/ar9170/ar9170.h
blob: e6c3ee3e0581f7abbe885efca41c320bbd28729c (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
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
/*
 * Atheros AR9170 driver
 *
 * Driver specific definitions
 *
 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; see the file COPYING.  If not, see
 * http://www.gnu.org/licenses/.
 *
 * This file incorporates work covered by the following copyright and
 * permission notice:
 *    Copyright (c) 2007-2008 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 __AR9170_H
#define __AR9170_H

#include <linux/completion.h>
#include <linux/spinlock.h>
#include <net/cfg80211.h>
#include <net/mac80211.h>
#ifdef CONFIG_AR9170_LEDS
#include <linux/leds.h>
#endif /* CONFIG_AR9170_LEDS */
#include "eeprom.h"
#include "hw.h"

#include "../regd.h"

#define PAYLOAD_MAX	(AR9170_MAX_CMD_LEN/4 - 1)

enum ar9170_bw {
	AR9170_BW_20,
	AR9170_BW_40_BELOW,
	AR9170_BW_40_ABOVE,

	__AR9170_NUM_BW,
};

static inline enum ar9170_bw nl80211_to_ar9170(enum nl80211_channel_type type)
{
	switch (type) {
	case NL80211_CHAN_NO_HT:
	case NL80211_CHAN_HT20:
		return AR9170_BW_20;
	case NL80211_CHAN_HT40MINUS:
		return AR9170_BW_40_BELOW;
	case NL80211_CHAN_HT40PLUS:
		return AR9170_BW_40_ABOVE;
	default:
		BUG();
	}
}

enum ar9170_rf_init_mode {
	AR9170_RFI_NONE,
	AR9170_RFI_WARM,
	AR9170_RFI_COLD,
};

#define AR9170_MAX_RX_BUFFER_SIZE		8192

#ifdef CONFIG_AR9170_LEDS
struct ar9170;

struct ar9170_led {
	struct ar9170 *ar;
	struct led_classdev l;
	char name[32];
	unsigned int toggled;
	bool last_state;
	bool registered;
};

#endif /* CONFIG_AR9170_LEDS */

enum ar9170_device_state {
	AR9170_UNKNOWN_STATE,
	AR9170_STOPPED,
	AR9170_IDLE,
	AR9170_STARTED,
};

struct ar9170_rxstream_mpdu_merge {
	struct ar9170_rx_head plcp;
	bool has_plcp;
};

#define AR9170_NUM_MAX_BA_RETRY	5
#define AR9170_NUM_TID	16
#define WME_BA_BMP_SIZE         64
#define AR9170_NUM_MAX_AGG_LEN	(2 * WME_BA_BMP_SIZE)

#define WME_AC_BE   2
#define WME_AC_BK   3
#define WME_AC_VI   1
#define WME_AC_VO   0

#define TID_TO_WME_AC(_tid)				\
	((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE :	\
	 (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK :	\
	 (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI :	\
	 WME_AC_VO)

#define BAW_WITHIN(_start, _bawsz, _seqno) \
	((((_seqno) - (_start)) & 0xfff) < (_bawsz))

enum ar9170_tid_state {
	AR9170_TID_STATE_INVALID,
	AR9170_TID_STATE_SHUTDOWN,
	AR9170_TID_STATE_PROGRESS,
	AR9170_TID_STATE_COMPLETE,
};

struct ar9170_sta_tid {
	struct list_head list;
	struct sk_buff_head queue;
	u8 addr[ETH_ALEN];
	u16 ssn;
	u16 tid;
	enum ar9170_tid_state state;
	bool active;
	u8 retry;
};

#define AR9170_QUEUE_TIMEOUT		64
#define AR9170_TX_TIMEOUT		8
#define AR9170_BA_TIMEOUT		4
#define AR9170_JANITOR_DELAY		128
#define AR9170_TX_INVALID_RATE		0xffffffff

#define AR9170_NUM_TX_STATUS		128
#define AR9170_NUM_TX_AGG_MAX		30

struct ar9170 {
	struct ieee80211_hw *hw;
	struct mutex mutex;
	enum ar9170_device_state state;
	unsigned long bad_hw_nagger;

	int (*open)(struct ar9170 *);
	void (*stop)(struct ar9170 *);
	int (*tx)(struct ar9170 *, struct sk_buff *);
	int (*exec_cmd)(struct ar9170 *, enum ar9170_cmd, u32 ,
			void *, u32 , void *);
	void (*callback_cmd)(struct ar9170 *, u32 , void *);
	int (*flush)(struct ar9170 *);

	/* interface mode settings */
	struct ieee80211_vif *vif;
	u8 mac_addr[ETH_ALEN];
	u8 bssid[ETH_ALEN];

	/* beaconing */
	struct sk_buff *beacon;
	struct work_struct beacon_work;

	/* cryptographic engine */
	u64 usedkeys;
	bool rx_software_decryption;
	bool disable_offload;

	/* filter settings */
	struct work_struct filter_config_work;
	u64 cur_mc_hash, want_mc_hash;
	u32 cur_filter, want_filter;
	unsigned long filter_changed;
	unsigned int filter_state;
	bool sniffer_enabled;

	/* PHY */
	struct ieee80211_channel *channel;
	int noise[4];

	/* power calibration data */
	u8 power_5G_leg[4];
	u8 power_2G_cck[4];
	u8 power_2G_ofdm[4];
	u8 power_5G_ht20[8];
	u8 power_5G_ht40[8];
	u8 power_2G_ht20[8];
	u8 power_2G_ht40[8];

#ifdef CONFIG_AR9170_LEDS
	struct delayed_work led_work;
	struct ar9170_led leds[AR9170_NUM_LEDS];
#endif /* CONFIG_AR9170_LEDS */

	/* qos queue settings */
	spinlock_t tx_stats_lock;
	struct ieee80211_tx_queue_stats tx_stats[5];
	struct ieee80211_tx_queue_params edcf[5];

	spinlock_t cmdlock;
	__le32 cmdbuf[PAYLOAD_MAX + 1];

	/* MAC statistics */
	struct ieee80211_low_level_stats stats;

	/* EEPROM */
	struct ar9170_eeprom eeprom;
	struct ath_regulatory regulatory;

	/* tx queues - as seen by hw - */
	struct sk_buff_head tx_pending[__AR9170_NUM_TXQ];
	struct sk_buff_head tx_status[__AR9170_NUM_TXQ];
	struct delayed_work tx_janitor;
	/* tx ampdu */
	struct sk_buff_head tx_status_ampdu;
	spinlock_t tx_ampdu_list_lock;
	struct list_head tx_ampdu_list;
	unsigned int tx_ampdu_pending;

	/* rxstream mpdu merge */
	struct ar9170_rxstream_mpdu_merge rx_mpdu;
	struct sk_buff *rx_failover;
	int rx_failover_missing;

	/* (cached) HW A-MPDU settings */
	u8 global_ampdu_density;
	u8 global_ampdu_factor;
};

struct ar9170_sta_info {
	struct ar9170_sta_tid agg[AR9170_NUM_TID];
	unsigned int ampdu_max_len;
};

#define AR9170_TX_FLAG_WAIT_FOR_ACK	BIT(0)
#define AR9170_TX_FLAG_NO_ACK		BIT(1)
#define AR9170_TX_FLAG_BLOCK_ACK	BIT(2)

struct ar9170_tx_info {
	unsigned long timeout;
	unsigned int flags;
};

#define IS_STARTED(a)		(((struct ar9170 *)a)->state >= AR9170_STARTED)
#define IS_ACCEPTING_CMD(a)	(((struct ar9170 *)a)->state >= AR9170_IDLE)

#define AR9170_FILTER_CHANGED_MODE		BIT(0)
#define AR9170_FILTER_CHANGED_MULTICAST		BIT(1)
#define AR9170_FILTER_CHANGED_FRAMEFILTER	BIT(2)

/* exported interface */
void *ar9170_alloc(size_t priv_size);
int ar9170_register(struct ar9170 *ar, struct device *pdev);
void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb);
void ar9170_unregister(struct ar9170 *ar);
void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb);
void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len);
int ar9170_nag_limiter(struct ar9170 *ar);

/* MAC */
int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
int ar9170_init_mac(struct ar9170 *ar);
int ar9170_set_qos(struct ar9170 *ar);
int ar9170_update_multicast(struct ar9170 *ar);
int ar9170_update_frame_filter(struct ar9170 *ar);
int ar9170_set_operating_mode(struct ar9170 *ar);
int ar9170_set_beacon_timers(struct ar9170 *ar);
int ar9170_set_dyn_sifs_ack(struct ar9170 *ar);
int ar9170_set_slot_time(struct ar9170 *ar);
int ar9170_set_basic_rates(struct ar9170 *ar);
int ar9170_set_hwretry_limit(struct ar9170 *ar, u32 max_retry);
int ar9170_update_beacon(struct ar9170 *ar);
void ar9170_new_beacon(struct work_struct *work);
int ar9170_upload_key(struct ar9170 *ar, u8 id, const u8 *mac, u8 ktype,
		      u8 keyidx, u8 *keydata, int keylen);
int ar9170_disable_key(struct ar9170 *ar, u8 id);

/* LEDs */
#ifdef CONFIG_AR9170_LEDS
int ar9170_register_leds(struct ar9170 *ar);
void ar9170_unregister_leds(struct ar9170 *ar);
#endif /* CONFIG_AR9170_LEDS */
int ar9170_init_leds(struct ar9170 *ar);
int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state);

/* PHY / RF */
int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band);
int ar9170_init_rf(struct ar9170 *ar);
int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
		       enum ar9170_rf_init_mode rfi, enum ar9170_bw bw);

#endif /* __AR9170_H */