#ifndef BCM43xx_H_
#define BCM43xx_H_
-#include <linux/hw_random.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/spinlock.h>
#define BCM43xx_PCICFG_ICR 0x94
/* MMIO offsets */
-#define BCM43xx_MMIO_DMA0_REASON 0x20
-#define BCM43xx_MMIO_DMA0_IRQ_MASK 0x24
-#define BCM43xx_MMIO_DMA1_REASON 0x28
-#define BCM43xx_MMIO_DMA1_IRQ_MASK 0x2C
-#define BCM43xx_MMIO_DMA2_REASON 0x30
-#define BCM43xx_MMIO_DMA2_IRQ_MASK 0x34
-#define BCM43xx_MMIO_DMA3_REASON 0x38
-#define BCM43xx_MMIO_DMA3_IRQ_MASK 0x3C
-#define BCM43xx_MMIO_DMA4_REASON 0x40
-#define BCM43xx_MMIO_DMA4_IRQ_MASK 0x44
-#define BCM43xx_MMIO_DMA5_REASON 0x48
-#define BCM43xx_MMIO_DMA5_IRQ_MASK 0x4C
+#define BCM43xx_MMIO_DMA1_REASON 0x20
+#define BCM43xx_MMIO_DMA1_IRQ_MASK 0x24
+#define BCM43xx_MMIO_DMA2_REASON 0x28
+#define BCM43xx_MMIO_DMA2_IRQ_MASK 0x2C
+#define BCM43xx_MMIO_DMA3_REASON 0x30
+#define BCM43xx_MMIO_DMA3_IRQ_MASK 0x34
+#define BCM43xx_MMIO_DMA4_REASON 0x38
+#define BCM43xx_MMIO_DMA4_IRQ_MASK 0x3C
#define BCM43xx_MMIO_STATUS_BITFIELD 0x120
#define BCM43xx_MMIO_STATUS2_BITFIELD 0x124
#define BCM43xx_MMIO_GEN_IRQ_REASON 0x128
#define BCM43xx_MMIO_XMITSTAT_1 0x174
#define BCM43xx_MMIO_REV3PLUS_TSF_LOW 0x180 /* core rev >= 3 only */
#define BCM43xx_MMIO_REV3PLUS_TSF_HIGH 0x184 /* core rev >= 3 only */
-
-/* 32-bit DMA */
-#define BCM43xx_MMIO_DMA32_BASE0 0x200
-#define BCM43xx_MMIO_DMA32_BASE1 0x220
-#define BCM43xx_MMIO_DMA32_BASE2 0x240
-#define BCM43xx_MMIO_DMA32_BASE3 0x260
-#define BCM43xx_MMIO_DMA32_BASE4 0x280
-#define BCM43xx_MMIO_DMA32_BASE5 0x2A0
-/* 64-bit DMA */
-#define BCM43xx_MMIO_DMA64_BASE0 0x200
-#define BCM43xx_MMIO_DMA64_BASE1 0x240
-#define BCM43xx_MMIO_DMA64_BASE2 0x280
-#define BCM43xx_MMIO_DMA64_BASE3 0x2C0
-#define BCM43xx_MMIO_DMA64_BASE4 0x300
-#define BCM43xx_MMIO_DMA64_BASE5 0x340
-/* PIO */
+#define BCM43xx_MMIO_DMA1_BASE 0x200
+#define BCM43xx_MMIO_DMA2_BASE 0x220
+#define BCM43xx_MMIO_DMA3_BASE 0x240
+#define BCM43xx_MMIO_DMA4_BASE 0x260
#define BCM43xx_MMIO_PIO1_BASE 0x300
#define BCM43xx_MMIO_PIO2_BASE 0x310
#define BCM43xx_MMIO_PIO3_BASE 0x320
#define BCM43xx_MMIO_PIO4_BASE 0x330
-
#define BCM43xx_MMIO_PHY_VER 0x3E0
#define BCM43xx_MMIO_PHY_RADIO 0x3E2
#define BCM43xx_MMIO_ANTENNA 0x3E8
#define BCM43xx_MMIO_TSF_1 0x634 /* core rev < 3 only */
#define BCM43xx_MMIO_TSF_2 0x636 /* core rev < 3 only */
#define BCM43xx_MMIO_TSF_3 0x638 /* core rev < 3 only */
-#define BCM43xx_MMIO_RNG 0x65A
#define BCM43xx_MMIO_POWERUP_DELAY 0x6A8
/* SPROM offsets. */
#define BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK 0x20000
/* sbtmstatehigh state flags */
-#define BCM43xx_SBTMSTATEHIGH_SERROR 0x00000001
-#define BCM43xx_SBTMSTATEHIGH_BUSY 0x00000004
-#define BCM43xx_SBTMSTATEHIGH_TIMEOUT 0x00000020
-#define BCM43xx_SBTMSTATEHIGH_COREFLAGS 0x1FFF0000
-#define BCM43xx_SBTMSTATEHIGH_DMA64BIT 0x10000000
-#define BCM43xx_SBTMSTATEHIGH_GATEDCLK 0x20000000
-#define BCM43xx_SBTMSTATEHIGH_BISTFAILED 0x40000000
-#define BCM43xx_SBTMSTATEHIGH_BISTCOMPLETE 0x80000000
+#define BCM43xx_SBTMSTATEHIGH_SERROR 0x1
+#define BCM43xx_SBTMSTATEHIGH_BUSY 0x4
/* sbimstate flags */
#define BCM43xx_SBIMSTATE_IB_ERROR 0x20000
#define BCM43xx_SBF_TIME_UPDATE 0x10000000
#define BCM43xx_SBF_80000000 0x80000000 /*FIXME: fix name*/
-/* Microcode */
-#define BCM43xx_UCODE_REVISION 0x0000
-#define BCM43xx_UCODE_PATCHLEVEL 0x0002
-#define BCM43xx_UCODE_DATE 0x0004
-#define BCM43xx_UCODE_TIME 0x0006
-#define BCM43xx_UCODE_STATUS 0x0040
-
/* MicrocodeFlagsBitfield (addr + lo-word values?)*/
#define BCM43xx_UCODEFLAGS_OFFSET 0x005E
* This lock is only used by bcm43xx_phy_{un}lock()
*/
spinlock_t lock;
-
- /* Firmware. */
- const struct firmware *ucode;
- const struct firmware *pcm;
- const struct firmware *initvals0;
- const struct firmware *initvals1;
};
struct bcm43xx_dmaring *tx_ring1;
struct bcm43xx_dmaring *tx_ring2;
struct bcm43xx_dmaring *tx_ring3;
- struct bcm43xx_dmaring *tx_ring4;
- struct bcm43xx_dmaring *tx_ring5;
-
struct bcm43xx_dmaring *rx_ring0;
- struct bcm43xx_dmaring *rx_ring3; /* only available on core.rev < 5 */
+ struct bcm43xx_dmaring *rx_ring1; /* only available on core.rev < 5 */
};
/* Data structures for PIO transmission, per 80211 core. */
u8 available:1,
enabled:1,
initialized:1;
+ /** core_id ID number */
+ u16 id;
/** core_rev revision number */
u8 rev;
/** Index number for _switch_core() */
u8 index;
- /** core_id ID number */
- u16 id;
- /** Core-specific data. */
- void *priv;
};
/* Additional information for each 80211 core. */
u8 algorithm;
};
-/* Driver initialization status. */
-enum {
- BCM43xx_STAT_UNINIT, /* Uninitialized. */
- BCM43xx_STAT_INITIALIZING, /* init_board() in progress. */
- BCM43xx_STAT_INITIALIZED, /* Fully operational. */
- BCM43xx_STAT_SHUTTINGDOWN, /* free_board() in progress. */
- BCM43xx_STAT_RESTARTING, /* controller_restart() called. */
-};
-#define bcm43xx_status(bcm) atomic_read(&(bcm)->init_status)
-#define bcm43xx_set_status(bcm, stat) do { \
- atomic_set(&(bcm)->init_status, (stat)); \
- smp_wmb(); \
- } while (0)
-
-/* *** THEORY OF LOCKING ***
- *
- * We have two different locks in the bcm43xx driver.
- * => bcm->mutex: General sleeping mutex. Protects struct bcm43xx_private
- * and the device registers. This mutex does _not_ protect
- * against concurrency from the IRQ handler.
- * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency.
- *
- * Please note that, if you only take the irq_lock, you are not protected
- * against concurrency from the periodic work handlers.
- * Most times you want to take _both_ locks.
- */
-
struct bcm43xx_private {
struct ieee80211_device *ieee;
struct ieee80211softmac_device *softmac;
unsigned int irq;
void __iomem *mmio_addr;
+ unsigned int mmio_len;
- spinlock_t irq_lock;
- struct mutex mutex;
-
- /* Driver initialization status BCM43xx_STAT_*** */
- atomic_t init_status;
+ /* Do not use the lock directly. Use the bcm43xx_lock* helper
+ * functions, to be MMIO-safe. */
+ spinlock_t _lock;
- u16 was_initialized:1, /* for PCI suspend/resume. */
+ /* Driver status flags. */
+ u32 initialized:1, /* init_board() succeed */
+ was_initialized:1, /* for PCI suspend/resume. */
+ shutting_down:1, /* free_board() in progress */
__using_pio:1, /* Internal, use bcm43xx_using_pio(). */
bad_frames_preempt:1, /* Use "Bad Frames Preemption" (default off) */
reg124_set_0x4:1, /* Some variable to keep track of IRQ stuff. */
+ powersaving:1, /* TRUE if we are in PowerSaving mode. FALSE otherwise. */
short_preamble:1, /* TRUE, if short preamble is enabled. */
firmware_norelease:1; /* Do not release the firmware. Used on suspend. */
struct bcm43xx_sprominfo sprom;
#define BCM43xx_NR_LEDS 4
struct bcm43xx_led leds[BCM43xx_NR_LEDS];
- spinlock_t leds_lock;
/* The currently active core. */
struct bcm43xx_coreinfo *current_core;
struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ];
/* Additional information, specific to the 80211 cores. */
struct bcm43xx_coreinfo_80211 core_80211_ext[ BCM43xx_MAX_80211_CORES ];
+ /* Index of the current 80211 core. If current_core is not
+ * an 80211 core, this is -1.
+ */
+ int current_80211_core_idx;
/* Number of available 80211 cores. */
int nr_80211_available;
/* Reason code of the last interrupt. */
u32 irq_reason;
- u32 dma_reason[6];
+ u32 dma_reason[4];
/* saved irq enable/disable state bitfield. */
u32 irq_savedstate;
/* Link Quality calculation context. */
struct bcm43xx_noise_calculation noisecalc;
- /* if > 0 MAC is suspended. if == 0 MAC is enabled. */
- int mac_suspended;
/* Threshold values. */
//TODO: The RTS thr has to be _used_. Currently, it is only set via WX.
struct tasklet_struct isr_tasklet;
/* Periodic tasks */
- struct work_struct periodic_work;
+ struct timer_list periodic_tasks;
unsigned int periodic_state;
struct work_struct restart_work;
struct bcm43xx_key key[54];
u8 default_key_idx;
- /* Random Number Generator. */
- struct hwrng rng;
- char rng_name[20 + 1];
+ /* Firmware. */
+ const struct firmware *ucode;
+ const struct firmware *pcm;
+ const struct firmware *initvals0;
+ const struct firmware *initvals1;
/* Debugging stuff follows. */
#ifdef CONFIG_BCM43XX_DEBUG
#endif
};
+/* bcm43xx_(un)lock() protect struct bcm43xx_private.
+ * Note that _NO_ MMIO writes are allowed. If you want to
+ * write to the device through MMIO in the critical section, use
+ * the *_mmio lock functions.
+ * MMIO read-access is allowed, though.
+ */
+#define bcm43xx_lock(bcm, flags) spin_lock_irqsave(&(bcm)->_lock, flags)
+#define bcm43xx_unlock(bcm, flags) spin_unlock_irqrestore(&(bcm)->_lock, flags)
+/* bcm43xx_(un)lock_mmio() protect struct bcm43xx_private and MMIO.
+ * MMIO write-access to the device is allowed.
+ * All MMIO writes are flushed on unlock, so it is guaranteed to not
+ * interfere with other threads writing MMIO registers.
+ */
+#define bcm43xx_lock_mmio(bcm, flags) bcm43xx_lock(bcm, flags)
+#define bcm43xx_unlock_mmio(bcm, flags) do { mmiowb(); bcm43xx_unlock(bcm, flags); } while (0)
static inline
struct bcm43xx_private * bcm43xx_priv(struct net_device *dev)
* any of these functions.
*/
static inline
-struct bcm43xx_coreinfo_80211 *
-bcm43xx_current_80211_priv(struct bcm43xx_private *bcm)
-{
- assert(bcm->current_core->id == BCM43xx_COREID_80211);
- return bcm->current_core->priv;
-}
-static inline
struct bcm43xx_pio * bcm43xx_current_pio(struct bcm43xx_private *bcm)
{
assert(bcm43xx_using_pio(bcm));
- return &(bcm43xx_current_80211_priv(bcm)->pio);
+ assert(bcm->current_80211_core_idx >= 0);
+ assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
+ return &(bcm->core_80211_ext[bcm->current_80211_core_idx].pio);
}
static inline
struct bcm43xx_dma * bcm43xx_current_dma(struct bcm43xx_private *bcm)
{
assert(!bcm43xx_using_pio(bcm));
- return &(bcm43xx_current_80211_priv(bcm)->dma);
+ assert(bcm->current_80211_core_idx >= 0);
+ assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
+ return &(bcm->core_80211_ext[bcm->current_80211_core_idx].dma);
}
static inline
struct bcm43xx_phyinfo * bcm43xx_current_phy(struct bcm43xx_private *bcm)
{
- return &(bcm43xx_current_80211_priv(bcm)->phy);
+ assert(bcm->current_80211_core_idx >= 0);
+ assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
+ return &(bcm->core_80211_ext[bcm->current_80211_core_idx].phy);
}
static inline
struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm)
{
- return &(bcm43xx_current_80211_priv(bcm)->radio);
+ assert(bcm->current_80211_core_idx >= 0);
+ assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
+ return &(bcm->core_80211_ext[bcm->current_80211_core_idx].radio);
}
+/* Are we running in init_board() context? */
+static inline
+int bcm43xx_is_initializing(struct bcm43xx_private *bcm)
+{
+ if (bcm->initialized)
+ return 0;
+ if (bcm->shutting_down)
+ return 0;
+ return 1;
+}
static inline
struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy,