aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorMichael Buesch <mbuesch@freenet.de>2006-02-12 10:47:44 -0500
committerJohn W. Linville <linville@tuxdriver.com>2006-03-27 11:18:32 -0500
commit77db31ea4322f2dd12dc814d6664ae96517604c0 (patch)
tree358519550cf715249ba836d06eb651d1fdf86079 /drivers/net
parent5c57807afcc28a6b8fb579ef2c79e49f0b688425 (diff)
[PATCH] bcm43xx: Partially fix PIO code. Add Kconfig option for PIO or DMA mode (or both).
Signed-off-by: Michael Buesch <mbuesch@freenet.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/Kconfig18
-rw-r--r--drivers/net/wireless/bcm43xx/Kconfig57
-rw-r--r--drivers/net/wireless/bcm43xx/Makefile6
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx.h29
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_dma.h46
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c69
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_pio.c383
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_pio.h78
8 files changed, 438 insertions, 248 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 3b1363c97191..5c4d7b4ece5e 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -500,23 +500,7 @@ config PRISM54
500 will be called prism54.ko. 500 will be called prism54.ko.
501 501
502source "drivers/net/wireless/hostap/Kconfig" 502source "drivers/net/wireless/hostap/Kconfig"
503 503source "drivers/net/wireless/bcm43xx/Kconfig"
504config BCM43XX
505 tristate "Broadcom BCM43xx wireless support"
506 depends on PCI && IEEE80211 && NET_RADIO && IEEE80211_SOFTMAC && EXPERIMENTAL
507 select FW_LOADER
508 ---help---
509 This is an experimental driver for the Broadcom 43xx wireless chip,
510 found in the Apple Airport Extreme and various other devices.
511
512config BCM43XX_DEBUG
513 bool "Broadcom BCM43xx debugging (RECOMMENDED)"
514 depends on BCM43XX
515 default y
516 ---help---
517 Broadcom 43xx debugging messages.
518 Say Y, because the driver is still very experimental and
519 this will help you get it running.
520 504
521# yes, this works even when no drivers are selected 505# yes, this works even when no drivers are selected
522config NET_WIRELESS 506config NET_WIRELESS
diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig
new file mode 100644
index 000000000000..d8d23155ee3c
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/Kconfig
@@ -0,0 +1,57 @@
1config BCM43XX
2 tristate "Broadcom BCM43xx wireless support"
3 depends on PCI && IEEE80211 && IEEE80211_SOFTMAC && NET_RADIO && EXPERIMENTAL
4 select FW_LOADER
5 ---help---
6 This is an experimental driver for the Broadcom 43xx wireless chip,
7 found in the Apple Airport Extreme and various other devices.
8
9config BCM43XX_DEBUG
10 bool "Broadcom BCM43xx debugging (RECOMMENDED)"
11 depends on BCM43XX
12 default y
13 ---help---
14 Broadcom 43xx debugging messages.
15 Say Y, because the driver is still very experimental and
16 this will help you get it running.
17
18config BCM43XX_DMA
19 bool
20config BCM43XX_PIO
21 bool
22
23choice
24 prompt "BCM43xx data transfer mode"
25 depends on BCM43XX
26 default BCM43XX_DMA_AND_PIO
27
28config BCM43XX_DMA_AND_PIO_MODE
29 bool "DMA + PIO"
30 select BCM43XX_DMA
31 select BCM43XX_PIO
32 ---help---
33 Include both, Direct Memory Access (DMA) and Programmed I/O (PIO)
34 data transfer modes.
35 The actually used mode is selectable through the module
36 parameter "pio". If the module parameter is pio=0, DMA is used.
37 Otherwise PIO is used. DMA is default.
38
39 If unsure, choose this option.
40
41config BCM43XX_DMA_MODE
42 bool "DMA (Direct Memory Access) only"
43 select BCM43XX_DMA
44 ---help---
45 Only include Direct Memory Access (DMA).
46 This reduces the size of the driver module, by omitting the PIO code.
47
48config BCM43XX_PIO_MODE
49 bool "PIO (Programmed I/O) only"
50 select BCM43XX_PIO
51 ---help---
52 Only include Programmed I/O (PIO).
53 This reduces the size of the driver module, by omitting the DMA code.
54 Please note that PIO transfers are slow (compared to DMA).
55 Only use PIO, if DMA does not work for you.
56
57endchoice
diff --git a/drivers/net/wireless/bcm43xx/Makefile b/drivers/net/wireless/bcm43xx/Makefile
index e025e9f052b2..c87c1525b39f 100644
--- a/drivers/net/wireless/bcm43xx/Makefile
+++ b/drivers/net/wireless/bcm43xx/Makefile
@@ -1,9 +1,11 @@
1obj-$(CONFIG_BCM43XX) += bcm43xx.o 1obj-$(CONFIG_BCM43XX) += bcm43xx.o
2bcm43xx-obj-$(CONFIG_BCM43XX_DEBUG) += bcm43xx_debugfs.o 2bcm43xx-obj-$(CONFIG_BCM43XX_DEBUG) += bcm43xx_debugfs.o
3 3
4bcm43xx-objs := bcm43xx_main.o bcm43xx_dma.o \ 4bcm43xx-obj-$(CONFIG_BCM43XX_DMA) += bcm43xx_dma.o
5bcm43xx-obj-$(CONFIG_BCM43XX_PIO) += bcm43xx_pio.o
6
7bcm43xx-objs := bcm43xx_main.o bcm43xx_ilt.o \
5 bcm43xx_radio.o bcm43xx_phy.o \ 8 bcm43xx_radio.o bcm43xx_phy.o \
6 bcm43xx_power.o bcm43xx_wx.o \ 9 bcm43xx_power.o bcm43xx_wx.o \
7 bcm43xx_pio.o bcm43xx_ilt.o \
8 bcm43xx_leds.o bcm43xx_ethtool.o \ 10 bcm43xx_leds.o bcm43xx_ethtool.o \
9 $(bcm43xx-obj-y) 11 $(bcm43xx-obj-y)
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index 981d563f5738..3d8ac7e952cc 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -639,7 +639,7 @@ struct bcm43xx_private {
639 u32 initialized:1, /* init_board() succeed */ 639 u32 initialized:1, /* init_board() succeed */
640 was_initialized:1, /* for PCI suspend/resume. */ 640 was_initialized:1, /* for PCI suspend/resume. */
641 shutting_down:1, /* free_board() in progress */ 641 shutting_down:1, /* free_board() in progress */
642 pio_mode:1, /* PIO (if true), or DMA (if false) used. */ 642 __using_pio:1, /* Internal, use bcm43xx_using_pio(). */
643 bad_frames_preempt:1, /* Use "Bad Frames Preemption" (default off) */ 643 bad_frames_preempt:1, /* Use "Bad Frames Preemption" (default off) */
644 reg124_set_0x4:1, /* Some variable to keep track of IRQ stuff. */ 644 reg124_set_0x4:1, /* Some variable to keep track of IRQ stuff. */
645 powersaving:1, /* TRUE if we are in PowerSaving mode. FALSE otherwise. */ 645 powersaving:1, /* TRUE if we are in PowerSaving mode. FALSE otherwise. */
@@ -749,6 +749,33 @@ struct bcm43xx_private * bcm43xx_priv(struct net_device *dev)
749 return ieee80211softmac_priv(dev); 749 return ieee80211softmac_priv(dev);
750} 750}
751 751
752
753/* Helper function, which returns a boolean.
754 * TRUE, if PIO is used; FALSE, if DMA is used.
755 */
756#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO)
757static inline
758int bcm43xx_using_pio(struct bcm43xx_private *bcm)
759{
760 return bcm->__using_pio;
761}
762#elif defined(CONFIG_BCM43XX_DMA)
763static inline
764int bcm43xx_using_pio(struct bcm43xx_private *bcm)
765{
766 return 0;
767}
768#elif defined(CONFIG_BCM43XX_PIO)
769static inline
770int bcm43xx_using_pio(struct bcm43xx_private *bcm)
771{
772 return 1;
773}
774#else
775# error "Using neither DMA nor PIO? Confused..."
776#endif
777
778
752static inline 779static inline
753int bcm43xx_num_80211_cores(struct bcm43xx_private *bcm) 780int bcm43xx_num_80211_cores(struct bcm43xx_private *bcm)
754{ 781{
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
index 93e99d61f2e1..88ad34dff2f2 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
@@ -94,6 +94,10 @@
94#define BCM43xx_TXRESUME_PERCENT 50 94#define BCM43xx_TXRESUME_PERCENT 50
95 95
96 96
97
98#ifdef CONFIG_BCM43XX_DMA
99
100
97struct sk_buff; 101struct sk_buff;
98struct bcm43xx_private; 102struct bcm43xx_private;
99struct bcm43xx_xmitstatus; 103struct bcm43xx_xmitstatus;
@@ -172,4 +176,46 @@ int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
172 struct ieee80211_txb *txb); 176 struct ieee80211_txb *txb);
173void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring); 177void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring);
174 178
179
180#else /* CONFIG_BCM43XX_DMA */
181
182
183static inline
184int bcm43xx_dma_init(struct bcm43xx_private *bcm)
185{
186 return 0;
187}
188static inline
189void bcm43xx_dma_free(struct bcm43xx_private *bcm)
190{
191}
192static inline
193int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
194 u16 dmacontroller_mmio_base)
195{
196 return 0;
197}
198static inline
199int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
200 u16 dmacontroller_mmio_base)
201{
202 return 0;
203}
204static inline
205int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
206 struct ieee80211_txb *txb)
207{
208 return 0;
209}
210static inline
211void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm,
212 struct bcm43xx_xmitstatus *status)
213{
214}
215static inline
216void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)
217{
218}
219
220#endif /* CONFIG_BCM43XX_DMA */
175#endif /* BCM43xx_DMA_H_ */ 221#endif /* BCM43xx_DMA_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 4c4a2d71ca04..4e49da99818d 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -62,10 +62,15 @@ MODULE_LICENSE("GPL");
62extern char *nvram_get(char *name); 62extern char *nvram_get(char *name);
63#endif 63#endif
64 64
65/* Module parameters */ 65#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO)
66static int modparam_pio; 66static int modparam_pio;
67module_param_named(pio, modparam_pio, int, 0444); 67module_param_named(pio, modparam_pio, int, 0444);
68MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode"); 68MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode");
69#elif defined(CONFIG_BCM43XX_DMA)
70# define modparam_pio 0
71#elif defined(CONFIG_BCM43XX_PIO)
72# define modparam_pio 1
73#endif
69 74
70static int modparam_bad_frames_preempt; 75static int modparam_bad_frames_preempt;
71module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444); 76module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
@@ -1528,7 +1533,8 @@ void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy)
1528{ 1533{
1529 u32 flags = 0x00040000; 1534 u32 flags = 0x00040000;
1530 1535
1531 if ((bcm43xx_core_enabled(bcm)) && (!bcm->pio_mode)) { 1536 if ((bcm43xx_core_enabled(bcm)) &&
1537 !bcm43xx_using_pio(bcm)) {
1532//FIXME: Do we _really_ want #ifndef CONFIG_BCM947XX here? 1538//FIXME: Do we _really_ want #ifndef CONFIG_BCM947XX here?
1533#ifndef CONFIG_BCM947XX 1539#ifndef CONFIG_BCM947XX
1534 /* reset all used DMA controllers. */ 1540 /* reset all used DMA controllers. */
@@ -1635,7 +1641,7 @@ static inline void handle_irq_transmit_status(struct bcm43xx_private *bcm)
1635 } 1641 }
1636 //TODO: There are more (unknown) flags to test. see bcm43xx_main.h 1642 //TODO: There are more (unknown) flags to test. see bcm43xx_main.h
1637 1643
1638 if (bcm->pio_mode) 1644 if (bcm43xx_using_pio(bcm))
1639 bcm43xx_pio_handle_xmitstatus(bcm, &stat); 1645 bcm43xx_pio_handle_xmitstatus(bcm, &stat);
1640 else 1646 else
1641 bcm43xx_dma_handle_xmitstatus(bcm, &stat); 1647 bcm43xx_dma_handle_xmitstatus(bcm, &stat);
@@ -1933,7 +1939,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm)
1933 assert(!(dma_reason[1] & BCM43xx_DMAIRQ_RX_DONE)); 1939 assert(!(dma_reason[1] & BCM43xx_DMAIRQ_RX_DONE));
1934 assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE)); 1940 assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE));
1935 if (dma_reason[0] & BCM43xx_DMAIRQ_RX_DONE) { 1941 if (dma_reason[0] & BCM43xx_DMAIRQ_RX_DONE) {
1936 if (bcm->pio_mode) 1942 if (bcm43xx_using_pio(bcm))
1937 bcm43xx_pio_rx(bcm->current_core->pio->queue0); 1943 bcm43xx_pio_rx(bcm->current_core->pio->queue0);
1938 else 1944 else
1939 bcm43xx_dma_rx(bcm->current_core->dma->rx_ring0); 1945 bcm43xx_dma_rx(bcm->current_core->dma->rx_ring0);
@@ -1941,7 +1947,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm)
1941 } 1947 }
1942 if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) { 1948 if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) {
1943 if (likely(bcm->current_core->rev < 5)) { 1949 if (likely(bcm->current_core->rev < 5)) {
1944 if (bcm->pio_mode) 1950 if (bcm43xx_using_pio(bcm))
1945 bcm43xx_pio_rx(bcm->current_core->pio->queue3); 1951 bcm43xx_pio_rx(bcm->current_core->pio->queue3);
1946 else 1952 else
1947 bcm43xx_dma_rx(bcm->current_core->dma->rx_ring1); 1953 bcm43xx_dma_rx(bcm->current_core->dma->rx_ring1);
@@ -1999,7 +2005,7 @@ void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm,
1999 bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON) 2005 bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON)
2000 & 0x0001dc00; 2006 & 0x0001dc00;
2001 2007
2002 if ((bcm->pio_mode) && 2008 if (bcm43xx_using_pio(bcm) &&
2003 (bcm->current_core->rev < 3) && 2009 (bcm->current_core->rev < 3) &&
2004 (!(reason & BCM43xx_IRQ_PIO_WORKAROUND))) { 2010 (!(reason & BCM43xx_IRQ_PIO_WORKAROUND))) {
2005 /* Apply a PIO specific workaround to the dma_reasons */ 2011 /* Apply a PIO specific workaround to the dma_reasons */
@@ -2624,7 +2630,7 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm)
2624 value32 |= 0x100000; //FIXME: What's this? Is this correct? 2630 value32 |= 0x100000; //FIXME: What's this? Is this correct?
2625 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); 2631 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
2626 2632
2627 if (bcm->pio_mode) { 2633 if (bcm43xx_using_pio(bcm)) {
2628 bcm43xx_write32(bcm, 0x0210, 0x00000100); 2634 bcm43xx_write32(bcm, 0x0210, 0x00000100);
2629 bcm43xx_write32(bcm, 0x0230, 0x00000100); 2635 bcm43xx_write32(bcm, 0x0230, 0x00000100);
2630 bcm43xx_write32(bcm, 0x0250, 0x00000100); 2636 bcm43xx_write32(bcm, 0x0250, 0x00000100);
@@ -3123,15 +3129,12 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm)
3123 if (bcm->current_core->rev >= 5) 3129 if (bcm->current_core->rev >= 5)
3124 bcm43xx_write16(bcm, 0x043C, 0x000C); 3130 bcm43xx_write16(bcm, 0x043C, 0x000C);
3125 3131
3126 if (!bcm->pio_mode) { 3132 if (bcm43xx_using_pio(bcm))
3127 err = bcm43xx_dma_init(bcm);
3128 if (err)
3129 goto err_chip_cleanup;
3130 } else {
3131 err = bcm43xx_pio_init(bcm); 3133 err = bcm43xx_pio_init(bcm);
3132 if (err) 3134 else
3133 goto err_chip_cleanup; 3135 err = bcm43xx_dma_init(bcm);
3134 } 3136 if (err)
3137 goto err_chip_cleanup;
3135 bcm43xx_write16(bcm, 0x0612, 0x0050); 3138 bcm43xx_write16(bcm, 0x0612, 0x0050);
3136 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050); 3139 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050);
3137 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4); 3140 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4);
@@ -4001,8 +4004,8 @@ static inline int bcm43xx_tx(struct bcm43xx_private *bcm,
4001{ 4004{
4002 int err = -ENODEV; 4005 int err = -ENODEV;
4003 4006
4004 if (bcm->pio_mode) 4007 if (bcm43xx_using_pio(bcm))
4005 err = bcm43xx_pio_transfer_txb(bcm, txb); 4008 err = bcm43xx_pio_tx(bcm, txb);
4006 else 4009 else
4007 err = bcm43xx_dma_tx(bcm, txb); 4010 err = bcm43xx_dma_tx(bcm, txb);
4008 4011
@@ -4158,10 +4161,10 @@ static int bcm43xx_net_stop(struct net_device *net_dev)
4158 return 0; 4161 return 0;
4159} 4162}
4160 4163
4161static void bcm43xx_init_private(struct bcm43xx_private *bcm, 4164static int bcm43xx_init_private(struct bcm43xx_private *bcm,
4162 struct net_device *net_dev, 4165 struct net_device *net_dev,
4163 struct pci_dev *pci_dev, 4166 struct pci_dev *pci_dev,
4164 struct workqueue_struct *wq) 4167 struct workqueue_struct *wq)
4165{ 4168{
4166 bcm->ieee = netdev_priv(net_dev); 4169 bcm->ieee = netdev_priv(net_dev);
4167 bcm->softmac = ieee80211_priv(net_dev); 4170 bcm->softmac = ieee80211_priv(net_dev);
@@ -4190,13 +4193,17 @@ static void bcm43xx_init_private(struct bcm43xx_private *bcm,
4190 (unsigned long)bcm); 4193 (unsigned long)bcm);
4191 tasklet_disable_nosync(&bcm->isr_tasklet); 4194 tasklet_disable_nosync(&bcm->isr_tasklet);
4192 if (modparam_pio) { 4195 if (modparam_pio) {
4193 bcm->pio_mode = 1; 4196 bcm->__using_pio = 1;
4194 } else { 4197 } else {
4195 if (pci_set_dma_mask(pci_dev, DMA_30BIT_MASK) == 0) { 4198 if (pci_set_dma_mask(pci_dev, DMA_30BIT_MASK)) {
4196 bcm->pio_mode = 0; 4199#ifdef CONFIG_BCM43XX_PIO
4197 } else {
4198 printk(KERN_WARNING PFX "DMA not supported. Falling back to PIO.\n"); 4200 printk(KERN_WARNING PFX "DMA not supported. Falling back to PIO.\n");
4199 bcm->pio_mode = 1; 4201 bcm->__using_pio = 1;
4202#else
4203 printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
4204 "Recompile the driver with PIO support, please.\n");
4205 return -ENODEV;
4206#endif /* CONFIG_BCM43XX_PIO */
4200 } 4207 }
4201 } 4208 }
4202 bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD; 4209 bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD;
@@ -4210,6 +4217,8 @@ static void bcm43xx_init_private(struct bcm43xx_private *bcm,
4210 bcm->ieee->tx_headroom = sizeof(struct bcm43xx_txhdr); 4217 bcm->ieee->tx_headroom = sizeof(struct bcm43xx_txhdr);
4211 bcm->ieee->set_security = bcm43xx_ieee80211_set_security; 4218 bcm->ieee->set_security = bcm43xx_ieee80211_set_security;
4212 bcm->ieee->hard_start_xmit = bcm43xx_ieee80211_hard_start_xmit; 4219 bcm->ieee->hard_start_xmit = bcm43xx_ieee80211_hard_start_xmit;
4220
4221 return 0;
4213} 4222}
4214 4223
4215static int __devinit bcm43xx_init_one(struct pci_dev *pdev, 4224static int __devinit bcm43xx_init_one(struct pci_dev *pdev,
@@ -4261,7 +4270,9 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev,
4261 err = -ENOMEM; 4270 err = -ENOMEM;
4262 goto err_free_netdev; 4271 goto err_free_netdev;
4263 } 4272 }
4264 bcm43xx_init_private(bcm, net_dev, pdev, wq); 4273 err = bcm43xx_init_private(bcm, net_dev, pdev, wq);
4274 if (err)
4275 goto err_destroy_wq;
4265 4276
4266 pci_set_drvdata(pdev, net_dev); 4277 pci_set_drvdata(pdev, net_dev);
4267 4278
@@ -4325,7 +4336,9 @@ static void bcm43xx_chip_reset(void *_bcm)
4325 bcm43xx_free_board(bcm); 4336 bcm43xx_free_board(bcm);
4326 bcm->firmware_norelease = 0; 4337 bcm->firmware_norelease = 0;
4327 bcm43xx_detach_board(bcm); 4338 bcm43xx_detach_board(bcm);
4328 bcm43xx_init_private(bcm, net_dev, pci_dev, wq); 4339 err = bcm43xx_init_private(bcm, net_dev, pci_dev, wq);
4340 if (err)
4341 goto failure;
4329 err = bcm43xx_attach_board(bcm); 4342 err = bcm43xx_attach_board(bcm);
4330 if (err) 4343 if (err)
4331 goto failure; 4344 goto failure;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
index 9a55e9d00528..0bf4b3e26f9d 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
@@ -30,81 +30,88 @@
30#include <linux/delay.h> 30#include <linux/delay.h>
31 31
32 32
33static inline 33static void tx_start(struct bcm43xx_pioqueue *queue)
34u16 bcm43xx_pio_read(struct bcm43xx_pioqueue *queue,
35 u16 offset)
36{ 34{
37 return bcm43xx_read16(queue->bcm, queue->mmio_base + offset); 35 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
36 BCM43xx_PIO_TXCTL_INIT);
38} 37}
39 38
40static inline 39static void tx_octet(struct bcm43xx_pioqueue *queue,
41void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue, 40 u8 octet)
42 u16 offset, u16 value)
43{ 41{
44 bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value); 42 if (queue->need_workarounds) {
43 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
44 octet);
45 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
46 BCM43xx_PIO_TXCTL_WRITEHI);
47 } else {
48 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
49 BCM43xx_PIO_TXCTL_WRITEHI);
50 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
51 octet);
52 }
45} 53}
46 54
47static inline 55static u16 tx_get_next_word(struct bcm43xx_txhdr *txhdr,
48void tx_start(struct bcm43xx_pioqueue *queue) 56 const u8 *packet,
57 unsigned int *pos)
49{ 58{
50 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, BCM43xx_PIO_TXCTL_INIT); 59 const u8 *source;
51} 60 unsigned int i = *pos;
61 u16 ret;
52 62
53static inline 63 if (i < sizeof(*txhdr)) {
54void tx_octet(struct bcm43xx_pioqueue *queue, 64 source = (const u8 *)txhdr;
55 u8 octet)
56{
57 if (queue->bcm->current_core->rev < 3) {
58 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, octet);
59 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, BCM43xx_PIO_TXCTL_WRITEHI);
60 } else { 65 } else {
61 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, BCM43xx_PIO_TXCTL_WRITEHI); 66 source = packet;
62 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, octet); 67 i -= sizeof(*txhdr);
63 } 68 }
69 ret = le16_to_cpu( *((u16 *)(source + i)) );
70 *pos += 2;
71
72 return ret;
64} 73}
65 74
66static inline 75static void tx_data(struct bcm43xx_pioqueue *queue,
67void tx_data(struct bcm43xx_pioqueue *queue, 76 struct bcm43xx_txhdr *txhdr,
68 u8 *packet, 77 const u8 *packet,
69 unsigned int octets) 78 unsigned int octets)
70{ 79{
71 u16 data; 80 u16 data;
72 unsigned int i = 0; 81 unsigned int i = 0;
73 82
74 if (queue->bcm->current_core->rev < 3) { 83 if (queue->need_workarounds) {
75 data = be16_to_cpu( *((u16 *)packet) ); 84 data = tx_get_next_word(txhdr, packet, &i);
76 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data); 85 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data);
77 i += 2;
78 } 86 }
79 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, 87 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
80 BCM43xx_PIO_TXCTL_WRITELO | BCM43xx_PIO_TXCTL_WRITEHI); 88 BCM43xx_PIO_TXCTL_WRITELO |
81 for ( ; i < octets - 1; i += 2) { 89 BCM43xx_PIO_TXCTL_WRITEHI);
82 data = be16_to_cpu( *((u16 *)(packet + i)) ); 90 while (i < octets - 1) {
91 data = tx_get_next_word(txhdr, packet, &i);
83 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data); 92 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data);
84 } 93 }
85 if (octets % 2) 94 if (octets % 2)
86 tx_octet(queue, packet[octets - 1]); 95 tx_octet(queue, packet[octets - sizeof(*txhdr) - 1]);
87} 96}
88 97
89static inline 98static void tx_complete(struct bcm43xx_pioqueue *queue,
90void tx_complete(struct bcm43xx_pioqueue *queue, 99 struct sk_buff *skb)
91 struct sk_buff *skb)
92{ 100{
93 u16 data; 101 if (queue->need_workarounds) {
94 102 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
95 if (queue->bcm->current_core->rev < 3) { 103 skb->data[skb->len - 1]);
96 data = be16_to_cpu( *((u16 *)(skb->data + skb->len - 2)) );
97 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data);
98 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, 104 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
99 BCM43xx_PIO_TXCTL_WRITEHI | BCM43xx_PIO_TXCTL_COMPLETE); 105 BCM43xx_PIO_TXCTL_WRITEHI |
106 BCM43xx_PIO_TXCTL_COMPLETE);
100 } else { 107 } else {
101 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, BCM43xx_PIO_TXCTL_COMPLETE); 108 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
109 BCM43xx_PIO_TXCTL_COMPLETE);
102 } 110 }
103} 111}
104 112
105static inline 113static u16 generate_cookie(struct bcm43xx_pioqueue *queue,
106u16 generate_cookie(struct bcm43xx_pioqueue *queue, 114 int packetindex)
107 int packetindex)
108{ 115{
109 u16 cookie = 0x0000; 116 u16 cookie = 0x0000;
110 117
@@ -113,8 +120,6 @@ u16 generate_cookie(struct bcm43xx_pioqueue *queue,
113 * for the packet index (in the cache). 120 * for the packet index (in the cache).
114 */ 121 */
115 switch (queue->mmio_base) { 122 switch (queue->mmio_base) {
116 default:
117 assert(0);
118 case BCM43xx_MMIO_PIO1_BASE: 123 case BCM43xx_MMIO_PIO1_BASE:
119 break; 124 break;
120 case BCM43xx_MMIO_PIO2_BASE: 125 case BCM43xx_MMIO_PIO2_BASE:
@@ -126,6 +131,8 @@ u16 generate_cookie(struct bcm43xx_pioqueue *queue,
126 case BCM43xx_MMIO_PIO4_BASE: 131 case BCM43xx_MMIO_PIO4_BASE:
127 cookie = 0x3000; 132 cookie = 0x3000;
128 break; 133 break;
134 default:
135 assert(0);
129 } 136 }
130 assert(((u16)packetindex & 0xF000) == 0x0000); 137 assert(((u16)packetindex & 0xF000) == 0x0000);
131 cookie |= (u16)packetindex; 138 cookie |= (u16)packetindex;
@@ -133,66 +140,75 @@ u16 generate_cookie(struct bcm43xx_pioqueue *queue,
133 return cookie; 140 return cookie;
134} 141}
135 142
136static inline 143static
137struct bcm43xx_pioqueue * parse_cookie(struct bcm43xx_private *bcm, 144struct bcm43xx_pioqueue * parse_cookie(struct bcm43xx_private *bcm,
138 u16 cookie, 145 u16 cookie,
139 struct bcm43xx_pio_txpacket **packet) 146 struct bcm43xx_pio_txpacket **packet)
140{ 147{
148 struct bcm43xx_pio *pio = bcm->current_core->pio;
141 struct bcm43xx_pioqueue *queue = NULL; 149 struct bcm43xx_pioqueue *queue = NULL;
142 int packetindex; 150 int packetindex;
143 151
144 switch (cookie & 0xF000) { 152 switch (cookie & 0xF000) {
145 case 0x0000: 153 case 0x0000:
146 queue = bcm->current_core->pio->queue0; 154 queue = pio->queue0;
147 break; 155 break;
148 case 0x1000: 156 case 0x1000:
149 queue = bcm->current_core->pio->queue1; 157 queue = pio->queue1;
150 break; 158 break;
151 case 0x2000: 159 case 0x2000:
152 queue = bcm->current_core->pio->queue2; 160 queue = pio->queue2;
153 break; 161 break;
154 case 0x3000: 162 case 0x3000:
155 queue = bcm->current_core->pio->queue3; 163 queue = pio->queue3;
156 break; 164 break;
157 default: 165 default:
158 assert(0); 166 assert(0);
159 } 167 }
160
161 packetindex = (cookie & 0x0FFF); 168 packetindex = (cookie & 0x0FFF);
162 assert(packetindex >= 0 && packetindex < BCM43xx_PIO_MAXTXPACKETS); 169 assert(packetindex >= 0 && packetindex < BCM43xx_PIO_MAXTXPACKETS);
163 *packet = queue->__tx_packets_cache + packetindex; 170 *packet = &(queue->tx_packets_cache[packetindex]);
164 171
165 return queue; 172 return queue;
166} 173}
167 174
168static inline 175static void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue,
169void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue, 176 struct sk_buff *skb,
170 struct sk_buff *skb, 177 struct bcm43xx_pio_txpacket *packet)
171 struct bcm43xx_pio_txpacket *packet)
172{ 178{
179 struct bcm43xx_txhdr txhdr;
173 unsigned int octets; 180 unsigned int octets;
174 181
175 assert(skb_shinfo(skb)->nr_frags == 0); 182 assert(skb_shinfo(skb)->nr_frags == 0);
176 assert(skb_headroom(skb) >= sizeof(struct bcm43xx_txhdr));
177
178 __skb_push(skb, sizeof(struct bcm43xx_txhdr));
179 bcm43xx_generate_txhdr(queue->bcm, 183 bcm43xx_generate_txhdr(queue->bcm,
180 (struct bcm43xx_txhdr *)skb->data, 184 &txhdr, skb->data, skb->len,
181 skb->data + sizeof(struct bcm43xx_txhdr),
182 skb->len - sizeof(struct bcm43xx_txhdr),
183 (packet->xmitted_frags == 0), 185 (packet->xmitted_frags == 0),
184 generate_cookie(queue, pio_txpacket_getindex(packet))); 186 generate_cookie(queue, pio_txpacket_getindex(packet)));
185 187
186 tx_start(queue); 188 tx_start(queue);
187 octets = skb->len; 189 octets = skb->len + sizeof(txhdr);
188 if (queue->bcm->current_core->rev < 3) //FIXME: && this is the last packet in the queue. 190 if (queue->need_workarounds)
189 octets -= 2; 191 octets--;
190 tx_data(queue, (u8 *)skb->data, octets); 192 tx_data(queue, &txhdr, (u8 *)skb->data, octets);
191 tx_complete(queue, skb); 193 tx_complete(queue, skb);
192} 194}
193 195
194static inline 196static void free_txpacket(struct bcm43xx_pio_txpacket *packet,
195int pio_tx_packet(struct bcm43xx_pio_txpacket *packet) 197 int irq_context)
198{
199 struct bcm43xx_pioqueue *queue = packet->queue;
200
201 ieee80211_txb_free(packet->txb);
202 list_move(&packet->list, &queue->txfree);
203 queue->nr_txfree++;
204
205 assert(queue->tx_devq_used >= packet->xmitted_octets);
206 assert(queue->tx_devq_packets >= packet->xmitted_frags);
207 queue->tx_devq_used -= packet->xmitted_octets;
208 queue->tx_devq_packets -= packet->xmitted_frags;
209}
210
211static int pio_tx_packet(struct bcm43xx_pio_txpacket *packet)
196{ 212{
197 struct bcm43xx_pioqueue *queue = packet->queue; 213 struct bcm43xx_pioqueue *queue = packet->queue;
198 struct ieee80211_txb *txb = packet->txb; 214 struct ieee80211_txb *txb = packet->txb;
@@ -204,12 +220,11 @@ int pio_tx_packet(struct bcm43xx_pio_txpacket *packet)
204 skb = txb->fragments[i]; 220 skb = txb->fragments[i];
205 221
206 octets = (u16)skb->len + sizeof(struct bcm43xx_txhdr); 222 octets = (u16)skb->len + sizeof(struct bcm43xx_txhdr);
207
208 assert(queue->tx_devq_size >= octets); 223 assert(queue->tx_devq_size >= octets);
209 assert(queue->tx_devq_packets <= BCM43xx_PIO_MAXTXDEVQPACKETS); 224 assert(queue->tx_devq_packets <= BCM43xx_PIO_MAXTXDEVQPACKETS);
210 assert(queue->tx_devq_used <= queue->tx_devq_size); 225 assert(queue->tx_devq_used <= queue->tx_devq_size);
211 /* Check if there is sufficient free space on the device 226 /* Check if there is sufficient free space on the device
212 * TX queue. If not, return and let the TX-work-handler 227 * TX queue. If not, return and let the TX tasklet
213 * retry later. 228 * retry later.
214 */ 229 */
215 if (queue->tx_devq_packets == BCM43xx_PIO_MAXTXDEVQPACKETS) 230 if (queue->tx_devq_packets == BCM43xx_PIO_MAXTXDEVQPACKETS)
@@ -234,28 +249,15 @@ int pio_tx_packet(struct bcm43xx_pio_txpacket *packet)
234 return 0; 249 return 0;
235} 250}
236 251
237static void free_txpacket(struct bcm43xx_pio_txpacket *packet) 252static void tx_tasklet(unsigned long d)
238{ 253{
239 struct bcm43xx_pioqueue *queue = packet->queue; 254 struct bcm43xx_pioqueue *queue = (struct bcm43xx_pioqueue *)d;
240 255 struct bcm43xx_private *bcm = queue->bcm;
241 ieee80211_txb_free(packet->txb);
242
243 list_move(&packet->list, &packet->queue->txfree);
244
245 assert(queue->tx_devq_used >= packet->xmitted_octets);
246 queue->tx_devq_used -= packet->xmitted_octets;
247 assert(queue->tx_devq_packets >= packet->xmitted_frags);
248 queue->tx_devq_packets -= packet->xmitted_frags;
249}
250
251static void txwork_handler(void *d)
252{
253 struct bcm43xx_pioqueue *queue = d;
254 unsigned long flags; 256 unsigned long flags;
255 struct bcm43xx_pio_txpacket *packet, *tmp_packet; 257 struct bcm43xx_pio_txpacket *packet, *tmp_packet;
256 int err; 258 int err;
257 259
258 spin_lock_irqsave(&queue->txlock, flags); 260 spin_lock_irqsave(&bcm->lock, flags);
259 list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) { 261 list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) {
260 assert(packet->xmitted_frags < packet->txb->nr_frags); 262 assert(packet->xmitted_frags < packet->txb->nr_frags);
261 if (packet->xmitted_frags == 0) { 263 if (packet->xmitted_frags == 0) {
@@ -270,22 +272,22 @@ static void txwork_handler(void *d)
270 skb = packet->txb->fragments[i]; 272 skb = packet->txb->fragments[i];
271 if (unlikely(skb->len > queue->tx_devq_size)) { 273 if (unlikely(skb->len > queue->tx_devq_size)) {
272 dprintkl(KERN_ERR PFX "PIO TX device queue too small. " 274 dprintkl(KERN_ERR PFX "PIO TX device queue too small. "
273 "Dropping packet...\n"); 275 "Dropping packet.\n");
274 free_txpacket(packet); 276 free_txpacket(packet, 1);
275 goto next_packet; 277 goto next_packet;
276 } 278 }
277 } 279 }
278 } 280 }
279 /* Now try to transmit the packet. 281 /* Try to transmit the packet.
280 * This may not completely succeed. 282 * This may not completely succeed.
281 */ 283 */
282 err = pio_tx_packet(packet); 284 err = pio_tx_packet(packet);
283 if (err) 285 if (err)
284 break; 286 break;
285next_packet: 287 next_packet:
286 continue; 288 continue;
287 } 289 }
288 spin_unlock_irqrestore(&queue->txlock, flags); 290 spin_unlock_irqrestore(&bcm->lock, flags);
289} 291}
290 292
291static void setup_txqueues(struct bcm43xx_pioqueue *queue) 293static void setup_txqueues(struct bcm43xx_pioqueue *queue)
@@ -293,8 +295,9 @@ static void setup_txqueues(struct bcm43xx_pioqueue *queue)
293 struct bcm43xx_pio_txpacket *packet; 295 struct bcm43xx_pio_txpacket *packet;
294 int i; 296 int i;
295 297
298 queue->nr_txfree = BCM43xx_PIO_MAXTXPACKETS;
296 for (i = 0; i < BCM43xx_PIO_MAXTXPACKETS; i++) { 299 for (i = 0; i < BCM43xx_PIO_MAXTXPACKETS; i++) {
297 packet = queue->__tx_packets_cache + i; 300 packet = &(queue->tx_packets_cache[i]);
298 301
299 packet->queue = queue; 302 packet->queue = queue;
300 INIT_LIST_HEAD(&packet->list); 303 INIT_LIST_HEAD(&packet->list);
@@ -311,19 +314,19 @@ struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm,
311 u32 value; 314 u32 value;
312 u16 qsize; 315 u16 qsize;
313 316
314 queue = kmalloc(sizeof(*queue), GFP_KERNEL); 317 queue = kzalloc(sizeof(*queue), GFP_KERNEL);
315 if (!queue) 318 if (!queue)
316 goto out; 319 goto out;
317 memset(queue, 0, sizeof(*queue));
318 320
319 queue->bcm = bcm; 321 queue->bcm = bcm;
320 queue->mmio_base = pio_mmio_base; 322 queue->mmio_base = pio_mmio_base;
323 queue->need_workarounds = (bcm->current_core->rev < 3);
321 324
322 INIT_LIST_HEAD(&queue->txfree); 325 INIT_LIST_HEAD(&queue->txfree);
323 INIT_LIST_HEAD(&queue->txqueue); 326 INIT_LIST_HEAD(&queue->txqueue);
324 INIT_LIST_HEAD(&queue->txrunning); 327 INIT_LIST_HEAD(&queue->txrunning);
325 spin_lock_init(&queue->txlock); 328 tasklet_init(&queue->txtask, tx_tasklet,
326 INIT_WORK(&queue->txwork, txwork_handler, queue); 329 (unsigned long)queue);
327 330
328 value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); 331 value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
329 value |= BCM43xx_SBF_XFER_REG_BYTESWAP; 332 value |= BCM43xx_SBF_XFER_REG_BYTESWAP;
@@ -331,7 +334,7 @@ struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm,
331 334
332 qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE); 335 qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE);
333 if (qsize <= BCM43xx_PIO_TXQADJUST) { 336 if (qsize <= BCM43xx_PIO_TXQADJUST) {
334 printk(KERN_ERR PFX "PIO tx queue too small (%u)\n", qsize); 337 printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n", qsize);
335 goto err_freequeue; 338 goto err_freequeue;
336 } 339 }
337 qsize -= BCM43xx_PIO_TXQADJUST; 340 qsize -= BCM43xx_PIO_TXQADJUST;
@@ -354,13 +357,12 @@ static void cancel_transfers(struct bcm43xx_pioqueue *queue)
354 357
355 netif_tx_disable(queue->bcm->net_dev); 358 netif_tx_disable(queue->bcm->net_dev);
356 assert(queue->bcm->shutting_down); 359 assert(queue->bcm->shutting_down);
357 cancel_delayed_work(&queue->txwork); 360 tasklet_disable(&queue->txtask);
358 flush_workqueue(queue->bcm->workqueue);
359 361
360 list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list) 362 list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list)
361 free_txpacket(packet); 363 free_txpacket(packet, 0);
362 list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) 364 list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list)
363 free_txpacket(packet); 365 free_txpacket(packet, 0);
364} 366}
365 367
366static void bcm43xx_destroy_pioqueue(struct bcm43xx_pioqueue *queue) 368static void bcm43xx_destroy_pioqueue(struct bcm43xx_pioqueue *queue)
@@ -374,40 +376,43 @@ static void bcm43xx_destroy_pioqueue(struct bcm43xx_pioqueue *queue)
374 376
375void bcm43xx_pio_free(struct bcm43xx_private *bcm) 377void bcm43xx_pio_free(struct bcm43xx_private *bcm)
376{ 378{
377 bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue3); 379 struct bcm43xx_pio *pio = bcm->current_core->pio;
378 bcm->current_core->pio->queue3 = NULL; 380
379 bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue2); 381 bcm43xx_destroy_pioqueue(pio->queue3);
380 bcm->current_core->pio->queue2 = NULL; 382 pio->queue3 = NULL;
381 bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue1); 383 bcm43xx_destroy_pioqueue(pio->queue2);
382 bcm->current_core->pio->queue1 = NULL; 384 pio->queue2 = NULL;
383 bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue0); 385 bcm43xx_destroy_pioqueue(pio->queue1);
384 bcm->current_core->pio->queue0 = NULL; 386 pio->queue1 = NULL;
387 bcm43xx_destroy_pioqueue(pio->queue0);
388 pio->queue0 = NULL;
385} 389}
386 390
387int bcm43xx_pio_init(struct bcm43xx_private *bcm) 391int bcm43xx_pio_init(struct bcm43xx_private *bcm)
388{ 392{
393 struct bcm43xx_pio *pio = bcm->current_core->pio;
389 struct bcm43xx_pioqueue *queue; 394 struct bcm43xx_pioqueue *queue;
390 int err = -ENOMEM; 395 int err = -ENOMEM;
391 396
392 queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO1_BASE); 397 queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO1_BASE);
393 if (!queue) 398 if (!queue)
394 goto out; 399 goto out;
395 bcm->current_core->pio->queue0 = queue; 400 pio->queue0 = queue;
396 401
397 queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO2_BASE); 402 queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO2_BASE);
398 if (!queue) 403 if (!queue)
399 goto err_destroy0; 404 goto err_destroy0;
400 bcm->current_core->pio->queue1 = queue; 405 pio->queue1 = queue;
401 406
402 queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO3_BASE); 407 queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO3_BASE);
403 if (!queue) 408 if (!queue)
404 goto err_destroy1; 409 goto err_destroy1;
405 bcm->current_core->pio->queue2 = queue; 410 pio->queue2 = queue;
406 411
407 queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO4_BASE); 412 queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO4_BASE);
408 if (!queue) 413 if (!queue)
409 goto err_destroy2; 414 goto err_destroy2;
410 bcm->current_core->pio->queue3 = queue; 415 pio->queue3 = queue;
411 416
412 if (bcm->current_core->rev < 3) 417 if (bcm->current_core->rev < 3)
413 bcm->irq_savedstate |= BCM43xx_IRQ_PIO_WORKAROUND; 418 bcm->irq_savedstate |= BCM43xx_IRQ_PIO_WORKAROUND;
@@ -418,41 +423,38 @@ out:
418 return err; 423 return err;
419 424
420err_destroy2: 425err_destroy2:
421 bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue2); 426 bcm43xx_destroy_pioqueue(pio->queue2);
422 bcm->current_core->pio->queue2 = NULL; 427 pio->queue2 = NULL;
423err_destroy1: 428err_destroy1:
424 bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue1); 429 bcm43xx_destroy_pioqueue(pio->queue1);
425 bcm->current_core->pio->queue1 = NULL; 430 pio->queue1 = NULL;
426err_destroy0: 431err_destroy0:
427 bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue0); 432 bcm43xx_destroy_pioqueue(pio->queue0);
428 bcm->current_core->pio->queue0 = NULL; 433 pio->queue0 = NULL;
429 goto out; 434 goto out;
430} 435}
431 436
432static inline 437int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
433int pio_transfer_txb(struct bcm43xx_pioqueue *queue, 438 struct ieee80211_txb *txb)
434 struct ieee80211_txb *txb)
435{ 439{
440 struct bcm43xx_pioqueue *queue = bcm->current_core->pio->queue1;
436 struct bcm43xx_pio_txpacket *packet; 441 struct bcm43xx_pio_txpacket *packet;
437 unsigned long flags;
438 u16 tmp; 442 u16 tmp;
439 443
440 spin_lock_irqsave(&queue->txlock, flags);
441 assert(!queue->tx_suspended); 444 assert(!queue->tx_suspended);
442 assert(!list_empty(&queue->txfree)); 445 assert(!list_empty(&queue->txfree));
443 446
444 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL); 447 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL);
445 if (tmp & BCM43xx_PIO_TXCTL_SUSPEND) { 448 if (tmp & BCM43xx_PIO_TXCTL_SUSPEND)
446 spin_unlock_irqrestore(&queue->txlock, flags);
447 return -EBUSY; 449 return -EBUSY;
448 }
449 450
450 packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list); 451 packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list);
451
452 packet->txb = txb; 452 packet->txb = txb;
453 list_move_tail(&packet->list, &queue->txqueue);
454 packet->xmitted_octets = 0;
455 packet->xmitted_frags = 0; 453 packet->xmitted_frags = 0;
454 packet->xmitted_octets = 0;
455 list_move_tail(&packet->list, &queue->txqueue);
456 queue->nr_txfree--;
457 assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS);
456 458
457 /* Suspend TX, if we are out of packets in the "free" queue. */ 459 /* Suspend TX, if we are out of packets in the "free" queue. */
458 if (unlikely(list_empty(&queue->txfree))) { 460 if (unlikely(list_empty(&queue->txfree))) {
@@ -460,69 +462,66 @@ int pio_transfer_txb(struct bcm43xx_pioqueue *queue,
460 queue->tx_suspended = 1; 462 queue->tx_suspended = 1;
461 } 463 }
462 464
463 spin_unlock_irqrestore(&queue->txlock, flags); 465 tasklet_schedule(&queue->txtask);
464 queue_work(queue->bcm->workqueue, &queue->txwork);
465 466
466 return 0; 467 return 0;
467} 468}
468 469
469int fastcall bcm43xx_pio_transfer_txb(struct bcm43xx_private *bcm, 470void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
470 struct ieee80211_txb *txb) 471 struct bcm43xx_xmitstatus *status)
471{
472 return pio_transfer_txb(bcm->current_core->pio->queue1, txb);
473}
474
475void fastcall
476bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
477 struct bcm43xx_xmitstatus *status)
478{ 472{
479 struct bcm43xx_pioqueue *queue; 473 struct bcm43xx_pioqueue *queue;
480 struct bcm43xx_pio_txpacket *packet; 474 struct bcm43xx_pio_txpacket *packet;
481 unsigned long flags;
482 475
483 queue = parse_cookie(bcm, status->cookie, &packet); 476 queue = parse_cookie(bcm, status->cookie, &packet);
484 assert(queue); 477 assert(queue);
485 spin_lock_irqsave(&queue->txlock, flags); 478//TODO
486 free_txpacket(packet); 479if (!queue)
480return;
481 free_txpacket(packet, 1);
487 if (unlikely(queue->tx_suspended)) { 482 if (unlikely(queue->tx_suspended)) {
488 queue->tx_suspended = 0; 483 queue->tx_suspended = 0;
489 netif_wake_queue(queue->bcm->net_dev); 484 netif_wake_queue(queue->bcm->net_dev);
490 } 485 }
491 486 /* If there are packets on the txqueue, poke the tasklet. */
492 /* If there are packets on the txqueue, 487 if (!list_empty(&queue->txqueue))
493 * start the work handler again. 488 tasklet_schedule(&queue->txtask);
494 */
495 if (!list_empty(&queue->txqueue)) {
496 queue_work(queue->bcm->workqueue,
497 &queue->txwork);
498 }
499 spin_unlock_irqrestore(&queue->txlock, flags);
500} 489}
501 490
502static void pio_rx_error(struct bcm43xx_pioqueue *queue, 491static void pio_rx_error(struct bcm43xx_pioqueue *queue,
492 int clear_buffers,
503 const char *error) 493 const char *error)
504{ 494{
505 printk("PIO RX error: %s\n", error); 495 int i;
506 bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, BCM43xx_PIO_RXCTL_READY); 496
497 printkl("PIO RX error: %s\n", error);
498 bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL,
499 BCM43xx_PIO_RXCTL_READY);
500 if (clear_buffers) {
501 assert(queue->mmio_base == BCM43xx_MMIO_PIO1_BASE);
502 for (i = 0; i < 15; i++) {
503 /* Dummy read. */
504 bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
505 }
506 }
507} 507}
508 508
509void fastcall 509void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
510bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
511{ 510{
512 u16 preamble[21] = { 0 }; 511 u16 preamble[21] = { 0 };
513 struct bcm43xx_rxhdr *rxhdr; 512 struct bcm43xx_rxhdr *rxhdr;
514 u16 tmp; 513 u16 tmp, len, rxflags2;
515 u16 len; 514 int i, preamble_readwords;
516 int i, err;
517 int preamble_readwords;
518 struct sk_buff *skb; 515 struct sk_buff *skb;
519 516
517return;
520 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); 518 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL);
521 if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) { 519 if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) {
522 dprintkl(KERN_ERR PFX "PIO RX: No data available\n"); 520 dprintkl(KERN_ERR PFX "PIO RX: No data available\n");//TODO: remove this printk.
523 return; 521 return;
524 } 522 }
525 bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, BCM43xx_PIO_RXCTL_DATAAVAILABLE); 523 bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL,
524 BCM43xx_PIO_RXCTL_DATAAVAILABLE);
526 525
527 for (i = 0; i < 10; i++) { 526 for (i = 0; i < 10; i++) {
528 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); 527 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL);
@@ -534,13 +533,14 @@ bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
534 return; 533 return;
535data_ready: 534data_ready:
536 535
536//FIXME: endianess in this function.
537 len = le16_to_cpu(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA)); 537 len = le16_to_cpu(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA));
538 if (unlikely(len > 0x700)) { 538 if (unlikely(len > 0x700)) {
539 pio_rx_error(queue, "len > 0x700"); 539 pio_rx_error(queue, 0, "len > 0x700");
540 return; 540 return;
541 } 541 }
542 if (unlikely(len == 0 && queue->mmio_base != BCM43xx_MMIO_PIO4_BASE)) { 542 if (unlikely(len == 0 && queue->mmio_base != BCM43xx_MMIO_PIO4_BASE)) {
543 pio_rx_error(queue, "len == 0"); 543 pio_rx_error(queue, 0, "len == 0");
544 return; 544 return;
545 } 545 }
546 preamble[0] = cpu_to_le16(len); 546 preamble[0] = cpu_to_le16(len);
@@ -550,28 +550,38 @@ data_ready:
550 preamble_readwords = 18 / sizeof(u16); 550 preamble_readwords = 18 / sizeof(u16);
551 for (i = 0; i < preamble_readwords; i++) { 551 for (i = 0; i < preamble_readwords; i++) {
552 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); 552 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
553 preamble[i + 1] = cpu_to_be16(tmp); 553 preamble[i + 1] = cpu_to_be16(tmp);//FIXME?
554 } 554 }
555 rxhdr = (struct bcm43xx_rxhdr *)preamble; 555 rxhdr = (struct bcm43xx_rxhdr *)preamble;
556 if (unlikely(rxhdr->flags2 & BCM43xx_RXHDR_FLAGS2_INVALIDFRAME)) { 556 rxflags2 = le16_to_cpu(rxhdr->flags2);
557 pio_rx_error(queue, "invalid frame"); 557 if (unlikely(rxflags2 & BCM43xx_RXHDR_FLAGS2_INVALIDFRAME)) {
558 if (queue->mmio_base == BCM43xx_MMIO_PIO1_BASE) { 558 pio_rx_error(queue,
559 for (i = 0; i < 15; i++) 559 (queue->mmio_base == BCM43xx_MMIO_PIO1_BASE),
560 bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); /* dummy read. */ 560 "invalid frame");
561 }
562 return; 561 return;
563 } 562 }
564//FIXME
565#if 0
566 if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE) { 563 if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE) {
567 bcm43xx_rx_transmitstatus(queue->bcm, 564 /* We received an xmit status. */
568 (const struct bcm43xx_hwxmitstatus *)(preamble + 1)); 565 struct bcm43xx_hwxmitstatus *hw;
566 struct bcm43xx_xmitstatus stat;
567
568 hw = (struct bcm43xx_hwxmitstatus *)(preamble + 1);
569 stat.cookie = le16_to_cpu(hw->cookie);
570 stat.flags = hw->flags;
571 stat.cnt1 = hw->cnt1;
572 stat.cnt2 = hw->cnt2;
573 stat.seq = le16_to_cpu(hw->seq);
574 stat.unknown = le16_to_cpu(hw->unknown);
575
576 bcm43xx_debugfs_log_txstat(queue->bcm, &stat);
577 bcm43xx_pio_handle_xmitstatus(queue->bcm, &stat);
578
569 return; 579 return;
570 } 580 }
571#endif 581
572 skb = dev_alloc_skb(len); 582 skb = dev_alloc_skb(len);
573 if (unlikely(!skb)) { 583 if (unlikely(!skb)) {
574 pio_rx_error(queue, "out of memory"); 584 pio_rx_error(queue, 1, "OOM");
575 return; 585 return;
576 } 586 }
577 skb_put(skb, len); 587 skb_put(skb, len);
@@ -580,13 +590,14 @@ data_ready:
580 *((u16 *)(skb->data + i)) = tmp; 590 *((u16 *)(skb->data + i)) = tmp;
581 } 591 }
582 if (len % 2) { 592 if (len % 2) {
583 tmp = cpu_to_be16(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA)); 593 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
584 skb->data[len - 1] = (tmp & 0x00FF); 594 skb->data[len - 1] = (tmp & 0x00FF);
585 skb->data[0] = (tmp & 0xFF00) >> 8; 595 if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME)
596 skb->data[0x20] = (tmp & 0xFF00) >> 8;
597 else
598 skb->data[0x1E] = (tmp & 0xFF00) >> 8;
586 } 599 }
587 err = bcm43xx_rx(queue->bcm, skb, rxhdr); 600 bcm43xx_rx(queue->bcm, skb, rxhdr);
588 if (unlikely(err))
589 dev_kfree_skb_irq(skb);
590} 601}
591 602
592/* vim: set ts=8 sw=8 sts=8: */ 603/* vim: set ts=8 sw=8 sts=8: */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
index 71b92ee34169..970627bc1769 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
@@ -3,9 +3,8 @@
3 3
4#include "bcm43xx.h" 4#include "bcm43xx.h"
5 5
6#include <linux/interrupt.h>
6#include <linux/list.h> 7#include <linux/list.h>
7#include <linux/spinlock.h>
8#include <linux/workqueue.h>
9#include <linux/skbuff.h> 8#include <linux/skbuff.h>
10 9
11 10
@@ -32,6 +31,10 @@
32#define BCM43xx_PIO_MAXTXPACKETS 256 31#define BCM43xx_PIO_MAXTXPACKETS 256
33 32
34 33
34
35#ifdef CONFIG_BCM43XX_PIO
36
37
35struct bcm43xx_pioqueue; 38struct bcm43xx_pioqueue;
36struct bcm43xx_xmitstatus; 39struct bcm43xx_xmitstatus;
37 40
@@ -44,13 +47,14 @@ struct bcm43xx_pio_txpacket {
44 u16 xmitted_octets; 47 u16 xmitted_octets;
45}; 48};
46 49
47#define pio_txpacket_getindex(packet) ((int)((packet) - (packet)->queue->__tx_packets_cache)) 50#define pio_txpacket_getindex(packet) ((int)((packet) - (packet)->queue->tx_packets_cache))
48 51
49struct bcm43xx_pioqueue { 52struct bcm43xx_pioqueue {
50 struct bcm43xx_private *bcm; 53 struct bcm43xx_private *bcm;
51 u16 mmio_base; 54 u16 mmio_base;
52 55
53 u8 tx_suspended:1; 56 u8 tx_suspended:1,
57 need_workarounds:1; /* Workarounds needed for core.rev < 3 */
54 58
55 /* Adjusted size of the device internal TX buffer. */ 59 /* Adjusted size of the device internal TX buffer. */
56 u16 tx_devq_size; 60 u16 tx_devq_size;
@@ -62,6 +66,7 @@ struct bcm43xx_pioqueue {
62 * be taken on incoming TX requests. 66 * be taken on incoming TX requests.
63 */ 67 */
64 struct list_head txfree; 68 struct list_head txfree;
69 unsigned int nr_txfree;
65 /* Packets on the txqueue are queued, 70 /* Packets on the txqueue are queued,
66 * but not completely written to the chip, yet. 71 * but not completely written to the chip, yet.
67 */ 72 */
@@ -70,19 +75,64 @@ struct bcm43xx_pioqueue {
70 * posted to the device. We are waiting for the txstatus. 75 * posted to the device. We are waiting for the txstatus.
71 */ 76 */
72 struct list_head txrunning; 77 struct list_head txrunning;
73 /* Locking of the TX queues and the accounting. */ 78 /* Total number or packets sent.
74 spinlock_t txlock; 79 * (This counter can obviously wrap).
75 struct work_struct txwork; 80 */
76 struct bcm43xx_pio_txpacket __tx_packets_cache[BCM43xx_PIO_MAXTXPACKETS]; 81 unsigned int nr_tx_packets;
82 struct tasklet_struct txtask;
83 struct bcm43xx_pio_txpacket tx_packets_cache[BCM43xx_PIO_MAXTXPACKETS];
77}; 84};
78 85
86static inline
87u16 bcm43xx_pio_read(struct bcm43xx_pioqueue *queue,
88 u16 offset)
89{
90 return bcm43xx_read16(queue->bcm, queue->mmio_base + offset);
91}
92
93static inline
94void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue,
95 u16 offset, u16 value)
96{
97 bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value);
98}
99
100
79int bcm43xx_pio_init(struct bcm43xx_private *bcm); 101int bcm43xx_pio_init(struct bcm43xx_private *bcm);
80void bcm43xx_pio_free(struct bcm43xx_private *bcm); 102void bcm43xx_pio_free(struct bcm43xx_private *bcm);
81 103
82int FASTCALL(bcm43xx_pio_transfer_txb(struct bcm43xx_private *bcm, 104int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
83 struct ieee80211_txb *txb)); 105 struct ieee80211_txb *txb);
84void FASTCALL(bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, 106void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
85 struct bcm43xx_xmitstatus *status)); 107 struct bcm43xx_xmitstatus *status);
86 108void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue);
87void FASTCALL(bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)); 109
110#else /* CONFIG_BCM43XX_PIO */
111
112static inline
113int bcm43xx_pio_init(struct bcm43xx_private *bcm)
114{
115 return 0;
116}
117static inline
118void bcm43xx_pio_free(struct bcm43xx_private *bcm)
119{
120}
121static inline
122int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
123 struct ieee80211_txb *txb)
124{
125 return 0;
126}
127static inline
128void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
129 struct bcm43xx_xmitstatus *status)
130{
131}
132static inline
133void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
134{
135}
136
137#endif /* CONFIG_BCM43XX_PIO */
88#endif /* BCM43xx_PIO_H_ */ 138#endif /* BCM43xx_PIO_H_ */