linux/drivers/net/wireless/broadcom/b43/main.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*

  Broadcom B43 wireless driver

  Copyright (c) 2005 Martin Langer <[email protected]>
  Copyright (c) 2005 Stefano Brivio <[email protected]>
  Copyright (c) 2005-2009 Michael Buesch <[email protected]>
  Copyright (c) 2005 Danny van Dyk <[email protected]>
  Copyright (c) 2005 Andreas Jaggi <[email protected]>
  Copyright (c) 2010-2011 Rafał Miłecki <[email protected]>

  SDIO support
  Copyright (c) 2009 Albert Herranz <[email protected]>

  Some parts of the code in this file are derived from the ipw2200
  driver  Copyright(c) 2003 - 2004 Intel Corporation.


*/

#include <linux/delay.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
#include <linux/firmware.h>
#include <linux/workqueue.h>
#include <linux/skbuff.h>
#include <linux/io.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/unaligned.h>

#include "b43.h"
#include "main.h"
#include "debugfs.h"
#include "phy_common.h"
#include "phy_g.h"
#include "phy_n.h"
#include "dma.h"
#include "pio.h"
#include "sysfs.h"
#include "xmit.h"
#include "lo.h"
#include "sdio.h"
#include <linux/mmc/sdio_func.h>

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_LICENSE();

MODULE_FIRMWARE();
MODULE_FIRMWARE();
MODULE_FIRMWARE();
MODULE_FIRMWARE();
MODULE_FIRMWARE();
MODULE_FIRMWARE();
MODULE_FIRMWARE();
MODULE_FIRMWARE();
MODULE_FIRMWARE();
MODULE_FIRMWARE();
MODULE_FIRMWARE();
MODULE_FIRMWARE();
MODULE_FIRMWARE();
MODULE_FIRMWARE();
MODULE_FIRMWARE();
MODULE_FIRMWARE();
MODULE_FIRMWARE();

static int modparam_bad_frames_preempt;
module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
MODULE_PARM_DESC();

static char modparam_fwpostfix[16];
module_param_string();
MODULE_PARM_DESC();

static int modparam_hwpctl;
module_param_named(hwpctl, modparam_hwpctl, int, 0444);
MODULE_PARM_DESC();

static int modparam_nohwcrypt;
module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
MODULE_PARM_DESC();

static int modparam_hwtkip;
module_param_named(hwtkip, modparam_hwtkip, int, 0444);
MODULE_PARM_DESC();

static int modparam_qos =;
module_param_named(qos, modparam_qos, int, 0444);
MODULE_PARM_DESC();

static int modparam_btcoex =;
module_param_named(btcoex, modparam_btcoex, int, 0444);
MODULE_PARM_DESC();

int b43_modparam_verbose =;
module_param_named(verbose, b43_modparam_verbose, int, 0644);
MODULE_PARM_DESC();

static int b43_modparam_pio;
module_param_named(pio, b43_modparam_pio, int, 0644);
MODULE_PARM_DESC();

static int modparam_allhwsupport = !IS_ENABLED();
module_param_named(allhwsupport, modparam_allhwsupport, int, 0444);
MODULE_PARM_DESC();

#ifdef CONFIG_B43_BCMA
static const struct bcma_device_id b43_bcma_tbl[] =;
MODULE_DEVICE_TABLE(bcma, b43_bcma_tbl);
#endif

#ifdef CONFIG_B43_SSB
static const struct ssb_device_id b43_ssb_tbl[] =;
MODULE_DEVICE_TABLE(ssb, b43_ssb_tbl);
#endif

/* Channel and ratetables are shared for all devices.
 * They can't be const, because ieee80211 puts some precalculated
 * data in there. This data is the same for all devices, so we don't
 * get concurrency issues */
#define RATETAB_ENT(_rateid, _flags)

/*
 * NOTE: When changing this, sync with xmit.c's
 *	 b43_plcp_get_bitrate_idx_* functions!
 */
static struct ieee80211_rate __b43_ratetable[] =;

#define b43_a_ratetable
#define b43_a_ratetable_size
#define b43_b_ratetable
#define b43_b_ratetable_size
#define b43_g_ratetable
#define b43_g_ratetable_size

#define CHAN2G
static struct ieee80211_channel b43_2ghz_chantable[] =;

/* No support for the last 3 channels (12, 13, 14) */
#define b43_2ghz_chantable_limited_size
#undef CHAN2G

#define CHAN4G
#define CHAN5G
static struct ieee80211_channel b43_5ghz_nphy_chantable[] =;

static struct ieee80211_channel b43_5ghz_nphy_chantable_limited[] =;

static struct ieee80211_channel b43_5ghz_aphy_chantable[] =;
#undef CHAN4G
#undef CHAN5G

static struct ieee80211_supported_band b43_band_5GHz_nphy =;

static struct ieee80211_supported_band b43_band_5GHz_nphy_limited =;

static struct ieee80211_supported_band b43_band_5GHz_aphy =;

static struct ieee80211_supported_band b43_band_2GHz =;

static struct ieee80211_supported_band b43_band_2ghz_limited =;

static void b43_wireless_core_exit(struct b43_wldev *dev);
static int b43_wireless_core_init(struct b43_wldev *dev);
static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev);
static int b43_wireless_core_start(struct b43_wldev *dev);
static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
				    struct ieee80211_vif *vif,
				    struct ieee80211_bss_conf *conf,
				    u64 changed);

static int b43_ratelimit(struct b43_wl *wl)
{}

void b43info(struct b43_wl *wl, const char *fmt, ...)
{}

void b43err(struct b43_wl *wl, const char *fmt, ...)
{}

void b43warn(struct b43_wl *wl, const char *fmt, ...)
{}

void b43dbg(struct b43_wl *wl, const char *fmt, ...)
{}

static void b43_ram_write(struct b43_wldev *dev, u16 offset, u32 val)
{}

static inline void b43_shm_control_word(struct b43_wldev *dev,
					u16 routing, u16 offset)
{}

u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset)
{}

u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset)
{}

void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value)
{}

void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value)
{}

/* Read HostFlags */
u64 b43_hf_read(struct b43_wldev *dev)
{}

/* Write HostFlags */
void b43_hf_write(struct b43_wldev *dev, u64 value)
{}

/* Read the firmware capabilities bitmask (Opensource firmware only) */
static u16 b43_fwcapa_read(struct b43_wldev *dev)
{}

void b43_tsf_read(struct b43_wldev *dev, u64 *tsf)
{}

static void b43_time_lock(struct b43_wldev *dev)
{}

static void b43_time_unlock(struct b43_wldev *dev)
{}

static void b43_tsf_write_locked(struct b43_wldev *dev, u64 tsf)
{}

void b43_tsf_write(struct b43_wldev *dev, u64 tsf)
{}

static
void b43_macfilter_set(struct b43_wldev *dev, u16 offset, const u8 *mac)
{}

static void b43_write_mac_bssid_templates(struct b43_wldev *dev)
{}

static void b43_upload_card_macaddress(struct b43_wldev *dev)
{}

static void b43_set_slot_time(struct b43_wldev *dev, u16 slot_time)
{}

static void b43_short_slot_timing_enable(struct b43_wldev *dev)
{}

static void b43_short_slot_timing_disable(struct b43_wldev *dev)
{}

/* DummyTransmission function, as documented on
 * https://bcm-v4.sipsolutions.net/802.11/DummyTransmission
 */
void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on)
{}

static void key_write(struct b43_wldev *dev,
		      u8 index, u8 algorithm, const u8 *key)
{}

static void keymac_write(struct b43_wldev *dev, u8 index, const u8 *addr)
{}

/* The ucode will use phase1 key with TEK key to decrypt rx packets.
 * When a packet is received, the iv32 is checked.
 * - if it doesn't the packet is returned without modification (and software
 *   decryption can be done). That's what happen when iv16 wrap.
 * - if it does, the rc4 key is computed, and decryption is tried.
 *   Either it will success and B43_RX_MAC_DEC is returned,
 *   either it fails and B43_RX_MAC_DEC|B43_RX_MAC_DECERR is returned
 *   and the packet is not usable (it got modified by the ucode).
 * So in order to never have B43_RX_MAC_DECERR, we should provide
 * a iv32 and phase1key that match. Because we drop packets in case of
 * B43_RX_MAC_DECERR, if we have a correct iv32 but a wrong phase1key, all
 * packets will be lost without higher layer knowing (ie no resync possible
 * until next wrap).
 *
 * NOTE : this should support 50 key like RCMTA because
 * (B43_SHM_SH_KEYIDXBLOCK - B43_SHM_SH_TKIPTSCTTAK)/14 = 50
 */
static void rx_tkip_phase1_write(struct b43_wldev *dev, u8 index, u32 iv32,
		u16 *phase1key)
{}

static void b43_op_update_tkip_key(struct ieee80211_hw *hw,
				   struct ieee80211_vif *vif,
				   struct ieee80211_key_conf *keyconf,
				   struct ieee80211_sta *sta,
				   u32 iv32, u16 *phase1key)
{}

static void do_key_write(struct b43_wldev *dev,
			 u8 index, u8 algorithm,
			 const u8 *key, size_t key_len, const u8 *mac_addr)
{}

static int b43_key_write(struct b43_wldev *dev,
			 int index, u8 algorithm,
			 const u8 *key, size_t key_len,
			 const u8 *mac_addr,
			 struct ieee80211_key_conf *keyconf)
{}

static int b43_key_clear(struct b43_wldev *dev, int index)
{}

static void b43_clear_keys(struct b43_wldev *dev)
{}

static void b43_dump_keymemory(struct b43_wldev *dev)
{}

void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags)
{}

/* https://bcm-v4.sipsolutions.net/802.11/PHY/BmacCorePllReset */
void b43_wireless_core_phy_pll_reset(struct b43_wldev *dev)
{}

#ifdef CONFIG_B43_BCMA
static void b43_bcma_phy_reset(struct b43_wldev *dev)
{}

static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode)
{}
#endif

#ifdef CONFIG_B43_SSB
static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, bool gmode)
{}
#endif

void b43_wireless_core_reset(struct b43_wldev *dev, bool gmode)
{}

static void handle_irq_transmit_status(struct b43_wldev *dev)
{}

static void drain_txstatus_queue(struct b43_wldev *dev)
{}

static u32 b43_jssi_read(struct b43_wldev *dev)
{}

static void b43_jssi_write(struct b43_wldev *dev, u32 jssi)
{}

static void b43_generate_noise_sample(struct b43_wldev *dev)
{}

static void b43_calculate_link_quality(struct b43_wldev *dev)
{}

static void handle_irq_noise(struct b43_wldev *dev)
{}

static void handle_irq_tbtt_indication(struct b43_wldev *dev)
{}

static void handle_irq_atim_end(struct b43_wldev *dev)
{}

static void handle_irq_pmq(struct b43_wldev *dev)
{}

static void b43_write_template_common(struct b43_wldev *dev,
				      const u8 *data, u16 size,
				      u16 ram_offset,
				      u16 shm_size_offset, u8 rate)
{}

/* Check if the use of the antenna that ieee80211 told us to
 * use is possible. This will fall back to DEFAULT.
 * "antenna_nr" is the antenna identifier we got from ieee80211. */
u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev,
				  u8 antenna_nr)
{}

/* Convert a b43 antenna number value to the PHY TX control value. */
static u16 b43_antenna_to_phyctl(int antenna)
{}

static void b43_write_beacon_template(struct b43_wldev *dev,
				      u16 ram_offset,
				      u16 shm_size_offset)
{}

static void b43_upload_beacon0(struct b43_wldev *dev)
{}

static void b43_upload_beacon1(struct b43_wldev *dev)
{}

static void handle_irq_beacon(struct b43_wldev *dev)
{}

static void b43_do_beacon_update_trigger_work(struct b43_wldev *dev)
{}

static void b43_beacon_update_trigger_work(struct work_struct *work)
{}

/* Asynchronously update the packet templates in template RAM. */
static void b43_update_templates(struct b43_wl *wl)
{}

static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
{}

static void b43_handle_firmware_panic(struct b43_wldev *dev)
{}

static void handle_irq_ucode_debug(struct b43_wldev *dev)
{}

static void b43_do_interrupt_thread(struct b43_wldev *dev)
{}

/* Interrupt thread handler. Handles device interrupts in thread context. */
static irqreturn_t b43_interrupt_thread_handler(int irq, void *dev_id)
{}

static irqreturn_t b43_do_interrupt(struct b43_wldev *dev)
{}

/* Interrupt handler top-half. This runs with interrupts disabled. */
static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
{}

/* SDIO interrupt handler. This runs in process context. */
static void b43_sdio_interrupt_handler(struct b43_wldev *dev)
{}

void b43_do_release_fw(struct b43_firmware_file *fw)
{}

static void b43_release_firmware(struct b43_wldev *dev)
{}

static void b43_print_fw_helptext(struct b43_wl *wl, bool error)
{}

static void b43_fw_cb(const struct firmware *firmware, void *context)
{}

int b43_do_request_fw(struct b43_request_fw_context *ctx,
		      const char *name,
		      struct b43_firmware_file *fw, bool async)
{}

/* https://bcm-v4.sipsolutions.net/802.11/Init/Firmware */
static int b43_try_request_fw(struct b43_request_fw_context *ctx)
{}

static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl);
static void b43_one_core_detach(struct b43_bus_dev *dev);
static int b43_rng_init(struct b43_wl *wl);

static void b43_request_firmware(struct work_struct *work)
{}

static int b43_upload_microcode(struct b43_wldev *dev)
{}

static int b43_write_initvals(struct b43_wldev *dev,
			      const struct b43_iv *ivals,
			      size_t count,
			      size_t array_size)
{}

static int b43_upload_initvals(struct b43_wldev *dev)
{}

static int b43_upload_initvals_band(struct b43_wldev *dev)
{}

/* Initialize the GPIOs
 * https://bcm-specs.sipsolutions.net/GPIO
 */

#ifdef CONFIG_B43_SSB
static struct ssb_device *b43_ssb_gpio_dev(struct b43_wldev *dev)
{}
#endif

static int b43_gpio_init(struct b43_wldev *dev)
{}

/* Turn off all GPIO stuff. Call this on module unload, for example. */
static void b43_gpio_cleanup(struct b43_wldev *dev)
{}

/* http://bcm-specs.sipsolutions.net/EnableMac */
void b43_mac_enable(struct b43_wldev *dev)
{}

/* https://bcm-specs.sipsolutions.net/SuspendMAC */
void b43_mac_suspend(struct b43_wldev *dev)
{}

/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */
void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on)
{}

/* brcms_b_switch_macfreq */
void b43_mac_switch_freq(struct b43_wldev *dev, u8 spurmode)
{}

static void b43_adjust_opmode(struct b43_wldev *dev)
{}

static void b43_rate_memory_write(struct b43_wldev *dev, u16 rate, int is_ofdm)
{}

static void b43_rate_memory_init(struct b43_wldev *dev)
{}

/* Set the default values for the PHY TX Control Words. */
static void b43_set_phytxctl_defaults(struct b43_wldev *dev)
{}

/* Set the TX-Antenna for management frames sent by firmware. */
static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna)
{}

/* This is the opposite of b43_chip_init() */
static void b43_chip_exit(struct b43_wldev *dev)
{}

/* Initialize the chip
 * https://bcm-specs.sipsolutions.net/ChipInit
 */
static int b43_chip_init(struct b43_wldev *dev)
{}

static void b43_periodic_every60sec(struct b43_wldev *dev)
{}

static void b43_periodic_every30sec(struct b43_wldev *dev)
{}

static void b43_periodic_every15sec(struct b43_wldev *dev)
{}

static void do_periodic_work(struct b43_wldev *dev)
{}

/* Periodic work locking policy:
 * 	The whole periodic work handler is protected by
 * 	wl->mutex. If another lock is needed somewhere in the
 * 	pwork callchain, it's acquired in-place, where it's needed.
 */
static void b43_periodic_work_handler(struct work_struct *work)
{}

static void b43_periodic_tasks_setup(struct b43_wldev *dev)
{}

/* Check if communication with the device works correctly. */
static int b43_validate_chipaccess(struct b43_wldev *dev)
{}

static void b43_security_init(struct b43_wldev *dev)
{}

#ifdef CONFIG_B43_HWRNG
static int b43_rng_read(struct hwrng *rng, u32 *data)
{}
#endif /* CONFIG_B43_HWRNG */

static void b43_rng_exit(struct b43_wl *wl)
{}

static int b43_rng_init(struct b43_wl *wl)
{}

static void b43_tx_work(struct work_struct *work)
{}

static void b43_op_tx(struct ieee80211_hw *hw,
		      struct ieee80211_tx_control *control,
		      struct sk_buff *skb)
{}

static void b43_qos_params_upload(struct b43_wldev *dev,
				  const struct ieee80211_tx_queue_params *p,
				  u16 shm_offset)
{}

/* Mapping of mac80211 queue numbers to b43 QoS SHM offsets. */
static const u16 b43_qos_shm_offsets[] =;

/* Update all QOS parameters in hardware. */
static void b43_qos_upload_all(struct b43_wldev *dev)
{}

static void b43_qos_clear(struct b43_wl *wl)
{}

/* Initialize the core's QOS capabilities */
static void b43_qos_init(struct b43_wldev *dev)
{}

static int b43_op_conf_tx(struct ieee80211_hw *hw,
			  struct ieee80211_vif *vif,
			  unsigned int link_id, u16 _queue,
			  const struct ieee80211_tx_queue_params *params)
{}

static int b43_op_get_stats(struct ieee80211_hw *hw,
			    struct ieee80211_low_level_stats *stats)
{}

static u64 b43_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{}

static void b43_op_set_tsf(struct ieee80211_hw *hw,
			   struct ieee80211_vif *vif, u64 tsf)
{}

static const char *band_to_string(enum nl80211_band band)
{}

/* Expects wl->mutex locked */
static int b43_switch_band(struct b43_wldev *dev,
			   struct ieee80211_channel *chan)
{}

static void b43_set_beacon_listen_interval(struct b43_wldev *dev, u16 interval)
{}

/* Write the short and long frame retry limit values. */
static void b43_set_retry_limits(struct b43_wldev *dev,
				 unsigned int short_retry,
				 unsigned int long_retry)
{}

static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
{}

static void b43_update_basic_rates(struct b43_wldev *dev, u32 brates)
{}

static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
				    struct ieee80211_vif *vif,
				    struct ieee80211_bss_conf *conf,
				    u64 changed)
{}

static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
			  struct ieee80211_vif *vif, struct ieee80211_sta *sta,
			  struct ieee80211_key_conf *key)
{}

static void b43_op_configure_filter(struct ieee80211_hw *hw,
				    unsigned int changed, unsigned int *fflags,
				    u64 multicast)
{}

/* Locking: wl->mutex
 * Returns the current dev. This might be different from the passed in dev,
 * because the core might be gone away while we unlocked the mutex. */
static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev)
{}

/* Locking: wl->mutex */
static int b43_wireless_core_start(struct b43_wldev *dev)
{}

static char *b43_phy_name(struct b43_wldev *dev, u8 phy_type)
{}

/* Get PHY and RADIO versioning numbers */
static int b43_phy_versioning(struct b43_wldev *dev)
{}

static void setup_struct_phy_for_init(struct b43_wldev *dev,
				      struct b43_phy *phy)
{}

static void setup_struct_wldev_for_init(struct b43_wldev *dev)
{}

static void b43_bluetooth_coext_enable(struct b43_wldev *dev)
{}

static void b43_bluetooth_coext_disable(struct b43_wldev *dev)
{}

static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev)
{}

static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle)
{}

/* Set the TSF CFP pre-TargetBeaconTransmissionTime. */
static void b43_set_pretbtt(struct b43_wldev *dev)
{}

/* Shutdown a wireless core */
/* Locking: wl->mutex */
static void b43_wireless_core_exit(struct b43_wldev *dev)
{}

/* Initialize a wireless core */
static int b43_wireless_core_init(struct b43_wldev *dev)
{}

static int b43_op_add_interface(struct ieee80211_hw *hw,
				struct ieee80211_vif *vif)
{}

static void b43_op_remove_interface(struct ieee80211_hw *hw,
				    struct ieee80211_vif *vif)
{}

static int b43_op_start(struct ieee80211_hw *hw)
{}

static void b43_op_stop(struct ieee80211_hw *hw, bool suspend)
{}

static int b43_op_beacon_set_tim(struct ieee80211_hw *hw,
				 struct ieee80211_sta *sta, bool set)
{}

static void b43_op_sta_notify(struct ieee80211_hw *hw,
			      struct ieee80211_vif *vif,
			      enum sta_notify_cmd notify_cmd,
			      struct ieee80211_sta *sta)
{}

static void b43_op_sw_scan_start_notifier(struct ieee80211_hw *hw,
					  struct ieee80211_vif *vif,
					  const u8 *mac_addr)
{}

static void b43_op_sw_scan_complete_notifier(struct ieee80211_hw *hw,
					     struct ieee80211_vif *vif)
{}

static int b43_op_get_survey(struct ieee80211_hw *hw, int idx,
			     struct survey_info *survey)
{}

static const struct ieee80211_ops b43_hw_ops =;

/* Hard-reset the chip. Do not call this directly.
 * Use b43_controller_restart()
 */
static void b43_chip_reset(struct work_struct *work)
{}

static int b43_setup_bands(struct b43_wldev *dev,
			   bool have_2ghz_phy, bool have_5ghz_phy)
{}

static void b43_wireless_core_detach(struct b43_wldev *dev)
{}

static void b43_supported_bands(struct b43_wldev *dev, bool *have_2ghz_phy,
				bool *have_5ghz_phy)
{}

static int b43_wireless_core_attach(struct b43_wldev *dev)
{}

static void b43_one_core_detach(struct b43_bus_dev *dev)
{}

static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl)
{}

#define IS_PDEV(pdev, _vendor, _device, _subvendor, _subdevice)

#ifdef CONFIG_B43_SSB
static void b43_sprom_fixup(struct ssb_bus *bus)
{}

static void b43_wireless_exit(struct b43_bus_dev *dev, struct b43_wl *wl)
{}
#endif

static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
{}

#ifdef CONFIG_B43_BCMA
static int b43_bcma_probe(struct bcma_device *core)
{}

static void b43_bcma_remove(struct bcma_device *core)
{}

static struct bcma_driver b43_bcma_driver =;
#endif

#ifdef CONFIG_B43_SSB
static
int b43_ssb_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
{}

static void b43_ssb_remove(struct ssb_device *sdev)
{}

static struct ssb_driver b43_ssb_driver =;
#endif /* CONFIG_B43_SSB */

/* Perform a hardware reset. This can be called from any context. */
void b43_controller_restart(struct b43_wldev *dev, const char *reason)
{}

static void b43_print_driverinfo(void)
{}

static int __init b43_init(void)
{}

static void __exit b43_exit(void)
{}

module_init()
module_exit()