0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/module.h>
0015 #include <net/mac80211.h>
0016 #include <linux/kthread.h>
0017 #include <linux/timer.h>
0018
0019 #include "cw1200.h"
0020 #include "bh.h"
0021 #include "hwio.h"
0022 #include "wsm.h"
0023 #include "hwbus.h"
0024 #include "debug.h"
0025 #include "fwio.h"
0026
0027 static int cw1200_bh(void *arg);
0028
0029 #define DOWNLOAD_BLOCK_SIZE_WR (0x1000 - 4)
0030
0031
0032
0033 #define MAX_SZ_RD_WR_BUFFERS (DOWNLOAD_BLOCK_SIZE_WR*2)
0034 #define PIGGYBACK_CTRL_REG (2)
0035 #define EFFECTIVE_BUF_SIZE (MAX_SZ_RD_WR_BUFFERS - PIGGYBACK_CTRL_REG)
0036
0037
0038 enum cw1200_bh_pm_state {
0039 CW1200_BH_RESUMED = 0,
0040 CW1200_BH_SUSPEND,
0041 CW1200_BH_SUSPENDED,
0042 CW1200_BH_RESUME,
0043 };
0044
0045 static void cw1200_bh_work(struct work_struct *work)
0046 {
0047 struct cw1200_common *priv =
0048 container_of(work, struct cw1200_common, bh_work);
0049 cw1200_bh(priv);
0050 }
0051
0052 int cw1200_register_bh(struct cw1200_common *priv)
0053 {
0054 int err = 0;
0055
0056 priv->bh_workqueue = alloc_workqueue("cw1200_bh",
0057 WQ_MEM_RECLAIM | WQ_HIGHPRI
0058 | WQ_CPU_INTENSIVE, 1);
0059
0060 if (!priv->bh_workqueue)
0061 return -ENOMEM;
0062
0063 INIT_WORK(&priv->bh_work, cw1200_bh_work);
0064
0065 pr_debug("[BH] register.\n");
0066
0067 atomic_set(&priv->bh_rx, 0);
0068 atomic_set(&priv->bh_tx, 0);
0069 atomic_set(&priv->bh_term, 0);
0070 atomic_set(&priv->bh_suspend, CW1200_BH_RESUMED);
0071 priv->bh_error = 0;
0072 priv->hw_bufs_used = 0;
0073 priv->buf_id_tx = 0;
0074 priv->buf_id_rx = 0;
0075 init_waitqueue_head(&priv->bh_wq);
0076 init_waitqueue_head(&priv->bh_evt_wq);
0077
0078 err = !queue_work(priv->bh_workqueue, &priv->bh_work);
0079 WARN_ON(err);
0080 return err;
0081 }
0082
0083 void cw1200_unregister_bh(struct cw1200_common *priv)
0084 {
0085 atomic_inc(&priv->bh_term);
0086 wake_up(&priv->bh_wq);
0087
0088 destroy_workqueue(priv->bh_workqueue);
0089 priv->bh_workqueue = NULL;
0090
0091 pr_debug("[BH] unregistered.\n");
0092 }
0093
0094 void cw1200_irq_handler(struct cw1200_common *priv)
0095 {
0096 pr_debug("[BH] irq.\n");
0097
0098
0099
0100 __cw1200_irq_enable(priv, 0);
0101
0102 if ((priv->bh_error))
0103 return;
0104
0105 if (atomic_inc_return(&priv->bh_rx) == 1)
0106 wake_up(&priv->bh_wq);
0107 }
0108 EXPORT_SYMBOL_GPL(cw1200_irq_handler);
0109
0110 void cw1200_bh_wakeup(struct cw1200_common *priv)
0111 {
0112 pr_debug("[BH] wakeup.\n");
0113 if (priv->bh_error) {
0114 pr_err("[BH] wakeup failed (BH error)\n");
0115 return;
0116 }
0117
0118 if (atomic_inc_return(&priv->bh_tx) == 1)
0119 wake_up(&priv->bh_wq);
0120 }
0121
0122 int cw1200_bh_suspend(struct cw1200_common *priv)
0123 {
0124 pr_debug("[BH] suspend.\n");
0125 if (priv->bh_error) {
0126 wiphy_warn(priv->hw->wiphy, "BH error -- can't suspend\n");
0127 return -EINVAL;
0128 }
0129
0130 atomic_set(&priv->bh_suspend, CW1200_BH_SUSPEND);
0131 wake_up(&priv->bh_wq);
0132 return wait_event_timeout(priv->bh_evt_wq, priv->bh_error ||
0133 (CW1200_BH_SUSPENDED == atomic_read(&priv->bh_suspend)),
0134 1 * HZ) ? 0 : -ETIMEDOUT;
0135 }
0136
0137 int cw1200_bh_resume(struct cw1200_common *priv)
0138 {
0139 pr_debug("[BH] resume.\n");
0140 if (priv->bh_error) {
0141 wiphy_warn(priv->hw->wiphy, "BH error -- can't resume\n");
0142 return -EINVAL;
0143 }
0144
0145 atomic_set(&priv->bh_suspend, CW1200_BH_RESUME);
0146 wake_up(&priv->bh_wq);
0147 return wait_event_timeout(priv->bh_evt_wq, priv->bh_error ||
0148 (CW1200_BH_RESUMED == atomic_read(&priv->bh_suspend)),
0149 1 * HZ) ? 0 : -ETIMEDOUT;
0150 }
0151
0152 static inline void wsm_alloc_tx_buffer(struct cw1200_common *priv)
0153 {
0154 ++priv->hw_bufs_used;
0155 }
0156
0157 int wsm_release_tx_buffer(struct cw1200_common *priv, int count)
0158 {
0159 int ret = 0;
0160 int hw_bufs_used = priv->hw_bufs_used;
0161
0162 priv->hw_bufs_used -= count;
0163 if (WARN_ON(priv->hw_bufs_used < 0))
0164 ret = -1;
0165 else if (hw_bufs_used >= priv->wsm_caps.input_buffers)
0166 ret = 1;
0167 if (!priv->hw_bufs_used)
0168 wake_up(&priv->bh_evt_wq);
0169 return ret;
0170 }
0171
0172 static int cw1200_bh_read_ctrl_reg(struct cw1200_common *priv,
0173 u16 *ctrl_reg)
0174 {
0175 int ret;
0176
0177 ret = cw1200_reg_read_16(priv,
0178 ST90TDS_CONTROL_REG_ID, ctrl_reg);
0179 if (ret) {
0180 ret = cw1200_reg_read_16(priv,
0181 ST90TDS_CONTROL_REG_ID, ctrl_reg);
0182 if (ret)
0183 pr_err("[BH] Failed to read control register.\n");
0184 }
0185
0186 return ret;
0187 }
0188
0189 static int cw1200_device_wakeup(struct cw1200_common *priv)
0190 {
0191 u16 ctrl_reg;
0192 int ret;
0193
0194 pr_debug("[BH] Device wakeup.\n");
0195
0196
0197 ret = cw1200_reg_write_32(priv, ST90TDS_TSET_GEN_R_W_REG_ID,
0198 cw1200_dpll_from_clk(priv->hw_refclk));
0199 if (WARN_ON(ret))
0200 return ret;
0201
0202
0203 ret = cw1200_reg_write_16(priv, ST90TDS_CONTROL_REG_ID,
0204 ST90TDS_CONT_WUP_BIT);
0205 if (WARN_ON(ret))
0206 return ret;
0207
0208 ret = cw1200_bh_read_ctrl_reg(priv, &ctrl_reg);
0209 if (WARN_ON(ret))
0210 return ret;
0211
0212
0213
0214
0215 if (ctrl_reg & ST90TDS_CONT_RDY_BIT) {
0216 pr_debug("[BH] Device awake.\n");
0217 return 1;
0218 }
0219
0220 return 0;
0221 }
0222
0223
0224 void cw1200_enable_powersave(struct cw1200_common *priv,
0225 bool enable)
0226 {
0227 pr_debug("[BH] Powerave is %s.\n",
0228 enable ? "enabled" : "disabled");
0229 priv->powersave_enabled = enable;
0230 }
0231
0232 static int cw1200_bh_rx_helper(struct cw1200_common *priv,
0233 uint16_t *ctrl_reg,
0234 int *tx)
0235 {
0236 size_t read_len = 0;
0237 struct sk_buff *skb_rx = NULL;
0238 struct wsm_hdr *wsm;
0239 size_t wsm_len;
0240 u16 wsm_id;
0241 u8 wsm_seq;
0242 int rx_resync = 1;
0243
0244 size_t alloc_len;
0245 u8 *data;
0246
0247 read_len = (*ctrl_reg & ST90TDS_CONT_NEXT_LEN_MASK) * 2;
0248 if (!read_len)
0249 return 0;
0250
0251 if (WARN_ON((read_len < sizeof(struct wsm_hdr)) ||
0252 (read_len > EFFECTIVE_BUF_SIZE))) {
0253 pr_debug("Invalid read len: %zu (%04x)",
0254 read_len, *ctrl_reg);
0255 goto err;
0256 }
0257
0258
0259
0260
0261 read_len = read_len + 2;
0262
0263 alloc_len = priv->hwbus_ops->align_size(
0264 priv->hwbus_priv, read_len);
0265
0266
0267 if (WARN_ON_ONCE(alloc_len > EFFECTIVE_BUF_SIZE)) {
0268 pr_debug("Read aligned len: %zu\n",
0269 alloc_len);
0270 }
0271
0272 skb_rx = dev_alloc_skb(alloc_len);
0273 if (WARN_ON(!skb_rx))
0274 goto err;
0275
0276 skb_trim(skb_rx, 0);
0277 skb_put(skb_rx, read_len);
0278 data = skb_rx->data;
0279 if (WARN_ON(!data))
0280 goto err;
0281
0282 if (WARN_ON(cw1200_data_read(priv, data, alloc_len))) {
0283 pr_err("rx blew up, len %zu\n", alloc_len);
0284 goto err;
0285 }
0286
0287
0288 *ctrl_reg = __le16_to_cpu(
0289 ((__le16 *)data)[alloc_len / 2 - 1]);
0290
0291 wsm = (struct wsm_hdr *)data;
0292 wsm_len = __le16_to_cpu(wsm->len);
0293 if (WARN_ON(wsm_len > read_len))
0294 goto err;
0295
0296 if (priv->wsm_enable_wsm_dumps)
0297 print_hex_dump_bytes("<-- ",
0298 DUMP_PREFIX_NONE,
0299 data, wsm_len);
0300
0301 wsm_id = __le16_to_cpu(wsm->id) & 0xFFF;
0302 wsm_seq = (__le16_to_cpu(wsm->id) >> 13) & 7;
0303
0304 skb_trim(skb_rx, wsm_len);
0305
0306 if (wsm_id == 0x0800) {
0307 wsm_handle_exception(priv,
0308 &data[sizeof(*wsm)],
0309 wsm_len - sizeof(*wsm));
0310 goto err;
0311 } else if (!rx_resync) {
0312 if (WARN_ON(wsm_seq != priv->wsm_rx_seq))
0313 goto err;
0314 }
0315 priv->wsm_rx_seq = (wsm_seq + 1) & 7;
0316 rx_resync = 0;
0317
0318 if (wsm_id & 0x0400) {
0319 int rc = wsm_release_tx_buffer(priv, 1);
0320 if (WARN_ON(rc < 0))
0321 return rc;
0322 else if (rc > 0)
0323 *tx = 1;
0324 }
0325
0326
0327 if (WARN_ON(wsm_handle_rx(priv, wsm_id, wsm, &skb_rx)))
0328 goto err;
0329
0330 dev_kfree_skb(skb_rx);
0331
0332 return 0;
0333
0334 err:
0335 dev_kfree_skb(skb_rx);
0336 return -1;
0337 }
0338
0339 static int cw1200_bh_tx_helper(struct cw1200_common *priv,
0340 int *pending_tx,
0341 int *tx_burst)
0342 {
0343 size_t tx_len;
0344 u8 *data;
0345 int ret;
0346 struct wsm_hdr *wsm;
0347
0348 if (priv->device_can_sleep) {
0349 ret = cw1200_device_wakeup(priv);
0350 if (WARN_ON(ret < 0)) {
0351 *pending_tx = 1;
0352 return 0;
0353 } else if (ret) {
0354 priv->device_can_sleep = false;
0355 } else {
0356 *pending_tx = 1;
0357 return 0;
0358 }
0359 }
0360
0361 wsm_alloc_tx_buffer(priv);
0362 ret = wsm_get_tx(priv, &data, &tx_len, tx_burst);
0363 if (ret <= 0) {
0364 wsm_release_tx_buffer(priv, 1);
0365 if (WARN_ON(ret < 0))
0366 return ret;
0367 return 0;
0368 }
0369
0370 wsm = (struct wsm_hdr *)data;
0371 BUG_ON(tx_len < sizeof(*wsm));
0372 BUG_ON(__le16_to_cpu(wsm->len) != tx_len);
0373
0374 atomic_inc(&priv->bh_tx);
0375
0376 tx_len = priv->hwbus_ops->align_size(
0377 priv->hwbus_priv, tx_len);
0378
0379
0380 if (WARN_ON_ONCE(tx_len > EFFECTIVE_BUF_SIZE))
0381 pr_debug("Write aligned len: %zu\n", tx_len);
0382
0383 wsm->id &= __cpu_to_le16(0xffff ^ WSM_TX_SEQ(WSM_TX_SEQ_MAX));
0384 wsm->id |= __cpu_to_le16(WSM_TX_SEQ(priv->wsm_tx_seq));
0385
0386 if (WARN_ON(cw1200_data_write(priv, data, tx_len))) {
0387 pr_err("tx blew up, len %zu\n", tx_len);
0388 wsm_release_tx_buffer(priv, 1);
0389 return -1;
0390 }
0391
0392 if (priv->wsm_enable_wsm_dumps)
0393 print_hex_dump_bytes("--> ",
0394 DUMP_PREFIX_NONE,
0395 data,
0396 __le16_to_cpu(wsm->len));
0397
0398 wsm_txed(priv, data);
0399 priv->wsm_tx_seq = (priv->wsm_tx_seq + 1) & WSM_TX_SEQ_MAX;
0400
0401 if (*tx_burst > 1) {
0402 cw1200_debug_tx_burst(priv);
0403 return 1;
0404 }
0405
0406 return 0;
0407 }
0408
0409 static int cw1200_bh(void *arg)
0410 {
0411 struct cw1200_common *priv = arg;
0412 int rx, tx, term, suspend;
0413 u16 ctrl_reg = 0;
0414 int tx_allowed;
0415 int pending_tx = 0;
0416 int tx_burst;
0417 long status;
0418 u32 dummy;
0419 int ret;
0420
0421 for (;;) {
0422 if (!priv->hw_bufs_used &&
0423 priv->powersave_enabled &&
0424 !priv->device_can_sleep &&
0425 !atomic_read(&priv->recent_scan)) {
0426 status = 1 * HZ;
0427 pr_debug("[BH] Device wakedown. No data.\n");
0428 cw1200_reg_write_16(priv, ST90TDS_CONTROL_REG_ID, 0);
0429 priv->device_can_sleep = true;
0430 } else if (priv->hw_bufs_used) {
0431
0432 status = 1 * HZ;
0433 } else {
0434 status = MAX_SCHEDULE_TIMEOUT;
0435 }
0436
0437
0438 if ((priv->hw_type != -1) &&
0439 (atomic_read(&priv->bh_rx) == 0) &&
0440 (atomic_read(&priv->bh_tx) == 0))
0441 cw1200_reg_read(priv, ST90TDS_CONFIG_REG_ID,
0442 &dummy, sizeof(dummy));
0443
0444 pr_debug("[BH] waiting ...\n");
0445 status = wait_event_interruptible_timeout(priv->bh_wq, ({
0446 rx = atomic_xchg(&priv->bh_rx, 0);
0447 tx = atomic_xchg(&priv->bh_tx, 0);
0448 term = atomic_xchg(&priv->bh_term, 0);
0449 suspend = pending_tx ?
0450 0 : atomic_read(&priv->bh_suspend);
0451 (rx || tx || term || suspend || priv->bh_error);
0452 }), status);
0453
0454 pr_debug("[BH] - rx: %d, tx: %d, term: %d, bh_err: %d, suspend: %d, status: %ld\n",
0455 rx, tx, term, suspend, priv->bh_error, status);
0456
0457
0458 if ((status < 0 && status != -ERESTARTSYS) ||
0459 term || priv->bh_error) {
0460 break;
0461 }
0462 if (!status) {
0463 unsigned long timestamp = jiffies;
0464 long timeout;
0465 int pending = 0;
0466 int i;
0467
0468
0469 if (priv->hw_bufs_used && (!rx || !tx)) {
0470 wiphy_warn(priv->hw->wiphy,
0471 "Missed interrupt? (%d frames outstanding)\n",
0472 priv->hw_bufs_used);
0473 rx = 1;
0474
0475
0476 for (i = 0; i < 4; ++i)
0477 pending += cw1200_queue_get_xmit_timestamp(
0478 &priv->tx_queue[i],
0479 ×tamp,
0480 priv->pending_frame_id);
0481
0482
0483
0484
0485
0486 timeout = timestamp +
0487 WSM_CMD_LAST_CHANCE_TIMEOUT +
0488 1 * HZ -
0489 jiffies;
0490
0491
0492 if (pending && timeout < 0) {
0493 wiphy_warn(priv->hw->wiphy,
0494 "Timeout waiting for TX confirm (%d/%d pending, %ld vs %lu).\n",
0495 priv->hw_bufs_used, pending,
0496 timestamp, jiffies);
0497 break;
0498 }
0499 } else if (!priv->device_can_sleep &&
0500 !atomic_read(&priv->recent_scan)) {
0501 pr_debug("[BH] Device wakedown. Timeout.\n");
0502 cw1200_reg_write_16(priv,
0503 ST90TDS_CONTROL_REG_ID, 0);
0504 priv->device_can_sleep = true;
0505 }
0506 goto done;
0507 } else if (suspend) {
0508 pr_debug("[BH] Device suspend.\n");
0509 if (priv->powersave_enabled) {
0510 pr_debug("[BH] Device wakedown. Suspend.\n");
0511 cw1200_reg_write_16(priv,
0512 ST90TDS_CONTROL_REG_ID, 0);
0513 priv->device_can_sleep = true;
0514 }
0515
0516 atomic_set(&priv->bh_suspend, CW1200_BH_SUSPENDED);
0517 wake_up(&priv->bh_evt_wq);
0518 status = wait_event_interruptible(priv->bh_wq,
0519 CW1200_BH_RESUME == atomic_read(&priv->bh_suspend));
0520 if (status < 0) {
0521 wiphy_err(priv->hw->wiphy,
0522 "Failed to wait for resume: %ld.\n",
0523 status);
0524 break;
0525 }
0526 pr_debug("[BH] Device resume.\n");
0527 atomic_set(&priv->bh_suspend, CW1200_BH_RESUMED);
0528 wake_up(&priv->bh_evt_wq);
0529 atomic_inc(&priv->bh_rx);
0530 goto done;
0531 }
0532
0533 rx:
0534 tx += pending_tx;
0535 pending_tx = 0;
0536
0537 if (cw1200_bh_read_ctrl_reg(priv, &ctrl_reg))
0538 break;
0539
0540
0541 if (ctrl_reg & ST90TDS_CONT_NEXT_LEN_MASK) {
0542 ret = cw1200_bh_rx_helper(priv, &ctrl_reg, &tx);
0543 if (ret < 0)
0544 break;
0545
0546 if (ctrl_reg & ST90TDS_CONT_NEXT_LEN_MASK) {
0547 ret = cw1200_bh_rx_helper(priv, &ctrl_reg, &tx);
0548 if (ret < 0)
0549 break;
0550 }
0551 }
0552
0553 tx:
0554 if (tx) {
0555 tx = 0;
0556
0557 BUG_ON(priv->hw_bufs_used > priv->wsm_caps.input_buffers);
0558 tx_burst = priv->wsm_caps.input_buffers - priv->hw_bufs_used;
0559 tx_allowed = tx_burst > 0;
0560
0561 if (!tx_allowed) {
0562
0563
0564
0565 pending_tx = tx;
0566 goto done_rx;
0567 }
0568 ret = cw1200_bh_tx_helper(priv, &pending_tx, &tx_burst);
0569 if (ret < 0)
0570 break;
0571 if (ret > 0)
0572 tx = ret;
0573
0574
0575 if (cw1200_bh_read_ctrl_reg(priv, &ctrl_reg))
0576 break;
0577 }
0578
0579 done_rx:
0580 if (priv->bh_error)
0581 break;
0582 if (ctrl_reg & ST90TDS_CONT_NEXT_LEN_MASK)
0583 goto rx;
0584 if (tx)
0585 goto tx;
0586
0587 done:
0588
0589 priv->hwbus_ops->lock(priv->hwbus_priv);
0590 __cw1200_irq_enable(priv, 1);
0591 priv->hwbus_ops->unlock(priv->hwbus_priv);
0592 }
0593
0594
0595 priv->hwbus_ops->lock(priv->hwbus_priv);
0596 __cw1200_irq_enable(priv, 0);
0597 priv->hwbus_ops->unlock(priv->hwbus_priv);
0598
0599 if (!term) {
0600 pr_err("[BH] Fatal error, exiting.\n");
0601 priv->bh_error = 1;
0602
0603 }
0604 return 0;
0605 }