2 * Device handling thread implementation for mac80211 ST-Ericsson CW1200 drivers
4 * Copyright (c) 2010, ST-Ericsson
5 * Author: Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>
8 * ST-Ericsson UMAC CW1200 driver, which is
9 * Copyright (c) 2010, ST-Ericsson
10 * Author: Ajitpal Singh <ajitpal.singh@stericsson.com>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
17 #include <linux/module.h>
18 #include <net/mac80211.h>
19 #include <linux/kthread.h>
20 #include <linux/timer.h>
30 static int cw1200_bh(void *arg
);
32 #define DOWNLOAD_BLOCK_SIZE_WR (0x1000 - 4)
33 /* an SPI message cannot be bigger than (2"12-1)*2 bytes
34 * "*2" to cvt to bytes
36 #define MAX_SZ_RD_WR_BUFFERS (DOWNLOAD_BLOCK_SIZE_WR*2)
37 #define PIGGYBACK_CTRL_REG (2)
38 #define EFFECTIVE_BUF_SIZE (MAX_SZ_RD_WR_BUFFERS - PIGGYBACK_CTRL_REG)
40 /* Suspend state privates */
41 enum cw1200_bh_pm_state
{
42 CW1200_BH_RESUMED
= 0,
48 typedef int (*cw1200_wsm_handler
)(struct cw1200_common
*priv
,
49 u8
*data
, size_t size
);
51 static void cw1200_bh_work(struct work_struct
*work
)
53 struct cw1200_common
*priv
=
54 container_of(work
, struct cw1200_common
, bh_work
);
58 int cw1200_register_bh(struct cw1200_common
*priv
)
61 /* Realtime workqueue */
62 priv
->bh_workqueue
= alloc_workqueue("cw1200_bh",
63 WQ_MEM_RECLAIM
| WQ_HIGHPRI
64 | WQ_CPU_INTENSIVE
, 1);
66 if (!priv
->bh_workqueue
)
69 INIT_WORK(&priv
->bh_work
, cw1200_bh_work
);
71 pr_debug("[BH] register.\n");
73 atomic_set(&priv
->bh_rx
, 0);
74 atomic_set(&priv
->bh_tx
, 0);
75 atomic_set(&priv
->bh_term
, 0);
76 atomic_set(&priv
->bh_suspend
, CW1200_BH_RESUMED
);
78 priv
->hw_bufs_used
= 0;
81 init_waitqueue_head(&priv
->bh_wq
);
82 init_waitqueue_head(&priv
->bh_evt_wq
);
84 err
= !queue_work(priv
->bh_workqueue
, &priv
->bh_work
);
89 void cw1200_unregister_bh(struct cw1200_common
*priv
)
91 atomic_add(1, &priv
->bh_term
);
92 wake_up(&priv
->bh_wq
);
94 flush_workqueue(priv
->bh_workqueue
);
96 destroy_workqueue(priv
->bh_workqueue
);
97 priv
->bh_workqueue
= NULL
;
99 pr_debug("[BH] unregistered.\n");
102 void cw1200_irq_handler(struct cw1200_common
*priv
)
104 pr_debug("[BH] irq.\n");
106 /* Disable Interrupts! */
107 /* NOTE: hwbus_ops->lock already held */
108 __cw1200_irq_enable(priv
, 0);
110 if (/* WARN_ON */(priv
->bh_error
))
113 if (atomic_add_return(1, &priv
->bh_rx
) == 1)
114 wake_up(&priv
->bh_wq
);
116 EXPORT_SYMBOL_GPL(cw1200_irq_handler
);
118 void cw1200_bh_wakeup(struct cw1200_common
*priv
)
120 pr_debug("[BH] wakeup.\n");
121 if (priv
->bh_error
) {
122 pr_err("[BH] wakeup failed (BH error)\n");
126 if (atomic_add_return(1, &priv
->bh_tx
) == 1)
127 wake_up(&priv
->bh_wq
);
130 int cw1200_bh_suspend(struct cw1200_common
*priv
)
132 pr_debug("[BH] suspend.\n");
133 if (priv
->bh_error
) {
134 wiphy_warn(priv
->hw
->wiphy
, "BH error -- can't suspend\n");
138 atomic_set(&priv
->bh_suspend
, CW1200_BH_SUSPEND
);
139 wake_up(&priv
->bh_wq
);
140 return wait_event_timeout(priv
->bh_evt_wq
, priv
->bh_error
||
141 (CW1200_BH_SUSPENDED
== atomic_read(&priv
->bh_suspend
)),
142 1 * HZ
) ? 0 : -ETIMEDOUT
;
145 int cw1200_bh_resume(struct cw1200_common
*priv
)
147 pr_debug("[BH] resume.\n");
148 if (priv
->bh_error
) {
149 wiphy_warn(priv
->hw
->wiphy
, "BH error -- can't resume\n");
153 atomic_set(&priv
->bh_suspend
, CW1200_BH_RESUME
);
154 wake_up(&priv
->bh_wq
);
155 return wait_event_timeout(priv
->bh_evt_wq
, priv
->bh_error
||
156 (CW1200_BH_RESUMED
== atomic_read(&priv
->bh_suspend
)),
157 1 * HZ
) ? 0 : -ETIMEDOUT
;
160 static inline void wsm_alloc_tx_buffer(struct cw1200_common
*priv
)
162 ++priv
->hw_bufs_used
;
165 int wsm_release_tx_buffer(struct cw1200_common
*priv
, int count
)
168 int hw_bufs_used
= priv
->hw_bufs_used
;
170 priv
->hw_bufs_used
-= count
;
171 if (WARN_ON(priv
->hw_bufs_used
< 0))
173 else if (hw_bufs_used
>= priv
->wsm_caps
.input_buffers
)
175 if (!priv
->hw_bufs_used
)
176 wake_up(&priv
->bh_evt_wq
);
180 static int cw1200_bh_read_ctrl_reg(struct cw1200_common
*priv
,
185 ret
= cw1200_reg_read_16(priv
,
186 ST90TDS_CONTROL_REG_ID
, ctrl_reg
);
188 ret
= cw1200_reg_read_16(priv
,
189 ST90TDS_CONTROL_REG_ID
, ctrl_reg
);
191 pr_err("[BH] Failed to read control register.\n");
197 static int cw1200_device_wakeup(struct cw1200_common
*priv
)
202 pr_debug("[BH] Device wakeup.\n");
204 /* First, set the dpll register */
205 ret
= cw1200_reg_write_32(priv
, ST90TDS_TSET_GEN_R_W_REG_ID
,
206 cw1200_dpll_from_clk(priv
->hw_refclk
));
210 /* To force the device to be always-on, the host sets WLAN_UP to 1 */
211 ret
= cw1200_reg_write_16(priv
, ST90TDS_CONTROL_REG_ID
,
212 ST90TDS_CONT_WUP_BIT
);
216 ret
= cw1200_bh_read_ctrl_reg(priv
, &ctrl_reg
);
220 /* If the device returns WLAN_RDY as 1, the device is active and will
223 if (ctrl_reg
& ST90TDS_CONT_RDY_BIT
) {
224 pr_debug("[BH] Device awake.\n");
231 /* Must be called from BH thraed. */
232 void cw1200_enable_powersave(struct cw1200_common
*priv
,
235 pr_debug("[BH] Powerave is %s.\n",
236 enable
? "enabled" : "disabled");
237 priv
->powersave_enabled
= enable
;
240 static int cw1200_bh_rx_helper(struct cw1200_common
*priv
,
245 struct sk_buff
*skb_rx
= NULL
;
255 read_len
= (*ctrl_reg
& ST90TDS_CONT_NEXT_LEN_MASK
) * 2;
257 return 0; /* No more work */
259 if (WARN_ON((read_len
< sizeof(struct wsm_hdr
)) ||
260 (read_len
> EFFECTIVE_BUF_SIZE
))) {
261 pr_debug("Invalid read len: %zu (%04x)",
262 read_len
, *ctrl_reg
);
266 /* Add SIZE of PIGGYBACK reg (CONTROL Reg)
267 * to the NEXT Message length + 2 Bytes for SKB
269 read_len
= read_len
+ 2;
271 alloc_len
= priv
->hwbus_ops
->align_size(
272 priv
->hwbus_priv
, read_len
);
274 /* Check if not exceeding CW1200 capabilities */
275 if (WARN_ON_ONCE(alloc_len
> EFFECTIVE_BUF_SIZE
)) {
276 pr_debug("Read aligned len: %zu\n",
280 skb_rx
= dev_alloc_skb(alloc_len
);
281 if (WARN_ON(!skb_rx
))
285 skb_put(skb_rx
, read_len
);
290 if (WARN_ON(cw1200_data_read(priv
, data
, alloc_len
))) {
291 pr_err("rx blew up, len %zu\n", alloc_len
);
296 *ctrl_reg
= __le16_to_cpu(
297 ((__le16
*)data
)[alloc_len
/ 2 - 1]);
299 wsm
= (struct wsm_hdr
*)data
;
300 wsm_len
= __le16_to_cpu(wsm
->len
);
301 if (WARN_ON(wsm_len
> read_len
))
304 if (priv
->wsm_enable_wsm_dumps
)
305 print_hex_dump_bytes("<-- ",
309 wsm_id
= __le16_to_cpu(wsm
->id
) & 0xFFF;
310 wsm_seq
= (__le16_to_cpu(wsm
->id
) >> 13) & 7;
312 skb_trim(skb_rx
, wsm_len
);
314 if (wsm_id
== 0x0800) {
315 wsm_handle_exception(priv
,
317 wsm_len
- sizeof(*wsm
));
319 } else if (!rx_resync
) {
320 if (WARN_ON(wsm_seq
!= priv
->wsm_rx_seq
))
323 priv
->wsm_rx_seq
= (wsm_seq
+ 1) & 7;
326 if (wsm_id
& 0x0400) {
327 int rc
= wsm_release_tx_buffer(priv
, 1);
334 /* cw1200_wsm_rx takes care on SKB livetime */
335 if (WARN_ON(wsm_handle_rx(priv
, wsm_id
, wsm
, &skb_rx
)))
339 dev_kfree_skb(skb_rx
);
347 dev_kfree_skb(skb_rx
);
353 static int cw1200_bh_tx_helper(struct cw1200_common
*priv
,
362 if (priv
->device_can_sleep
) {
363 ret
= cw1200_device_wakeup(priv
);
364 if (WARN_ON(ret
< 0)) { /* Error in wakeup */
367 } else if (ret
) { /* Woke up */
368 priv
->device_can_sleep
= false;
369 } else { /* Did not awake */
375 wsm_alloc_tx_buffer(priv
);
376 ret
= wsm_get_tx(priv
, &data
, &tx_len
, tx_burst
);
378 wsm_release_tx_buffer(priv
, 1);
379 if (WARN_ON(ret
< 0))
380 return ret
; /* Error */
381 return 0; /* No work */
384 wsm
= (struct wsm_hdr
*)data
;
385 BUG_ON(tx_len
< sizeof(*wsm
));
386 BUG_ON(__le16_to_cpu(wsm
->len
) != tx_len
);
388 atomic_add(1, &priv
->bh_tx
);
390 tx_len
= priv
->hwbus_ops
->align_size(
391 priv
->hwbus_priv
, tx_len
);
393 /* Check if not exceeding CW1200 capabilities */
394 if (WARN_ON_ONCE(tx_len
> EFFECTIVE_BUF_SIZE
))
395 pr_debug("Write aligned len: %zu\n", tx_len
);
397 wsm
->id
&= __cpu_to_le16(0xffff ^ WSM_TX_SEQ(WSM_TX_SEQ_MAX
));
398 wsm
->id
|= __cpu_to_le16(WSM_TX_SEQ(priv
->wsm_tx_seq
));
400 if (WARN_ON(cw1200_data_write(priv
, data
, tx_len
))) {
401 pr_err("tx blew up, len %zu\n", tx_len
);
402 wsm_release_tx_buffer(priv
, 1);
403 return -1; /* Error */
406 if (priv
->wsm_enable_wsm_dumps
)
407 print_hex_dump_bytes("--> ",
410 __le16_to_cpu(wsm
->len
));
412 wsm_txed(priv
, data
);
413 priv
->wsm_tx_seq
= (priv
->wsm_tx_seq
+ 1) & WSM_TX_SEQ_MAX
;
416 cw1200_debug_tx_burst(priv
);
417 return 1; /* Work remains */
423 static int cw1200_bh(void *arg
)
425 struct cw1200_common
*priv
= arg
;
426 int rx
, tx
, term
, suspend
;
436 if (!priv
->hw_bufs_used
&&
437 priv
->powersave_enabled
&&
438 !priv
->device_can_sleep
&&
439 !atomic_read(&priv
->recent_scan
)) {
441 pr_debug("[BH] Device wakedown. No data.\n");
442 cw1200_reg_write_16(priv
, ST90TDS_CONTROL_REG_ID
, 0);
443 priv
->device_can_sleep
= true;
444 } else if (priv
->hw_bufs_used
) {
445 /* Interrupt loss detection */
448 status
= MAX_SCHEDULE_TIMEOUT
;
451 /* Dummy Read for SDIO retry mechanism*/
452 if ((priv
->hw_type
!= -1) &&
453 (atomic_read(&priv
->bh_rx
) == 0) &&
454 (atomic_read(&priv
->bh_tx
) == 0))
455 cw1200_reg_read(priv
, ST90TDS_CONFIG_REG_ID
,
456 &dummy
, sizeof(dummy
));
458 pr_debug("[BH] waiting ...\n");
459 status
= wait_event_interruptible_timeout(priv
->bh_wq
, ({
460 rx
= atomic_xchg(&priv
->bh_rx
, 0);
461 tx
= atomic_xchg(&priv
->bh_tx
, 0);
462 term
= atomic_xchg(&priv
->bh_term
, 0);
463 suspend
= pending_tx
?
464 0 : atomic_read(&priv
->bh_suspend
);
465 (rx
|| tx
|| term
|| suspend
|| priv
->bh_error
);
468 pr_debug("[BH] - rx: %d, tx: %d, term: %d, bh_err: %d, suspend: %d, status: %ld\n",
469 rx
, tx
, term
, suspend
, priv
->bh_error
, status
);
471 /* Did an error occur? */
472 if ((status
< 0 && status
!= -ERESTARTSYS
) ||
473 term
|| priv
->bh_error
) {
476 if (!status
) { /* wait_event timed out */
477 unsigned long timestamp
= jiffies
;
482 /* Check to see if we have any outstanding frames */
483 if (priv
->hw_bufs_used
&& (!rx
|| !tx
)) {
484 wiphy_warn(priv
->hw
->wiphy
,
485 "Missed interrupt? (%d frames outstanding)\n",
489 /* Get a timestamp of "oldest" frame */
490 for (i
= 0; i
< 4; ++i
)
491 pending
+= cw1200_queue_get_xmit_timestamp(
494 priv
->pending_frame_id
);
496 /* Check if frame transmission is timed out.
497 * Add an extra second with respect to possible
500 timeout
= timestamp
+
501 WSM_CMD_LAST_CHANCE_TIMEOUT
+
505 /* And terminate BH thread if the frame is "stuck" */
506 if (pending
&& timeout
< 0) {
507 wiphy_warn(priv
->hw
->wiphy
,
508 "Timeout waiting for TX confirm (%d/%d pending, %ld vs %lu).\n",
509 priv
->hw_bufs_used
, pending
,
513 } else if (!priv
->device_can_sleep
&&
514 !atomic_read(&priv
->recent_scan
)) {
515 pr_debug("[BH] Device wakedown. Timeout.\n");
516 cw1200_reg_write_16(priv
,
517 ST90TDS_CONTROL_REG_ID
, 0);
518 priv
->device_can_sleep
= true;
521 } else if (suspend
) {
522 pr_debug("[BH] Device suspend.\n");
523 if (priv
->powersave_enabled
) {
524 pr_debug("[BH] Device wakedown. Suspend.\n");
525 cw1200_reg_write_16(priv
,
526 ST90TDS_CONTROL_REG_ID
, 0);
527 priv
->device_can_sleep
= true;
530 atomic_set(&priv
->bh_suspend
, CW1200_BH_SUSPENDED
);
531 wake_up(&priv
->bh_evt_wq
);
532 status
= wait_event_interruptible(priv
->bh_wq
,
533 CW1200_BH_RESUME
== atomic_read(&priv
->bh_suspend
));
535 wiphy_err(priv
->hw
->wiphy
,
536 "Failed to wait for resume: %ld.\n",
540 pr_debug("[BH] Device resume.\n");
541 atomic_set(&priv
->bh_suspend
, CW1200_BH_RESUMED
);
542 wake_up(&priv
->bh_evt_wq
);
543 atomic_add(1, &priv
->bh_rx
);
551 if (cw1200_bh_read_ctrl_reg(priv
, &ctrl_reg
))
554 /* Don't bother trying to rx unless we have data to read */
555 if (ctrl_reg
& ST90TDS_CONT_NEXT_LEN_MASK
) {
556 ret
= cw1200_bh_rx_helper(priv
, &ctrl_reg
, &tx
);
559 /* Double up here if there's more data.. */
560 if (ctrl_reg
& ST90TDS_CONT_NEXT_LEN_MASK
) {
561 ret
= cw1200_bh_rx_helper(priv
, &ctrl_reg
, &tx
);
571 BUG_ON(priv
->hw_bufs_used
> priv
->wsm_caps
.input_buffers
);
572 tx_burst
= priv
->wsm_caps
.input_buffers
- priv
->hw_bufs_used
;
573 tx_allowed
= tx_burst
> 0;
576 /* Buffers full. Ensure we process tx
577 * after we handle rx..
582 ret
= cw1200_bh_tx_helper(priv
, &pending_tx
, &tx_burst
);
585 if (ret
> 0) /* More to transmit */
588 /* Re-read ctrl reg */
589 if (cw1200_bh_read_ctrl_reg(priv
, &ctrl_reg
))
596 if (ctrl_reg
& ST90TDS_CONT_NEXT_LEN_MASK
)
602 /* Re-enable device interrupts */
603 priv
->hwbus_ops
->lock(priv
->hwbus_priv
);
604 __cw1200_irq_enable(priv
, 1);
605 priv
->hwbus_ops
->unlock(priv
->hwbus_priv
);
608 /* Explicitly disable device interrupts */
609 priv
->hwbus_ops
->lock(priv
->hwbus_priv
);
610 __cw1200_irq_enable(priv
, 0);
611 priv
->hwbus_ops
->unlock(priv
->hwbus_priv
);
614 pr_err("[BH] Fatal error, exiting.\n");
616 /* TODO: schedule_work(recovery) */