init.c revision 3df74f46d88e39a032eb2cc3f2a571b66082acba
1f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho/*
2f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * This file is part of wl1271
3f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho *
4f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * Copyright (C) 2009 Nokia Corporation
5f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho *
6f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * Contact: Luciano Coelho <luciano.coelho@nokia.com>
7f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho *
8f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * This program is free software; you can redistribute it and/or
9f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * modify it under the terms of the GNU General Public License
10f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * version 2 as published by the Free Software Foundation.
11f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho *
12f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * This program is distributed in the hope that it will be useful, but
13f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * WITHOUT ANY WARRANTY; without even the implied warranty of
14f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * General Public License for more details.
16f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho *
17f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * You should have received a copy of the GNU General Public License
18f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * along with this program; if not, write to the Free Software
19f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * 02110-1301 USA
21f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho *
22f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho */
23f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
24f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho#include <linux/kernel.h>
25f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho#include <linux/module.h>
265a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
27f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
280f4e31222a2c0b93f25a87effd2033cb78c7a79cLuciano Coelho#include "debug.h"
2900d201001bd4e8a46e3d03c970abcb72256c368bShahar Levi#include "init.h"
30f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho#include "wl12xx_80211.h"
3100d201001bd4e8a46e3d03c970abcb72256c368bShahar Levi#include "acx.h"
3200d201001bd4e8a46e3d03c970abcb72256c368bShahar Levi#include "cmd.h"
33e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov#include "tx.h"
3448a61477bdc04896bd96d259388a0c42a7019943Shahar Levi#include "io.h"
358a9affc08d676a9fe627361ab6767cdec0740af3Arik Nemtsov#include "hw_ops.h"
36f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
3792c77c734f958474ac73af670834bc32cb833e54Eliad Pellerint wl1271_init_templates_config(struct wl1271 *wl)
38f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{
39bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen	int ret, i;
405ec8a448e0e978103bc5ca7136084b5e2b36989eEliad Peller	size_t max_size;
41f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
42f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	/* send empty templates for fw memory reservation */
43cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller	ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
44cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller				      CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
45c08e371a683021cfb99632db799bea9b69d176e5Ido Reis				      WL1271_CMD_TEMPL_MAX_SIZE,
46606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen				      0, WL1271_RATE_AUTOMATIC);
47f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
48f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
49f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
50cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller	ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
51cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller				      CMD_TEMPL_CFG_PROBE_REQ_5,
52c08e371a683021cfb99632db799bea9b69d176e5Ido Reis				      NULL, WL1271_CMD_TEMPL_MAX_SIZE, 0,
5311eb54298fa7197cb4187f8a3474ead0709f76ffJuuso Oikarinen				      WL1271_RATE_AUTOMATIC);
5411eb54298fa7197cb4187f8a3474ead0709f76ffJuuso Oikarinen	if (ret < 0)
5511eb54298fa7197cb4187f8a3474ead0709f76ffJuuso Oikarinen		return ret;
56abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi
573df74f46d88e39a032eb2cc3f2a571b66082acbaYoni Divinsky	if (wl->quirks & WLCORE_QUIRK_DUAL_PROBE_TMPL) {
583df74f46d88e39a032eb2cc3f2a571b66082acbaYoni Divinsky		ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
593df74f46d88e39a032eb2cc3f2a571b66082acbaYoni Divinsky					      CMD_TEMPL_APP_PROBE_REQ_2_4, NULL,
603df74f46d88e39a032eb2cc3f2a571b66082acbaYoni Divinsky					      WL1271_CMD_TEMPL_MAX_SIZE,
613df74f46d88e39a032eb2cc3f2a571b66082acbaYoni Divinsky					      0, WL1271_RATE_AUTOMATIC);
623df74f46d88e39a032eb2cc3f2a571b66082acbaYoni Divinsky		if (ret < 0)
633df74f46d88e39a032eb2cc3f2a571b66082acbaYoni Divinsky			return ret;
643df74f46d88e39a032eb2cc3f2a571b66082acbaYoni Divinsky
653df74f46d88e39a032eb2cc3f2a571b66082acbaYoni Divinsky		ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
663df74f46d88e39a032eb2cc3f2a571b66082acbaYoni Divinsky					      CMD_TEMPL_APP_PROBE_REQ_5, NULL,
673df74f46d88e39a032eb2cc3f2a571b66082acbaYoni Divinsky					      WL1271_CMD_TEMPL_MAX_SIZE,
683df74f46d88e39a032eb2cc3f2a571b66082acbaYoni Divinsky					      0, WL1271_RATE_AUTOMATIC);
693df74f46d88e39a032eb2cc3f2a571b66082acbaYoni Divinsky		if (ret < 0)
703df74f46d88e39a032eb2cc3f2a571b66082acbaYoni Divinsky			return ret;
713df74f46d88e39a032eb2cc3f2a571b66082acbaYoni Divinsky	}
723df74f46d88e39a032eb2cc3f2a571b66082acbaYoni Divinsky
73cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller	ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
74cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller				      CMD_TEMPL_NULL_DATA, NULL,
75bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen				      sizeof(struct wl12xx_null_data_template),
76606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen				      0, WL1271_RATE_AUTOMATIC);
77f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
78f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
79f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
80cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller	ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
81cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller				      CMD_TEMPL_PS_POLL, NULL,
82bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen				      sizeof(struct wl12xx_ps_poll_template),
83606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen				      0, WL1271_RATE_AUTOMATIC);
84f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
85f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
86f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
87cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller	ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
88cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller				      CMD_TEMPL_QOS_NULL_DATA, NULL,
89f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho				      sizeof
9097127e67218e5970a5a7df0513ded730b19a67e9Eliad Peller				      (struct ieee80211_qos_hdr),
91606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen				      0, WL1271_RATE_AUTOMATIC);
92f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
93f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
94f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
95cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller	ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
96cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller				      CMD_TEMPL_PROBE_RESPONSE, NULL,
97154037d1681caaff7d33521b84017ee58b396438Eliad Peller				      WL1271_CMD_TEMPL_DFLT_SIZE,
98606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen				      0, WL1271_RATE_AUTOMATIC);
99f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
100f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
101f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
102cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller	ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
103cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller				      CMD_TEMPL_BEACON, NULL,
104154037d1681caaff7d33521b84017ee58b396438Eliad Peller				      WL1271_CMD_TEMPL_DFLT_SIZE,
105606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen				      0, WL1271_RATE_AUTOMATIC);
106f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
107f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
108f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
1095ec8a448e0e978103bc5ca7136084b5e2b36989eEliad Peller	max_size = sizeof(struct wl12xx_arp_rsp_template) +
1105ec8a448e0e978103bc5ca7136084b5e2b36989eEliad Peller		   WL1271_EXTRA_SPACE_MAX;
111cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller	ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
112cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller				      CMD_TEMPL_ARP_RSP, NULL,
1135ec8a448e0e978103bc5ca7136084b5e2b36989eEliad Peller				      max_size,
114c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller				      0, WL1271_RATE_AUTOMATIC);
115c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller	if (ret < 0)
116c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller		return ret;
117c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller
11892c77c734f958474ac73af670834bc32cb833e54Eliad Peller	/*
11992c77c734f958474ac73af670834bc32cb833e54Eliad Peller	 * Put very large empty placeholders for all templates. These
12092c77c734f958474ac73af670834bc32cb833e54Eliad Peller	 * reserve memory for later.
12192c77c734f958474ac73af670834bc32cb833e54Eliad Peller	 */
122cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller	ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
123cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller				      CMD_TEMPL_AP_PROBE_RESPONSE, NULL,
12492c77c734f958474ac73af670834bc32cb833e54Eliad Peller				      WL1271_CMD_TEMPL_MAX_SIZE,
12592c77c734f958474ac73af670834bc32cb833e54Eliad Peller				      0, WL1271_RATE_AUTOMATIC);
12692c77c734f958474ac73af670834bc32cb833e54Eliad Peller	if (ret < 0)
12792c77c734f958474ac73af670834bc32cb833e54Eliad Peller		return ret;
12892c77c734f958474ac73af670834bc32cb833e54Eliad Peller
129cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller	ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
130cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller				      CMD_TEMPL_AP_BEACON, NULL,
13192c77c734f958474ac73af670834bc32cb833e54Eliad Peller				      WL1271_CMD_TEMPL_MAX_SIZE,
13292c77c734f958474ac73af670834bc32cb833e54Eliad Peller				      0, WL1271_RATE_AUTOMATIC);
13392c77c734f958474ac73af670834bc32cb833e54Eliad Peller	if (ret < 0)
13492c77c734f958474ac73af670834bc32cb833e54Eliad Peller		return ret;
13592c77c734f958474ac73af670834bc32cb833e54Eliad Peller
136cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller	ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
137cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller				      CMD_TEMPL_DEAUTH_AP, NULL,
13892c77c734f958474ac73af670834bc32cb833e54Eliad Peller				      sizeof
13992c77c734f958474ac73af670834bc32cb833e54Eliad Peller				      (struct wl12xx_disconn_template),
14092c77c734f958474ac73af670834bc32cb833e54Eliad Peller				      0, WL1271_RATE_AUTOMATIC);
14192c77c734f958474ac73af670834bc32cb833e54Eliad Peller	if (ret < 0)
14292c77c734f958474ac73af670834bc32cb833e54Eliad Peller		return ret;
14392c77c734f958474ac73af670834bc32cb833e54Eliad Peller
144bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen	for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
145cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller		ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
146cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller					      CMD_TEMPL_KLV, NULL,
14797127e67218e5970a5a7df0513ded730b19a67e9Eliad Peller					      sizeof(struct ieee80211_qos_hdr),
14897127e67218e5970a5a7df0513ded730b19a67e9Eliad Peller					      i, WL1271_RATE_AUTOMATIC);
149bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen		if (ret < 0)
150bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen			return ret;
151bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen	}
152bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen
153f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	return 0;
154f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho}
155f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
15687fbcb0f8c5c8fd57a4e3e7e638977c04ce1e0caEliad Pellerstatic int wl1271_ap_init_deauth_template(struct wl1271 *wl,
15787fbcb0f8c5c8fd57a4e3e7e638977c04ce1e0caEliad Peller					  struct wl12xx_vif *wlvif)
158e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov{
159e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	struct wl12xx_disconn_template *tmpl;
160e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	int ret;
161af7fbb28efff0c0d8fc0852ad6622e5437a7611eEliad Peller	u32 rate;
162e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
163e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
164e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (!tmpl) {
165e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		ret = -ENOMEM;
166e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		goto out;
167e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	}
168e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
169e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	tmpl->header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
170e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov					     IEEE80211_STYPE_DEAUTH);
171e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
17287fbcb0f8c5c8fd57a4e3e7e638977c04ce1e0caEliad Peller	rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set);
173cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller	ret = wl1271_cmd_template_set(wl, wlvif->role_id,
174cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller				      CMD_TEMPL_DEAUTH_AP,
175af7fbb28efff0c0d8fc0852ad6622e5437a7611eEliad Peller				      tmpl, sizeof(*tmpl), 0, rate);
176e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
177e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsovout:
178e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	kfree(tmpl);
179e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	return ret;
180e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov}
181e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
182784f694d0f3ca927361aa0c26de1aa340eb5b275Eliad Pellerstatic int wl1271_ap_init_null_template(struct wl1271 *wl,
183784f694d0f3ca927361aa0c26de1aa340eb5b275Eliad Peller					struct ieee80211_vif *vif)
184e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov{
18587fbcb0f8c5c8fd57a4e3e7e638977c04ce1e0caEliad Peller	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
186e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	struct ieee80211_hdr_3addr *nullfunc;
187e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	int ret;
188af7fbb28efff0c0d8fc0852ad6622e5437a7611eEliad Peller	u32 rate;
189e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
190e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	nullfunc = kzalloc(sizeof(*nullfunc), GFP_KERNEL);
191e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (!nullfunc) {
192e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		ret = -ENOMEM;
193e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		goto out;
194e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	}
195e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
196e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
197e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov					      IEEE80211_STYPE_NULLFUNC |
198e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov					      IEEE80211_FCTL_FROMDS);
199e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
200e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	/* nullfunc->addr1 is filled by FW */
201e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
202784f694d0f3ca927361aa0c26de1aa340eb5b275Eliad Peller	memcpy(nullfunc->addr2, vif->addr, ETH_ALEN);
203784f694d0f3ca927361aa0c26de1aa340eb5b275Eliad Peller	memcpy(nullfunc->addr3, vif->addr, ETH_ALEN);
204e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
20587fbcb0f8c5c8fd57a4e3e7e638977c04ce1e0caEliad Peller	rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set);
206cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller	ret = wl1271_cmd_template_set(wl, wlvif->role_id,
207cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller				      CMD_TEMPL_NULL_DATA, nullfunc,
208af7fbb28efff0c0d8fc0852ad6622e5437a7611eEliad Peller				      sizeof(*nullfunc), 0, rate);
209e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
210e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsovout:
211e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	kfree(nullfunc);
212e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	return ret;
213e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov}
214e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
215784f694d0f3ca927361aa0c26de1aa340eb5b275Eliad Pellerstatic int wl1271_ap_init_qos_null_template(struct wl1271 *wl,
216784f694d0f3ca927361aa0c26de1aa340eb5b275Eliad Peller					    struct ieee80211_vif *vif)
217e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov{
21887fbcb0f8c5c8fd57a4e3e7e638977c04ce1e0caEliad Peller	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
219e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	struct ieee80211_qos_hdr *qosnull;
220e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	int ret;
221af7fbb28efff0c0d8fc0852ad6622e5437a7611eEliad Peller	u32 rate;
222e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
223e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	qosnull = kzalloc(sizeof(*qosnull), GFP_KERNEL);
224e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (!qosnull) {
225e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		ret = -ENOMEM;
226e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		goto out;
227e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	}
228e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
229e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	qosnull->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
230e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov					     IEEE80211_STYPE_QOS_NULLFUNC |
231e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov					     IEEE80211_FCTL_FROMDS);
232e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
233e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	/* qosnull->addr1 is filled by FW */
234e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
235784f694d0f3ca927361aa0c26de1aa340eb5b275Eliad Peller	memcpy(qosnull->addr2, vif->addr, ETH_ALEN);
236784f694d0f3ca927361aa0c26de1aa340eb5b275Eliad Peller	memcpy(qosnull->addr3, vif->addr, ETH_ALEN);
237e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
23887fbcb0f8c5c8fd57a4e3e7e638977c04ce1e0caEliad Peller	rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set);
239cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller	ret = wl1271_cmd_template_set(wl, wlvif->role_id,
240cdaac6281170ee2934ad443cb60fbdd6cf318b64Eliad Peller				      CMD_TEMPL_QOS_NULL_DATA, qosnull,
241af7fbb28efff0c0d8fc0852ad6622e5437a7611eEliad Peller				      sizeof(*qosnull), 0, rate);
242e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
243e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsovout:
244e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	kfree(qosnull);
245e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	return ret;
246e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov}
247e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
24892c77c734f958474ac73af670834bc32cb833e54Eliad Pellerstatic int wl12xx_init_rx_config(struct wl1271 *wl)
249e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov{
250e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	int ret;
251e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
25292c77c734f958474ac73af670834bc32cb833e54Eliad Peller	ret = wl1271_acx_rx_msdu_life_time(wl);
253e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
254e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
255e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
256e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	return 0;
257e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov}
258e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
2590603d891c5b5153f667a79357d4652824c22b54eEliad Pellerstatic int wl12xx_init_phy_vif_config(struct wl1271 *wl,
2600603d891c5b5153f667a79357d4652824c22b54eEliad Peller					    struct wl12xx_vif *wlvif)
261f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{
262f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	int ret;
263f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
2640603d891c5b5153f667a79357d4652824c22b54eEliad Peller	ret = wl1271_acx_slot(wl, wlvif, DEFAULT_SLOT_TIME);
265f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
266f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
267f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
2680603d891c5b5153f667a79357d4652824c22b54eEliad Peller	ret = wl1271_acx_service_period_timeout(wl, wlvif);
269f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
270f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
271f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
2720603d891c5b5153f667a79357d4652824c22b54eEliad Peller	ret = wl1271_acx_rts_threshold(wl, wlvif, wl->hw->wiphy->rts_threshold);
273f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
274f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
275f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
276f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	return 0;
277f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho}
278f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
279a693534b1a46ee934606cec52b12baeaebba0342Arik Nemtsovstatic int wl1271_init_sta_beacon_filter(struct wl1271 *wl,
280a693534b1a46ee934606cec52b12baeaebba0342Arik Nemtsov					 struct wl12xx_vif *wlvif)
281f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{
282f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	int ret;
283f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
284a693534b1a46ee934606cec52b12baeaebba0342Arik Nemtsov	ret = wl1271_acx_beacon_filter_table(wl, wlvif);
285f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
286f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
287f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
288a693534b1a46ee934606cec52b12baeaebba0342Arik Nemtsov	/* enable beacon filtering */
289a693534b1a46ee934606cec52b12baeaebba0342Arik Nemtsov	ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true);
290f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
291f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
292f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
293f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	return 0;
294f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho}
295f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
29612419cce88fa591a846a542d35cff43b69d9e271Luciano Coelhoint wl1271_init_pta(struct wl1271 *wl)
297f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{
298f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	int ret;
299f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
3003be4112cb2c53fcda85fb408aea9a6f94075683bEliad Peller	ret = wl12xx_acx_sg_cfg(wl);
301f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
302f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
303f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
3047fc3a8647d2eaa8bc2f7ac7e9baff55199da7be6Juuso Oikarinen	ret = wl1271_acx_sg_enable(wl, wl->sg_enabled);
305f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
306f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
307f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
308f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	return 0;
309f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho}
310f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
31112419cce88fa591a846a542d35cff43b69d9e271Luciano Coelhoint wl1271_init_energy_detection(struct wl1271 *wl)
312f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{
313f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	int ret;
314f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
315f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_acx_cca_threshold(wl);
316f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
317f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
318f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
319f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	return 0;
320f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho}
321f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
3220603d891c5b5153f667a79357d4652824c22b54eEliad Pellerstatic int wl1271_init_beacon_broadcast(struct wl1271 *wl,
3230603d891c5b5153f667a79357d4652824c22b54eEliad Peller					struct wl12xx_vif *wlvif)
324f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{
325f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	int ret;
326f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
3270603d891c5b5153f667a79357d4652824c22b54eEliad Peller	ret = wl1271_acx_bcn_dtim_options(wl, wlvif);
328f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
329f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
330f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
331f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	return 0;
332f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho}
333f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
33495dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yarivstatic int wl12xx_init_fwlog(struct wl1271 *wl)
33595dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv{
33695dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv	int ret;
33795dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv
3386f7dd16cb125468a5393861c22fbecfb52dd9653Luciano Coelho	if (wl->quirks & WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED)
33995dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv		return 0;
34095dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv
34195dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv	ret = wl12xx_cmd_config_fwlog(wl);
34295dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv	if (ret < 0)
34395dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv		return ret;
34495dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv
34595dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv	return 0;
34695dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv}
34795dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv
34892c77c734f958474ac73af670834bc32cb833e54Eliad Peller/* generic sta initialization (non vif-specific) */
34930d0c8fd5b87d1c5486705d6420545a21533e115Eliad Pellerstatic int wl1271_sta_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif)
350e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov{
351e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	int ret;
352e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
353c8bde243421d759844264cf11e4248e7862c2722Eliad Peller	/* PS config */
354d2d66c56cf6c8727662aa321991f791604c22094Eliad Peller	ret = wl12xx_acx_config_ps(wl, wlvif);
355c8bde243421d759844264cf11e4248e7862c2722Eliad Peller	if (ret < 0)
356c8bde243421d759844264cf11e4248e7862c2722Eliad Peller		return ret;
357c8bde243421d759844264cf11e4248e7862c2722Eliad Peller
358ff86843dfbb368766d0aecd0147821d9a2b60edbShahar Levi	/* FM WLAN coexistence */
359ff86843dfbb368766d0aecd0147821d9a2b60edbShahar Levi	ret = wl1271_acx_fm_coex(wl);
360ff86843dfbb368766d0aecd0147821d9a2b60edbShahar Levi	if (ret < 0)
361ff86843dfbb368766d0aecd0147821d9a2b60edbShahar Levi		return ret;
362ff86843dfbb368766d0aecd0147821d9a2b60edbShahar Levi
36330d0c8fd5b87d1c5486705d6420545a21533e115Eliad Peller	ret = wl1271_acx_sta_rate_policies(wl, wlvif);
364e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
365e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
366e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
367e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	return 0;
368e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov}
369e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
3700603d891c5b5153f667a79357d4652824c22b54eEliad Pellerstatic int wl1271_sta_hw_init_post_mem(struct wl1271 *wl,
3710603d891c5b5153f667a79357d4652824c22b54eEliad Peller				       struct ieee80211_vif *vif)
372e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov{
3730603d891c5b5153f667a79357d4652824c22b54eEliad Peller	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
374e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	int ret, i;
375e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
376e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	/* disable all keep-alive templates */
377e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
3780603d891c5b5153f667a79357d4652824c22b54eEliad Peller		ret = wl1271_acx_keep_alive_config(wl, wlvif, i,
379e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov						   ACX_KEEP_ALIVE_TPL_INVALID);
380e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		if (ret < 0)
381e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov			return ret;
382e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	}
383e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
384e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	/* disable the keep-alive feature */
3850603d891c5b5153f667a79357d4652824c22b54eEliad Peller	ret = wl1271_acx_keep_alive_mode(wl, wlvif, false);
386e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
387e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
388e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
389e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	return 0;
390e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov}
391e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
39292c77c734f958474ac73af670834bc32cb833e54Eliad Peller/* generic ap initialization (non vif-specific) */
39387fbcb0f8c5c8fd57a4e3e7e638977c04ce1e0caEliad Pellerstatic int wl1271_ap_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif)
394e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov{
39570f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	int ret;
396e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
39787fbcb0f8c5c8fd57a4e3e7e638977c04ce1e0caEliad Peller	ret = wl1271_init_ap_rates(wl, wlvif);
398e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
399e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
400e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
401e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	return 0;
402e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov}
403e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
404784f694d0f3ca927361aa0c26de1aa340eb5b275Eliad Pellerint wl1271_ap_init_templates(struct wl1271 *wl, struct ieee80211_vif *vif)
405e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov{
40687fbcb0f8c5c8fd57a4e3e7e638977c04ce1e0caEliad Peller	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
407e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	int ret;
408e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
40987fbcb0f8c5c8fd57a4e3e7e638977c04ce1e0caEliad Peller	ret = wl1271_ap_init_deauth_template(wl, wlvif);
410e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
411e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
412e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
413784f694d0f3ca927361aa0c26de1aa340eb5b275Eliad Peller	ret = wl1271_ap_init_null_template(wl, vif);
414e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
415e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
416e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
417784f694d0f3ca927361aa0c26de1aa340eb5b275Eliad Peller	ret = wl1271_ap_init_qos_null_template(wl, vif);
418e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
419e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
420e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
421521a4a23261354885c01bf75b42150629004ed83Arik Nemtsov	/*
422521a4a23261354885c01bf75b42150629004ed83Arik Nemtsov	 * when operating as AP we want to receive external beacons for
423521a4a23261354885c01bf75b42150629004ed83Arik Nemtsov	 * configuring ERP protection.
424521a4a23261354885c01bf75b42150629004ed83Arik Nemtsov	 */
4250603d891c5b5153f667a79357d4652824c22b54eEliad Peller	ret = wl1271_acx_beacon_filter_opt(wl, wlvif, false);
426521a4a23261354885c01bf75b42150629004ed83Arik Nemtsov	if (ret < 0)
427521a4a23261354885c01bf75b42150629004ed83Arik Nemtsov		return ret;
428521a4a23261354885c01bf75b42150629004ed83Arik Nemtsov
429e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	return 0;
430e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov}
431e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
432784f694d0f3ca927361aa0c26de1aa340eb5b275Eliad Pellerstatic int wl1271_ap_hw_init_post_mem(struct wl1271 *wl,
433784f694d0f3ca927361aa0c26de1aa340eb5b275Eliad Peller				      struct ieee80211_vif *vif)
434c45a85b5a3c0ca841a7ffc700bdece8ee01486beArik Nemtsov{
435784f694d0f3ca927361aa0c26de1aa340eb5b275Eliad Peller	return wl1271_ap_init_templates(wl, vif);
436c45a85b5a3c0ca841a7ffc700bdece8ee01486beArik Nemtsov}
437c45a85b5a3c0ca841a7ffc700bdece8ee01486beArik Nemtsov
43887fbcb0f8c5c8fd57a4e3e7e638977c04ce1e0caEliad Pellerint wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif)
43970f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov{
44070f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	int i, ret;
44170f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	struct conf_tx_rate_class rc;
44270f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	u32 supported_rates;
44370f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov
44487fbcb0f8c5c8fd57a4e3e7e638977c04ce1e0caEliad Peller	wl1271_debug(DEBUG_AP, "AP basic rate set: 0x%x",
44587fbcb0f8c5c8fd57a4e3e7e638977c04ce1e0caEliad Peller		     wlvif->basic_rate_set);
44670f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov
44787fbcb0f8c5c8fd57a4e3e7e638977c04ce1e0caEliad Peller	if (wlvif->basic_rate_set == 0)
44870f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov		return -EINVAL;
44970f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov
45087fbcb0f8c5c8fd57a4e3e7e638977c04ce1e0caEliad Peller	rc.enabled_rates = wlvif->basic_rate_set;
45170f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	rc.long_retry_limit = 10;
45270f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	rc.short_retry_limit = 10;
45370f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	rc.aflags = 0;
454e5a359f873f50cc123d5ca97637caa30fa095bb9Eliad Peller	ret = wl1271_acx_ap_rate_policy(wl, &rc, wlvif->ap.mgmt_rate_idx);
45570f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	if (ret < 0)
45670f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov		return ret;
45770f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov
45870f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	/* use the min basic rate for AP broadcast/multicast */
45987fbcb0f8c5c8fd57a4e3e7e638977c04ce1e0caEliad Peller	rc.enabled_rates = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set);
46070f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	rc.short_retry_limit = 10;
46170f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	rc.long_retry_limit = 10;
46270f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	rc.aflags = 0;
463e5a359f873f50cc123d5ca97637caa30fa095bb9Eliad Peller	ret = wl1271_acx_ap_rate_policy(wl, &rc, wlvif->ap.bcast_rate_idx);
46470f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	if (ret < 0)
46570f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov		return ret;
46670f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov
46770f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	/*
46870f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	 * If the basic rates contain OFDM rates, use OFDM only
46970f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	 * rates for unicast TX as well. Else use all supported rates.
47070f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	 */
47187fbcb0f8c5c8fd57a4e3e7e638977c04ce1e0caEliad Peller	if ((wlvif->basic_rate_set & CONF_TX_OFDM_RATES))
47270f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov		supported_rates = CONF_TX_OFDM_RATES;
47370f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	else
47470f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov		supported_rates = CONF_TX_AP_ENABLED_RATES;
47570f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov
4761a8adb67f9c37cad9539dd9dcb289ce1411680fcArik Nemtsov	/* unconditionally enable HT rates */
4771a8adb67f9c37cad9539dd9dcb289ce1411680fcArik Nemtsov	supported_rates |= CONF_TX_MCS_RATES;
4781a8adb67f9c37cad9539dd9dcb289ce1411680fcArik Nemtsov
479ebc7e57ddd01ffa4c996dde7095746259693755dArik Nemtsov	/* get extra MIMO or wide-chan rates where the HW supports it */
480ebc7e57ddd01ffa4c996dde7095746259693755dArik Nemtsov	supported_rates |= wlcore_hw_ap_get_mimo_wide_rate_mask(wl, wlvif);
481ebc7e57ddd01ffa4c996dde7095746259693755dArik Nemtsov
48270f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	/* configure unicast TX rate classes */
48370f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
48470f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov		rc.enabled_rates = supported_rates;
48570f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov		rc.short_retry_limit = 10;
48670f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov		rc.long_retry_limit = 10;
48770f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov		rc.aflags = 0;
488e5a359f873f50cc123d5ca97637caa30fa095bb9Eliad Peller		ret = wl1271_acx_ap_rate_policy(wl, &rc,
489e5a359f873f50cc123d5ca97637caa30fa095bb9Eliad Peller						wlvif->ap.ucast_rate_idx[i]);
49070f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov		if (ret < 0)
49170f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov			return ret;
49270f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	}
49370f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov
49470f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	return 0;
49570f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov}
49670f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov
497536129c8ad35de87ff2f864f205a54ac32bfebccEliad Pellerstatic int wl1271_set_ba_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif)
4984b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar{
4994b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar	/* Reset the BA RX indicators */
500d0802abdf9c60b1dadb097e806022f3449b0cc6bEliad Peller	wlvif->ba_allowed = true;
5010f9c8250e10a16f48f82ffda3a5a7cb9e7b4a9eeArik Nemtsov	wl->ba_rx_session_count = 0;
5024b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar
5030f9c8250e10a16f48f82ffda3a5a7cb9e7b4a9eeArik Nemtsov	/* BA is supported in STA/AP modes */
504536129c8ad35de87ff2f864f205a54ac32bfebccEliad Peller	if (wlvif->bss_type != BSS_TYPE_AP_BSS &&
505536129c8ad35de87ff2f864f205a54ac32bfebccEliad Peller	    wlvif->bss_type != BSS_TYPE_STA_BSS) {
506d0802abdf9c60b1dadb097e806022f3449b0cc6bEliad Peller		wlvif->ba_support = false;
5070f9c8250e10a16f48f82ffda3a5a7cb9e7b4a9eeArik Nemtsov		return 0;
5080f9c8250e10a16f48f82ffda3a5a7cb9e7b4a9eeArik Nemtsov	}
5094b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar
510d0802abdf9c60b1dadb097e806022f3449b0cc6bEliad Peller	wlvif->ba_support = true;
5114b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar
5120f9c8250e10a16f48f82ffda3a5a7cb9e7b4a9eeArik Nemtsov	/* 802.11n initiator BA session setting */
5130603d891c5b5153f667a79357d4652824c22b54eEliad Peller	return wl12xx_acx_set_ba_initiator_policy(wl, wlvif);
5144b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar}
5154b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar
51692c77c734f958474ac73af670834bc32cb833e54Eliad Peller/* vif-specifc initialization */
5170603d891c5b5153f667a79357d4652824c22b54eEliad Pellerstatic int wl12xx_init_sta_role(struct wl1271 *wl, struct wl12xx_vif *wlvif)
51892c77c734f958474ac73af670834bc32cb833e54Eliad Peller{
51992c77c734f958474ac73af670834bc32cb833e54Eliad Peller	int ret;
52092c77c734f958474ac73af670834bc32cb833e54Eliad Peller
5210603d891c5b5153f667a79357d4652824c22b54eEliad Peller	ret = wl1271_acx_group_address_tbl(wl, wlvif, true, NULL, 0);
52292c77c734f958474ac73af670834bc32cb833e54Eliad Peller	if (ret < 0)
52392c77c734f958474ac73af670834bc32cb833e54Eliad Peller		return ret;
52492c77c734f958474ac73af670834bc32cb833e54Eliad Peller
52592c77c734f958474ac73af670834bc32cb833e54Eliad Peller	/* Initialize connection monitoring thresholds */
5260603d891c5b5153f667a79357d4652824c22b54eEliad Peller	ret = wl1271_acx_conn_monit_params(wl, wlvif, false);
52792c77c734f958474ac73af670834bc32cb833e54Eliad Peller	if (ret < 0)
52892c77c734f958474ac73af670834bc32cb833e54Eliad Peller		return ret;
52992c77c734f958474ac73af670834bc32cb833e54Eliad Peller
53092c77c734f958474ac73af670834bc32cb833e54Eliad Peller	/* Beacon filtering */
531a693534b1a46ee934606cec52b12baeaebba0342Arik Nemtsov	ret = wl1271_init_sta_beacon_filter(wl, wlvif);
53292c77c734f958474ac73af670834bc32cb833e54Eliad Peller	if (ret < 0)
53392c77c734f958474ac73af670834bc32cb833e54Eliad Peller		return ret;
53492c77c734f958474ac73af670834bc32cb833e54Eliad Peller
53592c77c734f958474ac73af670834bc32cb833e54Eliad Peller	/* Beacons and broadcast settings */
5360603d891c5b5153f667a79357d4652824c22b54eEliad Peller	ret = wl1271_init_beacon_broadcast(wl, wlvif);
53792c77c734f958474ac73af670834bc32cb833e54Eliad Peller	if (ret < 0)
53892c77c734f958474ac73af670834bc32cb833e54Eliad Peller		return ret;
53948a61477bdc04896bd96d259388a0c42a7019943Shahar Levi
54092c77c734f958474ac73af670834bc32cb833e54Eliad Peller	/* Configure rssi/snr averaging weights */
5410603d891c5b5153f667a79357d4652824c22b54eEliad Peller	ret = wl1271_acx_rssi_snr_avg_weights(wl, wlvif);
54292c77c734f958474ac73af670834bc32cb833e54Eliad Peller	if (ret < 0)
54392c77c734f958474ac73af670834bc32cb833e54Eliad Peller		return ret;
54492c77c734f958474ac73af670834bc32cb833e54Eliad Peller
54592c77c734f958474ac73af670834bc32cb833e54Eliad Peller	return 0;
54692c77c734f958474ac73af670834bc32cb833e54Eliad Peller}
54792c77c734f958474ac73af670834bc32cb833e54Eliad Peller
54892c77c734f958474ac73af670834bc32cb833e54Eliad Peller/* vif-specific intialization */
5490603d891c5b5153f667a79357d4652824c22b54eEliad Pellerstatic int wl12xx_init_ap_role(struct wl1271 *wl, struct wl12xx_vif *wlvif)
55092c77c734f958474ac73af670834bc32cb833e54Eliad Peller{
55192c77c734f958474ac73af670834bc32cb833e54Eliad Peller	int ret;
55292c77c734f958474ac73af670834bc32cb833e54Eliad Peller
5530603d891c5b5153f667a79357d4652824c22b54eEliad Peller	ret = wl1271_acx_ap_max_tx_retry(wl, wlvif);
55492c77c734f958474ac73af670834bc32cb833e54Eliad Peller	if (ret < 0)
55592c77c734f958474ac73af670834bc32cb833e54Eliad Peller		return ret;
55692c77c734f958474ac73af670834bc32cb833e54Eliad Peller
55792c77c734f958474ac73af670834bc32cb833e54Eliad Peller	/* initialize Tx power */
5586bd650299046f00df6d7374c7f61c5afe6df6696Eliad Peller	ret = wl1271_acx_tx_power(wl, wlvif, wlvif->power_level);
55992c77c734f958474ac73af670834bc32cb833e54Eliad Peller	if (ret < 0)
56092c77c734f958474ac73af670834bc32cb833e54Eliad Peller		return ret;
56192c77c734f958474ac73af670834bc32cb833e54Eliad Peller
56292c77c734f958474ac73af670834bc32cb833e54Eliad Peller	return 0;
56392c77c734f958474ac73af670834bc32cb833e54Eliad Peller}
56492c77c734f958474ac73af670834bc32cb833e54Eliad Peller
56592c77c734f958474ac73af670834bc32cb833e54Eliad Pellerint wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif)
566f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{
56787fbcb0f8c5c8fd57a4e3e7e638977c04ce1e0caEliad Peller	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
568243eeb51eaa0a33caeff3e2275b2460eea5579ecKalle Valo	struct conf_tx_ac_category *conf_ac;
569f2054df5170734eacd1db82138c70746ec8387deKalle Valo	struct conf_tx_tid *conf_tid;
570536129c8ad35de87ff2f864f205a54ac32bfebccEliad Peller	bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
57192c77c734f958474ac73af670834bc32cb833e54Eliad Peller	int ret, i;
57292c77c734f958474ac73af670834bc32cb833e54Eliad Peller
5732f18cf7c3b99779465def78318b4243d1f66cce8Arik Nemtsov	/* consider all existing roles before configuring psm. */
5742f18cf7c3b99779465def78318b4243d1f66cce8Arik Nemtsov
5752f18cf7c3b99779465def78318b4243d1f66cce8Arik Nemtsov	if (wl->ap_count == 0 && is_ap) { /* first AP */
5762f18cf7c3b99779465def78318b4243d1f66cce8Arik Nemtsov		/* Configure for power always on */
5772f18cf7c3b99779465def78318b4243d1f66cce8Arik Nemtsov		ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
5782f18cf7c3b99779465def78318b4243d1f66cce8Arik Nemtsov		if (ret < 0)
5792f18cf7c3b99779465def78318b4243d1f66cce8Arik Nemtsov			return ret;
5802f18cf7c3b99779465def78318b4243d1f66cce8Arik Nemtsov	/* first STA, no APs */
5812f18cf7c3b99779465def78318b4243d1f66cce8Arik Nemtsov	} else if (wl->sta_count == 0 && wl->ap_count == 0 && !is_ap) {
5822f18cf7c3b99779465def78318b4243d1f66cce8Arik Nemtsov		u8 sta_auth = wl->conf.conn.sta_sleep_auth;
5832f18cf7c3b99779465def78318b4243d1f66cce8Arik Nemtsov		/* Configure for power according to debugfs */
5842f18cf7c3b99779465def78318b4243d1f66cce8Arik Nemtsov		if (sta_auth != WL1271_PSM_ILLEGAL)
5852f18cf7c3b99779465def78318b4243d1f66cce8Arik Nemtsov			ret = wl1271_acx_sleep_auth(wl, sta_auth);
5862f18cf7c3b99779465def78318b4243d1f66cce8Arik Nemtsov		/* Configure for power always on */
5872f18cf7c3b99779465def78318b4243d1f66cce8Arik Nemtsov		else if (wl->quirks & WLCORE_QUIRK_NO_ELP)
588a4e4130dcea01f3e0dfcbfeaf0d815b971e6e515Eliad Peller			ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
5892f18cf7c3b99779465def78318b4243d1f66cce8Arik Nemtsov		/* Configure for ELP power saving */
5902f18cf7c3b99779465def78318b4243d1f66cce8Arik Nemtsov		else
5912f18cf7c3b99779465def78318b4243d1f66cce8Arik Nemtsov			ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
5922f18cf7c3b99779465def78318b4243d1f66cce8Arik Nemtsov
5932f18cf7c3b99779465def78318b4243d1f66cce8Arik Nemtsov		if (ret < 0)
5942f18cf7c3b99779465def78318b4243d1f66cce8Arik Nemtsov			return ret;
595a4e4130dcea01f3e0dfcbfeaf0d815b971e6e515Eliad Peller	}
596a4e4130dcea01f3e0dfcbfeaf0d815b971e6e515Eliad Peller
59792c77c734f958474ac73af670834bc32cb833e54Eliad Peller	/* Mode specific init */
59892c77c734f958474ac73af670834bc32cb833e54Eliad Peller	if (is_ap) {
59987fbcb0f8c5c8fd57a4e3e7e638977c04ce1e0caEliad Peller		ret = wl1271_ap_hw_init(wl, wlvif);
60092c77c734f958474ac73af670834bc32cb833e54Eliad Peller		if (ret < 0)
60192c77c734f958474ac73af670834bc32cb833e54Eliad Peller			return ret;
60292c77c734f958474ac73af670834bc32cb833e54Eliad Peller
6030603d891c5b5153f667a79357d4652824c22b54eEliad Peller		ret = wl12xx_init_ap_role(wl, wlvif);
60492c77c734f958474ac73af670834bc32cb833e54Eliad Peller		if (ret < 0)
60592c77c734f958474ac73af670834bc32cb833e54Eliad Peller			return ret;
60692c77c734f958474ac73af670834bc32cb833e54Eliad Peller	} else {
60730d0c8fd5b87d1c5486705d6420545a21533e115Eliad Peller		ret = wl1271_sta_hw_init(wl, wlvif);
60892c77c734f958474ac73af670834bc32cb833e54Eliad Peller		if (ret < 0)
60992c77c734f958474ac73af670834bc32cb833e54Eliad Peller			return ret;
61092c77c734f958474ac73af670834bc32cb833e54Eliad Peller
6110603d891c5b5153f667a79357d4652824c22b54eEliad Peller		ret = wl12xx_init_sta_role(wl, wlvif);
61292c77c734f958474ac73af670834bc32cb833e54Eliad Peller		if (ret < 0)
61392c77c734f958474ac73af670834bc32cb833e54Eliad Peller			return ret;
61492c77c734f958474ac73af670834bc32cb833e54Eliad Peller	}
61592c77c734f958474ac73af670834bc32cb833e54Eliad Peller
6160603d891c5b5153f667a79357d4652824c22b54eEliad Peller	wl12xx_init_phy_vif_config(wl, wlvif);
61792c77c734f958474ac73af670834bc32cb833e54Eliad Peller
61892c77c734f958474ac73af670834bc32cb833e54Eliad Peller	/* Default TID/AC configuration */
61992c77c734f958474ac73af670834bc32cb833e54Eliad Peller	BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count);
62092c77c734f958474ac73af670834bc32cb833e54Eliad Peller	for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
62192c77c734f958474ac73af670834bc32cb833e54Eliad Peller		conf_ac = &wl->conf.tx.ac_conf[i];
6220603d891c5b5153f667a79357d4652824c22b54eEliad Peller		ret = wl1271_acx_ac_cfg(wl, wlvif, conf_ac->ac,
6230603d891c5b5153f667a79357d4652824c22b54eEliad Peller					conf_ac->cw_min, conf_ac->cw_max,
6240603d891c5b5153f667a79357d4652824c22b54eEliad Peller					conf_ac->aifsn, conf_ac->tx_op_limit);
62592c77c734f958474ac73af670834bc32cb833e54Eliad Peller		if (ret < 0)
62692c77c734f958474ac73af670834bc32cb833e54Eliad Peller			return ret;
62792c77c734f958474ac73af670834bc32cb833e54Eliad Peller
62892c77c734f958474ac73af670834bc32cb833e54Eliad Peller		conf_tid = &wl->conf.tx.tid_conf[i];
6290603d891c5b5153f667a79357d4652824c22b54eEliad Peller		ret = wl1271_acx_tid_cfg(wl, wlvif,
63092c77c734f958474ac73af670834bc32cb833e54Eliad Peller					 conf_tid->queue_id,
63192c77c734f958474ac73af670834bc32cb833e54Eliad Peller					 conf_tid->channel_type,
63292c77c734f958474ac73af670834bc32cb833e54Eliad Peller					 conf_tid->tsid,
63392c77c734f958474ac73af670834bc32cb833e54Eliad Peller					 conf_tid->ps_scheme,
63492c77c734f958474ac73af670834bc32cb833e54Eliad Peller					 conf_tid->ack_policy,
63592c77c734f958474ac73af670834bc32cb833e54Eliad Peller					 conf_tid->apsd_conf[0],
63692c77c734f958474ac73af670834bc32cb833e54Eliad Peller					 conf_tid->apsd_conf[1]);
63792c77c734f958474ac73af670834bc32cb833e54Eliad Peller		if (ret < 0)
63892c77c734f958474ac73af670834bc32cb833e54Eliad Peller			return ret;
63992c77c734f958474ac73af670834bc32cb833e54Eliad Peller	}
64092c77c734f958474ac73af670834bc32cb833e54Eliad Peller
64192c77c734f958474ac73af670834bc32cb833e54Eliad Peller	/* Configure HW encryption */
6420603d891c5b5153f667a79357d4652824c22b54eEliad Peller	ret = wl1271_acx_feature_cfg(wl, wlvif);
64392c77c734f958474ac73af670834bc32cb833e54Eliad Peller	if (ret < 0)
64492c77c734f958474ac73af670834bc32cb833e54Eliad Peller		return ret;
64592c77c734f958474ac73af670834bc32cb833e54Eliad Peller
64692c77c734f958474ac73af670834bc32cb833e54Eliad Peller	/* Mode specific init - post mem init */
64792c77c734f958474ac73af670834bc32cb833e54Eliad Peller	if (is_ap)
64892c77c734f958474ac73af670834bc32cb833e54Eliad Peller		ret = wl1271_ap_hw_init_post_mem(wl, vif);
64992c77c734f958474ac73af670834bc32cb833e54Eliad Peller	else
6500603d891c5b5153f667a79357d4652824c22b54eEliad Peller		ret = wl1271_sta_hw_init_post_mem(wl, vif);
65192c77c734f958474ac73af670834bc32cb833e54Eliad Peller
65292c77c734f958474ac73af670834bc32cb833e54Eliad Peller	if (ret < 0)
65392c77c734f958474ac73af670834bc32cb833e54Eliad Peller		return ret;
65492c77c734f958474ac73af670834bc32cb833e54Eliad Peller
65592c77c734f958474ac73af670834bc32cb833e54Eliad Peller	/* Configure initiator BA sessions policies */
656536129c8ad35de87ff2f864f205a54ac32bfebccEliad Peller	ret = wl1271_set_ba_policies(wl, wlvif);
65792c77c734f958474ac73af670834bc32cb833e54Eliad Peller	if (ret < 0)
65892c77c734f958474ac73af670834bc32cb833e54Eliad Peller		return ret;
65992c77c734f958474ac73af670834bc32cb833e54Eliad Peller
6608a9affc08d676a9fe627361ab6767cdec0740af3Arik Nemtsov	ret = wlcore_hw_init_vif(wl, wlvif);
6618a9affc08d676a9fe627361ab6767cdec0740af3Arik Nemtsov	if (ret < 0)
6628a9affc08d676a9fe627361ab6767cdec0740af3Arik Nemtsov		return ret;
6638a9affc08d676a9fe627361ab6767cdec0740af3Arik Nemtsov
66492c77c734f958474ac73af670834bc32cb833e54Eliad Peller	return 0;
66592c77c734f958474ac73af670834bc32cb833e54Eliad Peller}
66692c77c734f958474ac73af670834bc32cb833e54Eliad Peller
66792c77c734f958474ac73af670834bc32cb833e54Eliad Pellerint wl1271_hw_init(struct wl1271 *wl)
66892c77c734f958474ac73af670834bc32cb833e54Eliad Peller{
66992c77c734f958474ac73af670834bc32cb833e54Eliad Peller	int ret;
67092c77c734f958474ac73af670834bc32cb833e54Eliad Peller
6719d68d1eea7fb4d05b5bd037da6a66329d640b2f1Luciano Coelho	/* Chip-specific hw init */
6729d68d1eea7fb4d05b5bd037da6a66329d640b2f1Luciano Coelho	ret = wl->ops->hw_init(wl);
67348a61477bdc04896bd96d259388a0c42a7019943Shahar Levi	if (ret < 0)
67448a61477bdc04896bd96d259388a0c42a7019943Shahar Levi		return ret;
67548a61477bdc04896bd96d259388a0c42a7019943Shahar Levi
67692c77c734f958474ac73af670834bc32cb833e54Eliad Peller	/* Init templates */
67792c77c734f958474ac73af670834bc32cb833e54Eliad Peller	ret = wl1271_init_templates_config(wl);
67892c77c734f958474ac73af670834bc32cb833e54Eliad Peller	if (ret < 0)
67992c77c734f958474ac73af670834bc32cb833e54Eliad Peller		return ret;
680644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen
68192c77c734f958474ac73af670834bc32cb833e54Eliad Peller	ret = wl12xx_acx_mem_cfg(wl);
68292c77c734f958474ac73af670834bc32cb833e54Eliad Peller	if (ret < 0)
68392c77c734f958474ac73af670834bc32cb833e54Eliad Peller		return ret;
68492c77c734f958474ac73af670834bc32cb833e54Eliad Peller
68592c77c734f958474ac73af670834bc32cb833e54Eliad Peller	/* Configure the FW logger */
68692c77c734f958474ac73af670834bc32cb833e54Eliad Peller	ret = wl12xx_init_fwlog(wl);
687f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
688f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
689f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
690801f870bc0524bad7ebef9cea52d20e4d4992e4aArik Nemtsov	/* Bluetooth WLAN coexistence */
691801f870bc0524bad7ebef9cea52d20e4d4992e4aArik Nemtsov	ret = wl1271_init_pta(wl);
692801f870bc0524bad7ebef9cea52d20e4d4992e4aArik Nemtsov	if (ret < 0)
693801f870bc0524bad7ebef9cea52d20e4d4992e4aArik Nemtsov		return ret;
694801f870bc0524bad7ebef9cea52d20e4d4992e4aArik Nemtsov
695f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	/* Default memory configuration */
696f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_acx_init_mem_config(wl);
697f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
698f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
699f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
700f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	/* RX config */
70108c1d1c7042330e2280a7718be4ad88c2e8f8268Eliad Peller	ret = wl12xx_init_rx_config(wl);
702f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
703f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		goto out_free_memmap;
704f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
7056e92b416b0aa6a59629cc32ee2b27129d73b98b8Luciano Coelho	ret = wl1271_acx_dco_itrim_params(wl);
7066e92b416b0aa6a59629cc32ee2b27129d73b98b8Luciano Coelho	if (ret < 0)
7076e92b416b0aa6a59629cc32ee2b27129d73b98b8Luciano Coelho		goto out_free_memmap;
7086e92b416b0aa6a59629cc32ee2b27129d73b98b8Luciano Coelho
709f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	/* Configure TX patch complete interrupt behavior */
710f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_acx_tx_config_options(wl);
711f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
712f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		goto out_free_memmap;
713f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
714f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	/* RX complete interrupt pacing */
715f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_acx_init_rx_interrupt(wl);
716f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
717f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		goto out_free_memmap;
718f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
719f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	/* Energy detection */
720f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_init_energy_detection(wl);
721f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
722f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		goto out_free_memmap;
723f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
724f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	/* Default fragmentation threshold */
7255f704d180e448d05859e1cb6572822ba27dbcdc7Arik Nemtsov	ret = wl1271_acx_frag_threshold(wl, wl->hw->wiphy->frag_threshold);
726f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
727f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		goto out_free_memmap;
728f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
729f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	/* Enable data path */
73094210897e2b7df8446fdecd360342149e5b4a400Luciano Coelho	ret = wl1271_cmd_data_path(wl, 1);
731f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
732f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		goto out_free_memmap;
733f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
73438ad2d87d42ba847c100ef132e8e363513982c8bJuuso Oikarinen	/* configure PM */
73538ad2d87d42ba847c100ef132e8e363513982c8bJuuso Oikarinen	ret = wl1271_acx_pm_config(wl);
73638ad2d87d42ba847c100ef132e8e363513982c8bJuuso Oikarinen	if (ret < 0)
73738ad2d87d42ba847c100ef132e8e363513982c8bJuuso Oikarinen		goto out_free_memmap;
73838ad2d87d42ba847c100ef132e8e363513982c8bJuuso Oikarinen
739fa6ad9f0f34b0754ce7551866b33587f077a2a51Eliad Peller	ret = wl12xx_acx_set_rate_mgmt_params(wl);
740fa6ad9f0f34b0754ce7551866b33587f077a2a51Eliad Peller	if (ret < 0)
741fa6ad9f0f34b0754ce7551866b33587f077a2a51Eliad Peller		goto out_free_memmap;
742fa6ad9f0f34b0754ce7551866b33587f077a2a51Eliad Peller
7439487775c5b785d7c1e8182825c9ff9cf5e88149eEliad Peller	/* configure hangover */
7449487775c5b785d7c1e8182825c9ff9cf5e88149eEliad Peller	ret = wl12xx_acx_config_hangover(wl);
7459487775c5b785d7c1e8182825c9ff9cf5e88149eEliad Peller	if (ret < 0)
7469487775c5b785d7c1e8182825c9ff9cf5e88149eEliad Peller		goto out_free_memmap;
7479487775c5b785d7c1e8182825c9ff9cf5e88149eEliad Peller
748f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	return 0;
749f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
750f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho out_free_memmap:
751f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	kfree(wl->target_mem_map);
752344152361e6d14ade61d7f43678db7418cb445dbJuuso Oikarinen	wl->target_mem_map = NULL;
753f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
754f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	return ret;
755f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho}
756