aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2008-03-29 16:01:16 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-04-08 15:05:56 -0400
commit5100d5ac81b9330dc57e35adbe50923ba6107b8f (patch)
tree48224236b50703606c97c05ec077fde4880fc3b9 /drivers/net
parent3109ece1114293b8201d9c140d02d7ce9a9fa387 (diff)
b43: Add PIO support for PCMCIA devices
This adds PIO support back (D'oh!) for PCMCIA devices. This is a complete rewrite of the old PIO code. It does actually work and we get reasonable performance out of it on a modern machine. On a PowerBook G4 I get a few MBit for TX and a few more for RX. So it doesn't work as well as DMA (of course), but it's a _lot_ faster than the old PIO code (only got a few kBit with that). The limiting factor is the host CPU speed. So it will generate 100% CPU usage when the network interface is heavily loaded. A voluntary preemption point in the RX path makes sure Desktop Latency isn't hurt. PIO is needed for 16bit PCMCIA devices, as we really don't want to poke with the braindead DMA mechanisms on PCMCIA sockets. Additionally, not all PCMCIA sockets do actually support DMA in 16bit mode (mine doesn't). Signed-off-by: Michael Buesch <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/b43/Kconfig17
-rw-r--r--drivers/net/wireless/b43/Makefile1
-rw-r--r--drivers/net/wireless/b43/b43.h59
-rw-r--r--drivers/net/wireless/b43/dma.c120
-rw-r--r--drivers/net/wireless/b43/dma.h3
-rw-r--r--drivers/net/wireless/b43/main.c37
-rw-r--r--drivers/net/wireless/b43/pio.c835
-rw-r--r--drivers/net/wireless/b43/pio.h220
-rw-r--r--drivers/net/wireless/b43/xmit.c61
-rw-r--r--drivers/net/wireless/b43/xmit.h17
10 files changed, 1267 insertions, 103 deletions
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index 8bc4bc4c330e..94f04559028b 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -62,6 +62,13 @@ config B43_PCMCIA
62 62
63 If unsure, say N. 63 If unsure, say N.
64 64
65# Data transfers to the device via PIO
66# This is only needed on PCMCIA devices. All others can do DMA properly.
67config B43_PIO
68 bool
69 depends on B43 && (B43_PCMCIA || B43_FORCE_PIO)
70 default y
71
65config B43_NPHY 72config B43_NPHY
66 bool "Pre IEEE 802.11n support (BROKEN)" 73 bool "Pre IEEE 802.11n support (BROKEN)"
67 depends on B43 && EXPERIMENTAL && BROKEN 74 depends on B43 && EXPERIMENTAL && BROKEN
@@ -94,3 +101,13 @@ config B43_DEBUG
94 101
95 Say Y, if you want to find out why the driver does not 102 Say Y, if you want to find out why the driver does not
96 work for you. 103 work for you.
104
105config B43_FORCE_PIO
106 bool "Force usage of PIO instead of DMA"
107 depends on B43 && B43_DEBUG
108 ---help---
109 This will disable DMA and always enable PIO instead.
110
111 Say N!
112 This is only for debugging the PIO engine code. You do
113 _NOT_ want to enable this.
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile
index ae11fe4c0be6..8c52b0b9862a 100644
--- a/drivers/net/wireless/b43/Makefile
+++ b/drivers/net/wireless/b43/Makefile
@@ -8,6 +8,7 @@ b43-y += xmit.o
8b43-y += lo.o 8b43-y += lo.o
9b43-y += wa.o 9b43-y += wa.o
10b43-y += dma.o 10b43-y += dma.o
11b43-$(CONFIG_B43_PIO) += pio.o
11b43-$(CONFIG_B43_RFKILL) += rfkill.o 12b43-$(CONFIG_B43_RFKILL) += rfkill.o
12b43-$(CONFIG_B43_LEDS) += leds.o 13b43-$(CONFIG_B43_LEDS) += leds.o
13b43-$(CONFIG_B43_PCMCIA) += pcmcia.o 14b43-$(CONFIG_B43_PCMCIA) += pcmcia.o
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index d40be1568517..ef8ae385835a 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -75,6 +75,23 @@
75#define B43_MMIO_DMA64_BASE4 0x300 75#define B43_MMIO_DMA64_BASE4 0x300
76#define B43_MMIO_DMA64_BASE5 0x340 76#define B43_MMIO_DMA64_BASE5 0x340
77 77
78/* PIO on core rev < 11 */
79#define B43_MMIO_PIO_BASE0 0x300
80#define B43_MMIO_PIO_BASE1 0x310
81#define B43_MMIO_PIO_BASE2 0x320
82#define B43_MMIO_PIO_BASE3 0x330
83#define B43_MMIO_PIO_BASE4 0x340
84#define B43_MMIO_PIO_BASE5 0x350
85#define B43_MMIO_PIO_BASE6 0x360
86#define B43_MMIO_PIO_BASE7 0x370
87/* PIO on core rev >= 11 */
88#define B43_MMIO_PIO11_BASE0 0x200
89#define B43_MMIO_PIO11_BASE1 0x240
90#define B43_MMIO_PIO11_BASE2 0x280
91#define B43_MMIO_PIO11_BASE3 0x2C0
92#define B43_MMIO_PIO11_BASE4 0x300
93#define B43_MMIO_PIO11_BASE5 0x340
94
78#define B43_MMIO_PHY_VER 0x3E0 95#define B43_MMIO_PHY_VER 0x3E0
79#define B43_MMIO_PHY_RADIO 0x3E2 96#define B43_MMIO_PHY_RADIO 0x3E2
80#define B43_MMIO_PHY0 0x3E6 97#define B43_MMIO_PHY0 0x3E6
@@ -442,7 +459,6 @@ enum {
442}; 459};
443 460
444struct b43_dmaring; 461struct b43_dmaring;
445struct b43_pioqueue;
446 462
447/* The firmware file header */ 463/* The firmware file header */
448#define B43_FW_TYPE_UCODE 'u' 464#define B43_FW_TYPE_UCODE 'u'
@@ -598,6 +614,20 @@ struct b43_dma {
598 struct b43_dmaring *rx_ring; 614 struct b43_dmaring *rx_ring;
599}; 615};
600 616
617struct b43_pio_txqueue;
618struct b43_pio_rxqueue;
619
620/* Data structures for PIO transmission, per 80211 core. */
621struct b43_pio {
622 struct b43_pio_txqueue *tx_queue_AC_BK; /* Background */
623 struct b43_pio_txqueue *tx_queue_AC_BE; /* Best Effort */
624 struct b43_pio_txqueue *tx_queue_AC_VI; /* Video */
625 struct b43_pio_txqueue *tx_queue_AC_VO; /* Voice */
626 struct b43_pio_txqueue *tx_queue_mcast; /* Multicast */
627
628 struct b43_pio_rxqueue *rx_queue;
629};
630
601/* Context information for a noise calculation (Link Quality). */ 631/* Context information for a noise calculation (Link Quality). */
602struct b43_noise_calculation { 632struct b43_noise_calculation {
603 u8 channel_at_start; 633 u8 channel_at_start;
@@ -773,8 +803,15 @@ struct b43_wldev {
773 /* PHY/Radio device. */ 803 /* PHY/Radio device. */
774 struct b43_phy phy; 804 struct b43_phy phy;
775 805
776 /* DMA engines. */ 806 union {
777 struct b43_dma dma; 807 /* DMA engines. */
808 struct b43_dma dma;
809 /* PIO engines. */
810 struct b43_pio pio;
811 };
812 /* Use b43_using_pio_transfers() to check whether we are using
813 * DMA or PIO data transfers. */
814 bool __using_pio_transfers;
778 815
779 /* Various statistics about the physical device. */ 816 /* Various statistics about the physical device. */
780 struct b43_stats stats; 817 struct b43_stats stats;
@@ -858,6 +895,22 @@ static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value)
858 ssb_write32(dev->dev, offset, value); 895 ssb_write32(dev->dev, offset, value);
859} 896}
860 897
898static inline bool b43_using_pio_transfers(struct b43_wldev *dev)
899{
900#ifdef CONFIG_B43_PIO
901 return dev->__using_pio_transfers;
902#else
903 return 0;
904#endif
905}
906
907#ifdef CONFIG_B43_FORCE_PIO
908# define B43_FORCE_PIO 1
909#else
910# define B43_FORCE_PIO 0
911#endif
912
913
861/* Message printing */ 914/* Message printing */
862void b43info(struct b43_wl *wl, const char *fmt, ...) 915void b43info(struct b43_wl *wl, const char *fmt, ...)
863 __attribute__ ((format(printf, 2, 3))); 916 __attribute__ ((format(printf, 2, 3)));
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 70db0570adc5..f1b983cb9c1f 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -550,7 +550,6 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring,
550 struct b43_dmadesc_meta *meta, gfp_t gfp_flags) 550 struct b43_dmadesc_meta *meta, gfp_t gfp_flags)
551{ 551{
552 struct b43_rxhdr_fw4 *rxhdr; 552 struct b43_rxhdr_fw4 *rxhdr;
553 struct b43_hwtxstatus *txstat;
554 dma_addr_t dmaaddr; 553 dma_addr_t dmaaddr;
555 struct sk_buff *skb; 554 struct sk_buff *skb;
556 555
@@ -586,8 +585,6 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring,
586 585
587 rxhdr = (struct b43_rxhdr_fw4 *)(skb->data); 586 rxhdr = (struct b43_rxhdr_fw4 *)(skb->data);
588 rxhdr->frame_len = 0; 587 rxhdr->frame_len = 0;
589 txstat = (struct b43_hwtxstatus *)(skb->data);
590 txstat->cookie = 0;
591 588
592 return 0; 589 return 0;
593} 590}
@@ -776,6 +773,18 @@ static u64 supported_dma_mask(struct b43_wldev *dev)
776 return DMA_30BIT_MASK; 773 return DMA_30BIT_MASK;
777} 774}
778 775
776static enum b43_dmatype dma_mask_to_engine_type(u64 dmamask)
777{
778 if (dmamask == DMA_30BIT_MASK)
779 return B43_DMA_30BIT;
780 if (dmamask == DMA_32BIT_MASK)
781 return B43_DMA_32BIT;
782 if (dmamask == DMA_64BIT_MASK)
783 return B43_DMA_64BIT;
784 B43_WARN_ON(1);
785 return B43_DMA_30BIT;
786}
787
779/* Main initialization function. */ 788/* Main initialization function. */
780static 789static
781struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, 790struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
@@ -956,7 +965,11 @@ static void b43_destroy_dmaring(struct b43_dmaring *ring,
956 965
957void b43_dma_free(struct b43_wldev *dev) 966void b43_dma_free(struct b43_wldev *dev)
958{ 967{
959 struct b43_dma *dma = &dev->dma; 968 struct b43_dma *dma;
969
970 if (b43_using_pio_transfers(dev))
971 return;
972 dma = &dev->dma;
960 973
961 destroy_ring(dma, rx_ring); 974 destroy_ring(dma, rx_ring);
962 destroy_ring(dma, tx_ring_AC_BK); 975 destroy_ring(dma, tx_ring_AC_BK);
@@ -974,19 +987,7 @@ int b43_dma_init(struct b43_wldev *dev)
974 enum b43_dmatype type; 987 enum b43_dmatype type;
975 988
976 dmamask = supported_dma_mask(dev); 989 dmamask = supported_dma_mask(dev);
977 switch (dmamask) { 990 type = dma_mask_to_engine_type(dmamask);
978 default:
979 B43_WARN_ON(1);
980 case DMA_30BIT_MASK:
981 type = B43_DMA_30BIT;
982 break;
983 case DMA_32BIT_MASK:
984 type = B43_DMA_32BIT;
985 break;
986 case DMA_64BIT_MASK:
987 type = B43_DMA_64BIT;
988 break;
989 }
990 err = ssb_dma_set_mask(dev->dev, dmamask); 991 err = ssb_dma_set_mask(dev->dev, dmamask);
991 if (err) { 992 if (err) {
992 b43err(dev->wl, "The machine/kernel does not support " 993 b43err(dev->wl, "The machine/kernel does not support "
@@ -1113,7 +1114,6 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
1113 size_t hdrsize = b43_txhdr_size(ring->dev); 1114 size_t hdrsize = b43_txhdr_size(ring->dev);
1114 1115
1115#define SLOTS_PER_PACKET 2 1116#define SLOTS_PER_PACKET 2
1116 B43_WARN_ON(skb_shinfo(skb)->nr_frags);
1117 1117
1118 old_top_slot = ring->current_slot; 1118 old_top_slot = ring->current_slot;
1119 old_used_slots = ring->used_slots; 1119 old_used_slots = ring->used_slots;
@@ -1257,11 +1257,6 @@ int b43_dma_tx(struct b43_wldev *dev,
1257 int err = 0; 1257 int err = 0;
1258 unsigned long flags; 1258 unsigned long flags;
1259 1259
1260 if (unlikely(skb->len < 2 + 2 + 6)) {
1261 /* Too short, this can't be a valid frame. */
1262 return -EINVAL;
1263 }
1264
1265 hdr = (struct ieee80211_hdr *)skb->data; 1260 hdr = (struct ieee80211_hdr *)skb->data;
1266 if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) { 1261 if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) {
1267 /* The multicast ring will be sent after the DTIM */ 1262 /* The multicast ring will be sent after the DTIM */
@@ -1319,38 +1314,6 @@ out_unlock:
1319 return err; 1314 return err;
1320} 1315}
1321 1316
1322static void b43_fill_txstatus_report(struct b43_dmaring *ring,
1323 struct ieee80211_tx_status *report,
1324 const struct b43_txstatus *status)
1325{
1326 bool frame_failed = 0;
1327
1328 if (status->acked) {
1329 /* The frame was ACKed. */
1330 report->flags |= IEEE80211_TX_STATUS_ACK;
1331 } else {
1332 /* The frame was not ACKed... */
1333 if (!(report->control.flags & IEEE80211_TXCTL_NO_ACK)) {
1334 /* ...but we expected an ACK. */
1335 frame_failed = 1;
1336 report->excessive_retries = 1;
1337 }
1338 }
1339 if (status->frame_count == 0) {
1340 /* The frame was not transmitted at all. */
1341 report->retry_count = 0;
1342 } else {
1343 report->retry_count = status->frame_count - 1;
1344#ifdef CONFIG_B43_DEBUG
1345 if (frame_failed)
1346 ring->nr_failed_tx_packets++;
1347 else
1348 ring->nr_succeed_tx_packets++;
1349 ring->nr_total_packet_tries += status->frame_count;
1350#endif /* DEBUG */
1351 }
1352}
1353
1354/* Called with IRQs disabled. */ 1317/* Called with IRQs disabled. */
1355void b43_dma_handle_txstatus(struct b43_wldev *dev, 1318void b43_dma_handle_txstatus(struct b43_wldev *dev,
1356 const struct b43_txstatus *status) 1319 const struct b43_txstatus *status)
@@ -1360,6 +1323,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
1360 struct b43_dmadesc_generic *desc; 1323 struct b43_dmadesc_generic *desc;
1361 struct b43_dmadesc_meta *meta; 1324 struct b43_dmadesc_meta *meta;
1362 int slot; 1325 int slot;
1326 bool frame_succeed;
1363 1327
1364 ring = parse_cookie(dev, status->cookie, &slot); 1328 ring = parse_cookie(dev, status->cookie, &slot);
1365 if (unlikely(!ring)) 1329 if (unlikely(!ring))
@@ -1386,7 +1350,15 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
1386 * status of the transmission. 1350 * status of the transmission.
1387 * Some fields of txstat are already filled in dma_tx(). 1351 * Some fields of txstat are already filled in dma_tx().
1388 */ 1352 */
1389 b43_fill_txstatus_report(ring, &(meta->txstat), status); 1353 frame_succeed = b43_fill_txstatus_report(
1354 &(meta->txstat), status);
1355#ifdef CONFIG_B43_DEBUG
1356 if (frame_succeed)
1357 ring->nr_succeed_tx_packets++;
1358 else
1359 ring->nr_failed_tx_packets++;
1360 ring->nr_total_packet_tries += status->frame_count;
1361#endif /* DEBUG */
1390 ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb, 1362 ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb,
1391 &(meta->txstat)); 1363 &(meta->txstat));
1392 /* skb is freed by ieee80211_tx_status_irqsafe() */ 1364 /* skb is freed by ieee80211_tx_status_irqsafe() */
@@ -1573,3 +1545,39 @@ void b43_dma_tx_resume(struct b43_wldev *dev)
1573 b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_BK); 1545 b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_BK);
1574 b43_power_saving_ctl_bits(dev, 0); 1546 b43_power_saving_ctl_bits(dev, 0);
1575} 1547}
1548
1549#ifdef CONFIG_B43_PIO
1550static void direct_fifo_rx(struct b43_wldev *dev, enum b43_dmatype type,
1551 u16 mmio_base, bool enable)
1552{
1553 u32 ctl;
1554
1555 if (type == B43_DMA_64BIT) {
1556 ctl = b43_read32(dev, mmio_base + B43_DMA64_RXCTL);
1557 ctl &= ~B43_DMA64_RXDIRECTFIFO;
1558 if (enable)
1559 ctl |= B43_DMA64_RXDIRECTFIFO;
1560 b43_write32(dev, mmio_base + B43_DMA64_RXCTL, ctl);
1561 } else {
1562 ctl = b43_read32(dev, mmio_base + B43_DMA32_RXCTL);
1563 ctl &= ~B43_DMA32_RXDIRECTFIFO;
1564 if (enable)
1565 ctl |= B43_DMA32_RXDIRECTFIFO;
1566 b43_write32(dev, mmio_base + B43_DMA32_RXCTL, ctl);
1567 }
1568}
1569
1570/* Enable/Disable Direct FIFO Receive Mode (PIO) on a RX engine.
1571 * This is called from PIO code, so DMA structures are not available. */
1572void b43_dma_direct_fifo_rx(struct b43_wldev *dev,
1573 unsigned int engine_index, bool enable)
1574{
1575 enum b43_dmatype type;
1576 u16 mmio_base;
1577
1578 type = dma_mask_to_engine_type(supported_dma_mask(dev));
1579
1580 mmio_base = b43_dmacontroller_base(type, engine_index);
1581 direct_fifo_rx(dev, type, mmio_base, enable);
1582}
1583#endif /* CONFIG_B43_PIO */
diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h
index ea27085dec0e..20acf885dba5 100644
--- a/drivers/net/wireless/b43/dma.h
+++ b/drivers/net/wireless/b43/dma.h
@@ -291,4 +291,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
291 291
292void b43_dma_rx(struct b43_dmaring *ring); 292void b43_dma_rx(struct b43_dmaring *ring);
293 293
294void b43_dma_direct_fifo_rx(struct b43_wldev *dev,
295 unsigned int engine_index, bool enable);
296
294#endif /* B43_DMA_H_ */ 297#endif /* B43_DMA_H_ */
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index a4e6a59ccac8..355f28a2f7f5 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -47,6 +47,7 @@
47#include "debugfs.h" 47#include "debugfs.h"
48#include "phy.h" 48#include "phy.h"
49#include "dma.h" 49#include "dma.h"
50#include "pio.h"
50#include "sysfs.h" 51#include "sysfs.h"
51#include "xmit.h" 52#include "xmit.h"
52#include "lo.h" 53#include "lo.h"
@@ -1593,8 +1594,12 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
1593 handle_irq_noise(dev); 1594 handle_irq_noise(dev);
1594 1595
1595 /* Check the DMA reason registers for received data. */ 1596 /* Check the DMA reason registers for received data. */
1596 if (dma_reason[0] & B43_DMAIRQ_RX_DONE) 1597 if (dma_reason[0] & B43_DMAIRQ_RX_DONE) {
1597 b43_dma_rx(dev->dma.rx_ring); 1598 if (b43_using_pio_transfers(dev))
1599 b43_pio_rx(dev->pio.rx_queue);
1600 else
1601 b43_dma_rx(dev->dma.rx_ring);
1602 }
1598 B43_WARN_ON(dma_reason[1] & B43_DMAIRQ_RX_DONE); 1603 B43_WARN_ON(dma_reason[1] & B43_DMAIRQ_RX_DONE);
1599 B43_WARN_ON(dma_reason[2] & B43_DMAIRQ_RX_DONE); 1604 B43_WARN_ON(dma_reason[2] & B43_DMAIRQ_RX_DONE);
1600 B43_WARN_ON(dma_reason[3] & B43_DMAIRQ_RX_DONE); 1605 B43_WARN_ON(dma_reason[3] & B43_DMAIRQ_RX_DONE);
@@ -2698,12 +2703,21 @@ static int b43_op_tx(struct ieee80211_hw *hw,
2698 struct b43_wldev *dev = wl->current_dev; 2703 struct b43_wldev *dev = wl->current_dev;
2699 int err = -ENODEV; 2704 int err = -ENODEV;
2700 2705
2706 if (unlikely(skb->len < 2 + 2 + 6)) {
2707 /* Too short, this can't be a valid frame. */
2708 return -EINVAL;
2709 }
2710 B43_WARN_ON(skb_shinfo(skb)->nr_frags);
2711
2701 if (unlikely(!dev)) 2712 if (unlikely(!dev))
2702 goto out; 2713 goto out;
2703 if (unlikely(b43_status(dev) < B43_STAT_STARTED)) 2714 if (unlikely(b43_status(dev) < B43_STAT_STARTED))
2704 goto out; 2715 goto out;
2705 /* DMA-TX is done without a global lock. */ 2716 /* TX is done without a global lock. */
2706 err = b43_dma_tx(dev, skb, ctl); 2717 if (b43_using_pio_transfers(dev))
2718 err = b43_pio_tx(dev, skb, ctl);
2719 else
2720 err = b43_dma_tx(dev, skb, ctl);
2707out: 2721out:
2708 if (unlikely(err)) 2722 if (unlikely(err))
2709 return NETDEV_TX_BUSY; 2723 return NETDEV_TX_BUSY;
@@ -2897,7 +2911,10 @@ static int b43_op_get_tx_stats(struct ieee80211_hw *hw,
2897 goto out; 2911 goto out;
2898 spin_lock_irqsave(&wl->irq_lock, flags); 2912 spin_lock_irqsave(&wl->irq_lock, flags);
2899 if (likely(b43_status(dev) >= B43_STAT_STARTED)) { 2913 if (likely(b43_status(dev) >= B43_STAT_STARTED)) {
2900 b43_dma_get_tx_stats(dev, stats); 2914 if (b43_using_pio_transfers(dev))
2915 b43_pio_get_tx_stats(dev, stats);
2916 else
2917 b43_dma_get_tx_stats(dev, stats);
2901 err = 0; 2918 err = 0;
2902 } 2919 }
2903 spin_unlock_irqrestore(&wl->irq_lock, flags); 2920 spin_unlock_irqrestore(&wl->irq_lock, flags);
@@ -3366,6 +3383,7 @@ static void b43_wireless_core_stop(struct b43_wldev *dev)
3366 3383
3367 b43_set_status(dev, B43_STAT_INITIALIZED); 3384 b43_set_status(dev, B43_STAT_INITIALIZED);
3368 3385
3386 b43_pio_stop(dev);
3369 mutex_unlock(&wl->mutex); 3387 mutex_unlock(&wl->mutex);
3370 /* Must unlock as it would otherwise deadlock. No races here. 3388 /* Must unlock as it would otherwise deadlock. No races here.
3371 * Cancel the possibly running self-rearming periodic work. */ 3389 * Cancel the possibly running self-rearming periodic work. */
@@ -3683,6 +3701,7 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
3683 b43_rng_exit(dev->wl, false); 3701 b43_rng_exit(dev->wl, false);
3684 } 3702 }
3685 b43_dma_free(dev); 3703 b43_dma_free(dev);
3704 b43_pio_free(dev);
3686 b43_chip_exit(dev); 3705 b43_chip_exit(dev);
3687 b43_radio_turn_off(dev, 1); 3706 b43_radio_turn_off(dev, 1);
3688 b43_switch_analog(dev, 0); 3707 b43_switch_analog(dev, 0);
@@ -3780,7 +3799,13 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
3780 /* Maximum Contention Window */ 3799 /* Maximum Contention Window */
3781 b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF); 3800 b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF);
3782 3801
3783 err = b43_dma_init(dev); 3802 if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || B43_FORCE_PIO) {
3803 dev->__using_pio_transfers = 1;
3804 err = b43_pio_init(dev);
3805 } else {
3806 dev->__using_pio_transfers = 0;
3807 err = b43_dma_init(dev);
3808 }
3784 if (err) 3809 if (err)
3785 goto err_chip_exit; 3810 goto err_chip_exit;
3786 b43_qos_init(dev); 3811 b43_qos_init(dev);
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
new file mode 100644
index 000000000000..e73769ac027f
--- /dev/null
+++ b/drivers/net/wireless/b43/pio.c
@@ -0,0 +1,835 @@
1/*
2
3 Broadcom B43 wireless driver
4
5 PIO data transfer
6
7 Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
22 Boston, MA 02110-1301, USA.
23
24*/
25
26#include "b43.h"
27#include "pio.h"
28#include "dma.h"
29#include "main.h"
30#include "xmit.h"
31
32#include <linux/delay.h>
33
34
35static void b43_pio_rx_work(struct work_struct *work);
36
37
38static u16 generate_cookie(struct b43_pio_txqueue *q,
39 struct b43_pio_txpacket *pack)
40{
41 u16 cookie;
42
43 /* Use the upper 4 bits of the cookie as
44 * PIO controller ID and store the packet index number
45 * in the lower 12 bits.
46 * Note that the cookie must never be 0, as this
47 * is a special value used in RX path.
48 * It can also not be 0xFFFF because that is special
49 * for multicast frames.
50 */
51 cookie = (((u16)q->index + 1) << 12);
52 cookie |= pack->index;
53
54 return cookie;
55}
56
57static
58struct b43_pio_txqueue * parse_cookie(struct b43_wldev *dev,
59 u16 cookie,
60 struct b43_pio_txpacket **pack)
61{
62 struct b43_pio *pio = &dev->pio;
63 struct b43_pio_txqueue *q = NULL;
64 unsigned int pack_index;
65
66 switch (cookie & 0xF000) {
67 case 0x1000:
68 q = pio->tx_queue_AC_BK;
69 break;
70 case 0x2000:
71 q = pio->tx_queue_AC_BE;
72 break;
73 case 0x3000:
74 q = pio->tx_queue_AC_VI;
75 break;
76 case 0x4000:
77 q = pio->tx_queue_AC_VO;
78 break;
79 case 0x5000:
80 q = pio->tx_queue_mcast;
81 break;
82 }
83 if (B43_WARN_ON(!q))
84 return NULL;
85 pack_index = (cookie & 0x0FFF);
86 if (B43_WARN_ON(pack_index >= ARRAY_SIZE(q->packets)))
87 return NULL;
88 *pack = &q->packets[pack_index];
89
90 return q;
91}
92
93static u16 index_to_pioqueue_base(struct b43_wldev *dev,
94 unsigned int index)
95{
96 static const u16 bases[] = {
97 B43_MMIO_PIO_BASE0,
98 B43_MMIO_PIO_BASE1,
99 B43_MMIO_PIO_BASE2,
100 B43_MMIO_PIO_BASE3,
101 B43_MMIO_PIO_BASE4,
102 B43_MMIO_PIO_BASE5,
103 B43_MMIO_PIO_BASE6,
104 B43_MMIO_PIO_BASE7,
105 };
106 static const u16 bases_rev11[] = {
107 B43_MMIO_PIO11_BASE0,
108 B43_MMIO_PIO11_BASE1,
109 B43_MMIO_PIO11_BASE2,
110 B43_MMIO_PIO11_BASE3,
111 B43_MMIO_PIO11_BASE4,
112 B43_MMIO_PIO11_BASE5,
113 };
114
115 if (dev->dev->id.revision >= 11) {
116 B43_WARN_ON(index >= ARRAY_SIZE(bases_rev11));
117 return bases_rev11[index];
118 }
119 B43_WARN_ON(index >= ARRAY_SIZE(bases));
120 return bases[index];
121}
122
123static u16 pio_txqueue_offset(struct b43_wldev *dev)
124{
125 if (dev->dev->id.revision >= 11)
126 return 0x18;
127 return 0;
128}
129
130static u16 pio_rxqueue_offset(struct b43_wldev *dev)
131{
132 if (dev->dev->id.revision >= 11)
133 return 0x38;
134 return 8;
135}
136
137static struct b43_pio_txqueue * b43_setup_pioqueue_tx(struct b43_wldev *dev,
138 unsigned int index)
139{
140 struct b43_pio_txqueue *q;
141 struct b43_pio_txpacket *p;
142 unsigned int i;
143
144 q = kzalloc(sizeof(*q), GFP_KERNEL);
145 if (!q)
146 return NULL;
147 spin_lock_init(&q->lock);
148 q->dev = dev;
149 q->rev = dev->dev->id.revision;
150 q->mmio_base = index_to_pioqueue_base(dev, index) +
151 pio_txqueue_offset(dev);
152 q->index = index;
153
154 q->free_packet_slots = B43_PIO_MAX_NR_TXPACKETS;
155 if (q->rev >= 8) {
156 q->buffer_size = 1920; //FIXME this constant is wrong.
157 } else {
158 q->buffer_size = b43_piotx_read16(q, B43_PIO_TXQBUFSIZE);
159 q->buffer_size -= 80;
160 }
161
162 INIT_LIST_HEAD(&q->packets_list);
163 for (i = 0; i < ARRAY_SIZE(q->packets); i++) {
164 p = &(q->packets[i]);
165 INIT_LIST_HEAD(&p->list);
166 p->index = i;
167 p->queue = q;
168 list_add(&p->list, &q->packets_list);
169 }
170
171 return q;
172}
173
174static struct b43_pio_rxqueue * b43_setup_pioqueue_rx(struct b43_wldev *dev,
175 unsigned int index)
176{
177 struct b43_pio_rxqueue *q;
178
179 q = kzalloc(sizeof(*q), GFP_KERNEL);
180 if (!q)
181 return NULL;
182 spin_lock_init(&q->lock);
183 q->dev = dev;
184 q->rev = dev->dev->id.revision;
185 q->mmio_base = index_to_pioqueue_base(dev, index) +
186 pio_rxqueue_offset(dev);
187 INIT_WORK(&q->rx_work, b43_pio_rx_work);
188
189 /* Enable Direct FIFO RX (PIO) on the engine. */
190 b43_dma_direct_fifo_rx(dev, index, 1);
191
192 return q;
193}
194
195static void b43_pio_cancel_tx_packets(struct b43_pio_txqueue *q)
196{
197 struct b43_pio_txpacket *pack;
198 unsigned int i;
199
200 for (i = 0; i < ARRAY_SIZE(q->packets); i++) {
201 pack = &(q->packets[i]);
202 if (pack->skb) {
203 dev_kfree_skb_any(pack->skb);
204 pack->skb = NULL;
205 }
206 }
207}
208
209static void b43_destroy_pioqueue_tx(struct b43_pio_txqueue *q,
210 const char *name)
211{
212 if (!q)
213 return;
214 b43_pio_cancel_tx_packets(q);
215 kfree(q);
216}
217
218static void b43_destroy_pioqueue_rx(struct b43_pio_rxqueue *q,
219 const char *name)
220{
221 if (!q)
222 return;
223 kfree(q);
224}
225
226#define destroy_queue_tx(pio, queue) do { \
227 b43_destroy_pioqueue_tx((pio)->queue, __stringify(queue)); \
228 (pio)->queue = NULL; \
229 } while (0)
230
231#define destroy_queue_rx(pio, queue) do { \
232 b43_destroy_pioqueue_rx((pio)->queue, __stringify(queue)); \
233 (pio)->queue = NULL; \
234 } while (0)
235
236void b43_pio_free(struct b43_wldev *dev)
237{
238 struct b43_pio *pio;
239
240 if (!b43_using_pio_transfers(dev))
241 return;
242 pio = &dev->pio;
243
244 destroy_queue_rx(pio, rx_queue);
245 destroy_queue_tx(pio, tx_queue_mcast);
246 destroy_queue_tx(pio, tx_queue_AC_VO);
247 destroy_queue_tx(pio, tx_queue_AC_VI);
248 destroy_queue_tx(pio, tx_queue_AC_BE);
249 destroy_queue_tx(pio, tx_queue_AC_BK);
250}
251
252void b43_pio_stop(struct b43_wldev *dev)
253{
254 if (!b43_using_pio_transfers(dev))
255 return;
256 cancel_work_sync(&dev->pio.rx_queue->rx_work);
257}
258
259int b43_pio_init(struct b43_wldev *dev)
260{
261 struct b43_pio *pio = &dev->pio;
262 int err = -ENOMEM;
263
264 b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
265 & ~B43_MACCTL_BE);
266 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_RXPADOFF, 0);
267
268 pio->tx_queue_AC_BK = b43_setup_pioqueue_tx(dev, 0);
269 if (!pio->tx_queue_AC_BK)
270 goto out;
271
272 pio->tx_queue_AC_BE = b43_setup_pioqueue_tx(dev, 1);
273 if (!pio->tx_queue_AC_BE)
274 goto err_destroy_bk;
275
276 pio->tx_queue_AC_VI = b43_setup_pioqueue_tx(dev, 2);
277 if (!pio->tx_queue_AC_VI)
278 goto err_destroy_be;
279
280 pio->tx_queue_AC_VO = b43_setup_pioqueue_tx(dev, 3);
281 if (!pio->tx_queue_AC_VO)
282 goto err_destroy_vi;
283
284 pio->tx_queue_mcast = b43_setup_pioqueue_tx(dev, 4);
285 if (!pio->tx_queue_mcast)
286 goto err_destroy_vo;
287
288 pio->rx_queue = b43_setup_pioqueue_rx(dev, 0);
289 if (!pio->rx_queue)
290 goto err_destroy_mcast;
291
292 b43dbg(dev->wl, "PIO initialized\n");
293 err = 0;
294out:
295 return err;
296
297err_destroy_mcast:
298 destroy_queue_tx(pio, tx_queue_mcast);
299err_destroy_vo:
300 destroy_queue_tx(pio, tx_queue_AC_VO);
301err_destroy_vi:
302 destroy_queue_tx(pio, tx_queue_AC_VI);
303err_destroy_be:
304 destroy_queue_tx(pio, tx_queue_AC_BE);
305err_destroy_bk:
306 destroy_queue_tx(pio, tx_queue_AC_BK);
307 return err;
308}
309
310/* Static mapping of mac80211's queues (priorities) to b43 PIO queues. */
311static struct b43_pio_txqueue * select_queue_by_priority(struct b43_wldev *dev,
312 u8 queue_prio)
313{
314 struct b43_pio_txqueue *q;
315
316 if (b43_modparam_qos) {
317 /* 0 = highest priority */
318 switch (queue_prio) {
319 default:
320 B43_WARN_ON(1);
321 /* fallthrough */
322 case 0:
323 q = dev->pio.tx_queue_AC_VO;
324 break;
325 case 1:
326 q = dev->pio.tx_queue_AC_VI;
327 break;
328 case 2:
329 q = dev->pio.tx_queue_AC_BE;
330 break;
331 case 3:
332 q = dev->pio.tx_queue_AC_BK;
333 break;
334 }
335 } else
336 q = dev->pio.tx_queue_AC_BE;
337
338 return q;
339}
340
341static inline void tx_write_2byte_queue(struct b43_pio_txqueue *q,
342 u16 *ctl,
343 const void *_data,
344 unsigned int data_len)
345{
346 const u8 *data = _data;
347 unsigned int i;
348 u16 value;
349
350 *ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI;
351 b43_piotx_write16(q, B43_PIO_TXCTL, *ctl);
352 for (i = 0; i < data_len; i += 2) {
353 value = data[i];
354 if (i + 1 < data_len) {
355 value |= (u16)(data[i + 1]) << 8;
356 } else {
357 *ctl &= ~B43_PIO_TXCTL_WRITEHI;
358 b43_piotx_write16(q, B43_PIO_TXCTL, *ctl);
359 }
360 b43_piotx_write16(q, B43_PIO_TXDATA, value);
361 }
362}
363
364static void pio_tx_frame_2byte_queue(struct b43_pio_txpacket *pack,
365 const u8 *hdr, unsigned int hdrlen)
366{
367 struct b43_pio_txqueue *q = pack->queue;
368 const char *frame = pack->skb->data;
369 unsigned int frame_len = pack->skb->len;
370 u16 ctl;
371
372 ctl = b43_piotx_read16(q, B43_PIO_TXCTL);
373 ctl |= B43_PIO_TXCTL_FREADY;
374 ctl &= ~B43_PIO_TXCTL_EOF;
375
376 /* Transfer the header data. */
377 tx_write_2byte_queue(q, &ctl, hdr, hdrlen);
378 /* Transfer the frame data. */
379 tx_write_2byte_queue(q, &ctl, frame, frame_len);
380
381 ctl |= B43_PIO_TXCTL_EOF;
382 b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
383}
384
385static inline void tx_write_4byte_queue(struct b43_pio_txqueue *q,
386 u32 *ctl,
387 const void *_data,
388 unsigned int data_len)
389{
390 const u8 *data = _data;
391 unsigned int i;
392 u32 value;
393 bool ctl_changed = 0;
394
395 *ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 |
396 B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31;
397 b43_piotx_write32(q, B43_PIO8_TXCTL, *ctl);
398 for (i = 0; i < data_len; i += 4) {
399 value = data[i];
400 if (i + 1 < data_len) {
401 value |= (u32)(data[i + 1]) << 8;
402 } else {
403 *ctl &= ~B43_PIO8_TXCTL_8_15;
404 ctl_changed = 1;
405 }
406 if (i + 2 < data_len) {
407 value |= (u32)(data[i + 2]) << 16;
408 } else {
409 *ctl &= ~B43_PIO8_TXCTL_16_23;
410 ctl_changed = 1;
411 }
412 if (i + 3 < data_len) {
413 value |= (u32)(data[i + 3]) << 24;
414 } else {
415 *ctl &= ~B43_PIO8_TXCTL_24_31;
416 ctl_changed = 1;
417 }
418 if (ctl_changed)
419 b43_piotx_write32(q, B43_PIO8_TXCTL, *ctl);
420 b43_piotx_write32(q, B43_PIO8_TXDATA, value);
421 }
422}
423
424static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack,
425 const u8 *hdr, unsigned int hdrlen)
426{
427 struct b43_pio_txqueue *q = pack->queue;
428 const char *frame = pack->skb->data;
429 unsigned int frame_len = pack->skb->len;
430 u32 ctl;
431
432 ctl = b43_piotx_read32(q, B43_PIO8_TXCTL);
433 ctl |= B43_PIO8_TXCTL_FREADY;
434 ctl &= ~B43_PIO8_TXCTL_EOF;
435
436 /* Transfer the header data. */
437 tx_write_4byte_queue(q, &ctl, hdr, hdrlen);
438 /* Transfer the frame data. */
439 tx_write_4byte_queue(q, &ctl, frame, frame_len);
440
441 ctl |= B43_PIO8_TXCTL_EOF;
442 b43_piotx_write32(q, B43_PIO_TXCTL, ctl);
443}
444
445static int pio_tx_frame(struct b43_pio_txqueue *q,
446 struct sk_buff *skb,
447 struct ieee80211_tx_control *ctl)
448{
449 struct b43_pio_txpacket *pack;
450 struct b43_txhdr txhdr;
451 u16 cookie;
452 int err;
453 unsigned int hdrlen;
454
455 B43_WARN_ON(list_empty(&q->packets_list));
456 pack = list_entry(q->packets_list.next,
457 struct b43_pio_txpacket, list);
458 memset(&pack->txstat, 0, sizeof(pack->txstat));
459 memcpy(&pack->txstat.control, ctl, sizeof(*ctl));
460
461 cookie = generate_cookie(q, pack);
462 hdrlen = b43_txhdr_size(q->dev);
463 err = b43_generate_txhdr(q->dev, (u8 *)&txhdr, skb->data,
464 skb->len, ctl, cookie);
465 if (err)
466 return err;
467
468 if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) {
469 /* Tell the firmware about the cookie of the last
470 * mcast frame, so it can clear the more-data bit in it. */
471 b43_shm_write16(q->dev, B43_SHM_SHARED,
472 B43_SHM_SH_MCASTCOOKIE, cookie);
473 }
474
475 pack->skb = skb;
476 if (q->rev >= 8)
477 pio_tx_frame_4byte_queue(pack, (const u8 *)&txhdr, hdrlen);
478 else
479 pio_tx_frame_2byte_queue(pack, (const u8 *)&txhdr, hdrlen);
480
481 /* Remove it from the list of available packet slots.
482 * It will be put back when we receive the status report. */
483 list_del(&pack->list);
484
485 /* Update the queue statistics. */
486 q->buffer_used += roundup(skb->len + hdrlen, 4);
487 q->free_packet_slots -= 1;
488
489 return 0;
490}
491
492int b43_pio_tx(struct b43_wldev *dev,
493 struct sk_buff *skb, struct ieee80211_tx_control *ctl)
494{
495 struct b43_pio_txqueue *q;
496 struct ieee80211_hdr *hdr;
497 unsigned long flags;
498 unsigned int hdrlen, total_len;
499 int err = 0;
500
501 hdr = (struct ieee80211_hdr *)skb->data;
502 if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) {
503 /* The multicast queue will be sent after the DTIM. */
504 q = dev->pio.tx_queue_mcast;
505 /* Set the frame More-Data bit. Ucode will clear it
506 * for us on the last frame. */
507 hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
508 } else {
509 /* Decide by priority where to put this frame. */
510 q = select_queue_by_priority(dev, ctl->queue);
511 }
512
513 spin_lock_irqsave(&q->lock, flags);
514
515 hdrlen = b43_txhdr_size(dev);
516 total_len = roundup(skb->len + hdrlen, 4);
517
518 if (unlikely(total_len > q->buffer_size)) {
519 err = -ENOBUFS;
520 b43dbg(dev->wl, "PIO: TX packet longer than queue.\n");
521 goto out_unlock;
522 }
523 if (unlikely(q->free_packet_slots == 0)) {
524 err = -ENOBUFS;
525 b43warn(dev->wl, "PIO: TX packet overflow.\n");
526 goto out_unlock;
527 }
528 B43_WARN_ON(q->buffer_used > q->buffer_size);
529
530 if (total_len > (q->buffer_size - q->buffer_used)) {
531 /* Not enough memory on the queue. */
532 err = -EBUSY;
533 ieee80211_stop_queue(dev->wl->hw, ctl->queue);
534 q->stopped = 1;
535 goto out_unlock;
536 }
537
538 /* Assign the queue number to the ring (if not already done before)
539 * so TX status handling can use it. The mac80211-queue to b43-queue
540 * mapping is static, so we don't need to store it per frame. */
541 q->queue_prio = ctl->queue;
542
543 err = pio_tx_frame(q, skb, ctl);
544 if (unlikely(err == -ENOKEY)) {
545 /* Drop this packet, as we don't have the encryption key
546 * anymore and must not transmit it unencrypted. */
547 dev_kfree_skb_any(skb);
548 err = 0;
549 goto out_unlock;
550 }
551 if (unlikely(err)) {
552 b43err(dev->wl, "PIO transmission failure\n");
553 goto out_unlock;
554 }
555 q->nr_tx_packets++;
556
557 B43_WARN_ON(q->buffer_used > q->buffer_size);
558 if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) ||
559 (q->free_packet_slots == 0)) {
560 /* The queue is full. */
561 ieee80211_stop_queue(dev->wl->hw, ctl->queue);
562 q->stopped = 1;
563 }
564
565out_unlock:
566 spin_unlock_irqrestore(&q->lock, flags);
567
568 return err;
569}
570
571/* Called with IRQs disabled. */
572void b43_pio_handle_txstatus(struct b43_wldev *dev,
573 const struct b43_txstatus *status)
574{
575 struct b43_pio_txqueue *q;
576 struct b43_pio_txpacket *pack = NULL;
577 unsigned int total_len;
578
579 q = parse_cookie(dev, status->cookie, &pack);
580 if (unlikely(!q))
581 return;
582 B43_WARN_ON(!pack);
583
584 spin_lock(&q->lock); /* IRQs are already disabled. */
585
586 b43_fill_txstatus_report(&(pack->txstat), status);
587
588 total_len = pack->skb->len + b43_txhdr_size(dev);
589 total_len = roundup(total_len, 4);
590 q->buffer_used -= total_len;
591 q->free_packet_slots += 1;
592
593 ieee80211_tx_status_irqsafe(dev->wl->hw, pack->skb,
594 &(pack->txstat));
595 pack->skb = NULL;
596 list_add(&pack->list, &q->packets_list);
597
598 if (q->stopped) {
599 ieee80211_wake_queue(dev->wl->hw, q->queue_prio);
600 q->stopped = 0;
601 }
602
603 spin_unlock(&q->lock);
604}
605
606void b43_pio_get_tx_stats(struct b43_wldev *dev,
607 struct ieee80211_tx_queue_stats *stats)
608{
609 const int nr_queues = dev->wl->hw->queues;
610 struct b43_pio_txqueue *q;
611 struct ieee80211_tx_queue_stats_data *data;
612 unsigned long flags;
613 int i;
614
615 for (i = 0; i < nr_queues; i++) {
616 data = &(stats->data[i]);
617 q = select_queue_by_priority(dev, i);
618
619 spin_lock_irqsave(&q->lock, flags);
620 data->len = B43_PIO_MAX_NR_TXPACKETS - q->free_packet_slots;
621 data->limit = B43_PIO_MAX_NR_TXPACKETS;
622 data->count = q->nr_tx_packets;
623 spin_unlock_irqrestore(&q->lock, flags);
624 }
625}
626
627/* Returns whether we should fetch another frame. */
628static bool pio_rx_frame(struct b43_pio_rxqueue *q)
629{
630 struct b43_rxhdr_fw4 rxhdr;
631 u16 len;
632 u32 macstat;
633 unsigned int i, padding;
634 struct sk_buff *skb;
635 const char *err_msg = NULL;
636
637 memset(&rxhdr, 0, sizeof(rxhdr));
638
639 /* Check if we have data and wait for it to get ready. */
640 if (q->rev >= 8) {
641 u32 ctl;
642
643 ctl = b43_piorx_read32(q, B43_PIO8_RXCTL);
644 if (!(ctl & B43_PIO8_RXCTL_FRAMERDY))
645 return 0;
646 b43_piorx_write32(q, B43_PIO8_RXCTL,
647 B43_PIO8_RXCTL_FRAMERDY);
648 for (i = 0; i < 10; i++) {
649 ctl = b43_piorx_read32(q, B43_PIO8_RXCTL);
650 if (ctl & B43_PIO8_RXCTL_DATARDY)
651 goto data_ready;
652 udelay(10);
653 }
654 } else {
655 u16 ctl;
656
657 ctl = b43_piorx_read16(q, B43_PIO_RXCTL);
658 if (!(ctl & B43_PIO_RXCTL_FRAMERDY))
659 return 0;
660 b43_piorx_write16(q, B43_PIO_RXCTL,
661 B43_PIO_RXCTL_FRAMERDY);
662 for (i = 0; i < 10; i++) {
663 ctl = b43_piorx_read16(q, B43_PIO_RXCTL);
664 if (ctl & B43_PIO_RXCTL_DATARDY)
665 goto data_ready;
666 udelay(10);
667 }
668 }
669 b43dbg(q->dev->wl, "PIO RX timed out\n");
670 return 1;
671data_ready:
672
673 /* Get the preamble (RX header) */
674 if (q->rev >= 8) {
675 u32 *preamble = (u32 *)&rxhdr;
676 u32 value;
677
678 for (i = 0; i < sizeof(rxhdr); i += 4) {
679 value = b43_piorx_read32(q, B43_PIO8_RXDATA);
680 preamble[i / 4] = cpu_to_le32(value);
681 }
682 } else {
683 u16 *preamble = (u16 *)&rxhdr;
684 u16 value;
685
686 for (i = 0; i < sizeof(rxhdr); i += 2) {
687 value = b43_piorx_read16(q, B43_PIO_RXDATA);
688 preamble[i / 2] = cpu_to_le16(value);
689 }
690 }
691 /* Sanity checks. */
692 len = le16_to_cpu(rxhdr.frame_len);
693 if (unlikely(len > 0x700)) {
694 err_msg = "len > 0x700";
695 goto rx_error;
696 }
697 if (unlikely(len == 0)) {
698 err_msg = "len == 0";
699 goto rx_error;
700 }
701
702 macstat = le32_to_cpu(rxhdr.mac_status);
703 if (macstat & B43_RX_MAC_FCSERR) {
704 if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) {
705 /* Drop frames with failed FCS. */
706 err_msg = "Frame FCS error";
707 goto rx_error;
708 }
709 }
710
711 /* We always pad 2 bytes, as that's what upstream code expects
712 * due to the RX-header being 30 bytes. In case the frame is
713 * unaligned, we pad another 2 bytes. */
714 padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0;
715 skb = dev_alloc_skb(len + padding + 2);
716 if (unlikely(!skb)) {
717 err_msg = "Out of memory";
718 goto rx_error;
719 }
720 skb_reserve(skb, 2);
721 skb_put(skb, len + padding);
722 if (q->rev >= 8) {
723 u32 value;
724
725 for (i = padding; i < len + padding; i += 4) {
726 value = b43_piorx_read32(q, B43_PIO8_RXDATA);
727 skb->data[i] = value;
728 if ((i + 1) < (len + padding))
729 skb->data[i + 1] = value >> 8;
730 if ((i + 2) < (len + padding))
731 skb->data[i + 2] = value >> 16;
732 if ((i + 3) < (len + padding))
733 skb->data[i + 3] = value >> 24;
734 }
735 } else {
736 u16 value;
737
738 for (i = padding; i < len + padding; i += 2) {
739 value = b43_piorx_read16(q, B43_PIO_RXDATA);
740 skb->data[i] = value;
741 if ((i + 1) < (len + padding))
742 skb->data[i + 1] = value >> 8;
743 }
744 }
745
746 b43_rx(q->dev, skb, &rxhdr);
747
748 return 1;
749
750rx_error:
751 if (err_msg)
752 b43dbg(q->dev->wl, "PIO RX error: %s\n", err_msg);
753 b43_piorx_write16(q, B43_PIO_RXCTL, B43_PIO_RXCTL_DATARDY);
754 return 1;
755}
756
757/* RX workqueue. We can sleep, yay! */
758static void b43_pio_rx_work(struct work_struct *work)
759{
760 struct b43_pio_rxqueue *q = container_of(work, struct b43_pio_rxqueue,
761 rx_work);
762 unsigned int budget = 50;
763 bool stop;
764
765 do {
766 spin_lock_irq(&q->lock);
767 stop = (pio_rx_frame(q) == 0);
768 spin_unlock_irq(&q->lock);
769 cond_resched();
770 if (stop)
771 break;
772 } while (--budget);
773}
774
775/* Called with IRQs disabled. */
776void b43_pio_rx(struct b43_pio_rxqueue *q)
777{
778 /* Due to latency issues we must run the RX path in
779 * a workqueue to be able to schedule between packets. */
780 queue_work(q->dev->wl->hw->workqueue, &q->rx_work);
781}
782
783static void b43_pio_tx_suspend_queue(struct b43_pio_txqueue *q)
784{
785 unsigned long flags;
786
787 spin_lock_irqsave(&q->lock, flags);
788 if (q->rev >= 8) {
789 b43_piotx_write32(q, B43_PIO8_TXCTL,
790 b43_piotx_read32(q, B43_PIO8_TXCTL)
791 | B43_PIO8_TXCTL_SUSPREQ);
792 } else {
793 b43_piotx_write16(q, B43_PIO_TXCTL,
794 b43_piotx_read16(q, B43_PIO_TXCTL)
795 | B43_PIO_TXCTL_SUSPREQ);
796 }
797 spin_unlock_irqrestore(&q->lock, flags);
798}
799
800static void b43_pio_tx_resume_queue(struct b43_pio_txqueue *q)
801{
802 unsigned long flags;
803
804 spin_lock_irqsave(&q->lock, flags);
805 if (q->rev >= 8) {
806 b43_piotx_write32(q, B43_PIO8_TXCTL,
807 b43_piotx_read32(q, B43_PIO8_TXCTL)
808 & ~B43_PIO8_TXCTL_SUSPREQ);
809 } else {
810 b43_piotx_write16(q, B43_PIO_TXCTL,
811 b43_piotx_read16(q, B43_PIO_TXCTL)
812 & ~B43_PIO_TXCTL_SUSPREQ);
813 }
814 spin_unlock_irqrestore(&q->lock, flags);
815}
816
817void b43_pio_tx_suspend(struct b43_wldev *dev)
818{
819 b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
820 b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_BK);
821 b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_BE);
822 b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_VI);
823 b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_VO);
824 b43_pio_tx_suspend_queue(dev->pio.tx_queue_mcast);
825}
826
827void b43_pio_tx_resume(struct b43_wldev *dev)
828{
829 b43_pio_tx_resume_queue(dev->pio.tx_queue_mcast);
830 b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_VO);
831 b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_VI);
832 b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_BE);
833 b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_BK);
834 b43_power_saving_ctl_bits(dev, 0);
835}
diff --git a/drivers/net/wireless/b43/pio.h b/drivers/net/wireless/b43/pio.h
new file mode 100644
index 000000000000..e2ec676cc9e4
--- /dev/null
+++ b/drivers/net/wireless/b43/pio.h
@@ -0,0 +1,220 @@
1#ifndef B43_PIO_H_
2#define B43_PIO_H_
3
4#include "b43.h"
5
6#include <linux/interrupt.h>
7#include <linux/io.h>
8#include <linux/list.h>
9#include <linux/skbuff.h>
10
11
12/*** Registers for PIO queues up to revision 7. ***/
13/* TX queue. */
14#define B43_PIO_TXCTL 0x00
15#define B43_PIO_TXCTL_WRITELO 0x0001
16#define B43_PIO_TXCTL_WRITEHI 0x0002
17#define B43_PIO_TXCTL_EOF 0x0004
18#define B43_PIO_TXCTL_FREADY 0x0008
19#define B43_PIO_TXCTL_FLUSHREQ 0x0020
20#define B43_PIO_TXCTL_FLUSHPEND 0x0040
21#define B43_PIO_TXCTL_SUSPREQ 0x0080
22#define B43_PIO_TXCTL_QSUSP 0x0100
23#define B43_PIO_TXCTL_COMMCNT 0xFC00
24#define B43_PIO_TXCTL_COMMCNT_SHIFT 10
25#define B43_PIO_TXDATA 0x02
26#define B43_PIO_TXQBUFSIZE 0x04
27/* RX queue. */
28#define B43_PIO_RXCTL 0x00
29#define B43_PIO_RXCTL_FRAMERDY 0x0001
30#define B43_PIO_RXCTL_DATARDY 0x0002
31#define B43_PIO_RXDATA 0x02
32
33/*** Registers for PIO queues revision 8 and later. ***/
34/* TX queue */
35#define B43_PIO8_TXCTL 0x00
36#define B43_PIO8_TXCTL_0_7 0x00000001
37#define B43_PIO8_TXCTL_8_15 0x00000002
38#define B43_PIO8_TXCTL_16_23 0x00000004
39#define B43_PIO8_TXCTL_24_31 0x00000008
40#define B43_PIO8_TXCTL_EOF 0x00000010
41#define B43_PIO8_TXCTL_FREADY 0x00000080
42#define B43_PIO8_TXCTL_SUSPREQ 0x00000100
43#define B43_PIO8_TXCTL_QSUSP 0x00000200
44#define B43_PIO8_TXCTL_FLUSHREQ 0x00000400
45#define B43_PIO8_TXCTL_FLUSHPEND 0x00000800
46#define B43_PIO8_TXDATA 0x04
47/* RX queue */
48#define B43_PIO8_RXCTL 0x00
49#define B43_PIO8_RXCTL_FRAMERDY 0x00000001
50#define B43_PIO8_RXCTL_DATARDY 0x00000002
51#define B43_PIO8_RXDATA 0x04
52
53
54/* The maximum number of TX-packets the HW can handle. */
55#define B43_PIO_MAX_NR_TXPACKETS 32
56
57
58#ifdef CONFIG_B43_PIO
59
60struct b43_pio_txpacket {
61 /* Pointer to the TX queue we belong to. */
62 struct b43_pio_txqueue *queue;
63 /* The TX data packet. */
64 struct sk_buff *skb;
65 /* The status meta data. */
66 struct ieee80211_tx_status txstat;
67 /* Index in the (struct b43_pio_txqueue)->packets array. */
68 u8 index;
69
70 struct list_head list;
71};
72
73struct b43_pio_txqueue {
74 struct b43_wldev *dev;
75 spinlock_t lock;
76 u16 mmio_base;
77
78 /* The device queue buffer size in bytes. */
79 u16 buffer_size;
80 /* The number of used bytes in the device queue buffer. */
81 u16 buffer_used;
82 /* The number of packets that can still get queued.
83 * This is decremented on queueing a packet and incremented
84 * after receiving the transmit status. */
85 u16 free_packet_slots;
86
87 /* True, if the mac80211 queue was stopped due to overflow at TX. */
88 bool stopped;
89 /* Our b43 queue index number */
90 u8 index;
91 /* The mac80211 QoS queue priority. */
92 u8 queue_prio;
93
94 /* Buffer for TX packet meta data. */
95 struct b43_pio_txpacket packets[B43_PIO_MAX_NR_TXPACKETS];
96 struct list_head packets_list;
97
98 /* Total number of transmitted packets. */
99 unsigned int nr_tx_packets;
100
101 /* Shortcut to the 802.11 core revision. This is to
102 * avoid horrible pointer dereferencing in the fastpaths. */
103 u8 rev;
104};
105
106struct b43_pio_rxqueue {
107 struct b43_wldev *dev;
108 spinlock_t lock;
109 u16 mmio_base;
110
111 /* Work to reduce latency issues on RX. */
112 struct work_struct rx_work;
113
114 /* Shortcut to the 802.11 core revision. This is to
115 * avoid horrible pointer dereferencing in the fastpaths. */
116 u8 rev;
117};
118
119
120static inline u16 b43_piotx_read16(struct b43_pio_txqueue *q, u16 offset)
121{
122 return b43_read16(q->dev, q->mmio_base + offset);
123}
124
125static inline u32 b43_piotx_read32(struct b43_pio_txqueue *q, u16 offset)
126{
127 return b43_read32(q->dev, q->mmio_base + offset);
128}
129
130static inline void b43_piotx_write16(struct b43_pio_txqueue *q,
131 u16 offset, u16 value)
132{
133 b43_write16(q->dev, q->mmio_base + offset, value);
134}
135
136static inline void b43_piotx_write32(struct b43_pio_txqueue *q,
137 u16 offset, u32 value)
138{
139 b43_write32(q->dev, q->mmio_base + offset, value);
140}
141
142
143static inline u16 b43_piorx_read16(struct b43_pio_rxqueue *q, u16 offset)
144{
145 return b43_read16(q->dev, q->mmio_base + offset);
146}
147
148static inline u32 b43_piorx_read32(struct b43_pio_rxqueue *q, u16 offset)
149{
150 return b43_read32(q->dev, q->mmio_base + offset);
151}
152
153static inline void b43_piorx_write16(struct b43_pio_rxqueue *q,
154 u16 offset, u16 value)
155{
156 b43_write16(q->dev, q->mmio_base + offset, value);
157}
158
159static inline void b43_piorx_write32(struct b43_pio_rxqueue *q,
160 u16 offset, u32 value)
161{
162 b43_write32(q->dev, q->mmio_base + offset, value);
163}
164
165
166int b43_pio_init(struct b43_wldev *dev);
167void b43_pio_stop(struct b43_wldev *dev);
168void b43_pio_free(struct b43_wldev *dev);
169
170int b43_pio_tx(struct b43_wldev *dev,
171 struct sk_buff *skb, struct ieee80211_tx_control *ctl);
172void b43_pio_handle_txstatus(struct b43_wldev *dev,
173 const struct b43_txstatus *status);
174void b43_pio_get_tx_stats(struct b43_wldev *dev,
175 struct ieee80211_tx_queue_stats *stats);
176void b43_pio_rx(struct b43_pio_rxqueue *q);
177
178void b43_pio_tx_suspend(struct b43_wldev *dev);
179void b43_pio_tx_resume(struct b43_wldev *dev);
180
181
182#else /* CONFIG_B43_PIO */
183
184
185static inline int b43_pio_init(struct b43_wldev *dev)
186{
187 return 0;
188}
189static inline void b43_pio_free(struct b43_wldev *dev)
190{
191}
192static inline void b43_pio_stop(struct b43_wldev *dev)
193{
194}
195static inline int b43_pio_tx(struct b43_wldev *dev,
196 struct sk_buff *skb,
197 struct ieee80211_tx_control *ctl)
198{
199 return 0;
200}
201static inline void b43_pio_handle_txstatus(struct b43_wldev *dev,
202 const struct b43_txstatus *status)
203{
204}
205static inline void b43_pio_get_tx_stats(struct b43_wldev *dev,
206 struct ieee80211_tx_queue_stats *stats)
207{
208}
209static inline void b43_pio_rx(struct b43_pio_rxqueue *q)
210{
211}
212static inline void b43_pio_tx_suspend(struct b43_wldev *dev)
213{
214}
215static inline void b43_pio_tx_resume(struct b43_wldev *dev)
216{
217}
218
219#endif /* CONFIG_B43_PIO */
220#endif /* B43_PIO_H_ */
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index ec10a8e182f9..b2a3123f42db 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -30,6 +30,7 @@
30#include "xmit.h" 30#include "xmit.h"
31#include "phy.h" 31#include "phy.h"
32#include "dma.h" 32#include "dma.h"
33#include "pio.h"
33 34
34 35
35/* Extract the bitrate index out of a CCK PLCP header. */ 36/* Extract the bitrate index out of a CCK PLCP header. */
@@ -668,40 +669,54 @@ void b43_handle_txstatus(struct b43_wldev *dev,
668 dev->wl->ieee_stats.dot11RTSSuccessCount++; 669 dev->wl->ieee_stats.dot11RTSSuccessCount++;
669 } 670 }
670 671
671 b43_dma_handle_txstatus(dev, status); 672 if (b43_using_pio_transfers(dev))
673 b43_pio_handle_txstatus(dev, status);
674 else
675 b43_dma_handle_txstatus(dev, status);
672} 676}
673 677
674/* Handle TX status report as received through DMA/PIO queues */ 678/* Fill out the mac80211 TXstatus report based on the b43-specific
675void b43_handle_hwtxstatus(struct b43_wldev *dev, 679 * txstatus report data. This returns a boolean whether the frame was
676 const struct b43_hwtxstatus *hw) 680 * successfully transmitted. */
681bool b43_fill_txstatus_report(struct ieee80211_tx_status *report,
682 const struct b43_txstatus *status)
677{ 683{
678 struct b43_txstatus status; 684 bool frame_success = 1;
679 u8 tmp; 685
680 686 if (status->acked) {
681 status.cookie = le16_to_cpu(hw->cookie); 687 /* The frame was ACKed. */
682 status.seq = le16_to_cpu(hw->seq); 688 report->flags |= IEEE80211_TX_STATUS_ACK;
683 status.phy_stat = hw->phy_stat; 689 } else {
684 tmp = hw->count; 690 /* The frame was not ACKed... */
685 status.frame_count = (tmp >> 4); 691 if (!(report->control.flags & IEEE80211_TXCTL_NO_ACK)) {
686 status.rts_count = (tmp & 0x0F); 692 /* ...but we expected an ACK. */
687 tmp = hw->flags; 693 frame_success = 0;
688 status.supp_reason = ((tmp & 0x1C) >> 2); 694 report->excessive_retries = 1;
689 status.pm_indicated = !!(tmp & 0x80); 695 }
690 status.intermediate = !!(tmp & 0x40); 696 }
691 status.for_ampdu = !!(tmp & 0x20); 697 if (status->frame_count == 0) {
692 status.acked = !!(tmp & 0x02); 698 /* The frame was not transmitted at all. */
693 699 report->retry_count = 0;
694 b43_handle_txstatus(dev, &status); 700 } else
701 report->retry_count = status->frame_count - 1;
702
703 return frame_success;
695} 704}
696 705
697/* Stop any TX operation on the device (suspend the hardware queues) */ 706/* Stop any TX operation on the device (suspend the hardware queues) */
698void b43_tx_suspend(struct b43_wldev *dev) 707void b43_tx_suspend(struct b43_wldev *dev)
699{ 708{
700 b43_dma_tx_suspend(dev); 709 if (b43_using_pio_transfers(dev))
710 b43_pio_tx_suspend(dev);
711 else
712 b43_dma_tx_suspend(dev);
701} 713}
702 714
703/* Resume any TX operation on the device (resume the hardware queues) */ 715/* Resume any TX operation on the device (resume the hardware queues) */
704void b43_tx_resume(struct b43_wldev *dev) 716void b43_tx_resume(struct b43_wldev *dev)
705{ 717{
706 b43_dma_tx_resume(dev); 718 if (b43_using_pio_transfers(dev))
719 b43_pio_tx_resume(dev);
720 else
721 b43_dma_tx_resume(dev);
707} 722}
diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h
index bf58a8a85258..4f26988a5132 100644
--- a/drivers/net/wireless/b43/xmit.h
+++ b/drivers/net/wireless/b43/xmit.h
@@ -207,18 +207,6 @@ enum {
207 B43_TXST_SUPP_ABNACK, /* Afterburner NACK */ 207 B43_TXST_SUPP_ABNACK, /* Afterburner NACK */
208}; 208};
209 209
210/* Transmit Status as received through DMA/PIO on old chips */
211struct b43_hwtxstatus {
212 PAD_BYTES(4);
213 __le16 cookie;
214 u8 flags;
215 u8 count;
216 PAD_BYTES(2);
217 __le16 seq;
218 u8 phy_stat;
219 PAD_BYTES(1);
220} __attribute__ ((__packed__));
221
222/* Receive header for v4 firmware. */ 210/* Receive header for v4 firmware. */
223struct b43_rxhdr_fw4 { 211struct b43_rxhdr_fw4 {
224 __le16 frame_len; /* Frame length */ 212 __le16 frame_len; /* Frame length */
@@ -295,9 +283,8 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr);
295 283
296void b43_handle_txstatus(struct b43_wldev *dev, 284void b43_handle_txstatus(struct b43_wldev *dev,
297 const struct b43_txstatus *status); 285 const struct b43_txstatus *status);
298 286bool b43_fill_txstatus_report(struct ieee80211_tx_status *report,
299void b43_handle_hwtxstatus(struct b43_wldev *dev, 287 const struct b43_txstatus *status);
300 const struct b43_hwtxstatus *hw);
301 288
302void b43_tx_suspend(struct b43_wldev *dev); 289void b43_tx_suspend(struct b43_wldev *dev);
303void b43_tx_resume(struct b43_wldev *dev); 290void b43_tx_resume(struct b43_wldev *dev);