xref: /linux/drivers/net/wireless/morsemicro/mm81x/yaps.c (revision 1fc5a74b108fc90951890ec513ac81869f5eaff1)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2017-2026 Morse Micro
4  */
5 #include <linux/gpio.h>
6 #include <linux/random.h>
7 #include <linux/timer.h>
8 #include <linux/bitops.h>
9 #include <linux/slab.h>
10 #include "hif.h"
11 #include "ps.h"
12 #include "bus.h"
13 #include "command.h"
14 #include "skbq.h"
15 
16 /* This is a fail safe timeout */
17 #define CHIP_FULL_RECOVERY_TIMEOUT_MS 30
18 
19 /* Defined as the max number of MPDUs per AMPDU */
20 #define MAX_PKTS_PER_TX_TXN 16
21 #define MAX_PKTS_PER_RX_TXN 32
22 
mm81x_yaps_alloc_pkt_buffers(struct mm81x_yaps * yaps)23 static int mm81x_yaps_alloc_pkt_buffers(struct mm81x_yaps *yaps)
24 {
25 	yaps->hw.to_chip_pkts = kzalloc_objs(*yaps->hw.to_chip_pkts,
26 					     MAX_PKTS_PER_TX_TXN);
27 	if (!yaps->hw.to_chip_pkts)
28 		return -ENOMEM;
29 
30 	yaps->hw.from_chip_pkts = kzalloc_objs(*yaps->hw.from_chip_pkts,
31 					       MAX_PKTS_PER_RX_TXN);
32 	if (!yaps->hw.from_chip_pkts) {
33 		kfree(yaps->hw.to_chip_pkts);
34 		yaps->hw.to_chip_pkts = NULL;
35 		return -ENOMEM;
36 	}
37 
38 	return 0;
39 }
40 
mm81x_yaps_free_pkt_buffers(struct mm81x_yaps * yaps)41 static void mm81x_yaps_free_pkt_buffers(struct mm81x_yaps *yaps)
42 {
43 	kfree(yaps->hw.from_chip_pkts);
44 	yaps->hw.from_chip_pkts = NULL;
45 	kfree(yaps->hw.to_chip_pkts);
46 	yaps->hw.to_chip_pkts = NULL;
47 }
48 
mm81x_yaps_write_pkts(struct mm81x_yaps * yaps,struct mm81x_yaps_pkt * pkts,int num_pkts,int * num_pkts_sent)49 static int mm81x_yaps_write_pkts(struct mm81x_yaps *yaps,
50 				 struct mm81x_yaps_pkt *pkts, int num_pkts,
51 				 int *num_pkts_sent)
52 {
53 	return yaps->ops->write_pkts(yaps, pkts, num_pkts, num_pkts_sent);
54 }
55 
mm81x_yaps_read_pkts(struct mm81x_yaps * yaps,struct mm81x_yaps_pkt * pkts,int num_pkts_max,int * num_pkts_received)56 static int mm81x_yaps_read_pkts(struct mm81x_yaps *yaps,
57 				struct mm81x_yaps_pkt *pkts, int num_pkts_max,
58 				int *num_pkts_received)
59 {
60 	return yaps->ops->read_pkts(yaps, pkts, num_pkts_max,
61 				    num_pkts_received);
62 }
63 
mm81x_yaps_update_status(struct mm81x_yaps * yaps)64 static int mm81x_yaps_update_status(struct mm81x_yaps *yaps)
65 {
66 	return yaps->ops->update_status(yaps);
67 }
68 
69 /* Mappings between sk_buff, skbq and yaps */
mm81x_yaps_tc_q_from_aci(struct mm81x * mors,int aci)70 static struct mm81x_skbq *mm81x_yaps_tc_q_from_aci(struct mm81x *mors, int aci)
71 {
72 	struct mm81x_yaps *yaps = &mors->hif.u.yaps;
73 
74 	if (aci >= ARRAY_SIZE(yaps->data_tx_qs))
75 		return NULL;
76 	return &yaps->data_tx_qs[aci];
77 }
78 
mm81x_yaps_get_tx_qs(struct mm81x * mors,struct mm81x_skbq ** qs,int * num_qs)79 static void mm81x_yaps_get_tx_qs(struct mm81x *mors, struct mm81x_skbq **qs,
80 				 int *num_qs)
81 {
82 	*qs = mors->hif.u.yaps.data_tx_qs;
83 	*num_qs = YAPS_TX_SKBQ_MAX;
84 }
85 
mm81x_yaps_get_bcn_tc_q(struct mm81x * mors)86 static struct mm81x_skbq *mm81x_yaps_get_bcn_tc_q(struct mm81x *mors)
87 {
88 	return &mors->hif.u.yaps.beacon_q;
89 }
90 
mm81x_yaps_get_mgmt_tc_q(struct mm81x * mors)91 static struct mm81x_skbq *mm81x_yaps_get_mgmt_tc_q(struct mm81x *mors)
92 {
93 	return &mors->hif.u.yaps.mgmt_q;
94 }
95 
mm81x_yaps_get_tx_cmd_queue(struct mm81x * mors)96 static struct mm81x_skbq *mm81x_yaps_get_tx_cmd_queue(struct mm81x *mors)
97 {
98 	return &mors->hif.u.yaps.cmd_q;
99 }
100 
mm81x_yaps_irq_handler(struct mm81x * mors,u32 status)101 static int mm81x_yaps_irq_handler(struct mm81x *mors, u32 status)
102 {
103 	if (status & BIT(MM81X_INT_YAPS_FC_PKT_WAITING_IRQN))
104 		set_bit(MM81X_HIF_EVT_RX_PEND, &mors->hif.event_flags);
105 
106 	if (status & BIT(MM81X_INT_YAPS_FC_PACKET_FREED_UP_IRQN)) {
107 		timer_delete_sync_try(&mors->hif.u.yaps.chip_queue_full.timer);
108 		set_bit(MM81X_HIF_EVT_TX_PACKET_FREED_UP_PEND,
109 			&mors->hif.event_flags);
110 	}
111 
112 	queue_work(mors->chip_wq, &mors->hif_work);
113 	return 0;
114 }
115 
116 const struct mm81x_hif_ops mm81x_yaps_ops = {
117 	.init = mm81x_yaps_init,
118 	.flush_tx_data = mm81x_yaps_flush_tx_data,
119 	.flush_cmds = mm81x_yaps_flush_cmds,
120 	.get_tx_status_pending_count = mm81x_yaps_get_tx_status_pending_count,
121 	.get_tx_buffered_count = mm81x_yaps_get_tx_buffered_count,
122 	.finish = mm81x_yaps_finish,
123 	.skbq_get_tx_qs = mm81x_yaps_get_tx_qs,
124 	.get_tx_beacon_queue = mm81x_yaps_get_bcn_tc_q,
125 	.get_tx_mgmt_queue = mm81x_yaps_get_mgmt_tc_q,
126 	.get_tx_cmd_queue = mm81x_yaps_get_tx_cmd_queue,
127 	.get_tx_data_queue = mm81x_yaps_tc_q_from_aci,
128 	.handle_irq = mm81x_yaps_irq_handler
129 };
130 
mm81x_yaps_read_pkt(struct mm81x_yaps * yaps,struct sk_buff * skb)131 static int mm81x_yaps_read_pkt(struct mm81x_yaps *yaps, struct sk_buff *skb)
132 {
133 	struct mm81x *mors = yaps->mors;
134 	struct sk_buff_head skbq;
135 	struct mm81x_skbq *mq = NULL;
136 	struct mm81x_skb_hdr *hdr;
137 	int skb_bytes_remaining;
138 	int skb_len;
139 	int ret = 0;
140 
141 	if (!skb) {
142 		ret = -EINVAL;
143 		goto exit_return_page;
144 	}
145 
146 	__skb_queue_head_init(&skbq);
147 
148 	hdr = (struct mm81x_skb_hdr *)skb->data;
149 	if (hdr->sync != MM81X_SKB_HEADER_SYNC) {
150 		dev_err(mors->dev, "sync value error [0xAA:%d], hdr.len %d",
151 			hdr->sync, hdr->len);
152 		ret = -EIO;
153 		goto exit_return_page;
154 	}
155 
156 	if (yaps->mors->hif.validate_skb_checksum &&
157 	    !mm81x_skbq_validate_checksum(skb->data)) {
158 		dev_dbg(yaps->mors->dev,
159 			"SKB checksum is invalid hdr:[c:%02X s:%02X len:%d]",
160 			hdr->channel, hdr->sync, hdr->len);
161 
162 		if (hdr->channel != MM81X_SKB_CHAN_TX_STATUS) {
163 			ret = -EIO;
164 			goto exit;
165 		}
166 	}
167 
168 	switch (hdr->channel) {
169 	case MM81X_SKB_CHAN_DATA:
170 	case MM81X_SKB_CHAN_NDP_FRAMES:
171 	case MM81X_SKB_CHAN_TX_STATUS:
172 	case MM81X_SKB_CHAN_DATA_NOACK:
173 	case MM81X_SKB_CHAN_BEACON:
174 	case MM81X_SKB_CHAN_MGMT:
175 		mq = &yaps->data_rx_q;
176 		break;
177 	case MM81X_SKB_CHAN_COMMAND:
178 		mq = &yaps->cmd_resp_q;
179 		break;
180 	default:
181 		dev_err(mors->dev, "channel value error [%d]", hdr->channel);
182 		ret = -EIO;
183 		goto exit_return_page;
184 	}
185 
186 	skb_len = sizeof(*hdr) + hdr->offset + le16_to_cpu(hdr->len);
187 	skb_bytes_remaining = mm81x_skbq_space(mq);
188 
189 	if (skb_len > skb_bytes_remaining) {
190 		dev_err(mors->dev,
191 			"Page will not fit in SKBQ, dropping - len %d remain %d",
192 			skb_len, skb_bytes_remaining);
193 		ret = -ENOMEM;
194 		/* Queue work to clear backlog */
195 		queue_work(mors->net_wq, &mq->dispatch_work);
196 		goto exit_return_page;
197 	}
198 
199 	skb_trim(skb, skb_len);
200 	__skb_queue_tail(&skbq, skb);
201 
202 	if (skb_queue_len(&skbq))
203 		mm81x_skbq_enq(mq, &skbq);
204 
205 	/* push packets up in a different context */
206 	queue_work(mors->net_wq, &mq->dispatch_work);
207 
208 	goto exit;
209 
210 exit_return_page:
211 	if (ret && mq) {
212 		dev_err(mors->dev, "failed %d", ret);
213 		mm81x_skbq_purge(mq, &skbq);
214 		goto exit;
215 	}
216 
217 exit:
218 	if (ret && skb)
219 		dev_kfree_skb(skb);
220 
221 	return ret;
222 }
223 
mm81x_yaps_tx(struct mm81x_yaps * yaps,struct mm81x_skbq * mq)224 static int mm81x_yaps_tx(struct mm81x_yaps *yaps, struct mm81x_skbq *mq)
225 {
226 	int i;
227 	int ret = 0;
228 	int num_skbs = 0;
229 	int tc_pkt_idx = 0;
230 	int num_pkts_sent = 0;
231 	struct sk_buff *skb;
232 	struct sk_buff_head skbq_to_send;
233 	struct sk_buff_head skbq_sent;
234 	struct sk_buff_head skbq_failed;
235 	struct sk_buff *pfirst, *pnext;
236 	struct mm81x *mors = yaps->mors;
237 	struct mm81x_skb_hdr *hdr;
238 
239 	/* Check there is something on the queue */
240 	spin_lock_bh(&mq->lock);
241 	skb = skb_peek(&mq->skbq);
242 	spin_unlock_bh(&mq->lock);
243 	if (!skb)
244 		return 0;
245 
246 	__skb_queue_head_init(&skbq_to_send);
247 	__skb_queue_head_init(&skbq_sent);
248 	__skb_queue_head_init(&skbq_failed);
249 
250 	if (mq == &yaps->cmd_q)
251 		/* Purge timed-out commands (this should not happen) */
252 		mm81x_skbq_purge(mq, &mq->pending);
253 	else if (mq == &yaps->mgmt_q && skb_queue_len(&mq->skbq) > 0)
254 		/*
255 		 * Purge old mgmt frames that have not been sent due to
256 		 * congestion
257 		 */
258 		mm81x_skbq_purge_aged(mors, mq);
259 
260 	num_skbs =
261 		mm81x_skbq_deq_num_skb(mq, &skbq_to_send, MAX_PKTS_PER_TX_TXN);
262 
263 	skb_queue_walk_safe(&skbq_to_send, pfirst, pnext) {
264 		enum mm81x_yaps_to_chip_q tc_queue;
265 
266 		hdr = (struct mm81x_skb_hdr *)pfirst->data;
267 		switch (hdr->channel) {
268 		case MM81X_SKB_CHAN_COMMAND:
269 			tc_queue = MM81X_YAPS_CMD_Q;
270 			break;
271 		case MM81X_SKB_CHAN_BEACON:
272 			tc_queue = MM81X_YAPS_BEACON_Q;
273 			break;
274 		case MM81X_SKB_CHAN_MGMT:
275 			tc_queue = MM81X_YAPS_MGMT_Q;
276 			break;
277 		default:
278 			tc_queue = MM81X_YAPS_TX_Q;
279 			break;
280 		}
281 		yaps->hw.to_chip_pkts[tc_pkt_idx].tc_queue = tc_queue;
282 		yaps->hw.to_chip_pkts[tc_pkt_idx].skb = pfirst;
283 		tc_pkt_idx++;
284 	}
285 
286 	/* Send queued packets to chip */
287 	ret = mm81x_yaps_update_status(yaps);
288 	if (ret)
289 		return ret;
290 
291 	ret = mm81x_yaps_write_pkts(yaps, yaps->hw.to_chip_pkts, tc_pkt_idx,
292 				    &num_pkts_sent);
293 
294 	/* Move sent packets to done queue */
295 	for (i = 0; i < num_pkts_sent; ++i) {
296 		pfirst = __skb_dequeue(&skbq_to_send);
297 		__skb_queue_tail(&skbq_sent, pfirst);
298 	}
299 
300 	for (i = num_pkts_sent; i < num_skbs; ++i) {
301 		pfirst = __skb_dequeue(&skbq_to_send);
302 		__skb_queue_tail(&skbq_failed, pfirst);
303 	}
304 
305 	if (skb_queue_len(&skbq_failed) > 0) {
306 		mm81x_skbq_enq_prepend(mq, &skbq_failed);
307 
308 		/* queue full, can't requeue */
309 		if (skb_queue_len(&skbq_failed) > 0) {
310 			dev_warn(mors->dev,
311 				 "can't requeue failed pkts, purging");
312 			__skb_queue_purge(&skbq_failed);
313 		}
314 	}
315 
316 	if (skb_queue_len(&skbq_sent) > 0)
317 		mm81x_skbq_tx_complete(mq, &skbq_sent);
318 
319 	return ret;
320 }
321 
322 /* Returns true if there are TX data pages waiting to be sent */
mm81x_yaps_tx_data_handler(struct mm81x_yaps * yaps)323 static bool mm81x_yaps_tx_data_handler(struct mm81x_yaps *yaps)
324 {
325 	s16 aci;
326 	u32 count = 0;
327 	struct mm81x *mors = yaps->mors;
328 
329 	for (aci = MM81X_ACI_VO; aci >= 0; aci--) {
330 		struct mm81x_skbq *data_q = mm81x_yaps_tc_q_from_aci(mors, aci);
331 
332 		if (!mm81x_is_data_tx_allowed(mors))
333 			break;
334 
335 		yaps->chip_queue_full.is_full = mm81x_yaps_tx(yaps, data_q);
336 		count += mm81x_skbq_count(data_q);
337 
338 		if (yaps->chip_queue_full.is_full)
339 			break;
340 
341 		if (aci == MM81X_ACI_BE)
342 			break;
343 	}
344 
345 	/*
346 	 * Data has potentially been transmitted from the data SKBQs.
347 	 * If the mac80211 TX data Qs were previously stopped, now would
348 	 * be a good time to check if they can be started again.
349 	 */
350 	mm81x_skbq_may_wake_tx_queues(mors);
351 
352 	return (count > 0) && mm81x_is_data_tx_allowed(mors);
353 }
354 
355 /* Returns true if there are commands waiting to be sent */
mm81x_yaps_tx_cmd_handler(struct mm81x_yaps * yaps)356 static bool mm81x_yaps_tx_cmd_handler(struct mm81x_yaps *yaps)
357 {
358 	struct mm81x_skbq *cmd_q = &yaps->cmd_q;
359 
360 	mm81x_yaps_tx(yaps, cmd_q);
361 
362 	return mm81x_skbq_count(cmd_q) > 0;
363 }
364 
mm81x_yaps_tx_beacon_handler(struct mm81x_yaps * yaps)365 static bool mm81x_yaps_tx_beacon_handler(struct mm81x_yaps *yaps)
366 {
367 	struct mm81x_skbq *beacon_q = &yaps->beacon_q;
368 
369 	mm81x_yaps_tx(yaps, beacon_q);
370 
371 	return mm81x_skbq_count(beacon_q) > 0;
372 }
373 
mm81x_yaps_tx_mgmt_handler(struct mm81x_yaps * yaps)374 static bool mm81x_yaps_tx_mgmt_handler(struct mm81x_yaps *yaps)
375 {
376 	struct mm81x_skbq *mgmt_q = &yaps->mgmt_q;
377 
378 	mm81x_yaps_tx(yaps, mgmt_q);
379 
380 	return mm81x_skbq_count(mgmt_q) > 0;
381 }
382 
383 /* Returns true if there are populated RX pages left in the device */
mm81x_yaps_rx_handler(struct mm81x_yaps * yaps)384 static bool mm81x_yaps_rx_handler(struct mm81x_yaps *yaps)
385 {
386 	int ret = 0;
387 	int i;
388 	int num_pks_received;
389 
390 	ret = mm81x_yaps_update_status(yaps);
391 	if (ret)
392 		goto exit;
393 
394 	ret = mm81x_yaps_read_pkts(yaps, yaps->hw.from_chip_pkts,
395 				   MAX_PKTS_PER_RX_TXN, &num_pks_received);
396 	if (ret && ret != -EAGAIN) {
397 		dev_err(yaps->mors->dev, "YAPS read_pkts fail: %d", ret);
398 		goto exit;
399 	}
400 
401 	for (i = 0; i < num_pks_received; ++i) {
402 		mm81x_yaps_read_pkt(yaps, yaps->hw.from_chip_pkts[i].skb);
403 		yaps->hw.from_chip_pkts[i].skb = NULL;
404 	}
405 
406 exit:
407 	if (ret == -ENOMEM || ret == -EAGAIN)
408 		return true;
409 	else
410 		return false;
411 }
412 
mm81x_yaps_stale_tx_work(struct work_struct * work)413 void mm81x_yaps_stale_tx_work(struct work_struct *work)
414 {
415 	int i;
416 	int flushed = 0;
417 	struct mm81x *mors = container_of(work, struct mm81x, tx_stale_work);
418 	struct mm81x_yaps *yaps;
419 
420 	yaps = &mors->hif.u.yaps;
421 	flushed += mm81x_skbq_check_for_stale_tx(mors, &yaps->beacon_q);
422 	flushed += mm81x_skbq_check_for_stale_tx(mors, &yaps->mgmt_q);
423 
424 	for (i = 0; i < ARRAY_SIZE(yaps->data_tx_qs); i++)
425 		flushed += mm81x_skbq_check_for_stale_tx(mors,
426 							 &yaps->data_tx_qs[i]);
427 
428 	if (!flushed)
429 		return;
430 
431 	dev_dbg(mors->dev, "Flushed %d stale TX SKBs", flushed);
432 
433 	if (mors->ps.enable && !mors->ps.suspended &&
434 	    (mm81x_yaps_get_tx_buffered_count(mors) == 0)) {
435 		/* Evaluate ps to check if it was gated on a stale tx status */
436 		queue_delayed_work(mors->chip_wq, &mors->ps.delayed_eval_work,
437 				   0);
438 	}
439 }
440 
mm81x_yaps_work(struct work_struct * work)441 void mm81x_yaps_work(struct work_struct *work)
442 {
443 	struct mm81x *mors = container_of(work, struct mm81x, hif_work);
444 	unsigned long *flags = &mors->hif.event_flags;
445 	struct mm81x_yaps *yaps = &mors->hif.u.yaps;
446 
447 	if (test_bit(MM81X_STATE_CHIP_UNRESPONSIVE, &mors->state_flags))
448 		return;
449 
450 	if (!*flags)
451 		return;
452 
453 	/* Disable power save in case it is running */
454 	mm81x_ps_disable(mors);
455 	mm81x_claim_bus(mors);
456 
457 	/*
458 	 * Handle any populated RX pages from chip first to
459 	 * avoid dropping pkts due to full on-chip buffers.
460 	 * Check if all pages were removed, set event flags if not.
461 	 */
462 	if (test_and_clear_bit(MM81X_HIF_EVT_RX_PEND, flags)) {
463 		if (mm81x_yaps_rx_handler(yaps))
464 			set_bit(MM81X_HIF_EVT_RX_PEND, flags);
465 	}
466 
467 	/* TX any commands before considering data */
468 	if (test_and_clear_bit(MM81X_HIF_EVT_TX_COMMAND_PEND, flags)) {
469 		if (mm81x_yaps_tx_cmd_handler(yaps))
470 			set_bit(MM81X_HIF_EVT_TX_COMMAND_PEND, flags);
471 	}
472 
473 	/* TX beacons before considering mgmt/data */
474 	if (test_and_clear_bit(MM81X_HIF_EVT_TX_BEACON_PEND, flags)) {
475 		if (mm81x_yaps_tx_beacon_handler(yaps))
476 			set_bit(MM81X_HIF_EVT_TX_BEACON_PEND, flags);
477 	}
478 
479 	/* TX mgmt before considering data */
480 	if (test_and_clear_bit(MM81X_HIF_EVT_TX_MGMT_PEND, flags)) {
481 		if (mm81x_yaps_tx_mgmt_handler(yaps))
482 			set_bit(MM81X_HIF_EVT_TX_MGMT_PEND, flags);
483 	}
484 
485 	/* Pause TX data Qs */
486 	if (test_and_clear_bit(MM81X_HIF_EVT_DATA_TRAFFIC_PAUSE_PEND, flags)) {
487 		test_and_clear_bit(MM81X_HIF_EVT_DATA_TRAFFIC_RESUME_PEND,
488 				   flags);
489 		mm81x_skbq_data_traffic_pause(mors);
490 	}
491 
492 	/* Resume TX data Qs  */
493 	if (test_and_clear_bit(MM81X_HIF_EVT_DATA_TRAFFIC_RESUME_PEND, flags))
494 		mm81x_skbq_data_traffic_resume(mors);
495 
496 	/* Handle chip queue status */
497 	if (test_and_clear_bit(MM81X_HIF_EVT_TX_PACKET_FREED_UP_PEND, flags))
498 		yaps->chip_queue_full.is_full = false;
499 
500 	/* Check to see if the queue is full or
501 	 * long enough has past since the queue was full
502 	 */
503 	if (yaps->chip_queue_full.is_full &&
504 	    time_before(jiffies, yaps->chip_queue_full.retry_expiry))
505 		goto exit;
506 
507 	/* Finally TX any data */
508 	if (test_and_clear_bit(MM81X_HIF_EVT_TX_DATA_PEND, flags)) {
509 		if (mm81x_yaps_tx_data_handler(yaps))
510 			set_bit(MM81X_HIF_EVT_TX_DATA_PEND, flags);
511 
512 		if (yaps->chip_queue_full.is_full) {
513 			yaps->chip_queue_full.retry_expiry =
514 				jiffies +
515 				msecs_to_jiffies(CHIP_FULL_RECOVERY_TIMEOUT_MS);
516 			mod_timer(&yaps->chip_queue_full.timer,
517 				  yaps->chip_queue_full.retry_expiry);
518 		}
519 	}
520 
521 exit:
522 
523 	/* Disable power save in case it is running */
524 	mm81x_release_bus(mors);
525 	mm81x_ps_enable(mors);
526 
527 	/* Don't requeue work if we are shutting down. */
528 	if (yaps->finish)
529 		return;
530 	/*
531 	 * Evaluate all events except MM81X_HIF_EVT_TX_DATA_PEND in case data
532 	 * tx queue is full
533 	 */
534 	if ((*flags) & ~(1 << MM81X_HIF_EVT_TX_DATA_PEND))
535 		queue_work(mors->chip_wq, &mors->hif_work);
536 	/*
537 	 * if data tx queue is not full and the work hasn't been queued let's
538 	 * queue it
539 	 */
540 	else if (!yaps->chip_queue_full.is_full && *flags)
541 		queue_work(mors->chip_wq, &mors->hif_work);
542 }
543 
mm81x_yaps_get_tx_status_pending_count(struct mm81x * mors)544 int mm81x_yaps_get_tx_status_pending_count(struct mm81x *mors)
545 {
546 	int i = 0;
547 	int count = 0;
548 	struct mm81x_yaps *yaps;
549 
550 	yaps = &mors->hif.u.yaps;
551 	count += skb_queue_len(&yaps->beacon_q.pending);
552 	count += skb_queue_len(&yaps->mgmt_q.pending);
553 	count += skb_queue_len(&yaps->cmd_q.pending);
554 
555 	for (i = 0; i < ARRAY_SIZE(yaps->data_tx_qs); i++)
556 		count += skb_queue_len(&yaps->data_tx_qs[i].pending);
557 
558 	return count;
559 }
560 
mm81x_yaps_get_tx_buffered_count(struct mm81x * mors)561 int mm81x_yaps_get_tx_buffered_count(struct mm81x *mors)
562 {
563 	int i = 0;
564 	int count = 0;
565 	struct mm81x_yaps *yaps;
566 
567 	yaps = &mors->hif.u.yaps;
568 	count += skb_queue_len(&yaps->beacon_q.skbq) +
569 		 skb_queue_len(&yaps->beacon_q.pending);
570 	count += skb_queue_len(&yaps->mgmt_q.skbq) +
571 		 skb_queue_len(&yaps->mgmt_q.pending);
572 	count += skb_queue_len(&yaps->cmd_q.skbq) +
573 		 skb_queue_len(&yaps->cmd_q.pending);
574 
575 	for (i = 0; i < ARRAY_SIZE(yaps->data_tx_qs); i++)
576 		count += mm81x_skbq_count_tx_ready(&yaps->data_tx_qs[i]) +
577 			 skb_queue_len(&yaps->data_tx_qs[i].pending);
578 
579 	return count;
580 }
581 
mm81x_yaps_tx_q_full_timer(struct timer_list * t)582 static void mm81x_yaps_tx_q_full_timer(struct timer_list *t)
583 {
584 	struct mm81x_yaps *yaps =
585 		timer_container_of(yaps, t, chip_queue_full.timer);
586 
587 	queue_work(yaps->mors->chip_wq, &yaps->mors->hif_work);
588 }
589 
mm81x_yaps_q_chip_full_timer_init(struct mm81x_yaps * yaps)590 static void mm81x_yaps_q_chip_full_timer_init(struct mm81x_yaps *yaps)
591 {
592 	timer_setup(&yaps->chip_queue_full.timer, mm81x_yaps_tx_q_full_timer,
593 		    0);
594 }
595 
mm81x_yaps_q_chip_full_timer_finish(struct mm81x_yaps * yaps)596 static void mm81x_yaps_q_chip_full_timer_finish(struct mm81x_yaps *yaps)
597 {
598 	timer_shutdown_sync(&yaps->chip_queue_full.timer);
599 }
600 
mm81x_yaps_init(struct mm81x * mors)601 int mm81x_yaps_init(struct mm81x *mors)
602 {
603 	int i, ret;
604 	struct mm81x_yaps *yaps;
605 
606 	ret = mm81x_yaps_hw_init(mors);
607 	if (ret) {
608 		dev_err(mors->dev, "mm81x_yaps_hw_init failed %d", ret);
609 		return ret;
610 	}
611 
612 	yaps = &mors->hif.u.yaps;
613 	yaps->mors = mors;
614 
615 	mm81x_claim_bus(mors);
616 
617 	ret = mm81x_yaps_alloc_pkt_buffers(yaps);
618 	if (ret) {
619 		dev_err(mors->dev, "Failed to allocate YAPS packet buffers: %d",
620 			ret);
621 		mm81x_yaps_hw_finish(mors);
622 		mm81x_release_bus(mors);
623 		return ret;
624 	}
625 
626 	/* YAPS is bi-directional */
627 	mm81x_skbq_init(mors, &yaps->data_rx_q,
628 			MM81X_HIF_FLAGS_DATA | MM81X_HIF_FLAGS_DIR_TO_HOST);
629 	mm81x_skbq_init(mors, &yaps->beacon_q,
630 			MM81X_HIF_FLAGS_DATA | MM81X_HIF_FLAGS_DIR_TO_HOST);
631 	mm81x_skbq_init(mors, &yaps->mgmt_q,
632 			MM81X_HIF_FLAGS_DATA | MM81X_HIF_FLAGS_DIR_TO_HOST);
633 
634 	for (i = 0; i < ARRAY_SIZE(yaps->data_tx_qs); i++) {
635 		mm81x_skbq_init(mors, &yaps->data_tx_qs[i],
636 				MM81X_HIF_FLAGS_DATA |
637 					MM81X_HIF_FLAGS_DIR_TO_CHIP);
638 	}
639 
640 	mm81x_skbq_init(mors, &yaps->cmd_q,
641 			MM81X_HIF_FLAGS_COMMAND | MM81X_HIF_FLAGS_DIR_TO_CHIP);
642 	mm81x_skbq_init(mors, &yaps->cmd_resp_q,
643 			MM81X_HIF_FLAGS_COMMAND | MM81X_HIF_FLAGS_DIR_TO_HOST);
644 
645 	mm81x_yaps_q_chip_full_timer_init(yaps);
646 	INIT_WORK(&mors->hif_work, mm81x_yaps_work);
647 	INIT_WORK(&mors->tx_stale_work, mm81x_yaps_stale_tx_work);
648 	mm81x_release_bus(mors);
649 	mm81x_hw_enable_stop_notifications(mors, true);
650 	return 0;
651 }
652 
mm81x_yaps_finish(struct mm81x * mors)653 void mm81x_yaps_finish(struct mm81x *mors)
654 {
655 	int i;
656 	struct mm81x_yaps *yaps;
657 
658 	mm81x_yaps_hw_enable_irqs(mors, false);
659 
660 	yaps = &mors->hif.u.yaps;
661 	yaps->finish = true;
662 
663 	mm81x_skbq_finish(&yaps->data_rx_q);
664 	mm81x_skbq_finish(&yaps->beacon_q);
665 	mm81x_skbq_finish(&yaps->mgmt_q);
666 
667 	for (i = 0; i < ARRAY_SIZE(yaps->data_tx_qs); i++)
668 		mm81x_skbq_finish(&yaps->data_tx_qs[i]);
669 
670 	mm81x_skbq_finish(&yaps->cmd_q);
671 	mm81x_skbq_finish(&yaps->cmd_resp_q);
672 
673 	mm81x_yaps_q_chip_full_timer_finish(yaps);
674 
675 	cancel_work_sync(&mors->hif_work);
676 	cancel_work_sync(&mors->tx_stale_work);
677 
678 	mm81x_yaps_free_pkt_buffers(yaps);
679 	mm81x_yaps_hw_finish(mors);
680 }
681 
mm81x_yaps_flush_tx_data(struct mm81x * mors)682 void mm81x_yaps_flush_tx_data(struct mm81x *mors)
683 {
684 	int i;
685 	struct mm81x_yaps *yaps = &mors->hif.u.yaps;
686 
687 	mm81x_skbq_tx_flush(&yaps->beacon_q);
688 	mm81x_skbq_tx_flush(&yaps->mgmt_q);
689 
690 	for (i = 0; i < ARRAY_SIZE(yaps->data_tx_qs); i++)
691 		mm81x_skbq_tx_flush(&yaps->data_tx_qs[i]);
692 }
693 
mm81x_yaps_flush_cmds(struct mm81x * mors)694 void mm81x_yaps_flush_cmds(struct mm81x *mors)
695 {
696 	struct mm81x_yaps *yaps = &mors->hif.u.yaps;
697 
698 	if (yaps->flags & MM81X_HIF_FLAGS_COMMAND) {
699 		mm81x_skbq_finish(&yaps->cmd_q);
700 		mm81x_skbq_finish(&yaps->cmd_resp_q);
701 	}
702 }
703