1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright(c) 2018-2019  Realtek Corporation
3  */
4 
5 #include "main.h"
6 #include "coex.h"
7 #include "fw.h"
8 #include "tx.h"
9 #include "reg.h"
10 #include "debug.h"
11 
rtw_fw_c2h_cmd_handle_ext(struct rtw_dev * rtwdev,struct sk_buff * skb)12 static void rtw_fw_c2h_cmd_handle_ext(struct rtw_dev *rtwdev,
13 				      struct sk_buff *skb)
14 {
15 	struct rtw_c2h_cmd *c2h;
16 	u8 sub_cmd_id;
17 
18 	c2h = get_c2h_from_skb(skb);
19 	sub_cmd_id = c2h->payload[0];
20 
21 	switch (sub_cmd_id) {
22 	case C2H_CCX_RPT:
23 		rtw_tx_report_handle(rtwdev, skb);
24 		break;
25 	default:
26 		break;
27 	}
28 }
29 
rtw_fw_c2h_cmd_handle(struct rtw_dev * rtwdev,struct sk_buff * skb)30 void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
31 {
32 	struct rtw_c2h_cmd *c2h;
33 	u32 pkt_offset;
34 	u8 len;
35 
36 	pkt_offset = *((u32 *)skb->cb);
37 	c2h = (struct rtw_c2h_cmd *)(skb->data + pkt_offset);
38 	len = skb->len - pkt_offset - 2;
39 
40 	mutex_lock(&rtwdev->mutex);
41 
42 	switch (c2h->id) {
43 	case C2H_BT_INFO:
44 		rtw_coex_bt_info_notify(rtwdev, c2h->payload, len);
45 		break;
46 	case C2H_WLAN_INFO:
47 		rtw_coex_wl_fwdbginfo_notify(rtwdev, c2h->payload, len);
48 		break;
49 	case C2H_HALMAC:
50 		rtw_fw_c2h_cmd_handle_ext(rtwdev, skb);
51 		break;
52 	default:
53 		break;
54 	}
55 
56 	mutex_unlock(&rtwdev->mutex);
57 }
58 
rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev * rtwdev,u32 pkt_offset,struct sk_buff * skb)59 void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset,
60 			       struct sk_buff *skb)
61 {
62 	struct rtw_c2h_cmd *c2h;
63 	u8 len;
64 
65 	c2h = (struct rtw_c2h_cmd *)(skb->data + pkt_offset);
66 	len = skb->len - pkt_offset - 2;
67 	*((u32 *)skb->cb) = pkt_offset;
68 
69 	rtw_dbg(rtwdev, RTW_DBG_FW, "recv C2H, id=0x%02x, seq=0x%02x, len=%d\n",
70 		c2h->id, c2h->seq, len);
71 
72 	switch (c2h->id) {
73 	case C2H_BT_MP_INFO:
74 		rtw_coex_info_response(rtwdev, skb);
75 		break;
76 	default:
77 		/* pass offset for further operation */
78 		*((u32 *)skb->cb) = pkt_offset;
79 		skb_queue_tail(&rtwdev->c2h_queue, skb);
80 		ieee80211_queue_work(rtwdev->hw, &rtwdev->c2h_work);
81 		break;
82 	}
83 }
84 EXPORT_SYMBOL(rtw_fw_c2h_cmd_rx_irqsafe);
85 
rtw_fw_send_h2c_command(struct rtw_dev * rtwdev,u8 * h2c)86 static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev,
87 				    u8 *h2c)
88 {
89 	u8 box;
90 	u8 box_state;
91 	u32 box_reg, box_ex_reg;
92 	u32 h2c_wait;
93 	int idx;
94 
95 	rtw_dbg(rtwdev, RTW_DBG_FW,
96 		"send H2C content %02x%02x%02x%02x %02x%02x%02x%02x\n",
97 		h2c[3], h2c[2], h2c[1], h2c[0],
98 		h2c[7], h2c[6], h2c[5], h2c[4]);
99 
100 	spin_lock(&rtwdev->h2c.lock);
101 
102 	box = rtwdev->h2c.last_box_num;
103 	switch (box) {
104 	case 0:
105 		box_reg = REG_HMEBOX0;
106 		box_ex_reg = REG_HMEBOX0_EX;
107 		break;
108 	case 1:
109 		box_reg = REG_HMEBOX1;
110 		box_ex_reg = REG_HMEBOX1_EX;
111 		break;
112 	case 2:
113 		box_reg = REG_HMEBOX2;
114 		box_ex_reg = REG_HMEBOX2_EX;
115 		break;
116 	case 3:
117 		box_reg = REG_HMEBOX3;
118 		box_ex_reg = REG_HMEBOX3_EX;
119 		break;
120 	default:
121 		WARN(1, "invalid h2c mail box number\n");
122 		goto out;
123 	}
124 
125 	h2c_wait = 20;
126 	do {
127 		box_state = rtw_read8(rtwdev, REG_HMETFR);
128 	} while ((box_state >> box) & 0x1 && --h2c_wait > 0);
129 
130 	if (!h2c_wait) {
131 		rtw_err(rtwdev, "failed to send h2c command\n");
132 		goto out;
133 	}
134 
135 	for (idx = 0; idx < 4; idx++)
136 		rtw_write8(rtwdev, box_reg + idx, h2c[idx]);
137 	for (idx = 0; idx < 4; idx++)
138 		rtw_write8(rtwdev, box_ex_reg + idx, h2c[idx + 4]);
139 
140 	if (++rtwdev->h2c.last_box_num >= 4)
141 		rtwdev->h2c.last_box_num = 0;
142 
143 out:
144 	spin_unlock(&rtwdev->h2c.lock);
145 }
146 
rtw_fw_send_h2c_packet(struct rtw_dev * rtwdev,u8 * h2c_pkt)147 static void rtw_fw_send_h2c_packet(struct rtw_dev *rtwdev, u8 *h2c_pkt)
148 {
149 	int ret;
150 
151 	spin_lock(&rtwdev->h2c.lock);
152 
153 	FW_OFFLOAD_H2C_SET_SEQ_NUM(h2c_pkt, rtwdev->h2c.seq);
154 	ret = rtw_hci_write_data_h2c(rtwdev, h2c_pkt, H2C_PKT_SIZE);
155 	if (ret)
156 		rtw_err(rtwdev, "failed to send h2c packet\n");
157 	rtwdev->h2c.seq++;
158 
159 	spin_unlock(&rtwdev->h2c.lock);
160 }
161 
162 void
rtw_fw_send_general_info(struct rtw_dev * rtwdev)163 rtw_fw_send_general_info(struct rtw_dev *rtwdev)
164 {
165 	struct rtw_fifo_conf *fifo = &rtwdev->fifo;
166 	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
167 	u16 total_size = H2C_PKT_HDR_SIZE + 4;
168 
169 	rtw_h2c_pkt_set_header(h2c_pkt, H2C_PKT_GENERAL_INFO);
170 
171 	SET_PKT_H2C_TOTAL_LEN(h2c_pkt, total_size);
172 
173 	GENERAL_INFO_SET_FW_TX_BOUNDARY(h2c_pkt,
174 					fifo->rsvd_fw_txbuf_addr -
175 					fifo->rsvd_boundary);
176 
177 	rtw_fw_send_h2c_packet(rtwdev, h2c_pkt);
178 }
179 
180 void
rtw_fw_send_phydm_info(struct rtw_dev * rtwdev)181 rtw_fw_send_phydm_info(struct rtw_dev *rtwdev)
182 {
183 	struct rtw_hal *hal = &rtwdev->hal;
184 	struct rtw_efuse *efuse = &rtwdev->efuse;
185 	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
186 	u16 total_size = H2C_PKT_HDR_SIZE + 8;
187 	u8 fw_rf_type = 0;
188 
189 	if (hal->rf_type == RF_1T1R)
190 		fw_rf_type = FW_RF_1T1R;
191 	else if (hal->rf_type == RF_2T2R)
192 		fw_rf_type = FW_RF_2T2R;
193 
194 	rtw_h2c_pkt_set_header(h2c_pkt, H2C_PKT_PHYDM_INFO);
195 
196 	SET_PKT_H2C_TOTAL_LEN(h2c_pkt, total_size);
197 	PHYDM_INFO_SET_REF_TYPE(h2c_pkt, efuse->rfe_option);
198 	PHYDM_INFO_SET_RF_TYPE(h2c_pkt, fw_rf_type);
199 	PHYDM_INFO_SET_CUT_VER(h2c_pkt, hal->cut_version);
200 	PHYDM_INFO_SET_RX_ANT_STATUS(h2c_pkt, hal->antenna_tx);
201 	PHYDM_INFO_SET_TX_ANT_STATUS(h2c_pkt, hal->antenna_rx);
202 
203 	rtw_fw_send_h2c_packet(rtwdev, h2c_pkt);
204 }
205 
rtw_fw_do_iqk(struct rtw_dev * rtwdev,struct rtw_iqk_para * para)206 void rtw_fw_do_iqk(struct rtw_dev *rtwdev, struct rtw_iqk_para *para)
207 {
208 	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
209 	u16 total_size = H2C_PKT_HDR_SIZE + 1;
210 
211 	rtw_h2c_pkt_set_header(h2c_pkt, H2C_PKT_IQK);
212 	SET_PKT_H2C_TOTAL_LEN(h2c_pkt, total_size);
213 	IQK_SET_CLEAR(h2c_pkt, para->clear);
214 	IQK_SET_SEGMENT_IQK(h2c_pkt, para->segment_iqk);
215 
216 	rtw_fw_send_h2c_packet(rtwdev, h2c_pkt);
217 }
218 
rtw_fw_query_bt_info(struct rtw_dev * rtwdev)219 void rtw_fw_query_bt_info(struct rtw_dev *rtwdev)
220 {
221 	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
222 
223 	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_QUERY_BT_INFO);
224 
225 	SET_QUERY_BT_INFO(h2c_pkt, true);
226 
227 	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
228 }
229 
rtw_fw_wl_ch_info(struct rtw_dev * rtwdev,u8 link,u8 ch,u8 bw)230 void rtw_fw_wl_ch_info(struct rtw_dev *rtwdev, u8 link, u8 ch, u8 bw)
231 {
232 	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
233 
234 	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_WL_CH_INFO);
235 
236 	SET_WL_CH_INFO_LINK(h2c_pkt, link);
237 	SET_WL_CH_INFO_CHNL(h2c_pkt, ch);
238 	SET_WL_CH_INFO_BW(h2c_pkt, bw);
239 
240 	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
241 }
242 
rtw_fw_query_bt_mp_info(struct rtw_dev * rtwdev,struct rtw_coex_info_req * req)243 void rtw_fw_query_bt_mp_info(struct rtw_dev *rtwdev,
244 			     struct rtw_coex_info_req *req)
245 {
246 	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
247 
248 	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_QUERY_BT_MP_INFO);
249 
250 	SET_BT_MP_INFO_SEQ(h2c_pkt, req->seq);
251 	SET_BT_MP_INFO_OP_CODE(h2c_pkt, req->op_code);
252 	SET_BT_MP_INFO_PARA1(h2c_pkt, req->para1);
253 	SET_BT_MP_INFO_PARA2(h2c_pkt, req->para2);
254 	SET_BT_MP_INFO_PARA3(h2c_pkt, req->para3);
255 
256 	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
257 }
258 
rtw_fw_force_bt_tx_power(struct rtw_dev * rtwdev,u8 bt_pwr_dec_lvl)259 void rtw_fw_force_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl)
260 {
261 	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
262 	u8 index = 0 - bt_pwr_dec_lvl;
263 
264 	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_FORCE_BT_TX_POWER);
265 
266 	SET_BT_TX_POWER_INDEX(h2c_pkt, index);
267 
268 	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
269 }
270 
rtw_fw_bt_ignore_wlan_action(struct rtw_dev * rtwdev,bool enable)271 void rtw_fw_bt_ignore_wlan_action(struct rtw_dev *rtwdev, bool enable)
272 {
273 	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
274 
275 	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_IGNORE_WLAN_ACTION);
276 
277 	SET_IGNORE_WLAN_ACTION_EN(h2c_pkt, enable);
278 
279 	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
280 }
281 
rtw_fw_coex_tdma_type(struct rtw_dev * rtwdev,u8 para1,u8 para2,u8 para3,u8 para4,u8 para5)282 void rtw_fw_coex_tdma_type(struct rtw_dev *rtwdev,
283 			   u8 para1, u8 para2, u8 para3, u8 para4, u8 para5)
284 {
285 	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
286 
287 	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_COEX_TDMA_TYPE);
288 
289 	SET_COEX_TDMA_TYPE_PARA1(h2c_pkt, para1);
290 	SET_COEX_TDMA_TYPE_PARA2(h2c_pkt, para2);
291 	SET_COEX_TDMA_TYPE_PARA3(h2c_pkt, para3);
292 	SET_COEX_TDMA_TYPE_PARA4(h2c_pkt, para4);
293 	SET_COEX_TDMA_TYPE_PARA5(h2c_pkt, para5);
294 
295 	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
296 }
297 
rtw_fw_bt_wifi_control(struct rtw_dev * rtwdev,u8 op_code,u8 * data)298 void rtw_fw_bt_wifi_control(struct rtw_dev *rtwdev, u8 op_code, u8 *data)
299 {
300 	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
301 
302 	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_BT_WIFI_CONTROL);
303 
304 	SET_BT_WIFI_CONTROL_OP_CODE(h2c_pkt, op_code);
305 
306 	SET_BT_WIFI_CONTROL_DATA1(h2c_pkt, *data);
307 	SET_BT_WIFI_CONTROL_DATA2(h2c_pkt, *(data + 1));
308 	SET_BT_WIFI_CONTROL_DATA3(h2c_pkt, *(data + 2));
309 	SET_BT_WIFI_CONTROL_DATA4(h2c_pkt, *(data + 3));
310 	SET_BT_WIFI_CONTROL_DATA5(h2c_pkt, *(data + 4));
311 
312 	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
313 }
314 
rtw_fw_send_rssi_info(struct rtw_dev * rtwdev,struct rtw_sta_info * si)315 void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
316 {
317 	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
318 	u8 rssi = ewma_rssi_read(&si->avg_rssi);
319 	bool stbc_en = si->stbc_en ? true : false;
320 
321 	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_RSSI_MONITOR);
322 
323 	SET_RSSI_INFO_MACID(h2c_pkt, si->mac_id);
324 	SET_RSSI_INFO_RSSI(h2c_pkt, rssi);
325 	SET_RSSI_INFO_STBC(h2c_pkt, stbc_en);
326 
327 	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
328 }
329 
rtw_fw_send_ra_info(struct rtw_dev * rtwdev,struct rtw_sta_info * si)330 void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
331 {
332 	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
333 	bool no_update = si->updated;
334 	bool disable_pt = true;
335 
336 	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_RA_INFO);
337 
338 	SET_RA_INFO_MACID(h2c_pkt, si->mac_id);
339 	SET_RA_INFO_RATE_ID(h2c_pkt, si->rate_id);
340 	SET_RA_INFO_INIT_RA_LVL(h2c_pkt, si->init_ra_lv);
341 	SET_RA_INFO_SGI_EN(h2c_pkt, si->sgi_enable);
342 	SET_RA_INFO_BW_MODE(h2c_pkt, si->bw_mode);
343 	SET_RA_INFO_LDPC(h2c_pkt, si->ldpc_en);
344 	SET_RA_INFO_NO_UPDATE(h2c_pkt, no_update);
345 	SET_RA_INFO_VHT_EN(h2c_pkt, si->vht_enable);
346 	SET_RA_INFO_DIS_PT(h2c_pkt, disable_pt);
347 	SET_RA_INFO_RA_MASK0(h2c_pkt, (si->ra_mask & 0xff));
348 	SET_RA_INFO_RA_MASK1(h2c_pkt, (si->ra_mask & 0xff00) >> 8);
349 	SET_RA_INFO_RA_MASK2(h2c_pkt, (si->ra_mask & 0xff0000) >> 16);
350 	SET_RA_INFO_RA_MASK3(h2c_pkt, (si->ra_mask & 0xff000000) >> 24);
351 
352 	si->init_ra_lv = 0;
353 	si->updated = true;
354 
355 	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
356 }
357 
rtw_fw_media_status_report(struct rtw_dev * rtwdev,u8 mac_id,bool connect)358 void rtw_fw_media_status_report(struct rtw_dev *rtwdev, u8 mac_id, bool connect)
359 {
360 	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
361 
362 	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_MEDIA_STATUS_RPT);
363 	MEDIA_STATUS_RPT_SET_OP_MODE(h2c_pkt, connect);
364 	MEDIA_STATUS_RPT_SET_MACID(h2c_pkt, mac_id);
365 
366 	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
367 }
368 
rtw_fw_set_pwr_mode(struct rtw_dev * rtwdev)369 void rtw_fw_set_pwr_mode(struct rtw_dev *rtwdev)
370 {
371 	struct rtw_lps_conf *conf = &rtwdev->lps_conf;
372 	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
373 
374 	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_SET_PWR_MODE);
375 
376 	SET_PWR_MODE_SET_MODE(h2c_pkt, conf->mode);
377 	SET_PWR_MODE_SET_RLBM(h2c_pkt, conf->rlbm);
378 	SET_PWR_MODE_SET_SMART_PS(h2c_pkt, conf->smart_ps);
379 	SET_PWR_MODE_SET_AWAKE_INTERVAL(h2c_pkt, conf->awake_interval);
380 	SET_PWR_MODE_SET_PORT_ID(h2c_pkt, conf->port_id);
381 	SET_PWR_MODE_SET_PWR_STATE(h2c_pkt, conf->state);
382 
383 	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
384 }
385 
rtw_get_rsvd_page_location(struct rtw_dev * rtwdev,enum rtw_rsvd_packet_type type)386 static u8 rtw_get_rsvd_page_location(struct rtw_dev *rtwdev,
387 				     enum rtw_rsvd_packet_type type)
388 {
389 	struct rtw_rsvd_page *rsvd_pkt;
390 	u8 location = 0;
391 
392 	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) {
393 		if (type == rsvd_pkt->type)
394 			location = rsvd_pkt->page;
395 	}
396 
397 	return location;
398 }
399 
rtw_send_rsvd_page_h2c(struct rtw_dev * rtwdev)400 void rtw_send_rsvd_page_h2c(struct rtw_dev *rtwdev)
401 {
402 	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
403 	u8 location = 0;
404 
405 	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_RSVD_PAGE);
406 
407 	location = rtw_get_rsvd_page_location(rtwdev, RSVD_PROBE_RESP);
408 	*(h2c_pkt + 1) = location;
409 	rtw_dbg(rtwdev, RTW_DBG_FW, "RSVD_PROBE_RESP loc: %d\n", location);
410 
411 	location = rtw_get_rsvd_page_location(rtwdev, RSVD_PS_POLL);
412 	*(h2c_pkt + 2) = location;
413 	rtw_dbg(rtwdev, RTW_DBG_FW, "RSVD_PS_POLL loc: %d\n", location);
414 
415 	location = rtw_get_rsvd_page_location(rtwdev, RSVD_NULL);
416 	*(h2c_pkt + 3) = location;
417 	rtw_dbg(rtwdev, RTW_DBG_FW, "RSVD_NULL loc: %d\n", location);
418 
419 	location = rtw_get_rsvd_page_location(rtwdev, RSVD_QOS_NULL);
420 	*(h2c_pkt + 4) = location;
421 	rtw_dbg(rtwdev, RTW_DBG_FW, "RSVD_QOS_NULL loc: %d\n", location);
422 
423 	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
424 }
425 
426 static struct sk_buff *
rtw_beacon_get(struct ieee80211_hw * hw,struct ieee80211_vif * vif)427 rtw_beacon_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
428 {
429 	struct sk_buff *skb_new;
430 
431 	if (vif->type != NL80211_IFTYPE_AP &&
432 	    vif->type != NL80211_IFTYPE_ADHOC &&
433 	    !ieee80211_vif_is_mesh(vif)) {
434 		skb_new = alloc_skb(1, GFP_KERNEL);
435 		if (!skb_new)
436 			return NULL;
437 		skb_put(skb_new, 1);
438 	} else {
439 		skb_new = ieee80211_beacon_get(hw, vif);
440 	}
441 
442 	return skb_new;
443 }
444 
rtw_get_rsvd_page_skb(struct ieee80211_hw * hw,struct ieee80211_vif * vif,enum rtw_rsvd_packet_type type)445 static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw,
446 					     struct ieee80211_vif *vif,
447 					     enum rtw_rsvd_packet_type type)
448 {
449 	struct sk_buff *skb_new;
450 
451 	switch (type) {
452 	case RSVD_BEACON:
453 		skb_new = rtw_beacon_get(hw, vif);
454 		break;
455 	case RSVD_PS_POLL:
456 		skb_new = ieee80211_pspoll_get(hw, vif);
457 		break;
458 	case RSVD_PROBE_RESP:
459 		skb_new = ieee80211_proberesp_get(hw, vif);
460 		break;
461 	case RSVD_NULL:
462 		skb_new = ieee80211_nullfunc_get(hw, vif, false);
463 		break;
464 	case RSVD_QOS_NULL:
465 		skb_new = ieee80211_nullfunc_get(hw, vif, true);
466 		break;
467 	default:
468 		return NULL;
469 	}
470 
471 	if (!skb_new)
472 		return NULL;
473 
474 	return skb_new;
475 }
476 
rtw_fill_rsvd_page_desc(struct rtw_dev * rtwdev,struct sk_buff * skb)477 static void rtw_fill_rsvd_page_desc(struct rtw_dev *rtwdev, struct sk_buff *skb)
478 {
479 	struct rtw_tx_pkt_info pkt_info;
480 	struct rtw_chip_info *chip = rtwdev->chip;
481 	u8 *pkt_desc;
482 
483 	memset(&pkt_info, 0, sizeof(pkt_info));
484 	rtw_rsvd_page_pkt_info_update(rtwdev, &pkt_info, skb);
485 	pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz);
486 	memset(pkt_desc, 0, chip->tx_pkt_desc_sz);
487 	rtw_tx_fill_tx_desc(&pkt_info, skb);
488 }
489 
rtw_len_to_page(unsigned int len,u8 page_size)490 static inline u8 rtw_len_to_page(unsigned int len, u8 page_size)
491 {
492 	return DIV_ROUND_UP(len, page_size);
493 }
494 
rtw_rsvd_page_list_to_buf(struct rtw_dev * rtwdev,u8 page_size,u8 page_margin,u32 page,u8 * buf,struct rtw_rsvd_page * rsvd_pkt)495 static void rtw_rsvd_page_list_to_buf(struct rtw_dev *rtwdev, u8 page_size,
496 				      u8 page_margin, u32 page, u8 *buf,
497 				      struct rtw_rsvd_page *rsvd_pkt)
498 {
499 	struct sk_buff *skb = rsvd_pkt->skb;
500 
501 	if (rsvd_pkt->add_txdesc)
502 		rtw_fill_rsvd_page_desc(rtwdev, skb);
503 
504 	if (page >= 1)
505 		memcpy(buf + page_margin + page_size * (page - 1),
506 		       skb->data, skb->len);
507 	else
508 		memcpy(buf, skb->data, skb->len);
509 }
510 
rtw_add_rsvd_page(struct rtw_dev * rtwdev,enum rtw_rsvd_packet_type type,bool txdesc)511 void rtw_add_rsvd_page(struct rtw_dev *rtwdev, enum rtw_rsvd_packet_type type,
512 		       bool txdesc)
513 {
514 	struct rtw_rsvd_page *rsvd_pkt;
515 
516 	lockdep_assert_held(&rtwdev->mutex);
517 
518 	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) {
519 		if (rsvd_pkt->type == type)
520 			return;
521 	}
522 
523 	rsvd_pkt = kmalloc(sizeof(*rsvd_pkt), GFP_KERNEL);
524 	if (!rsvd_pkt)
525 		return;
526 
527 	rsvd_pkt->type = type;
528 	rsvd_pkt->add_txdesc = txdesc;
529 	list_add_tail(&rsvd_pkt->list, &rtwdev->rsvd_page_list);
530 }
531 
rtw_reset_rsvd_page(struct rtw_dev * rtwdev)532 void rtw_reset_rsvd_page(struct rtw_dev *rtwdev)
533 {
534 	struct rtw_rsvd_page *rsvd_pkt, *tmp;
535 
536 	lockdep_assert_held(&rtwdev->mutex);
537 
538 	list_for_each_entry_safe(rsvd_pkt, tmp, &rtwdev->rsvd_page_list, list) {
539 		if (rsvd_pkt->type == RSVD_BEACON)
540 			continue;
541 		list_del(&rsvd_pkt->list);
542 		kfree(rsvd_pkt);
543 	}
544 }
545 
rtw_fw_write_data_rsvd_page(struct rtw_dev * rtwdev,u16 pg_addr,u8 * buf,u32 size)546 int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr,
547 				u8 *buf, u32 size)
548 {
549 	u8 bckp[2];
550 	u8 val;
551 	u16 rsvd_pg_head;
552 	int ret;
553 
554 	lockdep_assert_held(&rtwdev->mutex);
555 
556 	if (!size)
557 		return -EINVAL;
558 
559 	pg_addr &= BIT_MASK_BCN_HEAD_1_V1;
560 	rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2, pg_addr | BIT_BCN_VALID_V1);
561 
562 	val = rtw_read8(rtwdev, REG_CR + 1);
563 	bckp[0] = val;
564 	val |= BIT_ENSWBCN >> 8;
565 	rtw_write8(rtwdev, REG_CR + 1, val);
566 
567 	val = rtw_read8(rtwdev, REG_FWHW_TXQ_CTRL + 2);
568 	bckp[1] = val;
569 	val &= ~(BIT_EN_BCNQ_DL >> 16);
570 	rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 2, val);
571 
572 	ret = rtw_hci_write_data_rsvd_page(rtwdev, buf, size);
573 	if (ret) {
574 		rtw_err(rtwdev, "failed to write data to rsvd page\n");
575 		goto restore;
576 	}
577 
578 	if (!check_hw_ready(rtwdev, REG_FIFOPAGE_CTRL_2, BIT_BCN_VALID_V1, 1)) {
579 		rtw_err(rtwdev, "error beacon valid\n");
580 		ret = -EBUSY;
581 	}
582 
583 restore:
584 	rsvd_pg_head = rtwdev->fifo.rsvd_boundary;
585 	rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2,
586 		    rsvd_pg_head | BIT_BCN_VALID_V1);
587 	rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 2, bckp[1]);
588 	rtw_write8(rtwdev, REG_CR + 1, bckp[0]);
589 
590 	return ret;
591 }
592 
rtw_download_drv_rsvd_page(struct rtw_dev * rtwdev,u8 * buf,u32 size)593 static int rtw_download_drv_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, u32 size)
594 {
595 	u32 pg_size;
596 	u32 pg_num = 0;
597 	u16 pg_addr = 0;
598 
599 	pg_size = rtwdev->chip->page_size;
600 	pg_num = size / pg_size + ((size & (pg_size - 1)) ? 1 : 0);
601 	if (pg_num > rtwdev->fifo.rsvd_drv_pg_num)
602 		return -ENOMEM;
603 
604 	pg_addr = rtwdev->fifo.rsvd_drv_addr;
605 
606 	return rtw_fw_write_data_rsvd_page(rtwdev, pg_addr, buf, size);
607 }
608 
rtw_build_rsvd_page(struct rtw_dev * rtwdev,struct ieee80211_vif * vif,u32 * size)609 static u8 *rtw_build_rsvd_page(struct rtw_dev *rtwdev,
610 			       struct ieee80211_vif *vif, u32 *size)
611 {
612 	struct ieee80211_hw *hw = rtwdev->hw;
613 	struct rtw_chip_info *chip = rtwdev->chip;
614 	struct sk_buff *iter;
615 	struct rtw_rsvd_page *rsvd_pkt;
616 	u32 page = 0;
617 	u8 total_page = 0;
618 	u8 page_size, page_margin, tx_desc_sz;
619 	u8 *buf;
620 
621 	page_size = chip->page_size;
622 	tx_desc_sz = chip->tx_pkt_desc_sz;
623 	page_margin = page_size - tx_desc_sz;
624 
625 	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) {
626 		iter = rtw_get_rsvd_page_skb(hw, vif, rsvd_pkt->type);
627 		if (!iter) {
628 			rtw_err(rtwdev, "fail to build rsvd packet\n");
629 			goto release_skb;
630 		}
631 		rsvd_pkt->skb = iter;
632 		rsvd_pkt->page = total_page;
633 		if (rsvd_pkt->add_txdesc)
634 			total_page += rtw_len_to_page(iter->len + tx_desc_sz,
635 						      page_size);
636 		else
637 			total_page += rtw_len_to_page(iter->len, page_size);
638 	}
639 
640 	if (total_page > rtwdev->fifo.rsvd_drv_pg_num) {
641 		rtw_err(rtwdev, "rsvd page over size: %d\n", total_page);
642 		goto release_skb;
643 	}
644 
645 	*size = (total_page - 1) * page_size + page_margin;
646 	buf = kzalloc(*size, GFP_KERNEL);
647 	if (!buf)
648 		goto release_skb;
649 
650 	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) {
651 		rtw_rsvd_page_list_to_buf(rtwdev, page_size, page_margin,
652 					  page, buf, rsvd_pkt);
653 		page += rtw_len_to_page(rsvd_pkt->skb->len, page_size);
654 	}
655 	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list)
656 		kfree_skb(rsvd_pkt->skb);
657 
658 	return buf;
659 
660 release_skb:
661 	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list)
662 		kfree_skb(rsvd_pkt->skb);
663 
664 	return NULL;
665 }
666 
667 static int
rtw_download_beacon(struct rtw_dev * rtwdev,struct ieee80211_vif * vif)668 rtw_download_beacon(struct rtw_dev *rtwdev, struct ieee80211_vif *vif)
669 {
670 	struct ieee80211_hw *hw = rtwdev->hw;
671 	struct sk_buff *skb;
672 	int ret = 0;
673 
674 	skb = rtw_beacon_get(hw, vif);
675 	if (!skb) {
676 		rtw_err(rtwdev, "failed to get beacon skb\n");
677 		ret = -ENOMEM;
678 		goto out;
679 	}
680 
681 	ret = rtw_download_drv_rsvd_page(rtwdev, skb->data, skb->len);
682 	if (ret)
683 		rtw_err(rtwdev, "failed to download drv rsvd page\n");
684 
685 	dev_kfree_skb(skb);
686 
687 out:
688 	return ret;
689 }
690 
rtw_fw_download_rsvd_page(struct rtw_dev * rtwdev,struct ieee80211_vif * vif)691 int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev, struct ieee80211_vif *vif)
692 {
693 	u8 *buf;
694 	u32 size;
695 	int ret;
696 
697 	buf = rtw_build_rsvd_page(rtwdev, vif, &size);
698 	if (!buf) {
699 		rtw_err(rtwdev, "failed to build rsvd page pkt\n");
700 		return -ENOMEM;
701 	}
702 
703 	ret = rtw_download_drv_rsvd_page(rtwdev, buf, size);
704 	if (ret) {
705 		rtw_err(rtwdev, "failed to download drv rsvd page\n");
706 		goto free;
707 	}
708 
709 	ret = rtw_download_beacon(rtwdev, vif);
710 	if (ret) {
711 		rtw_err(rtwdev, "failed to download beacon\n");
712 		goto free;
713 	}
714 
715 free:
716 	kfree(buf);
717 
718 	return ret;
719 }
720 
rtw_dump_drv_rsvd_page(struct rtw_dev * rtwdev,u32 offset,u32 size,u32 * buf)721 int rtw_dump_drv_rsvd_page(struct rtw_dev *rtwdev,
722 			   u32 offset, u32 size, u32 *buf)
723 {
724 	struct rtw_fifo_conf *fifo = &rtwdev->fifo;
725 	u32 residue, i;
726 	u16 start_pg;
727 	u16 idx = 0;
728 	u16 ctl;
729 	u8 rcr;
730 
731 	if (size & 0x3) {
732 		rtw_warn(rtwdev, "should be 4-byte aligned\n");
733 		return -EINVAL;
734 	}
735 
736 	offset += fifo->rsvd_boundary << TX_PAGE_SIZE_SHIFT;
737 	residue = offset & (FIFO_PAGE_SIZE - 1);
738 	start_pg = offset >> FIFO_PAGE_SIZE_SHIFT;
739 	start_pg += RSVD_PAGE_START_ADDR;
740 
741 	rcr = rtw_read8(rtwdev, REG_RCR + 2);
742 	ctl = rtw_read16(rtwdev, REG_PKTBUF_DBG_CTRL) & 0xf000;
743 
744 	/* disable rx clock gate */
745 	rtw_write8(rtwdev, REG_RCR, rcr | BIT(3));
746 
747 	do {
748 		rtw_write16(rtwdev, REG_PKTBUF_DBG_CTRL, start_pg | ctl);
749 
750 		for (i = FIFO_DUMP_ADDR + residue;
751 		     i < FIFO_DUMP_ADDR + FIFO_PAGE_SIZE; i += 4) {
752 			buf[idx++] = rtw_read32(rtwdev, i);
753 			size -= 4;
754 			if (size == 0)
755 				goto out;
756 		}
757 
758 		residue = 0;
759 		start_pg++;
760 	} while (size);
761 
762 out:
763 	rtw_write16(rtwdev, REG_PKTBUF_DBG_CTRL, ctl);
764 	rtw_write8(rtwdev, REG_RCR + 2, rcr);
765 	return 0;
766 }
767