Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6

This commit is contained in:
David S. Miller 2009-02-28 22:32:16 -08:00
commit 8010dc306b
126 changed files with 8014 additions and 4149 deletions

View file

@ -228,6 +228,14 @@ config PCMCIA_ATMEL
Enable support for PCMCIA cards containing the
Atmel at76c502 and at76c504 chips.
config AT76C50X_USB
tristate "Atmel at76c503/at76c505/at76c505a USB cards"
depends on MAC80211 && WLAN_80211 && USB
select FW_LOADER
---help---
Enable support for USB Wireless devices using Atmel at76c503,
at76c505 or at76c505a chips.
config AIRO_CS
tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards"
depends on PCMCIA && (BROKEN || !M32R) && WLAN_80211

View file

@ -24,6 +24,8 @@ obj-$(CONFIG_ATMEL) += atmel.o
obj-$(CONFIG_PCI_ATMEL) += atmel_pci.o
obj-$(CONFIG_PCMCIA_ATMEL) += atmel_cs.o
obj-$(CONFIG_AT76C50X_USB) += at76c50x-usb.o
obj-$(CONFIG_PRISM54) += prism54/
obj-$(CONFIG_HOSTAP) += hostap/

View file

@ -4727,7 +4727,7 @@ static int proc_stats_rid_open( struct inode *inode,
StatsRid stats;
int i, j;
__le32 *vals = stats.vals;
int len = le16_to_cpu(stats.len);
int len;
if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
return -ENOMEM;
@ -4738,6 +4738,7 @@ static int proc_stats_rid_open( struct inode *inode,
}
readStatsRid(apriv, &stats, rid, 1);
len = le16_to_cpu(stats.len);
j = 0;
for(i=0; statsLabels[i]!=(char *)-1 && i*4<len; i++) {

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,463 @@
/*
* Copyright (c) 2002,2003 Oliver Kurth
* (c) 2003,2004 Joerg Albert <joerg.albert@gmx.de>
* (c) 2007 Guido Guenther <agx@sigxcpu.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This driver was based on information from the Sourceforge driver
* released and maintained by Atmel:
*
* http://sourceforge.net/projects/atmelwlandriver/
*
* Although the code was completely re-written,
* it would have been impossible without Atmel's decision to
* release an Open Source driver (unfortunately the firmware was
* kept binary only). Thanks for that decision to Atmel!
*/
#ifndef _AT76_USB_H
#define _AT76_USB_H
/* Board types */
enum board_type {
BOARD_503_ISL3861 = 1,
BOARD_503_ISL3863 = 2,
BOARD_503 = 3,
BOARD_503_ACC = 4,
BOARD_505 = 5,
BOARD_505_2958 = 6,
BOARD_505A = 7,
BOARD_505AMX = 8
};
#define CMD_STATUS_IDLE 0x00
#define CMD_STATUS_COMPLETE 0x01
#define CMD_STATUS_UNKNOWN 0x02
#define CMD_STATUS_INVALID_PARAMETER 0x03
#define CMD_STATUS_FUNCTION_NOT_SUPPORTED 0x04
#define CMD_STATUS_TIME_OUT 0x07
#define CMD_STATUS_IN_PROGRESS 0x08
#define CMD_STATUS_HOST_FAILURE 0xff
#define CMD_STATUS_SCAN_FAILED 0xf0
/* answers to get op mode */
#define OPMODE_NONE 0x00
#define OPMODE_NORMAL_NIC_WITH_FLASH 0x01
#define OPMODE_HW_CONFIG_MODE 0x02
#define OPMODE_DFU_MODE_WITH_FLASH 0x03
#define OPMODE_NORMAL_NIC_WITHOUT_FLASH 0x04
#define CMD_SET_MIB 0x01
#define CMD_GET_MIB 0x02
#define CMD_SCAN 0x03
#define CMD_JOIN 0x04
#define CMD_START_IBSS 0x05
#define CMD_RADIO_ON 0x06
#define CMD_RADIO_OFF 0x07
#define CMD_STARTUP 0x0B
#define MIB_LOCAL 0x01
#define MIB_MAC_ADDR 0x02
#define MIB_MAC 0x03
#define MIB_MAC_MGMT 0x05
#define MIB_MAC_WEP 0x06
#define MIB_PHY 0x07
#define MIB_FW_VERSION 0x08
#define MIB_MDOMAIN 0x09
#define ADHOC_MODE 1
#define INFRASTRUCTURE_MODE 2
/* values for struct mib_local, field preamble_type */
#define PREAMBLE_TYPE_LONG 0
#define PREAMBLE_TYPE_SHORT 1
#define PREAMBLE_TYPE_AUTO 2
/* values for tx_rate */
#define TX_RATE_1MBIT 0
#define TX_RATE_2MBIT 1
#define TX_RATE_5_5MBIT 2
#define TX_RATE_11MBIT 3
#define TX_RATE_AUTO 4
/* power management modes */
#define AT76_PM_OFF 1
#define AT76_PM_ON 2
#define AT76_PM_SMART 3
struct hwcfg_r505 {
u8 cr39_values[14];
u8 reserved1[14];
u8 bb_cr[14];
u8 pidvid[4];
u8 mac_addr[ETH_ALEN];
u8 regulatory_domain;
u8 reserved2[14];
u8 cr15_values[14];
u8 reserved3[3];
} __attribute__((packed));
struct hwcfg_rfmd {
u8 cr20_values[14];
u8 cr21_values[14];
u8 bb_cr[14];
u8 pidvid[4];
u8 mac_addr[ETH_ALEN];
u8 regulatory_domain;
u8 low_power_values[14];
u8 normal_power_values[14];
u8 reserved1[3];
} __attribute__((packed));
struct hwcfg_intersil {
u8 mac_addr[ETH_ALEN];
u8 cr31_values[14];
u8 cr58_values[14];
u8 pidvid[4];
u8 regulatory_domain;
u8 reserved[1];
} __attribute__((packed));
union at76_hwcfg {
struct hwcfg_intersil i;
struct hwcfg_rfmd r3;
struct hwcfg_r505 r5;
};
#define WEP_SMALL_KEY_LEN (40 / 8)
#define WEP_LARGE_KEY_LEN (104 / 8)
#define WEP_KEYS (4)
struct at76_card_config {
u8 exclude_unencrypted;
u8 promiscuous_mode;
u8 short_retry_limit;
u8 encryption_type;
__le16 rts_threshold;
__le16 fragmentation_threshold; /* 256..2346 */
u8 basic_rate_set[4];
u8 auto_rate_fallback; /* 0,1 */
u8 channel;
u8 privacy_invoked;
u8 wep_default_key_id; /* 0..3 */
u8 current_ssid[32];
u8 wep_default_key_value[4][WEP_LARGE_KEY_LEN];
u8 ssid_len;
u8 short_preamble;
__le16 beacon_period;
} __attribute__((packed));
struct at76_command {
u8 cmd;
u8 reserved;
__le16 size;
u8 data[0];
} __attribute__((packed));
/* Length of Atmel-specific Rx header before 802.11 frame */
#define AT76_RX_HDRLEN offsetof(struct at76_rx_buffer, packet)
struct at76_rx_buffer {
__le16 wlength;
u8 rx_rate;
u8 newbss;
u8 fragmentation;
u8 rssi;
u8 link_quality;
u8 noise_level;
__le32 rx_time;
u8 packet[IEEE80211_MAX_FRAG_THRESHOLD];
} __attribute__((packed));
/* Length of Atmel-specific Tx header before 802.11 frame */
#define AT76_TX_HDRLEN offsetof(struct at76_tx_buffer, packet)
struct at76_tx_buffer {
__le16 wlength;
u8 tx_rate;
u8 padding;
u8 reserved[4];
u8 packet[IEEE80211_MAX_FRAG_THRESHOLD];
} __attribute__((packed));
/* defines for scan_type below */
#define SCAN_TYPE_ACTIVE 0
#define SCAN_TYPE_PASSIVE 1
struct at76_req_scan {
u8 bssid[ETH_ALEN];
u8 essid[32];
u8 scan_type;
u8 channel;
__le16 probe_delay;
__le16 min_channel_time;
__le16 max_channel_time;
u8 essid_size;
u8 international_scan;
} __attribute__((packed));
struct at76_req_ibss {
u8 bssid[ETH_ALEN];
u8 essid[32];
u8 bss_type;
u8 channel;
u8 essid_size;
u8 reserved[3];
} __attribute__((packed));
struct at76_req_join {
u8 bssid[ETH_ALEN];
u8 essid[32];
u8 bss_type;
u8 channel;
__le16 timeout;
u8 essid_size;
u8 reserved;
} __attribute__((packed));
struct set_mib_buffer {
u8 type;
u8 size;
u8 index;
u8 reserved;
union {
u8 byte;
__le16 word;
u8 addr[ETH_ALEN];
} data;
} __attribute__((packed));
struct mib_local {
u16 reserved0;
u8 beacon_enable;
u8 txautorate_fallback;
u8 reserved1;
u8 ssid_size;
u8 promiscuous_mode;
u16 reserved2;
u8 preamble_type;
u16 reserved3;
} __attribute__((packed));
struct mib_mac_addr {
u8 mac_addr[ETH_ALEN];
u8 res[2]; /* ??? */
u8 group_addr[4][ETH_ALEN];
u8 group_addr_status[4];
} __attribute__((packed));
struct mib_mac {
__le32 max_tx_msdu_lifetime;
__le32 max_rx_lifetime;
__le16 frag_threshold;
__le16 rts_threshold;
__le16 cwmin;
__le16 cwmax;
u8 short_retry_time;
u8 long_retry_time;
u8 scan_type; /* active or passive */
u8 scan_channel;
__le16 probe_delay; /* delay before ProbeReq in active scan, RO */
__le16 min_channel_time;
__le16 max_channel_time;
__le16 listen_interval;
u8 desired_ssid[32];
u8 desired_bssid[ETH_ALEN];
u8 desired_bsstype; /* ad-hoc or infrastructure */
u8 reserved2;
} __attribute__((packed));
struct mib_mac_mgmt {
__le16 beacon_period;
__le16 CFP_max_duration;
__le16 medium_occupancy_limit;
__le16 station_id; /* assoc id */
__le16 ATIM_window;
u8 CFP_mode;
u8 privacy_option_implemented;
u8 DTIM_period;
u8 CFP_period;
u8 current_bssid[ETH_ALEN];
u8 current_essid[32];
u8 current_bss_type;
u8 power_mgmt_mode;
/* rfmd and 505 */
u8 ibss_change;
u8 res;
u8 multi_domain_capability_implemented;
u8 multi_domain_capability_enabled;
u8 country_string[3];
u8 reserved[3];
} __attribute__((packed));
struct mib_mac_wep {
u8 privacy_invoked; /* 0 disable encr., 1 enable encr */
u8 wep_default_key_id;
u8 wep_key_mapping_len;
u8 exclude_unencrypted;
__le32 wep_icv_error_count;
__le32 wep_excluded_count;
u8 wep_default_keyvalue[WEP_KEYS][WEP_LARGE_KEY_LEN];
u8 encryption_level; /* 1 for 40bit, 2 for 104bit encryption */
} __attribute__((packed));
struct mib_phy {
__le32 ed_threshold;
__le16 slot_time;
__le16 sifs_time;
__le16 preamble_length;
__le16 plcp_header_length;
__le16 mpdu_max_length;
__le16 cca_mode_supported;
u8 operation_rate_set[4];
u8 channel_id;
u8 current_cca_mode;
u8 phy_type;
u8 current_reg_domain;
} __attribute__((packed));
struct mib_fw_version {
u8 major;
u8 minor;
u8 patch;
u8 build;
} __attribute__((packed));
struct mib_mdomain {
u8 tx_powerlevel[14];
u8 channel_list[14]; /* 0 for invalid channels */
} __attribute__((packed));
struct at76_fw_header {
__le32 crc; /* CRC32 of the whole image */
__le32 board_type; /* firmware compatibility code */
u8 build; /* firmware build number */
u8 patch; /* firmware patch level */
u8 minor; /* firmware minor version */
u8 major; /* firmware major version */
__le32 str_offset; /* offset of the copyright string */
__le32 int_fw_offset; /* internal firmware image offset */
__le32 int_fw_len; /* internal firmware image length */
__le32 ext_fw_offset; /* external firmware image offset */
__le32 ext_fw_len; /* external firmware image length */
} __attribute__((packed));
/* a description of a regulatory domain and the allowed channels */
struct reg_domain {
u16 code;
char const *name;
u32 channel_map; /* if bit N is set, channel (N+1) is allowed */
};
/* Data for one loaded firmware file */
struct fwentry {
const char *const fwname;
const struct firmware *fw;
int extfw_size;
int intfw_size;
/* pointer to loaded firmware, no need to free */
u8 *extfw; /* external firmware, extfw_size bytes long */
u8 *intfw; /* internal firmware, intfw_size bytes long */
enum board_type board_type; /* board type */
struct mib_fw_version fw_version;
int loaded; /* Loaded and parsed successfully */
};
struct at76_priv {
struct usb_device *udev; /* USB device pointer */
struct sk_buff *rx_skb; /* skbuff for receiving data */
struct sk_buff *tx_skb; /* skbuff for transmitting data */
void *bulk_out_buffer; /* buffer for sending data */
struct urb *tx_urb; /* URB for sending data */
struct urb *rx_urb; /* URB for receiving data */
unsigned int tx_pipe; /* bulk out pipe */
unsigned int rx_pipe; /* bulk in pipe */
struct mutex mtx; /* locks this structure */
/* work queues */
struct work_struct work_set_promisc;
struct work_struct work_submit_rx;
struct delayed_work dwork_hw_scan;
struct tasklet_struct rx_tasklet;
/* the WEP stuff */
int wep_enabled; /* 1 if WEP is enabled */
int wep_key_id; /* key id to be used */
u8 wep_keys[WEP_KEYS][WEP_LARGE_KEY_LEN]; /* WEP keys */
u8 wep_keys_len[WEP_KEYS]; /* length of WEP keys */
int channel;
int iw_mode;
u8 bssid[ETH_ALEN];
u8 essid[IW_ESSID_MAX_SIZE];
int essid_size;
int radio_on;
int promisc;
int preamble_type; /* 0 - long, 1 - short, 2 - auto */
int auth_mode; /* authentication type: 0 open, 1 shared key */
int txrate; /* 0,1,2,3 = 1,2,5.5,11 Mbps, 4 is auto */
int frag_threshold; /* threshold for fragmentation of tx packets */
int rts_threshold; /* threshold for RTS mechanism */
int short_retry_limit;
int scan_min_time; /* scan min channel time */
int scan_max_time; /* scan max channel time */
int scan_mode; /* SCAN_TYPE_ACTIVE, SCAN_TYPE_PASSIVE */
int scan_need_any; /* if set, need to scan for any ESSID */
u16 assoc_id; /* current association ID, if associated */
u8 pm_mode; /* power management mode */
u32 pm_period; /* power management period in microseconds */
struct reg_domain const *domain; /* reg domain description */
/* These fields contain HW config provided by the device (not all of
* these fields are used by all board types) */
u8 mac_addr[ETH_ALEN];
u8 regulatory_domain;
struct at76_card_config card_config;
enum board_type board_type;
struct mib_fw_version fw_version;
unsigned int device_unplugged:1;
unsigned int netdev_registered:1;
struct set_mib_buffer mib_buf; /* global buffer for set_mib calls */
int beacon_period; /* period of mgmt beacons, Kus */
struct ieee80211_hw *hw;
int mac80211_registered;
};
#define AT76_SUPPORTED_FILTERS FIF_PROMISC_IN_BSS
#define SCAN_POLL_INTERVAL (HZ / 4)
#define CMD_COMPLETION_TIMEOUT (5 * HZ)
#define DEF_RTS_THRESHOLD 1536
#define DEF_FRAG_THRESHOLD 1536
#define DEF_SHORT_RETRY_LIMIT 8
#define DEF_CHANNEL 10
#define DEF_SCAN_MIN_TIME 10
#define DEF_SCAN_MAX_TIME 120
/* the max padding size for tx in bytes (see calc_padding) */
#define MAX_PADDING_SIZE 53
#endif /* _AT76_USB_H */

View file

@ -350,6 +350,7 @@ static int ath5k_beacon_setup(struct ath5k_softc *sc,
static void ath5k_beacon_send(struct ath5k_softc *sc);
static void ath5k_beacon_config(struct ath5k_softc *sc);
static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
static void ath5k_tasklet_beacon(unsigned long data);
static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
{
@ -789,6 +790,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc);
tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc);
tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc);
tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc);
setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc);
ret = ath5k_eeprom_read_mac(ah, mac);
@ -1218,6 +1220,10 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
pktlen = skb->len;
if (info->control.hw_key) {
keyidx = info->control.hw_key->hw_key_idx;
pktlen += info->control.hw_key->icv_len;
}
if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
flags |= AR5K_TXDESC_RTSENA;
cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
@ -1230,11 +1236,6 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw,
sc->vif, pktlen, info));
}
if (info->control.hw_key) {
keyidx = info->control.hw_key->hw_key_idx;
pktlen += info->control.hw_key->icv_len;
}
ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
(sc->power_level * 2),
@ -1700,6 +1701,34 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
}
}
static void ath5k_tasklet_beacon(unsigned long data)
{
struct ath5k_softc *sc = (struct ath5k_softc *) data;
/*
* Software beacon alert--time to send a beacon.
*
* In IBSS mode we use this interrupt just to
* keep track of the next TBTT (target beacon
* transmission time) in order to detect wether
* automatic TSF updates happened.
*/
if (sc->opmode == NL80211_IFTYPE_ADHOC) {
/* XXX: only if VEOL suppported */
u64 tsf = ath5k_hw_get_tsf64(sc->ah);
sc->nexttbtt += sc->bintval;
ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
"SWBA nexttbtt: %x hw_tu: %x "
"TSF: %llx\n",
sc->nexttbtt,
TSF_TO_TU(tsf),
(unsigned long long) tsf);
} else {
spin_lock(&sc->block);
ath5k_beacon_send(sc);
spin_unlock(&sc->block);
}
}
static void
ath5k_tasklet_rx(unsigned long data)
@ -2040,9 +2069,8 @@ err_unmap:
* frame contents are done as needed and the slot time is
* also adjusted based on current state.
*
* this is usually called from interrupt context (ath5k_intr())
* but also from ath5k_beacon_config() in IBSS mode which in turn
* can be called from a tasklet and user context
* This is called from software irq context (beacontq or restq
* tasklets) or user context from ath5k_beacon_config.
*/
static void
ath5k_beacon_send(struct ath5k_softc *sc)
@ -2216,6 +2244,7 @@ static void
ath5k_beacon_config(struct ath5k_softc *sc)
{
struct ath5k_hw *ah = sc->ah;
unsigned long flags;
ath5k_hw_set_imr(ah, 0);
sc->bmisscount = 0;
@ -2237,9 +2266,9 @@ ath5k_beacon_config(struct ath5k_softc *sc)
if (sc->opmode == NL80211_IFTYPE_ADHOC) {
if (ath5k_hw_hasveol(ah)) {
spin_lock(&sc->block);
spin_lock_irqsave(&sc->block, flags);
ath5k_beacon_send(sc);
spin_unlock(&sc->block);
spin_unlock_irqrestore(&sc->block, flags);
}
} else
ath5k_beacon_update_timers(sc, -1);
@ -2391,6 +2420,7 @@ ath5k_stop_hw(struct ath5k_softc *sc)
tasklet_kill(&sc->rxtq);
tasklet_kill(&sc->txtq);
tasklet_kill(&sc->restq);
tasklet_kill(&sc->beacontq);
return ret;
}
@ -2408,16 +2438,9 @@ ath5k_intr(int irq, void *dev_id)
return IRQ_NONE;
do {
/*
* Figure out the reason(s) for the interrupt. Note
* that get_isr returns a pseudo-ISR that may include
* bits we haven't explicitly enabled so we mask the
* value to insure we only process bits we requested.
*/
ath5k_hw_get_isr(ah, &status); /* NB: clears IRQ too */
ATH5K_DBG(sc, ATH5K_DEBUG_INTR, "status 0x%x/0x%x\n",
status, sc->imask);
status &= sc->imask; /* discard unasked for bits */
if (unlikely(status & AR5K_INT_FATAL)) {
/*
* Fatal errors are unrecoverable.
@ -2428,32 +2451,7 @@ ath5k_intr(int irq, void *dev_id)
tasklet_schedule(&sc->restq);
} else {
if (status & AR5K_INT_SWBA) {
/*
* Software beacon alert--time to send a beacon.
* Handle beacon transmission directly; deferring
* this is too slow to meet timing constraints
* under load.
*
* In IBSS mode we use this interrupt just to
* keep track of the next TBTT (target beacon
* transmission time) in order to detect wether
* automatic TSF updates happened.
*/
if (sc->opmode == NL80211_IFTYPE_ADHOC) {
/* XXX: only if VEOL suppported */
u64 tsf = ath5k_hw_get_tsf64(ah);
sc->nexttbtt += sc->bintval;
ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
"SWBA nexttbtt: %x hw_tu: %x "
"TSF: %llx\n",
sc->nexttbtt,
TSF_TO_TU(tsf),
(unsigned long long) tsf);
} else {
spin_lock(&sc->block);
ath5k_beacon_send(sc);
spin_unlock(&sc->block);
}
tasklet_schedule(&sc->beacontq);
}
if (status & AR5K_INT_RXEOL) {
/*

View file

@ -169,6 +169,7 @@ struct ath5k_softc {
struct ath5k_led tx_led; /* tx led */
spinlock_t block; /* protects beacon */
struct tasklet_struct beacontq; /* beacon intr tasklet */
struct ath5k_buf *bbuf; /* beacon buffer */
unsigned int bhalq, /* SW q for outgoing beacons */
bmisscount, /* missed beacon transmits */

View file

@ -642,14 +642,13 @@ void ath9k_enable_mib_counters(struct ath_hw *ah)
REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
}
/* Freeze the MIB counters, get the stats and then clear them */
void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
{
DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disable MIB counters\n");
REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC | AR_MIBC_CMC);
REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC);
REG_WRITE(ah, AR_FILT_OFDM, 0);
REG_WRITE(ah, AR_FILT_CCK, 0);
}

View file

@ -464,13 +464,11 @@ void ath_beacon_sync(struct ath_softc *sc, int if_id);
/* ANI */
/*******/
/* ANI values for STA only.
FIXME: Add appropriate values for AP later */
#define ATH_ANI_POLLINTERVAL 100 /* 100 milliseconds between ANI poll */
#define ATH_SHORT_CALINTERVAL 1000 /* 1 second between calibrations */
#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds between calibrations */
#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes between calibrations */
#define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */
#define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */
#define ATH_ANI_POLLINTERVAL 100 /* 100 ms */
#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */
#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */
struct ath_ani {
bool caldone;

View file

@ -753,6 +753,9 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
if (bs.bs_sleepduration > bs.bs_dtimperiod)
bs.bs_sleepduration = bs.bs_dtimperiod;
/* TSF out of range threshold fixed at 1 second */
bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD;
DPRINTF(sc, ATH_DBG_BEACON,
"tsf %llu "
"tsf:tu %u "
@ -787,8 +790,6 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
u64 tsf;
u32 tsftu;
ath9k_hw_set_interrupts(ah, 0);
if (nexttbtt == intval)
intval |= ATH9K_BEACON_RESET_TSF;
if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) {
/*
* Pull nexttbtt forward to reflect the current
@ -822,6 +823,9 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
sc->imask |= ATH9K_INT_SWBA;
ath_beaconq_config(sc);
} else if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
if (nexttbtt == intval)
intval |= ATH9K_BEACON_RESET_TSF;
/*
* In AP mode we enable the beacon timers and
* SWBA interrupts to prepare beacon frames.

View file

@ -718,6 +718,33 @@ s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
return nf;
}
static void ath9k_olc_temp_compensation(struct ath_hw *ah)
{
u32 rddata, i;
int delta, currPDADC, regval;
rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
delta = (currPDADC - ah->initPDADC + 4) / 8;
else
delta = (currPDADC - ah->initPDADC + 5) / 10;
if (delta != ah->PDADCdelta) {
ah->PDADCdelta = delta;
for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
regval = ah->originalGain[i] - delta;
if (regval < 0)
regval = 0;
REG_RMW_FIELD(ah, AR_PHY_TX_GAIN_TBL1 + i * 4,
AR_PHY_TX_GAIN, regval);
}
}
}
bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
u8 rxchainmask, bool longcal,
bool *isCalDone)
@ -742,6 +769,8 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
}
if (longcal) {
if (OLC_FOR_AR9280_20_LATER)
ath9k_olc_temp_compensation(ah);
ath9k_hw_getnf(ah, chan);
ath9k_hw_loadnf(ah, ah->curchan);
ath9k_hw_start_nfcal(ah);
@ -851,20 +880,53 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah)
bool ath9k_hw_init_cal(struct ath_hw *ah,
struct ath9k_channel *chan)
{
if (AR_SREV_9280_10_OR_LATER(ah)) {
REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
/* Kick off the cal */
REG_WRITE(ah, AR_PHY_AGC_CONTROL,
REG_READ(ah, AR_PHY_AGC_CONTROL) |
AR_PHY_AGC_CONTROL_CAL);
if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
AR_PHY_AGC_CONTROL_CAL, 0,
AH_WAIT_TIMEOUT)) {
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
"offset calibration failed to complete in 1ms; "
"noisy environment?\n");
return false;
}
REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
}
/* Calibrate the AGC */
REG_WRITE(ah, AR_PHY_AGC_CONTROL,
REG_READ(ah, AR_PHY_AGC_CONTROL) |
AR_PHY_AGC_CONTROL_CAL);
if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
0, AH_WAIT_TIMEOUT)) {
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
"offset calibration failed to complete in 1ms; "
"noisy environment?\n");
return false;
}
if (AR_SREV_9280_10_OR_LATER(ah)) {
REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
}
/* Do PA Calibration */
if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah))
ath9k_hw_9285_pa_cal(ah);
/* Do NF Calibration */
REG_WRITE(ah, AR_PHY_AGC_CONTROL,
REG_READ(ah, AR_PHY_AGC_CONTROL) |
AR_PHY_AGC_CONTROL_NF);

View file

@ -27,7 +27,7 @@ extern const struct hal_percal_data adc_init_dc_cal;
#define AR_PHY_CCA_MAX_GOOD_VALUE -85
#define AR_PHY_CCA_MAX_HIGH_VALUE -62
#define AR_PHY_CCA_MIN_BAD_VALUE -121
#define AR_PHY_CCA_MIN_BAD_VALUE -140
#define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3
#define AR_PHY_CCA_FILTERWINDOW_LENGTH 5

View file

@ -258,13 +258,14 @@ void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb)
/* FIXME: legacy rates, later on .. */
void ath_debug_stat_retries(struct ath_softc *sc, int rix,
int xretries, int retries)
int xretries, int retries, u8 per)
{
if (conf_is_ht(&sc->hw->conf)) {
int idx = sc->cur_rate_table->info[rix].dot11rate;
sc->debug.stats.n_rcstats[idx].xretries += xretries;
sc->debug.stats.n_rcstats[idx].retries += retries;
sc->debug.stats.n_rcstats[idx].per = per;
}
}
@ -277,15 +278,16 @@ static ssize_t ath_read_file_stat_11n_rc(struct file *file,
unsigned int len = 0;
int i = 0;
len += sprintf(buf, "%7s %13s %8s %8s\n\n", "Rate", "Success",
"Retries", "XRetries");
len += sprintf(buf, "%7s %13s %8s %8s %6s\n\n", "Rate", "Success",
"Retries", "XRetries", "PER");
for (i = 0; i <= 15; i++) {
len += snprintf(buf + len, sizeof(buf) - len,
"%5s%3d: %8u %8u %8u\n", "MCS", i,
"%5s%3d: %8u %8u %8u %8u\n", "MCS", i,
sc->debug.stats.n_rcstats[i].success,
sc->debug.stats.n_rcstats[i].retries,
sc->debug.stats.n_rcstats[i].xretries);
sc->debug.stats.n_rcstats[i].xretries,
sc->debug.stats.n_rcstats[i].per);
}
return simple_read_from_buffer(user_buf, count, ppos, buf, len);

View file

@ -91,12 +91,13 @@ struct ath_11n_rc_stats {
u32 success;
u32 retries;
u32 xretries;
u8 per;
};
struct ath_stats {
struct ath_interrupt_stats istats;
struct ath_legacy_rc_stats legacy_rcstats[12]; /* max(11a,11b,11g) */
struct ath_11n_rc_stats n_rcstats[16]; /* 0..15 MCS rates */
struct ath_legacy_rc_stats legacy_rcstats[12]; /* max(11a,11b,11g) */
struct ath_11n_rc_stats n_rcstats[16]; /* 0..15 MCS rates */
};
struct ath9k_debug {
@ -115,7 +116,7 @@ void ath9k_exit_debug(struct ath_softc *sc);
void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb);
void ath_debug_stat_retries(struct ath_softc *sc, int rix,
int xretries, int retries);
int xretries, int retries, u8 per);
#else
@ -144,7 +145,7 @@ static inline void ath_debug_stat_rc(struct ath_softc *sc,
}
static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix,
int xretries, int retries)
int xretries, int retries, u8 per)
{
}

View file

@ -179,6 +179,69 @@ static void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
}
}
static void ath9k_get_txgain_index(struct ath_hw *ah,
struct ath9k_channel *chan,
struct calDataPerFreqOpLoop *rawDatasetOpLoop,
u8 *calChans, u16 availPiers, u8 *pwr, u8 *pcdacIdx)
{
u8 pcdac, i = 0;
u16 idxL = 0, idxR = 0, numPiers;
bool match;
struct chan_centers centers;
ath9k_hw_get_channel_centers(ah, chan, &centers);
for (numPiers = 0; numPiers < availPiers; numPiers++)
if (calChans[numPiers] == AR5416_BCHAN_UNUSED)
break;
match = ath9k_hw_get_lower_upper_index(
(u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
calChans, numPiers, &idxL, &idxR);
if (match) {
pcdac = rawDatasetOpLoop[idxL].pcdac[0][0];
*pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0];
} else {
pcdac = rawDatasetOpLoop[idxR].pcdac[0][0];
*pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] +
rawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
}
while (pcdac > ah->originalGain[i] &&
i < (AR9280_TX_GAIN_TABLE_SIZE - 1))
i++;
*pcdacIdx = i;
return;
}
static void ath9k_olc_get_pdadcs(struct ath_hw *ah,
u32 initTxGain,
int txPower,
u8 *pPDADCValues)
{
u32 i;
u32 offset;
REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0,
AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1,
AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7,
AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain);
offset = txPower;
for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++)
if (i < offset)
pPDADCValues[i] = 0x0;
else
pPDADCValues[i] = 0xFF;
}
static void ath9k_hw_get_target_powers(struct ath_hw *ah,
struct ath9k_channel *chan,
struct cal_target_power_ht *powInfo,
@ -439,7 +502,7 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
switch (param) {
case EEP_NFTHRESH_2:
return pModal[1].noiseFloorThreshCh[0];
return pModal->noiseFloorThreshCh[0];
case AR_EEPROM_MAC(0):
return pBase->macAddr[0] << 8 | pBase->macAddr[1];
case AR_EEPROM_MAC(1):
@ -466,6 +529,8 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
return pBase->txMask;
case EEP_RX_MASK:
return pBase->rxMask;
case EEP_FRAC_N_5G:
return 0;
default:
return 0;
}
@ -1594,11 +1659,26 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
return pBase->rxGainType;
case EEP_TXGAIN_TYPE:
return pBase->txGainType;
case EEP_OL_PWRCTRL:
if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
return pBase->openLoopPwrCntl ? true : false;
else
return false;
case EEP_RC_CHAIN_MASK:
if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
return pBase->rcChainMask;
else
return 0;
case EEP_DAC_HPWR_5G:
if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20)
return pBase->dacHiPwrMode_5G;
else
return 0;
case EEP_FRAC_N_5G:
if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_22)
return pBase->frac_n_5g;
else
return 0;
default:
return 0;
}
@ -1832,8 +1912,15 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah,
pModal->swSettleHt40);
}
if (AR_SREV_9280_20_OR_LATER(ah) &&
AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL,
AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK,
pModal->miscBits);
if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) {
if (IS_CHAN_HT20(chan))
if (IS_CHAN_2GHZ(chan))
REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
eep->baseEepHeader.dacLpMode);
else if (eep->baseEepHeader.dacHiPwrMode_5G)
@ -1844,6 +1931,10 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah,
REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,
pModal->miscBits >> 2);
REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9,
AR_PHY_TX_DESIRED_SCALE_CCK,
eep->baseEepHeader.desiredScaleCCK);
}
return true;
@ -2073,6 +2164,10 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
struct ath9k_channel *chan,
int16_t *pTxPowerIndexOffset)
{
#define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x)
#define SM_PDGAIN_B(x, y) \
SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y)
struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
struct cal_data_per_freq *pRawDataset;
u8 *pCalBChans = NULL;
@ -2106,6 +2201,12 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
numPiers = AR5416_NUM_5G_CAL_PIERS;
}
if (OLC_FOR_AR9280_20_LATER && IS_CHAN_2GHZ(chan)) {
pRawDataset = pEepData->calPierData2G[0];
ah->initPDADC = ((struct calDataPerFreqOpLoop *)
pRawDataset)->vpdPdg[0][0];
}
numXpdGain = 0;
for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
@ -2141,25 +2242,45 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
else
pRawDataset = pEepData->calPierData5G[i];
ath9k_hw_get_def_gain_boundaries_pdadcs(ah, chan,
pRawDataset, pCalBChans,
numPiers, pdGainOverlap_t2,
&tMinCalPower, gainBoundaries,
pdadcValues, numXpdGain);
if (OLC_FOR_AR9280_20_LATER) {
u8 pcdacIdx;
u8 txPower;
ath9k_get_txgain_index(ah, chan,
(struct calDataPerFreqOpLoop *)pRawDataset,
pCalBChans, numPiers, &txPower, &pcdacIdx);
ath9k_olc_get_pdadcs(ah, pcdacIdx,
txPower/2, pdadcValues);
} else {
ath9k_hw_get_def_gain_boundaries_pdadcs(ah,
chan, pRawDataset,
pCalBChans, numPiers,
pdGainOverlap_t2,
&tMinCalPower,
gainBoundaries,
pdadcValues,
numXpdGain);
}
if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
REG_WRITE(ah,
AR_PHY_TPCRG5 + regChainOffset,
SM(pdGainOverlap_t2,
AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
| SM(gainBoundaries[0],
AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
| SM(gainBoundaries[1],
AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
| SM(gainBoundaries[2],
AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
| SM(gainBoundaries[3],
AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
if (OLC_FOR_AR9280_20_LATER) {
REG_WRITE(ah,
AR_PHY_TPCRG5 + regChainOffset,
SM(0x6,
AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
SM_PD_GAIN(1) | SM_PD_GAIN(2) |
SM_PD_GAIN(3) | SM_PD_GAIN(4));
} else {
REG_WRITE(ah,
AR_PHY_TPCRG5 + regChainOffset,
SM(pdGainOverlap_t2,
AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
SM_PDGAIN_B(0, 1) |
SM_PDGAIN_B(1, 2) |
SM_PDGAIN_B(2, 3) |
SM_PDGAIN_B(3, 4));
}
}
regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
@ -2193,6 +2314,8 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
*pTxPowerIndexOffset = 0;
return true;
#undef SM_PD_GAIN
#undef SM_PDGAIN_B
}
static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
@ -2493,13 +2616,14 @@ static int ath9k_hw_def_set_txpower(struct ath_hw *ah,
u8 twiceMaxRegulatoryPower,
u8 powerLimit)
{
#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
struct modal_eep_header *pModal =
&(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
int16_t ratesArray[Ar5416RateSize];
int16_t txPowerIndexOffset = 0;
u8 ht40PowerIncForPdadc = 2;
int i;
int i, cck_ofdm_delta = 0;
memset(ratesArray, 0, sizeof(ratesArray));
@ -2548,16 +2672,30 @@ static int ath9k_hw_def_set_txpower(struct ath_hw *ah,
| ATH9K_POW_SM(ratesArray[rate24mb], 0));
if (IS_CHAN_2GHZ(chan)) {
REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
ATH9K_POW_SM(ratesArray[rate2s], 24)
| ATH9K_POW_SM(ratesArray[rate2l], 16)
| ATH9K_POW_SM(ratesArray[rateXr], 8)
| ATH9K_POW_SM(ratesArray[rate1l], 0));
REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
ATH9K_POW_SM(ratesArray[rate11s], 24)
| ATH9K_POW_SM(ratesArray[rate11l], 16)
| ATH9K_POW_SM(ratesArray[rate5_5s], 8)
| ATH9K_POW_SM(ratesArray[rate5_5l], 0));
if (OLC_FOR_AR9280_20_LATER) {
cck_ofdm_delta = 2;
REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
ATH9K_POW_SM(RT_AR_DELTA(rate2s), 24)
| ATH9K_POW_SM(RT_AR_DELTA(rate2l), 16)
| ATH9K_POW_SM(ratesArray[rateXr], 8)
| ATH9K_POW_SM(RT_AR_DELTA(rate1l), 0));
REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
ATH9K_POW_SM(RT_AR_DELTA(rate11s), 24)
| ATH9K_POW_SM(RT_AR_DELTA(rate11l), 16)
| ATH9K_POW_SM(RT_AR_DELTA(rate5_5s), 8)
| ATH9K_POW_SM(RT_AR_DELTA(rate5_5l), 0));
} else {
REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
ATH9K_POW_SM(ratesArray[rate2s], 24)
| ATH9K_POW_SM(ratesArray[rate2l], 16)
| ATH9K_POW_SM(ratesArray[rateXr], 8)
| ATH9K_POW_SM(ratesArray[rate1l], 0));
REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
ATH9K_POW_SM(ratesArray[rate11s], 24)
| ATH9K_POW_SM(ratesArray[rate11l], 16)
| ATH9K_POW_SM(ratesArray[rate5_5s], 8)
| ATH9K_POW_SM(ratesArray[rate5_5l], 0));
}
}
REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
@ -2590,12 +2728,19 @@ static int ath9k_hw_def_set_txpower(struct ath_hw *ah,
ht40PowerIncForPdadc, 8)
| ATH9K_POW_SM(ratesArray[rateHt40_4] +
ht40PowerIncForPdadc, 0));
REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
| ATH9K_POW_SM(ratesArray[rateExtCck], 16)
| ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
| ATH9K_POW_SM(ratesArray[rateDupCck], 0));
if (OLC_FOR_AR9280_20_LATER) {
REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
| ATH9K_POW_SM(RT_AR_DELTA(rateExtCck), 16)
| ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
| ATH9K_POW_SM(RT_AR_DELTA(rateDupCck), 0));
} else {
REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
| ATH9K_POW_SM(ratesArray[rateExtCck], 16)
| ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
| ATH9K_POW_SM(ratesArray[rateDupCck], 0));
}
}
REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
@ -2615,6 +2760,21 @@ static int ath9k_hw_def_set_txpower(struct ath_hw *ah,
else
ah->regulatory.max_power_level = ratesArray[i];
switch(ar5416_get_ntxchains(ah->txchainmask)) {
case 1:
break;
case 2:
ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
break;
case 3:
ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
break;
default:
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
"Invalid chainmask configuration\n");
break;
}
return 0;
}

View file

@ -75,11 +75,29 @@
#define SUB_NUM_CTL_MODES_AT_5G_40 2
#define SUB_NUM_CTL_MODES_AT_2G_40 3
#define INCREASE_MAXPOW_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
#define INCREASE_MAXPOW_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */
/*
* For AR9285 and later chipsets, the following bits are not being programmed
* in EEPROM and so need to be enabled always.
*
* Bit 0: en_fcc_mid
* Bit 1: en_jap_mid
* Bit 2: en_fcc_dfs_ht40
* Bit 3: en_jap_ht40
* Bit 4: en_jap_dfs_ht40
*/
#define AR9285_RDEXT_DEFAULT 0x1F
#define AR_EEPROM_MAC(i) (0x1d+(i))
#define ATH9K_POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
#define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5))
#define ath9k_hw_use_flash(_ah) (!(_ah->ah_flags & AH_USE_EEPROM))
#define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \
ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
#define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c
#define AR_EEPROM_RFSILENT_GPIO_SEL_S 2
#define AR_EEPROM_RFSILENT_POLARITY 0x0002
@ -110,6 +128,7 @@
#define AR5416_EEP_MINOR_VER_17 0x11
#define AR5416_EEP_MINOR_VER_19 0x13
#define AR5416_EEP_MINOR_VER_20 0x14
#define AR5416_EEP_MINOR_VER_22 0x16
#define AR5416_NUM_5G_CAL_PIERS 8
#define AR5416_NUM_2G_CAL_PIERS 4
@ -152,6 +171,8 @@
#define AR5416_EEP4K_PD_GAIN_ICEPTS 5
#define AR5416_EEP4K_MAX_CHAINS 1
#define AR9280_TX_GAIN_TABLE_SIZE 22
enum eeprom_param {
EEP_NFTHRESH_5,
EEP_NFTHRESH_2,
@ -172,7 +193,10 @@ enum eeprom_param {
EEP_RX_MASK,
EEP_RXGAIN_TYPE,
EEP_TXGAIN_TYPE,
EEP_OL_PWRCTRL,
EEP_RC_CHAIN_MASK,
EEP_DAC_HPWR_5G,
EEP_FRAC_N_5G
};
enum ar5416_rates {
@ -212,12 +236,14 @@ struct base_eep_header {
u8 futureBase_1[2];
u8 rxGainType;
u8 dacHiPwrMode_5G;
u8 futureBase_2;
u8 openLoopPwrCntl;
u8 dacLpMode;
u8 txGainType;
u8 rcChainMask;
u8 desiredScaleCCK;
u8 futureBase_3[23];
u8 power_table_offset;
u8 frac_n_5g;
u8 futureBase_3[21];
} __packed;
struct base_eep_header_4k {
@ -291,6 +317,13 @@ struct modal_eep_header {
struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS];
} __packed;
struct calDataPerFreqOpLoop {
u8 pwrPdg[2][5];
u8 vpdPdg[2][5];
u8 pcdac[2][5];
u8 empty[2][5];
} __packed;
struct modal_eep_4k_header {
u32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS];
u32 antCtrlCommon;

View file

@ -84,11 +84,13 @@ static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs)
return ath9k_hw_mac_clks(ah, usecs);
}
bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val)
bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout)
{
int i;
for (i = 0; i < (AH_TIMEOUT / AH_TIME_QUANTUM); i++) {
BUG_ON(timeout < AH_TIME_QUANTUM);
for (i = 0; i < (timeout / AH_TIME_QUANTUM); i++) {
if ((REG_READ(ah, reg) & mask) == val)
return true;
@ -96,8 +98,8 @@ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val)
}
DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
"timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
reg, REG_READ(ah, reg), mask, val);
"timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
timeout, reg, REG_READ(ah, reg), mask, val);
return false;
}
@ -823,7 +825,16 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
if (AR_SREV_9280_20(ah))
ath9k_hw_init_txgain_ini(ah);
if (ah->hw_version.devid == AR9280_DEVID_PCI) {
if (!ath9k_hw_fill_cap_info(ah)) {
DPRINTF(sc, ATH_DBG_RESET, "failed ath9k_hw_fill_cap_info\n");
ecode = -EINVAL;
goto bad;
}
if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) {
/* EEPROM Fixup */
for (i = 0; i < ah->iniModes.ia_rows; i++) {
u32 reg = INI_RA(&ah->iniModes, i, 0);
@ -838,13 +849,6 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
}
}
if (!ath9k_hw_fill_cap_info(ah)) {
DPRINTF(sc, ATH_DBG_RESET,
"failed ath9k_hw_fill_cap_info\n");
ecode = -EINVAL;
goto bad;
}
ecode = ath9k_hw_init_macaddr(ah);
if (ecode != 0) {
DPRINTF(sc, ATH_DBG_RESET,
@ -1200,6 +1204,17 @@ static u32 ath9k_hw_ini_fixup(struct ath_hw *ah,
return ath9k_hw_def_ini_fixup(ah, pEepData, reg, value);
}
static void ath9k_olc_init(struct ath_hw *ah)
{
u32 i;
for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++)
ah->originalGain[i] =
MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4),
AR_PHY_TX_GAIN);
ah->PDADCdelta = 0;
}
static int ath9k_hw_process_ini(struct ath_hw *ah,
struct ath9k_channel *chan,
enum ath9k_ht_macmode macmode)
@ -1306,6 +1321,9 @@ static int ath9k_hw_process_ini(struct ath_hw *ah,
ath9k_hw_set_regs(ah, chan, macmode);
ath9k_hw_init_chain_masks(ah);
if (OLC_FOR_AR9280_20_LATER)
ath9k_olc_init(ah);
status = ah->eep_ops->set_txpower(ah, chan,
ath9k_regd_get_ctl(ah, chan),
channel->max_antenna_gain * 2,
@ -1464,6 +1482,14 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
u32 rst_flags;
u32 tmpReg;
if (AR_SREV_9100(ah)) {
u32 val = REG_READ(ah, AR_RTC_DERIVED_CLK);
val &= ~AR_RTC_DERIVED_CLK_PERIOD;
val |= SM(1, AR_RTC_DERIVED_CLK_PERIOD);
REG_WRITE(ah, AR_RTC_DERIVED_CLK, val);
(void)REG_READ(ah, AR_RTC_DERIVED_CLK);
}
REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
AR_RTC_FORCE_WAKE_ON_INT);
@ -1490,7 +1516,7 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
udelay(50);
REG_WRITE(ah, AR_RTC_RC, 0);
if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0)) {
if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) {
DPRINTF(ah->ah_sc, ATH_DBG_RESET,
"RTC stuck in MAC reset\n");
return false;
@ -1513,12 +1539,14 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
AR_RTC_FORCE_WAKE_ON_INT);
REG_WRITE(ah, AR_RTC_RESET, 0);
udelay(2);
REG_WRITE(ah, AR_RTC_RESET, 1);
if (!ath9k_hw_wait(ah,
AR_RTC_STATUS,
AR_RTC_STATUS_M,
AR_RTC_STATUS_ON)) {
AR_RTC_STATUS_ON,
AH_WAIT_TIMEOUT)) {
DPRINTF(ah->ah_sc, ATH_DBG_RESET, "RTC not waking up\n");
return false;
}
@ -1580,7 +1608,10 @@ static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan,
static bool ath9k_hw_chip_reset(struct ath_hw *ah,
struct ath9k_channel *chan)
{
if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
if (OLC_FOR_AR9280_20_LATER) {
if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON))
return false;
} else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
return false;
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
@ -1610,7 +1641,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN);
if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN,
AR_PHY_RFBUS_GRANT_EN)) {
AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT)) {
DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
"Could not kill baseband RX\n");
return false;
@ -2801,6 +2832,8 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
mask2 |= ATH9K_INT_GTT;
if (isr2 & AR_ISR_S2_CST)
mask2 |= ATH9K_INT_CST;
if (isr2 & AR_ISR_S2_TSFOOR)
mask2 |= ATH9K_INT_TSFOOR;
}
isr = REG_READ(ah, AR_ISR_RAC);
@ -2946,7 +2979,9 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
if (ints & ATH9K_INT_DTIMSYNC)
mask2 |= AR_IMR_S2_DTIMSYNC;
if (ints & ATH9K_INT_CABEND)
mask2 |= (AR_IMR_S2_CABEND);
mask2 |= AR_IMR_S2_CABEND;
if (ints & ATH9K_INT_TSFOOR)
mask2 |= AR_IMR_S2_TSFOOR;
}
if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) {
@ -3116,6 +3151,8 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN |
AR_DTIM_TIMER_EN);
/* TSF Out of Range Threshold */
REG_WRITE(ah, AR_TSFOOR_THRESHOLD, bs->bs_tsfoor_threshold);
}
/*******************/
@ -3128,10 +3165,11 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah)
u16 capField = 0, eeval;
eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0);
ah->regulatory.current_rd = eeval;
eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1);
if (AR_SREV_9285_10_OR_LATER(ah))
eeval |= AR9285_RDEXT_DEFAULT;
ah->regulatory.current_rd_ext = eeval;
capField = ah->eep_ops->get_eeprom(ah, EEP_OP_CAP);
@ -3182,14 +3220,11 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah)
}
pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK);
if ((ah->is_pciexpress)
|| (eeval & AR5416_OPFLAGS_11A)) {
pCap->rx_chainmask =
ah->eep_ops->get_eeprom(ah, EEP_RX_MASK);
} else {
pCap->rx_chainmask =
(ath9k_hw_gpio_get(ah, 0)) ? 0x5 : 0x7;
}
if ((ah->hw_version.devid == AR5416_DEVID_PCI) &&
!(eeval & AR5416_OPFLAGS_11A))
pCap->rx_chainmask = ath9k_hw_gpio_get(ah, 0) ? 0x5 : 0x7;
else
pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK);
if (!(AR_SREV_9280(ah) && (ah->hw_version.macRev == 0)))
ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
@ -3317,8 +3352,6 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah)
bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
u32 capability, u32 *result)
{
const struct ath9k_hw_capabilities *pCap = &ah->caps;
switch (type) {
case ATH9K_CAP_CIPHER:
switch (capability) {
@ -3344,16 +3377,10 @@ bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
case ATH9K_CAP_TKIP_SPLIT:
return (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) ?
false : true;
case ATH9K_CAP_WME_TKIPMIC:
return 0;
case ATH9K_CAP_PHYCOUNTERS:
return ah->has_hw_phycounters ? 0 : -ENXIO;
case ATH9K_CAP_DIVERSITY:
return (REG_READ(ah, AR_PHY_CCK_DETECT) &
AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV) ?
true : false;
case ATH9K_CAP_PHYDIAG:
return true;
case ATH9K_CAP_MCAST_KEYSRCH:
switch (capability) {
case 0:
@ -3368,18 +3395,6 @@ bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
}
}
return false;
case ATH9K_CAP_TSF_ADJUST:
return (ah->misc_mode & AR_PCU_TX_ADD_TSF) ?
true : false;
case ATH9K_CAP_RFSILENT:
if (capability == 3)
return false;
case ATH9K_CAP_ANT_CFG_2GHZ:
*result = pCap->num_antcfg_2ghz;
return true;
case ATH9K_CAP_ANT_CFG_5GHZ:
*result = pCap->num_antcfg_5ghz;
return true;
case ATH9K_CAP_TXPOW:
switch (capability) {
case 0:
@ -3395,6 +3410,10 @@ bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
return 0;
}
return false;
case ATH9K_CAP_DS:
return (AR_SREV_9280_20_OR_LATER(ah) &&
(ah->eep_ops->get_eeprom(ah, EEP_RC_CHAIN_MASK) == 1))
? false : true;
default:
return false;
}
@ -3428,12 +3447,6 @@ bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type,
else
ah->sta_id1_defaults &= ~AR_STA_ID1_MCAST_KSRCH;
return true;
case ATH9K_CAP_TSF_ADJUST:
if (setting)
ah->misc_mode |= AR_PCU_TX_ADD_TSF;
else
ah->misc_mode &= ~AR_PCU_TX_ADD_TSF;
return true;
default:
return false;
}

View file

@ -93,7 +93,7 @@
#define ATH9K_NUM_QUEUES 10
#define MAX_RATE_POWER 63
#define AH_TIMEOUT 100000
#define AH_WAIT_TIMEOUT 100000 /* (us) */
#define AH_TIME_QUANTUM 10
#define AR_KEYTABLE_SIZE 128
#define POWER_UP_TIME 200000
@ -153,16 +153,10 @@ enum ath9k_capability_type {
ATH9K_CAP_CIPHER = 0,
ATH9K_CAP_TKIP_MIC,
ATH9K_CAP_TKIP_SPLIT,
ATH9K_CAP_PHYCOUNTERS,
ATH9K_CAP_DIVERSITY,
ATH9K_CAP_TXPOW,
ATH9K_CAP_PHYDIAG,
ATH9K_CAP_MCAST_KEYSRCH,
ATH9K_CAP_TSF_ADJUST,
ATH9K_CAP_WME_TKIPMIC,
ATH9K_CAP_RFSILENT,
ATH9K_CAP_ANT_CFG_2GHZ,
ATH9K_CAP_ANT_CFG_5GHZ
ATH9K_CAP_DS
};
struct ath9k_hw_capabilities {
@ -249,6 +243,7 @@ enum ath9k_int {
ATH9K_INT_DTIMSYNC = 0x00800000,
ATH9K_INT_GPIO = 0x01000000,
ATH9K_INT_CABEND = 0x02000000,
ATH9K_INT_TSFOOR = 0x04000000,
ATH9K_INT_CST = 0x10000000,
ATH9K_INT_GTT = 0x20000000,
ATH9K_INT_FATAL = 0x40000000,
@ -256,6 +251,7 @@ enum ath9k_int {
ATH9K_INT_BMISC = ATH9K_INT_TIM |
ATH9K_INT_DTIM |
ATH9K_INT_DTIMSYNC |
ATH9K_INT_TSFOOR |
ATH9K_INT_CABEND,
ATH9K_INT_COMMON = ATH9K_INT_RXNOFRM |
ATH9K_INT_RXDESC |
@ -385,6 +381,7 @@ struct ath9k_beacon_state {
#define ATH9K_BEACON_PERIOD 0x0000ffff
#define ATH9K_BEACON_ENA 0x00800000
#define ATH9K_BEACON_RESET_TSF 0x01000000
#define ATH9K_TSFOOR_THRESHOLD 0x00004240 /* 16k us */
u32 bs_dtimperiod;
u16 bs_cfpperiod;
u16 bs_cfpmaxduration;
@ -392,6 +389,7 @@ struct ath9k_beacon_state {
u16 bs_timoffset;
u16 bs_bmissthreshold;
u32 bs_sleepduration;
u32 bs_tsfoor_threshold;
};
struct chan_centers {
@ -547,6 +545,10 @@ struct ath_hw {
u8 txchainmask;
u8 rxchainmask;
u32 originalGain[22];
int initPDADC;
int PDADCdelta;
struct ar5416IniArray iniModes;
struct ar5416IniArray iniCommon;
struct ar5416IniArray iniBank0;
@ -603,7 +605,7 @@ bool ath9k_hw_setantennaswitch(struct ath_hw *ah,
u8 *antenna_cfgd);
/* General Operation */
bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val);
bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout);
u32 ath9k_hw_reverse_bits(u32 val, u32 n);
bool ath9k_get_channel_edges(struct ath_hw *ah, u16 flags, u16 *low, u16 *high);
u16 ath9k_hw_computetxtime(struct ath_hw *ah, struct ath_rate_table *rates,

View file

@ -285,7 +285,7 @@ int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds)
ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
ds->ds_txstat.ts_antenna = 1;
ds->ds_txstat.ts_antenna = 0;
return 0;
}
@ -886,7 +886,8 @@ bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set)
REG_SET_BIT(ah, AR_DIAG_SW,
(AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
if (!ath9k_hw_wait(ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE, 0)) {
if (!ath9k_hw_wait(ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE,
0, AH_WAIT_TIMEOUT)) {
REG_CLR_BIT(ah, AR_DIAG_SW,
(AR_DIAG_RX_DIS |
AR_DIAG_RX_ABORT));
@ -933,15 +934,32 @@ void ath9k_hw_stoppcurecv(struct ath_hw *ah)
bool ath9k_hw_stopdmarecv(struct ath_hw *ah)
{
#define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */
#define AH_RX_TIME_QUANTUM 100 /* usec */
int i;
REG_WRITE(ah, AR_CR, AR_CR_RXD);
if (!ath9k_hw_wait(ah, AR_CR, AR_CR_RXE, 0)) {
/* Wait for rx enable bit to go low */
for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) {
if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0)
break;
udelay(AH_TIME_QUANTUM);
}
if (i == 0) {
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
"dma failed to stop in 10ms\n"
"AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n",
REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW));
"dma failed to stop in %d ms "
"AR_CR=0x%08x AR_DIAG_SW=0x%08x\n",
AH_RX_STOP_DMA_TIMEOUT / 1000,
REG_READ(ah, AR_CR),
REG_READ(ah, AR_DIAG_SW));
return false;
} else {
return true;
}
#undef AH_RX_TIME_QUANTUM
#undef AH_RX_STOP_DMA_TIMEOUT
}

View file

@ -566,8 +566,9 @@ enum ath9k_rx_filter {
ATH9K_RX_FILTER_BEACON = 0x00000010,
ATH9K_RX_FILTER_PROM = 0x00000020,
ATH9K_RX_FILTER_PROBEREQ = 0x00000080,
ATH9K_RX_FILTER_PSPOLL = 0x00004000,
ATH9K_RX_FILTER_PHYERR = 0x00000100,
ATH9K_RX_FILTER_MYBEACON = 0x00000200,
ATH9K_RX_FILTER_PSPOLL = 0x00004000,
ATH9K_RX_FILTER_PHYRADAR = 0x00002000,
};

View file

@ -308,23 +308,23 @@ static int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan)
*/
static void ath_ani_calibrate(unsigned long data)
{
struct ath_softc *sc;
struct ath_hw *ah;
struct ath_softc *sc = (struct ath_softc *)data;
struct ath_hw *ah = sc->sc_ah;
bool longcal = false;
bool shortcal = false;
bool aniflag = false;
unsigned int timestamp = jiffies_to_msecs(jiffies);
u32 cal_interval;
u32 cal_interval, short_cal_interval;
sc = (struct ath_softc *)data;
ah = sc->sc_ah;
short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ?
ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL;
/*
* don't calibrate when we're scanning.
* we are most likely not on our home channel.
*/
if (sc->rx.rxfilter & FIF_BCN_PRBRESP_PROMISC)
return;
goto set_timer;
/* Long calibration runs independently of short calibration. */
if ((timestamp - sc->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) {
@ -335,8 +335,7 @@ static void ath_ani_calibrate(unsigned long data)
/* Short calibration applies only while caldone is false */
if (!sc->ani.caldone) {
if ((timestamp - sc->ani.shortcal_timer) >=
ATH_SHORT_CALINTERVAL) {
if ((timestamp - sc->ani.shortcal_timer) >= short_cal_interval) {
shortcal = true;
DPRINTF(sc, ATH_DBG_ANI, "shortcal @%lu\n", jiffies);
sc->ani.shortcal_timer = timestamp;
@ -352,8 +351,7 @@ static void ath_ani_calibrate(unsigned long data)
}
/* Verify whether we must check ANI */
if ((timestamp - sc->ani.checkani_timer) >=
ATH_ANI_POLLINTERVAL) {
if ((timestamp - sc->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) {
aniflag = true;
sc->ani.checkani_timer = timestamp;
}
@ -362,8 +360,7 @@ static void ath_ani_calibrate(unsigned long data)
if (longcal || shortcal || aniflag) {
/* Call ANI routine if necessary */
if (aniflag)
ath9k_hw_ani_monitor(ah, &sc->nodestats,
ah->curchan);
ath9k_hw_ani_monitor(ah, &sc->nodestats, ah->curchan);
/* Perform calibration if necessary */
if (longcal || shortcal) {
@ -392,6 +389,7 @@ static void ath_ani_calibrate(unsigned long data)
}
}
set_timer:
/*
* Set timer interval based on previous results.
* The interval must be the shortest necessary to satisfy ANI,
@ -401,7 +399,7 @@ static void ath_ani_calibrate(unsigned long data)
if (sc->sc_ah->config.enable_ani)
cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL);
if (!sc->ani.caldone)
cal_interval = min(cal_interval, (u32)ATH_SHORT_CALINTERVAL);
cal_interval = min(cal_interval, (u32)short_cal_interval);
mod_timer(&sc->ani.timer, jiffies + msecs_to_jiffies(cal_interval));
}
@ -574,6 +572,10 @@ irqreturn_t ath_isr(int irq, void *dev)
sc->sc_flags |= SC_OP_WAIT_FOR_BEACON;
}
}
if (status & ATH9K_INT_TSFOOR) {
/* FIXME: Handle this interrupt for power save */
sched = true;
}
}
} while (0);
@ -920,8 +922,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
/* Start ANI */
mod_timer(&sc->ani.timer,
jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
} else {
DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info DISSOC\n");
sc->curaid = 0;
@ -1566,6 +1567,7 @@ bad:
int ath_attach(u16 devid, struct ath_softc *sc)
{
struct ieee80211_hw *hw = sc->hw;
const struct ieee80211_regdomain *regd;
int error = 0, i;
DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n");
@ -1598,6 +1600,7 @@ int ath_attach(u16 devid, struct ath_softc *sc)
hw->queues = 4;
hw->max_rates = 4;
hw->channel_change_time = 5000;
hw->max_rate_tries = ATH_11N_TXMAXTRY;
hw->sta_data_size = sizeof(struct ath_node);
hw->vif_data_size = sizeof(struct ath_vif);
@ -1636,30 +1639,29 @@ int ath_attach(u16 devid, struct ath_softc *sc)
#endif
if (ath9k_is_world_regd(sc->sc_ah)) {
/* Anything applied here (prior to wiphy registratoin) gets
/* Anything applied here (prior to wiphy registration) gets
* saved on the wiphy orig_* parameters */
const struct ieee80211_regdomain *regd =
ath9k_world_regdomain(sc->sc_ah);
regd = ath9k_world_regdomain(sc->sc_ah);
hw->wiphy->custom_regulatory = true;
hw->wiphy->strict_regulatory = false;
wiphy_apply_custom_regulatory(sc->hw->wiphy, regd);
ath9k_reg_apply_radar_flags(hw->wiphy);
ath9k_reg_apply_world_flags(hw->wiphy, REGDOM_SET_BY_INIT);
} else {
/* This gets applied in the case of the absense of CRDA,
* its our own custom world regulatory domain, similar to
* it's our own custom world regulatory domain, similar to
* cfg80211's but we enable passive scanning */
const struct ieee80211_regdomain *regd =
ath9k_default_world_regdomain();
wiphy_apply_custom_regulatory(sc->hw->wiphy, regd);
ath9k_reg_apply_radar_flags(hw->wiphy);
ath9k_reg_apply_world_flags(hw->wiphy, REGDOM_SET_BY_INIT);
regd = ath9k_default_world_regdomain();
}
wiphy_apply_custom_regulatory(hw->wiphy, regd);
ath9k_reg_apply_radar_flags(hw->wiphy);
ath9k_reg_apply_world_flags(hw->wiphy, REGDOM_SET_BY_INIT);
error = ieee80211_register_hw(hw);
if (!ath9k_is_world_regd(sc->sc_ah))
regulatory_hint(hw->wiphy, sc->sc_ah->regulatory.alpha2);
if (!ath9k_is_world_regd(sc->sc_ah)) {
error = regulatory_hint(hw->wiphy,
sc->sc_ah->regulatory.alpha2);
if (error)
goto error_attach;
}
/* Initialize LED control */
ath_init_leds(sc);
@ -2143,6 +2145,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
default:
DPRINTF(sc, ATH_DBG_FATAL,
"Interface type %d not yet supported\n", conf->type);
mutex_unlock(&sc->mutex);
return -EOPNOTSUPP;
}
@ -2165,10 +2168,13 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
* Enable MIB interrupts when there are hardware phy counters.
* Note we only do this (at the moment) for station mode.
*/
if (ath9k_hw_phycounters(sc->sc_ah) &&
((conf->type == NL80211_IFTYPE_STATION) ||
(conf->type == NL80211_IFTYPE_ADHOC)))
sc->imask |= ATH9K_INT_MIB;
if ((conf->type == NL80211_IFTYPE_STATION) ||
(conf->type == NL80211_IFTYPE_ADHOC)) {
if (ath9k_hw_phycounters(sc->sc_ah))
sc->imask |= ATH9K_INT_MIB;
sc->imask |= ATH9K_INT_TSFOOR;
}
/*
* Some hardware processes the TIM IE and fires an
* interrupt when the TIM bit is set. For hardware

View file

@ -52,8 +52,8 @@ static void ath_pci_cleanup(struct ath_softc *sc)
struct pci_dev *pdev = to_pci_dev(sc->dev);
pci_iounmap(pdev, sc->mem);
pci_release_region(pdev, 0);
pci_disable_device(pdev);
pci_release_region(pdev, 0);
}
static bool ath_pci_eeprom_read(struct ath_hw *ah, u32 off, u16 *data)
@ -63,7 +63,8 @@ static bool ath_pci_eeprom_read(struct ath_hw *ah, u32 off, u16 *data)
if (!ath9k_hw_wait(ah,
AR_EEPROM_STATUS_DATA,
AR_EEPROM_STATUS_DATA_BUSY |
AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0)) {
AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0,
AH_WAIT_TIMEOUT)) {
return false;
}
@ -292,7 +293,7 @@ static struct pci_driver ath_pci_driver = {
#endif /* CONFIG_PM */
};
int __init ath_pci_init(void)
int ath_pci_init(void)
{
return pci_register_driver(&ath_pci_driver);
}

View file

@ -132,20 +132,27 @@ ath9k_hw_ar9280_set_channel(struct ath_hw *ah,
bMode = 0;
fracMode = 0;
if ((freq % 20) == 0) {
aModeRefSel = 3;
} else if ((freq % 10) == 0) {
aModeRefSel = 2;
} else {
switch(ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) {
case 0:
if ((freq % 20) == 0) {
aModeRefSel = 3;
} else if ((freq % 10) == 0) {
aModeRefSel = 2;
}
if (aModeRefSel)
break;
case 1:
default:
aModeRefSel = 0;
fracMode = 1;
refDivA = 1;
channelSel = (freq * 0x8000) / 15;
REG_RMW_FIELD(ah, AR_AN_SYNTH9,
AR_AN_SYNTH9_REFDIVA, refDivA);
}
if (!fracMode) {
ndiv = (freq * (refDivA >> aModeRefSel)) / 60;
channelSel = ndiv & 0x1ff;

View file

@ -387,6 +387,8 @@ bool ath9k_hw_init_rf(struct ath_hw *ah,
#define AR_PHY_CCK_TX_CTRL 0xA204
#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010
#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK 0x0000000C
#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S 2
#define AR_PHY_CCK_DETECT 0xA208
#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F
@ -444,6 +446,29 @@ bool ath9k_hw_init_rf(struct ath_hw *ah,
#define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000
#define AR_PHY_TPCRG1_PD_GAIN_3_S 20
#define AR_PHY_TX_PWRCTRL4 0xa264
#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID 0x00000001
#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID_S 0
#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT 0x000001FE
#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT_S 1
#define AR_PHY_TX_PWRCTRL6_0 0xa270
#define AR_PHY_TX_PWRCTRL6_1 0xb270
#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE 0x03000000
#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24
#define AR_PHY_TX_PWRCTRL7 0xa274
#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000
#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19
#define AR_PHY_TX_PWRCTRL9 0xa27C
#define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00
#define AR_PHY_TX_DESIRED_SCALE_CCK_S 10
#define AR_PHY_TX_GAIN_TBL1 0xa300
#define AR_PHY_TX_GAIN 0x0007F000
#define AR_PHY_TX_GAIN_S 12
#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0
#define AR_PHY_MASK2_M_31_45 0xa3a4
#define AR_PHY_MASK2_M_16_30 0xa3a8
@ -485,6 +510,10 @@ bool ath9k_hw_init_rf(struct ath_hw *ah,
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 0x0FC00000
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22
/* Carrier leak calibration control, do it after AGC calibration */
#define AR_PHY_CL_CAL_CTL 0xA358
#define AR_PHY_CL_CAL_ENABLE 0x00000002
#define AR_PHY_POWER_TX_RATE5 0xA38C
#define AR_PHY_POWER_TX_RATE6 0xA390

View file

@ -1267,7 +1267,8 @@ static void ath_rc_update_ht(struct ath_softc *sc,
ath_rc_priv->per_down_time = now_msec;
}
ath_debug_stat_retries(sc, tx_rate, xretries, retries);
ath_debug_stat_retries(sc, tx_rate, xretries, retries,
ath_rc_priv->state[tx_rate].per);
#undef CHK_RSSI
}
@ -1392,6 +1393,7 @@ static void ath_rc_init(struct ath_softc *sc,
struct ath_rateset *rateset = &ath_rc_priv->neg_rates;
u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates;
u8 i, j, k, hi = 0, hthi = 0;
struct ath_hw *ah = sc->sc_ah;
/* FIXME: Adhoc */
if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) ||
@ -1412,7 +1414,8 @@ static void ath_rc_init(struct ath_softc *sc,
if (sta->ht_cap.ht_supported) {
ath_rc_priv->ht_cap = WLAN_RC_HT_FLAG;
if (sc->sc_ah->caps.tx_chainmask != 1)
if (sc->sc_ah->caps.tx_chainmask != 1 &&
ath9k_hw_getcapability(ah, ATH9K_CAP_DS, 0, NULL))
ath_rc_priv->ht_cap |= WLAN_RC_DS_FLAG;
if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
ath_rc_priv->ht_cap |= WLAN_RC_40_FLAG;
@ -1533,7 +1536,8 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
tx_info_priv->tx.ts_longretry);
/* Check if aggregation has to be enabled for this tid */
if (conf_is_ht(&sc->hw->conf)) {
if (conf_is_ht(&sc->hw->conf) &&
!(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
if (ieee80211_is_data_qos(fc)) {
u8 *qc, tid;
struct ath_node *an;

View file

@ -375,14 +375,15 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
if (sc->rx.rxfilter & FIF_CONTROL)
rfilt |= ATH9K_RX_FILTER_CONTROL;
if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION ||
sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)
if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) &&
!(sc->rx.rxfilter & FIF_BCN_PRBRESP_PROMISC))
rfilt |= ATH9K_RX_FILTER_MYBEACON;
else
rfilt |= ATH9K_RX_FILTER_BEACON;
/* If in HOSTAP mode, want to enable reception of PSPOLL frames
& beacon frames */
/* If in HOSTAP mode, want to enable reception of PSPOLL frames */
if (sc->sc_ah->opmode == NL80211_IFTYPE_AP)
rfilt |= (ATH9K_RX_FILTER_BEACON | ATH9K_RX_FILTER_PSPOLL);
rfilt |= ATH9K_RX_FILTER_PSPOLL;
return rfilt;
@ -427,7 +428,6 @@ bool ath_stoprecv(struct ath_softc *sc)
ath9k_hw_stoppcurecv(ah);
ath9k_hw_setrxfilter(ah, 0);
stopped = ath9k_hw_stopdmarecv(ah);
mdelay(3); /* 3ms is long enough for 1 frame */
sc->rx.rxlink = NULL;
return stopped;

View file

@ -977,8 +977,6 @@ enum {
#define AR_RTC_PLL_CLKSEL 0x00000300
#define AR_RTC_PLL_CLKSEL_S 8
#define AR_RTC_RESET \
((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0040) : 0x7040)
#define AR_RTC_RESET_EN (0x00000001)
@ -1015,6 +1013,12 @@ enum {
#define AR_RTC_INTR_MASK \
((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0058) : 0x7058)
/* RTC_DERIVED_* - only for AR9100 */
#define AR_RTC_DERIVED_CLK (AR_RTC_BASE + 0x0038)
#define AR_RTC_DERIVED_CLK_PERIOD 0x0000fffe
#define AR_RTC_DERIVED_CLK_PERIOD_S 1
#define AR_SEQ_MASK 0x8060
#define AR_AN_RF2G1_CH0 0x7810
@ -1385,8 +1389,8 @@ enum {
#define AR_PHY_COUNTMAX (3 << 22)
#define AR_MIBCNT_INTRMASK (3 << 22)
#define AR_TSF_THRESHOLD 0x813c
#define AR_TSF_THRESHOLD_VAL 0x0000FFFF
#define AR_TSFOOR_THRESHOLD 0x813c
#define AR_TSFOOR_THRESHOLD_VAL 0x0000FFFF
#define AR_PHY_ERR_EIFS_MASK 8144

View file

@ -106,19 +106,20 @@ static const struct ieee80211_regdomain ath9k_world_regdom_67_68_6A = {
}
};
static inline bool is_wwr_sku(u16 regd)
{
return ((regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) ||
(regd == WORLD);
}
static u16 ath9k_regd_get_eepromRD(struct ath_hw *ah)
{
return ah->regulatory.current_rd & ~WORLDWIDE_ROAMING_FLAG;
}
u16 ath9k_regd_get_rd(struct ath_hw *ah)
{
return ath9k_regd_get_eepromRD(ah);
}
bool ath9k_is_world_regd(struct ath_hw *ah)
{
return isWwrSKU(ah);
return is_wwr_sku(ath9k_regd_get_eepromRD(ah));
}
const struct ieee80211_regdomain *ath9k_default_world_regdomain(void)
@ -159,13 +160,18 @@ static bool ath9k_is_radar_freq(u16 center_freq)
}
/*
* Enable adhoc on 5 GHz if allowed by 11d.
* Remove passive scan if channel is allowed by 11d,
* except when on radar frequencies.
* N.B: These exception rules do not apply radar freqs.
*
* - We enable adhoc (or beaconing) if allowed by 11d
* - We enable active scan if the channel is allowed by 11d
* - If no country IE has been processed and a we determine we have
* received a beacon on a channel we can enable active scan and
* adhoc (or beaconing).
*/
static void ath9k_reg_apply_5ghz_beaconing_flags(struct wiphy *wiphy,
static void ath9k_reg_apply_beaconing_flags(struct wiphy *wiphy,
enum reg_set_by setby)
{
enum ieee80211_band band;
struct ieee80211_supported_band *sband;
const struct ieee80211_reg_rule *reg_rule;
struct ieee80211_channel *ch;
@ -173,29 +179,50 @@ static void ath9k_reg_apply_5ghz_beaconing_flags(struct wiphy *wiphy,
u32 bandwidth = 0;
int r;
if (setby != REGDOM_SET_BY_COUNTRY_IE)
return;
if (!wiphy->bands[IEEE80211_BAND_5GHZ])
return;
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
sband = wiphy->bands[IEEE80211_BAND_5GHZ];
for (i = 0; i < sband->n_channels; i++) {
ch = &sband->channels[i];
r = freq_reg_info(wiphy, ch->center_freq,
&bandwidth, &reg_rule);
if (r)
if (!wiphy->bands[band])
continue;
/* If 11d had a rule for this channel ensure we enable adhoc
* if it allows us to use it. Note that we would have disabled
* it by applying our static world regdomain by default during
* probe */
if (!(reg_rule->flags & NL80211_RRF_NO_IBSS))
ch->flags &= ~IEEE80211_CHAN_NO_IBSS;
if (!ath9k_is_radar_freq(ch->center_freq))
continue;
if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
sband = wiphy->bands[band];
for (i = 0; i < sband->n_channels; i++) {
ch = &sband->channels[i];
if (ath9k_is_radar_freq(ch->center_freq) ||
(ch->flags & IEEE80211_CHAN_RADAR))
continue;
if (setby == REGDOM_SET_BY_COUNTRY_IE) {
r = freq_reg_info(wiphy, ch->center_freq,
&bandwidth, &reg_rule);
if (r)
continue;
/*
* If 11d had a rule for this channel ensure
* we enable adhoc/beaconing if it allows us to
* use it. Note that we would have disabled it
* by applying our static world regdomain by
* default during init, prior to calling our
* regulatory_hint().
*/
if (!(reg_rule->flags &
NL80211_RRF_NO_IBSS))
ch->flags &=
~IEEE80211_CHAN_NO_IBSS;
if (!(reg_rule->flags &
NL80211_RRF_PASSIVE_SCAN))
ch->flags &=
~IEEE80211_CHAN_PASSIVE_SCAN;
} else {
if (ch->beacon_found)
ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
IEEE80211_CHAN_PASSIVE_SCAN);
}
}
}
}
/* Allows active scan scan on Ch 12 and 13 */
@ -208,11 +235,12 @@ static void ath9k_reg_apply_active_scan_flags(struct wiphy *wiphy,
u32 bandwidth = 0;
int r;
/* Force passive scan on Channels 12-13 */
sband = wiphy->bands[IEEE80211_BAND_2GHZ];
/* If no country IE has been received always enable active scan
* on these channels */
/*
* If no country IE has been received always enable active scan
* on these channels. This is only done for specific regulatory SKUs
*/
if (setby != REGDOM_SET_BY_COUNTRY_IE) {
ch = &sband->channels[11]; /* CH 12 */
if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
@ -223,10 +251,12 @@ static void ath9k_reg_apply_active_scan_flags(struct wiphy *wiphy,
return;
}
/* If a country IE has been recieved check its rule for this
/*
* If a country IE has been recieved check its rule for this
* channel first before enabling active scan. The passive scan
* would have been enforced by the initial probe processing on
* our custom regulatory domain. */
* would have been enforced by the initial processing of our
* custom regulatory domain.
*/
ch = &sband->channels[11]; /* CH 12 */
r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, &reg_rule);
@ -289,10 +319,10 @@ void ath9k_reg_apply_world_flags(struct wiphy *wiphy, enum reg_set_by setby)
case 0x63:
case 0x66:
case 0x67:
ath9k_reg_apply_5ghz_beaconing_flags(wiphy, setby);
ath9k_reg_apply_beaconing_flags(wiphy, setby);
break;
case 0x68:
ath9k_reg_apply_5ghz_beaconing_flags(wiphy, setby);
ath9k_reg_apply_beaconing_flags(wiphy, setby);
ath9k_reg_apply_active_scan_flags(wiphy, setby);
break;
}
@ -371,11 +401,8 @@ ath9k_regd_find_country_by_rd(int regdmn)
}
/* Returns the map of the EEPROM set RD to a country code */
static u16 ath9k_regd_get_default_country(struct ath_hw *ah)
static u16 ath9k_regd_get_default_country(u16 rd)
{
u16 rd;
rd = ath9k_regd_get_eepromRD(ah);
if (rd & COUNTRY_ERD_FLAG) {
struct country_code_to_enum_rd *country = NULL;
u16 cc = rd & ~COUNTRY_ERD_FLAG;
@ -405,7 +432,7 @@ ath9k_get_regpair(int regdmn)
int ath9k_regd_init(struct ath_hw *ah)
{
struct country_code_to_enum_rd *country = NULL;
int regdmn;
u16 regdmn;
if (!ath9k_regd_is_eeprom_valid(ah)) {
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
@ -413,14 +440,14 @@ int ath9k_regd_init(struct ath_hw *ah)
return -EINVAL;
}
ah->regulatory.country_code = ath9k_regd_get_default_country(ah);
regdmn = ath9k_regd_get_eepromRD(ah);
ah->regulatory.country_code = ath9k_regd_get_default_country(regdmn);
if (ah->regulatory.country_code == CTRY_DEFAULT &&
ath9k_regd_get_eepromRD(ah) == CTRY_DEFAULT)
regdmn == CTRY_DEFAULT)
ah->regulatory.country_code = CTRY_UNITED_STATES;
if (ah->regulatory.country_code == CTRY_DEFAULT) {
regdmn = ath9k_regd_get_eepromRD(ah);
country = NULL;
} else {
country = ath9k_regd_find_country(ah->regulatory.country_code);
@ -433,7 +460,6 @@ int ath9k_regd_init(struct ath_hw *ah)
regdmn = country->regDmnEnum;
}
ah->regulatory.current_rd_inuse = regdmn;
ah->regulatory.regpair = ath9k_get_regpair(regdmn);
if (!ah->regulatory.regpair) {
@ -467,7 +493,8 @@ u32 ath9k_regd_get_ctl(struct ath_hw *ah, struct ath9k_channel *chan)
u32 ctl = NO_CTL;
if (!ah->regulatory.regpair ||
(ah->regulatory.country_code == CTRY_DEFAULT && isWwrSKU(ah))) {
(ah->regulatory.country_code == CTRY_DEFAULT &&
is_wwr_sku(ath9k_regd_get_eepromRD(ah)))) {
if (IS_CHAN_B(chan))
ctl = SD_NO_CTL | CTL_11B;
else if (IS_CHAN_G(chan))
@ -480,7 +507,7 @@ u32 ath9k_regd_get_ctl(struct ath_hw *ah, struct ath9k_channel *chan)
if (IS_CHAN_B(chan))
ctl = ah->regulatory.regpair->reg_2ghz_ctl | CTL_11B;
else if (IS_CHAN_G(chan))
ctl = ah->regulatory.regpair->reg_5ghz_ctl | CTL_11G;
ctl = ah->regulatory.regpair->reg_2ghz_ctl | CTL_11G;
else
ctl = ah->regulatory.regpair->reg_5ghz_ctl | CTL_11A;

View file

@ -20,11 +20,6 @@
#define COUNTRY_ERD_FLAG 0x8000
#define WORLDWIDE_ROAMING_FLAG 0x4000
#define isWwrSKU(_ah) \
(((ath9k_regd_get_eepromRD((_ah)) & WORLD_SKU_MASK) == \
WORLD_SKU_PREFIX) || \
(ath9k_regd_get_eepromRD(_ah) == WORLD))
#define MULTI_DOMAIN_MASK 0xFF00
#define WORLD_SKU_MASK 0x00F0
@ -52,7 +47,6 @@ struct ath9k_regulatory {
u32 tp_scale;
u16 current_rd;
u16 current_rd_ext;
u16 current_rd_inuse;
int16_t power_limit;
struct reg_dmn_pair_mapping *regpair;
};
@ -239,7 +233,6 @@ enum CountryCode {
CTRY_BELGIUM2 = 5002
};
u16 ath9k_regd_get_rd(struct ath_hw *ah);
bool ath9k_is_world_regd(struct ath_hw *ah);
const struct ieee80211_regdomain *ath9k_world_regdomain(struct ath_hw *ah);
const struct ieee80211_regdomain *ath9k_default_world_regdomain(void);
@ -249,7 +242,5 @@ int ath9k_regd_init(struct ath_hw *ah);
bool ath9k_regd_is_eeprom_valid(struct ath_hw *ah);
u32 ath9k_regd_get_ctl(struct ath_hw *ah, struct ath9k_channel *chan);
int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request);
void ath9k_regd_get_current_country(struct ath_hw *ah,
struct ath9k_country_entry *ctry);
#endif

View file

@ -772,24 +772,6 @@ bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno)
/* Queue Management */
/********************/
static u32 ath_txq_depth(struct ath_softc *sc, int qnum)
{
return sc->tx.txq[qnum].axq_depth;
}
static void ath_get_beaconconfig(struct ath_softc *sc, int if_id,
struct ath_beacon_config *conf)
{
struct ieee80211_hw *hw = sc->hw;
/* fill in beacon config data */
conf->beacon_interval = hw->conf.beacon_int;
conf->listen_interval = 100;
conf->dtim_count = 1;
conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval;
}
static void ath_txq_drain_pending_buffers(struct ath_softc *sc,
struct ath_txq *txq)
{
@ -964,7 +946,6 @@ int ath_cabq_update(struct ath_softc *sc)
{
struct ath9k_tx_queue_info qi;
int qnum = sc->beacon.cabq->axq_qnum;
struct ath_beacon_config conf;
ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi);
/*
@ -975,9 +956,8 @@ int ath_cabq_update(struct ath_softc *sc)
else if (sc->config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND)
sc->config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND;
ath_get_beaconconfig(sc, ATH_IF_ID_ANY, &conf);
qi.tqi_readyTime =
(conf.beacon_interval * sc->config.cabqReadytime) / 100;
qi.tqi_readyTime = (sc->hw->conf.beacon_int *
sc->config.cabqReadytime) / 100;
ath_txq_update(sc, qnum, &qi);
return 0;
@ -1657,7 +1637,7 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb,
* we will at least have to run TX completionon one buffer
* on the queue */
spin_lock_bh(&txq->axq_lock);
if (ath_txq_depth(sc, txq->axq_qnum) > 1) {
if (sc->tx.txq[txq->axq_qnum].axq_depth > 1) {
ieee80211_stop_queue(sc->hw,
skb_get_queue_mapping(skb));
txq->stopped = 1;
@ -1867,7 +1847,7 @@ static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq)
spin_lock_bh(&txq->axq_lock);
if (txq->stopped &&
ath_txq_depth(sc, txq->axq_qnum) <= (ATH_TXBUF - 20)) {
sc->tx.txq[txq->axq_qnum].axq_depth <= (ATH_TXBUF - 20)) {
qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc);
if (qnum != -1) {
ieee80211_wake_queue(sc->hw, qnum);

View file

@ -51,8 +51,8 @@ struct b43_debugfs_fops {
};
static inline
struct b43_dfs_file * fops_to_dfs_file(struct b43_wldev *dev,
const struct b43_debugfs_fops *dfops)
struct b43_dfs_file *fops_to_dfs_file(struct b43_wldev *dev,
const struct b43_debugfs_fops *dfops)
{
void *p;

View file

@ -41,6 +41,12 @@
#include <asm/div64.h>
/* Required number of TX DMA slots per TX frame.
* This currently is 2, because we put the header and the ieee80211 frame
* into separate slots. */
#define TX_SLOTS_PER_FRAME 2
/* 32bit DMA ops. */
static
struct b43_dmadesc_generic *op32_idx2desc(struct b43_dmaring *ring,
@ -74,8 +80,7 @@ static void op32_fill_descriptor(struct b43_dmaring *ring,
addrext = (u32) (dmaaddr & SSB_DMA_TRANSLATION_MASK)
>> SSB_DMA_TRANSLATION_SHIFT;
addr |= ssb_dma_translation(ring->dev->dev);
ctl = (bufsize - ring->frameoffset)
& B43_DMA32_DCTL_BYTECNT;
ctl = bufsize & B43_DMA32_DCTL_BYTECNT;
if (slot == ring->nr_slots - 1)
ctl |= B43_DMA32_DCTL_DTABLEEND;
if (start)
@ -177,8 +182,7 @@ static void op64_fill_descriptor(struct b43_dmaring *ring,
ctl0 |= B43_DMA64_DCTL0_FRAMEEND;
if (irq)
ctl0 |= B43_DMA64_DCTL0_IRQ;
ctl1 |= (bufsize - ring->frameoffset)
& B43_DMA64_DCTL1_BYTECNT;
ctl1 |= bufsize & B43_DMA64_DCTL1_BYTECNT;
ctl1 |= (addrext << B43_DMA64_DCTL1_ADDREXT_SHIFT)
& B43_DMA64_DCTL1_ADDREXT_MASK;
@ -576,12 +580,11 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring,
return -ENOMEM;
dmaaddr = map_descbuffer(ring, skb->data,
ring->rx_buffersize, 0);
}
if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) {
b43err(ring->dev->wl, "RX DMA buffer allocation failed\n");
dev_kfree_skb_any(skb);
return -EIO;
if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) {
b43err(ring->dev->wl, "RX DMA buffer allocation failed\n");
dev_kfree_skb_any(skb);
return -EIO;
}
}
meta->skb = skb;
@ -830,9 +833,6 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
if (ring->index == 0) {
ring->rx_buffersize = B43_DMA0_RX_BUFFERSIZE;
ring->frameoffset = B43_DMA0_RX_FRAMEOFFSET;
} else if (ring->index == 3) {
ring->rx_buffersize = B43_DMA3_RX_BUFFERSIZE;
ring->frameoffset = B43_DMA3_RX_FRAMEOFFSET;
} else
B43_WARN_ON(1);
}
@ -842,7 +842,10 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
#endif
if (for_tx) {
ring->txhdr_cache = kcalloc(ring->nr_slots,
/* Assumption: B43_TXRING_SLOTS can be divided by TX_SLOTS_PER_FRAME */
BUILD_BUG_ON(B43_TXRING_SLOTS % TX_SLOTS_PER_FRAME != 0);
ring->txhdr_cache = kcalloc(ring->nr_slots / TX_SLOTS_PER_FRAME,
b43_txhdr_size(dev),
GFP_KERNEL);
if (!ring->txhdr_cache)
@ -858,7 +861,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
b43_txhdr_size(dev), 1)) {
/* ugh realloc */
kfree(ring->txhdr_cache);
ring->txhdr_cache = kcalloc(ring->nr_slots,
ring->txhdr_cache = kcalloc(ring->nr_slots / TX_SLOTS_PER_FRAME,
b43_txhdr_size(dev),
GFP_KERNEL | GFP_DMA);
if (!ring->txhdr_cache)
@ -1149,7 +1152,10 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
u16 cookie;
size_t hdrsize = b43_txhdr_size(ring->dev);
#define SLOTS_PER_PACKET 2
/* Important note: If the number of used DMA slots per TX frame
* is changed here, the TX_SLOTS_PER_FRAME definition at the top of
* the file has to be updated, too!
*/
old_top_slot = ring->current_slot;
old_used_slots = ring->used_slots;
@ -1159,7 +1165,7 @@ 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 * hdrsize]);
header = &(ring->txhdr_cache[(slot / TX_SLOTS_PER_FRAME) * hdrsize]);
cookie = generate_cookie(ring, slot);
err = b43_generate_txhdr(ring->dev, header,
skb->data, skb->len, info, cookie);
@ -1254,8 +1260,8 @@ static inline int should_inject_overflow(struct b43_dmaring *ring)
}
/* Static mapping of mac80211's queues (priorities) to b43 DMA rings. */
static struct b43_dmaring * select_ring_by_priority(struct b43_wldev *dev,
u8 queue_prio)
static struct b43_dmaring *select_ring_by_priority(struct b43_wldev *dev,
u8 queue_prio)
{
struct b43_dmaring *ring;
@ -1306,17 +1312,19 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
}
spin_lock_irqsave(&ring->lock, flags);
B43_WARN_ON(!ring->tx);
if (unlikely(free_slots(ring) < SLOTS_PER_PACKET)) {
b43warn(dev->wl, "DMA queue overflow\n");
err = -ENOSPC;
goto out_unlock;
}
/* Check if the queue was stopped in mac80211,
* but we got called nevertheless.
* That would be a mac80211 bug. */
B43_WARN_ON(ring->stopped);
if (unlikely(free_slots(ring) < TX_SLOTS_PER_FRAME)) {
b43warn(dev->wl, "DMA queue overflow\n");
err = -ENOSPC;
goto out_unlock;
}
/* Assign the queue number to the ring (if not already done before)
* so TX status handling can use it. The queue to ring mapping is
* static, so we don't need to store it per frame. */
@ -1335,7 +1343,7 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
goto out_unlock;
}
ring->nr_tx_packets++;
if ((free_slots(ring) < SLOTS_PER_PACKET) ||
if ((free_slots(ring) < TX_SLOTS_PER_FRAME) ||
should_inject_overflow(ring)) {
/* This TX ring is full. */
ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb));
@ -1419,7 +1427,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
}
dev->stats.last_tx = jiffies;
if (ring->stopped) {
B43_WARN_ON(free_slots(ring) < SLOTS_PER_PACKET);
B43_WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME);
ieee80211_wake_queue(dev->wl->hw, ring->queue_prio);
ring->stopped = 0;
if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
@ -1442,8 +1450,8 @@ void b43_dma_get_tx_stats(struct b43_wldev *dev,
ring = select_ring_by_priority(dev, i);
spin_lock_irqsave(&ring->lock, flags);
stats[i].len = ring->used_slots / SLOTS_PER_PACKET;
stats[i].limit = ring->nr_slots / SLOTS_PER_PACKET;
stats[i].len = ring->used_slots / TX_SLOTS_PER_FRAME;
stats[i].limit = ring->nr_slots / TX_SLOTS_PER_FRAME;
stats[i].count = ring->nr_tx_packets;
spin_unlock_irqrestore(&ring->lock, flags);
}

View file

@ -1,14 +1,12 @@
#ifndef B43_DMA_H_
#define B43_DMA_H_
#include <linux/list.h>
#include <linux/ieee80211.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/linkage.h>
#include <asm/atomic.h>
#include "b43.h"
/* DMA-Interrupt reasons. */
#define B43_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \
| (1 << 14) | (1 << 15))
@ -161,14 +159,13 @@ struct b43_dmadesc_generic {
/* Misc DMA constants */
#define B43_DMA_RINGMEMSIZE PAGE_SIZE
#define B43_DMA0_RX_FRAMEOFFSET 30
#define B43_DMA3_RX_FRAMEOFFSET 0
#define B43_DMA0_RX_FRAMEOFFSET 30
/* DMA engine tuning knobs */
#define B43_TXRING_SLOTS 128
#define B43_TXRING_SLOTS 256
#define B43_RXRING_SLOTS 64
#define B43_DMA0_RX_BUFFERSIZE (2304 + 100)
#define B43_DMA3_RX_BUFFERSIZE 16
#define B43_DMA0_RX_BUFFERSIZE IEEE80211_MAX_FRAME_LEN
struct sk_buff;
struct b43_private;
@ -215,7 +212,7 @@ struct b43_dmaring {
void *descbase;
/* Meta data about all descriptors. */
struct b43_dmadesc_meta *meta;
/* Cache of TX headers for each slot.
/* Cache of TX headers for each TX frame.
* This is to avoid an allocation on each TX.
* This is NULL for an RX ring.
*/

View file

@ -36,8 +36,8 @@
#include <linux/sched.h>
static struct b43_lo_calib * b43_find_lo_calib(struct b43_txpower_lo_control *lo,
const struct b43_bbatt *bbatt,
static struct b43_lo_calib *b43_find_lo_calib(struct b43_txpower_lo_control *lo,
const struct b43_bbatt *bbatt,
const struct b43_rfatt *rfatt)
{
struct b43_lo_calib *c;
@ -138,7 +138,7 @@ static u16 lo_measure_feedthrough(struct b43_wldev *dev,
* "pad_mix_gain" is the PAD Mixer Gain.
*/
static u16 lo_txctl_register_table(struct b43_wldev *dev,
u16 * value, u16 * pad_mix_gain)
u16 *value, u16 *pad_mix_gain)
{
struct b43_phy *phy = &dev->phy;
u16 reg, v, padmix;
@ -225,14 +225,12 @@ static void lo_measure_txctl_values(struct b43_wldev *dev)
radio_pctl_reg = tmp;
}
}
b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43)
& 0xFFF0) | radio_pctl_reg);
b43_radio_maskset(dev, 0x43, 0xFFF0, radio_pctl_reg);
b43_gphy_set_baseband_attenuation(dev, 2);
reg = lo_txctl_register_table(dev, &mask, NULL);
mask = ~mask;
b43_radio_write16(dev, reg, b43_radio_read16(dev, reg)
& mask);
b43_radio_mask(dev, reg, mask);
if (has_tx_magnification(phy)) {
int i, j;
@ -242,14 +240,10 @@ static void lo_measure_txctl_values(struct b43_wldev *dev)
for (i = 0; i < ARRAY_SIZE(tx_magn_values); i++) {
tx_magn = tx_magn_values[i];
b43_radio_write16(dev, 0x52,
(b43_radio_read16(dev, 0x52)
& 0xFF0F) | tx_magn);
b43_radio_maskset(dev, 0x52, 0xFF0F, tx_magn);
for (j = 0; j < ARRAY_SIZE(tx_bias_values); j++) {
tx_bias = tx_bias_values[j];
b43_radio_write16(dev, 0x52,
(b43_radio_read16(dev, 0x52)
& 0xFFF0) | tx_bias);
b43_radio_maskset(dev, 0x52, 0xFFF0, tx_bias);
feedthrough =
lo_measure_feedthrough(dev, 0, pga,
trsw_rx);
@ -269,8 +263,7 @@ static void lo_measure_txctl_values(struct b43_wldev *dev)
} else {
lo->tx_magn = 0;
lo->tx_bias = 0;
b43_radio_write16(dev, 0x52, b43_radio_read16(dev, 0x52)
& 0xFFF0); /* TX bias == 0 */
b43_radio_mask(dev, 0x52, 0xFFF0); /* TX bias == 0 */
}
lo->txctl_measured_time = jiffies;
}
@ -406,18 +399,10 @@ static void lo_measure_setup(struct b43_wldev *dev,
sav->phy_cck_14 = b43_phy_read(dev, B43_PHY_CCK(0x14));
sav->phy_hpwr_tssictl = b43_phy_read(dev, B43_PHY_HPWR_TSSICTL);
b43_phy_write(dev, B43_PHY_HPWR_TSSICTL,
b43_phy_read(dev, B43_PHY_HPWR_TSSICTL)
| 0x100);
b43_phy_write(dev, B43_PHY_EXTG(0x01),
b43_phy_read(dev, B43_PHY_EXTG(0x01))
| 0x40);
b43_phy_write(dev, B43_PHY_DACCTL,
b43_phy_read(dev, B43_PHY_DACCTL)
| 0x40);
b43_phy_write(dev, B43_PHY_CCK(0x14),
b43_phy_read(dev, B43_PHY_CCK(0x14))
| 0x200);
b43_phy_set(dev, B43_PHY_HPWR_TSSICTL, 0x100);
b43_phy_set(dev, B43_PHY_EXTG(0x01), 0x40);
b43_phy_set(dev, B43_PHY_DACCTL, 0x40);
b43_phy_set(dev, B43_PHY_CCK(0x14), 0x200);
}
if (phy->type == B43_PHYTYPE_B &&
phy->radio_ver == 0x2050 && phy->radio_rev < 6) {
@ -434,17 +419,10 @@ static void lo_measure_setup(struct b43_wldev *dev,
sav->phy_cck_3E = b43_phy_read(dev, B43_PHY_CCK(0x3E));
sav->phy_crs0 = b43_phy_read(dev, B43_PHY_CRS0);
b43_phy_write(dev, B43_PHY_CLASSCTL,
b43_phy_read(dev, B43_PHY_CLASSCTL)
& 0xFFFC);
b43_phy_write(dev, B43_PHY_CRS0, b43_phy_read(dev, B43_PHY_CRS0)
& 0x7FFF);
b43_phy_write(dev, B43_PHY_ANALOGOVER,
b43_phy_read(dev, B43_PHY_ANALOGOVER)
| 0x0003);
b43_phy_write(dev, B43_PHY_ANALOGOVERVAL,
b43_phy_read(dev, B43_PHY_ANALOGOVERVAL)
& 0xFFFC);
b43_phy_mask(dev, B43_PHY_CLASSCTL, 0xFFFC);
b43_phy_mask(dev, B43_PHY_CRS0, 0x7FFF);
b43_phy_set(dev, B43_PHY_ANALOGOVER, 0x0003);
b43_phy_mask(dev, B43_PHY_ANALOGOVERVAL, 0xFFFC);
if (phy->type == B43_PHYTYPE_G) {
if ((phy->rev >= 7) &&
(sprom->boardflags_lo & B43_BFL_EXTLNA)) {
@ -558,8 +536,7 @@ static void lo_measure_restore(struct b43_wldev *dev,
b43_radio_write16(dev, 0x7A, sav->radio_7A);
if (!has_tx_magnification(phy)) {
tmp = sav->radio_52;
b43_radio_write16(dev, 0x52, (b43_radio_read16(dev, 0x52)
& 0xFF0F) | tmp);
b43_radio_maskset(dev, 0x52, 0xFF0F, tmp);
}
b43_write16(dev, 0x3E2, sav->reg_3E2);
if (phy->type == B43_PHYTYPE_B &&
@ -754,9 +731,9 @@ static void lo_probe_loctls_statemachine(struct b43_wldev *dev,
}
static
struct b43_lo_calib * b43_calibrate_lo_setting(struct b43_wldev *dev,
const struct b43_bbatt *bbatt,
const struct b43_rfatt *rfatt)
struct b43_lo_calib *b43_calibrate_lo_setting(struct b43_wldev *dev,
const struct b43_bbatt *bbatt,
const struct b43_rfatt *rfatt)
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
@ -778,12 +755,8 @@ struct b43_lo_calib * b43_calibrate_lo_setting(struct b43_wldev *dev,
txctl_reg = lo_txctl_register_table(dev, &txctl_value, &pad_mix_gain);
b43_radio_write16(dev, 0x43,
(b43_radio_read16(dev, 0x43) & 0xFFF0)
| rfatt->att);
b43_radio_write16(dev, txctl_reg,
(b43_radio_read16(dev, txctl_reg) & ~txctl_value)
| (rfatt->with_padmix) ? txctl_value : 0);
b43_radio_maskset(dev, 0x43, 0xFFF0, rfatt->att);
b43_radio_maskset(dev, txctl_reg, ~txctl_value, (rfatt->with_padmix ? txctl_value :0));
max_rx_gain = rfatt->att * 2;
max_rx_gain += bbatt->att / 2;
@ -824,9 +797,9 @@ struct b43_lo_calib * b43_calibrate_lo_setting(struct b43_wldev *dev,
/* Get a calibrated LO setting for the given attenuation values.
* Might return a NULL pointer under OOM! */
static
struct b43_lo_calib * b43_get_calib_lo_settings(struct b43_wldev *dev,
const struct b43_bbatt *bbatt,
const struct b43_rfatt *rfatt)
struct b43_lo_calib *b43_get_calib_lo_settings(struct b43_wldev *dev,
const struct b43_bbatt *bbatt,
const struct b43_rfatt *rfatt)
{
struct b43_txpower_lo_control *lo = dev->phy.g->lo_control;
struct b43_lo_calib *c;

View file

@ -512,7 +512,7 @@ void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value)
}
/* Read HostFlags */
u64 b43_hf_read(struct b43_wldev * dev)
u64 b43_hf_read(struct b43_wldev *dev)
{
u64 ret;
@ -600,7 +600,7 @@ void b43_tsf_write(struct b43_wldev *dev, u64 tsf)
}
static
void b43_macfilter_set(struct b43_wldev *dev, u16 offset, const u8 * mac)
void b43_macfilter_set(struct b43_wldev *dev, u16 offset, const u8 *mac)
{
static const u8 zero_addr[ETH_ALEN] = { 0 };
u16 data;
@ -790,7 +790,7 @@ void b43_dummy_transmission(struct b43_wldev *dev)
}
static void key_write(struct b43_wldev *dev,
u8 index, u8 algorithm, const u8 * key)
u8 index, u8 algorithm, const u8 *key)
{
unsigned int i;
u32 offset;
@ -812,7 +812,7 @@ static void key_write(struct b43_wldev *dev,
}
}
static void keymac_write(struct b43_wldev *dev, u8 index, const u8 * addr)
static void keymac_write(struct b43_wldev *dev, u8 index, const u8 *addr)
{
u32 addrtmp[2] = { 0, 0, };
u8 per_sta_keys_start = 8;
@ -862,7 +862,7 @@ static void keymac_write(struct b43_wldev *dev, u8 index, const u8 * addr)
static void do_key_write(struct b43_wldev *dev,
u8 index, u8 algorithm,
const u8 * key, size_t key_len, const u8 * mac_addr)
const u8 *key, size_t key_len, const u8 *mac_addr)
{
u8 buf[B43_SEC_KEYSIZE] = { 0, };
u8 per_sta_keys_start = 8;
@ -886,8 +886,8 @@ static void do_key_write(struct b43_wldev *dev,
static int b43_key_write(struct b43_wldev *dev,
int index, u8 algorithm,
const u8 * key, size_t key_len,
const u8 * mac_addr,
const u8 *key, size_t key_len,
const u8 *mac_addr,
struct ieee80211_key_conf *keyconf)
{
int i;
@ -1286,7 +1286,7 @@ static void handle_irq_pmq(struct b43_wldev *dev)
}
static void b43_write_template_common(struct b43_wldev *dev,
const u8 * data, u16 size,
const u8 *data, u16 size,
u16 ram_offset,
u16 shm_size_offset, u8 rate)
{
@ -1476,9 +1476,9 @@ static void b43_write_probe_resp_plcp(struct b43_wldev *dev,
* 2) Patching duration field
* 3) Stripping TIM
*/
static const u8 * b43_generate_probe_resp(struct b43_wldev *dev,
u16 *dest_size,
struct ieee80211_rate *rate)
static const u8 *b43_generate_probe_resp(struct b43_wldev *dev,
u16 *dest_size,
struct ieee80211_rate *rate)
{
const u8 *src_data;
u8 *dest_data;
@ -2980,7 +2980,7 @@ static void b43_security_init(struct b43_wldev *dev)
b43_clear_keys(dev);
}
static int b43_rng_read(struct hwrng *rng, u32 * data)
static int b43_rng_read(struct hwrng *rng, u32 *data)
{
struct b43_wl *wl = (struct b43_wl *)rng->priv;
unsigned long flags;
@ -3311,7 +3311,7 @@ static void b43_put_phy_into_reset(struct b43_wldev *dev)
msleep(1);
}
static const char * band_to_string(enum ieee80211_band band)
static const char *band_to_string(enum ieee80211_band band)
{
switch (band) {
case IEEE80211_BAND_5GHZ:
@ -4170,11 +4170,19 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
hf |= B43_HF_GDCW;
if (sprom->boardflags_lo & B43_BFL_PACTRL)
hf |= B43_HF_OFDMPABOOST;
} else if (phy->type == B43_PHYTYPE_B) {
hf |= B43_HF_SYMW;
if (phy->rev >= 2 && phy->radio_ver == 0x2050)
hf &= ~B43_HF_GDCW;
}
if (phy->radio_ver == 0x2050) {
if (phy->radio_rev == 6)
hf |= B43_HF_4318TSSI;
if (phy->radio_rev < 6)
hf |= B43_HF_VCORECALC;
}
if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)
hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */
if ((bus->bustype == SSB_BUSTYPE_PCI) &&
(bus->pcicore.dev->id.revision <= 10))
hf |= B43_HF_PCISCW; /* PCI slow clock workaround. */
hf &= ~B43_HF_SKCFPUP;
b43_hf_write(dev, hf);
b43_set_retry_limits(dev, B43_DEFAULT_SHORT_RETRY_LIMIT,
@ -4213,7 +4221,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
b43_set_synth_pu_delay(dev, 1);
b43_bluetooth_coext_enable(dev);
ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */
ssb_bus_powerup(bus, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW));
b43_upload_card_macaddress(dev);
b43_security_init(dev);
if (!dev->suspend_in_progress)
@ -4397,6 +4405,34 @@ static void b43_op_sta_notify(struct ieee80211_hw *hw,
B43_WARN_ON(!vif || wl->vif != vif);
}
static void b43_op_sw_scan_start_notifier(struct ieee80211_hw *hw)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev;
mutex_lock(&wl->mutex);
dev = wl->current_dev;
if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED)) {
/* Disable CFP update during scan on other channels. */
b43_hf_write(dev, b43_hf_read(dev) | B43_HF_SKCFPUP);
}
mutex_unlock(&wl->mutex);
}
static void b43_op_sw_scan_complete_notifier(struct ieee80211_hw *hw)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev;
mutex_lock(&wl->mutex);
dev = wl->current_dev;
if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED)) {
/* Re-enable CFP update. */
b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_SKCFPUP);
}
mutex_unlock(&wl->mutex);
}
static const struct ieee80211_ops b43_hw_ops = {
.tx = b43_op_tx,
.conf_tx = b43_op_conf_tx,
@ -4415,6 +4451,8 @@ static const struct ieee80211_ops b43_hw_ops = {
.stop = b43_op_stop,
.set_tim = b43_op_beacon_set_tim,
.sta_notify = b43_op_sta_notify,
.sw_scan_start = b43_op_sw_scan_start_notifier,
.sw_scan_complete = b43_op_sw_scan_complete_notifier,
};
/* Hard-reset the chip. Do not call this directly.

View file

@ -121,27 +121,18 @@ static void aphy_channel_switch(struct b43_wldev *dev, unsigned int channel)
b43_radio_write16(dev, 0x0007, (r8 << 4) | r8);
b43_radio_write16(dev, 0x0020, (r8 << 4) | r8);
b43_radio_write16(dev, 0x0021, (r8 << 4) | r8);
b43_radio_write16(dev, 0x0022, (b43_radio_read16(dev, 0x0022)
& 0x000F) | (r8 << 4));
b43_radio_maskset(dev, 0x0022, 0x000F, (r8 << 4));
b43_radio_write16(dev, 0x002A, (r8 << 4));
b43_radio_write16(dev, 0x002B, (r8 << 4));
b43_radio_write16(dev, 0x0008, (b43_radio_read16(dev, 0x0008)
& 0x00F0) | (r8 << 4));
b43_radio_write16(dev, 0x0029, (b43_radio_read16(dev, 0x0029)
& 0xFF0F) | 0x00B0);
b43_radio_maskset(dev, 0x0008, 0x00F0, (r8 << 4));
b43_radio_maskset(dev, 0x0029, 0xFF0F, 0x00B0);
b43_radio_write16(dev, 0x0035, 0x00AA);
b43_radio_write16(dev, 0x0036, 0x0085);
b43_radio_write16(dev, 0x003A, (b43_radio_read16(dev, 0x003A)
& 0xFF20) |
freq_r3A_value(freq));
b43_radio_write16(dev, 0x003D,
b43_radio_read16(dev, 0x003D) & 0x00FF);
b43_radio_write16(dev, 0x0081, (b43_radio_read16(dev, 0x0081)
& 0xFF7F) | 0x0080);
b43_radio_write16(dev, 0x0035,
b43_radio_read16(dev, 0x0035) & 0xFFEF);
b43_radio_write16(dev, 0x0035, (b43_radio_read16(dev, 0x0035)
& 0xFFEF) | 0x0010);
b43_radio_maskset(dev, 0x003A, 0xFF20, freq_r3A_value(freq));
b43_radio_mask(dev, 0x003D, 0x00FF);
b43_radio_maskset(dev, 0x0081, 0xFF7F, 0x0080);
b43_radio_mask(dev, 0x0035, 0xFFEF);
b43_radio_maskset(dev, 0x0035, 0xFFEF, 0x0010);
b43_radio_set_tx_iq(dev);
//TODO: TSSI2dbm workaround
//FIXME b43_phy_xmitpower(dev);
@ -160,23 +151,20 @@ static void b43_radio_init2060(struct b43_wldev *dev)
b43_radio_write16(dev, 0x0082, 0x0080);
b43_radio_write16(dev, 0x0080, 0x0000);
b43_radio_write16(dev, 0x003F, 0x00DA);
b43_radio_write16(dev, 0x0005, b43_radio_read16(dev, 0x0005) & ~0x0008);
b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0010);
b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0020);
b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0020);
b43_radio_mask(dev, 0x0005, ~0x0008);
b43_radio_mask(dev, 0x0081, ~0x0010);
b43_radio_mask(dev, 0x0081, ~0x0020);
b43_radio_mask(dev, 0x0081, ~0x0020);
msleep(1); /* delay 400usec */
b43_radio_write16(dev, 0x0081,
(b43_radio_read16(dev, 0x0081) & ~0x0020) | 0x0010);
b43_radio_maskset(dev, 0x0081, ~0x0020, 0x0010);
msleep(1); /* delay 400usec */
b43_radio_write16(dev, 0x0005,
(b43_radio_read16(dev, 0x0005) & ~0x0008) | 0x0008);
b43_radio_write16(dev, 0x0085, b43_radio_read16(dev, 0x0085) & ~0x0010);
b43_radio_write16(dev, 0x0005, b43_radio_read16(dev, 0x0005) & ~0x0008);
b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0040);
b43_radio_write16(dev, 0x0081,
(b43_radio_read16(dev, 0x0081) & ~0x0040) | 0x0040);
b43_radio_maskset(dev, 0x0005, ~0x0008, 0x0008);
b43_radio_mask(dev, 0x0085, ~0x0010);
b43_radio_mask(dev, 0x0005, ~0x0008);
b43_radio_mask(dev, 0x0081, ~0x0040);
b43_radio_maskset(dev, 0x0081, ~0x0040, 0x0040);
b43_radio_write16(dev, 0x0005,
(b43_radio_read16(dev, 0x0081) & ~0x0008) | 0x0008);
b43_phy_write(dev, 0x0063, 0xDDC6);
@ -224,22 +212,16 @@ static void b43_phy_ww(struct b43_wldev *dev)
u16 b, curr_s, best_s = 0xFFFF;
int i;
b43_phy_write(dev, B43_PHY_CRS0,
b43_phy_read(dev, B43_PHY_CRS0) & ~B43_PHY_CRS0_EN);
b43_phy_write(dev, B43_PHY_OFDM(0x1B),
b43_phy_read(dev, B43_PHY_OFDM(0x1B)) | 0x1000);
b43_phy_write(dev, B43_PHY_OFDM(0x82),
(b43_phy_read(dev, B43_PHY_OFDM(0x82)) & 0xF0FF) | 0x0300);
b43_radio_write16(dev, 0x0009,
b43_radio_read16(dev, 0x0009) | 0x0080);
b43_radio_write16(dev, 0x0012,
(b43_radio_read16(dev, 0x0012) & 0xFFFC) | 0x0002);
b43_phy_mask(dev, B43_PHY_CRS0, ~B43_PHY_CRS0_EN);
b43_phy_set(dev, B43_PHY_OFDM(0x1B), 0x1000);
b43_phy_maskset(dev, B43_PHY_OFDM(0x82), 0xF0FF, 0x0300);
b43_radio_set(dev, 0x0009, 0x0080);
b43_radio_maskset(dev, 0x0012, 0xFFFC, 0x0002);
b43_wa_initgains(dev);
b43_phy_write(dev, B43_PHY_OFDM(0xBA), 0x3ED5);
b = b43_phy_read(dev, B43_PHY_PWRDOWN);
b43_phy_write(dev, B43_PHY_PWRDOWN, (b & 0xFFF8) | 0x0005);
b43_radio_write16(dev, 0x0004,
b43_radio_read16(dev, 0x0004) | 0x0004);
b43_radio_set(dev, 0x0004, 0x0004);
for (i = 0x10; i <= 0x20; i++) {
b43_radio_write16(dev, 0x0013, i);
curr_s = b43_phy_read(dev, B43_PHY_OTABLEQ) & 0x00FF;
@ -252,8 +234,7 @@ static void b43_phy_ww(struct b43_wldev *dev)
best_s = curr_s;
}
b43_phy_write(dev, B43_PHY_PWRDOWN, b);
b43_radio_write16(dev, 0x0004,
b43_radio_read16(dev, 0x0004) & 0xFFFB);
b43_radio_mask(dev, 0x0004, 0xFFFB);
b43_radio_write16(dev, 0x0013, best_s);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 0, 0xFFEC);
b43_phy_write(dev, B43_PHY_OFDM(0xB7), 0x1E80);
@ -261,14 +242,10 @@ static void b43_phy_ww(struct b43_wldev *dev)
b43_phy_write(dev, B43_PHY_OFDM(0xB5), 0x0EC0);
b43_phy_write(dev, B43_PHY_OFDM(0xB2), 0x00C0);
b43_phy_write(dev, B43_PHY_OFDM(0xB9), 0x1FFF);
b43_phy_write(dev, B43_PHY_OFDM(0xBB),
(b43_phy_read(dev, B43_PHY_OFDM(0xBB)) & 0xF000) | 0x0053);
b43_phy_write(dev, B43_PHY_OFDM61,
(b43_phy_read(dev, B43_PHY_OFDM61) & 0xFE1F) | 0x0120);
b43_phy_write(dev, B43_PHY_OFDM(0x13),
(b43_phy_read(dev, B43_PHY_OFDM(0x13)) & 0x0FFF) | 0x3000);
b43_phy_write(dev, B43_PHY_OFDM(0x14),
(b43_phy_read(dev, B43_PHY_OFDM(0x14)) & 0x0FFF) | 0x3000);
b43_phy_maskset(dev, B43_PHY_OFDM(0xBB), 0xF000, 0x0053);
b43_phy_maskset(dev, B43_PHY_OFDM61, 0xFE1F, 0x0120);
b43_phy_maskset(dev, B43_PHY_OFDM(0x13), 0x0FFF, 0x3000);
b43_phy_maskset(dev, B43_PHY_OFDM(0x14), 0x0FFF, 0x3000);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 6, 0x0017);
for (i = 0; i < 6; i++)
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, i, 0x000F);
@ -276,8 +253,7 @@ static void b43_phy_ww(struct b43_wldev *dev)
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0E, 0x0011);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0F, 0x0013);
b43_phy_write(dev, B43_PHY_OFDM(0x33), 0x5030);
b43_phy_write(dev, B43_PHY_CRS0,
b43_phy_read(dev, B43_PHY_CRS0) | B43_PHY_CRS0_EN);
b43_phy_set(dev, B43_PHY_CRS0, B43_PHY_CRS0_EN);
}
static void hardware_pctl_init_aphy(struct b43_wldev *dev)
@ -300,26 +276,21 @@ void b43_phy_inita(struct b43_wldev *dev)
if (phy->rev >= 6) {
if (phy->type == B43_PHYTYPE_A)
b43_phy_write(dev, B43_PHY_OFDM(0x1B),
b43_phy_read(dev, B43_PHY_OFDM(0x1B)) & ~0x1000);
b43_phy_mask(dev, B43_PHY_OFDM(0x1B), ~0x1000);
if (b43_phy_read(dev, B43_PHY_ENCORE) & B43_PHY_ENCORE_EN)
b43_phy_write(dev, B43_PHY_ENCORE,
b43_phy_read(dev, B43_PHY_ENCORE) | 0x0010);
b43_phy_set(dev, B43_PHY_ENCORE, 0x0010);
else
b43_phy_write(dev, B43_PHY_ENCORE,
b43_phy_read(dev, B43_PHY_ENCORE) & ~0x1010);
b43_phy_mask(dev, B43_PHY_ENCORE, ~0x1010);
}
b43_wa_all(dev);
if (phy->type == B43_PHYTYPE_A) {
if (phy->gmode && (phy->rev < 3))
b43_phy_write(dev, 0x0034,
b43_phy_read(dev, 0x0034) | 0x0001);
b43_phy_set(dev, 0x0034, 0x0001);
b43_phy_rssiagc(dev, 0);
b43_phy_write(dev, B43_PHY_CRS0,
b43_phy_read(dev, B43_PHY_CRS0) | B43_PHY_CRS0_EN);
b43_phy_set(dev, B43_PHY_CRS0, B43_PHY_CRS0_EN);
b43_radio_init2060(dev);
@ -339,9 +310,7 @@ void b43_phy_inita(struct b43_wldev *dev)
if ((phy->type == B43_PHYTYPE_G) &&
(dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)) {
b43_phy_write(dev, B43_PHY_OFDM(0x6E),
(b43_phy_read(dev, B43_PHY_OFDM(0x6E))
& 0xE000) | 0x3CF);
b43_phy_maskset(dev, B43_PHY_OFDM(0x6E), 0xE000, 0x3CF);
}
}
@ -520,14 +489,14 @@ static void b43_aphy_op_software_rfkill(struct b43_wldev *dev,
return;
b43_radio_write16(dev, 0x0004, 0x00C0);
b43_radio_write16(dev, 0x0005, 0x0008);
b43_phy_write(dev, 0x0010, b43_phy_read(dev, 0x0010) & 0xFFF7);
b43_phy_write(dev, 0x0011, b43_phy_read(dev, 0x0011) & 0xFFF7);
b43_phy_mask(dev, 0x0010, 0xFFF7);
b43_phy_mask(dev, 0x0011, 0xFFF7);
b43_radio_init2060(dev);
} else {
b43_radio_write16(dev, 0x0004, 0x00FF);
b43_radio_write16(dev, 0x0005, 0x00FB);
b43_phy_write(dev, 0x0010, b43_phy_read(dev, 0x0010) | 0x0008);
b43_phy_write(dev, 0x0011, b43_phy_read(dev, 0x0011) | 0x0008);
b43_phy_set(dev, 0x0010, 0x0008);
b43_phy_set(dev, 0x0011, 0x0008);
}
}

File diff suppressed because it is too large Load diff

View file

@ -55,8 +55,8 @@ static u16 generate_cookie(struct b43_pio_txqueue *q,
}
static
struct b43_pio_txqueue * parse_cookie(struct b43_wldev *dev,
u16 cookie,
struct b43_pio_txqueue *parse_cookie(struct b43_wldev *dev,
u16 cookie,
struct b43_pio_txpacket **pack)
{
struct b43_pio *pio = &dev->pio;
@ -134,8 +134,8 @@ static u16 pio_rxqueue_offset(struct b43_wldev *dev)
return 8;
}
static struct b43_pio_txqueue * b43_setup_pioqueue_tx(struct b43_wldev *dev,
unsigned int index)
static struct b43_pio_txqueue *b43_setup_pioqueue_tx(struct b43_wldev *dev,
unsigned int index)
{
struct b43_pio_txqueue *q;
struct b43_pio_txpacket *p;
@ -171,8 +171,8 @@ static struct b43_pio_txqueue * b43_setup_pioqueue_tx(struct b43_wldev *dev,
return q;
}
static struct b43_pio_rxqueue * b43_setup_pioqueue_rx(struct b43_wldev *dev,
unsigned int index)
static struct b43_pio_rxqueue *b43_setup_pioqueue_rx(struct b43_wldev *dev,
unsigned int index)
{
struct b43_pio_rxqueue *q;
@ -308,8 +308,8 @@ err_destroy_bk:
}
/* Static mapping of mac80211's queues (priorities) to b43 PIO queues. */
static struct b43_pio_txqueue * select_queue_by_priority(struct b43_wldev *dev,
u8 queue_prio)
static struct b43_pio_txqueue *select_queue_by_priority(struct b43_wldev *dev,
u8 queue_prio)
{
struct b43_pio_txqueue *q;

View file

@ -113,7 +113,7 @@ out_unlock:
return err;
}
char * b43_rfkill_led_name(struct b43_wldev *dev)
char *b43_rfkill_led_name(struct b43_wldev *dev)
{
struct b43_rfkill *rfk = &(dev->wl->rfkill);

View file

@ -62,8 +62,7 @@ void b43_wa_initgains(struct b43_wldev *dev)
struct b43_phy *phy = &dev->phy;
b43_phy_write(dev, B43_PHY_LNAHPFCTL, 0x1FF9);
b43_phy_write(dev, B43_PHY_LPFGAINCTL,
b43_phy_read(dev, B43_PHY_LPFGAINCTL) & 0xFF0F);
b43_phy_mask(dev, B43_PHY_LPFGAINCTL, 0xFF0F);
if (phy->rev <= 2)
b43_ofdmtab_write16(dev, B43_OFDMTAB_LPFGAIN, 0, 0x1FBF);
b43_radio_write16(dev, 0x0002, 0x1FBF);
@ -73,11 +72,9 @@ void b43_wa_initgains(struct b43_wldev *dev)
b43_phy_write(dev, 0x001D, 0x0F40);
b43_phy_write(dev, 0x001F, 0x1C00);
if (phy->rev <= 3)
b43_phy_write(dev, 0x002A,
(b43_phy_read(dev, 0x002A) & 0x00FF) | 0x0400);
b43_phy_maskset(dev, 0x002A, 0x00FF, 0x0400);
else if (phy->rev == 5) {
b43_phy_write(dev, 0x002A,
(b43_phy_read(dev, 0x002A) & 0x00FF) | 0x1A00);
b43_phy_maskset(dev, 0x002A, 0x00FF, 0x1A00);
b43_phy_write(dev, 0x00CC, 0x2121);
}
if (phy->rev >= 3)
@ -86,7 +83,7 @@ void b43_wa_initgains(struct b43_wldev *dev)
static void b43_wa_divider(struct b43_wldev *dev)
{
b43_phy_write(dev, 0x002B, b43_phy_read(dev, 0x002B) & ~0x0100);
b43_phy_mask(dev, 0x002B, ~0x0100);
b43_phy_write(dev, 0x008E, 0x58C1);
}
@ -272,8 +269,7 @@ static void b43_wa_2060txlna_gain(struct b43_wldev *dev)
static void b43_wa_lms(struct b43_wldev *dev)
{
b43_phy_write(dev, 0x0055,
(b43_phy_read(dev, 0x0055) & 0xFFC0) | 0x0004);
b43_phy_maskset(dev, 0x0055, 0xFFC0, 0x0004);
}
static void b43_wa_mixedsignal(struct b43_wldev *dev)
@ -318,23 +314,18 @@ static void b43_wa_crs_ed(struct b43_wldev *dev)
} else if (phy->rev == 2) {
b43_phy_write(dev, B43_PHY_CRSTHRES1, 0x1861);
b43_phy_write(dev, B43_PHY_CRSTHRES2, 0x0271);
b43_phy_write(dev, B43_PHY_ANTDWELL,
b43_phy_read(dev, B43_PHY_ANTDWELL)
| 0x0800);
b43_phy_set(dev, B43_PHY_ANTDWELL, 0x0800);
} else {
b43_phy_write(dev, B43_PHY_CRSTHRES1, 0x0098);
b43_phy_write(dev, B43_PHY_CRSTHRES2, 0x0070);
b43_phy_write(dev, B43_PHY_OFDM(0xC9), 0x0080);
b43_phy_write(dev, B43_PHY_ANTDWELL,
b43_phy_read(dev, B43_PHY_ANTDWELL)
| 0x0800);
b43_phy_set(dev, B43_PHY_ANTDWELL, 0x0800);
}
}
static void b43_wa_crs_thr(struct b43_wldev *dev)
{
b43_phy_write(dev, B43_PHY_CRS0,
(b43_phy_read(dev, B43_PHY_CRS0) & ~0x03C0) | 0xD000);
b43_phy_maskset(dev, B43_PHY_CRS0, ~0x03C0, 0xD000);
}
static void b43_wa_crs_blank(struct b43_wldev *dev)
@ -391,72 +382,45 @@ static void b43_wa_altagc(struct b43_wldev *dev)
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 3, 25);
}
b43_phy_write(dev, B43_PHY_CCKSHIFTBITS_WA,
(b43_phy_read(dev, B43_PHY_CCKSHIFTBITS_WA) & ~0xFF00) | 0x5700);
b43_phy_write(dev, B43_PHY_OFDM(0x1A),
(b43_phy_read(dev, B43_PHY_OFDM(0x1A)) & ~0x007F) | 0x000F);
b43_phy_write(dev, B43_PHY_OFDM(0x1A),
(b43_phy_read(dev, B43_PHY_OFDM(0x1A)) & ~0x3F80) | 0x2B80);
b43_phy_write(dev, B43_PHY_ANTWRSETT,
(b43_phy_read(dev, B43_PHY_ANTWRSETT) & 0xF0FF) | 0x0300);
b43_radio_write16(dev, 0x7A,
b43_radio_read16(dev, 0x7A) | 0x0008);
b43_phy_write(dev, B43_PHY_N1P1GAIN,
(b43_phy_read(dev, B43_PHY_N1P1GAIN) & ~0x000F) | 0x0008);
b43_phy_write(dev, B43_PHY_P1P2GAIN,
(b43_phy_read(dev, B43_PHY_P1P2GAIN) & ~0x0F00) | 0x0600);
b43_phy_write(dev, B43_PHY_N1N2GAIN,
(b43_phy_read(dev, B43_PHY_N1N2GAIN) & ~0x0F00) | 0x0700);
b43_phy_write(dev, B43_PHY_N1P1GAIN,
(b43_phy_read(dev, B43_PHY_N1P1GAIN) & ~0x0F00) | 0x0100);
b43_phy_maskset(dev, B43_PHY_CCKSHIFTBITS_WA, (u16)~0xFF00, 0x5700);
b43_phy_maskset(dev, B43_PHY_OFDM(0x1A), ~0x007F, 0x000F);
b43_phy_maskset(dev, B43_PHY_OFDM(0x1A), ~0x3F80, 0x2B80);
b43_phy_maskset(dev, B43_PHY_ANTWRSETT, 0xF0FF, 0x0300);
b43_radio_set(dev, 0x7A, 0x0008);
b43_phy_maskset(dev, B43_PHY_N1P1GAIN, ~0x000F, 0x0008);
b43_phy_maskset(dev, B43_PHY_P1P2GAIN, ~0x0F00, 0x0600);
b43_phy_maskset(dev, B43_PHY_N1N2GAIN, ~0x0F00, 0x0700);
b43_phy_maskset(dev, B43_PHY_N1P1GAIN, ~0x0F00, 0x0100);
if (phy->rev == 1) {
b43_phy_write(dev, B43_PHY_N1N2GAIN,
(b43_phy_read(dev, B43_PHY_N1N2GAIN)
& ~0x000F) | 0x0007);
b43_phy_maskset(dev, B43_PHY_N1N2GAIN, ~0x000F, 0x0007);
}
b43_phy_write(dev, B43_PHY_OFDM(0x88),
(b43_phy_read(dev, B43_PHY_OFDM(0x88)) & ~0x00FF) | 0x001C);
b43_phy_write(dev, B43_PHY_OFDM(0x88),
(b43_phy_read(dev, B43_PHY_OFDM(0x88)) & ~0x3F00) | 0x0200);
b43_phy_write(dev, B43_PHY_OFDM(0x96),
(b43_phy_read(dev, B43_PHY_OFDM(0x96)) & ~0x00FF) | 0x001C);
b43_phy_write(dev, B43_PHY_OFDM(0x89),
(b43_phy_read(dev, B43_PHY_OFDM(0x89)) & ~0x00FF) | 0x0020);
b43_phy_write(dev, B43_PHY_OFDM(0x89),
(b43_phy_read(dev, B43_PHY_OFDM(0x89)) & ~0x3F00) | 0x0200);
b43_phy_write(dev, B43_PHY_OFDM(0x82),
(b43_phy_read(dev, B43_PHY_OFDM(0x82)) & ~0x00FF) | 0x002E);
b43_phy_write(dev, B43_PHY_OFDM(0x96),
(b43_phy_read(dev, B43_PHY_OFDM(0x96)) & ~0xFF00) | 0x1A00);
b43_phy_write(dev, B43_PHY_OFDM(0x81),
(b43_phy_read(dev, B43_PHY_OFDM(0x81)) & ~0x00FF) | 0x0028);
b43_phy_write(dev, B43_PHY_OFDM(0x81),
(b43_phy_read(dev, B43_PHY_OFDM(0x81)) & ~0xFF00) | 0x2C00);
b43_phy_maskset(dev, B43_PHY_OFDM(0x88), ~0x00FF, 0x001C);
b43_phy_maskset(dev, B43_PHY_OFDM(0x88), ~0x3F00, 0x0200);
b43_phy_maskset(dev, B43_PHY_OFDM(0x96), ~0x00FF, 0x001C);
b43_phy_maskset(dev, B43_PHY_OFDM(0x89), ~0x00FF, 0x0020);
b43_phy_maskset(dev, B43_PHY_OFDM(0x89), ~0x3F00, 0x0200);
b43_phy_maskset(dev, B43_PHY_OFDM(0x82), ~0x00FF, 0x002E);
b43_phy_maskset(dev, B43_PHY_OFDM(0x96), (u16)~0xFF00, 0x1A00);
b43_phy_maskset(dev, B43_PHY_OFDM(0x81), ~0x00FF, 0x0028);
b43_phy_maskset(dev, B43_PHY_OFDM(0x81), (u16)~0xFF00, 0x2C00);
if (phy->rev == 1) {
b43_phy_write(dev, B43_PHY_PEAK_COUNT, 0x092B);
b43_phy_write(dev, B43_PHY_OFDM(0x1B),
(b43_phy_read(dev, B43_PHY_OFDM(0x1B)) & ~0x001E) | 0x0002);
b43_phy_maskset(dev, B43_PHY_OFDM(0x1B), ~0x001E, 0x0002);
} else {
b43_phy_write(dev, B43_PHY_OFDM(0x1B),
b43_phy_read(dev, B43_PHY_OFDM(0x1B)) & ~0x001E);
b43_phy_mask(dev, B43_PHY_OFDM(0x1B), ~0x001E);
b43_phy_write(dev, B43_PHY_OFDM(0x1F), 0x287A);
b43_phy_write(dev, B43_PHY_LPFGAINCTL,
(b43_phy_read(dev, B43_PHY_LPFGAINCTL) & ~0x000F) | 0x0004);
b43_phy_maskset(dev, B43_PHY_LPFGAINCTL, ~0x000F, 0x0004);
if (phy->rev >= 6) {
b43_phy_write(dev, B43_PHY_OFDM(0x22), 0x287A);
b43_phy_write(dev, B43_PHY_LPFGAINCTL,
(b43_phy_read(dev, B43_PHY_LPFGAINCTL) & ~0xF000) | 0x3000);
b43_phy_maskset(dev, B43_PHY_LPFGAINCTL, (u16)~0xF000, 0x3000);
}
}
b43_phy_write(dev, B43_PHY_DIVSRCHIDX,
(b43_phy_read(dev, B43_PHY_DIVSRCHIDX) & 0x8080) | 0x7874);
b43_phy_maskset(dev, B43_PHY_DIVSRCHIDX, 0x8080, 0x7874);
b43_phy_write(dev, B43_PHY_OFDM(0x8E), 0x1C00);
if (phy->rev == 1) {
b43_phy_write(dev, B43_PHY_DIVP1P2GAIN,
(b43_phy_read(dev, B43_PHY_DIVP1P2GAIN) & ~0x0F00) | 0x0600);
b43_phy_maskset(dev, B43_PHY_DIVP1P2GAIN, ~0x0F00, 0x0600);
b43_phy_write(dev, B43_PHY_OFDM(0x8B), 0x005E);
b43_phy_write(dev, B43_PHY_ANTWRSETT,
(b43_phy_read(dev, B43_PHY_ANTWRSETT) & ~0x00FF) | 0x001E);
b43_phy_maskset(dev, B43_PHY_ANTWRSETT, ~0x00FF, 0x001E);
b43_phy_write(dev, B43_PHY_OFDM(0x8D), 0x0002);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3_R1, 0, 0);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3_R1, 1, 7);
@ -469,10 +433,8 @@ static void b43_wa_altagc(struct b43_wldev *dev)
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3, 3, 28);
}
if (phy->rev >= 6) {
b43_phy_write(dev, B43_PHY_OFDM(0x26),
b43_phy_read(dev, B43_PHY_OFDM(0x26)) & ~0x0003);
b43_phy_write(dev, B43_PHY_OFDM(0x26),
b43_phy_read(dev, B43_PHY_OFDM(0x26)) & ~0x1000);
b43_phy_mask(dev, B43_PHY_OFDM(0x26), ~0x0003);
b43_phy_mask(dev, B43_PHY_OFDM(0x26), ~0x1000);
}
b43_phy_read(dev, B43_PHY_VERSION_OFDM); /* Dummy read */
}
@ -538,8 +500,7 @@ static void b43_wa_boards_g(struct b43_wldev *dev)
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 2, 0x0001);
if ((bus->sprom.boardflags_lo & B43_BFL_EXTLNA) &&
(phy->rev >= 7)) {
b43_phy_write(dev, B43_PHY_EXTG(0x11),
b43_phy_read(dev, B43_PHY_EXTG(0x11)) & 0xF7FF);
b43_phy_mask(dev, B43_PHY_EXTG(0x11), 0xF7FF);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0020, 0x0001);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0021, 0x0001);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0022, 0x0001);

View file

@ -31,7 +31,7 @@ void hostap_dump_rx_header(const char *name,
void hostap_dump_tx_header(const char *name,
const struct hfa384x_tx_frame *tx);
extern const struct header_ops hostap_80211_ops;
int hostap_80211_get_hdrlen(u16 fc);
int hostap_80211_get_hdrlen(__le16 fc);
struct net_device_stats *hostap_get_stats(struct net_device *dev);
void hostap_setup_dev(struct net_device *dev, local_info_t *local,
int type);

View file

@ -2,7 +2,7 @@
#define HOSTAP_80211_H
#include <linux/types.h>
#include <net/ieee80211.h>
#include <linux/skbuff.h>
struct hostap_ieee80211_mgmt {
__le16 frame_control;

View file

@ -1,5 +1,6 @@
#include <linux/etherdevice.h>
#include <net/lib80211.h>
#include <linux/if_arp.h>
#include "hostap_80211.h"
#include "hostap.h"
@ -17,10 +18,10 @@ static unsigned char bridge_tunnel_header[] =
void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats)
{
struct ieee80211_hdr_4addr *hdr;
struct ieee80211_hdr *hdr;
u16 fc;
hdr = (struct ieee80211_hdr_4addr *) skb->data;
hdr = (struct ieee80211_hdr *) skb->data;
printk(KERN_DEBUG "%s: RX signal=%d noise=%d rate=%d len=%d "
"jiffies=%ld\n",
@ -30,9 +31,10 @@ void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
if (skb->len < 2)
return;
fc = le16_to_cpu(hdr->frame_ctl);
fc = le16_to_cpu(hdr->frame_control);
printk(KERN_DEBUG " FC=0x%04x (type=%d:%d)%s%s",
fc, WLAN_FC_GET_TYPE(fc) >> 2, WLAN_FC_GET_STYPE(fc) >> 4,
fc, (fc & IEEE80211_FCTL_FTYPE) >> 2,
(fc & IEEE80211_FCTL_STYPE) >> 4,
fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "",
fc & IEEE80211_FCTL_FROMDS ? " [FromDS]" : "");
@ -42,7 +44,7 @@ void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
}
printk(" dur=0x%04x seq=0x%04x\n", le16_to_cpu(hdr->duration_id),
le16_to_cpu(hdr->seq_ctl));
le16_to_cpu(hdr->seq_ctrl));
printk(KERN_DEBUG " A1=%pM", hdr->addr1);
printk(" A2=%pM", hdr->addr2);
@ -63,7 +65,7 @@ int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
int hdrlen, phdrlen, head_need, tail_need;
u16 fc;
int prism_header, ret;
struct ieee80211_hdr_4addr *fhdr;
struct ieee80211_hdr *fhdr;
iface = netdev_priv(dev);
local = iface->local;
@ -84,8 +86,8 @@ int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
phdrlen = 0;
}
fhdr = (struct ieee80211_hdr_4addr *) skb->data;
fc = le16_to_cpu(fhdr->frame_ctl);
fhdr = (struct ieee80211_hdr *) skb->data;
fc = le16_to_cpu(fhdr->frame_control);
if (type == PRISM2_RX_MGMT && (fc & IEEE80211_FCTL_VERS)) {
printk(KERN_DEBUG "%s: dropped management frame with header "
@ -94,7 +96,7 @@ int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
return 0;
}
hdrlen = hostap_80211_get_hdrlen(fc);
hdrlen = hostap_80211_get_hdrlen(fhdr->frame_control);
/* check if there is enough room for extra data; if not, expand skb
* buffer to be large enough for the changes */
@ -247,21 +249,21 @@ prism2_frag_cache_find(local_info_t *local, unsigned int seq,
/* Called only as a tasklet (software IRQ) */
static struct sk_buff *
prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr_4addr *hdr)
prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr *hdr)
{
struct sk_buff *skb = NULL;
u16 sc;
unsigned int frag, seq;
struct prism2_frag_entry *entry;
sc = le16_to_cpu(hdr->seq_ctl);
frag = WLAN_GET_SEQ_FRAG(sc);
seq = WLAN_GET_SEQ_SEQ(sc) >> 4;
sc = le16_to_cpu(hdr->seq_ctrl);
frag = sc & IEEE80211_SCTL_FRAG;
seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
if (frag == 0) {
/* Reserve enough space to fit maximum frame length */
skb = dev_alloc_skb(local->dev->mtu +
sizeof(struct ieee80211_hdr_4addr) +
sizeof(struct ieee80211_hdr) +
8 /* LLC */ +
2 /* alignment */ +
8 /* WEP */ + ETH_ALEN /* WDS */);
@ -299,14 +301,14 @@ prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr_4addr *hdr)
/* Called only as a tasklet (software IRQ) */
static int prism2_frag_cache_invalidate(local_info_t *local,
struct ieee80211_hdr_4addr *hdr)
struct ieee80211_hdr *hdr)
{
u16 sc;
unsigned int seq;
struct prism2_frag_entry *entry;
sc = le16_to_cpu(hdr->seq_ctl);
seq = WLAN_GET_SEQ_SEQ(sc) >> 4;
sc = le16_to_cpu(hdr->seq_ctrl);
seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
entry = prism2_frag_cache_find(local, seq, -1, hdr->addr2, hdr->addr1);
@ -472,10 +474,8 @@ hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats, u16 type,
u16 stype)
{
if (local->iw_mode == IW_MODE_MASTER) {
hostap_update_sta_ps(local, (struct ieee80211_hdr_4addr *)
skb->data);
}
if (local->iw_mode == IW_MODE_MASTER)
hostap_update_sta_ps(local, (struct ieee80211_hdr *) skb->data);
if (local->hostapd && type == IEEE80211_FTYPE_MGMT) {
if (stype == IEEE80211_STYPE_BEACON &&
@ -552,8 +552,8 @@ static struct net_device *prism2_rx_get_wds(local_info_t *local,
static int
hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
u16 fc, struct net_device **wds)
hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr *hdr, u16 fc,
struct net_device **wds)
{
/* FIX: is this really supposed to accept WDS frames only in Master
* mode? What about Repeater or Managed with WDS frames? */
@ -611,14 +611,14 @@ static int hostap_is_eapol_frame(local_info_t *local, struct sk_buff *skb)
{
struct net_device *dev = local->dev;
u16 fc, ethertype;
struct ieee80211_hdr_4addr *hdr;
struct ieee80211_hdr *hdr;
u8 *pos;
if (skb->len < 24)
return 0;
hdr = (struct ieee80211_hdr_4addr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
hdr = (struct ieee80211_hdr *) skb->data;
fc = le16_to_cpu(hdr->frame_control);
/* check that the frame is unicast frame to us */
if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
@ -651,14 +651,14 @@ static int
hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
struct lib80211_crypt_data *crypt)
{
struct ieee80211_hdr_4addr *hdr;
struct ieee80211_hdr *hdr;
int res, hdrlen;
if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
return 0;
hdr = (struct ieee80211_hdr_4addr *) skb->data;
hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
hdr = (struct ieee80211_hdr *) skb->data;
hdrlen = hostap_80211_get_hdrlen(hdr->frame_control);
if (local->tkip_countermeasures &&
strcmp(crypt->ops->name, "TKIP") == 0) {
@ -689,14 +689,14 @@ static int
hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb,
int keyidx, struct lib80211_crypt_data *crypt)
{
struct ieee80211_hdr_4addr *hdr;
struct ieee80211_hdr *hdr;
int res, hdrlen;
if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
return 0;
hdr = (struct ieee80211_hdr_4addr *) skb->data;
hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
hdr = (struct ieee80211_hdr *) skb->data;
hdrlen = hostap_80211_get_hdrlen(hdr->frame_control);
atomic_inc(&crypt->refcnt);
res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
@ -720,7 +720,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
{
struct hostap_interface *iface;
local_info_t *local;
struct ieee80211_hdr_4addr *hdr;
struct ieee80211_hdr *hdr;
size_t hdrlen;
u16 fc, type, stype, sc;
struct net_device *wds = NULL;
@ -747,18 +747,18 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
dev = local->ddev;
iface = netdev_priv(dev);
hdr = (struct ieee80211_hdr_4addr *) skb->data;
hdr = (struct ieee80211_hdr *) skb->data;
stats = hostap_get_stats(dev);
if (skb->len < 10)
goto rx_dropped;
fc = le16_to_cpu(hdr->frame_ctl);
type = WLAN_FC_GET_TYPE(fc);
stype = WLAN_FC_GET_STYPE(fc);
sc = le16_to_cpu(hdr->seq_ctl);
frag = WLAN_GET_SEQ_FRAG(sc);
hdrlen = hostap_80211_get_hdrlen(fc);
fc = le16_to_cpu(hdr->frame_control);
type = fc & IEEE80211_FCTL_FTYPE;
stype = fc & IEEE80211_FCTL_STYPE;
sc = le16_to_cpu(hdr->seq_ctrl);
frag = sc & IEEE80211_SCTL_FRAG;
hdrlen = hostap_80211_get_hdrlen(hdr->frame_control);
/* Put this code here so that we avoid duplicating it in all
* Rx paths. - Jean II */
@ -918,7 +918,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
if (local->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
(keyidx = hostap_rx_frame_decrypt(local, skb, crypt)) < 0)
goto rx_dropped;
hdr = (struct ieee80211_hdr_4addr *) skb->data;
hdr = (struct ieee80211_hdr *) skb->data;
/* skb: hdr + (possibly fragmented) plaintext payload */
@ -931,7 +931,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
printk(KERN_DEBUG "%s: Rx cannot get skb from "
"fragment cache (morefrag=%d seq=%u frag=%u)\n",
dev->name, (fc & IEEE80211_FCTL_MOREFRAGS) != 0,
WLAN_GET_SEQ_SEQ(sc) >> 4, frag);
(sc & IEEE80211_SCTL_SEQ) >> 4, frag);
goto rx_dropped;
}
@ -972,7 +972,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
/* this was the last fragment and the frame will be
* delivered, so remove skb from fragment cache */
skb = frag_skb;
hdr = (struct ieee80211_hdr_4addr *) skb->data;
hdr = (struct ieee80211_hdr *) skb->data;
prism2_frag_cache_invalidate(local, hdr);
}
@ -983,7 +983,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
hostap_rx_frame_decrypt_msdu(local, skb, keyidx, crypt))
goto rx_dropped;
hdr = (struct ieee80211_hdr_4addr *) skb->data;
hdr = (struct ieee80211_hdr *) skb->data;
if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !local->open_wep) {
if (local->ieee_802_1x &&
hostap_is_eapol_frame(local, skb)) {

View file

@ -15,10 +15,10 @@ static unsigned char bridge_tunnel_header[] =
void hostap_dump_tx_80211(const char *name, struct sk_buff *skb)
{
struct ieee80211_hdr_4addr *hdr;
struct ieee80211_hdr *hdr;
u16 fc;
hdr = (struct ieee80211_hdr_4addr *) skb->data;
hdr = (struct ieee80211_hdr *) skb->data;
printk(KERN_DEBUG "%s: TX len=%d jiffies=%ld\n",
name, skb->len, jiffies);
@ -26,9 +26,10 @@ void hostap_dump_tx_80211(const char *name, struct sk_buff *skb)
if (skb->len < 2)
return;
fc = le16_to_cpu(hdr->frame_ctl);
fc = le16_to_cpu(hdr->frame_control);
printk(KERN_DEBUG " FC=0x%04x (type=%d:%d)%s%s",
fc, WLAN_FC_GET_TYPE(fc) >> 2, WLAN_FC_GET_STYPE(fc) >> 4,
fc, (fc & IEEE80211_FCTL_FTYPE) >> 2,
(fc & IEEE80211_FCTL_STYPE) >> 4,
fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "",
fc & IEEE80211_FCTL_FROMDS ? " [FromDS]" : "");
@ -38,7 +39,7 @@ void hostap_dump_tx_80211(const char *name, struct sk_buff *skb)
}
printk(" dur=0x%04x seq=0x%04x\n", le16_to_cpu(hdr->duration_id),
le16_to_cpu(hdr->seq_ctl));
le16_to_cpu(hdr->seq_ctrl));
printk(KERN_DEBUG " A1=%pM", hdr->addr1);
printk(" A2=%pM", hdr->addr2);
@ -57,7 +58,7 @@ int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct hostap_interface *iface;
local_info_t *local;
int need_headroom, need_tailroom = 0;
struct ieee80211_hdr_4addr hdr;
struct ieee80211_hdr hdr;
u16 fc, ethertype = 0;
enum {
WDS_NO = 0, WDS_OWN_FRAME, WDS_COMPLIANT_FRAME
@ -201,7 +202,7 @@ int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev)
memcpy(&hdr.addr3, local->bssid, ETH_ALEN);
}
hdr.frame_ctl = cpu_to_le16(fc);
hdr.frame_control = cpu_to_le16(fc);
skb_pull(skb, skip_header_bytes);
need_headroom = local->func->need_tx_headroom + hdr_len + encaps_len;
@ -265,7 +266,7 @@ int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct hostap_interface *iface;
local_info_t *local;
struct hostap_skb_tx_data *meta;
struct ieee80211_hdr_4addr *hdr;
struct ieee80211_hdr *hdr;
u16 fc;
iface = netdev_priv(dev);
@ -287,10 +288,10 @@ int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
meta->iface = iface;
if (skb->len >= IEEE80211_DATA_HDR3_LEN + sizeof(rfc1042_header) + 2) {
hdr = (struct ieee80211_hdr_4addr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&
WLAN_FC_GET_STYPE(fc) == IEEE80211_STYPE_DATA) {
hdr = (struct ieee80211_hdr *) skb->data;
fc = le16_to_cpu(hdr->frame_control);
if (ieee80211_is_data(hdr->frame_control) &&
(fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DATA) {
u8 *pos = &skb->data[IEEE80211_DATA_HDR3_LEN +
sizeof(rfc1042_header)];
meta->ethertype = (pos[0] << 8) | pos[1];
@ -310,8 +311,7 @@ static struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
{
struct hostap_interface *iface;
local_info_t *local;
struct ieee80211_hdr_4addr *hdr;
u16 fc;
struct ieee80211_hdr *hdr;
int prefix_len, postfix_len, hdr_len, res;
iface = netdev_priv(skb->dev);
@ -324,7 +324,7 @@ static struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
if (local->tkip_countermeasures &&
strcmp(crypt->ops->name, "TKIP") == 0) {
hdr = (struct ieee80211_hdr_4addr *) skb->data;
hdr = (struct ieee80211_hdr *) skb->data;
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
"TX packet to %pM\n",
@ -349,9 +349,8 @@ static struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
return NULL;
}
hdr = (struct ieee80211_hdr_4addr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
hdr_len = hostap_80211_get_hdrlen(fc);
hdr = (struct ieee80211_hdr *) skb->data;
hdr_len = hostap_80211_get_hdrlen(hdr->frame_control);
/* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
* call both MSDU and MPDU encryption functions from here. */
@ -384,7 +383,7 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
ap_tx_ret tx_ret;
struct hostap_skb_tx_data *meta;
int no_encrypt = 0;
struct ieee80211_hdr_4addr *hdr;
struct ieee80211_hdr *hdr;
iface = netdev_priv(dev);
local = iface->local;
@ -427,14 +426,14 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
tx_ret = hostap_handle_sta_tx(local, &tx);
skb = tx.skb;
meta = (struct hostap_skb_tx_data *) skb->cb;
hdr = (struct ieee80211_hdr_4addr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
hdr = (struct ieee80211_hdr *) skb->data;
fc = le16_to_cpu(hdr->frame_control);
switch (tx_ret) {
case AP_TX_CONTINUE:
break;
case AP_TX_CONTINUE_NOT_AUTHORIZED:
if (local->ieee_802_1x &&
WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&
ieee80211_is_data(hdr->frame_control) &&
meta->ethertype != ETH_P_PAE &&
!(meta->flags & HOSTAP_TX_FLAGS_WDS)) {
printk(KERN_DEBUG "%s: dropped frame to unauthorized "
@ -469,10 +468,10 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* remove special version from the frame header */
fc &= ~IEEE80211_FCTL_VERS;
hdr->frame_ctl = cpu_to_le16(fc);
hdr->frame_control = cpu_to_le16(fc);
}
if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_DATA) {
if (!ieee80211_is_data(hdr->frame_control)) {
no_encrypt = 1;
tx.crypt = NULL;
}
@ -493,9 +492,9 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Add ISWEP flag both for firmware and host based encryption
*/
fc |= IEEE80211_FCTL_PROTECTED;
hdr->frame_ctl = cpu_to_le16(fc);
hdr->frame_control = cpu_to_le16(fc);
} else if (local->drop_unencrypted &&
WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&
ieee80211_is_data(hdr->frame_control) &&
meta->ethertype != ETH_P_PAE) {
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: dropped unencrypted TX data "

View file

@ -19,6 +19,7 @@
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/random.h>
#include <linux/if_arp.h>
#include "hostap_wlan.h"
#include "hostap.h"
@ -588,26 +589,22 @@ void hostap_check_sta_fw_version(struct ap_data *ap, int sta_fw_ver)
static void hostap_ap_tx_cb(struct sk_buff *skb, int ok, void *data)
{
struct ap_data *ap = data;
u16 fc;
struct ieee80211_hdr_4addr *hdr;
struct ieee80211_hdr *hdr;
if (!ap->local->hostapd || !ap->local->apdev) {
dev_kfree_skb(skb);
return;
}
hdr = (struct ieee80211_hdr_4addr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
/* Pass the TX callback frame to the hostapd; use 802.11 header version
* 1 to indicate failure (no ACK) and 2 success (frame ACKed) */
fc &= ~IEEE80211_FCTL_VERS;
fc |= ok ? BIT(1) : BIT(0);
hdr->frame_ctl = cpu_to_le16(fc);
hdr = (struct ieee80211_hdr *) skb->data;
hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_VERS);
hdr->frame_control |= cpu_to_le16(ok ? BIT(1) : BIT(0));
skb->dev = ap->local->apdev;
skb_pull(skb, hostap_80211_get_hdrlen(fc));
skb_pull(skb, hostap_80211_get_hdrlen(hdr->frame_control));
skb->pkt_type = PACKET_OTHERHOST;
skb->protocol = cpu_to_be16(ETH_P_802_2);
memset(skb->cb, 0, sizeof(skb->cb));
@ -621,8 +618,8 @@ static void hostap_ap_tx_cb_auth(struct sk_buff *skb, int ok, void *data)
{
struct ap_data *ap = data;
struct net_device *dev = ap->local->dev;
struct ieee80211_hdr_4addr *hdr;
u16 fc, auth_alg, auth_transaction, status;
struct ieee80211_hdr *hdr;
u16 auth_alg, auth_transaction, status;
__le16 *pos;
struct sta_info *sta = NULL;
char *txt = NULL;
@ -632,10 +629,8 @@ static void hostap_ap_tx_cb_auth(struct sk_buff *skb, int ok, void *data)
return;
}
hdr = (struct ieee80211_hdr_4addr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_MGMT ||
WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_AUTH ||
hdr = (struct ieee80211_hdr *) skb->data;
if (!ieee80211_is_auth(hdr->frame_control) ||
skb->len < IEEE80211_MGMT_HDR_LEN + 6) {
printk(KERN_DEBUG "%s: hostap_ap_tx_cb_auth received invalid "
"frame\n", dev->name);
@ -691,7 +686,7 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
{
struct ap_data *ap = data;
struct net_device *dev = ap->local->dev;
struct ieee80211_hdr_4addr *hdr;
struct ieee80211_hdr *hdr;
u16 fc, status;
__le16 *pos;
struct sta_info *sta = NULL;
@ -702,11 +697,10 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
return;
}
hdr = (struct ieee80211_hdr_4addr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_MGMT ||
(WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_ASSOC_RESP &&
WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_REASSOC_RESP) ||
hdr = (struct ieee80211_hdr *) skb->data;
fc = le16_to_cpu(hdr->frame_control);
if ((!ieee80211_is_assoc_resp(hdr->frame_control) &&
!ieee80211_is_reassoc_resp(hdr->frame_control)) ||
skb->len < IEEE80211_MGMT_HDR_LEN + 4) {
printk(KERN_DEBUG "%s: hostap_ap_tx_cb_assoc received invalid "
"frame\n", dev->name);
@ -757,12 +751,12 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
static void hostap_ap_tx_cb_poll(struct sk_buff *skb, int ok, void *data)
{
struct ap_data *ap = data;
struct ieee80211_hdr_4addr *hdr;
struct ieee80211_hdr *hdr;
struct sta_info *sta;
if (skb->len < 24)
goto fail;
hdr = (struct ieee80211_hdr_4addr *) skb->data;
hdr = (struct ieee80211_hdr *) skb->data;
if (ok) {
spin_lock(&ap->sta_table_lock);
sta = ap_get_sta(ap, hdr->addr1);
@ -917,7 +911,7 @@ static void prism2_send_mgmt(struct net_device *dev,
{
struct hostap_interface *iface;
local_info_t *local;
struct ieee80211_hdr_4addr *hdr;
struct ieee80211_hdr *hdr;
u16 fc;
struct sk_buff *skb;
struct hostap_skb_tx_data *meta;
@ -942,8 +936,8 @@ static void prism2_send_mgmt(struct net_device *dev,
}
fc = type_subtype;
hdrlen = hostap_80211_get_hdrlen(fc);
hdr = (struct ieee80211_hdr_4addr *) skb_put(skb, hdrlen);
hdrlen = hostap_80211_get_hdrlen(cpu_to_le16(type_subtype));
hdr = (struct ieee80211_hdr *) skb_put(skb, hdrlen);
if (body)
memcpy(skb_put(skb, body_len), body, body_len);
@ -954,11 +948,11 @@ static void prism2_send_mgmt(struct net_device *dev,
memcpy(hdr->addr1, addr, ETH_ALEN); /* DA / RA */
if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) {
if (ieee80211_is_data(hdr->frame_control)) {
fc |= IEEE80211_FCTL_FROMDS;
memcpy(hdr->addr2, dev->dev_addr, ETH_ALEN); /* BSSID */
memcpy(hdr->addr3, dev->dev_addr, ETH_ALEN); /* SA */
} else if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_CTL) {
} else if (ieee80211_is_ctl(hdr->frame_control)) {
/* control:ACK does not have addr2 or addr3 */
memset(hdr->addr2, 0, ETH_ALEN);
memset(hdr->addr3, 0, ETH_ALEN);
@ -967,7 +961,7 @@ static void prism2_send_mgmt(struct net_device *dev,
memcpy(hdr->addr3, dev->dev_addr, ETH_ALEN); /* BSSID */
}
hdr->frame_ctl = cpu_to_le16(fc);
hdr->frame_control = cpu_to_le16(fc);
meta = (struct hostap_skb_tx_data *) skb->cb;
memset(meta, 0, sizeof(*meta));
@ -1284,22 +1278,21 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats)
{
struct net_device *dev = local->dev;
struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
size_t hdrlen;
struct ap_data *ap = local->ap;
char body[8 + WLAN_AUTH_CHALLENGE_LEN], *challenge = NULL;
int len, olen;
u16 auth_alg, auth_transaction, status_code;
__le16 *pos;
u16 resp = WLAN_STATUS_SUCCESS, fc;
u16 resp = WLAN_STATUS_SUCCESS;
struct sta_info *sta = NULL;
struct lib80211_crypt_data *crypt;
char *txt = "";
len = skb->len - IEEE80211_MGMT_HDR_LEN;
fc = le16_to_cpu(hdr->frame_ctl);
hdrlen = hostap_80211_get_hdrlen(fc);
hdrlen = hostap_80211_get_hdrlen(hdr->frame_control);
if (len < 6) {
PDEBUG(DEBUG_AP, "%s: handle_authen - too short payload "
@ -1435,7 +1428,7 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb,
challenge == NULL ||
memcmp(sta->u.sta.challenge, challenge,
WLAN_AUTH_CHALLENGE_LEN) != 0 ||
!(fc & IEEE80211_FCTL_PROTECTED)) {
!ieee80211_has_protected(hdr->frame_control)) {
txt = "challenge response incorrect";
resp = WLAN_STATUS_CHALLENGE_FAIL;
goto fail;
@ -1488,7 +1481,7 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb,
"trans#=%d stat=%d len=%d fc=%04x) ==> %d (%s)\n",
dev->name, hdr->addr2,
auth_alg, auth_transaction, status_code, len,
fc, resp, txt);
le16_to_cpu(hdr->frame_control), resp, txt);
}
}
@ -1498,7 +1491,7 @@ static void handle_assoc(local_info_t *local, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats, int reassoc)
{
struct net_device *dev = local->dev;
struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
char body[12], *p, *lpos;
int len, left;
__le16 *pos;
@ -1707,7 +1700,7 @@ static void handle_deauth(local_info_t *local, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats)
{
struct net_device *dev = local->dev;
struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
char *body = (char *) (skb->data + IEEE80211_MGMT_HDR_LEN);
int len;
u16 reason_code;
@ -1749,7 +1742,7 @@ static void handle_disassoc(local_info_t *local, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats)
{
struct net_device *dev = local->dev;
struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
char *body = skb->data + IEEE80211_MGMT_HDR_LEN;
int len;
u16 reason_code;
@ -1788,7 +1781,7 @@ static void handle_disassoc(local_info_t *local, struct sk_buff *skb,
/* Called only as a scheduled task for pending AP frames. */
static void ap_handle_data_nullfunc(local_info_t *local,
struct ieee80211_hdr_4addr *hdr)
struct ieee80211_hdr *hdr)
{
struct net_device *dev = local->dev;
@ -1805,7 +1798,7 @@ static void ap_handle_data_nullfunc(local_info_t *local,
/* Called only as a scheduled task for pending AP frames. */
static void ap_handle_dropped_data(local_info_t *local,
struct ieee80211_hdr_4addr *hdr)
struct ieee80211_hdr *hdr)
{
struct net_device *dev = local->dev;
struct sta_info *sta;
@ -1863,7 +1856,7 @@ static void pspoll_send_buffered(local_info_t *local, struct sta_info *sta,
/* Called only as a scheduled task for pending AP frames. */
static void handle_pspoll(local_info_t *local,
struct ieee80211_hdr_4addr *hdr,
struct ieee80211_hdr *hdr,
struct hostap_80211_rx_status *rx_stats)
{
struct net_device *dev = local->dev;
@ -1872,8 +1865,7 @@ static void handle_pspoll(local_info_t *local,
struct sk_buff *skb;
PDEBUG(DEBUG_PS2, "handle_pspoll: BSSID=%pM, TA=%pM PWRMGT=%d\n",
hdr->addr1, hdr->addr2,
!!(le16_to_cpu(hdr->frame_ctl) & IEEE80211_FCTL_PM));
hdr->addr1, hdr->addr2, !!ieee80211_has_pm(hdr->frame_control));
if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) {
PDEBUG(DEBUG_AP,
@ -1984,7 +1976,7 @@ static void handle_wds_oper_queue(struct work_struct *work)
static void handle_beacon(local_info_t *local, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats)
{
struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
char *body = skb->data + IEEE80211_MGMT_HDR_LEN;
int len, left;
u16 beacon_int, capability;
@ -2143,14 +2135,14 @@ static void handle_ap_item(local_info_t *local, struct sk_buff *skb,
struct net_device *dev = local->dev;
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
u16 fc, type, stype;
struct ieee80211_hdr_4addr *hdr;
struct ieee80211_hdr *hdr;
/* FIX: should give skb->len to handler functions and check that the
* buffer is long enough */
hdr = (struct ieee80211_hdr_4addr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
type = WLAN_FC_GET_TYPE(fc);
stype = WLAN_FC_GET_STYPE(fc);
hdr = (struct ieee80211_hdr *) skb->data;
fc = le16_to_cpu(hdr->frame_control);
type = fc & IEEE80211_FCTL_FTYPE;
stype = fc & IEEE80211_FCTL_STYPE;
#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
if (!local->hostapd && type == IEEE80211_FTYPE_DATA) {
@ -2262,8 +2254,7 @@ void hostap_rx(struct net_device *dev, struct sk_buff *skb,
{
struct hostap_interface *iface;
local_info_t *local;
u16 fc;
struct ieee80211_hdr_4addr *hdr;
struct ieee80211_hdr *hdr;
iface = netdev_priv(dev);
local = iface->local;
@ -2273,12 +2264,10 @@ void hostap_rx(struct net_device *dev, struct sk_buff *skb,
local->stats.rx_packets++;
hdr = (struct ieee80211_hdr_4addr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
hdr = (struct ieee80211_hdr *) skb->data;
if (local->ap->ap_policy == AP_OTHER_AP_SKIP_ALL &&
WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_MGMT &&
WLAN_FC_GET_STYPE(fc) == IEEE80211_STYPE_BEACON)
ieee80211_is_beacon(hdr->frame_control))
goto drop;
skb->protocol = cpu_to_be16(ETH_P_HOSTAP);
@ -2294,7 +2283,7 @@ void hostap_rx(struct net_device *dev, struct sk_buff *skb,
static void schedule_packet_send(local_info_t *local, struct sta_info *sta)
{
struct sk_buff *skb;
struct ieee80211_hdr_4addr *hdr;
struct ieee80211_hdr *hdr;
struct hostap_80211_rx_status rx_stats;
if (skb_queue_empty(&sta->tx_buf))
@ -2307,10 +2296,10 @@ static void schedule_packet_send(local_info_t *local, struct sta_info *sta)
return;
}
hdr = (struct ieee80211_hdr_4addr *) skb_put(skb, 16);
hdr = (struct ieee80211_hdr *) skb_put(skb, 16);
/* Generate a fake pspoll frame to start packet delivery */
hdr->frame_ctl = cpu_to_le16(
hdr->frame_control = cpu_to_le16(
IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL);
memcpy(hdr->addr1, local->dev->dev_addr, ETH_ALEN);
memcpy(hdr->addr2, sta->addr, ETH_ALEN);
@ -2689,7 +2678,7 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx)
struct sta_info *sta = NULL;
struct sk_buff *skb = tx->skb;
int set_tim, ret;
struct ieee80211_hdr_4addr *hdr;
struct ieee80211_hdr *hdr;
struct hostap_skb_tx_data *meta;
meta = (struct hostap_skb_tx_data *) skb->cb;
@ -2698,7 +2687,7 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx)
meta->iface->type == HOSTAP_INTERFACE_STA)
goto out;
hdr = (struct ieee80211_hdr_4addr *) skb->data;
hdr = (struct ieee80211_hdr *) skb->data;
if (hdr->addr1[0] & 0x01) {
/* broadcast/multicast frame - no AP related processing */
@ -2753,7 +2742,7 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx)
if (meta->flags & HOSTAP_TX_FLAGS_ADD_MOREDATA) {
/* indicate to STA that more frames follow */
hdr->frame_ctl |=
hdr->frame_control |=
cpu_to_le16(IEEE80211_FCTL_MOREDATA);
}
@ -2828,10 +2817,10 @@ void hostap_handle_sta_release(void *ptr)
void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb)
{
struct sta_info *sta;
struct ieee80211_hdr_4addr *hdr;
struct ieee80211_hdr *hdr;
struct hostap_skb_tx_data *meta;
hdr = (struct ieee80211_hdr_4addr *) skb->data;
hdr = (struct ieee80211_hdr *) skb->data;
meta = (struct hostap_skb_tx_data *) skb->cb;
spin_lock(&local->ap->sta_table_lock);
@ -2898,8 +2887,8 @@ static void hostap_update_sta_ps2(local_info_t *local, struct sta_info *sta,
/* Called only as a tasklet (software IRQ). Called for each RX frame to update
* STA power saving state. pwrmgt is a flag from 802.11 frame_ctl field. */
int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr_4addr *hdr)
* STA power saving state. pwrmgt is a flag from 802.11 frame_control field. */
int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr *hdr)
{
struct sta_info *sta;
u16 fc;
@ -2913,9 +2902,10 @@ int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr_4addr *hdr)
if (!sta)
return -1;
fc = le16_to_cpu(hdr->frame_ctl);
fc = le16_to_cpu(hdr->frame_control);
hostap_update_sta_ps2(local, sta, fc & IEEE80211_FCTL_PM,
WLAN_FC_GET_TYPE(fc), WLAN_FC_GET_STYPE(fc));
fc & IEEE80211_FCTL_FTYPE,
fc & IEEE80211_FCTL_STYPE);
atomic_dec(&sta->users);
return 0;
@ -2932,16 +2922,16 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
int ret;
struct sta_info *sta;
u16 fc, type, stype;
struct ieee80211_hdr_4addr *hdr;
struct ieee80211_hdr *hdr;
if (local->ap == NULL)
return AP_RX_CONTINUE;
hdr = (struct ieee80211_hdr_4addr *) skb->data;
hdr = (struct ieee80211_hdr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
type = WLAN_FC_GET_TYPE(fc);
stype = WLAN_FC_GET_STYPE(fc);
fc = le16_to_cpu(hdr->frame_control);
type = fc & IEEE80211_FCTL_FTYPE;
stype = fc & IEEE80211_FCTL_STYPE;
spin_lock(&local->ap->sta_table_lock);
sta = ap_get_sta(local->ap, hdr->addr2);
@ -3064,7 +3054,7 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
/* Called only as a tasklet (software IRQ) */
int hostap_handle_sta_crypto(local_info_t *local,
struct ieee80211_hdr_4addr *hdr,
struct ieee80211_hdr *hdr,
struct lib80211_crypt_data **crypt,
void **sta_ptr)
{
@ -3166,7 +3156,7 @@ int hostap_add_sta(struct ap_data *ap, u8 *sta_addr)
/* Called only as a tasklet (software IRQ) */
int hostap_update_rx_stats(struct ap_data *ap,
struct ieee80211_hdr_4addr *hdr,
struct ieee80211_hdr *hdr,
struct hostap_80211_rx_status *rx_stats)
{
struct sta_info *sta;

View file

@ -235,7 +235,7 @@ struct hostap_tx_data {
ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx);
void hostap_handle_sta_release(void *ptr);
void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb);
int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr_4addr *hdr);
int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr *hdr);
typedef enum {
AP_RX_CONTINUE, AP_RX_DROP, AP_RX_EXIT, AP_RX_CONTINUE_NOT_AUTHORIZED
} ap_rx_ret;
@ -243,13 +243,13 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats,
int wds);
int hostap_handle_sta_crypto(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
int hostap_handle_sta_crypto(local_info_t *local, struct ieee80211_hdr *hdr,
struct lib80211_crypt_data **crypt,
void **sta_ptr);
int hostap_is_sta_assoc(struct ap_data *ap, u8 *sta_addr);
int hostap_is_sta_authorized(struct ap_data *ap, u8 *sta_addr);
int hostap_add_sta(struct ap_data *ap, u8 *sta_addr);
int hostap_update_rx_stats(struct ap_data *ap, struct ieee80211_hdr_4addr *hdr,
int hostap_update_rx_stats(struct ap_data *ap, struct ieee80211_hdr *hdr,
struct hostap_80211_rx_status *rx_stats);
void hostap_update_rates(local_info_t *local);
void hostap_add_wds_links(local_info_t *local);

View file

@ -46,7 +46,6 @@
#include <linux/rtnetlink.h>
#include <linux/wireless.h>
#include <net/iw_handler.h>
#include <net/ieee80211.h>
#include <net/lib80211.h>
#include <asm/irq.h>
@ -1840,8 +1839,8 @@ static int prism2_tx_80211(struct sk_buff *skb, struct net_device *dev)
hdr_len = 24;
skb_copy_from_linear_data(skb, &txdesc.frame_control, hdr_len);
fc = le16_to_cpu(txdesc.frame_control);
if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&
(fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS) &&
if (ieee80211_is_data(txdesc.frame_control) &&
ieee80211_has_a4(txdesc.frame_control) &&
skb->len >= 30) {
/* Addr4 */
skb_copy_from_linear_data_offset(skb, hdr_len, txdesc.addr4,
@ -2082,7 +2081,7 @@ static void hostap_rx_skb(local_info_t *local, struct sk_buff *skb)
stats.rate = rxdesc->rate;
/* Convert Prism2 RX structure into IEEE 802.11 header */
hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(rxdesc->frame_control));
hdrlen = hostap_80211_get_hdrlen(rxdesc->frame_control);
if (hdrlen > rx_hdrlen)
hdrlen = rx_hdrlen;
@ -2204,7 +2203,7 @@ static void hostap_tx_callback(local_info_t *local,
return;
}
hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(txdesc->frame_control));
hdrlen = hostap_80211_get_hdrlen(txdesc->frame_control);
len = le16_to_cpu(txdesc->data_len);
skb = dev_alloc_skb(hdrlen + len);
if (skb == NULL) {
@ -2315,8 +2314,7 @@ static void hostap_sta_tx_exc_tasklet(unsigned long data)
if (skb->len >= sizeof(*txdesc)) {
/* Convert Prism2 RX structure into IEEE 802.11 header
*/
u16 fc = le16_to_cpu(txdesc->frame_control);
int hdrlen = hostap_80211_get_hdrlen(fc);
int hdrlen = hostap_80211_get_hdrlen(txdesc->frame_control);
memmove(skb_pull(skb, sizeof(*txdesc) - hdrlen),
&txdesc->frame_control, hdrlen);
@ -2394,12 +2392,12 @@ static void prism2_txexc(local_info_t *local)
PDEBUG(DEBUG_EXTRA, " retry_count=%d tx_rate=%d fc=0x%04x "
"(%s%s%s::%d%s%s)\n",
txdesc.retry_count, txdesc.tx_rate, fc,
WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_MGMT ? "Mgmt" : "",
WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_CTL ? "Ctrl" : "",
WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA ? "Data" : "",
WLAN_FC_GET_STYPE(fc) >> 4,
fc & IEEE80211_FCTL_TODS ? " ToDS" : "",
fc & IEEE80211_FCTL_FROMDS ? " FromDS" : "");
ieee80211_is_mgmt(txdesc.frame_control) ? "Mgmt" : "",
ieee80211_is_ctl(txdesc.frame_control) ? "Ctrl" : "",
ieee80211_is_data(txdesc.frame_control) ? "Data" : "",
(fc & IEEE80211_FCTL_STYPE) >> 4,
ieee80211_has_tods(txdesc.frame_control) ? " ToDS" : "",
ieee80211_has_fromds(txdesc.frame_control) ? " FromDS" : "");
PDEBUG(DEBUG_EXTRA, " A1=%pM A2=%pM A3=%pM A4=%pM\n",
txdesc.addr1, txdesc.addr2,
txdesc.addr3, txdesc.addr4);

View file

@ -1,5 +1,6 @@
/* Host AP driver Info Frame processing (part of hostap.o module) */
#include <linux/if_arp.h>
#include "hostap_wlan.h"
#include "hostap.h"
#include "hostap_ap.h"

View file

@ -2,6 +2,7 @@
#include <linux/types.h>
#include <linux/ethtool.h>
#include <linux/if_arp.h>
#include <net/lib80211.h>
#include "hostap_wlan.h"

View file

@ -26,7 +26,6 @@
#include <linux/etherdevice.h>
#include <net/net_namespace.h>
#include <net/iw_handler.h>
#include <net/ieee80211.h>
#include <net/lib80211.h>
#include <asm/uaccess.h>
@ -543,7 +542,8 @@ void hostap_dump_rx_header(const char *name, const struct hfa384x_rx_frame *rx)
fc = __le16_to_cpu(rx->frame_control);
printk(KERN_DEBUG " FC=0x%04x (type=%d:%d) dur=0x%04x seq=0x%04x "
"data_len=%d%s%s\n",
fc, WLAN_FC_GET_TYPE(fc) >> 2, WLAN_FC_GET_STYPE(fc) >> 4,
fc, (fc & IEEE80211_FCTL_FTYPE) >> 2,
(fc & IEEE80211_FCTL_STYPE) >> 4,
__le16_to_cpu(rx->duration_id), __le16_to_cpu(rx->seq_ctrl),
__le16_to_cpu(rx->data_len),
fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "",
@ -570,7 +570,8 @@ void hostap_dump_tx_header(const char *name, const struct hfa384x_tx_frame *tx)
fc = __le16_to_cpu(tx->frame_control);
printk(KERN_DEBUG " FC=0x%04x (type=%d:%d) dur=0x%04x seq=0x%04x "
"data_len=%d%s%s\n",
fc, WLAN_FC_GET_TYPE(fc) >> 2, WLAN_FC_GET_STYPE(fc) >> 4,
fc, (fc & IEEE80211_FCTL_FTYPE) >> 2,
(fc & IEEE80211_FCTL_STYPE) >> 4,
__le16_to_cpu(tx->duration_id), __le16_to_cpu(tx->seq_ctrl),
__le16_to_cpu(tx->data_len),
fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "",
@ -593,29 +594,16 @@ static int hostap_80211_header_parse(const struct sk_buff *skb,
}
int hostap_80211_get_hdrlen(u16 fc)
int hostap_80211_get_hdrlen(__le16 fc)
{
int hdrlen = 24;
if (ieee80211_is_data(fc) && ieee80211_has_a4 (fc))
return 30; /* Addr4 */
else if (ieee80211_is_cts(fc) || ieee80211_is_ack(fc))
return 10;
else if (ieee80211_is_ctl(fc))
return 16;
switch (WLAN_FC_GET_TYPE(fc)) {
case IEEE80211_FTYPE_DATA:
if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))
hdrlen = 30; /* Addr4 */
break;
case IEEE80211_FTYPE_CTL:
switch (WLAN_FC_GET_STYPE(fc)) {
case IEEE80211_STYPE_CTS:
case IEEE80211_STYPE_ACK:
hdrlen = 10;
break;
default:
hdrlen = 16;
break;
}
break;
}
return hdrlen;
return 24;
}

View file

@ -186,7 +186,7 @@ config LIBIPW_DEBUG
% echo 0x00000FFO > /proc/net/ieee80211/debug_level
For a list of values you can assign to debug_level, you
can look at the bit mask values in <net/ieee80211.h>
can look at the bit mask values in ieee80211.h
If you are not trying to debug or develop the libipw
component, you most likely want to say N here.

View file

@ -1119,6 +1119,9 @@ static inline int ieee80211_is_cck_rate(u8 rate)
extern void free_ieee80211(struct net_device *dev);
extern struct net_device *alloc_ieee80211(int sizeof_priv);
extern void ieee80211_networks_age(struct ieee80211_device *ieee,
unsigned long age_secs);
extern int ieee80211_set_encryption(struct ieee80211_device *ieee);
/* ieee80211_tx.c */

View file

@ -1692,7 +1692,13 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
u32 lock;
u32 ord_len = sizeof(lock);
/* Quite if manually disabled. */
/* Age scan list entries found before suspend */
if (priv->suspend_time) {
ieee80211_networks_age(priv->ieee, priv->suspend_time);
priv->suspend_time = 0;
}
/* Quiet if manually disabled. */
if (priv->status & STATUS_RF_KILL_SW) {
IPW_DEBUG_INFO("%s: Radio is disabled by Manual Disable "
"switch\n", priv->net_dev->name);
@ -6415,6 +6421,8 @@ static int ipw2100_suspend(struct pci_dev *pci_dev, pm_message_t state)
pci_disable_device(pci_dev);
pci_set_power_state(pci_dev, PCI_D3hot);
priv->suspend_at = get_seconds();
mutex_unlock(&priv->action_mutex);
return 0;
@ -6458,6 +6466,8 @@ static int ipw2100_resume(struct pci_dev *pci_dev)
* the queue of needed */
netif_device_attach(dev);
priv->suspend_time = get_seconds() - priv->suspend_at;
/* Bring the device back up */
if (!(priv->status & STATUS_RF_KILL_SW))
ipw2100_up(priv, 0);

View file

@ -39,8 +39,6 @@
#include <linux/wireless.h>
#include <net/iw_handler.h> // new driver API
#include <net/ieee80211.h>
#ifdef CONFIG_IPW2100_MONITOR
#include <net/ieee80211_radiotap.h>
#endif
@ -48,6 +46,8 @@
#include <linux/workqueue.h>
#include <linux/mutex.h>
#include "ieee80211.h"
struct ipw2100_priv;
struct ipw2100_tx_packet;
struct ipw2100_rx_packet;
@ -591,6 +591,10 @@ struct ipw2100_priv {
int user_requested_scan;
/* Track time in suspend */
unsigned long suspend_at;
unsigned long suspend_time;
u32 interrupts;
int tx_interrupts;
int rx_interrupts;

View file

@ -301,88 +301,102 @@ static inline void ipw_write_reg32(struct ipw_priv *a, u32 b, u32 c)
}
/* 8-bit direct write (low 4K) */
#define _ipw_write8(ipw, ofs, val) writeb((val), (ipw)->hw_base + (ofs))
static inline void _ipw_write8(struct ipw_priv *ipw, unsigned long ofs,
u8 val)
{
writeb(val, ipw->hw_base + ofs);
}
/* 8-bit direct write (for low 4K of SRAM/regs), with debug wrapper */
#define ipw_write8(ipw, ofs, val) do { \
IPW_DEBUG_IO("%s %d: write_direct8(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \
_ipw_write8(ipw, ofs, val); \
} while (0)
IPW_DEBUG_IO("%s %d: write_direct8(0x%08X, 0x%08X)\n", __FILE__, \
__LINE__, (u32)(ofs), (u32)(val)); \
_ipw_write8(ipw, ofs, val); \
} while (0)
/* 16-bit direct write (low 4K) */
#define _ipw_write16(ipw, ofs, val) writew((val), (ipw)->hw_base + (ofs))
static inline void _ipw_write16(struct ipw_priv *ipw, unsigned long ofs,
u16 val)
{
writew(val, ipw->hw_base + ofs);
}
/* 16-bit direct write (for low 4K of SRAM/regs), with debug wrapper */
#define ipw_write16(ipw, ofs, val) \
IPW_DEBUG_IO("%s %d: write_direct16(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \
_ipw_write16(ipw, ofs, val)
#define ipw_write16(ipw, ofs, val) do { \
IPW_DEBUG_IO("%s %d: write_direct16(0x%08X, 0x%08X)\n", __FILE__, \
__LINE__, (u32)(ofs), (u32)(val)); \
_ipw_write16(ipw, ofs, val); \
} while (0)
/* 32-bit direct write (low 4K) */
#define _ipw_write32(ipw, ofs, val) writel((val), (ipw)->hw_base + (ofs))
static inline void _ipw_write32(struct ipw_priv *ipw, unsigned long ofs,
u32 val)
{
writel(val, ipw->hw_base + ofs);
}
/* 32-bit direct write (for low 4K of SRAM/regs), with debug wrapper */
#define ipw_write32(ipw, ofs, val) \
IPW_DEBUG_IO("%s %d: write_direct32(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \
_ipw_write32(ipw, ofs, val)
#define ipw_write32(ipw, ofs, val) do { \
IPW_DEBUG_IO("%s %d: write_direct32(0x%08X, 0x%08X)\n", __FILE__, \
__LINE__, (u32)(ofs), (u32)(val)); \
_ipw_write32(ipw, ofs, val); \
} while (0)
/* 8-bit direct read (low 4K) */
#define _ipw_read8(ipw, ofs) readb((ipw)->hw_base + (ofs))
/* 8-bit direct read (low 4K), with debug wrapper */
static inline u8 __ipw_read8(char *f, u32 l, struct ipw_priv *ipw, u32 ofs)
static inline u8 _ipw_read8(struct ipw_priv *ipw, unsigned long ofs)
{
IPW_DEBUG_IO("%s %d: read_direct8(0x%08X)\n", f, l, (u32) (ofs));
return _ipw_read8(ipw, ofs);
return readb(ipw->hw_base + ofs);
}
/* alias to 8-bit direct read (low 4K of SRAM/regs), with debug wrapper */
#define ipw_read8(ipw, ofs) __ipw_read8(__FILE__, __LINE__, ipw, ofs)
#define ipw_read8(ipw, ofs) ({ \
IPW_DEBUG_IO("%s %d: read_direct8(0x%08X)\n", __FILE__, __LINE__, \
(u32)(ofs)); \
_ipw_read8(ipw, ofs); \
})
/* 16-bit direct read (low 4K) */
#define _ipw_read16(ipw, ofs) readw((ipw)->hw_base + (ofs))
/* 16-bit direct read (low 4K), with debug wrapper */
static inline u16 __ipw_read16(char *f, u32 l, struct ipw_priv *ipw, u32 ofs)
static inline u16 _ipw_read16(struct ipw_priv *ipw, unsigned long ofs)
{
IPW_DEBUG_IO("%s %d: read_direct16(0x%08X)\n", f, l, (u32) (ofs));
return _ipw_read16(ipw, ofs);
return readw(ipw->hw_base + ofs);
}
/* alias to 16-bit direct read (low 4K of SRAM/regs), with debug wrapper */
#define ipw_read16(ipw, ofs) __ipw_read16(__FILE__, __LINE__, ipw, ofs)
#define ipw_read16(ipw, ofs) ({ \
IPW_DEBUG_IO("%s %d: read_direct16(0x%08X)\n", __FILE__, __LINE__, \
(u32)(ofs)); \
_ipw_read16(ipw, ofs); \
})
/* 32-bit direct read (low 4K) */
#define _ipw_read32(ipw, ofs) readl((ipw)->hw_base + (ofs))
/* 32-bit direct read (low 4K), with debug wrapper */
static inline u32 __ipw_read32(char *f, u32 l, struct ipw_priv *ipw, u32 ofs)
static inline u32 _ipw_read32(struct ipw_priv *ipw, unsigned long ofs)
{
IPW_DEBUG_IO("%s %d: read_direct32(0x%08X)\n", f, l, (u32) (ofs));
return _ipw_read32(ipw, ofs);
return readl(ipw->hw_base + ofs);
}
/* alias to 32-bit direct read (low 4K of SRAM/regs), with debug wrapper */
#define ipw_read32(ipw, ofs) __ipw_read32(__FILE__, __LINE__, ipw, ofs)
#define ipw_read32(ipw, ofs) ({ \
IPW_DEBUG_IO("%s %d: read_direct32(0x%08X)\n", __FILE__, __LINE__, \
(u32)(ofs)); \
_ipw_read32(ipw, ofs); \
})
/* multi-byte read (above 4K), with debug wrapper */
static void _ipw_read_indirect(struct ipw_priv *, u32, u8 *, int);
static inline void __ipw_read_indirect(const char *f, int l,
struct ipw_priv *a, u32 b, u8 * c, int d)
{
IPW_DEBUG_IO("%s %d: read_indirect(0x%08X) %d bytes\n", f, l, (u32) (b),
d);
_ipw_read_indirect(a, b, c, d);
}
/* alias to multi-byte read (SRAM/regs above 4K), with debug wrapper */
#define ipw_read_indirect(a, b, c, d) __ipw_read_indirect(__FILE__, __LINE__, a, b, c, d)
#define ipw_read_indirect(a, b, c, d) ({ \
IPW_DEBUG_IO("%s %d: read_indirect(0x%08X) %u bytes\n", __FILE__, \
__LINE__, (u32)(b), (u32)(d)); \
_ipw_read_indirect(a, b, c, d); \
})
/* alias to multi-byte read (SRAM/regs above 4K), with debug wrapper */
static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * data,
int num);
#define ipw_write_indirect(a, b, c, d) \
IPW_DEBUG_IO("%s %d: write_indirect(0x%08X) %d bytes\n", __FILE__, __LINE__, (u32)(b), d); \
_ipw_write_indirect(a, b, c, d)
#define ipw_write_indirect(a, b, c, d) do { \
IPW_DEBUG_IO("%s %d: write_indirect(0x%08X) %u bytes\n", __FILE__, \
__LINE__, (u32)(b), (u32)(d)); \
_ipw_write_indirect(a, b, c, d); \
} while (0)
/* 32-bit indirect write (above 4K) */
static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value)
@ -11224,6 +11238,12 @@ static int ipw_up(struct ipw_priv *priv)
{
int rc, i, j;
/* Age scan list entries found before suspend */
if (priv->suspend_time) {
ieee80211_networks_age(priv->ieee, priv->suspend_time);
priv->suspend_time = 0;
}
if (priv->status & STATUS_EXIT_PENDING)
return -EIO;
@ -11824,6 +11844,8 @@ static int ipw_pci_suspend(struct pci_dev *pdev, pm_message_t state)
pci_disable_device(pdev);
pci_set_power_state(pdev, pci_choose_state(pdev, state));
priv->suspend_at = get_seconds();
return 0;
}
@ -11859,6 +11881,8 @@ static int ipw_pci_resume(struct pci_dev *pdev)
* the queue of needed */
netif_device_attach(dev);
priv->suspend_time = get_seconds() - priv->suspend_at;
/* Bring the device back up */
queue_work(priv->workqueue, &priv->up);

View file

@ -49,13 +49,14 @@
#include <asm/io.h>
#include <net/lib80211.h>
#include <net/ieee80211.h>
#include <net/ieee80211_radiotap.h>
#define DRV_NAME "ipw2200"
#include <linux/workqueue.h>
#include "ieee80211.h"
/* Authentication and Association States */
enum connection_manager_assoc_states {
CMAS_INIT = 0,
@ -1346,6 +1347,10 @@ struct ipw_priv {
s8 tx_power;
/* Track time in suspend */
unsigned long suspend_at;
unsigned long suspend_time;
#ifdef CONFIG_PM
u32 pm_state[16];
#endif

View file

@ -41,7 +41,7 @@
#include <linux/etherdevice.h>
#include <asm/uaccess.h>
#include <net/ieee80211.h>
#include "ieee80211.h"
int ieee80211_is_valid_channel(struct ieee80211_device *ieee, u8 channel)
{

View file

@ -50,7 +50,7 @@
#include <net/net_namespace.h>
#include <net/arp.h>
#include <net/ieee80211.h>
#include "ieee80211.h"
#define DRV_DESCRIPTION "802.11 data/management/control stack"
#define DRV_NAME "ieee80211"
@ -105,6 +105,21 @@ static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
ieee->networks = NULL;
}
void ieee80211_networks_age(struct ieee80211_device *ieee,
unsigned long age_secs)
{
struct ieee80211_network *network = NULL;
unsigned long flags;
unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC);
spin_lock_irqsave(&ieee->lock, flags);
list_for_each_entry(network, &ieee->network_list, list) {
network->last_scanned -= age_jiffies;
}
spin_unlock_irqrestore(&ieee->lock, flags);
}
EXPORT_SYMBOL(ieee80211_networks_age);
static void ieee80211_networks_initialize(struct ieee80211_device *ieee)
{
int i;

View file

@ -33,7 +33,8 @@
#include <linux/ctype.h>
#include <net/lib80211.h>
#include <net/ieee80211.h>
#include "ieee80211.h"
static void ieee80211_monitor_rx(struct ieee80211_device *ieee,
struct sk_buff *skb,
@ -1615,7 +1616,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device
break;
if ((oldest == NULL) ||
(target->last_scanned < oldest->last_scanned))
time_before(target->last_scanned, oldest->last_scanned))
oldest = target;
}

View file

@ -41,7 +41,7 @@
#include <linux/etherdevice.h>
#include <asm/uaccess.h>
#include <net/ieee80211.h>
#include "ieee80211.h"
/*

View file

@ -35,13 +35,24 @@
#include <linux/jiffies.h>
#include <net/lib80211.h>
#include <net/ieee80211.h>
#include <linux/wireless.h>
#include "ieee80211.h"
static const char *ieee80211_modes[] = {
"?", "a", "b", "ab", "g", "ag", "bg", "abg"
};
static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
{
unsigned long end = jiffies;
if (end >= start)
return jiffies_to_msecs(end - start);
return jiffies_to_msecs(end + (MAX_JIFFY_OFFSET - start) + 1);
}
#define MAX_CUSTOM_LEN 64
static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
char *start, char *stop,
@ -215,8 +226,8 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
iwe.cmd = IWEVCUSTOM;
p = custom;
p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
" Last beacon: %dms ago",
jiffies_to_msecs(jiffies - network->last_scanned));
" Last beacon: %ums ago",
elapsed_jiffies_msecs(network->last_scanned));
iwe.u.data.length = p - custom;
if (iwe.u.data.length)
start = iwe_stream_add_point(info, start, stop, &iwe, custom);
@ -276,15 +287,15 @@ int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
time_after(network->last_scanned + ieee->scan_age, jiffies))
ev = ieee80211_translate_scan(ieee, ev, stop, network,
info);
else
else {
IEEE80211_DEBUG_SCAN("Not showing network '%s ("
"%pM)' due to age (%dms).\n",
"%pM)' due to age (%ums).\n",
print_ssid(ssid, network->ssid,
network->ssid_len),
network->bssid,
jiffies_to_msecs(jiffies -
network->
last_scanned));
elapsed_jiffies_msecs(
network->last_scanned));
}
}
spin_unlock_irqrestore(&ieee->lock, flags);

View file

@ -1,27 +1,31 @@
config IWLWIFI
bool "Intel Wireless Wifi"
tristate "Intel Wireless Wifi"
depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
default y
config IWLCORE
tristate "Intel Wireless Wifi Core"
depends on IWLWIFI
select LIB80211
select FW_LOADER
select MAC80211_LEDS if IWLWIFI_LEDS
select LEDS_CLASS if IWLWIFI_LEDS
select RFKILL if IWLWIFI_RFKILL
select MAC80211_LEDS if IWL3945_LEDS
select LEDS_CLASS if IWL3945_LEDS
config IWLWIFI_LEDS
bool "Enable LED support in iwlagn driver"
depends on IWLCORE
depends on IWLWIFI
config IWLWIFI_RFKILL
bool "Enable RF kill support in iwlagn driver"
depends on IWLCORE
bool "Enable RF kill support in iwlagn and iwl3945 drivers"
depends on IWLWIFI
config IWLWIFI_SPECTRUM_MEASUREMENT
bool "Enable Spectrum Measurement in iwlagn driver"
depends on IWLWIFI
---help---
This option will enable spectrum measurement for the iwlagn driver.
config IWLWIFI_DEBUG
bool "Enable full debugging output in iwlagn and iwl3945 drivers"
depends on IWLCORE
depends on IWLWIFI
---help---
This option will enable debug tracing output for the iwlwifi drivers
@ -45,16 +49,14 @@ config IWLWIFI_DEBUG
any problems you may encounter.
config IWLWIFI_DEBUGFS
bool "Iwlwifi debugfs support"
depends on IWLCORE && IWLWIFI_DEBUG && MAC80211_DEBUGFS
bool "iwlagn debugfs support"
depends on IWLWIFI && IWLWIFI_DEBUG && MAC80211_DEBUGFS
---help---
Enable creation of debugfs files for the iwlwifi drivers.
config IWLAGN
tristate "Intel Wireless WiFi Next Gen AGN"
tristate "Intel Wireless WiFi Next Gen AGN (iwlagn)"
depends on IWLWIFI
select FW_LOADER
select IWLCORE
---help---
Select to build the driver supporting the:
@ -77,19 +79,6 @@ config IWLAGN
say M here and read <file:Documentation/kbuild/modules.txt>. The
module will be called iwlagn.ko.
config IWLAGN_SPECTRUM_MEASUREMENT
bool "Enable Spectrum Measurement in iwlagn driver"
depends on IWLAGN
---help---
This option will enable spectrum measurement for the iwlagn driver.
config IWLAGN_LEDS
bool "Enable LEDS features in iwlagn driver"
depends on IWLAGN
select IWLWIFI_LEDS
---help---
This option enables LEDS for the iwlagn drivers
config IWL4965
bool "Intel Wireless WiFi 4965AGN"
@ -98,19 +87,14 @@ config IWL4965
This option enables support for Intel Wireless WiFi Link 4965AGN
config IWL5000
bool "Intel Wireless WiFi 5000AGN"
bool "Intel Wireless WiFi 5000AGN; Intel WiFi Link 100, 6000, and 6050 Series"
depends on IWLAGN
---help---
This option enables support for Intel Wireless WiFi Link 5000AGN Family
config IWL3945
tristate "Intel PRO/Wireless 3945ABG/BG Network Connection"
tristate "Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)"
depends on IWLWIFI
select FW_LOADER
select LIB80211
select MAC80211_LEDS if IWL3945_LEDS
select LEDS_CLASS if IWL3945_LEDS
select RFKILL if IWLWIFI_RFKILL
---help---
Select to build the driver supporting the:
@ -134,7 +118,7 @@ config IWL3945
module will be called iwl3945.ko.
config IWL3945_SPECTRUM_MEASUREMENT
bool "Enable Spectrum Measurement in iwl3945 drivers"
bool "Enable Spectrum Measurement in iwl3945 driver"
depends on IWL3945
---help---
This option will enable spectrum measurement for the iwl3945 driver.

View file

@ -1,11 +1,11 @@
obj-$(CONFIG_IWLCORE) += iwlcore.o
obj-$(CONFIG_IWLWIFI) += iwlcore.o
iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o iwl-calib.o
iwlcore-objs += iwl-scan.o
iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o
iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o
iwlcore-$(CONFIG_IWLAGN_SPECTRUM_MEASUREMENT) += iwl-spectrum.o
iwlcore-$(CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT) += iwl-spectrum.o
obj-$(CONFIG_IWLAGN) += iwlagn.o
iwlagn-objs := iwl-agn.o iwl-agn-rs.o

View file

@ -1073,7 +1073,7 @@ static int iwl3945_apm_init(struct iwl_priv *priv)
* D0U* --> D0A* state */
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
if (ret < 0) {
IWL_DEBUG_INFO(priv, "Failed to init the card\n");
@ -2747,6 +2747,7 @@ static struct iwl_lib_ops iwl3945_lib = {
.query_addr = iwlcore_eeprom_query_addr,
},
.send_tx_power = iwl3945_send_tx_power,
.is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr,
};
static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {

View file

@ -72,7 +72,7 @@
#define VD
#endif
#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT
#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
#define VS "s"
#else
#define VS
@ -444,7 +444,7 @@ void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
pci_unmap_single(dev,
pci_unmap_addr(&txq->cmd[index]->meta, mapping),
pci_unmap_len(&txq->cmd[index]->meta, len),
PCI_DMA_TODEVICE);
PCI_DMA_BIDIRECTIONAL);
/* Unmap chunks, if any. */
for (i = 1; i < num_tbs; i++) {
@ -644,6 +644,9 @@ static u16 iwl_adjust_beacon_interval(u16 beacon_val)
/ MAX_UCODE_BEACON_INTERVAL;
new_val = beacon_val / beacon_factor;
if (!new_val)
new_val = MAX_UCODE_BEACON_INTERVAL;
return new_val;
}
@ -751,41 +754,6 @@ static void iwl_rx_reply_alive(struct iwl_priv *priv,
IWL_WARN(priv, "uCode did not respond OK.\n");
}
static void iwl_rx_reply_error(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) "
"seq 0x%04X ser 0x%08X\n",
le32_to_cpu(pkt->u.err_resp.error_type),
get_cmd_string(pkt->u.err_resp.cmd_id),
pkt->u.err_resp.cmd_id,
le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num),
le32_to_cpu(pkt->u.err_resp.error_info));
}
static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
#ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n",
sleep->pm_sleep_mode, sleep->pm_wakeup_src);
#endif
}
static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
"notification for %s:\n",
le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
}
static void iwl_bg_beacon_update(struct work_struct *work)
{
struct iwl_priv *priv =
@ -1312,64 +1280,6 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);
}
static irqreturn_t iwl_isr(int irq, void *data)
{
struct iwl_priv *priv = data;
u32 inta, inta_mask;
u32 inta_fh;
if (!priv)
return IRQ_NONE;
spin_lock(&priv->lock);
/* Disable (but don't clear!) interrupts here to avoid
* back-to-back ISRs and sporadic interrupts from our NIC.
* If we have something to service, the tasklet will re-enable ints.
* If we *don't* have something, we'll re-enable before leaving here. */
inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
iwl_write32(priv, CSR_INT_MASK, 0x00000000);
/* Discover which interrupts are active/pending */
inta = iwl_read32(priv, CSR_INT);
inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
/* Ignore interrupt if there's nothing in NIC to service.
* This may be due to IRQ shared with another device,
* or due to sporadic interrupts thrown from our NIC. */
if (!inta && !inta_fh) {
IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0, inta_fh == 0\n");
goto none;
}
if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
/* Hardware disappeared. It might have already raised
* an interrupt */
IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
goto unplugged;
}
IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
inta, inta_mask, inta_fh);
inta &= ~CSR_INT_BIT_SCD;
/* iwl_irq_tasklet() will service interrupts and re-enable them */
if (likely(inta || inta_fh))
tasklet_schedule(&priv->irq_tasklet);
unplugged:
spin_unlock(&priv->lock);
return IRQ_HANDLED;
none:
/* re-enable interrupts here since we don't have anything to service. */
/* only Re-enable if diabled by irq */
if (test_bit(STATUS_INT_ENABLED, &priv->status))
iwl_enable_interrupts(priv);
spin_unlock(&priv->lock);
return IRQ_NONE;
}
/******************************************************************************
*
* uCode download functions
@ -2674,71 +2584,6 @@ static void iwl_bss_info_changed(struct ieee80211_hw *hw,
}
static int iwl_mac_hw_scan(struct ieee80211_hw *hw,
struct cfg80211_scan_request *req)
{
unsigned long flags;
struct iwl_priv *priv = hw->priv;
int ret;
u8 *ssid = NULL;
size_t ssid_len = 0;
if (req->n_ssids) {
ssid = req->ssids[0].ssid;
ssid_len = req->ssids[0].ssid_len;
}
IWL_DEBUG_MAC80211(priv, "enter\n");
mutex_lock(&priv->mutex);
spin_lock_irqsave(&priv->lock, flags);
if (!iwl_is_ready_rf(priv)) {
ret = -EIO;
IWL_DEBUG_MAC80211(priv, "leave - not ready or exit pending\n");
goto out_unlock;
}
/* We don't schedule scan within next_scan_jiffies period.
* Avoid scanning during possible EAPOL exchange, return
* success immediately.
*/
if (priv->next_scan_jiffies &&
time_after(priv->next_scan_jiffies, jiffies)) {
IWL_DEBUG_SCAN(priv, "scan rejected: within next scan period\n");
queue_work(priv->workqueue, &priv->scan_completed);
ret = 0;
goto out_unlock;
}
/* if we just finished scan ask for delay */
if (iwl_is_associated(priv) && priv->last_scan_jiffies &&
time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN, jiffies)) {
IWL_DEBUG_SCAN(priv, "scan rejected: within previous scan period\n");
queue_work(priv->workqueue, &priv->scan_completed);
ret = 0;
goto out_unlock;
}
if (ssid_len) {
priv->one_direct_scan = 1;
priv->direct_ssid_len = ssid_len;
memcpy(priv->direct_ssid, ssid, priv->direct_ssid_len);
} else {
priv->one_direct_scan = 0;
}
ret = iwl_scan_initiate(priv);
IWL_DEBUG_MAC80211(priv, "leave\n");
out_unlock:
spin_unlock_irqrestore(&priv->lock, flags);
mutex_unlock(&priv->mutex);
return ret;
}
static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw,
struct ieee80211_key_conf *keyconf, const u8 *addr,
u32 iv32, u16 *phase1key)
@ -3370,7 +3215,7 @@ static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);
static void iwl_setup_deferred_work(struct iwl_priv *priv)
{
priv->workqueue = create_workqueue(DRV_NAME);
priv->workqueue = create_singlethread_workqueue(DRV_NAME);
init_waitqueue_head(&priv->wait_command_queue);
@ -3612,7 +3457,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group);
if (err) {
IWL_ERR(priv, "failed to create sysfs device attributes\n");
goto out_uninit_drv;
goto out_free_irq;
}
iwl_setup_deferred_work(priv);
@ -3657,10 +3502,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
out_remove_sysfs:
sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
out_free_irq:
free_irq(priv->pci_dev->irq, priv);
out_disable_msi:
pci_disable_msi(priv->pci_dev);
pci_disable_device(priv->pci_dev);
out_uninit_drv:
iwl_uninit_drv(priv);
out_free_eeprom:
iwl_eeprom_free(priv);

View file

@ -1386,14 +1386,16 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
{
int ret = 0;
if (tx_power < IWL_TX_POWER_TARGET_POWER_MIN) {
IWL_WARN(priv, "Requested user TXPOWER %d below limit.\n",
priv->tx_power_user_lmt);
IWL_WARN(priv, "Requested user TXPOWER %d below lower limit %d.\n",
tx_power,
IWL_TX_POWER_TARGET_POWER_MIN);
return -EINVAL;
}
if (tx_power > IWL_TX_POWER_TARGET_POWER_MAX) {
IWL_WARN(priv, "Requested user TXPOWER %d above limit.\n",
priv->tx_power_user_lmt);
IWL_WARN(priv, "Requested user TXPOWER %d above upper limit %d.\n",
tx_power,
IWL_TX_POWER_TARGET_POWER_MAX);
return -EINVAL;
}
@ -1442,6 +1444,65 @@ void iwl_enable_interrupts(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_enable_interrupts);
irqreturn_t iwl_isr(int irq, void *data)
{
struct iwl_priv *priv = data;
u32 inta, inta_mask;
u32 inta_fh;
if (!priv)
return IRQ_NONE;
spin_lock(&priv->lock);
/* Disable (but don't clear!) interrupts here to avoid
* back-to-back ISRs and sporadic interrupts from our NIC.
* If we have something to service, the tasklet will re-enable ints.
* If we *don't* have something, we'll re-enable before leaving here. */
inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
iwl_write32(priv, CSR_INT_MASK, 0x00000000);
/* Discover which interrupts are active/pending */
inta = iwl_read32(priv, CSR_INT);
inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
/* Ignore interrupt if there's nothing in NIC to service.
* This may be due to IRQ shared with another device,
* or due to sporadic interrupts thrown from our NIC. */
if (!inta && !inta_fh) {
IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0, inta_fh == 0\n");
goto none;
}
if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
/* Hardware disappeared. It might have already raised
* an interrupt */
IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
goto unplugged;
}
IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
inta, inta_mask, inta_fh);
inta &= ~CSR_INT_BIT_SCD;
/* iwl_irq_tasklet() will service interrupts and re-enable them */
if (likely(inta || inta_fh))
tasklet_schedule(&priv->irq_tasklet);
unplugged:
spin_unlock(&priv->lock);
return IRQ_HANDLED;
none:
/* re-enable interrupts here since we don't have anything to service. */
/* only Re-enable if diabled by irq */
if (test_bit(STATUS_INT_ENABLED, &priv->status))
iwl_enable_interrupts(priv);
spin_unlock(&priv->lock);
return IRQ_NONE;
}
EXPORT_SYMBOL(iwl_isr);
int iwl_send_bt_config(struct iwl_priv *priv)
{
struct iwl_bt_cmd bt_cmd = {
@ -1977,3 +2038,42 @@ void iwl_bg_rf_kill(struct work_struct *work)
iwl_rfkill_set_hw_state(priv);
}
EXPORT_SYMBOL(iwl_bg_rf_kill);
void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
#ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n",
sleep->pm_sleep_mode, sleep->pm_wakeup_src);
#endif
}
EXPORT_SYMBOL(iwl_rx_pm_sleep_notif);
void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
"notification for %s:\n",
le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
}
EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif);
void iwl_rx_reply_error(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) "
"seq 0x%04X ser 0x%08X\n",
le32_to_cpu(pkt->u.err_resp.error_type),
get_cmd_string(pkt->u.err_resp.cmd_id),
pkt->u.err_resp.cmd_id,
le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num),
le32_to_cpu(pkt->u.err_resp.error_info));
}
EXPORT_SYMBOL(iwl_rx_reply_error);

View file

@ -249,6 +249,16 @@ int iwl_set_hw_params(struct iwl_priv *priv);
int iwl_init_drv(struct iwl_priv *priv);
void iwl_uninit_drv(struct iwl_priv *priv);
/*****************************************************
* RX handlers.
* **************************************************/
void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
void iwl_rx_reply_error(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
/*****************************************************
* RX
******************************************************/
@ -345,6 +355,7 @@ void iwl_init_scan_params(struct iwl_priv *priv);
int iwl_scan_cancel(struct iwl_priv *priv);
int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
int iwl_scan_initiate(struct iwl_priv *priv);
int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req);
u16 iwl_fill_probe_req(struct iwl_priv *priv, enum ieee80211_band band,
struct ieee80211_mgmt *frame, int left);
void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
@ -379,7 +390,7 @@ void iwl_calib_free_results(struct iwl_priv *priv);
/*******************************************************************************
* Spectrum Measureemtns in iwl-spectrum.c
******************************************************************************/
#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT
#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
void iwl_setup_spectrum_handlers(struct iwl_priv *priv);
#else
static inline void iwl_setup_spectrum_handlers(struct iwl_priv *priv) {}
@ -410,6 +421,7 @@ int iwl_send_card_state(struct iwl_priv *priv, u32 flags,
*****************************************************/
void iwl_disable_interrupts(struct iwl_priv *priv);
void iwl_enable_interrupts(struct iwl_priv *priv);
irqreturn_t iwl_isr(int irq, void *data);
static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv)
{
int pos;

View file

@ -841,7 +841,7 @@ struct iwl_priv {
struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
#if defined(CONFIG_IWLAGN_SPECTRUM_MEASUREMENT) || defined(CONFIG_IWL3945_SPECTRUM_MEASUREMENT)
#if defined(CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT) || defined(CONFIG_IWL3945_SPECTRUM_MEASUREMENT)
/* spectrum measurement report caching */
struct iwl_spectrum_notification measure_report;
u8 measurement_status;
@ -922,7 +922,7 @@ struct iwl_priv {
* 4965's initialize alive response contains some calibration data. */
struct iwl_init_alive_resp card_alive_init;
struct iwl_alive_resp card_alive;
#if defined(CONFIG_IWLWIFI_RFKILL) || defined(CONFIG_IWL3945_RFKILL)
#if defined(CONFIG_IWLWIFI_RFKILL)
struct rfkill *rfkill;
#endif

View file

@ -440,6 +440,74 @@ int iwl_scan_initiate(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_scan_initiate);
#define IWL_DELAY_NEXT_SCAN (HZ*2)
int iwl_mac_hw_scan(struct ieee80211_hw *hw,
struct cfg80211_scan_request *req)
{
unsigned long flags;
struct iwl_priv *priv = hw->priv;
int ret;
u8 *ssid = NULL;
size_t ssid_len = 0;
if (req->n_ssids) {
ssid = req->ssids[0].ssid;
ssid_len = req->ssids[0].ssid_len;
}
IWL_DEBUG_MAC80211(priv, "enter\n");
mutex_lock(&priv->mutex);
spin_lock_irqsave(&priv->lock, flags);
if (!iwl_is_ready_rf(priv)) {
ret = -EIO;
IWL_DEBUG_MAC80211(priv, "leave - not ready or exit pending\n");
goto out_unlock;
}
/* We don't schedule scan within next_scan_jiffies period.
* Avoid scanning during possible EAPOL exchange, return
* success immediately.
*/
if (priv->next_scan_jiffies &&
time_after(priv->next_scan_jiffies, jiffies)) {
IWL_DEBUG_SCAN(priv, "scan rejected: within next scan period\n");
queue_work(priv->workqueue, &priv->scan_completed);
ret = 0;
goto out_unlock;
}
/* if we just finished scan ask for delay */
if (iwl_is_associated(priv) && priv->last_scan_jiffies &&
time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN, jiffies)) {
IWL_DEBUG_SCAN(priv, "scan rejected: within previous scan period\n");
queue_work(priv->workqueue, &priv->scan_completed);
ret = 0;
goto out_unlock;
}
if (ssid_len) {
priv->one_direct_scan = 1;
priv->direct_ssid_len = ssid_len;
memcpy(priv->direct_ssid, ssid, priv->direct_ssid_len);
} else {
priv->one_direct_scan = 0;
}
ret = iwl_scan_initiate(priv);
IWL_DEBUG_MAC80211(priv, "leave\n");
out_unlock:
spin_unlock_irqrestore(&priv->lock, flags);
mutex_unlock(&priv->mutex);
return ret;
}
EXPORT_SYMBOL(iwl_mac_hw_scan);
#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
void iwl_bg_scan_check(struct work_struct *data)

View file

@ -819,7 +819,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
* within command buffer array. */
txcmd_phys = pci_map_single(priv->pci_dev,
out_cmd, sizeof(struct iwl_cmd),
PCI_DMA_TODEVICE);
PCI_DMA_BIDIRECTIONAL);
pci_unmap_addr_set(&out_cmd->meta, mapping, txcmd_phys);
pci_unmap_len_set(&out_cmd->meta, len, sizeof(struct iwl_cmd));
/* Add buffer containing Tx command and MAC(!) header to TFD's
@ -968,7 +968,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
IWL_MAX_SCAN_SIZE : sizeof(struct iwl_cmd);
phys_addr = pci_map_single(priv->pci_dev, out_cmd,
len, PCI_DMA_TODEVICE);
len, PCI_DMA_BIDIRECTIONAL);
pci_unmap_addr_set(&out_cmd->meta, mapping, phys_addr);
pci_unmap_len_set(&out_cmd->meta, len, len);
phys_addr += offsetof(struct iwl_cmd, hdr);
@ -1068,7 +1068,7 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id,
pci_unmap_single(priv->pci_dev,
pci_unmap_addr(&txq->cmd[cmd_idx]->meta, mapping),
pci_unmap_len(&txq->cmd[cmd_idx]->meta, len),
PCI_DMA_TODEVICE);
PCI_DMA_BIDIRECTIONAL);
for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {

View file

@ -726,38 +726,6 @@ static void iwl3945_setup_rxon_timing(struct iwl_priv *priv)
le16_to_cpu(priv->rxon_timing.atim_window));
}
static int iwl3945_scan_initiate(struct iwl_priv *priv)
{
if (!iwl_is_ready_rf(priv)) {
IWL_DEBUG_SCAN(priv, "Aborting scan due to not ready.\n");
return -EIO;
}
if (test_bit(STATUS_SCANNING, &priv->status)) {
IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
return -EAGAIN;
}
if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
IWL_DEBUG_SCAN(priv, "Scan request while abort pending. "
"Queuing.\n");
return -EAGAIN;
}
IWL_DEBUG_INFO(priv, "Starting scan...\n");
if (priv->cfg->sku & IWL_SKU_G)
priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ);
if (priv->cfg->sku & IWL_SKU_A)
priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ);
set_bit(STATUS_SCANNING, &priv->status);
priv->scan_start = jiffies;
priv->scan_pass_start = priv->scan_start;
queue_work(priv->workqueue, &priv->request_scan);
return 0;
}
static int iwl3945_set_mode(struct iwl_priv *priv, int mode)
{
if (mode == NL80211_IFTYPE_ADHOC) {
@ -1188,56 +1156,6 @@ drop:
return -1;
}
static void iwl3945_radio_kill_sw(struct iwl_priv *priv, int disable_radio)
{
unsigned long flags;
if (!!disable_radio == test_bit(STATUS_RF_KILL_SW, &priv->status))
return;
IWL_DEBUG_RF_KILL(priv, "Manual SW RF KILL set to: RADIO %s\n",
disable_radio ? "OFF" : "ON");
if (disable_radio) {
iwl_scan_cancel(priv);
/* FIXME: This is a workaround for AP */
if (priv->iw_mode != NL80211_IFTYPE_AP) {
spin_lock_irqsave(&priv->lock, flags);
iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
CSR_UCODE_SW_BIT_RFKILL);
spin_unlock_irqrestore(&priv->lock, flags);
iwl_send_card_state(priv, CARD_STATE_CMD_DISABLE, 0);
set_bit(STATUS_RF_KILL_SW, &priv->status);
}
return;
}
spin_lock_irqsave(&priv->lock, flags);
iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
clear_bit(STATUS_RF_KILL_SW, &priv->status);
spin_unlock_irqrestore(&priv->lock, flags);
/* wake up ucode */
msleep(10);
spin_lock_irqsave(&priv->lock, flags);
iwl_read32(priv, CSR_UCODE_DRV_GP1);
if (!iwl_grab_nic_access(priv))
iwl_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
IWL_DEBUG_RF_KILL(priv, "Can not turn radio back on - "
"disabled by HW switch\n");
return;
}
if (priv->is_open)
queue_work(priv->workqueue, &priv->restart);
return;
}
#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
#include "iwl-spectrum.h"
@ -1417,60 +1335,6 @@ static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv,
return;
}
static void iwl3945_rx_reply_error(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) "
"seq 0x%04X ser 0x%08X\n",
le32_to_cpu(pkt->u.err_resp.error_type),
get_cmd_string(pkt->u.err_resp.cmd_id),
pkt->u.err_resp.cmd_id,
le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num),
le32_to_cpu(pkt->u.err_resp.error_info));
}
static void iwl3945_rx_spectrum_measure_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
if (!report->state) {
IWL_DEBUG(priv, IWL_DL_11H | IWL_DL_INFO,
"Spectrum Measure Notification: Start\n");
return;
}
memcpy(&priv->measure_report, report, sizeof(*report));
priv->measurement_status |= MEASUREMENT_READY;
#endif
}
static void iwl3945_rx_pm_sleep_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
#ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n",
sleep->pm_sleep_mode, sleep->pm_wakeup_src);
#endif
}
static void iwl3945_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
"notification for %s:\n",
le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw,
le32_to_cpu(pkt->len));
}
static void iwl3945_bg_beacon_update(struct work_struct *work)
{
struct iwl_priv *priv =
@ -1518,127 +1382,6 @@ static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
queue_work(priv->workqueue, &priv->beacon_update);
}
/* Service response to REPLY_SCAN_CMD (0x80) */
static void iwl3945_rx_reply_scan(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
#ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
struct iwl_scanreq_notification *notif =
(struct iwl_scanreq_notification *)pkt->u.raw;
IWL_DEBUG_RX(priv, "Scan request status = 0x%x\n", notif->status);
#endif
}
/* Service SCAN_START_NOTIFICATION (0x82) */
static void iwl3945_rx_scan_start_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
struct iwl_scanstart_notification *notif =
(struct iwl_scanstart_notification *)pkt->u.raw;
priv->scan_start_tsf = le32_to_cpu(notif->tsf_low);
IWL_DEBUG_SCAN(priv, "Scan start: "
"%d [802.11%s] "
"(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n",
notif->channel,
notif->band ? "bg" : "a",
notif->tsf_high,
notif->tsf_low, notif->status, notif->beacon_timer);
}
/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
static void iwl3945_rx_scan_results_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
#ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
struct iwl_scanresults_notification *notif =
(struct iwl_scanresults_notification *)pkt->u.raw;
#endif
IWL_DEBUG_SCAN(priv, "Scan ch.res: "
"%d [802.11%s] "
"(TSF: 0x%08X:%08X) - %d "
"elapsed=%lu usec (%dms since last)\n",
notif->channel,
notif->band ? "bg" : "a",
le32_to_cpu(notif->tsf_high),
le32_to_cpu(notif->tsf_low),
le32_to_cpu(notif->statistics[0]),
le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf,
jiffies_to_msecs(elapsed_jiffies
(priv->last_scan_jiffies, jiffies)));
priv->last_scan_jiffies = jiffies;
priv->next_scan_jiffies = 0;
}
/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
static void iwl3945_rx_scan_complete_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
#ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
#endif
IWL_DEBUG_SCAN(priv, "Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
scan_notif->scanned_channels,
scan_notif->tsf_low,
scan_notif->tsf_high, scan_notif->status);
/* The HW is no longer scanning */
clear_bit(STATUS_SCAN_HW, &priv->status);
/* The scan completion notification came in, so kill that timer... */
cancel_delayed_work(&priv->scan_check);
IWL_DEBUG_INFO(priv, "Scan pass on %sGHz took %dms\n",
(priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) ?
"2.4" : "5.2",
jiffies_to_msecs(elapsed_jiffies
(priv->scan_pass_start, jiffies)));
/* Remove this scanned band from the list of pending
* bands to scan, band G precedes A in order of scanning
* as seen in iwl3945_bg_request_scan */
if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ))
priv->scan_bands &= ~BIT(IEEE80211_BAND_2GHZ);
else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ))
priv->scan_bands &= ~BIT(IEEE80211_BAND_5GHZ);
/* If a request to abort was given, or the scan did not succeed
* then we reset the scan state machine and terminate,
* re-queuing another scan if one has been requested */
if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
IWL_DEBUG_INFO(priv, "Aborted scan completed.\n");
clear_bit(STATUS_SCAN_ABORTING, &priv->status);
} else {
/* If there are more bands on this scan pass reschedule */
if (priv->scan_bands > 0)
goto reschedule;
}
priv->last_scan_jiffies = jiffies;
priv->next_scan_jiffies = 0;
IWL_DEBUG_INFO(priv, "Setting scan to off\n");
clear_bit(STATUS_SCANNING, &priv->status);
IWL_DEBUG_INFO(priv, "Scan took %dms\n",
jiffies_to_msecs(elapsed_jiffies(priv->scan_start, jiffies)));
queue_work(priv->workqueue, &priv->scan_completed);
return;
reschedule:
priv->scan_pass_start = jiffies;
queue_work(priv->workqueue, &priv->request_scan);
}
/* Handle notification from uCode that card's power state is changing
* due to software, hardware, or critical temperature RFKILL */
static void iwl3945_rx_card_state_notif(struct iwl_priv *priv,
@ -1690,13 +1433,11 @@ static void iwl3945_setup_rx_handlers(struct iwl_priv *priv)
{
priv->rx_handlers[REPLY_ALIVE] = iwl3945_rx_reply_alive;
priv->rx_handlers[REPLY_ADD_STA] = iwl3945_rx_reply_add_sta;
priv->rx_handlers[REPLY_ERROR] = iwl3945_rx_reply_error;
priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error;
priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
iwl3945_rx_spectrum_measure_notif;
priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl3945_rx_pm_sleep_notif;
priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
iwl3945_rx_pm_debug_statistics_notif;
iwl_rx_pm_debug_statistics_notif;
priv->rx_handlers[BEACON_NOTIFICATION] = iwl3945_rx_beacon_notif;
/*
@ -1707,12 +1448,8 @@ static void iwl3945_setup_rx_handlers(struct iwl_priv *priv)
priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_hw_rx_statistics;
priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics;
priv->rx_handlers[REPLY_SCAN_CMD] = iwl3945_rx_reply_scan;
priv->rx_handlers[SCAN_START_NOTIFICATION] = iwl3945_rx_scan_start_notif;
priv->rx_handlers[SCAN_RESULTS_NOTIFICATION] =
iwl3945_rx_scan_results_notif;
priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] =
iwl3945_rx_scan_complete_notif;
iwl_setup_spectrum_handlers(priv);
iwl_setup_rx_scan_handlers(priv);
priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif;
/* Set up hardware specific Rx handlers */
@ -2195,14 +1932,6 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
iwl3945_rx_queue_restock(priv);
}
static void iwl3945_enable_interrupts(struct iwl_priv *priv)
{
IWL_DEBUG_ISR(priv, "Enabling interrupts\n");
set_bit(STATUS_INT_ENABLED, &priv->status);
iwl_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
}
/* call this function to flush any scheduled tasklet */
static inline void iwl_synchronize_irq(struct iwl_priv *priv)
{
@ -2211,21 +1940,6 @@ static inline void iwl_synchronize_irq(struct iwl_priv *priv)
tasklet_kill(&priv->irq_tasklet);
}
static inline void iwl3945_disable_interrupts(struct iwl_priv *priv)
{
clear_bit(STATUS_INT_ENABLED, &priv->status);
/* disable interrupts from uCode/NIC to host */
iwl_write32(priv, CSR_INT_MASK, 0x00000000);
/* acknowledge/clear/reset any interrupts still pending
* from uCode or flow handler (Rx/Tx DMA) */
iwl_write32(priv, CSR_INT, 0xffffffff);
iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
IWL_DEBUG_ISR(priv, "Disabled interrupts\n");
}
static const char *desc_lookup(int i)
{
switch (i) {
@ -2467,7 +2181,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
IWL_ERR(priv, "Microcode HW error detected. Restarting.\n");
/* Tell the device to stop sending interrupts */
iwl3945_disable_interrupts(priv);
iwl_disable_interrupts(priv);
iwl_irq_handle_error(priv);
@ -2547,7 +2261,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
/* Re-enable all interrupts */
/* only Re-enable if disabled by irq */
if (test_bit(STATUS_INT_ENABLED, &priv->status))
iwl3945_enable_interrupts(priv);
iwl_enable_interrupts(priv);
#ifdef CONFIG_IWLWIFI_DEBUG
if (priv->debug_level & (IWL_DL_ISR)) {
@ -2561,63 +2275,6 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);
}
static irqreturn_t iwl3945_isr(int irq, void *data)
{
struct iwl_priv *priv = data;
u32 inta, inta_mask;
u32 inta_fh;
if (!priv)
return IRQ_NONE;
spin_lock(&priv->lock);
/* Disable (but don't clear!) interrupts here to avoid
* back-to-back ISRs and sporadic interrupts from our NIC.
* If we have something to service, the tasklet will re-enable ints.
* If we *don't* have something, we'll re-enable before leaving here. */
inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
iwl_write32(priv, CSR_INT_MASK, 0x00000000);
/* Discover which interrupts are active/pending */
inta = iwl_read32(priv, CSR_INT);
inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
/* Ignore interrupt if there's nothing in NIC to service.
* This may be due to IRQ shared with another device,
* or due to sporadic interrupts thrown from our NIC. */
if (!inta && !inta_fh) {
IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0, inta_fh == 0\n");
goto none;
}
if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
/* Hardware disappeared */
IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
goto unplugged;
}
IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
inta, inta_mask, inta_fh);
inta &= ~CSR_INT_BIT_SCD;
/* iwl3945_irq_tasklet() will service interrupts and re-enable them */
if (likely(inta || inta_fh))
tasklet_schedule(&priv->irq_tasklet);
unplugged:
spin_unlock(&priv->lock);
return IRQ_HANDLED;
none:
/* re-enable interrupts here since we don't have anything to service. */
/* only Re-enable if disabled by irq */
if (test_bit(STATUS_INT_ENABLED, &priv->status))
iwl3945_enable_interrupts(priv);
spin_unlock(&priv->lock);
return IRQ_NONE;
}
static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
enum ieee80211_band band,
u8 is_active, u8 n_probes,
@ -3387,7 +3044,7 @@ static void __iwl3945_down(struct iwl_priv *priv)
/* tell the device to stop sending interrupts */
spin_lock_irqsave(&priv->lock, flags);
iwl3945_disable_interrupts(priv);
iwl_disable_interrupts(priv);
spin_unlock_irqrestore(&priv->lock, flags);
iwl_synchronize_irq(priv);
@ -3517,7 +3174,7 @@ static int __iwl3945_up(struct iwl_priv *priv)
/* clear (again), then enable host interrupts */
iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
iwl3945_enable_interrupts(priv);
iwl_enable_interrupts(priv);
/* really make sure rfkill handshake bits are cleared */
iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
@ -4172,9 +3829,13 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed)
}
#endif
iwl3945_radio_kill_sw(priv, !conf->radio_enabled);
if (conf->radio_enabled && iwl_radio_kill_sw_enable_radio(priv)) {
IWL_DEBUG_MAC80211(priv, "leave - RF-KILL - waiting for uCode\n");
goto out;
}
if (!conf->radio_enabled) {
iwl_radio_kill_sw_disable_radio(priv);
IWL_DEBUG_MAC80211(priv, "leave - radio disabled\n");
goto out;
}
@ -4442,66 +4103,6 @@ static void iwl3945_bss_info_changed(struct ieee80211_hw *hw,
}
static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw,
struct cfg80211_scan_request *req)
{
int rc = 0;
unsigned long flags;
struct iwl_priv *priv = hw->priv;
size_t len = 0;
u8 *ssid = NULL;
DECLARE_SSID_BUF(ssid_buf);
IWL_DEBUG_MAC80211(priv, "enter\n");
if (req->n_ssids) {
ssid = req->ssids[0].ssid;
len = req->ssids[0].ssid_len;
}
mutex_lock(&priv->mutex);
spin_lock_irqsave(&priv->lock, flags);
if (!iwl_is_ready_rf(priv)) {
rc = -EIO;
IWL_DEBUG_MAC80211(priv, "leave - not ready or exit pending\n");
goto out_unlock;
}
/* we don't schedule scan within next_scan_jiffies period */
if (priv->next_scan_jiffies &&
time_after(priv->next_scan_jiffies, jiffies)) {
rc = -EAGAIN;
goto out_unlock;
}
/* if we just finished scan ask for delay for a broadcast scan */
if ((len == 0) && priv->last_scan_jiffies &&
time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN,
jiffies)) {
rc = -EAGAIN;
goto out_unlock;
}
if (len) {
IWL_DEBUG_SCAN(priv, "direct scan for %s [%zd]\n ",
print_ssid(ssid_buf, ssid, len), len);
priv->one_direct_scan = 1;
priv->direct_ssid_len = len;
memcpy(priv->direct_ssid, ssid, len);
} else
priv->one_direct_scan = 0;
rc = iwl3945_scan_initiate(priv);
IWL_DEBUG_MAC80211(priv, "leave\n");
out_unlock:
spin_unlock_irqrestore(&priv->lock, flags);
mutex_unlock(&priv->mutex);
return rc;
}
static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@ -5201,7 +4802,7 @@ static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log);
static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
{
priv->workqueue = create_workqueue(DRV_NAME);
priv->workqueue = create_singlethread_workqueue(DRV_NAME);
init_waitqueue_head(&priv->wait_command_queue);
@ -5275,7 +4876,7 @@ static struct ieee80211_ops iwl3945_hw_ops = {
.conf_tx = iwl3945_mac_conf_tx,
.reset_tsf = iwl3945_mac_reset_tsf,
.bss_info_changed = iwl3945_bss_info_changed,
.hw_scan = iwl3945_mac_hw_scan
.hw_scan = iwl_mac_hw_scan
};
static int iwl3945_init_drv(struct iwl_priv *priv)
@ -5526,12 +5127,12 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
* ********************/
spin_lock_irqsave(&priv->lock, flags);
iwl3945_disable_interrupts(priv);
iwl_disable_interrupts(priv);
spin_unlock_irqrestore(&priv->lock, flags);
pci_enable_msi(priv->pci_dev);
err = request_irq(priv->pci_dev->irq, iwl3945_isr, IRQF_SHARED,
err = request_irq(priv->pci_dev->irq, iwl_isr, IRQF_SHARED,
DRV_NAME, priv);
if (err) {
IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
@ -5621,7 +5222,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
* tasklet for the driver
*/
spin_lock_irqsave(&priv->lock, flags);
iwl3945_disable_interrupts(priv);
iwl_disable_interrupts(priv);
spin_unlock_irqrestore(&priv->lock, flags);
iwl_synchronize_irq(priv);

View file

@ -265,6 +265,7 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
#define CMD_F_HOSTCMD (1 << 0)
#define FW_CAPINFO_WPA (1 << 0)
#define FW_CAPINFO_PS (1 << 1)
#define FW_CAPINFO_FIRMWARE_UPGRADE (1 << 13)
#define FW_CAPINFO_BOOT2_UPGRADE (1<<14)
#define FW_CAPINFO_PERSISTENT_CONFIG (1<<15)

View file

@ -95,6 +95,8 @@ struct if_sdio_card {
spinlock_t lock;
struct if_sdio_packet *packets;
struct workqueue_struct *workqueue;
struct work_struct packet_worker;
};
@ -209,6 +211,9 @@ static int if_sdio_handle_event(struct if_sdio_card *card,
event = sdio_readb(card->func, IF_SDIO_EVENT, &ret);
if (ret)
goto out;
/* right shift 3 bits to get the event id */
event >>= 3;
} else {
if (size < 4) {
lbs_deb_sdio("event packet too small (%d bytes)\n",
@ -743,7 +748,7 @@ static int if_sdio_host_to_card(struct lbs_private *priv,
spin_unlock_irqrestore(&card->lock, flags);
schedule_work(&card->packet_worker);
queue_work(card->workqueue, &card->packet_worker);
ret = 0;
@ -833,6 +838,7 @@ static int if_sdio_probe(struct sdio_func *func,
card->func = func;
card->model = model;
spin_lock_init(&card->lock);
card->workqueue = create_workqueue("libertas_sdio");
INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker);
for (i = 0;i < ARRAY_SIZE(if_sdio_models);i++) {
@ -921,15 +927,17 @@ static int if_sdio_probe(struct sdio_func *func,
if (ret)
goto err_activate_card;
if (priv->fwcapinfo & FW_CAPINFO_PS)
priv->ps_supported = 1;
out:
lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
return ret;
err_activate_card:
flush_scheduled_work();
free_netdev(priv->dev);
kfree(priv);
flush_workqueue(card->workqueue);
lbs_remove_card(priv);
reclaim:
sdio_claim_host(func);
release_int:
@ -939,6 +947,7 @@ disable:
release:
sdio_release_host(func);
free:
destroy_workqueue(card->workqueue);
while (card->packets) {
packet = card->packets;
card->packets = card->packets->next;
@ -965,7 +974,8 @@ static void if_sdio_remove(struct sdio_func *func)
lbs_stop_card(card->priv);
lbs_remove_card(card->priv);
flush_scheduled_work();
flush_workqueue(card->workqueue);
destroy_workqueue(card->workqueue);
sdio_claim_host(func);
sdio_release_irq(func);

View file

@ -43,6 +43,33 @@ struct orinoco_fw_header {
char signature[0]; /* FW signature length headersize-20 */
} __attribute__ ((packed));
/* Check the range of various header entries. Return a pointer to a
* description of the problem, or NULL if everything checks out. */
static const char *validate_fw(const struct orinoco_fw_header *hdr, size_t len)
{
u16 hdrsize;
if (len < sizeof(*hdr))
return "image too small";
if (memcmp(hdr->hdr_vers, "HFW", 3) != 0)
return "format not recognised";
hdrsize = le16_to_cpu(hdr->headersize);
if (hdrsize > len)
return "bad headersize";
if ((hdrsize + le32_to_cpu(hdr->block_offset)) > len)
return "bad block offset";
if ((hdrsize + le32_to_cpu(hdr->pdr_offset)) > len)
return "bad PDR offset";
if ((hdrsize + le32_to_cpu(hdr->pri_offset)) > len)
return "bad PRI offset";
if ((hdrsize + le32_to_cpu(hdr->compat_offset)) > len)
return "bad compat offset";
/* TODO: consider adding a checksum or CRC to the firmware format */
return NULL;
}
/* Download either STA or AP firmware into the card. */
static int
orinoco_dl_firmware(struct orinoco_private *priv,
@ -56,8 +83,9 @@ orinoco_dl_firmware(struct orinoco_private *priv,
const struct firmware *fw_entry;
const struct orinoco_fw_header *hdr;
const unsigned char *first_block;
const unsigned char *end;
const void *end;
const char *firmware;
const char *fw_err;
struct net_device *dev = priv->ndev;
int err = 0;
@ -93,6 +121,15 @@ orinoco_dl_firmware(struct orinoco_private *priv,
hdr = (const struct orinoco_fw_header *) fw_entry->data;
fw_err = validate_fw(hdr, fw_entry->size);
if (fw_err) {
printk(KERN_WARNING "%s: Invalid firmware image detected (%s). "
"Aborting download\n",
dev->name, fw_err);
err = -EINVAL;
goto abort;
}
/* Enable aux port to allow programming */
err = hermesi_program_init(hw, le32_to_cpu(hdr->entry_point));
printk(KERN_DEBUG "%s: Program init returned %d\n", dev->name, err);
@ -115,7 +152,8 @@ orinoco_dl_firmware(struct orinoco_private *priv,
le16_to_cpu(hdr->headersize) +
le32_to_cpu(hdr->pdr_offset));
err = hermes_apply_pda_with_defaults(hw, first_block, pda);
err = hermes_apply_pda_with_defaults(hw, first_block, end, pda,
&pda[fw->pda_size / sizeof(*pda)]);
printk(KERN_DEBUG "%s: Apply PDA returned %d\n", dev->name, err);
if (err)
goto abort;
@ -147,7 +185,7 @@ free:
*/
static int
symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
const unsigned char *image, const unsigned char *end,
const unsigned char *image, const void *end,
int secondary)
{
hermes_t *hw = &priv->hw;
@ -188,9 +226,10 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
/* Write the PDA to the adapter */
if (secondary) {
size_t len = hermes_blocks_length(first_block);
size_t len = hermes_blocks_length(first_block, end);
ptr = first_block + len;
ret = hermes_apply_pda(hw, ptr, pda);
ret = hermes_apply_pda(hw, ptr, end, pda,
&pda[fw->pda_size / sizeof(*pda)]);
kfree(pda);
if (ret)
return ret;

View file

@ -71,18 +71,6 @@
#define BLOCK_END 0xFFFFFFFF /* Last image block */
#define TEXT_END 0x1A /* End of text header */
/*
* PDA == Production Data Area
*
* In principle, the max. size of the PDA is is 4096 words. Currently,
* however, only about 500 bytes of this area are used.
*
* Some USB implementations can't handle sizes in excess of 1016. Note
* that PDA is not actually used in those USB environments, but may be
* retrieved by common code.
*/
#define MAX_PDA_SIZE 1000
/* Limit the amout we try to download in a single shot.
* Size is in bytes.
*/
@ -218,13 +206,14 @@ hermes_aux_control(hermes_t *hw, int enabled)
* Scan PDR for the record with the specified RECORD_ID.
* If it's not found, return NULL.
*/
static struct pdr *
hermes_find_pdr(struct pdr *first_pdr, u32 record_id)
static const struct pdr *
hermes_find_pdr(const struct pdr *first_pdr, u32 record_id, const void *end)
{
struct pdr *pdr = first_pdr;
void *end = (void *)first_pdr + MAX_PDA_SIZE;
const struct pdr *pdr = first_pdr;
while (((void *)pdr < end) &&
end -= sizeof(struct pdr);
while (((void *) pdr <= end) &&
(pdr_id(pdr) != PDI_END)) {
/*
* PDR area is currently not terminated by PDI_END.
@ -244,12 +233,15 @@ hermes_find_pdr(struct pdr *first_pdr, u32 record_id)
}
/* Scan production data items for a particular entry */
static struct pdi *
hermes_find_pdi(struct pdi *first_pdi, u32 record_id)
static const struct pdi *
hermes_find_pdi(const struct pdi *first_pdi, u32 record_id, const void *end)
{
struct pdi *pdi = first_pdi;
const struct pdi *pdi = first_pdi;
while (pdi_id(pdi) != PDI_END) {
end -= sizeof(struct pdi);
while (((void *) pdi <= end) &&
(pdi_id(pdi) != PDI_END)) {
/* If the record ID matches, we are done */
if (pdi_id(pdi) == record_id)
@ -262,12 +254,13 @@ hermes_find_pdi(struct pdi *first_pdi, u32 record_id)
/* Process one Plug Data Item - find corresponding PDR and plug it */
static int
hermes_plug_pdi(hermes_t *hw, struct pdr *first_pdr, const struct pdi *pdi)
hermes_plug_pdi(hermes_t *hw, const struct pdr *first_pdr,
const struct pdi *pdi, const void *pdr_end)
{
struct pdr *pdr;
const struct pdr *pdr;
/* Find the PDR corresponding to this PDI */
pdr = hermes_find_pdr(first_pdr, pdi_id(pdi));
pdr = hermes_find_pdr(first_pdr, pdi_id(pdi), pdr_end);
/* No match is found, safe to ignore */
if (!pdr)
@ -345,18 +338,22 @@ int hermes_read_pda(hermes_t *hw,
*/
int hermes_apply_pda(hermes_t *hw,
const char *first_pdr,
const __le16 *pda)
const void *pdr_end,
const __le16 *pda,
const void *pda_end)
{
int ret;
const struct pdi *pdi;
struct pdr *pdr;
const struct pdr *pdr;
pdr = (struct pdr *) first_pdr;
pdr = (const struct pdr *) first_pdr;
pda_end -= sizeof(struct pdi);
/* Go through every PDI and plug them into the adapter */
pdi = (const struct pdi *) (pda + 2);
while (pdi_id(pdi) != PDI_END) {
ret = hermes_plug_pdi(hw, pdr, pdi);
while (((void *) pdi <= pda_end) &&
(pdi_id(pdi) != PDI_END)) {
ret = hermes_plug_pdi(hw, pdr, pdi, pdr_end);
if (ret)
return ret;
@ -370,15 +367,18 @@ int hermes_apply_pda(hermes_t *hw,
* including the header data.
*/
size_t
hermes_blocks_length(const char *first_block)
hermes_blocks_length(const char *first_block, const void *end)
{
const struct dblock *blk = (const struct dblock *) first_block;
int total_len = 0;
int len;
end -= sizeof(*blk);
/* Skip all blocks to locate Plug Data References
* (Spectrum CS) */
while (dblock_addr(blk) != BLOCK_END) {
while (((void *) blk <= end) &&
(dblock_addr(blk) != BLOCK_END)) {
len = dblock_len(blk);
total_len += sizeof(*blk) + len;
blk = (struct dblock *) &blk->data[len];
@ -476,7 +476,7 @@ int hermesi_program_end(hermes_t *hw)
}
/* Program the data blocks */
int hermes_program(hermes_t *hw, const char *first_block, const char *end)
int hermes_program(hermes_t *hw, const char *first_block, const void *end)
{
const struct dblock *blk;
u32 blkaddr;
@ -488,14 +488,14 @@ int hermes_program(hermes_t *hw, const char *first_block, const char *end)
blk = (const struct dblock *) first_block;
if ((const char *) blk > (end - sizeof(*blk)))
if ((void *) blk > (end - sizeof(*blk)))
return -EIO;
blkaddr = dblock_addr(blk);
blklen = dblock_len(blk);
while ((blkaddr != BLOCK_END) &&
(((const char *) blk + blklen) <= end)) {
(((void *) blk + blklen) <= end)) {
printk(KERN_DEBUG PFX
"Programming block of length %d to address 0x%08x\n",
blklen, blkaddr);
@ -527,7 +527,7 @@ int hermes_program(hermes_t *hw, const char *first_block, const char *end)
#endif
blk = (const struct dblock *) &blk->data[blklen];
if ((const char *) blk > (end - sizeof(*blk)))
if ((void *) blk > (end - sizeof(*blk)))
return -EIO;
blkaddr = dblock_addr(blk);
@ -545,9 +545,9 @@ static const struct { \
__le16 id; \
u8 val[length]; \
} __attribute__ ((packed)) default_pdr_data_##pid = { \
cpu_to_le16((sizeof(default_pdr_data_##pid)/ \
cpu_to_le16((sizeof(default_pdr_data_##pid)/ \
sizeof(__le16)) - 1), \
cpu_to_le16(pid), \
cpu_to_le16(pid), \
data \
}
@ -616,17 +616,20 @@ DEFINE_DEFAULT_PDR(0x0161, 256,
*/
int hermes_apply_pda_with_defaults(hermes_t *hw,
const char *first_pdr,
const __le16 *pda)
const void *pdr_end,
const __le16 *pda,
const void *pda_end)
{
const struct pdr *pdr = (const struct pdr *) first_pdr;
struct pdi *first_pdi = (struct pdi *) &pda[2];
struct pdi *pdi;
struct pdi *default_pdi = NULL;
struct pdi *outdoor_pdi;
void *end = (void *)first_pdr + MAX_PDA_SIZE;
const struct pdi *first_pdi = (const struct pdi *) &pda[2];
const struct pdi *pdi;
const struct pdi *default_pdi = NULL;
const struct pdi *outdoor_pdi;
int record_id;
while (((void *)pdr < end) &&
pdr_end -= sizeof(struct pdr);
while (((void *) pdr <= pdr_end) &&
(pdr_id(pdr) != PDI_END)) {
/*
* For spectrum_cs firmwares,
@ -638,7 +641,7 @@ int hermes_apply_pda_with_defaults(hermes_t *hw,
break;
record_id = pdr_id(pdr);
pdi = hermes_find_pdi(first_pdi, record_id);
pdi = hermes_find_pdi(first_pdi, record_id, pda_end);
if (pdi)
printk(KERN_DEBUG PFX "Found record 0x%04x at %p\n",
record_id, pdi);
@ -646,7 +649,8 @@ int hermes_apply_pda_with_defaults(hermes_t *hw,
switch (record_id) {
case 0x110: /* Modem REFDAC values */
case 0x120: /* Modem VGDAC values */
outdoor_pdi = hermes_find_pdi(first_pdi, record_id + 1);
outdoor_pdi = hermes_find_pdi(first_pdi, record_id + 1,
pda_end);
default_pdi = NULL;
if (outdoor_pdi) {
pdi = outdoor_pdi;
@ -687,7 +691,8 @@ int hermes_apply_pda_with_defaults(hermes_t *hw,
if (pdi) {
/* Lengths of the data in PDI and PDR must match */
if (pdi_len(pdi) == pdr_len(pdr)) {
if ((pdi_len(pdi) == pdr_len(pdr)) &&
((void *) pdi->data + pdi_len(pdi) < pda_end)) {
/* do the actual plugging */
hermes_aux_setaddr(hw, pdr_addr(pdr));
hermes_write_bytes(hw, HERMES_AUXDATA,

View file

@ -29,7 +29,7 @@
int hermesi_program_init(hermes_t *hw, u32 offset);
int hermesi_program_end(hermes_t *hw);
int hermes_program(hermes_t *hw, const char *first_block, const char *end);
int hermes_program(hermes_t *hw, const char *first_block, const void *end);
int hermes_read_pda(hermes_t *hw,
__le16 *pda,
@ -38,11 +38,15 @@ int hermes_read_pda(hermes_t *hw,
int use_eeprom);
int hermes_apply_pda(hermes_t *hw,
const char *first_pdr,
const __le16 *pda);
const void *pdr_end,
const __le16 *pda,
const void *pda_end);
int hermes_apply_pda_with_defaults(hermes_t *hw,
const char *first_pdr,
const __le16 *pda);
const void *pdr_end,
const __le16 *pda,
const void *pda_end);
size_t hermes_blocks_length(const char *first_block);
size_t hermes_blocks_length(const char *first_block, const void *end);
#endif /* _HERMES_DLD_H */

View file

@ -2212,8 +2212,8 @@ static void p54_configure_filter(struct ieee80211_hw *dev,
*total_flags &= FIF_PROMISC_IN_BSS |
FIF_OTHER_BSS |
(*total_flags & FIF_PROMISC_IN_BSS) ?
FIF_FCSFAIL : 0;
(*total_flags & FIF_PROMISC_IN_BSS ?
FIF_FCSFAIL : 0);
priv->filter_flags = *total_flags;

View file

@ -114,9 +114,6 @@ static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
if (!word)
return;
mutex_lock(&rt2x00dev->csr_mutex);
/*

View file

@ -48,8 +48,8 @@
#define EEPROM_SIZE 0x0100
#define BBP_BASE 0x0000
#define BBP_SIZE 0x0020
#define RF_BASE 0x0000
#define RF_SIZE 0x0010
#define RF_BASE 0x0004
#define RF_SIZE 0x000c
/*
* Number of TX queues.

View file

@ -114,9 +114,6 @@ static void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
if (!word)
return;
mutex_lock(&rt2x00dev->csr_mutex);
/*

View file

@ -59,8 +59,8 @@
#define EEPROM_SIZE 0x0200
#define BBP_BASE 0x0000
#define BBP_SIZE 0x0040
#define RF_BASE 0x0000
#define RF_SIZE 0x0014
#define RF_BASE 0x0004
#define RF_SIZE 0x0010
/*
* Number of TX queues.

View file

@ -204,9 +204,6 @@ static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev,
{
u16 reg;
if (!word)
return;
mutex_lock(&rt2x00dev->csr_mutex);
/*

View file

@ -59,8 +59,8 @@
#define EEPROM_SIZE 0x006a
#define BBP_BASE 0x0000
#define BBP_SIZE 0x0060
#define RF_BASE 0x0000
#define RF_SIZE 0x0014
#define RF_BASE 0x0004
#define RF_SIZE 0x0010
/*
* Number of TX queues.

View file

@ -435,11 +435,12 @@ static ssize_t rt2x00debug_read_##__name(struct file *file, \
if (index >= debug->__name.word_count) \
return -EINVAL; \
\
index += (debug->__name.word_base / \
debug->__name.word_size); \
\
if (debug->__name.flags & RT2X00DEBUGFS_OFFSET) \
index *= debug->__name.word_size; \
\
index += debug->__name.word_base; \
\
debug->__name.read(intf->rt2x00dev, index, &value); \
\
size = sprintf(line, __format, value); \
@ -476,11 +477,12 @@ static ssize_t rt2x00debug_write_##__name(struct file *file, \
size = strlen(line); \
value = simple_strtoul(line, NULL, 0); \
\
index += (debug->__name.word_base / \
debug->__name.word_size); \
\
if (debug->__name.flags & RT2X00DEBUGFS_OFFSET) \
index *= debug->__name.word_size; \
\
index += debug->__name.word_base; \
\
debug->__name.write(intf->rt2x00dev, index, value); \
\
*offset += size; \

View file

@ -123,9 +123,6 @@ static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
if (!word)
return;
mutex_lock(&rt2x00dev->csr_mutex);
/*

View file

@ -50,8 +50,8 @@
#define EEPROM_SIZE 0x0100
#define BBP_BASE 0x0000
#define BBP_SIZE 0x0080
#define RF_BASE 0x0000
#define RF_SIZE 0x0014
#define RF_BASE 0x0004
#define RF_SIZE 0x0010
/*
* Number of TX queues.

View file

@ -122,9 +122,6 @@ static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
if (!word)
return;
mutex_lock(&rt2x00dev->csr_mutex);
/*
@ -2241,13 +2238,6 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
return 0;
}
#if 0
/*
* Mac80211 demands get_tsf must be atomic.
* This is not possible for rt73usb since all register access
* functions require sleeping. Untill mac80211 no longer needs
* get_tsf to be atomic, this function should be disabled.
*/
static u64 rt73usb_get_tsf(struct ieee80211_hw *hw)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
@ -2261,9 +2251,6 @@ static u64 rt73usb_get_tsf(struct ieee80211_hw *hw)
return tsf;
}
#else
#define rt73usb_get_tsf NULL
#endif
static const struct ieee80211_ops rt73usb_mac80211_ops = {
.tx = rt2x00mac_tx,
@ -2355,6 +2342,9 @@ static const struct rt2x00_ops rt73usb_ops = {
static struct usb_device_id rt73usb_device_table[] = {
/* AboCom */
{ USB_DEVICE(0x07b8, 0xb21d), USB_DEVICE_DATA(&rt73usb_ops) },
/* Amigo */
{ USB_DEVICE(0x148f, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0eb0, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) },
/* Askey */
{ USB_DEVICE(0x1690, 0x0722), USB_DEVICE_DATA(&rt73usb_ops) },
/* ASUS */
@ -2402,6 +2392,7 @@ static struct usb_device_id rt73usb_device_table[] = {
{ USB_DEVICE(0x0db0, 0xa861), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0db0, 0xa874), USB_DEVICE_DATA(&rt73usb_ops) },
/* Ralink */
{ USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x148f, 0x2671), USB_DEVICE_DATA(&rt73usb_ops) },
/* Qcom */
@ -2418,6 +2409,8 @@ static struct usb_device_id rt73usb_device_table[] = {
/* Planex */
{ USB_DEVICE(0x2019, 0xab01), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x2019, 0xab50), USB_DEVICE_DATA(&rt73usb_ops) },
/* ZyXEL */
{ USB_DEVICE(0x0586, 0x3415), USB_DEVICE_DATA(&rt73usb_ops) },
{ 0, }
};

View file

@ -50,8 +50,8 @@
#define EEPROM_SIZE 0x0100
#define BBP_BASE 0x0000
#define BBP_SIZE 0x0080
#define RF_BASE 0x0000
#define RF_SIZE 0x0014
#define RF_BASE 0x0004
#define RF_SIZE 0x0010
/*
* Number of TX queues.

View file

@ -4281,8 +4281,7 @@ int __init init_module(void)
/* Loop on all possible base addresses. */
i = -1;
while ((io[++i] != 0) && (i < ARRAY_SIZE(io))) {
for (i = 0; i < ARRAY_SIZE(io) && io[i] != 0; i++) {
struct net_device *dev = alloc_etherdev(sizeof(net_local));
if (!dev)
break;

View file

@ -170,10 +170,10 @@ int zd_mac_init_hw(struct ieee80211_hw *hw)
goto disable_int;
r = zd_reg2alpha2(mac->regdomain, alpha2);
if (!r)
regulatory_hint(hw->wiphy, alpha2);
if (r)
goto disable_int;
r = 0;
r = regulatory_hint(hw->wiphy, alpha2);
disable_int:
zd_chip_disable_int(chip);
out:

View file

@ -526,6 +526,9 @@ enum nl80211_rate_info {
* @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
* @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
* containing info as possible, see &enum nl80211_sta_info_txrate.
* @NL80211_STA_INFO_RX_PACKETS: total received packet (u32, from this station)
* @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (u32, to this
* station)
*/
enum nl80211_sta_info {
__NL80211_STA_INFO_INVALID,
@ -537,6 +540,8 @@ enum nl80211_sta_info {
NL80211_STA_INFO_PLINK_STATE,
NL80211_STA_INFO_SIGNAL,
NL80211_STA_INFO_TX_BITRATE,
NL80211_STA_INFO_RX_PACKETS,
NL80211_STA_INFO_TX_PACKETS,
/* keep last */
__NL80211_STA_INFO_AFTER_LAST,

View file

@ -178,6 +178,8 @@ struct station_parameters {
* @STATION_INFO_SIGNAL: @signal filled
* @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled
* (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
* @STATION_INFO_RX_PACKETS: @rx_packets filled
* @STATION_INFO_TX_PACKETS: @tx_packets filled
*/
enum station_info_flags {
STATION_INFO_INACTIVE_TIME = 1<<0,
@ -188,6 +190,8 @@ enum station_info_flags {
STATION_INFO_PLINK_STATE = 1<<5,
STATION_INFO_SIGNAL = 1<<6,
STATION_INFO_TX_BITRATE = 1<<7,
STATION_INFO_RX_PACKETS = 1<<8,
STATION_INFO_TX_PACKETS = 1<<9,
};
/**
@ -235,6 +239,8 @@ struct rate_info {
* @plink_state: mesh peer link state
* @signal: signal strength of last received packet in dBm
* @txrate: current unicast bitrate to this station
* @rx_packets: packets received from this station
* @tx_packets: packets transmitted to this station
*/
struct station_info {
u32 filled;
@ -246,6 +252,8 @@ struct station_info {
u8 plink_state;
s8 signal;
struct rate_info txrate;
u32 rx_packets;
u32 tx_packets;
};
/**
@ -375,9 +383,9 @@ enum environment_cap {
};
/**
* struct regulatory_request - receipt of last regulatory request
* struct regulatory_request - used to keep track of regulatory requests
*
* @wiphy: this is set if this request's initiator is
* @wiphy_idx: this is set if this request's initiator is
* %REGDOM_SET_BY_COUNTRY_IE or %REGDOM_SET_BY_DRIVER. This
* can be used by the wireless core to deal with conflicts
* and potentially inform users of which devices specifically
@ -396,14 +404,16 @@ enum environment_cap {
* country IE
* @country_ie_env: lets us know if the AP is telling us we are outdoor,
* indoor, or if it doesn't matter
* @list: used to insert into the reg_requests_list linked list
*/
struct regulatory_request {
struct wiphy *wiphy;
int wiphy_idx;
enum reg_set_by initiator;
char alpha2[2];
bool intersect;
u32 country_ie_checksum;
enum environment_cap country_ie_env;
struct list_head list;
};
struct ieee80211_freq_range {
@ -525,6 +535,8 @@ struct cfg80211_ssid {
* @n_ssids: number of SSIDs
* @channels: channels to scan on.
* @n_channels: number of channels for each band
* @ie: optional information element(s) to add into Probe Request or %NULL
* @ie_len: length of ie in octets
* @wiphy: the wiphy this was for
* @ifidx: the interface index
*/
@ -533,6 +545,8 @@ struct cfg80211_scan_request {
int n_ssids;
struct ieee80211_channel **channels;
u32 n_channels;
u8 *ie;
size_t ie_len;
/* internal */
struct wiphy *wiphy;
@ -565,8 +579,7 @@ enum cfg80211_signal_type {
* @information_elements: the information elements (Note that there
* is no guarantee that these are well-formed!)
* @len_information_elements: total length of the information elements
* @signal: signal strength value
* @signal_type: signal type
* @signal: signal strength value (type depends on the wiphy's signal_type)
* @free_priv: function pointer to free private data
* @priv: private area for driver use, has at least wiphy->bss_priv_size bytes
*/
@ -581,7 +594,6 @@ struct cfg80211_bss {
size_t len_information_elements;
s32 signal;
enum cfg80211_signal_type signal_type;
void (*free_priv)(struct cfg80211_bss *bss);
u8 priv[0] __attribute__((__aligned__(sizeof(void *))));
@ -755,6 +767,9 @@ int cfg80211_wext_siwscan(struct net_device *dev,
int cfg80211_wext_giwscan(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *data, char *extra);
int cfg80211_wext_giwrange(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *data, char *extra);
/**
* cfg80211_scan_done - notify that scan finished
@ -770,6 +785,7 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted);
*
* @wiphy: the wiphy reporting the BSS
* @bss: the found BSS
* @signal: the signal strength, type depends on the wiphy's signal_type
* @gfp: context flags
*
* This informs cfg80211 that BSS information was found and
@ -779,8 +795,7 @@ struct cfg80211_bss*
cfg80211_inform_bss_frame(struct wiphy *wiphy,
struct ieee80211_channel *channel,
struct ieee80211_mgmt *mgmt, size_t len,
s32 signal, enum cfg80211_signal_type sigtype,
gfp_t gfp);
s32 signal, gfp_t gfp);
struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy,
struct ieee80211_channel *channel,

View file

@ -1022,11 +1022,6 @@ static inline int ieee80211_num_regular_queues(struct ieee80211_hw *hw)
return hw->queues;
}
static inline int ieee80211_num_queues(struct ieee80211_hw *hw)
{
return hw->queues + hw->ampdu_queues;
}
static inline struct ieee80211_rate *
ieee80211_get_tx_rate(const struct ieee80211_hw *hw,
const struct ieee80211_tx_info *c)
@ -1329,6 +1324,12 @@ enum ieee80211_ampdu_mlme_action {
* because the hardware is turned off! Anything else is a bug!
* Returns a negative error code which will be seen in userspace.
*
* @sw_scan_start: Notifier function that is called just before a software scan
* is started. Can be NULL, if the driver doesn't need this notification.
*
* @sw_scan_complete: Notifier function that is called just after a software scan
* finished. Can be NULL, if the driver doesn't need this notification.
*
* @get_stats: Return low-level statistics.
* Returns zero if statistics are available.
*
@ -1408,6 +1409,8 @@ struct ieee80211_ops {
u32 iv32, u16 *phase1key);
int (*hw_scan)(struct ieee80211_hw *hw,
struct cfg80211_scan_request *req);
void (*sw_scan_start)(struct ieee80211_hw *hw);
void (*sw_scan_complete)(struct ieee80211_hw *hw);
int (*get_stats)(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats);
void (*get_tkip_seq)(struct ieee80211_hw *hw, u8 hw_key_idx,
@ -1979,6 +1982,16 @@ struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw,
/* Rate control API */
/**
* enum rate_control_changed - flags to indicate which parameter changed
*
* @IEEE80211_RC_HT_CHANGED: The HT parameters of the operating channel have
* changed, rate control algorithm can update its internal state if needed.
*/
enum rate_control_changed {
IEEE80211_RC_HT_CHANGED = BIT(0)
};
/**
* struct ieee80211_tx_rate_control - rate control information for/from RC algo
*
@ -2015,6 +2028,9 @@ struct rate_control_ops {
void *(*alloc_sta)(void *priv, struct ieee80211_sta *sta, gfp_t gfp);
void (*rate_init)(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta);
void (*rate_update)(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta,
void *priv_sta, u32 changed);
void (*free_sta)(void *priv, struct ieee80211_sta *sta,
void *priv_sta);

View file

@ -69,6 +69,9 @@ enum ieee80211_channel_flags {
* @band: band this channel belongs to.
* @max_antenna_gain: maximum antenna gain in dBi
* @max_power: maximum transmission power (in dBm)
* @beacon_found: helper to regulatory code to indicate when a beacon
* has been found on this channel. Use regulatory_hint_found_beacon()
* to enable this, this is is useful only on 5 GHz band.
* @orig_mag: internal use
* @orig_mpwr: internal use
*/
@ -80,6 +83,7 @@ struct ieee80211_channel {
u32 flags;
int max_antenna_gain;
int max_power;
bool beacon_found;
u32 orig_flags;
int orig_mag, orig_mpwr;
};
@ -200,6 +204,7 @@ struct ieee80211_supported_band {
* the regulatory_hint() API. This can be used by the driver
* on the reg_notifier() if it chooses to ignore future
* regulatory domain changes caused by other drivers.
* @signal_type: signal type reported in &struct cfg80211_bss.
*/
struct wiphy {
/* assign these fields before you register the wiphy */
@ -213,6 +218,8 @@ struct wiphy {
bool custom_regulatory;
bool strict_regulatory;
enum cfg80211_signal_type signal_type;
int bss_priv_size;
u8 max_scan_ssids;
@ -398,8 +405,15 @@ ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
* domain should be in or by providing a completely build regulatory domain.
* If the driver provides an ISO/IEC 3166 alpha2 userspace will be queried
* for a regulatory domain structure for the respective country.
*
* The wiphy must have been registered to cfg80211 prior to this call.
* For cfg80211 drivers this means you must first use wiphy_register(),
* for mac80211 drivers you must first use ieee80211_register_hw().
*
* Drivers should check the return value, its possible you can get
* an -ENOMEM.
*/
extern void regulatory_hint(struct wiphy *wiphy, const char *alpha2);
extern int regulatory_hint(struct wiphy *wiphy, const char *alpha2);
/**
* regulatory_hint_11d - hints a country IE as a regulatory domain
@ -415,7 +429,6 @@ extern void regulatory_hint(struct wiphy *wiphy, const char *alpha2);
extern void regulatory_hint_11d(struct wiphy *wiphy,
u8 *country_ie,
u8 country_ie_len);
/**
* wiphy_apply_custom_regulatory - apply a custom driver regulatory domain
* @wiphy: the wireless device we want to process the regulatory domain on

View file

@ -9,6 +9,7 @@ mac80211-y := \
wpa.o \
scan.o \
ht.o agg-tx.o agg-rx.o \
ibss.o \
mlme.o \
iface.o \
rate.o \

View file

@ -129,7 +129,6 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d
u8 dialog_token, u16 status, u16 policy,
u16 buf_size, u16 timeout)
{
struct ieee80211_if_sta *ifsta = &sdata->u.sta;
struct ieee80211_local *local = sdata->local;
struct sk_buff *skb;
struct ieee80211_mgmt *mgmt;
@ -151,8 +150,9 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d
if (sdata->vif.type == NL80211_IFTYPE_AP ||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
else
memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
else if (sdata->vif.type == NL80211_IFTYPE_STATION)
memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);

View file

@ -49,7 +49,6 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
u16 agg_size, u16 timeout)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_sta *ifsta = &sdata->u.sta;
struct sk_buff *skb;
struct ieee80211_mgmt *mgmt;
u16 capab;
@ -69,8 +68,8 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
if (sdata->vif.type == NL80211_IFTYPE_AP ||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
else
memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
else if (sdata->vif.type == NL80211_IFTYPE_STATION)
memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
@ -132,9 +131,24 @@ static int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
state = &sta->ampdu_mlme.tid_state_tx[tid];
if (local->hw.ampdu_queues)
ieee80211_stop_queue(&local->hw, sta->tid_to_tx_q[tid]);
if (local->hw.ampdu_queues) {
if (initiator) {
/*
* Stop the AC queue to avoid issues where we send
* unaggregated frames already before the delba.
*/
ieee80211_stop_queue_by_reason(&local->hw,
local->hw.queues + sta->tid_to_tx_q[tid],
IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
}
/*
* Pretend the driver woke the queue, just in case
* it disabled it before the session was stopped.
*/
ieee80211_wake_queue(
&local->hw, local->hw.queues + sta->tid_to_tx_q[tid]);
}
*state = HT_AGG_STATE_REQ_STOP_BA_MSK |
(initiator << HT_AGG_STATE_INITIATOR_SHIFT);
@ -144,8 +158,6 @@ static int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
/* HW shall not deny going back to legacy */
if (WARN_ON(ret)) {
*state = HT_AGG_STATE_OPERATIONAL;
if (local->hw.ampdu_queues)
ieee80211_wake_queue(&local->hw, sta->tid_to_tx_q[tid]);
}
return ret;
@ -189,14 +201,19 @@ static void sta_addba_resp_timer_expired(unsigned long data)
spin_unlock_bh(&sta->lock);
}
static inline int ieee80211_ac_from_tid(int tid)
{
return ieee802_1d_to_ac[tid & 7];
}
int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
{
struct ieee80211_local *local = hw_to_local(hw);
struct sta_info *sta;
struct ieee80211_sub_if_data *sdata;
u16 start_seq_num;
u8 *state;
int ret = 0;
int i, qn = -1, ret = 0;
u16 start_seq_num;
if (WARN_ON(!local->ops->ampdu_action))
return -EINVAL;
@ -209,6 +226,13 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
ra, tid);
#endif /* CONFIG_MAC80211_HT_DEBUG */
if (hw->ampdu_queues && ieee80211_ac_from_tid(tid) == 0) {
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "rejecting on voice AC\n");
#endif
return -EINVAL;
}
rcu_read_lock();
sta = sta_info_get(local, ra);
@ -217,7 +241,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
printk(KERN_DEBUG "Could not find the station\n");
#endif
ret = -ENOENT;
goto exit;
goto unlock;
}
/*
@ -230,11 +254,13 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
sta->sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
sta->sdata->vif.type != NL80211_IFTYPE_AP) {
ret = -EINVAL;
goto exit;
goto unlock;
}
spin_lock_bh(&sta->lock);
sdata = sta->sdata;
/* we have tried too many times, receiver does not want A-MPDU */
if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) {
ret = -EBUSY;
@ -252,6 +278,42 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
goto err_unlock_sta;
}
if (hw->ampdu_queues) {
spin_lock(&local->queue_stop_reason_lock);
/* reserve a new queue for this session */
for (i = 0; i < local->hw.ampdu_queues; i++) {
if (local->ampdu_ac_queue[i] < 0) {
qn = i;
local->ampdu_ac_queue[qn] =
ieee80211_ac_from_tid(tid);
break;
}
}
spin_unlock(&local->queue_stop_reason_lock);
if (qn < 0) {
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "BA request denied - "
"queue unavailable for tid %d\n", tid);
#endif /* CONFIG_MAC80211_HT_DEBUG */
ret = -ENOSPC;
goto err_unlock_sta;
}
/*
* If we successfully allocate the session, we can't have
* anything going on on the queue this TID maps into, so
* stop it for now. This is a "virtual" stop using the same
* mechanism that drivers will use.
*
* XXX: queue up frames for this session in the sta_info
* struct instead to avoid hitting all other STAs.
*/
ieee80211_stop_queue_by_reason(
&local->hw, hw->queues + qn,
IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
}
/* prepare A-MPDU MLME for Tx aggregation */
sta->ampdu_mlme.tid_tx[tid] =
kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC);
@ -262,8 +324,9 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
tid);
#endif
ret = -ENOMEM;
goto err_unlock_sta;
goto err_return_queue;
}
/* Tx timer */
sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function =
sta_addba_resp_timer_expired;
@ -271,49 +334,25 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
(unsigned long)&sta->timer_to_tid[tid];
init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
if (hw->ampdu_queues) {
/* create a new queue for this aggregation */
ret = ieee80211_ht_agg_queue_add(local, sta, tid);
/* case no queue is available to aggregation
* don't switch to aggregation */
if (ret) {
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "BA request denied - "
"queue unavailable for tid %d\n", tid);
#endif /* CONFIG_MAC80211_HT_DEBUG */
goto err_unlock_queue;
}
}
sdata = sta->sdata;
/* Ok, the Addba frame hasn't been sent yet, but if the driver calls the
* call back right away, it must see that the flow has begun */
*state |= HT_ADDBA_REQUESTED_MSK;
/* This is slightly racy because the queue isn't stopped */
start_seq_num = sta->tid_seq[tid];
ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START,
&sta->sta, tid, &start_seq_num);
if (ret) {
/* No need to requeue the packets in the agg queue, since we
* held the tx lock: no packet could be enqueued to the newly
* allocated queue */
if (hw->ampdu_queues)
ieee80211_ht_agg_queue_remove(local, sta, tid, 0);
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "BA request denied - HW unavailable for"
" tid %d\n", tid);
#endif /* CONFIG_MAC80211_HT_DEBUG */
*state = HT_AGG_STATE_IDLE;
goto err_unlock_queue;
goto err_free;
}
sta->tid_to_tx_q[tid] = qn;
/* Will put all the packets in the new SW queue */
if (hw->ampdu_queues)
ieee80211_requeue(local, ieee802_1d_to_ac[tid]);
spin_unlock_bh(&sta->lock);
/* send an addBA request */
@ -322,7 +361,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
sta->ampdu_mlme.dialog_token_allocator;
sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num;
ieee80211_send_addba_request(sta->sdata, ra, tid,
sta->ampdu_mlme.tid_tx[tid]->dialog_token,
sta->ampdu_mlme.tid_tx[tid]->ssn,
@ -334,15 +372,24 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid);
#endif
goto exit;
goto unlock;
err_unlock_queue:
err_free:
kfree(sta->ampdu_mlme.tid_tx[tid]);
sta->ampdu_mlme.tid_tx[tid] = NULL;
ret = -EBUSY;
err_unlock_sta:
err_return_queue:
if (qn >= 0) {
/* We failed, so start queue again right away. */
ieee80211_wake_queue_by_reason(hw, hw->queues + qn,
IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
/* give queue back to pool */
spin_lock(&local->queue_stop_reason_lock);
local->ampdu_ac_queue[qn] = -1;
spin_unlock(&local->queue_stop_reason_lock);
}
err_unlock_sta:
spin_unlock_bh(&sta->lock);
exit:
unlock:
rcu_read_unlock();
return ret;
}
@ -375,7 +422,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
state = &sta->ampdu_mlme.tid_state_tx[tid];
spin_lock_bh(&sta->lock);
if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
if (WARN_ON(!(*state & HT_ADDBA_REQUESTED_MSK))) {
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "addBA was not requested yet, state is %d\n",
*state);
@ -385,7 +432,8 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
return;
}
WARN_ON_ONCE(*state & HT_ADDBA_DRV_READY_MSK);
if (WARN_ON(*state & HT_ADDBA_DRV_READY_MSK))
goto out;
*state |= HT_ADDBA_DRV_READY_MSK;
@ -393,9 +441,18 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid);
#endif
if (hw->ampdu_queues)
ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
if (hw->ampdu_queues) {
/*
* Wake up this queue, we stopped it earlier,
* this will in turn wake the entire AC.
*/
ieee80211_wake_queue_by_reason(hw,
hw->queues + sta->tid_to_tx_q[tid],
IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
}
}
out:
spin_unlock_bh(&sta->lock);
rcu_read_unlock();
}
@ -485,7 +542,6 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
struct ieee80211_local *local = hw_to_local(hw);
struct sta_info *sta;
u8 *state;
int agg_queue;
if (tid >= STA_TID_NUM) {
#ifdef CONFIG_MAC80211_HT_DEBUG
@ -527,19 +583,19 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
ieee80211_send_delba(sta->sdata, ra, tid,
WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
if (hw->ampdu_queues) {
agg_queue = sta->tid_to_tx_q[tid];
ieee80211_ht_agg_queue_remove(local, sta, tid, 1);
/* We just requeued the all the frames that were in the
* removed queue, and since we might miss a softirq we do
* netif_schedule_queue. ieee80211_wake_queue is not used
* here as this queue is not necessarily stopped
*/
netif_schedule_queue(netdev_get_tx_queue(local->mdev,
agg_queue));
}
spin_lock_bh(&sta->lock);
if (*state & HT_AGG_STATE_INITIATOR_MSK &&
hw->ampdu_queues) {
/*
* Wake up this queue, we stopped it earlier,
* this will in turn wake the entire AC.
*/
ieee80211_wake_queue_by_reason(hw,
hw->queues + sta->tid_to_tx_q[tid],
IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
}
*state = HT_AGG_STATE_IDLE;
sta->ampdu_mlme.addba_req_num[tid] = 0;
kfree(sta->ampdu_mlme.tid_tx[tid]);
@ -613,12 +669,21 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
#endif /* CONFIG_MAC80211_HT_DEBUG */
if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
== WLAN_STATUS_SUCCESS) {
*state |= HT_ADDBA_RECEIVED_MSK;
sta->ampdu_mlme.addba_req_num[tid] = 0;
u8 curstate = *state;
if (*state == HT_AGG_STATE_OPERATIONAL &&
local->hw.ampdu_queues)
ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
*state |= HT_ADDBA_RECEIVED_MSK;
if (hw->ampdu_queues && *state != curstate &&
*state == HT_AGG_STATE_OPERATIONAL) {
/*
* Wake up this queue, we stopped it earlier,
* this will in turn wake the entire AC.
*/
ieee80211_wake_queue_by_reason(hw,
hw->queues + sta->tid_to_tx_q[tid],
IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
}
sta->ampdu_mlme.addba_req_num[tid] = 0;
if (local->ops->ampdu_action) {
(void)local->ops->ampdu_action(hw,

View file

@ -341,11 +341,15 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
sinfo->filled = STATION_INFO_INACTIVE_TIME |
STATION_INFO_RX_BYTES |
STATION_INFO_TX_BYTES |
STATION_INFO_RX_PACKETS |
STATION_INFO_TX_PACKETS |
STATION_INFO_TX_BITRATE;
sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
sinfo->rx_bytes = sta->rx_bytes;
sinfo->tx_bytes = sta->tx_bytes;
sinfo->rx_packets = sta->rx_packets;
sinfo->tx_packets = sta->tx_packets;
if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
sinfo->filled |= STATION_INFO_SIGNAL;
@ -1180,45 +1184,45 @@ static int set_mgmt_extra_ie_sta(struct ieee80211_sub_if_data *sdata,
u8 subtype, u8 *ies, size_t ies_len)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_sta *ifsta = &sdata->u.sta;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
switch (subtype) {
case IEEE80211_STYPE_PROBE_REQ >> 4:
if (local->ops->hw_scan)
break;
kfree(ifsta->ie_probereq);
ifsta->ie_probereq = ies;
ifsta->ie_probereq_len = ies_len;
kfree(ifmgd->ie_probereq);
ifmgd->ie_probereq = ies;
ifmgd->ie_probereq_len = ies_len;
return 0;
case IEEE80211_STYPE_PROBE_RESP >> 4:
kfree(ifsta->ie_proberesp);
ifsta->ie_proberesp = ies;
ifsta->ie_proberesp_len = ies_len;
kfree(ifmgd->ie_proberesp);
ifmgd->ie_proberesp = ies;
ifmgd->ie_proberesp_len = ies_len;
return 0;
case IEEE80211_STYPE_AUTH >> 4:
kfree(ifsta->ie_auth);
ifsta->ie_auth = ies;
ifsta->ie_auth_len = ies_len;
kfree(ifmgd->ie_auth);
ifmgd->ie_auth = ies;
ifmgd->ie_auth_len = ies_len;
return 0;
case IEEE80211_STYPE_ASSOC_REQ >> 4:
kfree(ifsta->ie_assocreq);
ifsta->ie_assocreq = ies;
ifsta->ie_assocreq_len = ies_len;
kfree(ifmgd->ie_assocreq);
ifmgd->ie_assocreq = ies;
ifmgd->ie_assocreq_len = ies_len;
return 0;
case IEEE80211_STYPE_REASSOC_REQ >> 4:
kfree(ifsta->ie_reassocreq);
ifsta->ie_reassocreq = ies;
ifsta->ie_reassocreq_len = ies_len;
kfree(ifmgd->ie_reassocreq);
ifmgd->ie_reassocreq = ies;
ifmgd->ie_reassocreq_len = ies_len;
return 0;
case IEEE80211_STYPE_DEAUTH >> 4:
kfree(ifsta->ie_deauth);
ifsta->ie_deauth = ies;
ifsta->ie_deauth_len = ies_len;
kfree(ifmgd->ie_deauth);
ifmgd->ie_deauth = ies;
ifmgd->ie_deauth_len = ies_len;
return 0;
case IEEE80211_STYPE_DISASSOC >> 4:
kfree(ifsta->ie_disassoc);
ifsta->ie_disassoc = ies;
ifsta->ie_disassoc_len = ies_len;
kfree(ifmgd->ie_disassoc);
ifmgd->ie_disassoc = ies;
ifmgd->ie_disassoc_len = ies_len;
return 0;
}
@ -1248,7 +1252,6 @@ static int ieee80211_set_mgmt_extra_ie(struct wiphy *wiphy,
switch (sdata->vif.type) {
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
ret = set_mgmt_extra_ie_sta(sdata, params->subtype,
ies, ies_len);
break;

View file

@ -94,31 +94,31 @@ IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
IEEE80211_IF_FILE(force_unicast_rateidx, force_unicast_rateidx, DEC);
IEEE80211_IF_FILE(max_ratectrl_rateidx, max_ratectrl_rateidx, DEC);
/* STA/IBSS attributes */
IEEE80211_IF_FILE(state, u.sta.state, DEC);
IEEE80211_IF_FILE(bssid, u.sta.bssid, MAC);
IEEE80211_IF_FILE(prev_bssid, u.sta.prev_bssid, MAC);
IEEE80211_IF_FILE(ssid_len, u.sta.ssid_len, SIZE);
IEEE80211_IF_FILE(aid, u.sta.aid, DEC);
IEEE80211_IF_FILE(ap_capab, u.sta.ap_capab, HEX);
IEEE80211_IF_FILE(capab, u.sta.capab, HEX);
IEEE80211_IF_FILE(extra_ie_len, u.sta.extra_ie_len, SIZE);
IEEE80211_IF_FILE(auth_tries, u.sta.auth_tries, DEC);
IEEE80211_IF_FILE(assoc_tries, u.sta.assoc_tries, DEC);
IEEE80211_IF_FILE(auth_algs, u.sta.auth_algs, HEX);
IEEE80211_IF_FILE(auth_alg, u.sta.auth_alg, DEC);
IEEE80211_IF_FILE(auth_transaction, u.sta.auth_transaction, DEC);
/* STA attributes */
IEEE80211_IF_FILE(state, u.mgd.state, DEC);
IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
IEEE80211_IF_FILE(prev_bssid, u.mgd.prev_bssid, MAC);
IEEE80211_IF_FILE(ssid_len, u.mgd.ssid_len, SIZE);
IEEE80211_IF_FILE(aid, u.mgd.aid, DEC);
IEEE80211_IF_FILE(ap_capab, u.mgd.ap_capab, HEX);
IEEE80211_IF_FILE(capab, u.mgd.capab, HEX);
IEEE80211_IF_FILE(extra_ie_len, u.mgd.extra_ie_len, SIZE);
IEEE80211_IF_FILE(auth_tries, u.mgd.auth_tries, DEC);
IEEE80211_IF_FILE(assoc_tries, u.mgd.assoc_tries, DEC);
IEEE80211_IF_FILE(auth_algs, u.mgd.auth_algs, HEX);
IEEE80211_IF_FILE(auth_alg, u.mgd.auth_alg, DEC);
IEEE80211_IF_FILE(auth_transaction, u.mgd.auth_transaction, DEC);
static ssize_t ieee80211_if_fmt_flags(
const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
{
return scnprintf(buf, buflen, "%s%s%s%s%s%s%s\n",
sdata->u.sta.flags & IEEE80211_STA_SSID_SET ? "SSID\n" : "",
sdata->u.sta.flags & IEEE80211_STA_BSSID_SET ? "BSSID\n" : "",
sdata->u.sta.flags & IEEE80211_STA_PREV_BSSID_SET ? "prev BSSID\n" : "",
sdata->u.sta.flags & IEEE80211_STA_AUTHENTICATED ? "AUTH\n" : "",
sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED ? "ASSOC\n" : "",
sdata->u.sta.flags & IEEE80211_STA_PROBEREQ_POLL ? "PROBEREQ POLL\n" : "",
sdata->u.mgd.flags & IEEE80211_STA_SSID_SET ? "SSID\n" : "",
sdata->u.mgd.flags & IEEE80211_STA_BSSID_SET ? "BSSID\n" : "",
sdata->u.mgd.flags & IEEE80211_STA_PREV_BSSID_SET ? "prev BSSID\n" : "",
sdata->u.mgd.flags & IEEE80211_STA_AUTHENTICATED ? "AUTH\n" : "",
sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED ? "ASSOC\n" : "",
sdata->u.mgd.flags & IEEE80211_STA_PROBEREQ_POLL ? "PROBEREQ POLL\n" : "",
sdata->vif.bss_conf.use_cts_prot ? "CTS prot\n" : "");
}
__IEEE80211_IF_FILE(flags);
@ -283,9 +283,11 @@ static void add_files(struct ieee80211_sub_if_data *sdata)
#endif
break;
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
add_sta_files(sdata);
break;
case NL80211_IFTYPE_ADHOC:
/* XXX */
break;
case NL80211_IFTYPE_AP:
add_ap_files(sdata);
break;
@ -418,9 +420,11 @@ static void del_files(struct ieee80211_sub_if_data *sdata)
#endif
break;
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
del_sta_files(sdata);
break;
case NL80211_IFTYPE_ADHOC:
/* XXX */
break;
case NL80211_IFTYPE_AP:
del_ap_files(sdata);
break;

View file

@ -17,6 +17,7 @@
#include <net/wireless.h>
#include <net/mac80211.h>
#include "ieee80211_i.h"
#include "rate.h"
void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
struct ieee80211_ht_cap *ht_cap_ie,
@ -93,7 +94,9 @@ u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_supported_band *sband;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_bss_ht_conf ht;
struct sta_info *sta;
u32 changed = 0;
bool enable_ht = true, ht_changed;
enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
@ -136,6 +139,16 @@ u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
if (ht_changed) {
/* channel_type change automatically detected */
ieee80211_hw_config(local, 0);
rcu_read_lock();
sta = sta_info_get(local, ifmgd->bssid);
if (sta)
rate_control_rate_update(local, sband, sta,
IEEE80211_RC_HT_CHANGED);
rcu_read_unlock();
}
/* disable HT */
@ -169,7 +182,6 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
u16 initiator, u16 reason_code)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_sta *ifsta = &sdata->u.sta;
struct sk_buff *skb;
struct ieee80211_mgmt *mgmt;
u16 params;
@ -190,8 +202,9 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
if (sdata->vif.type == NL80211_IFTYPE_AP ||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
else
memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
else if (sdata->vif.type == NL80211_IFTYPE_STATION)
memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);

Some files were not shown because too many files have changed in this diff Show more