mac80211: use multi-queue master netdevice
[deliverable/linux.git] / drivers / net / wireless / b43 / dma.c
index 70db0570adc5efe76fdae697a99e7dd81d73d118..b4eadd908beabc46675dd356b0cdc373a8010224 100644 (file)
@@ -328,10 +328,10 @@ static inline
        dma_addr_t dmaaddr;
 
        if (tx) {
-               dmaaddr = dma_map_single(ring->dev->dev->dev,
+               dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
                                         buf, len, DMA_TO_DEVICE);
        } else {
-               dmaaddr = dma_map_single(ring->dev->dev->dev,
+               dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
                                         buf, len, DMA_FROM_DEVICE);
        }
 
@@ -343,9 +343,10 @@ static inline
                          dma_addr_t addr, size_t len, int tx)
 {
        if (tx) {
-               dma_unmap_single(ring->dev->dev->dev, addr, len, DMA_TO_DEVICE);
+               dma_unmap_single(ring->dev->dev->dma_dev,
+                                addr, len, DMA_TO_DEVICE);
        } else {
-               dma_unmap_single(ring->dev->dev->dev,
+               dma_unmap_single(ring->dev->dev->dma_dev,
                                 addr, len, DMA_FROM_DEVICE);
        }
 }
@@ -355,7 +356,7 @@ static inline
                                 dma_addr_t addr, size_t len)
 {
        B43_WARN_ON(ring->tx);
-       dma_sync_single_for_cpu(ring->dev->dev->dev,
+       dma_sync_single_for_cpu(ring->dev->dev->dma_dev,
                                addr, len, DMA_FROM_DEVICE);
 }
 
@@ -364,7 +365,7 @@ static inline
                                    dma_addr_t addr, size_t len)
 {
        B43_WARN_ON(ring->tx);
-       dma_sync_single_for_device(ring->dev->dev->dev,
+       dma_sync_single_for_device(ring->dev->dev->dma_dev,
                                   addr, len, DMA_FROM_DEVICE);
 }
 
@@ -380,7 +381,7 @@ static inline
 
 static int alloc_ringmemory(struct b43_dmaring *ring)
 {
-       struct device *dev = ring->dev->dev->dev;
+       struct device *dma_dev = ring->dev->dev->dma_dev;
        gfp_t flags = GFP_KERNEL;
 
        /* The specs call for 4K buffers for 30- and 32-bit DMA with 4K
@@ -394,7 +395,7 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
         */
        if (ring->type == B43_DMA_64BIT)
                flags |= GFP_DMA;
-       ring->descbase = dma_alloc_coherent(dev, B43_DMA_RINGMEMSIZE,
+       ring->descbase = dma_alloc_coherent(dma_dev, B43_DMA_RINGMEMSIZE,
                                            &(ring->dmabase), flags);
        if (!ring->descbase) {
                b43err(ring->dev->wl, "DMA ringmemory allocation failed\n");
@@ -407,9 +408,9 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
 
 static void free_ringmemory(struct b43_dmaring *ring)
 {
-       struct device *dev = ring->dev->dev->dev;
+       struct device *dma_dev = ring->dev->dev->dma_dev;
 
-       dma_free_coherent(dev, B43_DMA_RINGMEMSIZE,
+       dma_free_coherent(dma_dev, B43_DMA_RINGMEMSIZE,
                          ring->descbase, ring->dmabase);
 }
 
@@ -550,7 +551,6 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring,
                               struct b43_dmadesc_meta *meta, gfp_t gfp_flags)
 {
        struct b43_rxhdr_fw4 *rxhdr;
-       struct b43_hwtxstatus *txstat;
        dma_addr_t dmaaddr;
        struct sk_buff *skb;
 
@@ -586,8 +586,6 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring,
 
        rxhdr = (struct b43_rxhdr_fw4 *)(skb->data);
        rxhdr->frame_len = 0;
-       txstat = (struct b43_hwtxstatus *)(skb->data);
-       txstat->cookie = 0;
 
        return 0;
 }
@@ -776,6 +774,18 @@ static u64 supported_dma_mask(struct b43_wldev *dev)
        return DMA_30BIT_MASK;
 }
 
+static enum b43_dmatype dma_mask_to_engine_type(u64 dmamask)
+{
+       if (dmamask == DMA_30BIT_MASK)
+               return B43_DMA_30BIT;
+       if (dmamask == DMA_32BIT_MASK)
+               return B43_DMA_32BIT;
+       if (dmamask == DMA_64BIT_MASK)
+               return B43_DMA_64BIT;
+       B43_WARN_ON(1);
+       return B43_DMA_30BIT;
+}
+
 /* Main initialization function. */
 static
 struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
@@ -809,7 +819,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
                        goto err_kfree_meta;
 
                /* test for ability to dma to txhdr_cache */
-               dma_test = dma_map_single(dev->dev->dev,
+               dma_test = dma_map_single(dev->dev->dma_dev,
                                          ring->txhdr_cache,
                                          b43_txhdr_size(dev),
                                          DMA_TO_DEVICE);
@@ -824,7 +834,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
                        if (!ring->txhdr_cache)
                                goto err_kfree_meta;
 
-                       dma_test = dma_map_single(dev->dev->dev,
+                       dma_test = dma_map_single(dev->dev->dma_dev,
                                                  ring->txhdr_cache,
                                                  b43_txhdr_size(dev),
                                                  DMA_TO_DEVICE);
@@ -838,7 +848,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
                        }
                }
 
-               dma_unmap_single(dev->dev->dev,
+               dma_unmap_single(dev->dev->dma_dev,
                                 dma_test, b43_txhdr_size(dev),
                                 DMA_TO_DEVICE);
        }
@@ -956,7 +966,11 @@ static void b43_destroy_dmaring(struct b43_dmaring *ring,
 
 void b43_dma_free(struct b43_wldev *dev)
 {
-       struct b43_dma *dma = &dev->dma;
+       struct b43_dma *dma;
+
+       if (b43_using_pio_transfers(dev))
+               return;
+       dma = &dev->dma;
 
        destroy_ring(dma, rx_ring);
        destroy_ring(dma, tx_ring_AC_BK);
@@ -966,6 +980,42 @@ void b43_dma_free(struct b43_wldev *dev)
        destroy_ring(dma, tx_ring_mcast);
 }
 
+static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask)
+{
+       u64 orig_mask = mask;
+       bool fallback = 0;
+       int err;
+
+       /* Try to set the DMA mask. If it fails, try falling back to a
+        * lower mask, as we can always also support a lower one. */
+       while (1) {
+               err = ssb_dma_set_mask(dev->dev, mask);
+               if (!err)
+                       break;
+               if (mask == DMA_64BIT_MASK) {
+                       mask = DMA_32BIT_MASK;
+                       fallback = 1;
+                       continue;
+               }
+               if (mask == DMA_32BIT_MASK) {
+                       mask = DMA_30BIT_MASK;
+                       fallback = 1;
+                       continue;
+               }
+               b43err(dev->wl, "The machine/kernel does not support "
+                      "the required %u-bit DMA mask\n",
+                      (unsigned int)dma_mask_to_engine_type(orig_mask));
+               return -EOPNOTSUPP;
+       }
+       if (fallback) {
+               b43info(dev->wl, "DMA mask fallback from %u-bit to %u-bit\n",
+                       (unsigned int)dma_mask_to_engine_type(orig_mask),
+                       (unsigned int)dma_mask_to_engine_type(mask));
+       }
+
+       return 0;
+}
+
 int b43_dma_init(struct b43_wldev *dev)
 {
        struct b43_dma *dma = &dev->dma;
@@ -974,27 +1024,10 @@ int b43_dma_init(struct b43_wldev *dev)
        enum b43_dmatype type;
 
        dmamask = supported_dma_mask(dev);
-       switch (dmamask) {
-       default:
-               B43_WARN_ON(1);
-       case DMA_30BIT_MASK:
-               type = B43_DMA_30BIT;
-               break;
-       case DMA_32BIT_MASK:
-               type = B43_DMA_32BIT;
-               break;
-       case DMA_64BIT_MASK:
-               type = B43_DMA_64BIT;
-               break;
-       }
-       err = ssb_dma_set_mask(dev->dev, dmamask);
-       if (err) {
-               b43err(dev->wl, "The machine/kernel does not support "
-                      "the required DMA mask (0x%08X%08X)\n",
-                      (unsigned int)((dmamask & 0xFFFFFFFF00000000ULL) >> 32),
-                      (unsigned int)(dmamask & 0x00000000FFFFFFFFULL));
-               return -EOPNOTSUPP;
-       }
+       type = dma_mask_to_engine_type(dmamask);
+       err = b43_dma_set_mask(dev, dmamask);
+       if (err)
+               return err;
 
        err = -ENOMEM;
        /* setup TX DMA channels. */
@@ -1098,10 +1131,10 @@ struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot)
 }
 
 static int dma_tx_fragment(struct b43_dmaring *ring,
-                          struct sk_buff *skb,
-                          struct ieee80211_tx_control *ctl)
+                          struct sk_buff *skb)
 {
        const struct b43_dma_ops *ops = ring->ops;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        u8 *header;
        int slot, old_top_slot, old_used_slots;
        int err;
@@ -1113,7 +1146,6 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
        size_t hdrsize = b43_txhdr_size(ring->dev);
 
 #define SLOTS_PER_PACKET  2
-       B43_WARN_ON(skb_shinfo(skb)->nr_frags);
 
        old_top_slot = ring->current_slot;
        old_used_slots = ring->used_slots;
@@ -1126,7 +1158,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
        header = &(ring->txhdr_cache[slot * hdrsize]);
        cookie = generate_cookie(ring, slot);
        err = b43_generate_txhdr(ring->dev, header,
-                                skb->data, skb->len, ctl, cookie);
+                                skb->data, skb->len, info, cookie);
        if (unlikely(err)) {
                ring->current_slot = old_top_slot;
                ring->used_slots = old_used_slots;
@@ -1148,7 +1180,6 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
        desc = ops->idx2desc(ring, slot, &meta);
        memset(meta, 0, sizeof(*meta));
 
-       memcpy(&meta->txstat.control, ctl, sizeof(*ctl));
        meta->skb = skb;
        meta->is_last_fragment = 1;
 
@@ -1178,7 +1209,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
 
        ops->fill_descriptor(ring, desc, meta->dmaaddr, skb->len, 0, 1, 1);
 
-       if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) {
+       if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
                /* Tell the firmware about the cookie of the last
                 * mcast frame, so it can clear the more-data bit in it. */
                b43_shm_write16(ring->dev, B43_SHM_SHARED,
@@ -1249,21 +1280,16 @@ static struct b43_dmaring * select_ring_by_priority(struct b43_wldev *dev,
        return ring;
 }
 
-int b43_dma_tx(struct b43_wldev *dev,
-              struct sk_buff *skb, struct ieee80211_tx_control *ctl)
+int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
 {
        struct b43_dmaring *ring;
        struct ieee80211_hdr *hdr;
        int err = 0;
        unsigned long flags;
-
-       if (unlikely(skb->len < 2 + 2 + 6)) {
-               /* Too short, this can't be a valid frame. */
-               return -EINVAL;
-       }
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
        hdr = (struct ieee80211_hdr *)skb->data;
-       if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) {
+       if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
                /* The multicast ring will be sent after the DTIM */
                ring = dev->dma.tx_ring_mcast;
                /* Set the more-data bit. Ucode will clear it on
@@ -1271,7 +1297,8 @@ int b43_dma_tx(struct b43_wldev *dev,
                hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
        } else {
                /* Decide by priority where to put this frame. */
-               ring = select_ring_by_priority(dev, ctl->queue);
+               ring = select_ring_by_priority(
+                       dev, skb_get_queue_mapping(skb));
        }
 
        spin_lock_irqsave(&ring->lock, flags);
@@ -1289,9 +1316,9 @@ int b43_dma_tx(struct b43_wldev *dev,
        /* Assign the queue number to the ring (if not already done before)
         * so TX status handling can use it. The queue to ring mapping is
         * static, so we don't need to store it per frame. */
-       ring->queue_prio = ctl->queue;
+       ring->queue_prio = skb_get_queue_mapping(skb);
 
-       err = dma_tx_fragment(ring, skb, ctl);
+       err = dma_tx_fragment(ring, skb);
        if (unlikely(err == -ENOKEY)) {
                /* Drop this packet, as we don't have the encryption key
                 * anymore and must not transmit it unencrypted. */
@@ -1307,7 +1334,7 @@ int b43_dma_tx(struct b43_wldev *dev,
        if ((free_slots(ring) < SLOTS_PER_PACKET) ||
            should_inject_overflow(ring)) {
                /* This TX ring is full. */
-               ieee80211_stop_queue(dev->wl->hw, ctl->queue);
+               ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb));
                ring->stopped = 1;
                if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
                        b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index);
@@ -1319,38 +1346,6 @@ out_unlock:
        return err;
 }
 
-static void b43_fill_txstatus_report(struct b43_dmaring *ring,
-                                   struct ieee80211_tx_status *report,
-                                   const struct b43_txstatus *status)
-{
-       bool frame_failed = 0;
-
-       if (status->acked) {
-               /* The frame was ACKed. */
-               report->flags |= IEEE80211_TX_STATUS_ACK;
-       } else {
-               /* The frame was not ACKed... */
-               if (!(report->control.flags & IEEE80211_TXCTL_NO_ACK)) {
-                       /* ...but we expected an ACK. */
-                       frame_failed = 1;
-                       report->excessive_retries = 1;
-               }
-       }
-       if (status->frame_count == 0) {
-               /* The frame was not transmitted at all. */
-               report->retry_count = 0;
-       } else {
-               report->retry_count = status->frame_count - 1;
-#ifdef CONFIG_B43_DEBUG
-               if (frame_failed)
-                       ring->nr_failed_tx_packets++;
-               else
-                       ring->nr_succeed_tx_packets++;
-               ring->nr_total_packet_tries += status->frame_count;
-#endif /* DEBUG */
-       }
-}
-
 /* Called with IRQs disabled. */
 void b43_dma_handle_txstatus(struct b43_wldev *dev,
                             const struct b43_txstatus *status)
@@ -1360,6 +1355,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
        struct b43_dmadesc_generic *desc;
        struct b43_dmadesc_meta *meta;
        int slot;
+       bool frame_succeed;
 
        ring = parse_cookie(dev, status->cookie, &slot);
        if (unlikely(!ring))
@@ -1381,14 +1377,28 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
                                         b43_txhdr_size(dev), 1);
 
                if (meta->is_last_fragment) {
-                       B43_WARN_ON(!meta->skb);
-                       /* Call back to inform the ieee80211 subsystem about the
-                        * status of the transmission.
-                        * Some fields of txstat are already filled in dma_tx().
+                       struct ieee80211_tx_info *info;
+
+                       BUG_ON(!meta->skb);
+
+                       info = IEEE80211_SKB_CB(meta->skb);
+
+                       memset(&info->status, 0, sizeof(info->status));
+
+                       /*
+                        * Call back to inform the ieee80211 subsystem about
+                        * the status of the transmission.
                         */
-                       b43_fill_txstatus_report(ring, &(meta->txstat), status);
-                       ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb,
-                                                   &(meta->txstat));
+                       frame_succeed = b43_fill_txstatus_report(info, status);
+#ifdef CONFIG_B43_DEBUG
+                       if (frame_succeed)
+                               ring->nr_succeed_tx_packets++;
+                       else
+                               ring->nr_failed_tx_packets++;
+                       ring->nr_total_packet_tries += status->frame_count;
+#endif /* DEBUG */
+                       ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb);
+
                        /* skb is freed by ieee80211_tx_status_irqsafe() */
                        meta->skb = NULL;
                } else {
@@ -1423,18 +1433,16 @@ void b43_dma_get_tx_stats(struct b43_wldev *dev,
 {
        const int nr_queues = dev->wl->hw->queues;
        struct b43_dmaring *ring;
-       struct ieee80211_tx_queue_stats_data *data;
        unsigned long flags;
        int i;
 
        for (i = 0; i < nr_queues; i++) {
-               data = &(stats->data[i]);
                ring = select_ring_by_priority(dev, i);
 
                spin_lock_irqsave(&ring->lock, flags);
-               data->len = ring->used_slots / SLOTS_PER_PACKET;
-               data->limit = ring->nr_slots / SLOTS_PER_PACKET;
-               data->count = ring->nr_tx_packets;
+               stats[i].len = ring->used_slots / SLOTS_PER_PACKET;
+               stats[i].limit = ring->nr_slots / SLOTS_PER_PACKET;
+               stats[i].count = ring->nr_tx_packets;
                spin_unlock_irqrestore(&ring->lock, flags);
        }
 }
@@ -1573,3 +1581,39 @@ void b43_dma_tx_resume(struct b43_wldev *dev)
        b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_BK);
        b43_power_saving_ctl_bits(dev, 0);
 }
+
+#ifdef CONFIG_B43_PIO
+static void direct_fifo_rx(struct b43_wldev *dev, enum b43_dmatype type,
+                          u16 mmio_base, bool enable)
+{
+       u32 ctl;
+
+       if (type == B43_DMA_64BIT) {
+               ctl = b43_read32(dev, mmio_base + B43_DMA64_RXCTL);
+               ctl &= ~B43_DMA64_RXDIRECTFIFO;
+               if (enable)
+                       ctl |= B43_DMA64_RXDIRECTFIFO;
+               b43_write32(dev, mmio_base + B43_DMA64_RXCTL, ctl);
+       } else {
+               ctl = b43_read32(dev, mmio_base + B43_DMA32_RXCTL);
+               ctl &= ~B43_DMA32_RXDIRECTFIFO;
+               if (enable)
+                       ctl |= B43_DMA32_RXDIRECTFIFO;
+               b43_write32(dev, mmio_base + B43_DMA32_RXCTL, ctl);
+       }
+}
+
+/* Enable/Disable Direct FIFO Receive Mode (PIO) on a RX engine.
+ * This is called from PIO code, so DMA structures are not available. */
+void b43_dma_direct_fifo_rx(struct b43_wldev *dev,
+                           unsigned int engine_index, bool enable)
+{
+       enum b43_dmatype type;
+       u16 mmio_base;
+
+       type = dma_mask_to_engine_type(supported_dma_mask(dev));
+
+       mmio_base = b43_dmacontroller_base(type, engine_index);
+       direct_fifo_rx(dev, type, mmio_base, enable);
+}
+#endif /* CONFIG_B43_PIO */
This page took 0.030917 seconds and 5 git commands to generate.