diff options
Diffstat (limited to 'drivers/net/wireless/b43')
24 files changed, 6439 insertions, 2430 deletions
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index fdbc351ac33..1a2141dabdc 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -61,6 +61,16 @@ config B43_PCMCIA If unsure, say N. +config B43_NPHY + bool "Pre IEEE 802.11n support (BROKEN)" + depends on B43 && EXPERIMENTAL && BROKEN + ---help--- + Support for the IEEE 802.11n draft. + + THIS IS BROKEN AND DOES NOT WORK YET. + + SAY N. + # This config option automatically enables b43 LEDS support, # if it's possible. config B43_LEDS @@ -83,51 +93,3 @@ config B43_DEBUG Say Y, if you want to find out why the driver does not work for you. - -config B43_DMA - bool - depends on B43 -config B43_PIO - bool - depends on B43 - -choice - prompt "Broadcom 43xx data transfer mode" - depends on B43 - default B43_DMA_AND_PIO_MODE - -config B43_DMA_AND_PIO_MODE - bool "DMA + PIO" - select B43_DMA - select B43_PIO - ---help--- - Include both, Direct Memory Access (DMA) and Programmed I/O (PIO) - data transfer modes. - The actually used mode is selectable through the module - parameter "pio". If the module parameter is pio=0, DMA is used. - Otherwise PIO is used. DMA is default. - - If unsure, choose this option. - -config B43_DMA_MODE - bool "DMA (Direct Memory Access) only" - select B43_DMA - ---help--- - Only include Direct Memory Access (DMA). - This reduces the size of the driver module, by omitting the PIO code. - -config B43_PIO_MODE - bool "PIO (Programmed I/O) only" - select B43_PIO - ---help--- - Only include Programmed I/O (PIO). - This reduces the size of the driver module, by omitting the DMA code. - Please note that PIO transfers are slow (compared to DMA). - - Also note that not all devices of the 43xx series support PIO. - The 4306 (Apple Airport Extreme and others) supports PIO, while - the 4318 is known to _not_ support PIO. - - Only use PIO, if DMA does not work for you. - -endchoice diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile index 485e59e2dfa..ac1329dba04 100644 --- a/drivers/net/wireless/b43/Makefile +++ b/drivers/net/wireless/b43/Makefile @@ -1,20 +1,16 @@ -# b43 core b43-y += main.o b43-y += tables.o +b43-y += tables_nphy.o b43-y += phy.o +b43-y += nphy.o b43-y += sysfs.o b43-y += xmit.o b43-y += lo.o -# b43 RFKILL button support +b43-y += wa.o +b43-y += dma.o b43-$(CONFIG_B43_RFKILL) += rfkill.o -# b43 LED support b43-$(CONFIG_B43_LEDS) += leds.o -# b43 PCMCIA support b43-$(CONFIG_B43_PCMCIA) += pcmcia.o -# b43 debugging b43-$(CONFIG_B43_DEBUG) += debugfs.o -# b43 DMA and PIO -b43-$(CONFIG_B43_DMA) += dma.o -b43-$(CONFIG_B43_PIO) += pio.o obj-$(CONFIG_B43) += b43.o diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 7b6fc1ab2b9..32a24f5c4fa 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -35,8 +35,8 @@ #define B43_MMIO_DMA4_IRQ_MASK 0x44 #define B43_MMIO_DMA5_REASON 0x48 #define B43_MMIO_DMA5_IRQ_MASK 0x4C -#define B43_MMIO_MACCTL 0x120 -#define B43_MMIO_STATUS2_BITFIELD 0x124 +#define B43_MMIO_MACCTL 0x120 /* MAC control */ +#define B43_MMIO_MACCMD 0x124 /* MAC command */ #define B43_MMIO_GEN_IRQ_REASON 0x128 #define B43_MMIO_GEN_IRQ_MASK 0x12C #define B43_MMIO_RAM_CONTROL 0x130 @@ -50,6 +50,9 @@ #define B43_MMIO_XMITSTAT_1 0x174 #define B43_MMIO_REV3PLUS_TSF_LOW 0x180 /* core rev >= 3 only */ #define B43_MMIO_REV3PLUS_TSF_HIGH 0x184 /* core rev >= 3 only */ +#define B43_MMIO_TSF_CFP_REP 0x188 +#define B43_MMIO_TSF_CFP_START 0x18C +#define B43_MMIO_TSF_CFP_MAXDUR 0x190 /* 32-bit DMA */ #define B43_MMIO_DMA32_BASE0 0x200 @@ -65,11 +68,6 @@ #define B43_MMIO_DMA64_BASE3 0x2C0 #define B43_MMIO_DMA64_BASE4 0x300 #define B43_MMIO_DMA64_BASE5 0x340 -/* PIO */ -#define B43_MMIO_PIO1_BASE 0x300 -#define B43_MMIO_PIO2_BASE 0x310 -#define B43_MMIO_PIO3_BASE 0x320 -#define B43_MMIO_PIO4_BASE 0x330 #define B43_MMIO_PHY_VER 0x3E0 #define B43_MMIO_PHY_RADIO 0x3E2 @@ -88,6 +86,8 @@ #define B43_MMIO_RADIO_HWENABLED_LO 0x49A #define B43_MMIO_GPIO_CONTROL 0x49C #define B43_MMIO_GPIO_MASK 0x49E +#define B43_MMIO_TSF_CFP_START_LOW 0x604 +#define B43_MMIO_TSF_CFP_START_HIGH 0x606 #define B43_MMIO_TSF_0 0x632 /* core rev < 3 only */ #define B43_MMIO_TSF_1 0x634 /* core rev < 3 only */ #define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */ @@ -170,14 +170,17 @@ enum { #define B43_SHM_SH_SLOTT 0x0010 /* Slot time */ #define B43_SHM_SH_DTIMPER 0x0012 /* DTIM period */ #define B43_SHM_SH_NOSLPZNATDTIM 0x004C /* NOSLPZNAT DTIM */ -/* SHM_SHARED beacon variables */ +/* SHM_SHARED beacon/AP variables */ #define B43_SHM_SH_BTL0 0x0018 /* Beacon template length 0 */ #define B43_SHM_SH_BTL1 0x001A /* Beacon template length 1 */ #define B43_SHM_SH_BTSFOFF 0x001C /* Beacon TSF offset */ #define B43_SHM_SH_TIMBPOS 0x001E /* TIM B position in beacon */ +#define B43_SHM_SH_DTIMP 0x0012 /* DTIP period */ +#define B43_SHM_SH_MCASTCOOKIE 0x00A8 /* Last bcast/mcast frame ID */ #define B43_SHM_SH_SFFBLIM 0x0044 /* Short frame fallback retry limit */ #define B43_SHM_SH_LFFBLIM 0x0046 /* Long frame fallback retry limit */ #define B43_SHM_SH_BEACPHYCTL 0x0054 /* Beacon PHY TX control word (see PHY TX control) */ +#define B43_SHM_SH_EXTNPHYCTL 0x00B0 /* Extended bytes for beacon PHY control (N) */ /* SHM_SHARED ACK/CTS control */ #define B43_SHM_SH_ACKCTSPHYCTL 0x0022 /* ACK/CTS PHY control word (see PHY TX control) */ /* SHM_SHARED probe response variables */ @@ -321,17 +324,29 @@ enum { #define B43_MACCTL_DISCPMQ 0x40000000 /* Discard Power Management Queue */ #define B43_MACCTL_GMODE 0x80000000 /* G Mode */ -/* 802.11 core specific TM State Low flags */ +/* MAC Command bitfield */ +#define B43_MACCMD_BEACON0_VALID 0x00000001 /* Beacon 0 in template RAM is busy/valid */ +#define B43_MACCMD_BEACON1_VALID 0x00000002 /* Beacon 1 in template RAM is busy/valid */ +#define B43_MACCMD_DFQ_VALID 0x00000004 /* Directed frame queue valid (IBSS PS mode, ATIM) */ +#define B43_MACCMD_CCA 0x00000008 /* Clear channel assessment */ +#define B43_MACCMD_BGNOISE 0x00000010 /* Background noise */ + +/* 802.11 core specific TM State Low (SSB_TMSLOW) flags */ #define B43_TMSLOW_GMODE 0x20000000 /* G Mode Enable */ -#define B43_TMSLOW_PLLREFSEL 0x00200000 /* PLL Frequency Reference Select */ +#define B43_TMSLOW_PHYCLKSPEED 0x00C00000 /* PHY clock speed mask (N-PHY only) */ +#define B43_TMSLOW_PHYCLKSPEED_40MHZ 0x00000000 /* 40 MHz PHY */ +#define B43_TMSLOW_PHYCLKSPEED_80MHZ 0x00400000 /* 80 MHz PHY */ +#define B43_TMSLOW_PHYCLKSPEED_160MHZ 0x00800000 /* 160 MHz PHY */ +#define B43_TMSLOW_PLLREFSEL 0x00200000 /* PLL Frequency Reference Select (rev >= 5) */ #define B43_TMSLOW_MACPHYCLKEN 0x00100000 /* MAC PHY Clock Control Enable (rev >= 5) */ #define B43_TMSLOW_PHYRESET 0x00080000 /* PHY Reset */ #define B43_TMSLOW_PHYCLKEN 0x00040000 /* PHY Clock Enable */ -/* 802.11 core specific TM State High flags */ +/* 802.11 core specific TM State High (SSB_TMSHIGH) flags */ +#define B43_TMSHIGH_DUALBAND_PHY 0x00080000 /* Dualband PHY available */ #define B43_TMSHIGH_FCLOCK 0x00040000 /* Fast Clock Available (rev >= 5) */ -#define B43_TMSHIGH_APHY 0x00020000 /* A-PHY available (rev >= 5) */ -#define B43_TMSHIGH_GPHY 0x00010000 /* G-PHY available (rev >= 5) */ +#define B43_TMSHIGH_HAVE_5GHZ_PHY 0x00020000 /* 5 GHz PHY available (rev >= 5) */ +#define B43_TMSHIGH_HAVE_2GHZ_PHY 0x00010000 /* 2.4 GHz PHY available (rev >= 5) */ /* Generic-Interrupt reasons. */ #define B43_IRQ_MAC_SUSPENDED 0x00000001 @@ -393,6 +408,8 @@ enum { #define B43_DEFAULT_SHORT_RETRY_LIMIT 7 #define B43_DEFAULT_LONG_RETRY_LIMIT 4 +#define B43_PHY_TX_BADNESS_LIMIT 1000 + /* Max size of a security key */ #define B43_SEC_KEYSIZE 16 /* Security algorithms. */ @@ -462,7 +479,6 @@ struct b43_phy { u16 radio_ver; /* Radio version */ u8 radio_rev; /* Radio revision */ - bool locked; /* Only used in b43_phy_{un}lock() */ bool dyn_tssi_tbl; /* tssi2dbm is kmalloc()ed. */ /* ACI (adjacent channel interference) flags. */ @@ -499,11 +515,6 @@ struct b43_phy { s16 lna_gain; /* LNA */ s16 pga_gain; /* PGA */ - /* PHY lock for core.rev < 3 - * This lock is only used by b43_phy_{un}lock() - */ - spinlock_t lock; - /* Desired TX power level (in dBm). * This is set by the user and adjusted in b43_phy_xmitpower(). */ u8 power_level; @@ -514,9 +525,7 @@ struct b43_phy { struct b43_bbatt bbatt; struct b43_rfatt rfatt; u8 tx_control; /* B43_TXCTL_XXX */ -#ifdef CONFIG_B43_DEBUG - bool manual_txpower_control; /* Manual TX-power control enabled? */ -#endif + /* Hardware Power Control enabled? */ bool hardware_power_control; @@ -544,6 +553,26 @@ struct b43_phy { u16 lofcal; u16 initval; //FIXME rename? + + /* PHY TX errors counter. */ + atomic_t txerr_cnt; + + /* The device does address auto increment for the OFDM tables. + * We cache the previously used address here and omit the address + * write on the next table access, if possible. */ + u16 ofdmtab_addr; /* The address currently set in hardware. */ + enum { /* The last data flow direction. */ + B43_OFDMTAB_DIRECTION_UNKNOWN = 0, + B43_OFDMTAB_DIRECTION_READ, + B43_OFDMTAB_DIRECTION_WRITE, + } ofdmtab_addr_direction; + +#if B43_DEBUG + /* Manual TX-power control enabled? */ + bool manual_txpower_control; + /* PHY registers locked by b43_phy_lock()? */ + bool phy_locked; +#endif /* B43_DEBUG */ }; /* Data structures for DMA transmission, per 80211 core. */ @@ -559,14 +588,6 @@ struct b43_dma { struct b43_dmaring *rx_ring3; /* only available on core.rev < 5 */ }; -/* Data structures for PIO transmission, per 80211 core. */ -struct b43_pio { - struct b43_pioqueue *queue0; - struct b43_pioqueue *queue1; - struct b43_pioqueue *queue2; - struct b43_pioqueue *queue3; -}; - /* Context information for a noise calculation (Link Quality). */ struct b43_noise_calculation { u8 channel_at_start; @@ -599,18 +620,18 @@ struct b43_wl { /* Pointer to the ieee80211 hardware data structure */ struct ieee80211_hw *hw; - spinlock_t irq_lock; struct mutex mutex; + spinlock_t irq_lock; + /* Lock for LEDs access. */ spinlock_t leds_lock; + /* Lock for SHM access. */ + spinlock_t shm_lock; /* We can only have one operating interface (802.11 core) * at a time. General information about this interface follows. */ - /* Opaque ID of the operating interface from the ieee80211 - * subsystem. Do not modify. - */ - int if_id; + struct ieee80211_vif *vif; /* The MAC address of the operating interface. */ u8 mac_addr[ETH_ALEN]; /* Current BSSID */ @@ -634,18 +655,33 @@ struct b43_wl { /* List of all wireless devices on this chip */ struct list_head devlist; u8 nr_devs; + + bool radiotap_enabled; + + /* The beacon we are currently using (AP or IBSS mode). + * This beacon stuff is protected by the irq_lock. */ + struct sk_buff *current_beacon; + bool beacon0_uploaded; + bool beacon1_uploaded; +}; + +/* In-memory representation of a cached microcode file. */ +struct b43_firmware_file { + const char *filename; + const struct firmware *data; }; /* Pointers to the firmware data and meta information about it. */ struct b43_firmware { /* Microcode */ - const struct firmware *ucode; + struct b43_firmware_file ucode; /* PCM code */ - const struct firmware *pcm; + struct b43_firmware_file pcm; /* Initial MMIO values for the firmware */ - const struct firmware *initvals; + struct b43_firmware_file initvals; /* Initial MMIO values for the firmware, band-specific */ - const struct firmware *initvals_band; + struct b43_firmware_file initvals_band; + /* Firmware revision */ u16 rev; /* Firmware patchlevel */ @@ -683,21 +719,17 @@ struct b43_wldev { /* Saved init status for handling suspend. */ int suspend_init_status; - bool __using_pio; /* Internal, use b43_using_pio(). */ bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */ - bool reg124_set_0x4; /* Some variable to keep track of IRQ stuff. */ + bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */ bool short_preamble; /* TRUE, if short preamble is enabled. */ bool short_slot; /* TRUE, if short slot timing is enabled. */ bool radio_hw_enable; /* saved state of radio hardware enabled state */ /* PHY/Radio device. */ struct b43_phy phy; - union { - /* DMA engines. */ - struct b43_dma dma; - /* PIO engines. */ - struct b43_pio pio; - }; + + /* DMA engines. */ + struct b43_dma dma; /* Various statistics about the physical device. */ struct b43_stats stats; @@ -732,9 +764,6 @@ struct b43_wldev { u8 max_nr_keys; struct b43_key key[58]; - /* Cached beacon template while uploading the template. */ - struct sk_buff *cached_beacon; - /* Firmware data */ struct b43_firmware fw; @@ -752,28 +781,6 @@ static inline struct b43_wl *hw_to_b43_wl(struct ieee80211_hw *hw) return hw->priv; } -/* Helper function, which returns a boolean. - * TRUE, if PIO is used; FALSE, if DMA is used. - */ -#if defined(CONFIG_B43_DMA) && defined(CONFIG_B43_PIO) -static inline int b43_using_pio(struct b43_wldev *dev) -{ - return dev->__using_pio; -} -#elif defined(CONFIG_B43_DMA) -static inline int b43_using_pio(struct b43_wldev *dev) -{ - return 0; -} -#elif defined(CONFIG_B43_PIO) -static inline int b43_using_pio(struct b43_wldev *dev) -{ - return 1; -} -#else -# error "Using neither DMA nor PIO? Confused..." -#endif - static inline struct b43_wldev *dev_to_b43_wldev(struct device *dev) { struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c index ef0075d9f9c..e38ed0fe72e 100644 --- a/drivers/net/wireless/b43/debugfs.c +++ b/drivers/net/wireless/b43/debugfs.c @@ -34,7 +34,6 @@ #include "main.h" #include "debugfs.h" #include "dma.h" -#include "pio.h" #include "xmit.h" @@ -223,8 +222,6 @@ out: static int txpower_g_write_file(struct b43_wldev *dev, const char *buf, size_t count) { - unsigned long phy_flags; - if (dev->phy.type != B43_PHYTYPE_G) return -ENODEV; if ((count >= 4) && (memcmp(buf, "auto", 4) == 0)) { @@ -248,12 +245,12 @@ static int txpower_g_write_file(struct b43_wldev *dev, dev->phy.tx_control |= B43_TXCTL_PA2DB; if (pa3db) dev->phy.tx_control |= B43_TXCTL_PA3DB; - b43_phy_lock(dev, phy_flags); + b43_phy_lock(dev); b43_radio_lock(dev); b43_set_txpower_g(dev, &dev->phy.bbatt, &dev->phy.rfatt, dev->phy.tx_control); b43_radio_unlock(dev); - b43_phy_unlock(dev, phy_flags); + b43_phy_unlock(dev); } return 0; @@ -352,7 +349,7 @@ static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf, struct b43_wldev *dev; struct b43_debugfs_fops *dfops; struct b43_dfs_file *dfile; - ssize_t ret; + ssize_t uninitialized_var(ret); char *buf; const size_t bufsize = 1024 * 128; const size_t buforder = get_order(bufsize); diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 5e8f8ac0f1d..3e73d2a523a 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -37,6 +37,8 @@ #include <linux/pci.h> #include <linux/delay.h> #include <linux/skbuff.h> +#include <linux/etherdevice.h> + /* 32bit DMA ops. */ static @@ -165,7 +167,7 @@ static void op64_fill_descriptor(struct b43_dmaring *ring, addrhi = (((u64) dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK); addrext = (((u64) dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK) >> SSB_DMA_TRANSLATION_SHIFT; - addrhi |= ssb_dma_translation(ring->dev->dev); + addrhi |= (ssb_dma_translation(ring->dev->dev) << 1); if (slot == ring->nr_slots - 1) ctl0 |= B43_DMA64_DCTL0_DTABLEEND; if (start) @@ -315,26 +317,24 @@ static struct b43_dmaring *priority_to_txring(struct b43_wldev *dev, case 3: ring = dev->dma.tx_ring0; break; - case 4: - ring = dev->dma.tx_ring4; - break; - case 5: - ring = dev->dma.tx_ring5; - break; } return ring; } -/* Bcm43xx-ring to mac80211-queue mapping */ +/* b43-ring to mac80211-queue mapping */ static inline int txring_to_priority(struct b43_dmaring *ring) { - static const u8 idx_to_prio[] = { 3, 2, 1, 0, 4, 5, }; + static const u8 idx_to_prio[] = { 3, 2, 1, 0, }; + unsigned int index; /*FIXME: have only one queue, for now */ return 0; - return idx_to_prio[ring->index]; + index = ring->index; + if (B43_WARN_ON(index >= ARRAY_SIZE(idx_to_prio))) + index = 0; + return idx_to_prio[index]; } u16 b43_dmacontroller_base(int dma64bit, int controller_idx) @@ -426,9 +426,21 @@ static inline static int alloc_ringmemory(struct b43_dmaring *ring) { struct device *dev = ring->dev->dev->dev; - + gfp_t flags = GFP_KERNEL; + + /* The specs call for 4K buffers for 30- and 32-bit DMA with 4K + * alignment and 8K buffers for 64-bit DMA with 8K alignment. Testing + * has shown that 4K is sufficient for the latter as long as the buffer + * does not cross an 8K boundary. + * + * For unknown reasons - possibly a hardware error - the BCM4311 rev + * 02, which uses 64-bit DMA, needs the ring buffer in very low memory, + * which accounts for the GFP_DMA flag below. + */ + if (ring->dma64) + flags |= GFP_DMA; ring->descbase = dma_alloc_coherent(dev, B43_DMA_RINGMEMSIZE, - &(ring->dmabase), GFP_KERNEL); + &(ring->dmabase), flags); if (!ring->descbase) { b43err(ring->dev->wl, "DMA ringmemory allocation failed\n"); return -ENOMEM; @@ -483,7 +495,7 @@ int b43_dmacontroller_rx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64) return 0; } -/* Reset the RX DMA channel */ +/* Reset the TX DMA channel */ int b43_dmacontroller_tx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64) { int i; @@ -647,7 +659,7 @@ static int dmacontroller_setup(struct b43_dmaring *ring) b43_dma_write(ring, B43_DMA64_TXRINGHI, ((ringbase >> 32) & ~SSB_DMA_TRANSLATION_MASK) - | trans); + | (trans << 1)); } else { u32 ringbase = (u32) (ring->dmabase); @@ -680,8 +692,9 @@ static int dmacontroller_setup(struct b43_dmaring *ring) b43_dma_write(ring, B43_DMA64_RXRINGHI, ((ringbase >> 32) & ~SSB_DMA_TRANSLATION_MASK) - | trans); - b43_dma_write(ring, B43_DMA64_RXINDEX, 200); + | (trans << 1)); + b43_dma_write(ring, B43_DMA64_RXINDEX, ring->nr_slots * + sizeof(struct b43_dmadesc64)); } else { u32 ringbase = (u32) (ring->dmabase); @@ -695,11 +708,12 @@ static int dmacontroller_setup(struct b43_dmaring *ring) b43_dma_write(ring, B43_DMA32_RXRING, (ringbase & ~SSB_DMA_TRANSLATION_MASK) | trans); - b43_dma_write(ring, B43_DMA32_RXINDEX, 200); + b43_dma_write(ring, B43_DMA32_RXINDEX, ring->nr_slots * + sizeof(struct b43_dmadesc32)); } } - out: +out: return err; } @@ -793,7 +807,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, goto err_kfree_ring; if (for_tx) { ring->txhdr_cache = kcalloc(nr_slots, - sizeof(struct b43_txhdr_fw4), + b43_txhdr_size(dev), GFP_KERNEL); if (!ring->txhdr_cache) goto err_kfree_meta; @@ -801,22 +815,21 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, /* test for ability to dma to txhdr_cache */ dma_test = dma_map_single(dev->dev->dev, ring->txhdr_cache, - sizeof(struct b43_txhdr_fw4), + b43_txhdr_size(dev), DMA_TO_DEVICE); if (dma_mapping_error(dma_test)) { /* ugh realloc */ kfree(ring->txhdr_cache); ring->txhdr_cache = kcalloc(nr_slots, - sizeof(struct - b43_txhdr_fw4), + b43_txhdr_size(dev), GFP_KERNEL | GFP_DMA); if (!ring->txhdr_cache) goto err_kfree_meta; dma_test = dma_map_single(dev->dev->dev, ring->txhdr_cache, - sizeof(struct b43_txhdr_fw4), + b43_txhdr_size(dev), DMA_TO_DEVICE); if (dma_mapping_error(dma_test)) @@ -824,7 +837,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, } dma_unmap_single(dev->dev->dev, - dma_test, sizeof(struct b43_txhdr_fw4), + dma_test, b43_txhdr_size(dev), DMA_TO_DEVICE); } @@ -901,11 +914,7 @@ static void b43_destroy_dmaring(struct b43_dmaring *ring) void b43_dma_free(struct b43_wldev *dev) { - struct b43_dma *dma; - - if (b43_using_pio(dev)) - return; - dma = &dev->dma; + struct b43_dma *dma = &dev->dma; b43_destroy_dmaring(dma->rx_ring3); dma->rx_ring3 = NULL; @@ -940,16 +949,11 @@ int b43_dma_init(struct b43_wldev *dev) err = ssb_dma_set_mask(dev->dev, dmamask); if (err) { -#ifdef B43_PIO - b43warn(dev->wl, "DMA for this device not supported. " - "Falling back to PIO\n"); - dev->__using_pio = 1; - return -EAGAIN; -#else - b43err(dev->wl, "DMA for this device not supported and " - "no PIO support compiled in\n"); + b43err(dev->wl, "The machine/kernel does not support " + "the required DMA mask (0x%08X%08X)\n", + (unsigned int)((dmamask & 0xFFFFFFFF00000000ULL) >> 32), + (unsigned int)(dmamask & 0x00000000FFFFFFFFULL)); return -EOPNOTSUPP; -#endif } err = -ENOMEM; @@ -1038,26 +1042,30 @@ static u16 generate_cookie(struct b43_dmaring *ring, int slot) * in the lower 12 bits. * Note that the cookie must never be 0, as this * is a special value used in RX path. + * It can also not be 0xFFFF because that is special + * for multicast frames. */ switch (ring->index) { case 0: - cookie = 0xA000; + cookie = 0x1000; break; case 1: - cookie = 0xB000; + cookie = 0x2000; break; case 2: - cookie = 0xC000; + cookie = 0x3000; break; case 3: - cookie = 0xD000; + cookie = 0x4000; break; case 4: - cookie = 0xE000; + cookie = 0x5000; break; case 5: - cookie = 0xF000; + cookie = 0x6000; break; + default: + B43_WARN_ON(1); } B43_WARN_ON(slot & ~0x0FFF); cookie |= (u16) slot; @@ -1073,22 +1081,22 @@ struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot) struct b43_dmaring *ring = NULL; switch (cookie & 0xF000) { - case 0xA000: + case 0x1000: ring = dma->tx_ring0; break; - case 0xB000: + case 0x2000: ring = dma->tx_ring1; break; - case 0xC000: + case 0x3000: ring = dma->tx_ring2; break; - case 0xD000: + case 0x4000: ring = dma->tx_ring3; break; - case 0xE000: + case 0x5000: ring = dma->tx_ring4; break; - case 0xF000: + case 0x6000: ring = dma->tx_ring5; break; default: @@ -1112,6 +1120,8 @@ static int dma_tx_fragment(struct b43_dmaring *ring, struct b43_dmadesc_meta *meta; struct b43_dmadesc_meta *meta_hdr; struct sk_buff *bounce_skb; + u16 cookie; + size_t hdrsize = b43_txhdr_size(ring->dev); #define SLOTS_PER_PACKET 2 B43_WARN_ON(skb_shinfo(skb)->nr_frags); @@ -1121,17 +1131,17 @@ static int dma_tx_fragment(struct b43_dmaring *ring, desc = ops->idx2desc(ring, slot, &meta_hdr); memset(meta_hdr, 0, sizeof(*meta_hdr)); - header = &(ring->txhdr_cache[slot * sizeof(struct b43_txhdr_fw4)]); + header = &(ring->txhdr_cache[slot * hdrsize]); + cookie = generate_cookie(ring, slot); b43_generate_txhdr(ring->dev, header, - skb->data, skb->len, ctl, - generate_cookie(ring, slot)); + skb->data, skb->len, ctl, cookie); meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, - sizeof(struct b43_txhdr_fw4), 1); + hdrsize, 1); if (dma_mapping_error(meta_hdr->dmaaddr)) return -EIO; ops->fill_descriptor(ring, desc, meta_hdr->dmaaddr, - sizeof(struct b43_txhdr_fw4), 1, 0, 0); + hdrsize, 1, 0, 0); /* Get a slot for the payload. */ slot = request_slot(ring); @@ -1164,16 +1174,22 @@ static int dma_tx_fragment(struct b43_dmaring *ring, ops->fill_descriptor(ring, desc, meta->dmaaddr, skb->len, 0, 1, 1); + if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) { + /* Tell the firmware about the cookie of the last + * mcast frame, so it can clear the more-data bit in it. */ + b43_shm_write16(ring->dev, B43_SHM_SHARED, + B43_SHM_SH_MCASTCOOKIE, cookie); + } /* Now transfer the whole frame. */ wmb(); ops->poke_tx(ring, next_slot(ring, slot)); return 0; - out_free_bounce: +out_free_bounce: dev_kfree_skb_any(skb); - out_unmap_hdr: +out_unmap_hdr: unmap_descbuffer(ring, meta_hdr->dmaaddr, - sizeof(struct b43_txhdr_fw4), 1); + hdrsize, 1); return err; } @@ -1202,10 +1218,27 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb, struct ieee80211_tx_control *ctl) { struct b43_dmaring *ring; + struct ieee80211_hdr *hdr; int err = 0; unsigned long flags; - ring = priority_to_txring(dev, ctl->queue); + if (unlikely(skb->len < 2 + 2 + 6)) { + /* Too short, this can't be a valid frame. */ + return -EINVAL; + } + + hdr = (struct ieee80211_hdr *)skb->data; + if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) { + /* The multicast ring will be sent after the DTIM */ + ring = dev->dma.tx_ring4; + /* Set the more-data bit. Ucode will clear it on + * the last frame for us. */ + hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); + } else { + /* Decide by priority where to put this frame. */ + ring = priority_to_txring(dev, ctl->queue); + } + spin_lock_irqsave(&ring->lock, flags); B43_WARN_ON(!ring->tx); if (unlikely(free_slots(ring) < SLOTS_PER_PACKET)) { @@ -1233,7 +1266,7 @@ int b43_dma_tx(struct b43_wldev *dev, b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index); } } - out_unlock: +out_unlock: spin_unlock_irqrestore(&ring->lock, flags); return err; @@ -1265,7 +1298,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, 1); else unmap_descbuffer(ring, meta->dmaaddr, - sizeof(struct b43_txhdr_fw4), 1); + b43_txhdr_size(dev), 1); if (meta->is_last_fragment) { B43_WARN_ON(!meta->skb); diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index 3eed185be72..58db03ac536 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h @@ -170,8 +170,6 @@ struct b43_dmadesc_generic { #define B43_DMA0_RX_BUFFERSIZE (2304 + 100) #define B43_DMA3_RX_BUFFERSIZE 16 -#ifdef CONFIG_B43_DMA - struct sk_buff; struct b43_private; struct b43_txstatus; @@ -286,52 +284,4 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, void b43_dma_rx(struct b43_dmaring *ring); -#else /* CONFIG_B43_DMA */ - -static inline int b43_dma_init(struct b43_wldev *dev) -{ - return 0; -} -static inline void b43_dma_free(struct b43_wldev *dev) -{ -} -static inline - int b43_dmacontroller_rx_reset(struct b43_wldev *dev, - u16 dmacontroller_mmio_base, int dma64) -{ - return 0; -} -static inline - int b43_dmacontroller_tx_reset(struct b43_wldev *dev, - u16 dmacontroller_mmio_base, int dma64) -{ - return 0; -} -static inline - void b43_dma_get_tx_stats(struct b43_wldev *dev, - struct ieee80211_tx_queue_stats *stats) -{ -} -static inline - int b43_dma_tx(struct b43_wldev *dev, - struct sk_buff *skb, struct ieee80211_tx_control *ctl) -{ - return 0; -} -static inline - void b43_dma_handle_txstatus(struct b43_wldev *dev, - const struct b43_txstatus *status) -{ -} -static inline void b43_dma_rx(struct b43_dmaring *ring) -{ -} -static inline void b43_dma_tx_suspend(struct b43_wldev *dev) -{ -} -static inline void b43_dma_tx_resume(struct b43_wldev *dev) -{ -} - -#endif /* CONFIG_B43_DMA */ #endif /* B43_DMA_H_ */ diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c index 6c0e2b9f776..4b590d8c65f 100644 --- a/drivers/net/wireless/b43/leds.c +++ b/drivers/net/wireless/b43/leds.c @@ -4,7 +4,7 @@ LED control Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>, - Copyright (c) 2005 Stefano Brivio <st3@riseup.net> + Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it> Copyright (c) 2005-2007 Michael Buesch & |