init.c revision 70f474241b3d5fb633635a2ce39ea9da4afeea6c
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
2800d201001bd4e8a46e3d03c970abcb72256c368bShahar Levi#include "init.h"
29f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho#include "wl12xx_80211.h"
3000d201001bd4e8a46e3d03c970abcb72256c368bShahar Levi#include "acx.h"
3100d201001bd4e8a46e3d03c970abcb72256c368bShahar Levi#include "cmd.h"
3200d201001bd4e8a46e3d03c970abcb72256c368bShahar Levi#include "reg.h"
33e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov#include "tx.h"
3448a61477bdc04896bd96d259388a0c42a7019943Shahar Levi#include "io.h"
35f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
36e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsovint wl1271_sta_init_templates_config(struct wl1271 *wl)
37f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{
38bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen	int ret, i;
39f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
40f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	/* send empty templates for fw memory reservation */
41f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
42ea559b460509b241cc1a3f36eebe0b2b634b3cf2Guy Eilam				      WL1271_CMD_TEMPL_MAX_SIZE,
43606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen				      0, WL1271_RATE_AUTOMATIC);
44f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
45f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
46f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
4711eb54298fa7197cb4187f8a3474ead0709f76ffJuuso Oikarinen	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
48ea559b460509b241cc1a3f36eebe0b2b634b3cf2Guy Eilam				      NULL, WL1271_CMD_TEMPL_MAX_SIZE, 0,
4911eb54298fa7197cb4187f8a3474ead0709f76ffJuuso Oikarinen				      WL1271_RATE_AUTOMATIC);
5011eb54298fa7197cb4187f8a3474ead0709f76ffJuuso Oikarinen	if (ret < 0)
5111eb54298fa7197cb4187f8a3474ead0709f76ffJuuso Oikarinen		return ret;
52abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi
53f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL,
54bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen				      sizeof(struct wl12xx_null_data_template),
55606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen				      0, WL1271_RATE_AUTOMATIC);
56f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
57f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
58f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
59f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL,
60bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen				      sizeof(struct wl12xx_ps_poll_template),
61606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen				      0, WL1271_RATE_AUTOMATIC);
62f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
63f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
64f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
65f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL,
66f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho				      sizeof
67bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen				      (struct wl12xx_qos_null_data_template),
68606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen				      0, WL1271_RATE_AUTOMATIC);
69f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
70f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
71f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
72f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL,
73f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho				      sizeof
74bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen				      (struct wl12xx_probe_resp_template),
75606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen				      0, WL1271_RATE_AUTOMATIC);
76f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
77f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
78f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
79f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL,
80f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho				      sizeof
81bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen				      (struct wl12xx_beacon_template),
82606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen				      0, WL1271_RATE_AUTOMATIC);
83f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
84f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
85f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
86c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP, NULL,
87c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller				      sizeof
88c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller				      (struct wl12xx_arp_rsp_template),
89c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller				      0, WL1271_RATE_AUTOMATIC);
90c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller	if (ret < 0)
91c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller		return ret;
92c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller
93bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen	for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
94bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen		ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL,
95606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen					      WL1271_CMD_TEMPL_MAX_SIZE, i,
96606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen					      WL1271_RATE_AUTOMATIC);
97bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen		if (ret < 0)
98bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen			return ret;
99bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen	}
100bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen
101f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	return 0;
102f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho}
103f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
104e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsovstatic int wl1271_ap_init_deauth_template(struct wl1271 *wl)
105e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov{
106e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	struct wl12xx_disconn_template *tmpl;
107e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	int ret;
108e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
109e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
110e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (!tmpl) {
111e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		ret = -ENOMEM;
112e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		goto out;
113e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	}
114e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
115e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	tmpl->header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
116e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov					     IEEE80211_STYPE_DEAUTH);
117e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
118e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP,
119e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov				      tmpl, sizeof(*tmpl), 0,
120e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov				      wl1271_tx_min_rate_get(wl));
121e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
122e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsovout:
123e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	kfree(tmpl);
124e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	return ret;
125e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov}
126e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
127e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsovstatic int wl1271_ap_init_null_template(struct wl1271 *wl)
128e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov{
129e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	struct ieee80211_hdr_3addr *nullfunc;
130e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	int ret;
131e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
132e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	nullfunc = kzalloc(sizeof(*nullfunc), GFP_KERNEL);
133e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (!nullfunc) {
134e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		ret = -ENOMEM;
135e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		goto out;
136e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	}
137e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
138e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
139e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov					      IEEE80211_STYPE_NULLFUNC |
140e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov					      IEEE80211_FCTL_FROMDS);
141e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
142e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	/* nullfunc->addr1 is filled by FW */
143e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
144e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	memcpy(nullfunc->addr2, wl->mac_addr, ETH_ALEN);
145e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	memcpy(nullfunc->addr3, wl->mac_addr, ETH_ALEN);
146e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
147e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, nullfunc,
148e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov				      sizeof(*nullfunc), 0,
149e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov				      wl1271_tx_min_rate_get(wl));
150e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
151e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsovout:
152e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	kfree(nullfunc);
153e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	return ret;
154e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov}
155e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
156e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsovstatic int wl1271_ap_init_qos_null_template(struct wl1271 *wl)
157e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov{
158e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	struct ieee80211_qos_hdr *qosnull;
159e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	int ret;
160e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
161e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	qosnull = kzalloc(sizeof(*qosnull), GFP_KERNEL);
162e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (!qosnull) {
163e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		ret = -ENOMEM;
164e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		goto out;
165e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	}
166e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
167e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	qosnull->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
168e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov					     IEEE80211_STYPE_QOS_NULLFUNC |
169e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov					     IEEE80211_FCTL_FROMDS);
170e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
171e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	/* qosnull->addr1 is filled by FW */
172e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
173e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	memcpy(qosnull->addr2, wl->mac_addr, ETH_ALEN);
174e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	memcpy(qosnull->addr3, wl->mac_addr, ETH_ALEN);
175e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
176e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, qosnull,
177e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov				      sizeof(*qosnull), 0,
178e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov				      wl1271_tx_min_rate_get(wl));
179e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
180e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsovout:
181e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	kfree(qosnull);
182e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	return ret;
183e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov}
184e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
185e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsovstatic int wl1271_ap_init_templates_config(struct wl1271 *wl)
186e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov{
187e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	int ret;
188e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
189e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	/*
190e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	 * Put very large empty placeholders for all templates. These
191e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	 * reserve memory for later.
192e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	 */
193e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, NULL,
194e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov				      sizeof
195e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov				      (struct wl12xx_probe_resp_template),
196e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov				      0, WL1271_RATE_AUTOMATIC);
197e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
198e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
199e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
200e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_BEACON, NULL,
201e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov				      sizeof
202e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov				      (struct wl12xx_beacon_template),
203e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov				      0, WL1271_RATE_AUTOMATIC);
204e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
205e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
206e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
207e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, NULL,
208e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov				      sizeof
209e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov				      (struct wl12xx_disconn_template),
210e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov				      0, WL1271_RATE_AUTOMATIC);
211e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
212e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
213e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
214e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL,
215e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov				      sizeof(struct wl12xx_null_data_template),
216e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov				      0, WL1271_RATE_AUTOMATIC);
217e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
218e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
219e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
220e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL,
221e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov				      sizeof
222e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov				      (struct wl12xx_qos_null_data_template),
223e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov				      0, WL1271_RATE_AUTOMATIC);
224e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
225e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
226e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
227e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	return 0;
228e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov}
229e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
230f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhostatic int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter)
231f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{
232f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	int ret;
233f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
2348793f9bb19c00b26532e37f1f516e1d9c7bc0476Juuso Oikarinen	ret = wl1271_acx_rx_msdu_life_time(wl);
235f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
236f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
237f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
238f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_acx_rx_config(wl, config, filter);
239f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
240f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
241f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
242f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	return 0;
243f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho}
244f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
24512419cce88fa591a846a542d35cff43b69d9e271Luciano Coelhoint wl1271_init_phy_config(struct wl1271 *wl)
246f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{
247f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	int ret;
248f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
249f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_acx_pd_threshold(wl);
250f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
251f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
252f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
253f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_acx_slot(wl, DEFAULT_SLOT_TIME);
254f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
255f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
256f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
257f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_acx_service_period_timeout(wl);
258f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
259f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
260f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
2615f704d180e448d05859e1cb6572822ba27dbcdc7Arik Nemtsov	ret = wl1271_acx_rts_threshold(wl, wl->hw->wiphy->rts_threshold);
262f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
263f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
264f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
265f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	return 0;
266f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho}
267f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
268f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhostatic int wl1271_init_beacon_filter(struct wl1271 *wl)
269f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{
270f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	int ret;
271f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
2721922167b9de575d9d1a56be9b80f0fa3b22785f9Juuso Oikarinen	/* disable beacon filtering at this stage */
2731922167b9de575d9d1a56be9b80f0fa3b22785f9Juuso Oikarinen	ret = wl1271_acx_beacon_filter_opt(wl, false);
274f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
275f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
276f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
277f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_acx_beacon_filter_table(wl);
278f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
279f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
280f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
281f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	return 0;
282f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho}
283f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
28412419cce88fa591a846a542d35cff43b69d9e271Luciano Coelhoint wl1271_init_pta(struct wl1271 *wl)
285f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{
286f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	int ret;
287f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
288801f870bc0524bad7ebef9cea52d20e4d4992e4aArik Nemtsov	if (wl->bss_type == BSS_TYPE_AP_BSS)
289801f870bc0524bad7ebef9cea52d20e4d4992e4aArik Nemtsov		ret = wl1271_acx_ap_sg_cfg(wl);
290801f870bc0524bad7ebef9cea52d20e4d4992e4aArik Nemtsov	else
291801f870bc0524bad7ebef9cea52d20e4d4992e4aArik Nemtsov		ret = wl1271_acx_sta_sg_cfg(wl);
292f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
293f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
294f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
2957fc3a8647d2eaa8bc2f7ac7e9baff55199da7be6Juuso Oikarinen	ret = wl1271_acx_sg_enable(wl, wl->sg_enabled);
296f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
297f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
298f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
299f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	return 0;
300f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho}
301f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
30212419cce88fa591a846a542d35cff43b69d9e271Luciano Coelhoint wl1271_init_energy_detection(struct wl1271 *wl)
303f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{
304f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	int ret;
305f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
306f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_acx_cca_threshold(wl);
307f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
308f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
309f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
310f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	return 0;
311f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho}
312f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
313f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhostatic int wl1271_init_beacon_broadcast(struct wl1271 *wl)
314f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{
315f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	int ret;
316f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
317f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_acx_bcn_dtim_options(wl);
318f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
319f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
320f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
321f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	return 0;
322f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho}
323f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
324e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsovstatic int wl1271_sta_hw_init(struct wl1271 *wl)
325e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov{
326e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	int ret;
327e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
32849d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi	if (wl->chip.id != CHIP_ID_1283_PG20) {
32949d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi		ret = wl1271_cmd_ext_radio_parms(wl);
33049d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi		if (ret < 0)
33149d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi			return ret;
33249d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi	}
333e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
334c8bde243421d759844264cf11e4248e7862c2722Eliad Peller	/* PS config */
335c8bde243421d759844264cf11e4248e7862c2722Eliad Peller	ret = wl1271_acx_config_ps(wl);
336c8bde243421d759844264cf11e4248e7862c2722Eliad Peller	if (ret < 0)
337c8bde243421d759844264cf11e4248e7862c2722Eliad Peller		return ret;
338c8bde243421d759844264cf11e4248e7862c2722Eliad Peller
339e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_sta_init_templates_config(wl);
340e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
341e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
342e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
343e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0);
344e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
345e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
346e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
347e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	/* Initialize connection monitoring thresholds */
348e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_acx_conn_monit_params(wl, false);
349e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
350e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
351e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
352e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	/* Beacon filtering */
353e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_init_beacon_filter(wl);
354e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
355e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
356e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
357ff86843dfbb368766d0aecd0147821d9a2b60edbShahar Levi	/* FM WLAN coexistence */
358ff86843dfbb368766d0aecd0147821d9a2b60edbShahar Levi	ret = wl1271_acx_fm_coex(wl);
359ff86843dfbb368766d0aecd0147821d9a2b60edbShahar Levi	if (ret < 0)
360ff86843dfbb368766d0aecd0147821d9a2b60edbShahar Levi		return ret;
361ff86843dfbb368766d0aecd0147821d9a2b60edbShahar Levi
362e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	/* Beacons and broadcast settings */
363e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_init_beacon_broadcast(wl);
364e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
365e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
366e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
367e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	/* Configure for ELP power saving */
368e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
369e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
370e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
371e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
372e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	/* Configure rssi/snr averaging weights */
373e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_acx_rssi_snr_avg_weights(wl);
374e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
375e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
376e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
377e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_acx_sta_rate_policies(wl);
378e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
379e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
380e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
38147684808fd89d6809c0886e06f8ac324252499d8Arik Nemtsov	ret = wl1271_acx_sta_max_tx_retry(wl);
38247684808fd89d6809c0886e06f8ac324252499d8Arik Nemtsov	if (ret < 0)
38347684808fd89d6809c0886e06f8ac324252499d8Arik Nemtsov		return ret;
38447684808fd89d6809c0886e06f8ac324252499d8Arik Nemtsov
385c8bde243421d759844264cf11e4248e7862c2722Eliad Peller	ret = wl1271_acx_sta_mem_cfg(wl);
386c8bde243421d759844264cf11e4248e7862c2722Eliad Peller	if (ret < 0)
387c8bde243421d759844264cf11e4248e7862c2722Eliad Peller		return ret;
388c8bde243421d759844264cf11e4248e7862c2722Eliad Peller
389e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	return 0;
390e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov}
391e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
392e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsovstatic int wl1271_sta_hw_init_post_mem(struct wl1271 *wl)
393e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov{
394e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	int ret, i;
395e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
396e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_cmd_set_sta_default_wep_key(wl, wl->default_key);
397e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0) {
398e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		wl1271_warning("couldn't set default key");
399e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
400e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	}
401e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
402e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	/* disable all keep-alive templates */
403e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
404e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		ret = wl1271_acx_keep_alive_config(wl, i,
405e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov						   ACX_KEEP_ALIVE_TPL_INVALID);
406e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		if (ret < 0)
407e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov			return ret;
408e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	}
409e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
410e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	/* disable the keep-alive feature */
411e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_acx_keep_alive_mode(wl, false);
412e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
413e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
414e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
415e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	return 0;
416e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov}
417e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
418e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsovstatic int wl1271_ap_hw_init(struct wl1271 *wl)
419e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov{
42070f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	int ret;
421e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
422e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_ap_init_templates_config(wl);
423e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
424e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
425e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
426e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	/* Configure for power always on */
427e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
428e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
429e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
430e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
43170f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	ret = wl1271_init_ap_rates(wl);
432e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
433e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
434e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
43547684808fd89d6809c0886e06f8ac324252499d8Arik Nemtsov	ret = wl1271_acx_ap_max_tx_retry(wl);
436e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
437e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
438e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
439c8bde243421d759844264cf11e4248e7862c2722Eliad Peller	ret = wl1271_acx_ap_mem_cfg(wl);
440c8bde243421d759844264cf11e4248e7862c2722Eliad Peller	if (ret < 0)
441c8bde243421d759844264cf11e4248e7862c2722Eliad Peller		return ret;
442c8bde243421d759844264cf11e4248e7862c2722Eliad Peller
443e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	return 0;
444e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov}
445e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
446e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsovstatic int wl1271_ap_hw_init_post_mem(struct wl1271 *wl)
447e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov{
448e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	int ret;
449e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
450e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_ap_init_deauth_template(wl);
451e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
452e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
453e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
454e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_ap_init_null_template(wl);
455e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
456e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
457e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
458e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_ap_init_qos_null_template(wl);
459e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (ret < 0)
460e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		return ret;
461e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
462521a4a23261354885c01bf75b42150629004ed83Arik Nemtsov	/*
463521a4a23261354885c01bf75b42150629004ed83Arik Nemtsov	 * when operating as AP we want to receive external beacons for
464521a4a23261354885c01bf75b42150629004ed83Arik Nemtsov	 * configuring ERP protection.
465521a4a23261354885c01bf75b42150629004ed83Arik Nemtsov	 */
466521a4a23261354885c01bf75b42150629004ed83Arik Nemtsov	ret = wl1271_acx_set_ap_beacon_filter(wl, false);
467521a4a23261354885c01bf75b42150629004ed83Arik Nemtsov	if (ret < 0)
468521a4a23261354885c01bf75b42150629004ed83Arik Nemtsov		return ret;
469521a4a23261354885c01bf75b42150629004ed83Arik Nemtsov
470e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	return 0;
471e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov}
472e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov
47370f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsovint wl1271_init_ap_rates(struct wl1271 *wl)
47470f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov{
47570f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	int i, ret;
47670f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	struct conf_tx_rate_class rc;
47770f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	u32 supported_rates;
47870f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov
47970f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	wl1271_debug(DEBUG_AP, "AP basic rate set: 0x%x", wl->basic_rate_set);
48070f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov
48170f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	if (wl->basic_rate_set == 0)
48270f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov		return -EINVAL;
48370f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov
48470f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	rc.enabled_rates = wl->basic_rate_set;
48570f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	rc.long_retry_limit = 10;
48670f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	rc.short_retry_limit = 10;
48770f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	rc.aflags = 0;
48870f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	ret = wl1271_acx_ap_rate_policy(wl, &rc, ACX_TX_AP_MODE_MGMT_RATE);
48970f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	if (ret < 0)
49070f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov		return ret;
49170f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov
49270f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	/* use the min basic rate for AP broadcast/multicast */
49370f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	rc.enabled_rates = wl1271_tx_min_rate_get(wl);
49470f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	rc.short_retry_limit = 10;
49570f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	rc.long_retry_limit = 10;
49670f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	rc.aflags = 0;
49770f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	ret = wl1271_acx_ap_rate_policy(wl, &rc, ACX_TX_AP_MODE_BCST_RATE);
49870f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	if (ret < 0)
49970f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov		return ret;
50070f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov
50170f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	/*
50270f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	 * If the basic rates contain OFDM rates, use OFDM only
50370f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	 * rates for unicast TX as well. Else use all supported rates.
50470f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	 */
50570f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	if ((wl->basic_rate_set & CONF_TX_OFDM_RATES))
50670f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov		supported_rates = CONF_TX_OFDM_RATES;
50770f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	else
50870f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov		supported_rates = CONF_TX_AP_ENABLED_RATES;
50970f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov
51070f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	/* configure unicast TX rate classes */
51170f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
51270f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov		rc.enabled_rates = supported_rates;
51370f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov		rc.short_retry_limit = 10;
51470f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov		rc.long_retry_limit = 10;
51570f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov		rc.aflags = 0;
51670f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov		ret = wl1271_acx_ap_rate_policy(wl, &rc, i);
51770f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov		if (ret < 0)
51870f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov			return ret;
51970f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	}
52070f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov
52170f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov	return 0;
52270f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov}
52370f474241b3d5fb633635a2ce39ea9da4afeea6cArik Nemtsov
5244b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shaharstatic void wl1271_check_ba_support(struct wl1271 *wl)
5254b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar{
5264b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar	/* validate FW cose ver x.x.x.50-60.x */
5274b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar	if ((wl->chip.fw_ver[3] >= WL12XX_BA_SUPPORT_FW_COST_VER2_START) &&
5284b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar	    (wl->chip.fw_ver[3] < WL12XX_BA_SUPPORT_FW_COST_VER2_END)) {
5294b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar		wl->ba_support = true;
5304b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar		return;
5314b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar	}
5324b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar
5334b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar	wl->ba_support = false;
5344b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar}
5354b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar
5364b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shaharstatic int wl1271_set_ba_policies(struct wl1271 *wl)
5374b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar{
5384b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar	u8 tid_index;
53903c5a9cf49999ca3431eb9199c9bb831b0020be2Dan Carpenter	int ret = 0;
5404b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar
5414b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar	/* Reset the BA RX indicators */
5424b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar	wl->ba_rx_bitmap = 0;
5434b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar
5444b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar	/* validate that FW support BA */
5454b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar	wl1271_check_ba_support(wl);
5464b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar
5474b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar	if (wl->ba_support)
5484b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar		/* 802.11n initiator BA session setting */
5494b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar		for (tid_index = 0; tid_index < CONF_TX_MAX_TID_COUNT;
5504b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar		     ++tid_index) {
5514b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar			ret = wl1271_acx_set_ba_session(wl, WLAN_BACK_INITIATOR,
5524b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar							tid_index, true);
5534b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar			if (ret < 0)
5544b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar				break;
5554b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar		}
5564b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar
5574b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar	return ret;
5584b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar}
5594b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar
56048a61477bdc04896bd96d259388a0c42a7019943Shahar Leviint wl1271_chip_specific_init(struct wl1271 *wl)
56148a61477bdc04896bd96d259388a0c42a7019943Shahar Levi{
56248a61477bdc04896bd96d259388a0c42a7019943Shahar Levi	int ret = 0;
56348a61477bdc04896bd96d259388a0c42a7019943Shahar Levi
56448a61477bdc04896bd96d259388a0c42a7019943Shahar Levi	if (wl->chip.id == CHIP_ID_1283_PG20) {
56548a61477bdc04896bd96d259388a0c42a7019943Shahar Levi		u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE;
56648a61477bdc04896bd96d259388a0c42a7019943Shahar Levi
5670da13da767cd568c1fe2a7b5b936e86e521b5ae7Ido Yariv		if (wl->quirks & WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT)
56848a61477bdc04896bd96d259388a0c42a7019943Shahar Levi			/* Enable SDIO padding */
56948a61477bdc04896bd96d259388a0c42a7019943Shahar Levi			host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK;
57048a61477bdc04896bd96d259388a0c42a7019943Shahar Levi
57148a61477bdc04896bd96d259388a0c42a7019943Shahar Levi		/* Must be before wl1271_acx_init_mem_config() */
57248a61477bdc04896bd96d259388a0c42a7019943Shahar Levi		ret = wl1271_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap);
57348a61477bdc04896bd96d259388a0c42a7019943Shahar Levi		if (ret < 0)
57448a61477bdc04896bd96d259388a0c42a7019943Shahar Levi			goto out;
57548a61477bdc04896bd96d259388a0c42a7019943Shahar Levi	}
57648a61477bdc04896bd96d259388a0c42a7019943Shahar Leviout:
57748a61477bdc04896bd96d259388a0c42a7019943Shahar Levi	return ret;
57848a61477bdc04896bd96d259388a0c42a7019943Shahar Levi}
57948a61477bdc04896bd96d259388a0c42a7019943Shahar Levi
58048a61477bdc04896bd96d259388a0c42a7019943Shahar Levi
581f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_hw_init(struct wl1271 *wl)
582f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{
583243eeb51eaa0a33caeff3e2275b2460eea5579ecKalle Valo	struct conf_tx_ac_category *conf_ac;
584f2054df5170734eacd1db82138c70746ec8387deKalle Valo	struct conf_tx_tid *conf_tid;
585243eeb51eaa0a33caeff3e2275b2460eea5579ecKalle Valo	int ret, i;
586e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
587f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
58849d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi	if (wl->chip.id == CHIP_ID_1283_PG20)
58949d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi		ret = wl128x_cmd_general_parms(wl);
59049d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi	else
59149d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi		ret = wl1271_cmd_general_parms(wl);
5924a90406b876cade9bb8d9c95b048d60fb979ba6bLuciano Coelho	if (ret < 0)
593f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
594f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
59549d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi	if (wl->chip.id == CHIP_ID_1283_PG20)
59649d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi		ret = wl128x_cmd_radio_parms(wl);
59749d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi	else
59849d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi		ret = wl1271_cmd_radio_parms(wl);
5994a90406b876cade9bb8d9c95b048d60fb979ba6bLuciano Coelho	if (ret < 0)
600f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
601f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
60248a61477bdc04896bd96d259388a0c42a7019943Shahar Levi	/* Chip-specific init */
60348a61477bdc04896bd96d259388a0c42a7019943Shahar Levi	ret = wl1271_chip_specific_init(wl);
60448a61477bdc04896bd96d259388a0c42a7019943Shahar Levi	if (ret < 0)
60548a61477bdc04896bd96d259388a0c42a7019943Shahar Levi		return ret;
60648a61477bdc04896bd96d259388a0c42a7019943Shahar Levi
607e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	/* Mode specific init */
608e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (is_ap)
609e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		ret = wl1271_ap_hw_init(wl);
610e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	else
611e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		ret = wl1271_sta_hw_init(wl);
612644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen
613f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
614f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
615f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
616801f870bc0524bad7ebef9cea52d20e4d4992e4aArik Nemtsov	/* Bluetooth WLAN coexistence */
617801f870bc0524bad7ebef9cea52d20e4d4992e4aArik Nemtsov	ret = wl1271_init_pta(wl);
618801f870bc0524bad7ebef9cea52d20e4d4992e4aArik Nemtsov	if (ret < 0)
619801f870bc0524bad7ebef9cea52d20e4d4992e4aArik Nemtsov		return ret;
620801f870bc0524bad7ebef9cea52d20e4d4992e4aArik Nemtsov
621f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	/* Default memory configuration */
622f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_acx_init_mem_config(wl);
623f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
624f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		return ret;
625f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
626f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	/* RX config */
627f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_init_rx_config(wl,
628eb5b28d021a1b96050f7af46e9140eb0051cc6d8Juuso Oikarinen				    RX_CFG_PROMISCUOUS | RX_CFG_TSF,
629eb5b28d021a1b96050f7af46e9140eb0051cc6d8Juuso Oikarinen				    RX_FILTER_OPTION_DEF);
630f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	/* RX_CONFIG_OPTION_ANY_DST_ANY_BSS,
631f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	   RX_FILTER_OPTION_FILTER_ALL); */
632f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
633f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		goto out_free_memmap;
634f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
635f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	/* PHY layer config */
636f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_init_phy_config(wl);
637f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
638f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		goto out_free_memmap;
639f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
6406e92b416b0aa6a59629cc32ee2b27129d73b98b8Luciano Coelho	ret = wl1271_acx_dco_itrim_params(wl);
6416e92b416b0aa6a59629cc32ee2b27129d73b98b8Luciano Coelho	if (ret < 0)
6426e92b416b0aa6a59629cc32ee2b27129d73b98b8Luciano Coelho		goto out_free_memmap;
6436e92b416b0aa6a59629cc32ee2b27129d73b98b8Luciano Coelho
644f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	/* Configure TX patch complete interrupt behavior */
645f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_acx_tx_config_options(wl);
646f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
647f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		goto out_free_memmap;
648f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
649f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	/* RX complete interrupt pacing */
650f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_acx_init_rx_interrupt(wl);
651f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
652f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		goto out_free_memmap;
653f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
654f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	/* Energy detection */
655f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	ret = wl1271_init_energy_detection(wl);
656f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
657f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		goto out_free_memmap;
658f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
659f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	/* Default fragmentation threshold */
6605f704d180e448d05859e1cb6572822ba27dbcdc7Arik Nemtsov	ret = wl1271_acx_frag_threshold(wl, wl->hw->wiphy->frag_threshold);
661f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
662f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		goto out_free_memmap;
663f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
6649987a9da3eda093ceeff14ad4926adb130a0d0eaJuuso Oikarinen	/* Default TID/AC configuration */
6659987a9da3eda093ceeff14ad4926adb130a0d0eaJuuso Oikarinen	BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count);
666f2054df5170734eacd1db82138c70746ec8387deKalle Valo	for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
6679987a9da3eda093ceeff14ad4926adb130a0d0eaJuuso Oikarinen		conf_ac = &wl->conf.tx.ac_conf[i];
6689987a9da3eda093ceeff14ad4926adb130a0d0eaJuuso Oikarinen		ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
6699987a9da3eda093ceeff14ad4926adb130a0d0eaJuuso Oikarinen					conf_ac->cw_max, conf_ac->aifsn,
6709987a9da3eda093ceeff14ad4926adb130a0d0eaJuuso Oikarinen					conf_ac->tx_op_limit);
6719987a9da3eda093ceeff14ad4926adb130a0d0eaJuuso Oikarinen		if (ret < 0)
6729987a9da3eda093ceeff14ad4926adb130a0d0eaJuuso Oikarinen			goto out_free_memmap;
6739987a9da3eda093ceeff14ad4926adb130a0d0eaJuuso Oikarinen
674f2054df5170734eacd1db82138c70746ec8387deKalle Valo		conf_tid = &wl->conf.tx.tid_conf[i];
675f2054df5170734eacd1db82138c70746ec8387deKalle Valo		ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id,
676f2054df5170734eacd1db82138c70746ec8387deKalle Valo					 conf_tid->channel_type,
677f2054df5170734eacd1db82138c70746ec8387deKalle Valo					 conf_tid->tsid,
678f2054df5170734eacd1db82138c70746ec8387deKalle Valo					 conf_tid->ps_scheme,
679f2054df5170734eacd1db82138c70746ec8387deKalle Valo					 conf_tid->ack_policy,
680f2054df5170734eacd1db82138c70746ec8387deKalle Valo					 conf_tid->apsd_conf[0],
681f2054df5170734eacd1db82138c70746ec8387deKalle Valo					 conf_tid->apsd_conf[1]);
682f2054df5170734eacd1db82138c70746ec8387deKalle Valo		if (ret < 0)
683f2054df5170734eacd1db82138c70746ec8387deKalle Valo			goto out_free_memmap;
684f2054df5170734eacd1db82138c70746ec8387deKalle Valo	}
685f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
686f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	/* Enable data path */
68794210897e2b7df8446fdecd360342149e5b4a400Luciano Coelho	ret = wl1271_cmd_data_path(wl, 1);
688f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
689f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		goto out_free_memmap;
690f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
691f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	/* Configure HW encryption */
692e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	ret = wl1271_acx_feature_cfg(wl);
693f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	if (ret < 0)
694f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho		goto out_free_memmap;
695f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
69638ad2d87d42ba847c100ef132e8e363513982c8bJuuso Oikarinen	/* configure PM */
69738ad2d87d42ba847c100ef132e8e363513982c8bJuuso Oikarinen	ret = wl1271_acx_pm_config(wl);
69838ad2d87d42ba847c100ef132e8e363513982c8bJuuso Oikarinen	if (ret < 0)
69938ad2d87d42ba847c100ef132e8e363513982c8bJuuso Oikarinen		goto out_free_memmap;
70038ad2d87d42ba847c100ef132e8e363513982c8bJuuso Oikarinen
701e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	/* Mode specific init - post mem init */
702e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	if (is_ap)
703e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		ret = wl1271_ap_hw_init_post_mem(wl);
704e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov	else
705e0fe371b74326a85029fe8720506e021fe73905aArik Nemtsov		ret = wl1271_sta_hw_init_post_mem(wl);
706c18995540cc4d2c84d130581b8b6720b22ca16b5Juuso Oikarinen
70700236aedf1d2c49a18ae9ea00698d97705ff7289Juuso Oikarinen	if (ret < 0)
70800236aedf1d2c49a18ae9ea00698d97705ff7289Juuso Oikarinen		goto out_free_memmap;
70900236aedf1d2c49a18ae9ea00698d97705ff7289Juuso Oikarinen
7104b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar	/* Configure initiator BA sessions policies */
7114b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar	ret = wl1271_set_ba_policies(wl);
7124b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar	if (ret < 0)
7134b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar		goto out_free_memmap;
7144b7fac77b4c1badac84df3dcbdf07199d94cb1c3Levi, Shahar
715f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	return 0;
716f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
717f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho out_free_memmap:
718f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	kfree(wl->target_mem_map);
719344152361e6d14ade61d7f43678db7418cb445dbJuuso Oikarinen	wl->target_mem_map = NULL;
720f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho
721f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho	return ret;
722f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho}
723