summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/mediatek/mt76/mt76_connac.h
blob: b353c26b7d27b7e8e3b5710cf5860ba49346c099 (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
/* SPDX-License-Identifier: ISC */
/* Copyright (C) 2020 MediaTek Inc. */

#ifndef __MT76_CONNAC_H
#define __MT76_CONNAC_H

#include "mt76.h"

#define MT76_CONNAC_SCAN_IE_LEN			600
#define MT76_CONNAC_MAX_NUM_SCHED_SCAN_INTERVAL	 10
#define MT76_CONNAC_MAX_TIME_SCHED_SCAN_INTERVAL U16_MAX
#define MT76_CONNAC_MAX_SCHED_SCAN_SSID		10
#define MT76_CONNAC_MAX_SCAN_MATCH		16

#define MT76_CONNAC_COREDUMP_TIMEOUT		(HZ / 20)
#define MT76_CONNAC_COREDUMP_SZ			(1300 * 1024)

enum {
	CMD_CBW_20MHZ = IEEE80211_STA_RX_BW_20,
	CMD_CBW_40MHZ = IEEE80211_STA_RX_BW_40,
	CMD_CBW_80MHZ = IEEE80211_STA_RX_BW_80,
	CMD_CBW_160MHZ = IEEE80211_STA_RX_BW_160,
	CMD_CBW_10MHZ,
	CMD_CBW_5MHZ,
	CMD_CBW_8080MHZ,

	CMD_HE_MCS_BW80 = 0,
	CMD_HE_MCS_BW160,
	CMD_HE_MCS_BW8080,
	CMD_HE_MCS_BW_NUM
};

enum {
	HW_BSSID_0 = 0x0,
	HW_BSSID_1,
	HW_BSSID_2,
	HW_BSSID_3,
	HW_BSSID_MAX = HW_BSSID_3,
	EXT_BSSID_START = 0x10,
	EXT_BSSID_1,
	EXT_BSSID_15 = 0x1f,
	EXT_BSSID_MAX = EXT_BSSID_15,
	REPEATER_BSSID_START = 0x20,
	REPEATER_BSSID_MAX = 0x3f,
};

struct mt76_connac_pm {
	bool enable:1;
	bool enable_user:1;
	bool ds_enable:1;
	bool ds_enable_user:1;
	bool suspended:1;

	spinlock_t txq_lock;
	struct {
		struct mt76_wcid *wcid;
		struct sk_buff *skb;
	} tx_q[IEEE80211_NUM_ACS];

	struct work_struct wake_work;
	wait_queue_head_t wait;

	struct {
		spinlock_t lock;
		u32 count;
	} wake;
	struct mutex mutex;

	struct delayed_work ps_work;
	unsigned long last_activity;
	unsigned long idle_timeout;

	struct {
		unsigned long last_wake_event;
		unsigned long awake_time;
		unsigned long last_doze_event;
		unsigned long doze_time;
		unsigned int lp_wake;
	} stats;
};

struct mt76_connac_coredump {
	struct sk_buff_head msg_list;
	struct delayed_work work;
	unsigned long last_activity;
};

struct mt76_connac_sta_key_conf {
	s8 keyidx;
	u8 key[16];
};

extern const struct wiphy_wowlan_support mt76_connac_wowlan_support;

static inline bool is_mt7922(struct mt76_dev *dev)
{
	return mt76_chip(dev) == 0x7922;
}

static inline bool is_mt7921(struct mt76_dev *dev)
{
	return mt76_chip(dev) == 0x7961 || is_mt7922(dev);
}

static inline bool is_mt7663(struct mt76_dev *dev)
{
	return mt76_chip(dev) == 0x7663;
}

static inline bool is_mt7915(struct mt76_dev *dev)
{
	return mt76_chip(dev) == 0x7915;
}

static inline bool is_mt7916(struct mt76_dev *dev)
{
	return mt76_chip(dev) == 0x7906;
}

static inline bool is_mt7622(struct mt76_dev *dev)
{
	if (!IS_ENABLED(CONFIG_MT7622_WMAC))
		return false;

	return mt76_chip(dev) == 0x7622;
}

static inline bool is_mt7615(struct mt76_dev *dev)
{
	return mt76_chip(dev) == 0x7615 || mt76_chip(dev) == 0x7611;
}

static inline bool is_mt7611(struct mt76_dev *dev)
{
	return mt76_chip(dev) == 0x7611;
}

static inline bool is_connac_v1(struct mt76_dev *dev)
{
	return is_mt7615(dev) || is_mt7663(dev) || is_mt7622(dev);
}

static inline u8 mt76_connac_chan_bw(struct cfg80211_chan_def *chandef)
{
	static const u8 width_to_bw[] = {
		[NL80211_CHAN_WIDTH_40] = CMD_CBW_40MHZ,
		[NL80211_CHAN_WIDTH_80] = CMD_CBW_80MHZ,
		[NL80211_CHAN_WIDTH_80P80] = CMD_CBW_8080MHZ,
		[NL80211_CHAN_WIDTH_160] = CMD_CBW_160MHZ,
		[NL80211_CHAN_WIDTH_5] = CMD_CBW_5MHZ,
		[NL80211_CHAN_WIDTH_10] = CMD_CBW_10MHZ,
		[NL80211_CHAN_WIDTH_20] = CMD_CBW_20MHZ,
		[NL80211_CHAN_WIDTH_20_NOHT] = CMD_CBW_20MHZ,
	};

	if (chandef->width >= ARRAY_SIZE(width_to_bw))
		return 0;

	return width_to_bw[chandef->width];
}

int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm);
void mt76_connac_power_save_sched(struct mt76_phy *phy,
				  struct mt76_connac_pm *pm);
void mt76_connac_free_pending_tx_skbs(struct mt76_connac_pm *pm,
				      struct mt76_wcid *wcid);

static inline bool
mt76_connac_pm_ref(struct mt76_phy *phy, struct mt76_connac_pm *pm)
{
	bool ret = false;

	spin_lock_bh(&pm->wake.lock);
	if (test_bit(MT76_STATE_PM, &phy->state))
		goto out;

	pm->wake.count++;
	ret = true;
out:
	spin_unlock_bh(&pm->wake.lock);

	return ret;
}

static inline void
mt76_connac_pm_unref(struct mt76_phy *phy, struct mt76_connac_pm *pm)
{
	spin_lock_bh(&pm->wake.lock);

	pm->last_activity = jiffies;
	if (--pm->wake.count == 0 &&
	    test_bit(MT76_STATE_MCU_RUNNING, &phy->state))
		mt76_connac_power_save_sched(phy, pm);

	spin_unlock_bh(&pm->wake.lock);
}

static inline bool
mt76_connac_skip_fw_pmctrl(struct mt76_phy *phy, struct mt76_connac_pm *pm)
{
	struct mt76_dev *dev = phy->dev;
	bool ret;

	if (dev->token_count)
		return true;

	spin_lock_bh(&pm->wake.lock);
	ret = pm->wake.count || test_and_set_bit(MT76_STATE_PM, &phy->state);
	spin_unlock_bh(&pm->wake.lock);

	return ret;
}

static inline void
mt76_connac_mutex_acquire(struct mt76_dev *dev, struct mt76_connac_pm *pm)
	__acquires(&dev->mutex)
{
	mutex_lock(&dev->mutex);
	mt76_connac_pm_wake(&dev->phy, pm);
}

static inline void
mt76_connac_mutex_release(struct mt76_dev *dev, struct mt76_connac_pm *pm)
	__releases(&dev->mutex)
{
	mt76_connac_power_save_sched(&dev->phy, pm);
	mutex_unlock(&dev->mutex);
}

void mt76_connac_pm_queue_skb(struct ieee80211_hw *hw,
			      struct mt76_connac_pm *pm,
			      struct mt76_wcid *wcid,
			      struct sk_buff *skb);
void mt76_connac_pm_dequeue_skbs(struct mt76_phy *phy,
				 struct mt76_connac_pm *pm);

#endif /* __MT76_CONNAC_H */