Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * NXP Wireless LAN device driver: generic TX/RX data handling
0004  *
0005  * Copyright 2011-2020 NXP
0006  */
0007 
0008 #include "decl.h"
0009 #include "ioctl.h"
0010 #include "util.h"
0011 #include "fw.h"
0012 #include "main.h"
0013 #include "wmm.h"
0014 
0015 /*
0016  * This function processes the received buffer.
0017  *
0018  * Main responsibility of this function is to parse the RxPD to
0019  * identify the correct interface this packet is headed for and
0020  * forwarding it to the associated handling function, where the
0021  * packet will be further processed and sent to kernel/upper layer
0022  * if required.
0023  */
0024 int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,
0025                  struct sk_buff *skb)
0026 {
0027     struct mwifiex_private *priv =
0028         mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
0029     struct rxpd *local_rx_pd;
0030     struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
0031     int ret;
0032 
0033     local_rx_pd = (struct rxpd *) (skb->data);
0034     /* Get the BSS number from rxpd, get corresponding priv */
0035     priv = mwifiex_get_priv_by_id(adapter, local_rx_pd->bss_num &
0036                       BSS_NUM_MASK, local_rx_pd->bss_type);
0037     if (!priv)
0038         priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
0039 
0040     if (!priv) {
0041         mwifiex_dbg(adapter, ERROR,
0042                 "data: priv not found. Drop RX packet\n");
0043         dev_kfree_skb_any(skb);
0044         return -1;
0045     }
0046 
0047     mwifiex_dbg_dump(adapter, DAT_D, "rx pkt:", skb->data,
0048              min_t(size_t, skb->len, DEBUG_DUMP_DATA_MAX_LEN));
0049 
0050     memset(rx_info, 0, sizeof(*rx_info));
0051     rx_info->bss_num = priv->bss_num;
0052     rx_info->bss_type = priv->bss_type;
0053 
0054     if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
0055         ret = mwifiex_process_uap_rx_packet(priv, skb);
0056     else
0057         ret = mwifiex_process_sta_rx_packet(priv, skb);
0058 
0059     return ret;
0060 }
0061 EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet);
0062 
0063 /*
0064  * This function sends a packet to device.
0065  *
0066  * It processes the packet to add the TxPD, checks condition and
0067  * sends the processed packet to firmware for transmission.
0068  *
0069  * On successful completion, the function calls the completion callback
0070  * and logs the time.
0071  */
0072 int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
0073                struct mwifiex_tx_param *tx_param)
0074 {
0075     int hroom, ret = -1;
0076     struct mwifiex_adapter *adapter = priv->adapter;
0077     u8 *head_ptr;
0078     struct txpd *local_tx_pd = NULL;
0079     struct mwifiex_sta_node *dest_node;
0080     struct ethhdr *hdr = (void *)skb->data;
0081 
0082     hroom = adapter->intf_hdr_len;
0083 
0084     if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) {
0085         dest_node = mwifiex_get_sta_entry(priv, hdr->h_dest);
0086         if (dest_node) {
0087             dest_node->stats.tx_bytes += skb->len;
0088             dest_node->stats.tx_packets++;
0089         }
0090 
0091         head_ptr = mwifiex_process_uap_txpd(priv, skb);
0092     } else {
0093         head_ptr = mwifiex_process_sta_txpd(priv, skb);
0094     }
0095 
0096     if ((adapter->data_sent || adapter->tx_lock_flag) && head_ptr) {
0097         skb_queue_tail(&adapter->tx_data_q, skb);
0098         atomic_inc(&adapter->tx_queued);
0099         return 0;
0100     }
0101 
0102     if (head_ptr) {
0103         if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
0104             local_tx_pd = (struct txpd *)(head_ptr + hroom);
0105         if (adapter->iface_type == MWIFIEX_USB) {
0106             ret = adapter->if_ops.host_to_card(adapter,
0107                                priv->usb_port,
0108                                skb, tx_param);
0109         } else {
0110             ret = adapter->if_ops.host_to_card(adapter,
0111                                MWIFIEX_TYPE_DATA,
0112                                skb, tx_param);
0113         }
0114     }
0115     mwifiex_dbg_dump(adapter, DAT_D, "tx pkt:", skb->data,
0116              min_t(size_t, skb->len, DEBUG_DUMP_DATA_MAX_LEN));
0117 
0118     switch (ret) {
0119     case -ENOSR:
0120         mwifiex_dbg(adapter, DATA, "data: -ENOSR is returned\n");
0121         break;
0122     case -EBUSY:
0123         if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
0124             (adapter->pps_uapsd_mode) && (adapter->tx_lock_flag)) {
0125                 priv->adapter->tx_lock_flag = false;
0126                 if (local_tx_pd)
0127                     local_tx_pd->flags = 0;
0128         }
0129         mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
0130         break;
0131     case -1:
0132         mwifiex_dbg(adapter, ERROR,
0133                 "mwifiex_write_data_async failed: 0x%X\n",
0134                 ret);
0135         adapter->dbg.num_tx_host_to_card_failure++;
0136         mwifiex_write_data_complete(adapter, skb, 0, ret);
0137         break;
0138     case -EINPROGRESS:
0139         break;
0140     case 0:
0141         mwifiex_write_data_complete(adapter, skb, 0, ret);
0142         break;
0143     default:
0144         break;
0145     }
0146 
0147     return ret;
0148 }
0149 
0150 static int mwifiex_host_to_card(struct mwifiex_adapter *adapter,
0151                 struct sk_buff *skb,
0152                 struct mwifiex_tx_param *tx_param)
0153 {
0154     struct txpd *local_tx_pd = NULL;
0155     u8 *head_ptr = skb->data;
0156     int ret = 0;
0157     struct mwifiex_private *priv;
0158     struct mwifiex_txinfo *tx_info;
0159 
0160     tx_info = MWIFIEX_SKB_TXCB(skb);
0161     priv = mwifiex_get_priv_by_id(adapter, tx_info->bss_num,
0162                       tx_info->bss_type);
0163     if (!priv) {
0164         mwifiex_dbg(adapter, ERROR,
0165                 "data: priv not found. Drop TX packet\n");
0166         adapter->dbg.num_tx_host_to_card_failure++;
0167         mwifiex_write_data_complete(adapter, skb, 0, 0);
0168         return ret;
0169     }
0170     if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
0171         local_tx_pd = (struct txpd *)(head_ptr + adapter->intf_hdr_len);
0172 
0173     if (adapter->iface_type == MWIFIEX_USB) {
0174         ret = adapter->if_ops.host_to_card(adapter,
0175                            priv->usb_port,
0176                            skb, tx_param);
0177     } else {
0178         ret = adapter->if_ops.host_to_card(adapter,
0179                            MWIFIEX_TYPE_DATA,
0180                            skb, tx_param);
0181     }
0182     switch (ret) {
0183     case -ENOSR:
0184         mwifiex_dbg(adapter, ERROR, "data: -ENOSR is returned\n");
0185         break;
0186     case -EBUSY:
0187         if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
0188             (adapter->pps_uapsd_mode) &&
0189             (adapter->tx_lock_flag)) {
0190             priv->adapter->tx_lock_flag = false;
0191             if (local_tx_pd)
0192                 local_tx_pd->flags = 0;
0193         }
0194         skb_queue_head(&adapter->tx_data_q, skb);
0195         if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT)
0196             atomic_add(tx_info->aggr_num, &adapter->tx_queued);
0197         else
0198             atomic_inc(&adapter->tx_queued);
0199         mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
0200         break;
0201     case -1:
0202         mwifiex_dbg(adapter, ERROR,
0203                 "mwifiex_write_data_async failed: 0x%X\n", ret);
0204         adapter->dbg.num_tx_host_to_card_failure++;
0205         mwifiex_write_data_complete(adapter, skb, 0, ret);
0206         break;
0207     case -EINPROGRESS:
0208         break;
0209     case 0:
0210         mwifiex_write_data_complete(adapter, skb, 0, ret);
0211         break;
0212     default:
0213         break;
0214     }
0215     return ret;
0216 }
0217 
0218 static int
0219 mwifiex_dequeue_tx_queue(struct mwifiex_adapter *adapter)
0220 {
0221     struct sk_buff *skb, *skb_next;
0222     struct mwifiex_txinfo *tx_info;
0223     struct mwifiex_tx_param tx_param;
0224 
0225     skb = skb_dequeue(&adapter->tx_data_q);
0226     if (!skb)
0227         return -1;
0228 
0229     tx_info = MWIFIEX_SKB_TXCB(skb);
0230     if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT)
0231         atomic_sub(tx_info->aggr_num, &adapter->tx_queued);
0232     else
0233         atomic_dec(&adapter->tx_queued);
0234 
0235     if (!skb_queue_empty(&adapter->tx_data_q))
0236         skb_next = skb_peek(&adapter->tx_data_q);
0237     else
0238         skb_next = NULL;
0239     tx_param.next_pkt_len = ((skb_next) ? skb_next->len : 0);
0240     if (!tx_param.next_pkt_len) {
0241         if (!mwifiex_wmm_lists_empty(adapter))
0242             tx_param.next_pkt_len = 1;
0243     }
0244     return mwifiex_host_to_card(adapter, skb, &tx_param);
0245 }
0246 
0247 void
0248 mwifiex_process_tx_queue(struct mwifiex_adapter *adapter)
0249 {
0250     do {
0251         if (adapter->data_sent || adapter->tx_lock_flag)
0252             break;
0253         if (mwifiex_dequeue_tx_queue(adapter))
0254             break;
0255     } while (!skb_queue_empty(&adapter->tx_data_q));
0256 }
0257 
0258 /*
0259  * Packet send completion callback handler.
0260  *
0261  * It either frees the buffer directly or forwards it to another
0262  * completion callback which checks conditions, updates statistics,
0263  * wakes up stalled traffic queue if required, and then frees the buffer.
0264  */
0265 int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
0266                 struct sk_buff *skb, int aggr, int status)
0267 {
0268     struct mwifiex_private *priv;
0269     struct mwifiex_txinfo *tx_info;
0270     struct netdev_queue *txq;
0271     int index;
0272 
0273     if (!skb)
0274         return 0;
0275 
0276     tx_info = MWIFIEX_SKB_TXCB(skb);
0277     priv = mwifiex_get_priv_by_id(adapter, tx_info->bss_num,
0278                       tx_info->bss_type);
0279     if (!priv)
0280         goto done;
0281 
0282     mwifiex_set_trans_start(priv->netdev);
0283 
0284     if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT)
0285         atomic_dec_return(&adapter->pending_bridged_pkts);
0286 
0287     if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT)
0288         goto done;
0289 
0290     if (!status) {
0291         priv->stats.tx_packets++;
0292         priv->stats.tx_bytes += tx_info->pkt_len;
0293         if (priv->tx_timeout_cnt)
0294             priv->tx_timeout_cnt = 0;
0295     } else {
0296         priv->stats.tx_errors++;
0297     }
0298 
0299     if (aggr)
0300         /* For skb_aggr, do not wake up tx queue */
0301         goto done;
0302 
0303     atomic_dec(&adapter->tx_pending);
0304 
0305     index = mwifiex_1d_to_wmm_queue[skb->priority];
0306     if (atomic_dec_return(&priv->wmm_tx_pending[index]) < LOW_TX_PENDING) {
0307         txq = netdev_get_tx_queue(priv->netdev, index);
0308         if (netif_tx_queue_stopped(txq)) {
0309             netif_tx_wake_queue(txq);
0310             mwifiex_dbg(adapter, DATA, "wake queue: %d\n", index);
0311         }
0312     }
0313 done:
0314     dev_kfree_skb_any(skb);
0315 
0316     return 0;
0317 }
0318 EXPORT_SYMBOL_GPL(mwifiex_write_data_complete);
0319 
0320 void mwifiex_parse_tx_status_event(struct mwifiex_private *priv,
0321                    void *event_body)
0322 {
0323     struct tx_status_event *tx_status = (void *)priv->adapter->event_body;
0324     struct sk_buff *ack_skb;
0325     struct mwifiex_txinfo *tx_info;
0326 
0327     if (!tx_status->tx_token_id)
0328         return;
0329 
0330     spin_lock_bh(&priv->ack_status_lock);
0331     ack_skb = idr_remove(&priv->ack_status_frames, tx_status->tx_token_id);
0332     spin_unlock_bh(&priv->ack_status_lock);
0333 
0334     if (ack_skb) {
0335         tx_info = MWIFIEX_SKB_TXCB(ack_skb);
0336 
0337         if (tx_info->flags & MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS) {
0338             /* consumes ack_skb */
0339             skb_complete_wifi_ack(ack_skb, !tx_status->status);
0340         } else {
0341             /* Remove broadcast address which was added by driver */
0342             memmove(ack_skb->data +
0343                 sizeof(struct ieee80211_hdr_3addr) +
0344                 MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(u16),
0345                 ack_skb->data +
0346                 sizeof(struct ieee80211_hdr_3addr) +
0347                 MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(u16) +
0348                 ETH_ALEN, ack_skb->len -
0349                 (sizeof(struct ieee80211_hdr_3addr) +
0350                 MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(u16) +
0351                 ETH_ALEN));
0352             ack_skb->len = ack_skb->len - ETH_ALEN;
0353             /* Remove driver's proprietary header including 2 bytes
0354              * of packet length and pass actual management frame buffer
0355              * to cfg80211.
0356              */
0357             cfg80211_mgmt_tx_status(&priv->wdev, tx_info->cookie,
0358                         ack_skb->data +
0359                         MWIFIEX_MGMT_FRAME_HEADER_SIZE +
0360                         sizeof(u16), ack_skb->len -
0361                         (MWIFIEX_MGMT_FRAME_HEADER_SIZE
0362                          + sizeof(u16)),
0363                         !tx_status->status, GFP_ATOMIC);
0364             dev_kfree_skb_any(ack_skb);
0365         }
0366     }
0367 }