]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/net/wireless/iwlwifi/iwl-tx.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[mv-sheeva.git] / drivers / net / wireless / iwlwifi / iwl-tx.c
index 1f117a49c569422ae31a0d6f69a0fa2ea11a8f9b..a82cca0a30c7b6b82b9ecc61ab4b205a683d3cdf 100644 (file)
@@ -728,7 +728,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
        /* drop all data frame if we are not associated */
        if (ieee80211_is_data(fc) &&
-           (priv->iw_mode != NL80211_IFTYPE_MONITOR ||
+           (!iwl_is_monitor_mode(priv) ||
            !(info->flags & IEEE80211_TX_CTL_INJECTED)) && /* packet injection */
            (!iwl_is_associated(priv) ||
             ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id) ||
@@ -799,6 +799,22 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        /* Copy MAC header from skb into command buffer */
        memcpy(tx_cmd->hdr, hdr, hdr_len);
 
+
+       /* Total # bytes to be transmitted */
+       len = (u16)skb->len;
+       tx_cmd->len = cpu_to_le16(len);
+
+       if (info->control.hw_key)
+               iwl_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id);
+
+       /* TODO need this for burst mode later on */
+       iwl_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id);
+
+       /* set is_hcca to 0; it probably will never be implemented */
+       iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, sta_id, 0);
+
+       iwl_update_tx_stats(priv, le16_to_cpu(fc), len);
+
        /*
         * Use the first empty entry in this queue's command buffer array
         * to contain the Tx command and MAC header concatenated together
@@ -819,21 +835,30 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        else
                len_org = 0;
 
+       /* Tell NIC about any 2-byte padding after MAC header */
+       if (len_org)
+               tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
+
        /* Physical address of this Tx command's header (not MAC header!),
         * within command buffer array. */
        txcmd_phys = pci_map_single(priv->pci_dev,
-                                   out_cmd, sizeof(struct iwl_cmd),
+                                   &out_cmd->hdr, len,
                                    PCI_DMA_BIDIRECTIONAL);
        pci_unmap_addr_set(&out_cmd->meta, mapping, txcmd_phys);
-       pci_unmap_len_set(&out_cmd->meta, len, sizeof(struct iwl_cmd));
+       pci_unmap_len_set(&out_cmd->meta, len, len);
        /* Add buffer containing Tx command and MAC(!) header to TFD's
         * first entry */
-       txcmd_phys += offsetof(struct iwl_cmd, hdr);
        priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
                                                   txcmd_phys, len, 1, 0);
 
-       if (info->control.hw_key)
-               iwl_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id);
+       if (!ieee80211_has_morefrags(hdr->frame_control)) {
+               txq->need_update = 1;
+               if (qc)
+                       priv->stations[sta_id].tid[tid].seq_number = seq_number;
+       } else {
+               wait_write_ptr = 1;
+               txq->need_update = 0;
+       }
 
        /* Set up TFD's 2nd entry to point directly to remainder of skb,
         * if any (802.11 null frames have no payload). */
@@ -846,41 +871,29 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
                                                           0, 0);
        }
 
-       /* Tell NIC about any 2-byte padding after MAC header */
-       if (len_org)
-               tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
-
-       /* Total # bytes to be transmitted */
-       len = (u16)skb->len;
-       tx_cmd->len = cpu_to_le16(len);
-       /* TODO need this for burst mode later on */
-       iwl_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id);
-
-       /* set is_hcca to 0; it probably will never be implemented */
-       iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, sta_id, 0);
-
-       iwl_update_tx_stats(priv, le16_to_cpu(fc), len);
-
        scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
-               offsetof(struct iwl_tx_cmd, scratch);
+                               offsetof(struct iwl_tx_cmd, scratch);
+
+       len = sizeof(struct iwl_tx_cmd) +
+               sizeof(struct iwl_cmd_header) + hdr_len;
+       /* take back ownership of DMA buffer to enable update */
+       pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys,
+                                   len, PCI_DMA_BIDIRECTIONAL);
        tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
        tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
 
-       if (!ieee80211_has_morefrags(hdr->frame_control)) {
-               txq->need_update = 1;
-               if (qc)
-                       priv->stations[sta_id].tid[tid].seq_number = seq_number;
-       } else {
-               wait_write_ptr = 1;
-               txq->need_update = 0;
-       }
-
+       IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n",
+                    le16_to_cpu(out_cmd->hdr.sequence));
+       IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx_cmd->tx_flags));
        iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd));
-
        iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len);
 
        /* Set up entry for this TFD in Tx byte-count array */
-       priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, len);
+       priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq,
+                                                    le16_to_cpu(tx_cmd->len));
+
+       pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys,
+                                      len, PCI_DMA_BIDIRECTIONAL);
 
        /* Tell device the write index *just past* this latest filled TFD */
        q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
@@ -968,18 +981,9 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
                        INDEX_TO_SEQ(q->write_ptr));
        if (out_cmd->meta.flags & CMD_SIZE_HUGE)
                out_cmd->hdr.sequence |= SEQ_HUGE_FRAME;
-       len = (idx == TFD_CMD_SLOTS) ?
-                       IWL_MAX_SCAN_SIZE : sizeof(struct iwl_cmd);
+       len = sizeof(struct iwl_cmd) - sizeof(struct iwl_cmd_meta);
+       len += (idx == TFD_CMD_SLOTS) ?  IWL_MAX_SCAN_SIZE : 0;
 
-       phys_addr = pci_map_single(priv->pci_dev, out_cmd,
-                                  len, PCI_DMA_BIDIRECTIONAL);
-       pci_unmap_addr_set(&out_cmd->meta, mapping, phys_addr);
-       pci_unmap_len_set(&out_cmd->meta, len, len);
-       phys_addr += offsetof(struct iwl_cmd, hdr);
-
-       priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
-                                                  phys_addr, fix_size, 1,
-                                                  U32_PAD(cmd->len));
 
 #ifdef CONFIG_IWLWIFI_DEBUG
        switch (out_cmd->hdr.cmd) {
@@ -1007,6 +1011,15 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
                /* Set up entry in queue's byte count circular buffer */
                priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, 0);
 
+       phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr,
+                                  fix_size, PCI_DMA_BIDIRECTIONAL);
+       pci_unmap_addr_set(&out_cmd->meta, mapping, phys_addr);
+       pci_unmap_len_set(&out_cmd->meta, len, fix_size);
+
+       priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
+                                                  phys_addr, fix_size, 1,
+                                                  U32_PAD(cmd->len));
+
        /* Increment and update queue's write index */
        q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
        ret = iwl_txq_update_write_ptr(priv, txq);
@@ -1170,8 +1183,10 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn)
                        __func__, ra, tid);
 
        sta_id = iwl_find_station(priv, ra);
-       if (sta_id == IWL_INVALID_STATION)
+       if (sta_id == IWL_INVALID_STATION) {
+               IWL_ERR(priv, "Start AGG on invalid station\n");
                return -ENXIO;
+       }
 
        if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) {
                IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n");
@@ -1179,8 +1194,10 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn)
        }
 
        txq_id = iwl_txq_ctx_activate_free(priv);
-       if (txq_id == -1)
+       if (txq_id == -1) {
+               IWL_ERR(priv, "No free aggregation queue available\n");
                return -ENXIO;
+       }
 
        spin_lock_irqsave(&priv->sta_lock, flags);
        tid_data = &priv->stations[sta_id].tid[tid];
@@ -1194,7 +1211,7 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn)
                return ret;
 
        if (tid_data->tfds_in_queue == 0) {
-               IWL_ERR(priv, "HW queue is empty\n");
+               IWL_DEBUG_HT(priv, "HW queue is empty\n");
                tid_data->agg.state = IWL_AGG_ON;
                ieee80211_start_tx_ba_cb_irqsafe(priv->hw, ra, tid);
        } else {