linux/drivers/net/wireless/ath/ath5k/base.c

/*-
 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
 * Copyright (c) 2004-2005 Atheros Communications, Inc.
 * Copyright (c) 2006 Devicescape Software, Inc.
 * Copyright (c) 2007 Jiri Slaby <[email protected]>
 * Copyright (c) 2007 Luis R. Rodriguez <[email protected]>
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer,
 *    without modification.
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
 *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
 *    redistribution must be conditioned upon including a substantially
 *    similar Disclaimer requirement for further binary redistribution.
 * 3. Neither the names of the above-listed copyright holders nor the names
 *    of any contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
 *
 * NO WARRANTY
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGES.
 *
 */

#define pr_fmt(fmt)

#include <linux/module.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/hardirq.h>
#include <linux/if.h>
#include <linux/io.h>
#include <linux/netdevice.h>
#include <linux/cache.h>
#include <linux/ethtool.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/etherdevice.h>
#include <linux/nl80211.h>

#include <net/cfg80211.h>
#include <net/ieee80211_radiotap.h>

#include <asm/unaligned.h>

#include <net/mac80211.h>
#include "base.h"
#include "reg.h"
#include "debug.h"
#include "ani.h"
#include "ath5k.h"
#include "../regd.h"

#define CREATE_TRACE_POINTS
#include "trace.h"

bool ath5k_modparam_nohwcrypt;
module_param_named(nohwcrypt, ath5k_modparam_nohwcrypt, bool, 0444);
MODULE_PARM_DESC();

static bool modparam_fastchanswitch;
module_param_named(fastchanswitch, modparam_fastchanswitch, bool, 0444);
MODULE_PARM_DESC();

static bool ath5k_modparam_no_hw_rfkill_switch;
module_param_named(no_hw_rfkill_switch, ath5k_modparam_no_hw_rfkill_switch,
		   bool, 0444);
MODULE_PARM_DESC();


/* Module info */
MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();

static int ath5k_init(struct ieee80211_hw *hw);
static int ath5k_reset(struct ath5k_hw *ah, struct ieee80211_channel *chan,
								bool skip_pcu);

/* Known SREVs */
static const struct ath5k_srev_name srev_names[] =;

static const struct ieee80211_rate ath5k_rates[] =;

static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
{}

const char *
ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val)
{}
static unsigned int ath5k_ioread32(void *hw_priv, u32 reg_offset)
{}

static void ath5k_iowrite32(void *hw_priv, u32 val, u32 reg_offset)
{}

static const struct ath_ops ath5k_common_ops =;

/***********************\
* Driver Initialization *
\***********************/

static void ath5k_reg_notifier(struct wiphy *wiphy,
			       struct regulatory_request *request)
{}

/********************\
* Channel/mode setup *
\********************/

/*
 * Returns true for the channel numbers used.
 */
#ifdef CONFIG_ATH5K_TEST_CHANNELS
static bool ath5k_is_standard_channel(short chan, enum nl80211_band band)
{}

#else
static bool ath5k_is_standard_channel(short chan, enum nl80211_band band)
{
	if (band == NL80211_BAND_2GHZ && chan <= 14)
		return true;

	return	/* UNII 1,2 */
		(((chan & 3) == 0 && chan >= 36 && chan <= 64) ||
		/* midband */
		((chan & 3) == 0 && chan >= 100 && chan <= 140) ||
		/* UNII-3 */
		((chan & 3) == 1 && chan >= 149 && chan <= 165) ||
		/* 802.11j 5.030-5.080 GHz (20MHz) */
		(chan == 8 || chan == 12 || chan == 16) ||
		/* 802.11j 4.9GHz (20MHz) */
		(chan == 184 || chan == 188 || chan == 192 || chan == 196));
}
#endif

static unsigned int
ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels,
		unsigned int mode, unsigned int max)
{}

static void
ath5k_setup_rate_idx(struct ath5k_hw *ah, struct ieee80211_supported_band *b)
{}

static int
ath5k_setup_bands(struct ieee80211_hw *hw)
{}

/*
 * Set/change channels. We always reset the chip.
 * To accomplish this we must first cleanup any pending DMA,
 * then restart stuff after a la  ath5k_init.
 *
 * Called with ah->lock.
 */
int
ath5k_chan_set(struct ath5k_hw *ah, struct cfg80211_chan_def *chandef)
{}

void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
{}

void
ath5k_update_bssid_mask_and_opmode(struct ath5k_hw *ah,
				   struct ieee80211_vif *vif)
{}

static inline int
ath5k_hw_to_driver_rix(struct ath5k_hw *ah, int hw_rix)
{}

/***************\
* Buffers setup *
\***************/

static
struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_hw *ah, dma_addr_t *skb_addr)
{}

static int
ath5k_rxbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf)
{}

static enum ath5k_pkt_type get_hw_packet_type(struct sk_buff *skb)
{}

static struct ieee80211_rate *
ath5k_get_rate(const struct ieee80211_hw *hw,
	       const struct ieee80211_tx_info *info,
	       struct ath5k_buf *bf, int idx)
{}

static u16
ath5k_get_rate_hw_value(const struct ieee80211_hw *hw,
			const struct ieee80211_tx_info *info,
			struct ath5k_buf *bf, int idx)
{}

static bool ath5k_merge_ratetbl(struct ieee80211_sta *sta,
				struct ath5k_buf *bf,
				struct ieee80211_tx_info *tx_info)
{}

static int
ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf,
		  struct ath5k_txq *txq, int padsize,
		  struct ieee80211_tx_control *control)
{}

/*******************\
* Descriptors setup *
\*******************/

static int
ath5k_desc_alloc(struct ath5k_hw *ah)
{}

void
ath5k_txbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf)
{}

void
ath5k_rxbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf)
{}

static void
ath5k_desc_free(struct ath5k_hw *ah)
{}


/**************\
* Queues setup *
\**************/

static struct ath5k_txq *
ath5k_txq_setup(struct ath5k_hw *ah,
		int qtype, int subtype)
{}

static int
ath5k_beaconq_setup(struct ath5k_hw *ah)
{}

static int
ath5k_beaconq_config(struct ath5k_hw *ah)
{}

/**
 * ath5k_drain_tx_buffs - Empty tx buffers
 *
 * @ah: The &struct ath5k_hw
 *
 * Empty tx buffers from all queues in preparation
 * of a reset or during shutdown.
 *
 * NB:	this assumes output has been stopped and
 *	we do not need to block ath5k_tx_tasklet
 */
static void
ath5k_drain_tx_buffs(struct ath5k_hw *ah)
{}

static void
ath5k_txq_release(struct ath5k_hw *ah)
{}


/*************\
* RX Handling *
\*************/

/*
 * Enable the receive h/w following a reset.
 */
static int
ath5k_rx_start(struct ath5k_hw *ah)
{}

/*
 * Disable the receive logic on PCU (DRU)
 * In preparation for a shutdown.
 *
 * Note: Doesn't stop rx DMA, ath5k_hw_dma_stop
 * does.
 */
static void
ath5k_rx_stop(struct ath5k_hw *ah)
{}

static unsigned int
ath5k_rx_decrypted(struct ath5k_hw *ah, struct sk_buff *skb,
		   struct ath5k_rx_status *rs)
{}


static void
ath5k_check_ibss_tsf(struct ath5k_hw *ah, struct sk_buff *skb,
		     struct ieee80211_rx_status *rxs)
{}

/*
 * Compute padding position. skb must contain an IEEE 802.11 frame
 */
static int ath5k_common_padpos(struct sk_buff *skb)
{}

/*
 * This function expects an 802.11 frame and returns the number of
 * bytes added, or -1 if we don't have enough header room.
 */
static int ath5k_add_padding(struct sk_buff *skb)
{}

/*
 * The MAC header is padded to have 32-bit boundary if the
 * packet payload is non-zero. The general calculation for
 * padsize would take into account odd header lengths:
 * padsize = 4 - (hdrlen & 3); however, since only
 * even-length headers are used, padding can only be 0 or 2
 * bytes and we can optimize this a bit.  We must not try to
 * remove padding from short control frames that do not have a
 * payload.
 *
 * This function expects an 802.11 frame and returns the number of
 * bytes removed.
 */
static int ath5k_remove_padding(struct sk_buff *skb)
{}

static void
ath5k_receive_frame(struct ath5k_hw *ah, struct sk_buff *skb,
		    struct ath5k_rx_status *rs)
{}

/** ath5k_frame_receive_ok() - Do we want to receive this frame or not?
 *
 * Check if we want to further process this frame or not. Also update
 * statistics. Return true if we want this frame, false if not.
 */
static bool
ath5k_receive_frame_ok(struct ath5k_hw *ah, struct ath5k_rx_status *rs)
{}

static void
ath5k_set_current_imask(struct ath5k_hw *ah)
{}

static void
ath5k_tasklet_rx(struct tasklet_struct *t)
{}


/*************\
* TX Handling *
\*************/

void
ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
	       struct ath5k_txq *txq, struct ieee80211_tx_control *control)
{}

static void
ath5k_tx_frame_completed(struct ath5k_hw *ah, struct sk_buff *skb,
			 struct ath5k_txq *txq, struct ath5k_tx_status *ts,
			 struct ath5k_buf *bf)
{}

static void
ath5k_tx_processq(struct ath5k_hw *ah, struct ath5k_txq *txq)
{}

static void
ath5k_tasklet_tx(struct tasklet_struct *t)
{}


/*****************\
* Beacon handling *
\*****************/

/*
 * Setup the beacon frame for transmit.
 */
static int
ath5k_beacon_setup(struct ath5k_hw *ah, struct ath5k_buf *bf)
{}

/*
 * Updates the beacon that is sent by ath5k_beacon_send.  For adhoc,
 * this is called only once at config_bss time, for AP we do it every
 * SWBA interrupt so that the TIM will reflect buffered frames.
 *
 * Called with the beacon lock.
 */
int
ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{}

/*
 * Transmit a beacon frame at SWBA.  Dynamic updates to the
 * frame contents are done as needed and the slot time is
 * also adjusted based on current state.
 *
 * This is called from software irq context (beacontq tasklets)
 * or user context from ath5k_beacon_config.
 */
static void
ath5k_beacon_send(struct ath5k_hw *ah)
{}

/**
 * ath5k_beacon_update_timers - update beacon timers
 *
 * @ah: struct ath5k_hw pointer we are operating on
 * @bc_tsf: the timestamp of the beacon. 0 to reset the TSF. -1 to perform a
 *          beacon timer update based on the current HW TSF.
 *
 * Calculate the next target beacon transmit time (TBTT) based on the timestamp
 * of a received beacon or the current local hardware TSF and write it to the
 * beacon timer registers.
 *
 * This is called in a variety of situations, e.g. when a beacon is received,
 * when a TSF update has been detected, but also when an new IBSS is created or
 * when we otherwise know we have to update the timers, but we keep it in this
 * function to have it all together in one place.
 */
void
ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf)
{}

/**
 * ath5k_beacon_config - Configure the beacon queues and interrupts
 *
 * @ah: struct ath5k_hw pointer we are operating on
 *
 * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA
 * interrupts to detect TSF updates only.
 */
void
ath5k_beacon_config(struct ath5k_hw *ah)
{}

static void ath5k_tasklet_beacon(struct tasklet_struct *t)
{}


/********************\
* Interrupt handling *
\********************/

static void
ath5k_intr_calibration_poll(struct ath5k_hw *ah)
{}

static void
ath5k_schedule_rx(struct ath5k_hw *ah)
{}

static void
ath5k_schedule_tx(struct ath5k_hw *ah)
{}

static irqreturn_t
ath5k_intr(int irq, void *dev_id)
{}

/*
 * Periodically recalibrate the PHY to account
 * for temperature/environment changes.
 */
static void
ath5k_calibrate_work(struct work_struct *work)
{}


static void
ath5k_tasklet_ani(struct tasklet_struct *t)
{}


static void
ath5k_tx_complete_poll_work(struct work_struct *work)
{}


/*************************\
* Initialization routines *
\*************************/

static const struct ieee80211_iface_limit if_limits[] =;

static const struct ieee80211_iface_combination if_comb =;

int
ath5k_init_ah(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops)
{}

static int
ath5k_stop_locked(struct ath5k_hw *ah)
{}

int ath5k_start(struct ieee80211_hw *hw)
{}

static void ath5k_stop_tasklets(struct ath5k_hw *ah)
{}

/*
 * Stop the device, grabbing the top-level lock to protect
 * against concurrent entry through ath5k_init (which can happen
 * if another thread does a system call and the thread doing the
 * stop is preempted).
 */
void ath5k_stop(struct ieee80211_hw *hw, bool suspend)
{}

/*
 * Reset the hardware.  If chan is not NULL, then also pause rx/tx
 * and change to the given channel.
 *
 * This should be called with ah->lock.
 */
static int
ath5k_reset(struct ath5k_hw *ah, struct ieee80211_channel *chan,
							bool skip_pcu)
{}

static void ath5k_reset_work(struct work_struct *work)
{}

static int
ath5k_init(struct ieee80211_hw *hw)
{}

void
ath5k_deinit_ah(struct ath5k_hw *ah)
{}

bool
ath5k_any_vif_assoc(struct ath5k_hw *ah)
{}

void
ath5k_set_beacon_filter(struct ieee80211_hw *hw, bool enable)
{}

void _ath5k_printk(const struct ath5k_hw *ah, const char *level,
		   const char *fmt, ...)
{}