Lines Matching +full:tx +full:- +full:device

1 // SPDX-License-Identifier: GPL-2.0-only
3 * Device handling thread implementation for mac80211 ST-Ericsson CW1200 drivers
5 * Copyright (c) 2010, ST-Ericsson
9 * ST-Ericsson UMAC CW1200 driver, which is
10 * Copyright (c) 2010, ST-Ericsson
29 #define DOWNLOAD_BLOCK_SIZE_WR (0x1000 - 4)
30 /* an SPI message cannot be bigger than (2"12-1)*2 bytes
35 #define EFFECTIVE_BUF_SIZE (MAX_SZ_RD_WR_BUFFERS - PIGGYBACK_CTRL_REG)
56 priv->bh_workqueue = alloc_workqueue("cw1200_bh", in cw1200_register_bh()
60 if (!priv->bh_workqueue) in cw1200_register_bh()
61 return -ENOMEM; in cw1200_register_bh()
63 INIT_WORK(&priv->bh_work, cw1200_bh_work); in cw1200_register_bh()
67 atomic_set(&priv->bh_rx, 0); in cw1200_register_bh()
68 atomic_set(&priv->bh_tx, 0); in cw1200_register_bh()
69 atomic_set(&priv->bh_term, 0); in cw1200_register_bh()
70 atomic_set(&priv->bh_suspend, CW1200_BH_RESUMED); in cw1200_register_bh()
71 priv->bh_error = 0; in cw1200_register_bh()
72 priv->hw_bufs_used = 0; in cw1200_register_bh()
73 priv->buf_id_tx = 0; in cw1200_register_bh()
74 priv->buf_id_rx = 0; in cw1200_register_bh()
75 init_waitqueue_head(&priv->bh_wq); in cw1200_register_bh()
76 init_waitqueue_head(&priv->bh_evt_wq); in cw1200_register_bh()
78 err = !queue_work(priv->bh_workqueue, &priv->bh_work); in cw1200_register_bh()
85 atomic_inc(&priv->bh_term); in cw1200_unregister_bh()
86 wake_up(&priv->bh_wq); in cw1200_unregister_bh()
88 destroy_workqueue(priv->bh_workqueue); in cw1200_unregister_bh()
89 priv->bh_workqueue = NULL; in cw1200_unregister_bh()
99 /* NOTE: hwbus_ops->lock already held */ in cw1200_irq_handler()
102 if (/* WARN_ON */(priv->bh_error)) in cw1200_irq_handler()
105 if (atomic_inc_return(&priv->bh_rx) == 1) in cw1200_irq_handler()
106 wake_up(&priv->bh_wq); in cw1200_irq_handler()
113 if (priv->bh_error) { in cw1200_bh_wakeup()
118 if (atomic_inc_return(&priv->bh_tx) == 1) in cw1200_bh_wakeup()
119 wake_up(&priv->bh_wq); in cw1200_bh_wakeup()
125 if (priv->bh_error) { in cw1200_bh_suspend()
126 wiphy_warn(priv->hw->wiphy, "BH error -- can't suspend\n"); in cw1200_bh_suspend()
127 return -EINVAL; in cw1200_bh_suspend()
130 atomic_set(&priv->bh_suspend, CW1200_BH_SUSPEND); in cw1200_bh_suspend()
131 wake_up(&priv->bh_wq); in cw1200_bh_suspend()
132 return wait_event_timeout(priv->bh_evt_wq, priv->bh_error || in cw1200_bh_suspend()
133 (CW1200_BH_SUSPENDED == atomic_read(&priv->bh_suspend)), in cw1200_bh_suspend()
134 1 * HZ) ? 0 : -ETIMEDOUT; in cw1200_bh_suspend()
140 if (priv->bh_error) { in cw1200_bh_resume()
141 wiphy_warn(priv->hw->wiphy, "BH error -- can't resume\n"); in cw1200_bh_resume()
142 return -EINVAL; in cw1200_bh_resume()
145 atomic_set(&priv->bh_suspend, CW1200_BH_RESUME); in cw1200_bh_resume()
146 wake_up(&priv->bh_wq); in cw1200_bh_resume()
147 return wait_event_timeout(priv->bh_evt_wq, priv->bh_error || in cw1200_bh_resume()
148 (CW1200_BH_RESUMED == atomic_read(&priv->bh_suspend)), in cw1200_bh_resume()
149 1 * HZ) ? 0 : -ETIMEDOUT; in cw1200_bh_resume()
154 ++priv->hw_bufs_used; in wsm_alloc_tx_buffer()
160 int hw_bufs_used = priv->hw_bufs_used; in wsm_release_tx_buffer()
162 priv->hw_bufs_used -= count; in wsm_release_tx_buffer()
163 if (WARN_ON(priv->hw_bufs_used < 0)) in wsm_release_tx_buffer()
164 ret = -1; in wsm_release_tx_buffer()
165 else if (hw_bufs_used >= priv->wsm_caps.input_buffers) in wsm_release_tx_buffer()
167 if (!priv->hw_bufs_used) in wsm_release_tx_buffer()
168 wake_up(&priv->bh_evt_wq); in wsm_release_tx_buffer()
194 pr_debug("[BH] Device wakeup.\n"); in cw1200_device_wakeup()
198 cw1200_dpll_from_clk(priv->hw_refclk)); in cw1200_device_wakeup()
202 /* To force the device to be always-on, the host sets WLAN_UP to 1 */ in cw1200_device_wakeup()
212 /* If the device returns WLAN_RDY as 1, the device is active and will in cw1200_device_wakeup()
216 pr_debug("[BH] Device awake.\n"); in cw1200_device_wakeup()
229 priv->powersave_enabled = enable; in cw1200_enable_powersave()
234 int *tx) in cw1200_bh_rx_helper() argument
263 alloc_len = priv->hwbus_ops->align_size( in cw1200_bh_rx_helper()
264 priv->hwbus_priv, read_len); in cw1200_bh_rx_helper()
278 data = skb_rx->data; in cw1200_bh_rx_helper()
289 ((__le16 *)data)[alloc_len / 2 - 1]); in cw1200_bh_rx_helper()
292 wsm_len = __le16_to_cpu(wsm->len); in cw1200_bh_rx_helper()
296 if (priv->wsm_enable_wsm_dumps) in cw1200_bh_rx_helper()
297 print_hex_dump_bytes("<-- ", in cw1200_bh_rx_helper()
301 wsm_id = __le16_to_cpu(wsm->id) & 0xFFF; in cw1200_bh_rx_helper()
302 wsm_seq = (__le16_to_cpu(wsm->id) >> 13) & 7; in cw1200_bh_rx_helper()
309 wsm_len - sizeof(*wsm)); in cw1200_bh_rx_helper()
312 if (WARN_ON(wsm_seq != priv->wsm_rx_seq)) in cw1200_bh_rx_helper()
315 priv->wsm_rx_seq = (wsm_seq + 1) & 7; in cw1200_bh_rx_helper()
323 *tx = 1; in cw1200_bh_rx_helper()
336 return -1; in cw1200_bh_rx_helper()
348 if (priv->device_can_sleep) { in cw1200_bh_tx_helper()
354 priv->device_can_sleep = false; in cw1200_bh_tx_helper()
372 BUG_ON(__le16_to_cpu(wsm->len) != tx_len); in cw1200_bh_tx_helper()
374 atomic_inc(&priv->bh_tx); in cw1200_bh_tx_helper()
376 tx_len = priv->hwbus_ops->align_size( in cw1200_bh_tx_helper()
377 priv->hwbus_priv, tx_len); in cw1200_bh_tx_helper()
383 wsm->id &= __cpu_to_le16(0xffff ^ WSM_TX_SEQ(WSM_TX_SEQ_MAX)); in cw1200_bh_tx_helper()
384 wsm->id |= __cpu_to_le16(WSM_TX_SEQ(priv->wsm_tx_seq)); in cw1200_bh_tx_helper()
387 pr_err("tx blew up, len %zu\n", tx_len); in cw1200_bh_tx_helper()
389 return -1; /* Error */ in cw1200_bh_tx_helper()
392 if (priv->wsm_enable_wsm_dumps) in cw1200_bh_tx_helper()
393 print_hex_dump_bytes("--> ", in cw1200_bh_tx_helper()
396 __le16_to_cpu(wsm->len)); in cw1200_bh_tx_helper()
399 priv->wsm_tx_seq = (priv->wsm_tx_seq + 1) & WSM_TX_SEQ_MAX; in cw1200_bh_tx_helper()
412 int rx, tx, term, suspend; in cw1200_bh() local
422 if (!priv->hw_bufs_used && in cw1200_bh()
423 priv->powersave_enabled && in cw1200_bh()
424 !priv->device_can_sleep && in cw1200_bh()
425 !atomic_read(&priv->recent_scan)) { in cw1200_bh()
427 pr_debug("[BH] Device wakedown. No data.\n"); in cw1200_bh()
429 priv->device_can_sleep = true; in cw1200_bh()
430 } else if (priv->hw_bufs_used) { in cw1200_bh()
438 if ((priv->hw_type != -1) && in cw1200_bh()
439 (atomic_read(&priv->bh_rx) == 0) && in cw1200_bh()
440 (atomic_read(&priv->bh_tx) == 0)) in cw1200_bh()
445 status = wait_event_interruptible_timeout(priv->bh_wq, ({ in cw1200_bh()
446 rx = atomic_xchg(&priv->bh_rx, 0); in cw1200_bh()
447 tx = atomic_xchg(&priv->bh_tx, 0); in cw1200_bh()
448 term = atomic_xchg(&priv->bh_term, 0); in cw1200_bh()
450 0 : atomic_read(&priv->bh_suspend); in cw1200_bh()
451 (rx || tx || term || suspend || priv->bh_error); in cw1200_bh()
454 pr_debug("[BH] - rx: %d, tx: %d, term: %d, bh_err: %d, suspend: %d, status: %ld\n", in cw1200_bh()
455 rx, tx, term, suspend, priv->bh_error, status); in cw1200_bh()
458 if ((status < 0 && status != -ERESTARTSYS) || in cw1200_bh()
459 term || priv->bh_error) { in cw1200_bh()
469 if (priv->hw_bufs_used && (!rx || !tx)) { in cw1200_bh()
470 wiphy_warn(priv->hw->wiphy, in cw1200_bh()
472 priv->hw_bufs_used); in cw1200_bh()
478 &priv->tx_queue[i], in cw1200_bh()
480 priv->pending_frame_id); in cw1200_bh()
488 1 * HZ - in cw1200_bh()
493 wiphy_warn(priv->hw->wiphy, in cw1200_bh()
494 "Timeout waiting for TX confirm (%d/%d pending, %ld vs %lu).\n", in cw1200_bh()
495 priv->hw_bufs_used, pending, in cw1200_bh()
499 } else if (!priv->device_can_sleep && in cw1200_bh()
500 !atomic_read(&priv->recent_scan)) { in cw1200_bh()
501 pr_debug("[BH] Device wakedown. Timeout.\n"); in cw1200_bh()
504 priv->device_can_sleep = true; in cw1200_bh()
508 pr_debug("[BH] Device suspend.\n"); in cw1200_bh()
509 if (priv->powersave_enabled) { in cw1200_bh()
510 pr_debug("[BH] Device wakedown. Suspend.\n"); in cw1200_bh()
513 priv->device_can_sleep = true; in cw1200_bh()
516 atomic_set(&priv->bh_suspend, CW1200_BH_SUSPENDED); in cw1200_bh()
517 wake_up(&priv->bh_evt_wq); in cw1200_bh()
518 status = wait_event_interruptible(priv->bh_wq, in cw1200_bh()
519 CW1200_BH_RESUME == atomic_read(&priv->bh_suspend)); in cw1200_bh()
521 wiphy_err(priv->hw->wiphy, in cw1200_bh()
526 pr_debug("[BH] Device resume.\n"); in cw1200_bh()
527 atomic_set(&priv->bh_suspend, CW1200_BH_RESUMED); in cw1200_bh()
528 wake_up(&priv->bh_evt_wq); in cw1200_bh()
529 atomic_inc(&priv->bh_rx); in cw1200_bh()
534 tx += pending_tx; in cw1200_bh()
542 ret = cw1200_bh_rx_helper(priv, &ctrl_reg, &tx); in cw1200_bh()
547 ret = cw1200_bh_rx_helper(priv, &ctrl_reg, &tx); in cw1200_bh()
553 tx: in cw1200_bh()
554 if (tx) { in cw1200_bh()
555 tx = 0; in cw1200_bh()
557 BUG_ON(priv->hw_bufs_used > priv->wsm_caps.input_buffers); in cw1200_bh()
558 tx_burst = priv->wsm_caps.input_buffers - priv->hw_bufs_used; in cw1200_bh()
562 /* Buffers full. Ensure we process tx in cw1200_bh()
565 pending_tx = tx; in cw1200_bh()
572 tx = ret; in cw1200_bh()
574 /* Re-read ctrl reg */ in cw1200_bh()
580 if (priv->bh_error) in cw1200_bh()
584 if (tx) in cw1200_bh()
585 goto tx; in cw1200_bh()
588 /* Re-enable device interrupts */ in cw1200_bh()
589 priv->hwbus_ops->lock(priv->hwbus_priv); in cw1200_bh()
591 priv->hwbus_ops->unlock(priv->hwbus_priv); in cw1200_bh()
594 /* Explicitly disable device interrupts */ in cw1200_bh()
595 priv->hwbus_ops->lock(priv->hwbus_priv); in cw1200_bh()
597 priv->hwbus_ops->unlock(priv->hwbus_priv); in cw1200_bh()
601 priv->bh_error = 1; in cw1200_bh()