|
@@ -879,15 +879,15 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
|
|
|
}
|
|
|
|
|
|
/* Main cleanup function. */
|
|
|
-static void b43_destroy_dmaring(struct b43_dmaring *ring)
|
|
|
+static void b43_destroy_dmaring(struct b43_dmaring *ring,
|
|
|
+ const char *ringname)
|
|
|
{
|
|
|
if (!ring)
|
|
|
return;
|
|
|
|
|
|
- b43dbg(ring->dev->wl, "DMA-%u 0x%04X (%s) max used slots: %d/%d\n",
|
|
|
- (unsigned int)(ring->type),
|
|
|
- ring->mmio_base,
|
|
|
- (ring->tx) ? "TX" : "RX", ring->max_used_slots, ring->nr_slots);
|
|
|
+ b43dbg(ring->dev->wl, "DMA-%u %s max used slots: %d/%d\n",
|
|
|
+ (unsigned int)(ring->type), ringname,
|
|
|
+ ring->max_used_slots, ring->nr_slots);
|
|
|
/* Device IRQs are disabled prior entering this function,
|
|
|
* so no need to take care of concurrency with rx handler stuff.
|
|
|
*/
|
|
@@ -900,33 +900,26 @@ static void b43_destroy_dmaring(struct b43_dmaring *ring)
|
|
|
kfree(ring);
|
|
|
}
|
|
|
|
|
|
+#define destroy_ring(dma, ring) do { \
|
|
|
+ b43_destroy_dmaring((dma)->ring, __stringify(ring)); \
|
|
|
+ (dma)->ring = NULL; \
|
|
|
+ } while (0)
|
|
|
+
|
|
|
void b43_dma_free(struct b43_wldev *dev)
|
|
|
{
|
|
|
struct b43_dma *dma = &dev->dma;
|
|
|
|
|
|
- b43_destroy_dmaring(dma->rx_ring3);
|
|
|
- dma->rx_ring3 = NULL;
|
|
|
- b43_destroy_dmaring(dma->rx_ring0);
|
|
|
- dma->rx_ring0 = NULL;
|
|
|
-
|
|
|
- b43_destroy_dmaring(dma->tx_ring5);
|
|
|
- dma->tx_ring5 = NULL;
|
|
|
- b43_destroy_dmaring(dma->tx_ring4);
|
|
|
- dma->tx_ring4 = NULL;
|
|
|
- b43_destroy_dmaring(dma->tx_ring3);
|
|
|
- dma->tx_ring3 = NULL;
|
|
|
- b43_destroy_dmaring(dma->tx_ring2);
|
|
|
- dma->tx_ring2 = NULL;
|
|
|
- b43_destroy_dmaring(dma->tx_ring1);
|
|
|
- dma->tx_ring1 = NULL;
|
|
|
- b43_destroy_dmaring(dma->tx_ring0);
|
|
|
- dma->tx_ring0 = NULL;
|
|
|
+ destroy_ring(dma, rx_ring);
|
|
|
+ destroy_ring(dma, tx_ring_AC_BK);
|
|
|
+ destroy_ring(dma, tx_ring_AC_BE);
|
|
|
+ destroy_ring(dma, tx_ring_AC_VI);
|
|
|
+ destroy_ring(dma, tx_ring_AC_VO);
|
|
|
+ destroy_ring(dma, tx_ring_mcast);
|
|
|
}
|
|
|
|
|
|
int b43_dma_init(struct b43_wldev *dev)
|
|
|
{
|
|
|
struct b43_dma *dma = &dev->dma;
|
|
|
- struct b43_dmaring *ring;
|
|
|
int err;
|
|
|
u64 dmamask;
|
|
|
enum b43_dmatype type;
|
|
@@ -956,83 +949,57 @@ int b43_dma_init(struct b43_wldev *dev)
|
|
|
|
|
|
err = -ENOMEM;
|
|
|
/* setup TX DMA channels. */
|
|
|
- ring = b43_setup_dmaring(dev, 0, 1, type);
|
|
|
- if (!ring)
|
|
|
+ dma->tx_ring_AC_BK = b43_setup_dmaring(dev, 0, 1, type);
|
|
|
+ if (!dma->tx_ring_AC_BK)
|
|
|
goto out;
|
|
|
- dma->tx_ring0 = ring;
|
|
|
|
|
|
- ring = b43_setup_dmaring(dev, 1, 1, type);
|
|
|
- if (!ring)
|
|
|
- goto err_destroy_tx0;
|
|
|
- dma->tx_ring1 = ring;
|
|
|
+ dma->tx_ring_AC_BE = b43_setup_dmaring(dev, 1, 1, type);
|
|
|
+ if (!dma->tx_ring_AC_BE)
|
|
|
+ goto err_destroy_bk;
|
|
|
|
|
|
- ring = b43_setup_dmaring(dev, 2, 1, type);
|
|
|
- if (!ring)
|
|
|
- goto err_destroy_tx1;
|
|
|
- dma->tx_ring2 = ring;
|
|
|
+ dma->tx_ring_AC_VI = b43_setup_dmaring(dev, 2, 1, type);
|
|
|
+ if (!dma->tx_ring_AC_VI)
|
|
|
+ goto err_destroy_be;
|
|
|
|
|
|
- ring = b43_setup_dmaring(dev, 3, 1, type);
|
|
|
- if (!ring)
|
|
|
- goto err_destroy_tx2;
|
|
|
- dma->tx_ring3 = ring;
|
|
|
+ dma->tx_ring_AC_VO = b43_setup_dmaring(dev, 3, 1, type);
|
|
|
+ if (!dma->tx_ring_AC_VO)
|
|
|
+ goto err_destroy_vi;
|
|
|
|
|
|
- ring = b43_setup_dmaring(dev, 4, 1, type);
|
|
|
- if (!ring)
|
|
|
- goto err_destroy_tx3;
|
|
|
- dma->tx_ring4 = ring;
|
|
|
+ dma->tx_ring_mcast = b43_setup_dmaring(dev, 4, 1, type);
|
|
|
+ if (!dma->tx_ring_mcast)
|
|
|
+ goto err_destroy_vo;
|
|
|
|
|
|
- ring = b43_setup_dmaring(dev, 5, 1, type);
|
|
|
- if (!ring)
|
|
|
- goto err_destroy_tx4;
|
|
|
- dma->tx_ring5 = ring;
|
|
|
+ /* setup RX DMA channel. */
|
|
|
+ dma->rx_ring = b43_setup_dmaring(dev, 0, 0, type);
|
|
|
+ if (!dma->rx_ring)
|
|
|
+ goto err_destroy_mcast;
|
|
|
|
|
|
- /* setup RX DMA channels. */
|
|
|
- ring = b43_setup_dmaring(dev, 0, 0, type);
|
|
|
- if (!ring)
|
|
|
- goto err_destroy_tx5;
|
|
|
- dma->rx_ring0 = ring;
|
|
|
-
|
|
|
- if (dev->dev->id.revision < 5) {
|
|
|
- ring = b43_setup_dmaring(dev, 3, 0, type);
|
|
|
- if (!ring)
|
|
|
- goto err_destroy_rx0;
|
|
|
- dma->rx_ring3 = ring;
|
|
|
- }
|
|
|
+ /* No support for the TX status DMA ring. */
|
|
|
+ B43_WARN_ON(dev->dev->id.revision < 5);
|
|
|
|
|
|
b43dbg(dev->wl, "%u-bit DMA initialized\n",
|
|
|
(unsigned int)type);
|
|
|
err = 0;
|
|
|
- out:
|
|
|
+out:
|
|
|
return err;
|
|
|
|
|
|
- err_destroy_rx0:
|
|
|
- b43_destroy_dmaring(dma->rx_ring0);
|
|
|
- dma->rx_ring0 = NULL;
|
|
|
- err_destroy_tx5:
|
|
|
- b43_destroy_dmaring(dma->tx_ring5);
|
|
|
- dma->tx_ring5 = NULL;
|
|
|
- err_destroy_tx4:
|
|
|
- b43_destroy_dmaring(dma->tx_ring4);
|
|
|
- dma->tx_ring4 = NULL;
|
|
|
- err_destroy_tx3:
|
|
|
- b43_destroy_dmaring(dma->tx_ring3);
|
|
|
- dma->tx_ring3 = NULL;
|
|
|
- err_destroy_tx2:
|
|
|
- b43_destroy_dmaring(dma->tx_ring2);
|
|
|
- dma->tx_ring2 = NULL;
|
|
|
- err_destroy_tx1:
|
|
|
- b43_destroy_dmaring(dma->tx_ring1);
|
|
|
- dma->tx_ring1 = NULL;
|
|
|
- err_destroy_tx0:
|
|
|
- b43_destroy_dmaring(dma->tx_ring0);
|
|
|
- dma->tx_ring0 = NULL;
|
|
|
- goto out;
|
|
|
+err_destroy_mcast:
|
|
|
+ destroy_ring(dma, tx_ring_mcast);
|
|
|
+err_destroy_vo:
|
|
|
+ destroy_ring(dma, tx_ring_AC_VO);
|
|
|
+err_destroy_vi:
|
|
|
+ destroy_ring(dma, tx_ring_AC_VI);
|
|
|
+err_destroy_be:
|
|
|
+ destroy_ring(dma, tx_ring_AC_BE);
|
|
|
+err_destroy_bk:
|
|
|
+ destroy_ring(dma, tx_ring_AC_BK);
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
/* Generate a cookie for the TX header. */
|
|
|
static u16 generate_cookie(struct b43_dmaring *ring, int slot)
|
|
|
{
|
|
|
- u16 cookie = 0x1000;
|
|
|
+ u16 cookie;
|
|
|
|
|
|
/* Use the upper 4 bits of the cookie as
|
|
|
* DMA controller ID and store the slot number
|
|
@@ -1042,30 +1009,9 @@ static u16 generate_cookie(struct b43_dmaring *ring, int slot)
|
|
|
* It can also not be 0xFFFF because that is special
|
|
|
* for multicast frames.
|
|
|
*/
|
|
|
- switch (ring->index) {
|
|
|
- case 0:
|
|
|
- cookie = 0x1000;
|
|
|
- break;
|
|
|
- case 1:
|
|
|
- cookie = 0x2000;
|
|
|
- break;
|
|
|
- case 2:
|
|
|
- cookie = 0x3000;
|
|
|
- break;
|
|
|
- case 3:
|
|
|
- cookie = 0x4000;
|
|
|
- break;
|
|
|
- case 4:
|
|
|
- cookie = 0x5000;
|
|
|
- break;
|
|
|
- case 5:
|
|
|
- cookie = 0x6000;
|
|
|
- break;
|
|
|
- default:
|
|
|
- B43_WARN_ON(1);
|
|
|
- }
|
|
|
+ cookie = (((u16)ring->index + 1) << 12);
|
|
|
B43_WARN_ON(slot & ~0x0FFF);
|
|
|
- cookie |= (u16) slot;
|
|
|
+ cookie |= (u16)slot;
|
|
|
|
|
|
return cookie;
|
|
|
}
|
|
@@ -1079,22 +1025,19 @@ struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot)
|
|
|
|
|
|
switch (cookie & 0xF000) {
|
|
|
case 0x1000:
|
|
|
- ring = dma->tx_ring0;
|
|
|
+ ring = dma->tx_ring_AC_BK;
|
|
|
break;
|
|
|
case 0x2000:
|
|
|
- ring = dma->tx_ring1;
|
|
|
+ ring = dma->tx_ring_AC_BE;
|
|
|
break;
|
|
|
case 0x3000:
|
|
|
- ring = dma->tx_ring2;
|
|
|
+ ring = dma->tx_ring_AC_VI;
|
|
|
break;
|
|
|
case 0x4000:
|
|
|
- ring = dma->tx_ring3;
|
|
|
+ ring = dma->tx_ring_AC_VO;
|
|
|
break;
|
|
|
case 0x5000:
|
|
|
- ring = dma->tx_ring4;
|
|
|
- break;
|
|
|
- case 0x6000:
|
|
|
- ring = dma->tx_ring5;
|
|
|
+ ring = dma->tx_ring_mcast;
|
|
|
break;
|
|
|
default:
|
|
|
B43_WARN_ON(1);
|
|
@@ -1239,20 +1182,20 @@ static struct b43_dmaring * select_ring_by_priority(struct b43_wldev *dev,
|
|
|
B43_WARN_ON(1);
|
|
|
/* fallthrough */
|
|
|
case 0:
|
|
|
- ring = dev->dma.tx_ring3; /* AC_VO */
|
|
|
+ ring = dev->dma.tx_ring_AC_VO;
|
|
|
break;
|
|
|
case 1:
|
|
|
- ring = dev->dma.tx_ring2; /* AC_VI */
|
|
|
+ ring = dev->dma.tx_ring_AC_VI;
|
|
|
break;
|
|
|
case 2:
|
|
|
- ring = dev->dma.tx_ring1; /* AC_BE */
|
|
|
+ ring = dev->dma.tx_ring_AC_BE;
|
|
|
break;
|
|
|
case 3:
|
|
|
- ring = dev->dma.tx_ring0; /* AC_BK */
|
|
|
+ ring = dev->dma.tx_ring_AC_BK;
|
|
|
break;
|
|
|
}
|
|
|
} else
|
|
|
- ring = dev->dma.tx_ring1;
|
|
|
+ ring = dev->dma.tx_ring_AC_BE;
|
|
|
|
|
|
return ring;
|
|
|
}
|
|
@@ -1273,7 +1216,7 @@ int b43_dma_tx(struct b43_wldev *dev,
|
|
|
hdr = (struct ieee80211_hdr *)skb->data;
|
|
|
if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) {
|
|
|
/* The multicast ring will be sent after the DTIM */
|
|
|
- ring = dev->dma.tx_ring4;
|
|
|
+ ring = dev->dma.tx_ring_mcast;
|
|
|
/* Set the more-data bit. Ucode will clear it on
|
|
|
* the last frame for us. */
|
|
|
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
|
|
@@ -1441,25 +1384,6 @@ static void dma_rx(struct b43_dmaring *ring, int *slot)
|
|
|
sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize);
|
|
|
skb = meta->skb;
|
|
|
|
|
|
- if (ring->index == 3) {
|
|
|
- /* We received an xmit status. */
|
|
|
- struct b43_hwtxstatus *hw = (struct b43_hwtxstatus *)skb->data;
|
|
|
- int i = 0;
|
|
|
-
|
|
|
- while (hw->cookie == 0) {
|
|
|
- if (i > 100)
|
|
|
- break;
|
|
|
- i++;
|
|
|
- udelay(2);
|
|
|
- barrier();
|
|
|
- }
|
|
|
- b43_handle_hwtxstatus(ring->dev, hw);
|
|
|
- /* recycle the descriptor buffer. */
|
|
|
- sync_descbuffer_for_device(ring, meta->dmaaddr,
|
|
|
- ring->rx_buffersize);
|
|
|
-
|
|
|
- return;
|
|
|
- }
|
|
|
rxhdr = (struct b43_rxhdr_fw4 *)skb->data;
|
|
|
len = le16_to_cpu(rxhdr->frame_len);
|
|
|
if (len == 0) {
|
|
@@ -1516,7 +1440,7 @@ static void dma_rx(struct b43_dmaring *ring, int *slot)
|
|
|
skb_pull(skb, ring->frameoffset);
|
|
|
|
|
|
b43_rx(ring->dev, skb, rxhdr);
|
|
|
- drop:
|
|
|
+drop:
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -1562,21 +1486,19 @@ static void b43_dma_tx_resume_ring(struct b43_dmaring *ring)
|
|
|
void b43_dma_tx_suspend(struct b43_wldev *dev)
|
|
|
{
|
|
|
b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
|
|
|
- b43_dma_tx_suspend_ring(dev->dma.tx_ring0);
|
|
|
- b43_dma_tx_suspend_ring(dev->dma.tx_ring1);
|
|
|
- b43_dma_tx_suspend_ring(dev->dma.tx_ring2);
|
|
|
- b43_dma_tx_suspend_ring(dev->dma.tx_ring3);
|
|
|
- b43_dma_tx_suspend_ring(dev->dma.tx_ring4);
|
|
|
- b43_dma_tx_suspend_ring(dev->dma.tx_ring5);
|
|
|
+ b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_BK);
|
|
|
+ b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_BE);
|
|
|
+ b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_VI);
|
|
|
+ b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_VO);
|
|
|
+ b43_dma_tx_suspend_ring(dev->dma.tx_ring_mcast);
|
|
|
}
|
|
|
|
|
|
void b43_dma_tx_resume(struct b43_wldev *dev)
|
|
|
{
|
|
|
- b43_dma_tx_resume_ring(dev->dma.tx_ring5);
|
|
|
- b43_dma_tx_resume_ring(dev->dma.tx_ring4);
|
|
|
- b43_dma_tx_resume_ring(dev->dma.tx_ring3);
|
|
|
- b43_dma_tx_resume_ring(dev->dma.tx_ring2);
|
|
|
- b43_dma_tx_resume_ring(dev->dma.tx_ring1);
|
|
|
- b43_dma_tx_resume_ring(dev->dma.tx_ring0);
|
|
|
+ b43_dma_tx_resume_ring(dev->dma.tx_ring_mcast);
|
|
|
+ b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_VO);
|
|
|
+ b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_VI);
|
|
|
+ b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_BE);
|
|
|
+ b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_BK);
|
|
|
b43_power_saving_ctl_bits(dev, 0);
|
|
|
}
|