Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Device handling thread implementation for mac80211 ST-Ericsson CW1200 drivers
0004  *
0005  * Copyright (c) 2010, ST-Ericsson
0006  * Author: Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>
0007  *
0008  * Based on:
0009  * ST-Ericsson UMAC CW1200 driver, which is
0010  * Copyright (c) 2010, ST-Ericsson
0011  * Author: Ajitpal Singh <ajitpal.singh@stericsson.com>
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 /* an SPI message cannot be bigger than (2"12-1)*2 bytes
0031  * "*2" to cvt to bytes
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 /* Suspend state privates */
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     /* Realtime workqueue */
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     /* Disable Interrupts! */
0099     /* NOTE:  hwbus_ops->lock already held */
0100     __cw1200_irq_enable(priv, 0);
0101 
0102     if (/* WARN_ON */(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     /* First, set the dpll register */
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     /* To force the device to be always-on, the host sets WLAN_UP to 1 */
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     /* If the device returns WLAN_RDY as 1, the device is active and will
0213      * remain active.
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 /* Must be called from BH thraed. */
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; /* No more work */
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     /* Add SIZE of PIGGYBACK reg (CONTROL Reg)
0259      * to the NEXT Message length + 2 Bytes for SKB
0260      */
0261     read_len = read_len + 2;
0262 
0263     alloc_len = priv->hwbus_ops->align_size(
0264         priv->hwbus_priv, read_len);
0265 
0266     /* Check if not exceeding CW1200 capabilities */
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     /* Piggyback */
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     /* cw1200_wsm_rx takes care on SKB livetime */
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)) { /* Error in wakeup */
0351             *pending_tx = 1;
0352             return 0;
0353         } else if (ret) { /* Woke up */
0354             priv->device_can_sleep = false;
0355         } else { /* Did not awake */
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; /* Error */
0367         return 0; /* No work */
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     /* Check if not exceeding CW1200 capabilities */
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; /* Error */
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; /* Work remains */
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             /* Interrupt loss detection */
0432             status = 1 * HZ;
0433         } else {
0434             status = MAX_SCHEDULE_TIMEOUT;
0435         }
0436 
0437         /* Dummy Read for SDIO retry mechanism*/
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         /* Did an error occur? */
0458         if ((status < 0 && status != -ERESTARTSYS) ||
0459             term || priv->bh_error) {
0460             break;
0461         }
0462         if (!status) {  /* wait_event timed out */
0463             unsigned long timestamp = jiffies;
0464             long timeout;
0465             int pending = 0;
0466             int i;
0467 
0468             /* Check to see if we have any outstanding frames */
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                 /* Get a timestamp of "oldest" frame */
0476                 for (i = 0; i < 4; ++i)
0477                     pending += cw1200_queue_get_xmit_timestamp(
0478                         &priv->tx_queue[i],
0479                         &timestamp,
0480                         priv->pending_frame_id);
0481 
0482                 /* Check if frame transmission is timed out.
0483                  * Add an extra second with respect to possible
0484                  * interrupt loss.
0485                  */
0486                 timeout = timestamp +
0487                     WSM_CMD_LAST_CHANCE_TIMEOUT +
0488                     1 * HZ  -
0489                     jiffies;
0490 
0491                 /* And terminate BH thread if the frame is "stuck" */
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         /* Don't bother trying to rx unless we have data to read */
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             /* Double up here if there's more data.. */
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                 /* Buffers full.  Ensure we process tx
0563                  * after we handle rx..
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) /* More to transmit */
0572                 tx = ret;
0573 
0574             /* Re-read ctrl reg */
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         /* Re-enable device interrupts */
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     /* Explicitly disable device interrupts */
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         /* TODO: schedule_work(recovery) */
0603     }
0604     return 0;
0605 }