mirror of
https://github.com/adulau/aha.git
synced 2024-12-29 04:06:22 +00:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
This commit is contained in:
commit
8010dc306b
126 changed files with 8014 additions and 4149 deletions
|
@ -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
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -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++) {
|
||||
|
|
2501
drivers/net/wireless/at76c50x-usb.c
Normal file
2501
drivers/net/wireless/at76c50x-usb.c
Normal file
File diff suppressed because it is too large
Load diff
463
drivers/net/wireless/at76c50x-usb.h
Normal file
463
drivers/net/wireless/at76c50x-usb.h
Normal 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 */
|
|
@ -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) {
|
||||
/*
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -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, ¢ers);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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, ®_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, ®_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, ®_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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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 "
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 */
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#include <linux/etherdevice.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include <net/ieee80211.h>
|
||||
#include "ieee80211.h"
|
||||
|
||||
/*
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -114,9 +114,6 @@ static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev,
|
|||
{
|
||||
u32 reg;
|
||||
|
||||
if (!word)
|
||||
return;
|
||||
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
|
||||
/*
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -114,9 +114,6 @@ static void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev,
|
|||
{
|
||||
u32 reg;
|
||||
|
||||
if (!word)
|
||||
return;
|
||||
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
|
||||
/*
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -204,9 +204,6 @@ static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev,
|
|||
{
|
||||
u16 reg;
|
||||
|
||||
if (!word)
|
||||
return;
|
||||
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
|
||||
/*
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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; \
|
||||
|
|
|
@ -123,9 +123,6 @@ static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev,
|
|||
{
|
||||
u32 reg;
|
||||
|
||||
if (!word)
|
||||
return;
|
||||
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
|
||||
/*
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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, }
|
||||
};
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue