mwl8k: mwl8k_txq_xmit() rework
authorLennert Buytenhek <buytenh@wantstofly.org>
Fri, 17 Jul 2009 03:21:04 +0000 (05:21 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 20 Aug 2009 15:38:07 +0000 (11:38 -0400)
Various mwl8k_txq_xmit changes:
- Extract the QoS field before adding the DMA header.
- Only write to tx->status once, and only after all the other
  descriptor fields have been set.
- Do all tx state manipulation under the tx spinlock.
- Remove the priv->inconfig check, as all transmit queues will
  be frozen during config cycles, so we won't ever be asked to
  transmit if a config cycle is running.
- Remove some more dead code.

Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/mwl8k.c

index 65eefe835024a5d06a7b77e33a4df936ac4a8bf3..88ba52e13af2441e5e14625cf4695300d04c9ec6 100644 (file)
@@ -1257,46 +1257,60 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
 {
        struct mwl8k_priv *priv = hw->priv;
        struct ieee80211_tx_info *tx_info;
+       struct mwl8k_vif *mwl8k_vif;
        struct ieee80211_hdr *wh;
        struct mwl8k_tx_queue *txq;
        struct mwl8k_tx_desc *tx;
-       struct mwl8k_dma_data *tr;
-       struct mwl8k_vif *mwl8k_vif;
        dma_addr_t dma;
-       u16 qos = 0;
-       bool qosframe = false, ampduframe = false;
-       bool mcframe = false, eapolframe = false;
-       bool amsduframe = false;
-       __le16 fc;
+       u32 txstatus;
+       u8 txdatarate;
+       u16 qos;
 
-       txq = priv->txq + index;
-       tx = txq->tx_desc_area + txq->tx_tail;
-
-       BUG_ON(txq->tx_skb[txq->tx_tail] != NULL);
+       wh = (struct ieee80211_hdr *)skb->data;
+       if (ieee80211_is_data_qos(wh->frame_control))
+               qos = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(wh)));
+       else
+               qos = 0;
 
-       /*
-        * Append HW DMA header to start of packet.
-        */
        mwl8k_add_dma_header(skb);
+       wh = &((struct mwl8k_dma_data *)skb->data)->wh;
 
        tx_info = IEEE80211_SKB_CB(skb);
        mwl8k_vif = MWL8K_VIF(tx_info->control.vif);
-       tr = (struct mwl8k_dma_data *)skb->data;
-       wh = &tr->wh;
-       fc = wh->frame_control;
-       qosframe = ieee80211_is_data_qos(fc);
-       mcframe = is_multicast_ether_addr(wh->addr1);
-       ampduframe = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
 
        if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
                u16 seqno = mwl8k_vif->seqno;
+
                wh->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
                wh->seq_ctrl |= cpu_to_le16(seqno << 4);
                mwl8k_vif->seqno = seqno++ % 4096;
        }
 
-       if (qosframe)
-               qos = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(wh)));
+       /* Setup firmware control bit fields for each frame type.  */
+       txstatus = 0;
+       txdatarate = 0;
+       if (ieee80211_is_mgmt(wh->frame_control) ||
+           ieee80211_is_ctl(wh->frame_control)) {
+               txdatarate = 0;
+               qos = mwl8k_qos_setbit_eosp(qos);
+               /* Set Queue size to unspecified */
+               qos = mwl8k_qos_setbit_qlen(qos, 0xff);
+       } else if (ieee80211_is_data(wh->frame_control)) {
+               txdatarate = 1;
+               if (is_multicast_ether_addr(wh->addr1))
+                       txstatus |= MWL8K_TXD_STATUS_MULTICAST_TX;
+
+               /* Send pkt in an aggregate if AMPDU frame.  */
+               if (tx_info->flags & IEEE80211_TX_CTL_AMPDU)
+                       qos = mwl8k_qos_setbit_ack(qos,
+                               MWL8K_TXD_ACK_POLICY_BLOCKACK);
+               else
+                       qos = mwl8k_qos_setbit_ack(qos,
+                               MWL8K_TXD_ACK_POLICY_NORMAL);
+
+               if (qos & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
+                       qos = mwl8k_qos_setbit_amsdu(qos);
+       }
 
        dma = pci_map_single(priv->pdev, skb->data,
                                skb->len, PCI_DMA_TODEVICE);
@@ -1304,95 +1318,40 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
        if (pci_dma_mapping_error(priv->pdev, dma)) {
                printk(KERN_DEBUG "%s: failed to dma map skb, "
                        "dropping TX frame.\n", priv->name);
-
-               if (skb != NULL)
-                       dev_kfree_skb(skb);
+               dev_kfree_skb(skb);
                return NETDEV_TX_OK;
        }
 
-       /* Set desc header, cpu bit order.  */
-       tx->status = 0;
-       tx->data_rate = 0;
-       tx->tx_priority = index;
-       tx->qos_control = 0;
-       tx->rate_info = 0;
-       tx->peer_id = mwl8k_vif->peer_id;
-
-       amsduframe = !!(qos & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT);
-
-       /* Setup firmware control bit fields for each frame type.  */
-       if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) {
-               tx->data_rate = 0;
-               qos = mwl8k_qos_setbit_eosp(qos);
-               /* Set Queue size to unspecified */
-               qos = mwl8k_qos_setbit_qlen(qos, 0xff);
-       } else if (ieee80211_is_data(fc)) {
-               tx->data_rate = 1;
-               if (mcframe)
-                       tx->status |= MWL8K_TXD_STATUS_MULTICAST_TX;
+       spin_lock_bh(&priv->tx_lock);
 
-               /*
-                * Tell firmware to not send EAPOL pkts in an
-                * aggregate.  Verify against mac80211 tx path.  If
-                * stack turns off AMPDU for an EAPOL frame this
-                * check will be removed.
-                */
-               if (eapolframe) {
-                       qos = mwl8k_qos_setbit_ack(qos,
-                               MWL8K_TXD_ACK_POLICY_NORMAL);
-               } else {
-                       /* Send pkt in an aggregate if AMPDU frame.  */
-                       if (ampduframe)
-                               qos = mwl8k_qos_setbit_ack(qos,
-                                       MWL8K_TXD_ACK_POLICY_BLOCKACK);
-                       else
-                               qos = mwl8k_qos_setbit_ack(qos,
-                                       MWL8K_TXD_ACK_POLICY_NORMAL);
+       txq = priv->txq + index;
 
-                       if (amsduframe)
-                               qos = mwl8k_qos_setbit_amsdu(qos);
-               }
-       }
+       BUG_ON(txq->tx_skb[txq->tx_tail] != NULL);
+       txq->tx_skb[txq->tx_tail] = skb;
 
-       /* Convert to little endian */
+       tx = txq->tx_desc_area + txq->tx_tail;
+       tx->data_rate = txdatarate;
+       tx->tx_priority = index;
        tx->qos_control = cpu_to_le16(qos);
-       tx->status = cpu_to_le32(tx->status);
        tx->pkt_phys_addr = cpu_to_le32(dma);
        tx->pkt_len = cpu_to_le16(skb->len);
-
-       txq->tx_skb[txq->tx_tail] = skb;
-
-       spin_lock_bh(&priv->tx_lock);
-
-       tx->status = cpu_to_le32(MWL8K_TXD_STATUS_OK |
-                                       MWL8K_TXD_STATUS_FW_OWNED);
+       tx->rate_info = 0;
+       tx->peer_id = mwl8k_vif->peer_id;
        wmb();
+       tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus);
+
+       txq->tx_stats.count++;
        txq->tx_stats.len++;
        priv->pending_tx_pkts++;
-       txq->tx_stats.count++;
-       txq->tx_tail++;
 
+       txq->tx_tail++;
        if (txq->tx_tail == MWL8K_TX_DESCS)
                txq->tx_tail = 0;
+
        if (txq->tx_head == txq->tx_tail)
                ieee80211_stop_queue(hw, index);
 
-       if (priv->inconfig) {
-               /*
-                * Silently queue packet when we are in the middle of
-                * a config cycle.  Notify firmware only if we are
-                * waiting for TXQs to empty.  If a packet is sent
-                * before .config() is complete, perhaps it is better
-                * to drop the packet, as the channel is being changed
-                * and the packet will end up on the wrong channel.
-                */
-               printk(KERN_ERR "%s(): WARNING TX activity while "
-                       "in config\n", __func__);
-
-               if (priv->tx_wait != NULL)
-                       mwl8k_tx_start(priv);
-       } else
-               mwl8k_tx_start(priv);
+       mwl8k_tx_start(priv);
 
        spin_unlock_bh(&priv->tx_lock);