/* * Add buffer into wmm tx queue and queue work to transmit it. */ int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb) { struct netdev_queue *txq; int index = mwifiex_1d_to_wmm_queue[skb->priority]; if (atomic_inc_return(&priv->wmm_tx_pending[index]) >= MAX_TX_PENDING) { txq = netdev_get_tx_queue(priv->netdev, index); if (!netif_tx_queue_stopped(txq)) { netif_tx_stop_queue(txq); mwifiex_dbg(priv->adapter, DATA, "stop queue: %d\n", index); } } if (mwifiex_bypass_tx_queue(priv, skb)) { atomic_inc(&priv->adapter->tx_pending); atomic_inc(&priv->adapter->bypass_tx_pending); mwifiex_wmm_add_buf_bypass_txqueue(priv, skb); } else { atomic_inc(&priv->adapter->tx_pending); mwifiex_wmm_add_buf_txqueue(priv, skb); } mwifiex_queue_main_work(priv->adapter); return 0; }
static int mwifiex_process_rx(struct mwifiex_adapter *adapter) { unsigned long flags; struct sk_buff *skb; struct mwifiex_rxinfo *rx_info; spin_lock_irqsave(&adapter->rx_proc_lock, flags); if (adapter->rx_processing || adapter->rx_locked) { spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); goto exit_rx_proc; } else { adapter->rx_processing = true; spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); } /* Check for Rx data */ while ((skb = skb_dequeue(&adapter->rx_data_q))) { atomic_dec(&adapter->rx_pending); if ((adapter->delay_main_work || adapter->iface_type == MWIFIEX_USB) && (atomic_read(&adapter->rx_pending) < LOW_RX_PENDING)) { if (adapter->if_ops.submit_rem_rx_urbs) adapter->if_ops.submit_rem_rx_urbs(adapter); adapter->delay_main_work = false; mwifiex_queue_main_work(adapter); } rx_info = MWIFIEX_SKB_RXCB(skb); if (rx_info->buf_type == MWIFIEX_TYPE_AGGR_DATA) { if (adapter->if_ops.deaggr_pkt) adapter->if_ops.deaggr_pkt(adapter, skb); dev_kfree_skb_any(skb); } else { mwifiex_handle_rx_packet(adapter, skb); } } spin_lock_irqsave(&adapter->rx_proc_lock, flags); adapter->rx_processing = false; spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); exit_rx_proc: return 0; }
static void mwifiex_usb_tx_complete(struct urb *urb) { struct urb_context *context = (struct urb_context *)(urb->context); struct mwifiex_adapter *adapter = context->adapter; struct usb_card_rec *card = adapter->card; struct usb_tx_data_port *port; int i; mwifiex_dbg(adapter, INFO, "%s: status: %d\n", __func__, urb->status); if (context->ep == card->tx_cmd_ep) { mwifiex_dbg(adapter, CMD, "%s: CMD\n", __func__); atomic_dec(&card->tx_cmd_urb_pending); adapter->cmd_sent = false; } else { mwifiex_dbg(adapter, DATA, "%s: DATA\n", __func__); mwifiex_write_data_complete(adapter, context->skb, 0, urb->status ? -1 : 0); for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) { port = &card->port[i]; if (context->ep == port->tx_data_ep) { atomic_dec(&port->tx_data_urb_pending); port->block_status = false; break; } } adapter->data_sent = false; } if (card->mc_resync_flag) mwifiex_multi_chan_resync(adapter); mwifiex_queue_main_work(adapter); return; }
static void mwifiex_usb_tx_complete(struct urb *urb) { struct urb_context *context = (struct urb_context *)(urb->context); struct mwifiex_adapter *adapter = context->adapter; struct usb_card_rec *card = adapter->card; dev_dbg(adapter->dev, "%s: status: %d\n", __func__, urb->status); if (context->ep == card->tx_cmd_ep) { dev_dbg(adapter->dev, "%s: CMD\n", __func__); atomic_dec(&card->tx_cmd_urb_pending); adapter->cmd_sent = false; } else { dev_dbg(adapter->dev, "%s: DATA\n", __func__); atomic_dec(&card->tx_data_urb_pending); mwifiex_write_data_complete(adapter, context->skb, 0, urb->status ? -1 : 0); } mwifiex_queue_main_work(adapter); return; }
static void mwifiex_usb_rx_complete(struct urb *urb) { struct urb_context *context = (struct urb_context *)urb->context; struct mwifiex_adapter *adapter = context->adapter; struct sk_buff *skb = context->skb; struct usb_card_rec *card; int recv_length = urb->actual_length; int size, status; if (!adapter || !adapter->card) { pr_err("mwifiex adapter or card structure is not valid\n"); return; } card = (struct usb_card_rec *)adapter->card; if (card->rx_cmd_ep == context->ep) atomic_dec(&card->rx_cmd_urb_pending); else atomic_dec(&card->rx_data_urb_pending); if (recv_length) { if (urb->status || (adapter->surprise_removed)) { dev_err(adapter->dev, "URB status is failed: %d\n", urb->status); /* Do not free skb in case of command ep */ if (card->rx_cmd_ep != context->ep) dev_kfree_skb_any(skb); goto setup_for_next; } if (skb->len > recv_length) skb_trim(skb, recv_length); else skb_put(skb, recv_length - skb->len); status = mwifiex_usb_recv(adapter, skb, context->ep); dev_dbg(adapter->dev, "info: recv_length=%d, status=%d\n", recv_length, status); if (status == -EINPROGRESS) { mwifiex_queue_main_work(adapter); /* urb for data_ep is re-submitted now; * urb for cmd_ep will be re-submitted in callback * mwifiex_usb_recv_complete */ if (card->rx_cmd_ep == context->ep) return; } else { if (status == -1) dev_err(adapter->dev, "received data processing failed!\n"); /* Do not free skb in case of command ep */ if (card->rx_cmd_ep != context->ep) dev_kfree_skb_any(skb); } } else if (urb->status) { if (!adapter->is_suspended) { dev_warn(adapter->dev, "Card is removed: %d\n", urb->status); adapter->surprise_removed = true; } dev_kfree_skb_any(skb); return; } else { /* Do not free skb in case of command ep */ if (card->rx_cmd_ep != context->ep) dev_kfree_skb_any(skb); /* fall through setup_for_next */ } setup_for_next: if (card->rx_cmd_ep == context->ep) size = MWIFIEX_RX_CMD_BUF_SIZE; else size = MWIFIEX_RX_DATA_BUF_SIZE; if (card->rx_cmd_ep == context->ep) { mwifiex_usb_submit_rx_urb(context, size); } else { context->skb = NULL; if (atomic_read(&adapter->rx_pending) <= HIGH_RX_PENDING) mwifiex_usb_submit_rx_urb(context, size); } return; }