diff options
Diffstat (limited to 'drivers/net/wireless/ipw2x00')
-rw-r--r-- | drivers/net/wireless/ipw2x00/Kconfig | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ipw2x00/ieee80211.h | 1087 | ||||
-rw-r--r-- | drivers/net/wireless/ipw2x00/ipw2100.c | 74 | ||||
-rw-r--r-- | drivers/net/wireless/ipw2x00/ipw2100.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/ipw2x00/ipw2200.c | 198 | ||||
-rw-r--r-- | drivers/net/wireless/ipw2x00/ipw2200.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/ipw2x00/libipw_geo.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ipw2x00/libipw_module.c | 49 | ||||
-rw-r--r-- | drivers/net/wireless/ipw2x00/libipw_rx.c | 122 | ||||
-rw-r--r-- | drivers/net/wireless/ipw2x00/libipw_tx.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/ipw2x00/libipw_wx.c | 27 |
11 files changed, 1373 insertions, 216 deletions
diff --git a/drivers/net/wireless/ipw2x00/Kconfig b/drivers/net/wireless/ipw2x00/Kconfig index 3d5cc4463d4..85cc79995f6 100644 --- a/drivers/net/wireless/ipw2x00/Kconfig +++ b/drivers/net/wireless/ipw2x00/Kconfig @@ -150,6 +150,7 @@ config IPW2200_DEBUG config LIBIPW tristate + depends on PCI && WLAN_80211 select WIRELESS_EXT select CRYPTO select CRYPTO_ARC4 @@ -185,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. diff --git a/drivers/net/wireless/ipw2x00/ieee80211.h b/drivers/net/wireless/ipw2x00/ieee80211.h new file mode 100644 index 00000000000..70755c1336d --- /dev/null +++ b/drivers/net/wireless/ipw2x00/ieee80211.h @@ -0,0 +1,1087 @@ +/* + * Merged with mainline ieee80211.h in Aug 2004. Original ieee802_11 + * remains copyright by the original authors + * + * Portions of the merged code are based on Host AP (software wireless + * LAN access point) driver for Intersil Prism2/2.5/3. + * + * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen + * <j@w1.fi> + * Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi> + * + * Adaption to a generic IEEE 802.11 stack by James Ketrenos + * <jketreno@linux.intel.com> + * Copyright (c) 2004-2005, Intel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. See README and COPYING for + * more details. + * + * API Version History + * 1.0.x -- Initial version + * 1.1.x -- Added radiotap, QoS, TIM, ieee80211_geo APIs, + * various structure changes, and crypto API init method + */ +#ifndef IEEE80211_H +#define IEEE80211_H +#include <linux/if_ether.h> /* ETH_ALEN */ +#include <linux/kernel.h> /* ARRAY_SIZE */ +#include <linux/wireless.h> +#include <linux/ieee80211.h> + +#include <net/lib80211.h> + +#define IEEE80211_VERSION "git-1.1.13" + +#define IEEE80211_DATA_LEN 2304 +/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section + 6.2.1.1.2. + + The figure in section 7.1.2 suggests a body size of up to 2312 + bytes is allowed, which is a bit confusing, I suspect this + represents the 2304 bytes of real data, plus a possible 8 bytes of + WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */ + +#define IEEE80211_1ADDR_LEN 10 +#define IEEE80211_2ADDR_LEN 16 +#define IEEE80211_3ADDR_LEN 24 +#define IEEE80211_4ADDR_LEN 30 +#define IEEE80211_FCS_LEN 4 +#define IEEE80211_HLEN (IEEE80211_4ADDR_LEN) +#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN) + +#define MIN_FRAG_THRESHOLD 256U +#define MAX_FRAG_THRESHOLD 2346U + +/* QOS control */ +#define IEEE80211_QCTL_TID 0x000F + +/* debug macros */ + +#ifdef CONFIG_LIBIPW_DEBUG +extern u32 ieee80211_debug_level; +#define IEEE80211_DEBUG(level, fmt, args...) \ +do { if (ieee80211_debug_level & (level)) \ + printk(KERN_DEBUG "ieee80211: %c %s " fmt, \ + in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0) +static inline bool ieee80211_ratelimit_debug(u32 level) +{ + return (ieee80211_debug_level & level) && net_ratelimit(); +} +#else +#define IEEE80211_DEBUG(level, fmt, args...) do {} while (0) +static inline bool ieee80211_ratelimit_debug(u32 level) +{ + return false; +} +#endif /* CONFIG_LIBIPW_DEBUG */ + +/* + * To use the debug system: + * + * If you are defining a new debug classification, simply add it to the #define + * list here in the form of: + * + * #define IEEE80211_DL_xxxx VALUE + * + * shifting value to the left one bit from the previous entry. xxxx should be + * the name of the classification (for example, WEP) + * + * You then need to either add a IEEE80211_xxxx_DEBUG() macro definition for your + * classification, or use IEEE80211_DEBUG(IEEE80211_DL_xxxx, ...) whenever you want + * to send output to that classification. + * + * To add your debug level to the list of levels seen when you perform + * + * % cat /proc/net/ieee80211/debug_level + * + * you simply need to add your entry to the ieee80211_debug_level array. + * + * If you do not see debug_level in /proc/net/ieee80211 then you do not have + * CONFIG_LIBIPW_DEBUG defined in your kernel configuration + * + */ + +#define IEEE80211_DL_INFO (1<<0) +#define IEEE80211_DL_WX (1<<1) +#define IEEE80211_DL_SCAN (1<<2) +#define IEEE80211_DL_STATE (1<<3) +#define IEEE80211_DL_MGMT (1<<4) +#define IEEE80211_DL_FRAG (1<<5) +#define IEEE80211_DL_DROP (1<<7) + +#define IEEE80211_DL_TX (1<<8) +#define IEEE80211_DL_RX (1<<9) +#define IEEE80211_DL_QOS (1<<31) + +#define IEEE80211_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a) +#define IEEE80211_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a) +#define IEEE80211_DEBUG_INFO(f, a...) IEEE80211_DEBUG(IEEE80211_DL_INFO, f, ## a) + +#define IEEE80211_DEBUG_WX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_WX, f, ## a) +#define IEEE80211_DEBUG_SCAN(f, a...) IEEE80211_DEBUG(IEEE80211_DL_SCAN, f, ## a) +#define IEEE80211_DEBUG_STATE(f, a...) IEEE80211_DEBUG(IEEE80211_DL_STATE, f, ## a) +#define IEEE80211_DEBUG_MGMT(f, a...) IEEE80211_DEBUG(IEEE80211_DL_MGMT, f, ## a) +#define IEEE80211_DEBUG_FRAG(f, a...) IEEE80211_DEBUG(IEEE80211_DL_FRAG, f, ## a) +#define IEEE80211_DEBUG_DROP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_DROP, f, ## a) +#define IEEE80211_DEBUG_TX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_TX, f, ## a) +#define IEEE80211_DEBUG_RX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a) +#define IEEE80211_DEBUG_QOS(f, a...) IEEE80211_DEBUG(IEEE80211_DL_QOS, f, ## a) +#include <linux/netdevice.h> +#include <linux/if_arp.h> /* ARPHRD_ETHER */ + +#ifndef WIRELESS_SPY +#define WIRELESS_SPY /* enable iwspy support */ +#endif +#include <net/iw_handler.h> /* new driver API */ + +#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */ + +#ifndef ETH_P_80211_RAW +#define ETH_P_80211_RAW (ETH_P_ECONET + 1) +#endif + +/* IEEE 802.11 defines */ + +#define P80211_OUI_LEN 3 + +struct ieee80211_snap_hdr { + + u8 dsap; /* always 0xAA */ + u8 ssap; /* always 0xAA */ + u8 ctrl; /* always 0x03 */ + u8 oui[P80211_OUI_LEN]; /* organizational universal id */ + +} __attribute__ ((packed)); + +#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr) + +#define WLAN_FC_GET_VERS(fc) ((fc) & IEEE80211_FCTL_VERS) +#define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE) +#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE) + +#define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG) +#define WLAN_GET_SEQ_SEQ(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) + +#define IEEE80211_STATMASK_SIGNAL (1<<0) +#define IEEE80211_STATMASK_RSSI (1<<1) +#define IEEE80211_STATMASK_NOISE (1<<2) +#define IEEE80211_STATMASK_RATE (1<<3) +#define IEEE80211_STATMASK_WEMASK 0x7 + +#define IEEE80211_CCK_MODULATION (1<<0) +#define IEEE80211_OFDM_MODULATION (1<<1) + +#define IEEE80211_24GHZ_BAND (1<<0) +#define IEEE80211_52GHZ_BAND (1<<1) + +#define IEEE80211_CCK_RATE_1MB 0x02 +#define IEEE80211_CCK_RATE_2MB 0x04 +#define IEEE80211_CCK_RATE_5MB 0x0B +#define IEEE80211_CCK_RATE_11MB 0x16 +#define IEEE80211_OFDM_RATE_6MB 0x0C +#define IEEE80211_OFDM_RATE_9MB 0x12 +#define IEEE80211_OFDM_RATE_12MB 0x18 +#define IEEE80211_OFDM_RATE_18MB 0x24 +#define IEEE80211_OFDM_RATE_24MB 0x30 +#define IEEE80211_OFDM_RATE_36MB 0x48 +#define IEEE80211_OFDM_RATE_48MB 0x60 +#define IEEE80211_OFDM_RATE_54MB 0x6C +#define IEEE80211_BASIC_RATE_MASK 0x80 + +#define IEEE80211_CCK_RATE_1MB_MASK (1<<0) +#define IEEE80211_CCK_RATE_2MB_MASK (1<<1) +#define IEEE80211_CCK_RATE_5MB_MASK (1<<2) +#define IEEE80211_CCK_RATE_11MB_MASK (1<<3) +#define IEEE80211_OFDM_RATE_6MB_MASK (1<<4) +#define IEEE80211_OFDM_RATE_9MB_MASK (1<<5) +#define IEEE80211_OFDM_RATE_12MB_MASK (1<<6) +#define IEEE80211_OFDM_RATE_18MB_MASK (1<<7) +#define IEEE80211_OFDM_RATE_24MB_MASK (1<<8) +#define IEEE80211_OFDM_RATE_36MB_MASK (1<<9) +#define IEEE80211_OFDM_RATE_48MB_MASK (1<<10) +#define IEEE80211_OFDM_RATE_54MB_MASK (1<<11) + +#define IEEE80211_CCK_RATES_MASK 0x0000000F +#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \ + IEEE80211_CCK_RATE_2MB_MASK) +#define IEEE80211_CCK_DEFAULT_RATES_MASK (IEEE80211_CCK_BASIC_RATES_MASK | \ + IEEE80211_CCK_RATE_5MB_MASK | \ + IEEE80211_CCK_RATE_11MB_MASK) + +#define IEEE80211_OFDM_RATES_MASK 0x00000FF0 +#define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \ + IEEE80211_OFDM_RATE_12MB_MASK | \ + IEEE80211_OFDM_RATE_24MB_MASK) +#define IEEE80211_OFDM_DEFAULT_RATES_MASK (IEEE80211_OFDM_BASIC_RATES_MASK | \ + IEEE80211_OFDM_RATE_9MB_MASK | \ + IEEE80211_OFDM_RATE_18MB_MASK | \ + IEEE80211_OFDM_RATE_36MB_MASK | \ + IEEE80211_OFDM_RATE_48MB_MASK | \ + IEEE80211_OFDM_RATE_54MB_MASK) +#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \ + IEEE80211_CCK_DEFAULT_RATES_MASK) + +#define IEEE80211_NUM_OFDM_RATES 8 +#define IEEE80211_NUM_CCK_RATES 4 +#define IEEE80211_OFDM_SHIFT_MASK_A 4 + +/* NOTE: This data is for statistical purposes; not all hardware provides this + * information for frames received. + * For ieee80211_rx_mgt, you need to set at least the 'len' parameter. + */ +struct ieee80211_rx_stats { + u32 mac_time; + s8 rssi; + u8 signal; + u8 noise; + u16 rate; /* in 100 kbps */ + u8 received_channel; + u8 control; + u8 mask; + u8 freq; + u16 len; + u64 tsf; + u32 beacon_time; +}; + +/* IEEE 802.11 requires that STA supports concurrent reception of at least + * three fragmented frames. This define can be increased to support more + * concurrent frames, but it should be noted that each entry can consume about + * 2 kB of RAM and increasing cache size will slow down frame reassembly. */ +#define IEEE80211_FRAG_CACHE_LEN 4 + +struct ieee80211_frag_entry { + unsigned long first_frag_time; + unsigned int seq; + unsigned int last_frag; + struct sk_buff *skb; + u8 src_addr[ETH_ALEN]; + u8 dst_addr[ETH_ALEN]; +}; + +struct ieee80211_stats { + unsigned int tx_unicast_frames; + unsigned int tx_multicast_frames; + unsigned int tx_fragments; + unsigned int tx_unicast_octets; + unsigned int tx_multicast_octets; + unsigned int tx_deferred_transmissions; + unsigned int tx_single_retry_frames; + unsigned int tx_multiple_retry_frames; + unsigned int tx_retry_limit_exceeded; + unsigned int tx_discards; + unsigned int rx_unicast_frames; + unsigned int rx_multicast_frames; + unsigned int rx_fragments; + unsigned int rx_unicast_octets; + unsigned int rx_multicast_octets; + unsigned int rx_fcs_errors; + unsigned int rx_discards_no_buffer; + unsigned int tx_discards_wrong_sa; + unsigned int rx_discards_undecryptable; + unsigned int rx_message_in_msg_fragments; + unsigned int rx_message_in_bad_msg_fragments; +}; + +struct ieee80211_device; + +#define SEC_KEY_1 (1<<0) +#define SEC_KEY_2 (1<<1) +#define SEC_KEY_3 (1<<2) +#define SEC_KEY_4 (1<<3) +#define SEC_ACTIVE_KEY (1<<4) +#define SEC_AUTH_MODE (1<<5) +#define SEC_UNICAST_GROUP (1<<6) +#define SEC_LEVEL (1<<7) +#define SEC_ENABLED (1<<8) +#define SEC_ENCRYPT (1<<9) + +#define SEC_LEVEL_0 0 /* None */ +#define SEC_LEVEL_1 1 /* WEP 40 and 104 bit */ +#define SEC_LEVEL_2 2 /* Level 1 + TKIP */ +#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */ +#define SEC_LEVEL_3 4 /* Level 2 + CCMP */ + +#define SEC_ALG_NONE 0 +#define SEC_ALG_WEP 1 +#define SEC_ALG_TKIP 2 +#define SEC_ALG_CCMP 3 + +#define WEP_KEYS 4 +#define WEP_KEY_LEN 13 +#define SCM_KEY_LEN 32 +#define SCM_TEMPORAL_KEY_LENGTH 16 + +struct ieee80211_security { + u16 active_key:2, enabled:1, unicast_uses_group:1, encrypt:1; + u8 auth_mode; + u8 encode_alg[WEP_KEYS]; + u8 key_sizes[WEP_KEYS]; + u8 keys[WEP_KEYS][SCM_KEY_LEN]; + u8 level; + u16 flags; +} __attribute__ ((packed)); + +/* + + 802.11 data frame from AP + + ,-------------------------------------------------------------------. +Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | + |------|------|---------|---------|---------|------|---------|------| +Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | frame | fcs | + | | tion | (BSSID) | | | ence | data | | + `-------------------------------------------------------------------' + +Total: 28-2340 bytes + +*/ + +#define BEACON_PROBE_SSID_ID_POSITION 12 + +struct ieee80211_hdr_1addr { + __le16 frame_ctl; + __le16 duration_id; + u8 addr1[ETH_ALEN]; + u8 payload[0]; +} __attribute__ ((packed)); + +struct ieee80211_hdr_2addr { + __le16 frame_ctl; + __le16 duration_id; + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 payload[0]; +} __attribute__ ((packed)); + +struct ieee80211_hdr_3addr { + __le16 frame_ctl; + __le16 duration_id; + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 addr3[ETH_ALEN]; + __le16 seq_ctl; + u8 payload[0]; +} __attribute__ ((packed)); + +struct ieee80211_hdr_4addr { + __le16 frame_ctl; + __le16 duration_id; + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 addr3[ETH_ALEN]; + __le16 seq_ctl; + u8 addr4[ETH_ALEN]; + u8 payload[0]; +} __attribute__ ((packed)); + +struct ieee80211_hdr_3addrqos { + __le16 frame_ctl; + __le16 duration_id; + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 addr3[ETH_ALEN]; + __le16 seq_ctl; + u8 payload[0]; + __le16 qos_ctl; +} __attribute__ ((packed)); + +struct ieee80211_info_element { + u8 id; + u8 len; + u8 data[0]; +} __attribute__ ((packed)); + +/* + * These are the data types that can make up management packets + * + u16 auth_algorithm; + u16 auth_sequence; + u16 beacon_interval; + u16 capability; + u8 current_ap[ETH_ALEN]; + u16 listen_interval; + struct { + u16 association_id:14, reserved:2; + } __attribute__ ((packed)); + u32 time_stamp[2]; + u16 reason; + u16 status; +*/ + +struct ieee80211_auth { + struct ieee80211_hdr_3addr header; + __le16 algorithm; + __le16 transaction; + __le16 status; + /* challenge */ + struct ieee80211_info_element info_element[0]; +} __attribute__ ((packed)); + +struct ieee80211_channel_switch { + u8 id; + u8 len; + u8 mode; + u8 channel; + u8 count; +} __attribute__ ((packed)); + +struct ieee80211_action { + struct ieee80211_hdr_3addr header; + u8 category; + u8 action; + union { + struct ieee80211_action_exchange { + u8 token; + struct ieee80211_info_element info_element[0]; + } exchange; + struct ieee80211_channel_switch channel_switch; + + } format; +} __attribute__ ((packed)); + +struct ieee80211_disassoc { + struct ieee80211_hdr_3addr header; + __le16 reason; +} __attribute__ ((packed)); + +/* Alias deauth for disassoc */ +#define ieee80211_deauth ieee80211_disassoc + +struct ieee80211_probe_request { + struct ieee80211_hdr_3addr header; + /* SSID, supported rates */ + struct ieee80211_info_element info_element[0]; +} __attribute__ ((packed)); + +struct ieee80211_probe_response { + struct ieee80211_hdr_3addr header; + __le32 time_stamp[2]; + __le16 beacon_interval; + __le16 capability; + /* SSID, supported rates, FH params, DS params, + * CF params, IBSS params, TIM (if beacon), RSN */ + struct ieee80211_info_element info_element[0]; +} __attribute__ ((packed)); + +/* Alias beacon for probe_response */ +#define ieee80211_beacon ieee80211_probe_response + +struct ieee80211_assoc_request { + struct ieee80211_hdr_3addr header; + __le16 capability; + __le16 listen_interval; + /* SSID, supported rates, RSN */ + struct ieee80211_info_element info_element[0]; +} __attribute__ ((packed)); + +struct ieee80211_reassoc_request { + struct ieee80211_hdr_3addr header; + __le16 capability; + __le16 listen_interval; + u8 current_ap[ETH_ALEN]; + struct ieee80211_info_element info_element[0]; +} __attribute__ ((packed)); + +struct ieee80211_assoc_response { + struct ieee80211_hdr_3addr header; + __le16 capability; + __le16 status; + __le16 aid; + /* supported rates */ + struct ieee80211_info_element info_element[0]; +} __attribute__ ((packed)); + +struct ieee80211_txb { + u8 nr_frags; + u8 encrypted; + u8 rts_included; + u8 reserved; + u16 frag_size; + u16 payload_size; + struct sk_buff *fragments[0]; +}; + +/* SWEEP TABLE ENTRIES NUMBER */ +#define MAX_SWEEP_TAB_ENTRIES 42 +#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET 7 +/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs + * only use 8, and then use extended rates for the remaining supported + * rates. Other APs, however, stick all of their supported rates on the + * main rates information element... */ +#define MAX_RATES_LENGTH ((u8)12) +#define MAX_RATES_EX_LENGTH ((u8)16) +#define MAX_NETWORK_COUNT 128 + +#define CRC_LENGTH 4U + +#define MAX_WPA_IE_LEN 64 + +#define NETWORK_HAS_OFDM (1<<1) +#define NETWORK_HAS_CCK (1<<2) + +/* QoS structure */ +#define NETWORK_HAS_QOS_PARAMETERS (1<<3) +#define NETWORK_HAS_QOS_INFORMATION (1<<4) +#define NETWORK_HAS_QOS_MASK (NETWORK_HAS_QOS_PARAMETERS | \ + NETWORK_HAS_QOS_INFORMATION) + +/* 802.11h */ +#define NETWORK_HAS_POWER_CONSTRAINT (1<<5) +#define NETWORK_HAS_CSA (1<<6) +#define NETWORK_HAS_QUIET (1<<7) +#define NETWORK_HAS_IBSS_DFS (1<<8) +#define NETWORK_HAS_TPC_REPORT (1<<9) + +#define NETWORK_HAS_ERP_VALUE (1<<10) + +#define QOS_QUEUE_NUM 4 +#define QOS_OUI_LEN 3 +#define QOS_OUI_TYPE 2 +#define QOS_ELEMENT_ID 221 +#define QOS_OUI_INFO_SUB_TYPE 0 +#define QOS_OUI_PARAM_SUB_TYPE 1 +#define QOS_VERSION_1 1 +#define QOS_AIFSN_MIN_VALUE 2 + +struct ieee80211_qos_information_element { + u8 elementID; + u8 length; + u8 qui[QOS_OUI_LEN]; + u8 qui_type; + u8 qui_subtype; + u8 version; + u8 ac_info; +} __attribute__ ((packed)); + +struct ieee80211_qos_ac_parameter { + u8 aci_aifsn; + u8 ecw_min_max; + __le16 tx_op_limit; +} __attribute__ ((packed)); + +struct ieee80211_qos_parameter_info { + struct ieee80211_qos_information_element info_element; + u8 reserved; + struct ieee80211_qos_ac_parameter ac_params_record[QOS_QUEUE_NUM]; +} __attribute__ ((packed)); + +struct ieee80211_qos_parameters { + __le16 cw_min[QOS_QUEUE_NUM]; + __le16 cw_max[QOS_QUEUE_NUM]; + u8 aifs[QOS_QUEUE_NUM]; + u8 flag[QOS_QUEUE_NUM]; + __le16 tx_op_limit[QOS_QUEUE_NUM]; +} __attribute__ ((packed)); + +struct ieee80211_qos_data { + struct ieee80211_qos_parameters parameters; + int active; + int supported; + u8 param_count; + u8 old_param_count; +}; + +struct ieee80211_tim_parameters { + u8 tim_count; + u8 tim_period; +} __attribute__ ((packed)); + +/*******************************************************/ + +enum { /* ieee80211_basic_report.map */ + IEEE80211_BASIC_MAP_BSS = (1 << 0), + IEEE80211_BASIC_MAP_OFDM = (1 << 1), + IEEE80211_BASIC_MAP_UNIDENTIFIED = (1 << 2), + IEEE80211_BASIC_MAP_RADAR = (1 << 3), + IEEE80211_BASIC_MAP_UNMEASURED = (1 << 4), + /* Bits 5-7 are reserved */ + +}; +struct ieee80211_basic_report { + u8 channel; + __le64 start_time; + __le16 duration; + u8 map; +} __attribute__ ((packed)); + +enum { /* ieee80211_measurement_request.mode */ + /* Bit 0 is reserved */ + IEEE80211_MEASUREMENT_ENABLE = (1 << 1), + IEEE80211_MEASUREMENT_REQUEST = (1 << 2), + IEEE80211_MEASUREMENT_REPORT = (1 << 3), + /* Bits 4-7 are reserved */ +}; + +enum { + IEEE80211_REPORT_BASIC = 0, /* required */ + IEEE80211_REPORT_CCA = 1, /* optional */ + IEEE80211_REPORT_RPI = 2, /* optional */ + /* 3-255 reserved */ +}; + +struct ieee80211_measurement_params { + u8 channel; + __le64 start_time; + __le16 duration; +} __attribute__ ((packed)); + +struct ieee80211_measurement_request { + struct ieee80211_info_element ie; + u8 token; + u8 mode; + u8 type; + struct ieee80211_measurement_params params[0]; +} __attribute__ ((packed)); + +struct ieee80211_measurement_report { + struct ieee80211_info_element ie; + u8 token; + u8 mode; + u8 type; + union { + struct ieee80211_basic_report basic[0]; + } u; +} __attribute__ ((packed)); + +struct ieee80211_tpc_report { + u8 transmit_power; + u8 link_margin; +} __attribute__ ((packed)); + +struct ieee80211_channel_map { + u8 channel; + u8 map; +} __attribute__ ((packed)); + +struct ieee80211_ibss_dfs { + struct ieee80211_info_element ie; + u8 owner[ETH_ALEN]; + u8 recovery_interval; + struct ieee80211_channel_map channel_map[0]; +}; + +struct ieee80211_csa { + u8 mode; + u8 channel; + u8 count; +} __attribute__ ((packed)); + +struct ieee80211_quiet { + u8 count; + u8 period; + u8 duration; + u8 offset; +} __attribute__ ((packed)); + +struct ieee80211_network { + /* These entries are used to identify a unique network */ + u8 bssid[ETH_ALEN]; + u8 channel; + /* Ensure null-terminated for any debug msgs */ + u8 ssid[IW_ESSID_MAX_SIZE + 1]; + u8 ssid_len; + + struct ieee80211_qos_data qos_data; + + /* These are network statistics */ + struct ieee80211_rx_stats stats; + u16 capability; + u8 rates[MAX_RATES_LENGTH]; + u8 rates_len; + u8 rates_ex[MAX_RATES_EX_LENGTH]; + u8 rates_ex_len; + unsigned long last_scanned; + u8 mode; + u32 flags; + u32 last_associate; + u32 time_stamp[2]; + u16 beacon_interval; + u16 listen_interval; + u16 atim_window; + u8 erp_value; + u8 wpa_ie[MAX_WPA_IE_LEN]; + size_t wpa_ie_len; + u8 rsn_ie[MAX_WPA_IE_LEN]; + size_t rsn_ie_len; + struct ieee80211_tim_parameters tim; + + /* 802.11h info */ + + /* Power Constraint - mandatory if spctrm mgmt required */ + u8 power_constraint; + + /* TPC Report - mandatory if spctrm mgmt required */ + struct ieee80211_tpc_report tpc_report; + + /* IBSS DFS - mandatory if spctrm mgmt required and IBSS + * NOTE: This is variable length and so must be allocated dynamically */ + struct ieee80211_ibss_dfs *ibss_dfs; + + /* Channel Switch Announcement - optional if spctrm mgmt required */ + struct ieee80211_csa csa; + + /* Quiet - optional if spctrm mgmt required */ + struct ieee80211_quiet quiet; + + struct list_head list; +}; + +enum ieee80211_state { + IEEE80211_UNINITIALIZED = 0, + IEEE80211_INITIALIZED, + IEEE80211_ASSOCIATING, + IEEE80211_ASSOCIATED, + IEEE80211_AUTHENTICATING, + IEEE80211_AUTHENTICATED, + IEEE80211_SHUTDOWN +}; + +#define DEFAULT_MAX_SCAN_AGE (15 * HZ) +#define DEFAULT_FTS 2346 + +#define CFG_IEEE80211_RESERVE_FCS (1<<0) +#define CFG_IEEE80211_COMPUTE_FCS (1<<1) +#define CFG_IEEE80211_RTS (1<<2) + +#define IEEE80211_24GHZ_MIN_CHANNEL 1 +#define IEEE80211_24GHZ_MAX_CHANNEL 14 +#define IEEE80211_24GHZ_CHANNELS (IEEE80211_24GHZ_MAX_CHANNEL - \ + IEEE80211_24GHZ_MIN_CHANNEL + 1) + +#define IEEE80211_52GHZ_MIN_CHANNEL 34 +#define IEEE80211_52GHZ_MAX_CHANNEL 165 +#define IEEE80211_52GHZ_CHANNELS (IEEE80211_52GHZ_MAX_CHANNEL - \ + IEEE80211_52GHZ_MIN_CHANNEL + 1) + +enum { + IEEE80211_CH_PASSIVE_ONLY = (1 << 0), + IEEE80211_CH_80211H_RULES = (1 << 1), + IEEE80211_CH_B_ONLY = (1 << 2), + IEEE80211_CH_NO_IBSS = (1 << 3), + IEEE80211_CH_UNIFORM_SPREADING = (1 << 4), + IEEE80211_CH_RADAR_DETECT = (1 << 5), + IEEE80211_CH_INVALID = (1 << 6), +}; + +struct ieee80211_channel { + u32 freq; /* in MHz */ + u8 channel; + u8 flags; + u8 max_power; /* in dBm */ +}; + +struct ieee80211_geo { + u8 name[4]; + u8 bg_channels; + u8 a_channels; + struct ieee80211_channel bg[IEEE80211_24GHZ_CHANNELS]; + struct ieee80211_channel a[IEEE80211_52GHZ_CHANNELS]; +}; + +struct ieee80211_device { + struct net_device *dev; + struct ieee80211_security sec; + + /* Bookkeeping structures */ + struct ieee80211_stats ieee_stats; + + struct ieee80211_geo geo; + + /* Probe / Beacon management */ + struct list_head network_free_list; + struct list_head network_list; + struct ieee80211_network *networks; + int scans; + int scan_age; + + int iw_mode; /* operating mode (IW_MODE_*) */ + struct iw_spy_data spy_data; /* iwspy support */ + + spinlock_t lock; + + int tx_headroom; /* Set to size of any additional room needed at front + * of allocated Tx SKBs */ + u32 config; + + /* WEP and other encryption related settings at the device level */ + int open_wep; /* Set to 1 to allow unencrypted frames */ + + int reset_on_keychange; /* Set to 1 if the HW needs to be reset on + * WEP key changes */ + + /* If the host performs {en,de}cryption, then set to 1 */ + int host_encrypt; + int host_encrypt_msdu; + int host_decrypt; + /* host performs multicast decryption */ + int host_mc_decrypt; + + /* host should strip IV and ICV from protected frames */ + /* meaningful only when hardware decryption is being used */ + int host_strip_iv_icv; + + int host_open_frag; + int host_build_iv; + int ieee802_1x; /* is IEEE 802.1X used */ + + /* WPA data */ + int wpa_enabled; + int drop_unencrypted; + int privacy_invoked; + size_t wpa_ie_len; + u8 *wpa_ie; + + struct lib80211_crypt_info crypt_info; + + int bcrx_sta_key; /* use individual keys to override default keys even + * with RX of broad/multicast frames */ + + /* Fragmentation structures */ + struct ieee80211_frag_entry frag_cache[IEEE80211_FRAG_CACHE_LEN]; + unsigned int frag_next_idx; + u16 fts; /* Fragmentation Threshold */ + u16 rts; /* RTS threshold */ + + /* Association info */ + u8 bssid[ETH_ALEN]; + + enum ieee80211_state state; + + int mode; /* A, B, G */ + int modulation; /* CCK, OFDM */ + int freq_band; /* 2.4Ghz, 5.2Ghz, Mixed */ + int abg_true; /* ABG flag */ + + int perfect_rssi; + int worst_rssi; + + u16 prev_seq_ctl; /* used to drop duplicate frames */ + + /* Callback functions */ + void (*set_security) (struct net_device * dev, + struct ieee80211_security * sec); + int (*hard_start_xmit) (struct ieee80211_txb * txb, + struct net_device * dev, int pri); + int (*reset_port) (struct net_device * dev); + int (*is_queue_full) (struct net_device * dev, int pri); + + int (*handle_management) (struct net_device * dev, + struct ieee80211_network * network, u16 type); + int (*is_qos_active) (struct net_device *dev, struct sk_buff *skb); + + /* Typical STA methods */ + int (*handle_auth) (struct net_device * dev, + struct ieee80211_auth * auth); + int (*handle_deauth) (struct net_device * dev, + struct ieee80211_deauth * auth); + int (*handle_action) (struct net_device * dev, + struct ieee80211_action * action, + struct ieee80211_rx_stats * stats); + int (*handle_disassoc) (struct net_device * dev, + struct ieee80211_disassoc * assoc); + int (*handle_beacon) (struct net_device * dev, + struct ieee80211_beacon * beacon, + struct ieee80211_network * network); + int (*handle_probe_response) (struct net_device * dev, + struct ieee80211_probe_response * resp, + struct ieee80211_network * network); + int (*handle_probe_request) (struct net_device * dev, + struct ieee80211_probe_request * req, + struct ieee80211_rx_stats * stats); + int (*handle_assoc_response) (struct net_device * dev, + struct ieee80211_assoc_response * resp, + struct ieee80211_network * network); + + /* Typical AP methods */ + int (*handle_assoc_request) (struct net_device * dev); + int (*handle_reassoc_request) (struct net_device * dev, + struct ieee80211_reassoc_request * req); + + /* This must be the last item so that it points to the data + * allocated beyond this structure by alloc_ieee80211 */ + u8 priv[0]; +}; + +#define IEEE_A (1<<0) +#define IEEE_B (1<<1) +#define IEEE_G (1<<2) +#define IEEE_MODE_MASK (IEEE_A|IEEE_B|IEEE_G) + +static inline void *ieee80211_priv(struct net_device *dev) +{ + return ((struct ieee80211_device *)netdev_priv(dev))->priv; +} + +static inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, + int mode) +{ + /* + * It is possible for both access points and our device to support + * combinations of modes, so as long as there is one valid combination + * of ap/device supported modes, then return success + * + */ + if ((mode & IEEE_A) && + (ieee->modulation & IEEE80211_OFDM_MODULATION) && + (ieee->freq_band & IEEE80211_52GHZ_BAND)) + return 1; + + if ((mode & IEEE_G) && + (ieee->modulation & IEEE80211_OFDM_MODULATION) && + (ieee->freq_band & IEEE80211_24GHZ_BAND)) + return 1; + + if ((mode & IEEE_B) && + (ieee->modulation & IEEE80211_CCK_MODULATION) && + (ieee->freq_band & IEEE80211_24GHZ_BAND)) + return 1; + + return 0; +} + +static inline int ieee80211_get_hdrlen(u16 fc) +{ + int hdrlen = IEEE80211_3ADDR_LEN; + u16 stype = WLAN_FC_GET_STYPE(fc); + + switch (WLAN_FC_GET_TYPE(fc)) { + case IEEE80211_FTYPE_DATA: + if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS)) + hdrlen = IEEE80211_4ADDR_LEN; + if (stype & IEEE80211_STYPE_QOS_DATA) + hdrlen += 2; + break; + case IEEE80211_FTYPE_CTL: + switch (WLAN_FC_GET_STYPE(fc)) { + case IEEE80211_STYPE_CTS: + case IEEE80211_STYPE_ACK: + hdrlen = IEEE80211_1ADDR_LEN; + break; + default: + hdrlen = IEEE80211_2ADDR_LEN; + break; + } + break; + } + + return hdrlen; +} + +static inline u8 *ieee80211_get_payload(struct ieee80211_hdr *hdr) +{ + switch (ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control))) { + case IEEE80211_1ADDR_LEN: + return ((struct ieee80211_hdr_1addr *)hdr)->payload; + case IEEE80211_2ADDR_LEN: + return ((struct ieee80211_hdr_2addr *)hdr)->payload; + case IEEE80211_3ADDR_LEN: + return ((struct ieee80211_hdr_3addr *)hdr)->payload; + case IEEE80211_4ADDR_LEN: + return ((struct ieee80211_hdr_4addr *)hdr)->payload; + } + return NULL; +} + +static inline int ieee80211_is_ofdm_rate(u8 rate) +{ + switch (rate & ~IEEE80211_BASIC_RATE_MASK) { + case IEEE80211_OFDM_RATE_6MB: + case IEEE80211_OFDM_RATE_9MB: + case IEEE80211_OFDM_RATE_12MB: + case IEEE80211_OFDM_RATE_18MB: + case IEEE80211_OFDM_RATE_24MB: + case IEEE80211_OFDM_RATE_36MB: + case IEEE80211_OFDM_RATE_48MB: + case IEEE80211_OFDM_RATE_54MB: + return 1; + } + return 0; +} + +static inline int ieee80211_is_cck_rate(u8 rate) +{ + switch (rate & ~IEEE80211_BASIC_RATE_MASK) { + case IEEE80211_CCK_RATE_1MB: + case IEEE80211_CCK_RATE_2MB: + case IEEE80211_CCK_RATE_5MB: + case IEEE80211_CCK_RATE_11MB: + return 1; + } + return 0; +} + +/* ieee80211.c */ +extern void free_ieee80211(struct net_device *dev); +extern struct net_device *alloc_ieee80211(int sizeof_priv); +extern int ieee80211_change_mtu(struct net_device *dev, int new_mtu); + +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 */ +extern int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev); +extern void ieee80211_txb_free(struct ieee80211_txb *); + +/* ieee80211_rx.c */ +extern void ieee80211_rx_any(struct ieee80211_device *ieee, + struct sk_buff *skb, struct ieee80211_rx_stats *stats); +extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, + struct ieee80211_rx_stats *rx_stats); +/* make sure to set stats->len */ +extern void ieee80211_rx_mgt(struct ieee80211_device *ieee, + struct ieee80211_hdr_4addr *header, + struct ieee80211_rx_stats *stats); +extern void ieee80211_network_reset(struct ieee80211_network *network); + +/* ieee80211_geo.c */ +extern const struct ieee80211_geo *ieee80211_get_geo(struct ieee80211_device + *ieee); +extern int ieee80211_set_geo(struct ieee80211_device *ieee, + const struct ieee80211_geo *geo); + +extern int ieee80211_is_valid_channel(struct ieee80211_device *ieee, + u8 channel); +extern int ieee80211_channel_to_index(struct ieee80211_device *ieee, + u8 channel); +extern u8 ieee80211_freq_to_channel(struct ieee80211_device *ieee, u32 freq); +extern u8 ieee80211_get_channel_flags(struct ieee80211_device *ieee, + u8 channel); +extern const struct ieee80211_channel *ieee80211_get_channel(struct + ieee80211_device + *ieee, u8 channel); +extern u32 ieee80211_channel_to_freq(struct ieee80211_device * ieee, + u8 channel); + +/* ieee80211_wx.c */ +extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *key); +extern int ieee80211_wx_set_encode(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *key); +extern int ieee80211_wx_get_encode(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *key); +extern int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); +extern int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +static inline void ieee80211_increment_scans(struct ieee80211_device *ieee) +{ + ieee->scans++; +} + +static inline int ieee80211_get_scans(struct ieee80211_device *ieee) +{ + return ieee->scans; +} + +#endif /* IEEE80211_H */ diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 823c2bf5e31..115b7048750 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.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); @@ -1910,7 +1916,8 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status) { #define MAC_ASSOCIATION_READ_DELAY (HZ) - int ret, len, essid_len; + int ret; + unsigned int len, essid_len; char essid[IW_ESSID_MAX_SIZE]; u32 txrate; u32 chan; @@ -2384,13 +2391,14 @@ static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i) #endif priv->fatal_error = IPW2100_ERR_C3_CORRUPTION; - priv->ieee->stats.rx_errors++; + priv->net_dev->stats.rx_errors++; schedule_reset(priv); } static void isr_rx(struct ipw2100_priv *priv, int i, struct ieee80211_rx_stats *stats) { + struct net_device *dev = priv->net_dev; struct ipw2100_status *status = &priv->status_queue.drv[i]; struct ipw2100_rx_packet *packet = &priv->rx_buffers[i]; @@ -2399,14 +2407,14 @@ static void isr_rx(struct ipw2100_priv *priv, int i, if (unlikely(status->frame_size > skb_tailroom(packet->skb))) { IPW_DEBUG_INFO("%s: frame_size (%u) > skb_tailroom (%u)!" " Dropping.\n", - priv->net_dev->name, + dev->name, status->frame_size, skb_tailroom(packet->skb)); - priv->ieee->stats.rx_errors++; + dev->stats.rx_errors++; return; } - if (unlikely(!netif_running(priv->net_dev))) { - priv->ieee->stats.rx_errors++; + if (unlikely(!netif_running(dev))) { + dev->stats.rx_errors++; priv->wstats.discard.misc++; IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); return; @@ -2436,10 +2444,10 @@ static void isr_rx(struct ipw2100_priv *priv, int i, if (!ieee80211_rx(priv->ieee, packet->skb, stats)) { #ifdef IPW2100_RX_DEBUG IPW_DEBUG_DROP("%s: Non consumed packet:\n", - priv->net_dev->name); + dev->name); printk_buf(IPW_DL_DROP, packet_data, status->frame_size); #endif - priv->ieee->stats.rx_errors++; + dev->stats.rx_errors++; /* ieee80211_rx failed, so it didn't free the SKB */ dev_kfree_skb_any(packet->skb); @@ -2450,7 +2458,7 @@ static void isr_rx(struct ipw2100_priv *priv, int i, if (unlikely(ipw2100_alloc_skb(priv, packet))) { printk(KERN_WARNING DRV_NAME ": " "%s: Unable to allocate SKB onto RBD ring - disabling " - "adapter.\n", priv->net_dev->name); + "adapter.\n", dev->name); /* TODO: schedule adapter shutdown */ IPW_DEBUG_INFO("TODO: Shutdown adapter...\n"); } @@ -2464,6 +2472,7 @@ static void isr_rx(struct ipw2100_priv *priv, int i, static void isr_rx_monitor(struct ipw2100_priv *priv, int i, struct ieee80211_rx_stats *stats) { + struct net_device *dev = priv->net_dev; struct ipw2100_status *status = &priv->status_queue.drv[i]; struct ipw2100_rx_packet *packet = &priv->rx_buffers[i]; @@ -2481,15 +2490,15 @@ static void isr_rx_monitor(struct ipw2100_priv *priv, int i, sizeof(struct ipw_rt_hdr))) { IPW_DEBUG_INFO("%s: frame_size (%u) > skb_tailroom (%u)!" " Dropping.\n", - priv->net_dev->name, + dev->name, status->frame_size, skb_tailroom(packet->skb)); - priv->ieee->stats.rx_errors++; + dev->stats.rx_errors++; return; } - if (unlikely(!netif_running(priv->net_dev))) { - priv->ieee->stats.rx_errors++; + if (unlikely(!netif_running(dev))) { + dev->stats.rx_errors++; priv->wstats.discard.misc++; IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); return; @@ -2498,7 +2507,7 @@ static void isr_rx_monitor(struct ipw2100_priv *priv, int i, if (unlikely(priv->config & CFG_CRC_CHECK && status->flags & IPW_STATUS_FLAG_CRC_ERROR)) { IPW_DEBUG_RX("CRC error in packet. Dropping.\n"); - priv->ieee->stats.rx_errors++; + dev->stats.rx_errors++; return; } @@ -2520,7 +2529,7 @@ static void isr_rx_monitor(struct ipw2100_priv *priv, int i, skb_put(packet->skb, status->frame_size + sizeof(struct ipw_rt_hdr)); if (!ieee80211_rx(priv->ieee, packet->skb, stats)) { - priv->ieee->stats.rx_errors++; + dev->stats.rx_errors++; /* ieee80211_rx failed, so it didn't free the SKB */ dev_kfree_skb_any(packet->skb); @@ -2531,7 +2540,7 @@ static void isr_rx_monitor(struct ipw2100_priv *priv, int i, if (unlikely(ipw2100_alloc_skb(priv, packet))) { IPW_DEBUG_WARNING( "%s: Unable to allocate SKB onto RBD ring - disabling " - "adapter.\n", priv->net_dev->name); + "adapter.\n", dev->name); /* TODO: schedule adapter shutdown */ IPW_DEBUG_INFO("TODO: Shutdown adapter...\n"); } @@ -3333,7 +3342,7 @@ static int ipw2100_tx(struct ieee80211_txb *txb, struct net_device *dev, if (!(priv->status & STATUS_ASSOCIATED)) { IPW_DEBUG_INFO("Can not transmit when not connected.\n"); - priv->ieee->stats.tx_carrier_errors++; + priv->net_dev->stats.tx_carrier_errors++; netif_stop_queue(dev); goto fail_unlock; } @@ -4058,7 +4067,7 @@ static ssize_t show_bssinfo(struct device *d, struct device_attribute *attr, u8 bssid[ETH_ALEN]; u32 chan = 0; char *out = buf; - int length; + unsigned int length; int ret; if (priv->status & STATUS_RF_KILL_MASK) @@ -5829,7 +5838,7 @@ static void ipw2100_tx_timeout(struct net_device *dev) { struct ipw2100_priv *priv = ieee80211_priv(dev); - priv->ieee->stats.tx_errors++; + dev->stats.tx_errors++; #ifdef CONFIG_IPW2100_MONITOR if (priv->ieee->iw_mode == IW_MODE_MONITOR) @@ -5999,6 +6008,17 @@ static void ipw2100_rf_kill(struct work_struct *work) static void ipw2100_irq_tasklet(struct ipw2100_priv *priv); +static const struct net_device_ops ipw2100_netdev_ops = { + .ndo_open = ipw2100_open, + .ndo_stop = ipw2100_close, + .ndo_start_xmit = ieee80211_xmit, + .ndo_change_mtu = ieee80211_change_mtu, + .ndo_init = ipw2100_net_init, + .ndo_tx_timeout = ipw2100_tx_timeout, + .ndo_set_mac_address = ipw2100_set_address, + .ndo_validate_addr = eth_validate_addr, +}; + /* Look into using netdev destructor to shutdown ieee80211? */ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, @@ -6023,15 +6043,11 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, priv->ieee->perfect_rssi = -20; priv->ieee->worst_rssi = -85; - dev->open = ipw2100_open; - dev->stop = ipw2100_close; - dev->init = ipw2100_net_init; + dev->netdev_ops = &ipw2100_netdev_ops; dev->ethtool_ops = &ipw2100_ethtool_ops; - dev->tx_timeout = ipw2100_tx_timeout; dev->wireless_handlers = &ipw2100_wx_handler_def; priv->wireless_data.ieee80211 = priv->ieee; dev->wireless_data = &priv->wireless_data; - dev->set_mac_address = ipw2100_set_address; dev->watchdog_timeo = 3 * HZ; dev->irq = 0; @@ -6414,6 +6430,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; @@ -6457,6 +6475,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); @@ -7122,7 +7142,7 @@ static int ipw2100_wx_get_rate(struct net_device *dev, { struct ipw2100_priv *priv = ieee80211_priv(dev); int val; - int len = sizeof(val); + unsigned int len = sizeof(val); int err = 0; if (!(priv->status & STATUS_ENABLED) || @@ -8297,7 +8317,7 @@ static void ipw2100_wx_event_work(struct work_struct *work) struct ipw2100_priv *priv = container_of(work, struct ipw2100_priv, wx_event_work.work); union iwreq_data wrqu; - int len = ETH_ALEN; + unsigned int len = ETH_ALEN; if (priv->status & STATUS_STOPPING) return; diff --git a/drivers/net/wireless/ipw2x00/ipw2100.h b/drivers/net/wireless/ipw2x00/ipw2100.h index bbf1ddcafba..f183d951cd3 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.h +++ b/drivers/net/wireless/ipw2x00/ipw2100.h @@ -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; diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 625f2cf99fa..b3449948a25 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -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) @@ -7717,22 +7731,23 @@ static void ipw_handle_data_packet(struct ipw_priv *priv, struct ipw_rx_mem_buffer *rxb, struct ieee80211_rx_stats *stats) { + struct net_device *dev = priv->net_dev; struct ieee80211_hdr_4addr *hdr; struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data; /* We received data from the HW, so stop the watchdog */ - priv->net_dev->trans_start = jiffies; + dev->trans_start = jiffies; /* We only process data packets if the * interface is open */ if (unlikely((le16_to_cpu(pkt->u.frame.length) + IPW_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) { - priv->ieee->stats.rx_errors++; + dev->stats.rx_errors++; priv->wstats.discard.misc++; IPW_DEBUG_DROP("Corruption detected! Oh no!\n"); return; } else if (unlikely(!netif_running(priv->net_dev))) { - priv->ieee->stats.rx_dropped++; + dev->stats.rx_dropped++; priv->wstats.discard.misc++; IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); return; @@ -7754,7 +7769,7 @@ static void ipw_handle_data_packet(struct ipw_priv *priv, ipw_rebuild_decrypted_skb(priv, rxb->skb); if (!ieee80211_rx(priv->ieee, rxb->skb, stats)) - priv->ieee->stats.rx_errors++; + dev->stats.rx_errors++; else { /* ieee80211_rx succeeded, so it now owns the SKB */ rxb->skb = NULL; __ipw_led_activity_on(priv); @@ -7766,6 +7781,7 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, struct ipw_rx_mem_buffer *rxb, struct ieee80211_rx_stats *stats) { + struct net_device *dev = priv->net_dev; struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data; struct ipw_rx_frame *frame = &pkt->u.frame; @@ -7783,18 +7799,18 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, short len = le16_to_cpu(pkt->u.frame.length); /* We received data from the HW, so stop the watchdog */ - priv->net_dev->trans_start = jiffies; + dev->trans_start = jiffies; /* We only process data packets if the * interface is open */ if (unlikely((le16_to_cpu(pkt->u.frame.length) + IPW_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) { - priv->ieee->stats.rx_errors++; + dev->stats.rx_errors++; priv->wstats.discard.misc++; IPW_DEBUG_DROP("Corruption detected! Oh no!\n"); return; } else if (unlikely(!netif_running(priv->net_dev))) { - priv->ieee->stats.rx_dropped++; + dev->stats.rx_dropped++; priv->wstats.discard.misc++; IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); return; @@ -7804,7 +7820,7 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, * that now */ if (len > IPW_RX_BUF_SIZE - sizeof(struct ipw_rt_hdr)) { /* FIXME: Should alloc bigger skb instead */ - priv->ieee->stats.rx_dropped++; + dev->stats.rx_dropped++; priv->wstats.discard.misc++; IPW_DEBUG_DROP("Dropping too large packet in monitor\n"); return; @@ -7910,7 +7926,7 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, IPW_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len); if (!ieee80211_rx(priv->ieee, rxb->skb, stats)) - priv->ieee->stats.rx_errors++; + dev->stats.rx_errors++; else { /* ieee80211_rx succeeded, so it now owns the SKB */ rxb->skb = NULL; /* no LED during capture */ @@ -7942,6 +7958,7 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, struct ipw_rx_mem_buffer *rxb, struct ieee80211_rx_stats *stats) { + struct net_device *dev = priv->prom_net_dev; struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data; struct ipw_rx_frame *frame = &pkt->u.frame; struct ipw_rt_hdr *ipw_rt; @@ -7964,17 +7981,17 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, return; /* We received data from the HW, so stop the watchdog */ - priv->prom_net_dev->trans_start = jiffies; + dev->trans_start = jiffies; if (unlikely((len + IPW_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) { - priv->prom_priv->ieee->stats.rx_errors++; + dev->stats.rx_errors++; IPW_DEBUG_DROP("Corruption detected! Oh no!\n"); return; } /* We only process data packets if the interface is open */ - if (unlikely(!netif_running(priv->prom_net_dev))) { - priv->prom_priv->ieee->stats.rx_dropped++; + if (unlikely(!netif_running(dev))) { + dev->stats.rx_dropped++; IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); return; } @@ -7983,7 +8000,7 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, * that now */ if (len > IPW_RX_BUF_SIZE - sizeof(struct ipw_rt_hdr)) { /* FIXME: Should alloc bigger skb instead */ - priv->prom_priv->ieee->stats.rx_dropped++; + dev->stats.rx_dropped++; IPW_DEBUG_DROP("Dropping too large packet in monitor\n"); return; } @@ -8115,7 +8132,7 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, IPW_DEBUG_RX("Rx packet of %d bytes.\n", skb->len); if (!ieee80211_rx(priv->prom_priv->ieee, skb, stats)) { - priv->prom_priv->ieee->stats.rx_errors++; + dev->stats.rx_errors++; dev_kfree_skb_any(skb); } } @@ -8272,7 +8289,7 @@ static void ipw_handle_mgmt_packet(struct ipw_priv *priv, skb_reset_mac_header(skb); skb->pkt_type = PACKET_OTHERHOST; - skb->protocol = __constant_htons(ETH_P_80211_STATS); + skb->protocol = cpu_to_be16(ETH_P_80211_STATS); memset(skb->cb, 0, sizeof(rxb->skb->cb)); netif_rx(skb); rxb->skb = NULL; @@ -8399,7 +8416,7 @@ static void ipw_rx(struct ipw_priv *priv) IPW_DEBUG_DROP ("Received packet is too small. " "Dropping.\n"); - priv->ieee->stats.rx_errors++; + priv->net_dev->stats.rx_errors++; priv->wstats.discard.misc++; break; } @@ -10470,15 +10487,6 @@ static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb, return ret; } -static struct net_device_stats *ipw_net_get_stats(struct net_device *dev) -{ - struct ipw_priv *priv = ieee80211_priv(dev); - - priv->ieee->stats.tx_packets = priv->tx_packets; - priv->ieee->stats.rx_packets = priv->rx_packets; - return &priv->ieee->stats; -} - static void ipw_net_set_multicast_list(struct net_device *dev) { @@ -11224,6 +11232,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; @@ -11515,11 +11529,14 @@ static int ipw_prom_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) return -EOPNOTSUPP; } -static struct net_device_stats *ipw_prom_get_stats(struct net_device *dev) -{ - struct ipw_prom_priv *prom_priv = ieee80211_priv(dev); - return &prom_priv->ieee->stats; -} +static const struct net_device_ops ipw_prom_netdev_ops = { + .ndo_open = ipw_prom_open, + .ndo_stop = ipw_prom_stop, + .ndo_start_xmit = ipw_prom_hard_start_xmit, + .ndo_change_mtu = ieee80211_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; static int ipw_prom_alloc(struct ipw_priv *priv) { @@ -11540,10 +11557,7 @@ static int ipw_prom_alloc(struct ipw_priv *priv) memcpy(priv->prom_net_dev->dev_addr, priv->mac_addr, ETH_ALEN); priv->prom_net_dev->type = ARPHRD_IEEE80211_RADIOTAP; - priv->prom_net_dev->open = ipw_prom_open; - priv->prom_net_dev->stop = ipw_prom_stop; - priv->prom_net_dev->get_stats = ipw_prom_get_stats; - priv->prom_net_dev->hard_start_xmit = ipw_prom_hard_start_xmit; + priv->prom_net_dev->netdev_ops = &ipw_prom_netdev_ops; priv->prom_priv->ieee->iw_mode = IW_MODE_MONITOR; SET_NETDEV_DEV(priv->prom_net_dev, &priv->pci_dev->dev); @@ -11571,6 +11585,17 @@ static void ipw_prom_free(struct ipw_priv *priv) #endif +static const struct net_device_ops ipw_netdev_ops = { + .ndo_init = ipw_net_init, + .ndo_open = ipw_net_open, + .ndo_stop = ipw_net_stop, + .ndo_set_multicast_list = ipw_net_set_multicast_list, + .ndo_set_mac_address = ipw_net_set_mac_address, + .ndo_start_xmit = ieee80211_xmit, + .ndo_change_mtu = ieee80211_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; static int __devinit ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -11672,12 +11697,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, priv->ieee->perfect_rssi = -20; priv->ieee->worst_rssi = -85; - net_dev->open = ipw_net_open; - net_dev->stop = ipw_net_stop; - net_dev->init = ipw_net_init; - net_dev->get_stats = ipw_net_get_stats; - net_dev->set_multicast_list = ipw_net_set_multicast_list; - net_dev->set_mac_address = ipw_net_set_mac_address; + net_dev->netdev_ops = &ipw_netdev_ops; priv->wireless_data.spy_data = &priv->ieee->spy_data; net_dev->wireless_data = &priv->wireless_data; net_dev->wireless_handlers = &ipw_wx_handler_def; @@ -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); diff --git a/drivers/net/wireless/ipw2x00/ipw2200.h b/drivers/net/wireless/ipw2x00/ipw2200.h index 277b274d4be..05e8ccf01c5 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.h +++ b/drivers/net/wireless/ipw2x00/ipw2200.h @@ -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 diff --git a/drivers/net/wireless/ipw2x00/libipw_geo.c b/drivers/net/wireless/ipw2x00/libipw_geo.c index 960ad13f5e9..9dfbb8760f6 100644 --- a/drivers/net/wireless/ipw2x00/libipw_geo.c +++ b/drivers/net/wireless/ipw2x00/libipw_geo.c @@ -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) { diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c index a2f5616d5b0..92a26922e79 100644 --- a/drivers/net/wireless/ipw2x00/libipw_module.c +++ b/drivers/net/wireless/ipw2x00/libipw_module.c @@ -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; @@ -116,20 +131,14 @@ static void ieee80211_networks_initialize(struct ieee80211_device *ieee) &ieee->network_free_list); } -static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) +int ieee80211_change_mtu(struct net_device *dev, int new_mtu) { if ((new_mtu < 68) || (new_mtu > IEEE80211_DATA_LEN)) return -EINVAL; dev->mtu = new_mtu; return 0; } - -static struct net_device_stats *ieee80211_generic_get_stats( - struct net_device *dev) -{ - struct ieee80211_device *ieee = netdev_priv(dev); - return &ieee->stats; -} +EXPORT_SYMBOL(ieee80211_change_mtu); struct net_device *alloc_ieee80211(int sizeof_priv) { @@ -145,12 +154,10 @@ struct net_device *alloc_ieee80211(int sizeof_priv) goto failed; } ieee = netdev_priv(dev); +#ifdef CONFIG_COMPAT_NET_DEV_OPS dev->hard_start_xmit = ieee80211_xmit; dev->change_mtu = ieee80211_change_mtu; - - /* Drivers are free to override this if the generic implementation - * does not meet their needs. */ - dev->get_stats = ieee80211_generic_get_stats; +#endif ieee->dev = dev; @@ -206,7 +213,7 @@ void free_ieee80211(struct net_device *dev) free_netdev(dev); } -#ifdef CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG static int debug = 0; u32 ieee80211_debug_level = 0; @@ -237,11 +244,11 @@ static int store_debug_level(struct file *file, const char __user * buffer, return strnlen(buf, len); } -#endif /* CONFIG_IEEE80211_DEBUG */ +#endif /* CONFIG_LIBIPW_DEBUG */ static int __init ieee80211_init(void) { -#ifdef CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG struct proc_dir_entry *e; ieee80211_debug_level = debug; @@ -261,7 +268,7 @@ static int __init ieee80211_init(void) e->read_proc = show_debug_level; e->write_proc = store_debug_level; e->data = NULL; -#endif /* CONFIG_IEEE80211_DEBUG */ +#endif /* CONFIG_LIBIPW_DEBUG */ printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); @@ -271,20 +278,20 @@ static int __init ieee80211_init(void) static void __exit ieee80211_exit(void) { -#ifdef CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG if (ieee80211_proc) { remove_proc_entry("debug_level", ieee80211_proc); remove_proc_entry(DRV_NAME, init_net.proc_net); ieee80211_proc = NULL; } -#endif /* CONFIG_IEEE80211_DEBUG */ +#endif /* CONFIG_LIBIPW_DEBUG */ } -#ifdef CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG #include <linux/moduleparam.h> module_param(debug, int, 0444); MODULE_PARM_DESC(debug, "debug output mask"); -#endif /* CONFIG_IEEE80211_DEBUG */ +#endif /* CONFIG_LIBIPW_DEBUG */ module_exit(ieee80211_exit); module_init(ieee80211_init); diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c index 9c67dfae432..dae4b8e4d8e 100644 --- a/drivers/net/wireless/ipw2x00/libipw_rx.c +++ b/drivers/net/wireless/ipw2x00/libipw_rx.c @@ -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, @@ -334,7 +335,6 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_hdr_4addr *hdr; size_t hdrlen; u16 fc, type, stype, sc; - struct net_device_stats *stats; unsigned int frag; u8 *payload; u16 ethertype; @@ -353,8 +353,6 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, int can_be_decrypted = 0; hdr = (struct ieee80211_hdr_4addr *)skb->data; - stats = &ieee->stats; - if (skb->len < 10) { printk(KERN_INFO "%s: SKB length < 10\n", dev->name); goto rx_dropped; @@ -411,8 +409,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, #endif if (ieee->iw_mode == IW_MODE_MONITOR) { - stats->rx_packets++; - stats->rx_bytes += skb->len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; ieee80211_monitor_rx(ieee, skb, rx_stats); return 1; } @@ -768,8 +766,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, } #endif - stats->rx_packets++; - stats->rx_bytes += skb->len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; #ifdef NOT_YET if (ieee->iw_mode == IW_MODE_MASTER && !wds && ieee->ap->bridge_packets) { @@ -811,7 +809,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, * in our stats. */ IEEE80211_DEBUG_DROP ("RX: netif_rx dropped the packet\n"); - stats->rx_dropped++; + dev->stats.rx_dropped++; } } @@ -823,7 +821,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, return 1; rx_dropped: - stats->rx_dropped++; + dev->stats.rx_dropped++; /* Returning 0 indicates to caller that we have not handled the SKB-- * so it is still allocated and can be used again by underlying @@ -918,7 +916,7 @@ void ieee80211_rx_any(struct ieee80211_device *ieee, drop_free: dev_kfree_skb_irq(skb); - ieee->stats.rx_dropped++; + ieee->dev->stats.rx_dropped++; return; } @@ -1079,37 +1077,37 @@ static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element return rc; } -#ifdef CONFIG_IEEE80211_DEBUG -#define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x +#ifdef CONFIG_LIBIPW_DEBUG +#define MFIE_STRING(x) case WLAN_EID_ ##x: return #x static const char *get_info_element_string(u16 id) { switch (id) { MFIE_STRING(SSID); - MFIE_STRING(RATES); - MFIE_STRING(FH_SET); - MFIE_STRING(DS_SET); - MFIE_STRING(CF_SET); + MFIE_STRING(SUPP_RATES); + MFIE_STRING(FH_PARAMS); + MFIE_STRING(DS_PARAMS); + MFIE_STRING(CF_PARAMS); MFIE_STRING(TIM); - MFIE_STRING(IBSS_SET); + MFIE_STRING(IBSS_PARAMS); MFIE_STRING(COUNTRY); - MFIE_STRING(HOP_PARAMS); - MFIE_STRING(HOP_TABLE); + MFIE_STRING(HP_PARAMS); + MFIE_STRING(HP_TABLE); MFIE_STRING(REQUEST); MFIE_STRING(CHALLENGE); - MFIE_STRING(POWER_CONSTRAINT); - MFIE_STRING(POWER_CAPABILITY); + MFIE_STRING(PWR_CONSTRAINT); + MFIE_STRING(PWR_CAPABILITY); MFIE_STRING(TPC_REQUEST); MFIE_STRING(TPC_REPORT); - MFIE_STRING(SUPP_CHANNELS); - MFIE_STRING(CSA); + MFIE_STRING(SUPPORTED_CHANNELS); + MFIE_STRING(CHANNEL_SWITCH); MFIE_STRING(MEASURE_REQUEST); MFIE_STRING(MEASURE_REPORT); MFIE_STRING(QUIET); MFIE_STRING(IBSS_DFS); MFIE_STRING(ERP_INFO); MFIE_STRING(RSN); - MFIE_STRING(RATES_EX); + MFIE_STRING(EXT_SUPP_RATES); MFIE_STRING(GENERIC); MFIE_STRING(QOS_PARAMETER); default: @@ -1124,7 +1122,7 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element { DECLARE_SSID_BUF(ssid); u8 i; -#ifdef CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG char rates_str[64]; char *p; #endif @@ -1144,7 +1142,7 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element } switch (info_element->id) { - case MFIE_TYPE_SSID: + case WLAN_EID_SSID: network->ssid_len = min(info_element->len, (u8) IW_ESSID_MAX_SIZE); memcpy(network->ssid, info_element->data, @@ -1153,21 +1151,21 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element memset(network->ssid + network->ssid_len, 0, IW_ESSID_MAX_SIZE - network->ssid_len); - IEEE80211_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n", + IEEE80211_DEBUG_MGMT("WLAN_EID_SSID: '%s' len=%d.\n", print_ssid(ssid, network->ssid, network->ssid_len), network->ssid_len); break; - case MFIE_TYPE_RATES: -#ifdef CONFIG_IEEE80211_DEBUG + case WLAN_EID_SUPP_RATES: +#ifdef CONFIG_LIBIPW_DEBUG p = rates_str; #endif network->rates_len = min(info_element->len, MAX_RATES_LENGTH); for (i = 0; i < network->rates_len; i++) { network->rates[i] = info_element->data[i]; -#ifdef CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]); @@ -1182,19 +1180,19 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element } } - IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n", + IEEE80211_DEBUG_MGMT("WLAN_EID_SUPP_RATES: '%s' (%d)\n", rates_str, network->rates_len); break; - case MFIE_TYPE_RATES_EX: -#ifdef CONFIG_IEEE80211_DEBUG + case WLAN_EID_EXT_SUPP_RATES: +#ifdef CONFIG_LIBIPW_DEBUG p = rates_str; #endif network->rates_ex_len = min(info_element->len, MAX_RATES_EX_LENGTH); for (i = 0; i < network->rates_ex_len; i++) { network->rates_ex[i] = info_element->data[i]; -#ifdef CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]); @@ -1209,49 +1207,49 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element } } - IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n", + IEEE80211_DEBUG_MGMT("WLAN_EID_EXT_SUPP_RATES: '%s' (%d)\n", rates_str, network->rates_ex_len); break; - case MFIE_TYPE_DS_SET: - IEEE80211_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n", + case WLAN_EID_DS_PARAMS: + IEEE80211_DEBUG_MGMT("WLAN_EID_DS_PARAMS: %d\n", info_element->data[0]); network->channel = info_element->data[0]; break; - case MFIE_TYPE_FH_SET: - IEEE80211_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n"); + case WLAN_EID_FH_PARAMS: + IEEE80211_DEBUG_MGMT("WLAN_EID_FH_PARAMS: ignored\n"); break; - case MFIE_TYPE_CF_SET: - IEEE80211_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n"); + case WLAN_EID_CF_PARAMS: + IEEE80211_DEBUG_MGMT("WLAN_EID_CF_PARAMS: ignored\n"); break; - case MFIE_TYPE_TIM: + case WLAN_EID_TIM: network->tim.tim_count = info_element->data[0]; network->tim.tim_period = info_element->data[1]; - IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: partially ignored\n"); + IEEE80211_DEBUG_MGMT("WLAN_EID_TIM: partially ignored\n"); break; - case MFIE_TYPE_ERP_INFO: + case WLAN_EID_ERP_INFO: network->erp_value = info_element->data[0]; network->flags |= NETWORK_HAS_ERP_VALUE; IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n", network->erp_value); break; - case MFIE_TYPE_IBSS_SET: + case WLAN_EID_IBSS_PARAMS: network->atim_window = info_element->data[0]; - IEEE80211_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n", + IEEE80211_DEBUG_MGMT("WLAN_EID_IBSS_PARAMS: %d\n", network->atim_window); break; - case MFIE_TYPE_CHALLENGE: - IEEE80211_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n"); + case WLAN_EID_CHALLENGE: + IEEE80211_DEBUG_MGMT("WLAN_EID_CHALLENGE: ignored\n"); break; - case MFIE_TYPE_GENERIC: - IEEE80211_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n", + case WLAN_EID_GENERIC: + IEEE80211_DEBUG_MGMT("WLAN_EID_GENERIC: %d bytes\n", info_element->len); if (!ieee80211_parse_qos_info_param_IE(info_element, network)) @@ -1269,8 +1267,8 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element } break; - case MFIE_TYPE_RSN: - IEEE80211_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n", + case WLAN_EID_RSN: + IEEE80211_DEBUG_MGMT("WLAN_EID_RSN: %d bytes\n", info_element->len); network->rsn_ie_len = min(info_element->len + 2, MAX_WPA_IE_LEN); @@ -1278,22 +1276,22 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element network->rsn_ie_len); break; - case MFIE_TYPE_QOS_PARAMETER: + case WLAN_EID_QOS_PARAMETER: printk(KERN_ERR "QoS Error need to parse QOS_PARAMETER IE\n"); break; /* 802.11h */ - case MFIE_TYPE_POWER_CONSTRAINT: + case WLAN_EID_PWR_CONSTRAINT: network->power_constraint = info_element->data[0]; network->flags |= NETWORK_HAS_POWER_CONSTRAINT; break; - case MFIE_TYPE_CSA: + case WLAN_EID_CHANNEL_SWITCH: network->power_constraint = info_element->data[0]; network->flags |= NETWORK_HAS_CSA; break; - case MFIE_TYPE_QUIET: + case WLAN_EID_QUIET: network->quiet.count = info_element->data[0]; network->quiet.period = info_element->data[1]; network->quiet.duration = info_element->data[2]; @@ -1301,7 +1299,7 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element network->flags |= NETWORK_HAS_QUIET; break; - case MFIE_TYPE_IBSS_DFS: + case WLAN_EID_IBSS_DFS: if (network->ibss_dfs) break; network->ibss_dfs = kmemdup(info_element->data, @@ -1312,7 +1310,7 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element network->flags |= NETWORK_HAS_IBSS_DFS; break; - case MFIE_TYPE_TPC_REPORT: + case WLAN_EID_TPC_REPORT: network->tpc_report.transmit_power = info_element->data[0]; network->tpc_report.link_margin = info_element->data[1]; @@ -1561,7 +1559,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device }; struct ieee80211_network *target; struct ieee80211_network *oldest = NULL; -#ifdef CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG struct ieee80211_info_element *info_element = beacon->info_element; #endif unsigned long flags; @@ -1615,7 +1613,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; } @@ -1639,7 +1637,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device list_del(ieee->network_free_list.next); } -#ifdef CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n", print_ssid(ssid, network.ssid, network.ssid_len), diff --git a/drivers/net/wireless/ipw2x00/libipw_tx.c b/drivers/net/wireless/ipw2x00/libipw_tx.c index f78f57e8844..65a8195b3d9 100644 --- a/drivers/net/wireless/ipw2x00/libipw_tx.c +++ b/drivers/net/wireless/ipw2x00/libipw_tx.c @@ -41,7 +41,7 @@ #include <linux/etherdevice.h> #include <asm/uaccess.h> -#include <net/ieee80211.h> +#include "ieee80211.h" /* @@ -260,7 +260,6 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size, rts_required; unsigned long flags; - struct net_device_stats *stats = &ieee->stats; int encrypt, host_encrypt, host_encrypt_msdu, host_build_iv; __be16 ether_type; int bytes, fc, hdr_len; @@ -306,7 +305,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) if (!encrypt && ieee->ieee802_1x && ieee->drop_unencrypted && ether_type != htons(ETH_P_PAE)) { - stats->tx_dropped++; + dev->stats.tx_dropped++; goto success; } @@ -526,8 +525,8 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) if (txb) { int ret = (*ieee->hard_start_xmit) (txb, dev, priority); if (ret == 0) { - stats->tx_packets++; - stats->tx_bytes += txb->payload_size; + dev->stats.tx_packets++; + dev->stats.tx_bytes += txb->payload_size; return 0; } @@ -539,8 +538,9 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) failed: spin_unlock_irqrestore(&ieee->lock, flags); netif_stop_queue(dev); - stats->tx_errors++; + dev->stats.tx_errors++; return 1; } +EXPORT_SYMBOL(ieee80211_xmit); EXPORT_SYMBOL(ieee80211_txb_free); diff --git a/drivers/net/wireless/ipw2x00/libipw_wx.c b/drivers/net/wireless/ipw2x00/libipw_wx.c index 31ea3abfc32..3c0812db030 100644 --- a/drivers/net/wireless/ipw2x00/libipw_wx.c +++ b/drivers/net/wireless/ipw2x00/libipw_wx.c @@ -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); |