diff options
Diffstat (limited to 'drivers/net/wireless/airo.c')
| -rw-r--r-- | drivers/net/wireless/airo.c | 3253 |
1 files changed, 1645 insertions, 1608 deletions
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 074055e18c5..64747d457bb 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -36,8 +36,8 @@ #include <linux/bitops.h> #include <linux/scatterlist.h> #include <linux/crypto.h> -#include <asm/io.h> -#include <asm/system.h> +#include <linux/io.h> +#include <asm/unaligned.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> @@ -45,17 +45,19 @@ #include <linux/if_arp.h> #include <linux/ioport.h> #include <linux/pci.h> -#include <asm/uaccess.h> -#include <net/ieee80211.h> +#include <linux/uaccess.h> #include <linux/kthread.h> #include <linux/freezer.h> +#include <net/cfg80211.h> +#include <net/iw_handler.h> + #include "airo.h" #define DRV_NAME "airo" #ifdef CONFIG_PCI -static struct pci_device_id card_ids[] = { +static DEFINE_PCI_DEVICE_TABLE(card_ids) = { { 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, }, { 0x14b9, 0x4500, PCI_ANY_ID, PCI_ANY_ID }, { 0x14b9, 0x4800, PCI_ANY_ID, PCI_ANY_ID, }, @@ -76,7 +78,7 @@ static struct pci_driver airo_driver = { .name = DRV_NAME, .id_table = card_ids, .probe = airo_pci_probe, - .remove = __devexit_p(airo_pci_remove), + .remove = airo_pci_remove, .suspend = airo_pci_suspend, .resume = airo_pci_resume, }; @@ -84,10 +86,9 @@ static struct pci_driver airo_driver = { /* Include Wireless Extension definition and check version - Jean II */ #include <linux/wireless.h> -#define WIRELESS_SPY // enable iwspy support -#include <net/iw_handler.h> // New driver API +#define WIRELESS_SPY /* enable iwspy support */ -#define CISCO_EXT // enable Cisco extensions +#define CISCO_EXT /* enable Cisco extensions */ #ifdef CISCO_EXT #include <linux/delay.h> #endif @@ -102,7 +103,7 @@ static struct pci_driver airo_driver = { of statistics in the /proc filesystem */ #define IGNLABEL(comment) NULL -static char *statsLabels[] = { +static const char *statsLabels[] = { "RxOverrun", IGNLABEL("RxPlcpCrcErr"), IGNLABEL("RxPlcpFormatErr"), @@ -214,7 +215,6 @@ static char *statsLabels[] = { (no spaces) list of rates (up to 8). */ static int rates[8]; -static int basic_rate; static char *ssids[3]; static int io[4]; @@ -231,8 +231,10 @@ static int adhoc; static int probe = 1; +static kuid_t proc_kuid; static int proc_uid /* = 0 */; +static kgid_t proc_kgid; static int proc_gid /* = 0 */; static int airo_perm = 0555; @@ -240,29 +242,29 @@ static int airo_perm = 0555; static int proc_perm = 0644; MODULE_AUTHOR("Benjamin Reed"); -MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet \ -cards. Direct support for ISA/PCI/MPI cards and support \ -for PCMCIA when used with airo_cs."); +MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet cards. " + "Direct support for ISA/PCI/MPI cards and support for PCMCIA when used with airo_cs."); MODULE_LICENSE("Dual BSD/GPL"); MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340/350"); module_param_array(io, int, NULL, 0); module_param_array(irq, int, NULL, 0); -module_param(basic_rate, int, 0); module_param_array(rates, int, NULL, 0); module_param_array(ssids, charp, NULL, 0); module_param(auto_wep, int, 0); -MODULE_PARM_DESC(auto_wep, "If non-zero, the driver will keep looping through \ -the authentication options until an association is made. The value of \ -auto_wep is number of the wep keys to check. A value of 2 will try using \ -the key at index 0 and index 1."); +MODULE_PARM_DESC(auto_wep, + "If non-zero, the driver will keep looping through the authentication options until an association is made. " + "The value of auto_wep is number of the wep keys to check. " + "A value of 2 will try using the key at index 0 and index 1."); module_param(aux_bap, int, 0); -MODULE_PARM_DESC(aux_bap, "If non-zero, the driver will switch into a mode \ -than seems to work better for older cards with some older buses. Before \ -switching it checks that the switch is needed."); +MODULE_PARM_DESC(aux_bap, + "If non-zero, the driver will switch into a mode that seems to work better for older cards with some older buses. " + "Before switching it checks that the switch is needed."); module_param(maxencrypt, int, 0); -MODULE_PARM_DESC(maxencrypt, "The maximum speed that the card can do \ -encryption. Units are in 512kbs. Zero (default) means there is no limit. \ -Older cards used to be limited to 2mbs (4)."); +MODULE_PARM_DESC(maxencrypt, + "The maximum speed that the card can do encryption. " + "Units are in 512kbs. " + "Zero (default) means there is no limit. " + "Older cards used to be limited to 2mbs (4)."); module_param(adhoc, int, 0); MODULE_PARM_DESC(adhoc, "If non-zero, the card will start in adhoc mode."); module_param(probe, int, 0); @@ -280,7 +282,7 @@ MODULE_PARM_DESC(proc_perm, "The permission bits of the files in /proc"); /* This is a kind of sloppy hack to get this information to OUT4500 and IN4500. I would be extremely interested in the situation where this doesn't work though!!! */ -static int do8bitIO = 0; +static int do8bitIO /* = 0 */; /* Return codes */ #define SUCCESS 0 @@ -397,8 +399,8 @@ static int do8bitIO = 0; #define MAXTXQ 64 /* BAP selectors */ -#define BAP0 0 // Used for receiving packets -#define BAP1 2 // Used for xmiting packets and working with RIDS +#define BAP0 0 /* Used for receiving packets */ +#define BAP1 2 /* Used for xmiting packets and working with RIDS */ /* Flags */ #define COMMAND_BUSY 0x8000 @@ -494,146 +496,151 @@ typedef struct { * so all rid access should use the read/writeXXXRid routines. */ -/* This is redundant for x86 archs, but it seems necessary for ARM */ -#pragma pack(1) - /* This structure came from an email sent to me from an engineer at aironet for inclusion into this driver */ -typedef struct { - u16 len; - u16 kindex; +typedef struct WepKeyRid WepKeyRid; +struct WepKeyRid { + __le16 len; + __le16 kindex; u8 mac[ETH_ALEN]; - u16 klen; + __le16 klen; u8 key[16]; -} WepKeyRid; +} __packed; /* These structures are from the Aironet's PC4500 Developers Manual */ -typedef struct { - u16 len; +typedef struct Ssid Ssid; +struct Ssid { + __le16 len; u8 ssid[32]; -} Ssid; +} __packed; -typedef struct { - u16 len; +typedef struct SsidRid SsidRid; +struct SsidRid { + __le16 len; Ssid ssids[3]; -} SsidRid; - -typedef struct { - u16 len; - u16 modulation; -#define MOD_DEFAULT 0 -#define MOD_CCK 1 -#define MOD_MOK 2 -} ModulationRid; - -typedef struct { - u16 len; /* sizeof(ConfigRid) */ - u16 opmode; /* operating mode */ -#define MODE_STA_IBSS 0 -#define MODE_STA_ESS 1 -#define MODE_AP 2 -#define MODE_AP_RPTR 3 -#define MODE_ETHERNET_HOST (0<<8) /* rx payloads converted */ -#define MODE_LLC_HOST (1<<8) /* rx payloads left as is */ -#define MODE_AIRONET_EXTEND (1<<9) /* enable Aironet extenstions */ -#define MODE_AP_INTERFACE (1<<10) /* enable ap interface extensions */ -#define MODE_ANTENNA_ALIGN (1<<11) /* enable antenna alignment */ -#define MODE_ETHER_LLC (1<<12) /* enable ethernet LLC */ -#define MODE_LEAF_NODE (1<<13) /* enable leaf node bridge */ -#define MODE_CF_POLLABLE (1<<14) /* enable CF pollable */ -#define MODE_MIC (1<<15) /* enable MIC */ - u16 rmode; /* receive mode */ -#define RXMODE_BC_MC_ADDR 0 -#define RXMODE_BC_ADDR 1 /* ignore multicasts */ -#define RXMODE_ADDR 2 /* ignore multicast and broadcast */ -#define RXMODE_RFMON 3 /* wireless monitor mode */ -#define RXMODE_RFMON_ANYBSS 4 -#define RXMODE_LANMON 5 /* lan style monitor -- data packets only */ -#define RXMODE_DISABLE_802_3_HEADER (1<<8) /* disables 802.3 header on rx */ -#define RXMODE_NORMALIZED_RSSI (1<<9) /* return normalized RSSI */ - u16 fragThresh; - u16 rtsThres; +} __packed; + +typedef struct ModulationRid ModulationRid; +struct ModulationRid { + __le16 len; + __le16 modulation; +#define MOD_DEFAULT cpu_to_le16(0) +#define MOD_CCK cpu_to_le16(1) +#define MOD_MOK cpu_to_le16(2) +} __packed; + +typedef struct ConfigRid ConfigRid; +struct ConfigRid { + __le16 len; /* sizeof(ConfigRid) */ + __le16 opmode; /* operating mode */ +#define MODE_STA_IBSS cpu_to_le16(0) +#define MODE_STA_ESS cpu_to_le16(1) +#define MODE_AP cpu_to_le16(2) +#define MODE_AP_RPTR cpu_to_le16(3) +#define MODE_CFG_MASK cpu_to_le16(0xff) +#define MODE_ETHERNET_HOST cpu_to_le16(0<<8) /* rx payloads converted */ +#define MODE_LLC_HOST cpu_to_le16(1<<8) /* rx payloads left as is */ +#define MODE_AIRONET_EXTEND cpu_to_le16(1<<9) /* enable Aironet extenstions */ +#define MODE_AP_INTERFACE cpu_to_le16(1<<10) /* enable ap interface extensions */ +#define MODE_ANTENNA_ALIGN cpu_to_le16(1<<11) /* enable antenna alignment */ +#define MODE_ETHER_LLC cpu_to_le16(1<<12) /* enable ethernet LLC */ +#define MODE_LEAF_NODE cpu_to_le16(1<<13) /* enable leaf node bridge */ +#define MODE_CF_POLLABLE cpu_to_le16(1<<14) /* enable CF pollable */ +#define MODE_MIC cpu_to_le16(1<<15) /* enable MIC */ + __le16 rmode; /* receive mode */ +#define RXMODE_BC_MC_ADDR cpu_to_le16(0) +#define RXMODE_BC_ADDR cpu_to_le16(1) /* ignore multicasts */ +#define RXMODE_ADDR cpu_to_le16(2) /* ignore multicast and broadcast */ +#define RXMODE_RFMON cpu_to_le16(3) /* wireless monitor mode */ +#define RXMODE_RFMON_ANYBSS cpu_to_le16(4) +#define RXMODE_LANMON cpu_to_le16(5) /* lan style monitor -- data packets only */ +#define RXMODE_MASK cpu_to_le16(255) +#define RXMODE_DISABLE_802_3_HEADER cpu_to_le16(1<<8) /* disables 802.3 header on rx */ +#define RXMODE_FULL_MASK (RXMODE_MASK | RXMODE_DISABLE_802_3_HEADER) +#define RXMODE_NORMALIZED_RSSI cpu_to_le16(1<<9) /* return normalized RSSI */ + __le16 fragThresh; + __le16 rtsThres; u8 macAddr[ETH_ALEN]; u8 rates[8]; - u16 shortRetryLimit; - u16 longRetryLimit; - u16 txLifetime; /* in kusec */ - u16 rxLifetime; /* in kusec */ - u16 stationary; - u16 ordering; - u16 u16deviceType; /* for overriding device type */ - u16 cfpRate; - u16 cfpDuration; - u16 _reserved1[3]; + __le16 shortRetryLimit; + __le16 longRetryLimit; + __le16 txLifetime; /* in kusec */ + __le16 rxLifetime; /* in kusec */ + __le16 stationary; + __le16 ordering; + __le16 u16deviceType; /* for overriding device type */ + __le16 cfpRate; + __le16 cfpDuration; + __le16 _reserved1[3]; /*---------- Scanning/Associating ----------*/ - u16 scanMode; -#define SCANMODE_ACTIVE 0 -#define SCANMODE_PASSIVE 1 -#define SCANMODE_AIROSCAN 2 - u16 probeDelay; /* in kusec */ - u16 probeEnergyTimeout; /* in kusec */ - u16 probeResponseTimeout; - u16 beaconListenTimeout; - u16 joinNetTimeout; - u16 authTimeout; - u16 authType; -#define AUTH_OPEN 0x1 -#define AUTH_ENCRYPT 0x101 -#define AUTH_SHAREDKEY 0x102 -#define AUTH_ALLOW_UNENCRYPTED 0x200 - u16 associationTimeout; - u16 specifiedApTimeout; - u16 offlineScanInterval; - u16 offlineScanDuration; - u16 linkLossDelay; - u16 maxBeaconLostTime; - u16 refreshInterval; -#define DISABLE_REFRESH 0xFFFF - u16 _reserved1a[1]; + __le16 scanMode; +#define SCANMODE_ACTIVE cpu_to_le16(0) +#define SCANMODE_PASSIVE cpu_to_le16(1) +#define SCANMODE_AIROSCAN cpu_to_le16(2) + __le16 probeDelay; /* in kusec */ + __le16 probeEnergyTimeout; /* in kusec */ + __le16 probeResponseTimeout; + __le16 beaconListenTimeout; + __le16 joinNetTimeout; + __le16 authTimeout; + __le16 authType; +#define AUTH_OPEN cpu_to_le16(0x1) +#define AUTH_ENCRYPT cpu_to_le16(0x101) +#define AUTH_SHAREDKEY cpu_to_le16(0x102) +#define AUTH_ALLOW_UNENCRYPTED cpu_to_le16(0x200) + __le16 associationTimeout; + __le16 specifiedApTimeout; + __le16 offlineScanInterval; + __le16 offlineScanDuration; + __le16 linkLossDelay; + __le16 maxBeaconLostTime; + __le16 refreshInterval; +#define DISABLE_REFRESH cpu_to_le16(0xFFFF) + __le16 _reserved1a[1]; /*---------- Power save operation ----------*/ - u16 powerSaveMode; -#define POWERSAVE_CAM 0 -#define POWERSAVE_PSP 1 -#define POWERSAVE_PSPCAM 2 - u16 sleepForDtims; - u16 listenInterval; - u16 fastListenInterval; - u16 listenDecay; - u16 fastListenDelay; - u16 _reserved2[2]; + __le16 powerSaveMode; +#define POWERSAVE_CAM cpu_to_le16(0) +#define POWERSAVE_PSP cpu_to_le16(1) +#define POWERSAVE_PSPCAM cpu_to_le16(2) + __le16 sleepForDtims; + __le16 listenInterval; + __le16 fastListenInterval; + __le16 listenDecay; + __le16 fastListenDelay; + __le16 _reserved2[2]; /*---------- Ap/Ibss config items ----------*/ - u16 beaconPeriod; - u16 atimDuration; - u16 hopPeriod; - u16 channelSet; - u16 channel; - u16 dtimPeriod; - u16 bridgeDistance; - u16 radioID; + __le16 beaconPeriod; + __le16 atimDuration; + __le16 hopPeriod; + __le16 channelSet; + __le16 channel; + __le16 dtimPeriod; + __le16 bridgeDistance; + __le16 radioID; /*---------- Radio configuration ----------*/ - u16 radioType; -#define RADIOTYPE_DEFAULT 0 -#define RADIOTYPE_802_11 1 -#define RADIOTYPE_LEGACY 2 + __le16 radioType; +#define RADIOTYPE_DEFAULT cpu_to_le16(0) +#define RADIOTYPE_802_11 cpu_to_le16(1) +#define RADIOTYPE_LEGACY cpu_to_le16(2) u8 rxDiversity; u8 txDiversity; - u16 txPower; + __le16 txPower; #define TXPOWER_DEFAULT 0 - u16 rssiThreshold; + __le16 rssiThreshold; #define RSSI_DEFAULT 0 - u16 modulation; -#define PREAMBLE_AUTO 0 -#define PREAMBLE_LONG 1 -#define PREAMBLE_SHORT 2 - u16 preamble; - u16 homeProduct; - u16 radioSpecific; + __le16 modulation; +#define PREAMBLE_AUTO cpu_to_le16(0) +#define PREAMBLE_LONG cpu_to_le16(1) +#define PREAMBLE_SHORT cpu_to_le16(2) + __le16 preamble; + __le16 homeProduct; + __le16 radioSpecific; /*---------- Aironet Extensions ----------*/ u8 nodeName[16]; - u16 arlThreshold; - u16 arlDecay; - u16 arlDelay; - u16 _reserved4[1]; + __le16 arlThreshold; + __le16 arlDecay; + __le16 arlDelay; + __le16 _reserved4[1]; /*---------- Aironet Extensions ----------*/ u8 magicAction; #define MAGIC_ACTION_STSCHG 1 @@ -643,34 +650,35 @@ typedef struct { #define MAGIC_SWITCH_TO_PSP (0<<10) #define MAGIC_STAY_IN_CAM (1<<10) u8 magicControl; - u16 autoWake; -} ConfigRid; + __le16 autoWake; +} __packed; -typedef struct { - u16 len; +typedef struct StatusRid StatusRid; +struct StatusRid { + __le16 len; u8 mac[ETH_ALEN]; - u16 mode; - u16 errorCode; - u16 sigQuality; - u16 SSIDlen; + __le16 mode; + __le16 errorCode; + __le16 sigQuality; + __le16 SSIDlen; char SSID[32]; char apName[16]; u8 bssid[4][ETH_ALEN]; - u16 beaconPeriod; - u16 dimPeriod; - u16 atimDuration; - u16 hopPeriod; - u16 channelSet; - u16 channel; - u16 hopsToBackbone; - u16 apTotalLoad; - u16 generatedLoad; - u16 accumulatedArl; - u16 signalQuality; - u16 currentXmitRate; - u16 apDevExtensions; - u16 normalizedSignalStrength; - u16 shortPreamble; + __le16 beaconPeriod; + __le16 dimPeriod; + __le16 atimDuration; + __le16 hopPeriod; + __le16 channelSet; + __le16 channel; + __le16 hopsToBackbone; + __le16 apTotalLoad; + __le16 generatedLoad; + __le16 accumulatedArl; + __le16 signalQuality; + __le16 currentXmitRate; + __le16 apDevExtensions; + __le16 normalizedSignalStrength; + __le16 shortPreamble; u8 apIP[4]; u8 noisePercent; /* Noise percent in last second */ u8 noisedBm; /* Noise dBm in last second */ @@ -678,9 +686,9 @@ typedef struct { u8 noiseAvedBm; /* Noise dBm in last minute */ u8 noiseMaxPercent; /* Highest noise percent in last minute */ u8 noiseMaxdBm; /* Highest noise dbm in last minute */ - u16 load; + __le16 load; u8 carrier[4]; - u16 assocStatus; + __le16 assocStatus; #define STAT_NOPACKETS 0 #define STAT_NOCARRIERSET 10 #define STAT_GOTCARRIERSET 11 @@ -702,116 +710,123 @@ typedef struct { #define STAT_LEAPFAILED 91 #define STAT_LEAPTIMEDOUT 92 #define STAT_LEAPCOMPLETE 93 -} StatusRid; - -typedef struct { - u16 len; - u16 spacer; - u32 vals[100]; -} StatsRid; - - -typedef struct { - u16 len; +} __packed; + +typedef struct StatsRid StatsRid; +struct StatsRid { + __le16 len; + __le16 spacer; + __le32 vals[100]; +} __packed; + +typedef struct APListRid APListRid; +struct APListRid { + __le16 len; u8 ap[4][ETH_ALEN]; -} APListRid; +} __packed; -typedef struct { - u16 len; +typedef struct CapabilityRid CapabilityRid; +struct CapabilityRid { + __le16 len; char oui[3]; char zero; - u16 prodNum; + __le16 prodNum; char manName[32]; char prodName[16]; char prodVer[8]; char factoryAddr[ETH_ALEN]; char aironetAddr[ETH_ALEN]; - u16 radioType; - u16 country; + __le16 radioType; + __le16 country; char callid[ETH_ALEN]; char supportedRates[8]; char rxDiversity; char txDiversity; - u16 txPowerLevels[8]; - u16 hardVer; - u16 hardCap; - u16 tempRange; - u16 softVer; - u16 softSubVer; - u16 interfaceVer; - u16 softCap; - u16 bootBlockVer; - u16 requiredHard; - u16 extSoftCap; -} CapabilityRid; - + __le16 txPowerLevels[8]; + __le16 hardVer; + __le16 hardCap; + __le16 tempRange; + __le16 softVer; + __le16 softSubVer; + __le16 interfaceVer; + __le16 softCap; + __le16 bootBlockVer; + __le16 requiredHard; + __le16 extSoftCap; +} __packed; /* Only present on firmware >= 5.30.17 */ -typedef struct { - u16 unknown[4]; +typedef struct BSSListRidExtra BSSListRidExtra; +struct BSSListRidExtra { + __le16 unknown[4]; u8 fixed[12]; /* WLAN management frame */ u8 iep[624]; -} BSSListRidExtra; +} __packed; -typedef struct { - u16 len; - u16 index; /* First is 0 and 0xffff means end of list */ +typedef struct BSSListRid BSSListRid; +struct BSSListRid { + __le16 len; + __le16 index; /* First is 0 and 0xffff means end of list */ #define RADIO_FH 1 /* Frequency hopping radio type */ #define RADIO_DS 2 /* Direct sequence radio type */ #define RADIO_TMA 4 /* Proprietary radio used in old cards (2500) */ - u16 radioType; + __le16 radioType; u8 bssid[ETH_ALEN]; /* Mac address of the BSS */ u8 zero; u8 ssidLen; u8 ssid[32]; - u16 dBm; -#define CAP_ESS (1<<0) -#define CAP_IBSS (1<<1) -#define CAP_PRIVACY (1<<4) -#define CAP_SHORTHDR (1<<5) - u16 cap; - u16 beaconInterval; + __le16 dBm; +#define CAP_ESS cpu_to_le16(1<<0) +#define CAP_IBSS cpu_to_le16(1<<1) +#define CAP_PRIVACY cpu_to_le16(1<<4) +#define CAP_SHORTHDR cpu_to_le16(1<<5) + __le16 cap; + __le16 beaconInterval; u8 rates[8]; /* Same as rates for config rid */ struct { /* For frequency hopping only */ - u16 dwell; + __le16 dwell; u8 hopSet; u8 hopPattern; u8 hopIndex; u8 fill; } fh; - u16 dsChannel; - u16 atimWindow; + __le16 dsChannel; + __le16 atimWindow; /* Only present on firmware >= 5.30.17 */ BSSListRidExtra extra; -} BSSListRid; +} __packed; typedef struct { BSSListRid bss; struct list_head list; } BSSListElement; -typedef struct { +typedef struct tdsRssiEntry tdsRssiEntry; +struct tdsRssiEntry { u8 rssipct; u8 rssidBm; -} tdsRssiEntry; +} __packed; -typedef struct { +typedef struct tdsRssiRid tdsRssiRid; +struct tdsRssiRid { u16 len; tdsRssiEntry x[256]; -} tdsRssiRid; +} __packed; -typedef struct { - u16 len; - u16 state; - u16 multicastValid; +typedef struct MICRid MICRid; +struct MICRid { + __le16 len; + __le16 state; + __le16 multicastValid; u8 multicast[16]; - u16 unicastValid; + __le16 unicastValid; u8 unicast[16]; -} MICRid; +} __packed; -typedef struct { - u16 typelen; +typedef struct MICBuffer MICBuffer; +struct MICBuffer { + __be16 typelen; union { u8 snap[8]; @@ -823,17 +838,15 @@ typedef struct { u8 fieldtype[2]; } llc; } u; - u32 mic; - u32 seq; -} MICBuffer; + __be32 mic; + __be32 seq; +} __packed; typedef struct { u8 da[ETH_ALEN]; u8 sa[ETH_ALEN]; } etherHead; -#pragma pack() - #define TXCTL_TXOK (1<<1) /* report if tx is ok */ #define TXCTL_TXEX (1<<2) /* report if tx fails */ #define TXCTL_802_3 (0<<3) /* 802.3 packet */ @@ -918,7 +931,7 @@ typedef struct aironet_ioctl { unsigned char __user *data; // d-data } aironet_ioctl; -static char swversion[] = "2.1"; +static const char swversion[] = "2.1"; #endif /* CISCO_EXT */ #define NUM_MODULES 2 @@ -943,7 +956,7 @@ typedef struct { int position; // current position (byte offset) in message union { u8 d8[4]; - u32 d32; + __be32 d32; } part; // saves partial message word across update() calls } emmh32_context; @@ -976,6 +989,14 @@ typedef struct { dma_addr_t host_addr; } TxFid; +struct rx_hdr { + __le16 status, len; + u8 rssi[2]; + u8 rate; + u8 freq; + __le16 tmp[4]; +} __packed; + typedef struct { unsigned int ctl: 15; unsigned int rdy: 1; @@ -1065,10 +1086,6 @@ static WifiCtlHdr wifictlhdr8023 = { } }; -// Frequency list (map channels to frequencies) -static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442, - 2447, 2452, 2457, 2462, 2467, 2472, 2484 }; - // A few details needed for WEP (Wireless Equivalent Privacy) #define MAX_KEY_SIZE 13 // 128 (?) bits #define MIN_KEY_SIZE 5 // 40 bits RC4 - WEP @@ -1077,12 +1094,6 @@ typedef struct wep_key_t { u8 key[16]; /* 40-bit and 104-bit keys */ } wep_key_t; -/* Backward compatibility */ -#ifndef IW_ENCODE_NOKEY -#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ -#define IW_ENCODE_MODE (IW_ENCODE_DISABLED | IW_ENCODE_RESTRICTED | IW_ENCODE_OPEN) -#endif /* IW_ENCODE_NOKEY */ - /* List of Wireless Handlers (new API) */ static const struct iw_handler_def airo_handler_def; @@ -1100,11 +1111,11 @@ static void enable_interrupts(struct airo_info*); static void disable_interrupts(struct airo_info*); static u16 issuecommand(struct airo_info*, Cmd *pCmd, Resp *pRsp); static int bap_setup(struct airo_info*, u16 rid, u16 offset, int whichbap); -static int aux_bap_read(struct airo_info*, u16 *pu16Dst, int bytelen, +static int aux_bap_read(struct airo_info*, __le16 *pu16Dst, int bytelen, int whichbap); -static int fast_bap_read(struct airo_info*, u16 *pu16Dst, int bytelen, +static int fast_bap_read(struct airo_info*, __le16 *pu16Dst, int bytelen, int whichbap); -static int bap_write(struct airo_info*, const u16 *pu16Src, int bytelen, +static int bap_write(struct airo_info*, const __le16 *pu16Src, int bytelen, int whichbap); static int PC4500_accessrid(struct airo_info*, u16 rid, u16 accmd); static int PC4500_readrid(struct airo_info*, u16 rid, void *pBuf, int len, int lock); @@ -1144,14 +1155,13 @@ static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm); static void airo_networks_free(struct airo_info *ai); struct airo_info { - struct net_device_stats stats; struct net_device *dev; struct list_head dev_list; /* Note, we can have MAX_FIDS outstanding. FIDs are 16-bits, so we use the high bit to mark whether it is in use. */ #define MAX_FIDS 6 #define MPI_MAX_FIDS 1 - int fids[MAX_FIDS]; + u32 fids[MAX_FIDS]; ConfigRid config; char keyindex; // Used with auto wep char defindex; // Used with auto wep @@ -1187,7 +1197,7 @@ struct airo_info { #define JOB_WSTATS 8 #define JOB_SCAN_RESULTS 9 unsigned long jobs; - int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen, + int (*bap_read)(struct airo_info*, __le16 *pu16Dst, int bytelen, int whichbap); unsigned short *flash; tdsRssiEntry *rssi; @@ -1225,6 +1235,9 @@ struct airo_info { #define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE char proc_name[IFNAMSIZ]; + int wep_capable; + int max_wep_idx; + /* WPA-related stuff */ unsigned int bssListFirst; unsigned int bssListNext; @@ -1235,8 +1248,9 @@ struct airo_info { BSSListElement *networks; }; -static inline int bap_read(struct airo_info *ai, u16 *pu16Dst, int bytelen, - int whichbap) { +static inline int bap_read(struct airo_info *ai, __le16 *pu16Dst, int bytelen, + int whichbap) +{ return ai->bap_read(ai, pu16Dst, bytelen, whichbap); } @@ -1266,6 +1280,7 @@ static int flashrestart(struct airo_info *ai,struct net_device *dev); #define airo_print_err(name, fmt, args...) \ airo_print(KERN_ERR, name, fmt, ##args) +#define AIRO_FLASH(dev) (((struct airo_info *)dev->ml_priv)->flash) /*********************************************************************** * MIC ROUTINES * @@ -1281,6 +1296,29 @@ static void emmh32_update(emmh32_context *context, u8 *pOctets, int len); static void emmh32_final(emmh32_context *context, u8 digest[4]); static int flashpchar(struct airo_info *ai,int byte,int dwelltime); +static void age_mic_context(miccntx *cur, miccntx *old, u8 *key, int key_len, + struct crypto_cipher *tfm) +{ + /* If the current MIC context is valid and its key is the same as + * the MIC register, there's nothing to do. + */ + if (cur->valid && (memcmp(cur->key, key, key_len) == 0)) + return; + + /* Age current mic Context */ + memcpy(old, cur, sizeof(*cur)); + + /* Initialize new context */ + memcpy(cur->key, key, key_len); + cur->window = 33; /* Window always points to the middle */ + cur->rx = 0; /* Rx Sequence numbers */ + cur->tx = 0; /* Tx sequence numbers */ + cur->valid = 1; /* Key is now valid */ + + /* Give key to mic seed */ + emmh32_setseed(&cur->seed, key, key_len, tfm); +} + /* micinit - Initialize mic seed */ static void micinit(struct airo_info *ai) @@ -1291,49 +1329,26 @@ static void micinit(struct airo_info *ai) PC4500_readrid(ai, RID_MIC, &mic_rid, sizeof(mic_rid), 0); up(&ai->sem); - ai->micstats.enabled = (mic_rid.state & 0x00FF) ? 1 : 0; - - if (ai->micstats.enabled) { - /* Key must be valid and different */ - if (mic_rid.multicastValid && (!ai->mod[0].mCtx.valid || - (memcmp (ai->mod[0].mCtx.key, mic_rid.multicast, - sizeof(ai->mod[0].mCtx.key)) != 0))) { - /* Age current mic Context */ - memcpy(&ai->mod[1].mCtx,&ai->mod[0].mCtx,sizeof(miccntx)); - /* Initialize new context */ - memcpy(&ai->mod[0].mCtx.key,mic_rid.multicast,sizeof(mic_rid.multicast)); - ai->mod[0].mCtx.window = 33; //Window always points to the middle - ai->mod[0].mCtx.rx = 0; //Rx Sequence numbers - ai->mod[0].mCtx.tx = 0; //Tx sequence numbers - ai->mod[0].mCtx.valid = 1; //Key is now valid - - /* Give key to mic seed */ - emmh32_setseed(&ai->mod[0].mCtx.seed,mic_rid.multicast,sizeof(mic_rid.multicast), ai->tfm); - } - - /* Key must be valid and different */ - if (mic_rid.unicastValid && (!ai->mod[0].uCtx.valid || - (memcmp(ai->mod[0].uCtx.key, mic_rid.unicast, - sizeof(ai->mod[0].uCtx.key)) != 0))) { - /* Age current mic Context */ - memcpy(&ai->mod[1].uCtx,&ai->mod[0].uCtx,sizeof(miccntx)); - /* Initialize new context */ - memcpy(&ai->mod[0].uCtx.key,mic_rid.unicast,sizeof(mic_rid.unicast)); - - ai->mod[0].uCtx.window = 33; //Window always points to the middle - ai->mod[0].uCtx.rx = 0; //Rx Sequence numbers - ai->mod[0].uCtx.tx = 0; //Tx sequence numbers - ai->mod[0].uCtx.valid = 1; //Key is now valid - - //Give key to mic seed - emmh32_setseed(&ai->mod[0].uCtx.seed, mic_rid.unicast, sizeof(mic_rid.unicast), ai->tfm); - } - } else { - /* So next time we have a valid key and mic is enabled, we will update - * the sequence number if the key is the same as before. - */ + ai->micstats.enabled = (le16_to_cpu(mic_rid.state) & 0x00FF) ? 1 : 0; + if (!ai->micstats.enabled) { + /* So next time we have a valid key and mic is enabled, we will + * update the sequence number if the key is the same as before. + */ ai->mod[0].uCtx.valid = 0; ai->mod[0].mCtx.valid = 0; + return; + } + + if (mic_rid.multicastValid) { + age_mic_context(&ai->mod[0].mCtx, &ai->mod[1].mCtx, + mic_rid.multicast, sizeof(mic_rid.multicast), + ai->tfm); + } + + if (mic_rid.unicastValid) { + age_mic_context(&ai->mod[0].uCtx, &ai->mod[1].uCtx, + mic_rid.unicast, sizeof(mic_rid.unicast), + ai->tfm); } } @@ -1358,7 +1373,7 @@ static int micsetup(struct airo_info *ai) { return SUCCESS; } -static char micsnap[] = {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02}; +static const u8 micsnap[] = {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02}; /*=========================================================================== * Description: Mic a packet @@ -1403,7 +1418,7 @@ static int encapsulate(struct airo_info *ai ,etherHead *frame, MICBuffer *mic, i emmh32_update(&context->seed,frame->da,ETH_ALEN * 2); // DA,SA emmh32_update(&context->seed,(u8*)&mic->typelen,10); // Type/Length and Snap emmh32_update(&context->seed,(u8*)&mic->seq,sizeof(mic->seq)); //SEQ - emmh32_update(&context->seed,frame->da + ETH_ALEN * 2,payLen); //payload + emmh32_update(&context->seed,(u8*)(frame + 1),payLen); //payload emmh32_final(&context->seed, (u8*)&mic->mic); /* New Type/length ?????????? */ @@ -1491,7 +1506,7 @@ static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *eth, u16 emmh32_update(&context->seed, eth->da, ETH_ALEN*2); emmh32_update(&context->seed, (u8 *)&mic->typelen, sizeof(mic->typelen)+sizeof(mic->u.snap)); emmh32_update(&context->seed, (u8 *)&mic->seq,sizeof(mic->seq)); - emmh32_update(&context->seed, eth->da + ETH_ALEN*2,payLen); + emmh32_update(&context->seed, (u8 *)(eth + 1),payLen); //Calculate MIC emmh32_final(&context->seed, digest); @@ -1635,7 +1650,7 @@ static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, crypto_cipher_encrypt_one(tfm, plain, plain); cipher = plain; for (j = 0; (j < 16) && (i < ARRAY_SIZE(context->coeff)); ) { - context->coeff[i++] = ntohl(*(u32 *)&cipher[j]); + context->coeff[i++] = ntohl(*(__be32 *)&cipher[j]); j += 4; } } @@ -1668,12 +1683,12 @@ static void emmh32_update(emmh32_context *context, u8 *pOctets, int len) context->position++; len--; } while (byte_position < 4); - MIC_ACCUM(htonl(context->part.d32)); + MIC_ACCUM(ntohl(context->part.d32)); } /* deal with full 32-bit words */ while (len >= 4) { - MIC_ACCUM(htonl(*(u32 *)pOctets)); + MIC_ACCUM(ntohl(*(__be32 *)pOctets)); context->position += 4; pOctets += 4; len -= 4; @@ -1706,7 +1721,7 @@ static void emmh32_final(emmh32_context *context, u8 digest[4]) byte_position = context->position & 3; if (byte_position) { /* have a partial word in part to deal with */ - val = htonl(context->part.d32); + val = ntohl(context->part.d32); MIC_ACCUM(val & mask32[byte_position]); /* zero empty bytes */ } @@ -1726,8 +1741,8 @@ static void emmh32_final(emmh32_context *context, u8 digest[4]) } static int readBSSListRid(struct airo_info *ai, int first, - BSSListRid *list) { - int rc; + BSSListRid *list) +{ Cmd cmd; Resp rsp; @@ -1744,75 +1759,43 @@ static int readBSSListRid(struct airo_info *ai, int first, schedule_timeout_uninterruptible(3 * HZ); ai->list_bss_task = NULL; } - rc = PC4500_readrid(ai, first ? ai->bssListFirst : ai->bssListNext, + return PC4500_readrid(ai, first ? ai->bssListFirst : ai->bssListNext, list, ai->bssListRidLen, 1); - - list->len = le16_to_cpu(list->len); - list->index = le16_to_cpu(list->index); - list->radioType = le16_to_cpu(list->radioType); - list->cap = le16_to_cpu(list->cap); - list->beaconInterval = le16_to_cpu(list->beaconInterval); - list->fh.dwell = le16_to_cpu(list->fh.dwell); - list->dsChannel = le16_to_cpu(list->dsChannel); - list->atimWindow = le16_to_cpu(list->atimWindow); - list->dBm = le16_to_cpu(list->dBm); - return rc; } -static int readWepKeyRid(struct airo_info*ai, WepKeyRid *wkr, int temp, int lock) { - int rc = PC4500_readrid(ai, temp ? RID_WEP_TEMP : RID_WEP_PERM, +static int readWepKeyRid(struct airo_info *ai, WepKeyRid *wkr, int temp, int lock) +{ + return PC4500_readrid(ai, temp ? RID_WEP_TEMP : RID_WEP_PERM, wkr, sizeof(*wkr), lock); - - wkr->len = le16_to_cpu(wkr->len); - wkr->kindex = le16_to_cpu(wkr->kindex); - wkr->klen = le16_to_cpu(wkr->klen); - return rc; } -/* In the writeXXXRid routines we copy the rids so that we don't screwup - * the originals when we endian them... */ -static int writeWepKeyRid(struct airo_info*ai, WepKeyRid *pwkr, int perm, int lock) { - int rc; - WepKeyRid wkr = *pwkr; - wkr.len = cpu_to_le16(wkr.len); - wkr.kindex = cpu_to_le16(wkr.kindex); - wkr.klen = cpu_to_le16(wkr.klen); - rc = PC4500_writerid(ai, RID_WEP_TEMP, &wkr, sizeof(wkr), lock); - if (rc!=SUCCESS) airo_print_err(ai->dev->name, "WEP_TEMP set %x", rc); +static int writeWepKeyRid(struct airo_info *ai, WepKeyRid *wkr, int perm, int lock) +{ + int rc; + rc = PC4500_writerid(ai, RID_WEP_TEMP, wkr, sizeof(*wkr), lock); + if (rc!=SUCCESS) + airo_print_err(ai->dev->name, "WEP_TEMP set %x", rc); if (perm) { - rc = PC4500_writerid(ai, RID_WEP_PERM, &wkr, sizeof(wkr), lock); - if (rc!=SUCCESS) { + rc = PC4500_writerid(ai, RID_WEP_PERM, wkr, sizeof(*wkr), lock); + if (rc!=SUCCESS) airo_print_err(ai->dev->name, "WEP_PERM set %x", rc); - } } return rc; } -static int readSsidRid(struct airo_info*ai, SsidRid *ssidr) { - int i; - int rc = PC4500_readrid(ai, RID_SSID, ssidr, sizeof(*ssidr), 1); - - ssidr->len = le16_to_cpu(ssidr->len); - for(i = 0; i < 3; i++) { - ssidr->ssids[i].len = le16_to_cpu(ssidr->ssids[i].len); - } - return rc; +static int readSsidRid(struct airo_info*ai, SsidRid *ssidr) +{ + return PC4500_readrid(ai, RID_SSID, ssidr, sizeof(*ssidr), 1); } -static int writeSsidRid(struct airo_info*ai, SsidRid *pssidr, int lock) { - int rc; - int i; - SsidRid ssidr = *pssidr; - ssidr.len = cpu_to_le16(ssidr.len); - for(i = 0; i < 3; i++) { - ssidr.ssids[i].len = cpu_to_le16(ssidr.ssids[i].len); - } - rc = PC4500_writerid(ai, RID_SSID, &ssidr, sizeof(ssidr), lock); - return rc; +static int writeSsidRid(struct airo_info*ai, SsidRid *pssidr, int lock) +{ + return PC4500_writerid(ai, RID_SSID, pssidr, sizeof(*pssidr), lock); } -static int readConfigRid(struct airo_info*ai, int lock) { + +static int readConfigRid(struct airo_info *ai, int lock) +{ int rc; - u16 *s; ConfigRid cfg; if (ai->config.len) @@ -1822,24 +1805,12 @@ static int readConfigRid(struct airo_info*ai, int lock) { if (rc != SUCCESS) return rc; - for(s = &cfg.len; s <= &cfg.rtsThres; s++) *s = le16_to_cpu(*s); - - for(s = &cfg.shortRetryLimit; s <= &cfg.radioType; s++) - *s = le16_to_cpu(*s); - - for(s = &cfg.txPower; s <= &cfg.radioSpecific; s++) - *s = le16_to_cpu(*s); - - for(s = &cfg.arlThreshold; s <= &cfg._reserved4[0]; s++) - *s = cpu_to_le16(*s); - - for(s = &cfg.autoWake; s <= &cfg.autoWake; s++) - *s = cpu_to_le16(*s); - ai->config = cfg; return SUCCESS; } -static inline void checkThrottle(struct airo_info *ai) { + +static inline void checkThrottle(struct airo_info *ai) +{ int i; /* Old hardware had a limit on encryption speed */ if (ai->config.authType != AUTH_OPEN && maxencrypt) { @@ -1850,8 +1821,9 @@ static inline void checkThrottle(struct airo_info *ai) { } } } -static int writeConfigRid(struct airo_info*ai, int lock) { - u16 *s; + +static int writeConfigRid(struct airo_info *ai, int lock) +{ ConfigRid cfgr; if (!test_bit (FLAG_COMMIT, &ai->flags)) @@ -1862,82 +1834,49 @@ static int writeConfigRid(struct airo_info*ai, int lock) { checkThrottle(ai); cfgr = ai->config; - if ((cfgr.opmode & 0xFF) == MODE_STA_IBSS) + if ((cfgr.opmode & MODE_CFG_MASK) == MODE_STA_IBSS) set_bit(FLAG_ADHOC, &ai->flags); else clear_bit(FLAG_ADHOC, &ai->flags); - for(s = &cfgr.len; s <= &cfgr.rtsThres; s++) *s = cpu_to_le16(*s); - - for(s = &cfgr.shortRetryLimit; s <= &cfgr.radioType; s++) - *s = cpu_to_le16(*s); - - for(s = &cfgr.txPower; s <= &cfgr.radioSpecific; s++) - *s = cpu_to_le16(*s); - - for(s = &cfgr.arlThreshold; s <= &cfgr._reserved4[0]; s++) - *s = cpu_to_le16(*s); - - for(s = &cfgr.autoWake; s <= &cfgr.autoWake; s++) - *s = cpu_to_le16(*s); - return PC4500_writerid( ai, RID_CONFIG, &cfgr, sizeof(cfgr), lock); } -static int readStatusRid(struct airo_info*ai, StatusRid *statr, int lock) { - int rc = PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr), lock); - u16 *s; - statr->len = le16_to_cpu(statr->len); - for(s = &statr->mode; s <= &statr->SSIDlen; s++) *s = le16_to_cpu(*s); - - for(s = &statr->beaconPeriod; s <= &statr->shortPreamble; s++) - *s = le16_to_cpu(*s); - statr->load = le16_to_cpu(statr->load); - statr->assocStatus = le16_to_cpu(statr->assocStatus); - return rc; +static int readStatusRid(struct airo_info *ai, StatusRid *statr, int lock) +{ + return PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr), lock); } -static int readAPListRid(struct airo_info*ai, APListRid *aplr) { - int rc = PC4500_readrid(ai, RID_APLIST, aplr, sizeof(*aplr), 1); - aplr->len = le16_to_cpu(aplr->len); - return rc; + +static int readAPListRid(struct airo_info *ai, APListRid *aplr) +{ + return PC4500_readrid(ai, RID_APLIST, aplr, sizeof(*aplr), 1); } -static int writeAPListRid(struct airo_info*ai, APListRid *aplr, int lock) { - int rc; - aplr->len = cpu_to_le16(aplr->len); - rc = PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr), lock); - return rc; + +static int writeAPListRid(struct airo_info *ai, APListRid *aplr, int lock) +{ + return PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr), lock); } -static int readCapabilityRid(struct airo_info*ai, CapabilityRid *capr, int lock) { - int rc = PC4500_readrid(ai, RID_CAPABILITIES, capr, sizeof(*capr), lock); - u16 *s; - capr->len = le16_to_cpu(capr->len); - capr->prodNum = le16_to_cpu(capr->prodNum); - capr->radioType = le16_to_cpu(capr->radioType); - capr->country = le16_to_cpu(capr->country); - for(s = &capr->txPowerLevels[0]; s <= &capr->requiredHard; s++) - *s = le16_to_cpu(*s); - return rc; +static int readCapabilityRid(struct airo_info *ai, CapabilityRid *capr, int lock) +{ + return PC4500_readrid(ai, RID_CAPABILITIES, capr, sizeof(*capr), lock); } -static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock) { - int rc = PC4500_readrid(ai, rid, sr, sizeof(*sr), lock); - u32 *i; - sr->len = le16_to_cpu(sr->len); - for(i = &sr->vals[0]; i <= &sr->vals[99]; i++) *i = le32_to_cpu(*i); - return rc; +static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock) +{ + return PC4500_readrid(ai, rid, sr, sizeof(*sr), lock); } static void try_auto_wep(struct airo_info *ai) { - if (auto_wep && !(ai->flags & FLAG_RADIO_DOWN)) { + if (auto_wep && !test_bit(FLAG_RADIO_DOWN, &ai->flags)) { ai->expires = RUN_AT(3*HZ); wake_up_interruptible(&ai->thr_wait); } } static int airo_open(struct net_device *dev) { - struct airo_info *ai = dev->priv; + struct airo_info *ai = dev->ml_priv; int rc = 0; if (test_bit(FLAG_FLASHING, &ai->flags)) @@ -1946,7 +1885,7 @@ static int airo_open(struct net_device *dev) { /* Make sure the card is configured. * Wireless Extensions may postpone config changes until the card * is open (to pipeline changes and speed-up card setup). If - * those changes are not yet commited, do it now - Jean II */ + * those changes are not yet committed, do it now - Jean II */ if (test_bit(FLAG_COMMIT, &ai->flags)) { disable_MAC(ai, 1); writeConfigRid(ai, 1); @@ -1954,7 +1893,8 @@ static int airo_open(struct net_device *dev) { if (ai->wifidev != dev) { clear_bit(JOB_DIE, &ai->jobs); - ai->airo_thread_task = kthread_run(airo_thread, dev, dev->name); + ai->airo_thread_task = kthread_run(airo_thread, dev, "%s", + dev->name); if (IS_ERR(ai->airo_thread_task)) return (int)PTR_ERR(ai->airo_thread_task); @@ -1981,25 +1921,27 @@ static int airo_open(struct net_device *dev) { return 0; } -static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) { +static netdev_tx_t mpi_start_xmit(struct sk_buff *skb, + struct net_device *dev) +{ int npacks, pending; unsigned long flags; - struct airo_info *ai = dev->priv; + struct airo_info *ai = dev->ml_priv; if (!skb) { - airo_print_err(dev->name, "%s: skb == NULL!",__FUNCTION__); - return 0; + airo_print_err(dev->name, "%s: skb == NULL!",__func__); + return NETDEV_TX_OK; } npacks = skb_queue_len (&ai->txq); if (npacks >= MAXTXQ - 1) { netif_stop_queue (dev); if (npacks > MAXTXQ) { - ai->stats.tx_fifo_errors++; - return 1; + dev->stats.tx_fifo_errors++; + return NETDEV_TX_BUSY; } skb_queue_tail (&ai->txq, skb); - return 0; + return NETDEV_TX_OK; } spin_lock_irqsave(&ai->aux_lock, flags); @@ -2012,7 +1954,7 @@ static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) { set_bit(FLAG_PENDING_XMIT, &ai->flags); mpi_send_packet (dev); } - return 0; + return NETDEV_TX_OK; } /* @@ -2026,16 +1968,17 @@ static int mpi_send_packet (struct net_device *dev) { struct sk_buff *skb; unsigned char *buffer; - s16 len, *payloadLen; - struct airo_info *ai = dev->priv; + s16 len; + __le16 *payloadLen; + struct airo_info *ai = dev->ml_priv; u8 *sendbuf; /* get a packet to send */ - if ((skb = skb_dequeue(&ai->txq)) == 0) { + if ((skb = skb_dequeue(&ai->txq)) == NULL) { airo_print_err(dev->name, "%s: Dequeue'd zero in send_packet()", - __FUNCTION__); + __func__); return 0; } @@ -2051,25 +1994,25 @@ static int mpi_send_packet (struct net_device *dev) /* * Magic, the cards firmware needs a length count (2 bytes) in the host buffer * right after TXFID_HDR.The TXFID_HDR contains the status short so payloadlen - * is immediatly after it. ------------------------------------------------ + * is immediately after it. ------------------------------------------------ * |TXFIDHDR+STATUS|PAYLOADLEN|802.3HDR|PACKETDATA| * ------------------------------------------------ */ - memcpy((char *)ai->txfids[0].virtual_host_addr, + memcpy(ai->txfids[0].virtual_host_addr, (char *)&wifictlhdr8023, sizeof(wifictlhdr8023)); - payloadLen = (s16 *)(ai->txfids[0].virtual_host_addr + + payloadLen = (__le16 *)(ai->txfids[0].virtual_host_addr + sizeof(wifictlhdr8023)); sendbuf = ai->txfids[0].virtual_host_addr + sizeof(wifictlhdr8023) + 2 ; /* - * Firmware automaticly puts 802 header on so + * Firmware automatically puts 802 header on so * we don't need to account for it in the length */ if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled && - (ntohs(((u16 *)buffer)[6]) != 0x888E)) { + (ntohs(((__be16 *)buffer)[6]) != 0x888E)) { MICBuffer pMic; if (encapsulate(ai, (etherHead *)buffer, &pMic, len - sizeof(etherHead)) != SUCCESS) @@ -2104,7 +2047,7 @@ static int mpi_send_packet (struct net_device *dev) static void get_tx_error(struct airo_info *ai, s32 fid) { - u16 status; + __le16 status; if (fid < 0) status = ((WifiCtlHdr *)ai->txfids[0].virtual_host_addr)->ctlhdr.status; @@ -2114,13 +2057,13 @@ static void get_tx_error(struct airo_info *ai, s32 fid) bap_read(ai, &status, 2, BAP0); } if (le16_to_cpu(status) & 2) /* Too many retries */ - ai->stats.tx_aborted_errors++; + ai->dev->stats.tx_aborted_errors++; if (le16_to_cpu(status) & 4) /* Transmit lifetime exceeded */ - ai->stats.tx_heartbeat_errors++; + ai->dev->stats.tx_heartbeat_errors++; if (le16_to_cpu(status) & 8) /* Aid fail */ { } if (le16_to_cpu(status) & 0x10) /* MAC disabled */ - ai->stats.tx_carrier_errors++; + ai->dev->stats.tx_carrier_errors++; if (le16_to_cpu(status) & 0x20) /* Association lost */ { } /* We produce a TXDROP event only for retry or lifetime @@ -2135,7 +2078,7 @@ static void get_tx_error(struct airo_info *ai, s32 fid) /* Faster to skip over useless data than to do * another bap_setup(). We are at offset 0x6 and * need to go to 0x18 and read 6 bytes - Jean II */ - bap_read(ai, (u16 *) junk, 0x18, BAP0); + bap_read(ai, (__le16 *) junk, 0x18, BAP0); /* Copy 802.11 dest address. * We use the 802.11 header because the frame may @@ -2156,7 +2099,7 @@ static void get_tx_error(struct airo_info *ai, s32 fid) static void airo_end_xmit(struct net_device *dev) { u16 status; int i; - struct airo_info *priv = dev->priv; + struct airo_info *priv = dev->ml_priv; struct sk_buff *skb = priv->xmit.skb; int fid = priv->xmit.fid; u32 *fids = priv->fids; @@ -2172,22 +2115,24 @@ static void airo_end_xmit(struct net_device *dev) { for (; i < MAX_FIDS / 2 && (priv->fids[i] & 0xffff0000); i++); } else { priv->fids[fid] &= 0xffff; - priv->stats.tx_window_errors++; + dev->stats.tx_window_errors++; } if (i < MAX_FIDS / 2) netif_wake_queue(dev); dev_kfree_skb(skb); } -static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) { +static netdev_tx_t airo_start_xmit(struct sk_buff *skb, + struct net_device *dev) +{ s16 len; int i, j; - struct airo_info *priv = dev->priv; + struct airo_info *priv = dev->ml_priv; u32 *fids = priv->fids; if ( skb == NULL ) { - airo_print_err(dev->name, "%s: skb == NULL!", __FUNCTION__); - return 0; + airo_print_err(dev->name, "%s: skb == NULL!", __func__); + return NETDEV_TX_OK; } /* Find a vacant FID */ @@ -2198,8 +2143,8 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) { netif_stop_queue(dev); if (i == MAX_FIDS / 2) { - priv->stats.tx_fifo_errors++; - return 1; + dev->stats.tx_fifo_errors++; + return NETDEV_TX_BUSY; } } /* check min length*/ @@ -2215,13 +2160,13 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) { wake_up_interruptible(&priv->thr_wait); } else airo_end_xmit(dev); - return 0; + return NETDEV_TX_OK; } static void airo_end_xmit11(struct net_device *dev) { u16 status; int i; - struct airo_info *priv = dev->priv; + struct airo_info *priv = dev->ml_priv; struct sk_buff *skb = priv->xmit11.skb; int fid = priv->xmit11.fid; u32 *fids = priv->fids; @@ -2237,28 +2182,31 @@ static void airo_end_xmit11(struct net_device *dev) { for (; i < MAX_FIDS && (priv->fids[i] & 0xffff0000); i++); } else { priv->fids[fid] &= 0xffff; - priv->stats.tx_window_errors++; + dev->stats.tx_window_errors++; } if (i < MAX_FIDS) netif_wake_queue(dev); dev_kfree_skb(skb); } -static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) { +static netdev_tx_t airo_start_xmit11(struct sk_buff *skb, + struct net_device *dev) +{ s16 len; int i, j; - struct airo_info *priv = dev->priv; + struct airo_info *priv = dev->ml_priv; u32 *fids = priv->fids; if (test_bit(FLAG_MPI, &priv->flags)) { /* Not implemented yet for MPI350 */ netif_stop_queue(dev); - return -ENETDOWN; + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; } if ( skb == NULL ) { - airo_print_err(dev->name, "%s: skb == NULL!", __FUNCTION__); - return 0; + airo_print_err(dev->name, "%s: skb == NULL!", __func__); + return NETDEV_TX_OK; } /* Find a vacant FID */ @@ -2269,8 +2217,8 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) { netif_stop_queue(dev); if (i == MAX_FIDS) { - priv->stats.tx_fifo_errors++; - return 1; + dev->stats.tx_fifo_errors++; + return NETDEV_TX_BUSY; } } /* check min length*/ @@ -2286,12 +2234,14 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) { wake_up_interruptible(&priv->thr_wait); } else airo_end_xmit11(dev); - return 0; + return NETDEV_TX_OK; } -static void airo_read_stats(struct airo_info *ai) { +static void airo_read_stats(struct net_device *dev) +{ + struct airo_info *ai = dev->ml_priv; StatsRid stats_rid; - u32 *vals = stats_rid.vals; + __le32 *vals = stats_rid.vals; clear_bit(JOB_STATS, &ai->jobs); if (ai->power.event) { @@ -2301,25 +2251,29 @@ static void airo_read_stats(struct airo_info *ai) { readStatsRid(ai, &stats_rid, RID_STATS, 0); up(&ai->sem); - ai->stats.rx_packets = vals[43] + vals[44] + vals[45]; - ai->stats.tx_packets = vals[39] + vals[40] + vals[41]; - ai->stats.rx_bytes = vals[92]; - ai->stats.tx_bytes = vals[91]; - ai->stats.rx_errors = vals[0] + vals[2] + vals[3] + vals[4]; - ai->stats.tx_errors = vals[42] + ai->stats.tx_fifo_errors; - ai->stats.multicast = vals[43]; - ai->stats.collisions = vals[89]; + dev->stats.rx_packets = le32_to_cpu(vals[43]) + le32_to_cpu(vals[44]) + + le32_to_cpu(vals[45]); + dev->stats.tx_packets = le32_to_cpu(vals[39]) + le32_to_cpu(vals[40]) + + le32_to_cpu(vals[41]); + dev->stats.rx_bytes = le32_to_cpu(vals[92]); + dev->stats.tx_bytes = le32_to_cpu(vals[91]); + dev->stats.rx_errors = le32_to_cpu(vals[0]) + le32_to_cpu(vals[2]) + + le32_to_cpu(vals[3]) + le32_to_cpu(vals[4]); + dev->stats.tx_errors = le32_to_cpu(vals[42]) + + dev->stats.tx_fifo_errors; + dev->stats.multicast = le32_to_cpu(vals[43]); + dev->stats.collisions = le32_to_cpu(vals[89]); /* detailed rx_errors: */ - ai->stats.rx_length_errors = vals[3]; - ai->stats.rx_crc_errors = vals[4]; - ai->stats.rx_frame_errors = vals[2]; - ai->stats.rx_fifo_errors = vals[0]; + dev->stats.rx_length_errors = le32_to_cpu(vals[3]); + dev->stats.rx_crc_errors = le32_to_cpu(vals[4]); + dev->stats.rx_frame_errors = le32_to_cpu(vals[2]); + dev->stats.rx_fifo_errors = le32_to_cpu(vals[0]); } static struct net_device_stats *airo_get_stats(struct net_device *dev) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; if (!test_bit(JOB_STATS, &local->jobs)) { /* Get stats out of the card if available */ @@ -2327,10 +2281,10 @@ static struct net_device_stats *airo_get_stats(struct net_device *dev) set_bit(JOB_STATS, &local->jobs); wake_up_interruptible(&local->thr_wait); } else - airo_read_stats(local); + airo_read_stats(dev); } - return &local->stats; + return &dev->stats; } static void airo_set_promisc(struct airo_info *ai) { @@ -2346,7 +2300,7 @@ static void airo_set_promisc(struct airo_info *ai) { } static void airo_set_multicast_list(struct net_device *dev) { - struct airo_info *ai = dev->priv; + struct airo_info *ai = dev->ml_priv; if ((dev->flags ^ ai->flags) & IFF_PROMISC) { change_bit(FLAG_PROMISC, &ai->flags); @@ -2357,14 +2311,14 @@ static void airo_set_multicast_list(struct net_device *dev) { airo_set_promisc(ai); } - if ((dev->flags&IFF_ALLMULTI)||dev->mc_count>0) { + if ((dev->flags&IFF_ALLMULTI) || !netdev_mc_empty(dev)) { /* Turn on multicast. (Should be already setup...) */ } } static int airo_set_mac_address(struct net_device *dev, void *p) { - struct airo_info *ai = dev->priv; + struct airo_info *ai = dev->ml_priv; struct sockaddr *addr = p; readConfigRid(ai, 1); @@ -2404,7 +2358,7 @@ static void del_airo_dev(struct airo_info *ai) } static int airo_close(struct net_device *dev) { - struct airo_info *ai = dev->priv; + struct airo_info *ai = dev->ml_priv; netif_stop_queue(dev); @@ -2430,7 +2384,7 @@ static int airo_close(struct net_device *dev) { void stop_airo_card( struct net_device *dev, int freeres ) { - struct airo_info *ai = dev->priv; + struct airo_info *ai = dev->ml_priv; set_bit(FLAG_RADIO_DOWN, &ai->flags); disable_MAC(ai, 1); @@ -2579,7 +2533,7 @@ static int mpi_init_descriptors (struct airo_info *ai) /* * We are setting up three things here: * 1) Map AUX memory for descriptors: Rid, TxFid, or RxFid. - * 2) Map PCI memory for issueing commands. + * 2) Map PCI memory for issuing commands. * 3) Allocate memory (shared) to send and receive ethernet frames. */ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci) @@ -2700,17 +2654,21 @@ static const struct header_ops airo_header_ops = { .parse = wll_header_parse, }; +static const struct net_device_ops airo11_netdev_ops = { + .ndo_open = airo_open, + .ndo_stop = airo_close, + .ndo_start_xmit = airo_start_xmit11, + .ndo_get_stats = airo_get_stats, + .ndo_set_mac_address = airo_set_mac_address, + .ndo_do_ioctl = airo_ioctl, + .ndo_change_mtu = airo_change_mtu, +}; + static void wifi_setup(struct net_device *dev) { + dev->netdev_ops = &airo11_netdev_ops; dev->header_ops = &airo_header_ops; - dev->hard_start_xmit = &airo_start_xmit11; - dev->get_stats = &airo_get_stats; - dev->set_mac_address = &airo_set_mac_address; - dev->do_ioctl = &airo_ioctl; dev->wireless_handlers = &airo_handler_def; - dev->change_mtu = &airo_change_mtu; - dev->open = &airo_open; - dev->stop = &airo_close; dev->type = ARPHRD_IEEE80211; dev->hard_header_len = ETH_HLEN; @@ -2730,11 +2688,12 @@ static struct net_device *init_wifidev(struct airo_info *ai, struct net_device *dev = alloc_netdev(0, "wifi%d", wifi_setup); if (!dev) return NULL; - dev->priv = ethdev->priv; + dev->ml_priv = ethdev->ml_priv; dev->irq = ethdev->irq; dev->base_addr = ethdev->base_addr; dev->wireless_data = ethdev->wireless_data; - memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len); + SET_NETDEV_DEV(dev, ethdev->dev.parent); + eth_hw_addr_inherit(dev, ethdev); err = register_netdev(dev); if (err<0) { free_netdev(dev); @@ -2744,7 +2703,7 @@ static struct net_device *init_wifidev(struct airo_info *ai, } static int reset_card( struct net_device *dev , int lock) { - struct airo_info *ai = dev->priv; + struct airo_info *ai = dev->ml_priv; if (lock && down_interruptible(&ai->sem)) return -1; @@ -2764,9 +2723,8 @@ static int airo_networks_allocate(struct airo_info *ai) if (ai->networks) return 0; - ai->networks = - kzalloc(AIRO_MAX_NETWORK_COUNT * sizeof(BSSListElement), - GFP_KERNEL); + ai->networks = kcalloc(AIRO_MAX_NETWORK_COUNT, sizeof(BSSListElement), + GFP_KERNEL); if (!ai->networks) { airo_print_warn("", "Out of memory allocating beacons"); return -ENOMEM; @@ -2792,26 +2750,30 @@ static void airo_networks_initialize(struct airo_info *ai) &ai->network_free_list); } -static int airo_test_wpa_capable(struct airo_info *ai) -{ - int status; - CapabilityRid cap_rid; - - status = readCapabilityRid(ai, &cap_rid, 1); - if (status != SUCCESS) return 0; +static const struct net_device_ops airo_netdev_ops = { + .ndo_open = airo_open, + .ndo_stop = airo_close, + .ndo_start_xmit = airo_start_xmit, + .ndo_get_stats = airo_get_stats, + .ndo_set_rx_mode = airo_set_multicast_list, + .ndo_set_mac_address = airo_set_mac_address, + .ndo_do_ioctl = airo_ioctl, + .ndo_change_mtu = airo_change_mtu, + .ndo_validate_addr = eth_validate_addr, +}; - /* Only firmware versions 5.30.17 or better can do WPA */ - if ((cap_rid.softVer > 0x530) - || ((cap_rid.softVer == 0x530) && (cap_rid.softSubVer >= 17))) { - airo_print_info("", "WPA is supported."); - return 1; - } +static const struct net_device_ops mpi_netdev_ops = { + .ndo_open = airo_open, + .ndo_stop = airo_close, + .ndo_start_xmit = mpi_start_xmit, + .ndo_get_stats = airo_get_stats, + .ndo_set_rx_mode = airo_set_multicast_list, + .ndo_set_mac_address = airo_set_mac_address, + .ndo_do_ioctl = airo_ioctl, + .ndo_change_mtu = airo_change_mtu, + .ndo_validate_addr = eth_validate_addr, +}; - /* No WPA support */ - airo_print_info("", "WPA unsupported (only firmware versions 5.30.17" - " and greater support WPA. Detected %s)", cap_rid.prodVer); - return 0; -} static struct net_device *_init_airo_card( unsigned short irq, int port, int is_pcmcia, struct pci_dev *pci, @@ -2820,7 +2782,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, struct net_device *dev; struct airo_info *ai; int i, rc; - DECLARE_MAC_BUF(mac); + CapabilityRid cap_rid; /* Create the network device object. */ dev = alloc_netdev(sizeof(*ai), "", ether_setup); @@ -2829,7 +2791,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, return NULL; } - ai = dev->priv; + ai = dev->ml_priv = netdev_priv(dev); ai->wifidev = NULL; ai->flags = 1 << FLAG_RADIO_DOWN; ai->jobs = 0; @@ -2850,24 +2812,19 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, goto err_out_free; airo_networks_initialize (ai); + skb_queue_head_init (&ai->txq); + /* The Airo-specific entries in the device structure. */ - if (test_bit(FLAG_MPI,&ai->flags)) { - skb_queue_head_init (&ai->txq); - dev->hard_start_xmit = &mpi_start_xmit; - } else - dev->hard_start_xmit = &airo_start_xmit; - dev->get_stats = &airo_get_stats; - dev->set_multicast_list = &airo_set_multicast_list; - dev->set_mac_address = &airo_set_mac_address; - dev->do_ioctl = &airo_ioctl; + if (test_bit(FLAG_MPI,&ai->flags)) + dev->netdev_ops = &mpi_netdev_ops; + else + dev->netdev_ops = &airo_netdev_ops; dev->wireless_handlers = &airo_handler_def; ai->wireless_data.spy_data = &ai->spy_data; dev->wireless_data = &ai->wireless_data; - dev->change_mtu = &airo_change_mtu; - dev->open = &airo_open; - dev->stop = &airo_close; dev->irq = irq; dev->base_addr = port; + dev->priv_flags &= ~IFF_TX_SKB_SHARING; SET_NETDEV_DEV(dev, dmdev); @@ -2890,7 +2847,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, } if (probe) { - if ( setup_card( ai, dev->dev_addr, 1 ) != SUCCESS ) { + if (setup_card(ai, dev->dev_addr, 1) != SUCCESS) { airo_print_err(dev->name, "MAC could not be enabled" ); rc = -EIO; goto err_out_map; @@ -2900,38 +2857,59 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, set_bit(FLAG_FLASHING, &ai->flags); } + strcpy(dev->name, "eth%d"); + rc = register_netdev(dev); + if (rc) { + airo_print_err(dev->name, "Couldn't register_netdev"); + goto err_out_map; + } + ai->wifidev = init_wifidev(ai, dev); + if (!ai->wifidev) + goto err_out_reg; + + rc = readCapabilityRid(ai, &cap_rid, 1); + if (rc != SUCCESS) { + rc = -EIO; + goto err_out_wifi; + } + /* WEP capability discovery */ + ai->wep_capable = (cap_rid.softCap & cpu_to_le16(0x02)) ? 1 : 0; + ai->max_wep_idx = (cap_rid.softCap & cpu_to_le16(0x80)) ? 3 : 0; + + airo_print_info(dev->name, "Firmware version %x.%x.%02d", + ((le16_to_cpu(cap_rid.softVer) >> 8) & 0xF), + (le16_to_cpu(cap_rid.softVer) & 0xFF), + le16_to_cpu(cap_rid.softSubVer)); + /* Test for WPA support */ - if (airo_test_wpa_capable(ai)) { + /* Only firmware versions 5.30.17 or better can do WPA */ + if (le16_to_cpu(cap_rid.softVer) > 0x530 + || (le16_to_cpu(cap_rid.softVer) == 0x530 + && le16_to_cpu(cap_rid.softSubVer) >= 17)) { + airo_print_info(ai->dev->name, "WPA supported."); + set_bit(FLAG_WPA_CAPABLE, &ai->flags); ai->bssListFirst = RID_WPA_BSSLISTFIRST; ai->bssListNext = RID_WPA_BSSLISTNEXT; ai->bssListRidLen = sizeof(BSSListRid); } else { + airo_print_info(ai->dev->name, "WPA unsupported with firmware " + "versions older than 5.30.17."); + ai->bssListFirst = RID_BSSLISTFIRST; ai->bssListNext = RID_BSSLISTNEXT; ai->bssListRidLen = sizeof(BSSListRid) - sizeof(BSSListRidExtra); } - strcpy(dev->name, "eth%d"); - rc = register_netdev(dev); - if (rc) { - airo_print_err(dev->name, "Couldn't register_netdev"); - goto err_out_map; - } - ai->wifidev = init_wifidev(ai, dev); - if (!ai->wifidev) - goto err_out_reg; - set_bit(FLAG_REGISTERED,&ai->flags); - airo_print_info(dev->name, "MAC enabled %s", - print_mac(mac, dev->dev_addr)); + airo_print_info(dev->name, "MAC enabled %pM", dev->dev_addr); /* Allocate the transmit buffers */ if (probe && !test_bit(FLAG_MPI,&ai->flags)) for( i = 0; i < MAX_FIDS; i++ ) ai->fids[i] = transmit_allocate(ai,AIRO_DEF_MTU,i>=MAX_FIDS/2); - if (setup_proc_entry(dev, dev->priv) < 0) + if (setup_proc_entry(dev, dev->ml_priv) < 0) goto err_out_wifi; return dev; @@ -2953,8 +2931,8 @@ err_out_res: release_region( dev->base_addr, 64 ); err_out_nets: airo_networks_free(ai); - del_airo_dev(ai); err_out_free: + del_airo_dev(ai); free_netdev(dev); return NULL; } @@ -2969,7 +2947,7 @@ EXPORT_SYMBOL(init_airo_card); static int waitbusy (struct airo_info *ai) { int delay = 0; - while ((IN4500 (ai, COMMAND) & COMMAND_BUSY) & (delay < 10000)) { + while ((IN4500(ai, COMMAND) & COMMAND_BUSY) && (delay < 10000)) { udelay (10); if ((++delay % 20) == 0) OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY); @@ -2980,8 +2958,7 @@ static int waitbusy (struct airo_info *ai) { int reset_airo_card( struct net_device *dev ) { int i; - struct airo_info *ai = dev->priv; - DECLARE_MAC_BUF(mac); + struct airo_info *ai = dev->ml_priv; if (reset_card (dev, 1)) return -1; @@ -2990,8 +2967,7 @@ int reset_airo_card( struct net_device *dev ) airo_print_err(dev->name, "MAC could not be enabled"); return -1; } - airo_print_info(dev->name, "MAC enabled %s", - print_mac(mac, dev->dev_addr)); + airo_print_info(dev->name, "MAC enabled %pM", dev->dev_addr); /* Allocate the transmit buffers if needed */ if (!test_bit(FLAG_MPI,&ai->flags)) for( i = 0; i < MAX_FIDS; i++ ) @@ -3005,7 +2981,7 @@ int reset_airo_card( struct net_device *dev ) EXPORT_SYMBOL(reset_airo_card); static void airo_send_event(struct net_device *dev) { - struct airo_info *ai = dev->priv; + struct airo_info *ai = dev->ml_priv; union iwreq_data wrqu; StatusRid status_rid; @@ -3037,14 +3013,14 @@ static void airo_process_scan_results (struct airo_info *ai) { /* Try to read the first entry of the scan result */ rc = PC4500_readrid(ai, ai->bssListFirst, &bss, ai->bssListRidLen, 0); - if((rc) || (bss.index == 0xffff)) { + if((rc) || (bss.index == cpu_to_le16(0xffff))) { /* No scan results */ goto out; } /* Read and parse all entries */ tmp_net = NULL; - while((!rc) && (bss.index != 0xffff)) { + while((!rc) && (bss.index != cpu_to_le16(0xffff))) { /* Grab a network off the free list */ if (!list_empty(&ai->network_free_list)) { tmp_net = list_entry(ai->network_free_list.next, @@ -3082,7 +3058,7 @@ out: static int airo_thread(void *data) { struct net_device *dev = data; - struct airo_info *ai = dev->priv; + struct airo_info *ai = dev->ml_priv; int locked; set_freezable(); @@ -3157,7 +3133,7 @@ static int airo_thread(void *data) { else if (test_bit(JOB_XMIT11, &ai->jobs)) airo_end_xmit11(dev); else if (test_bit(JOB_STATS, &ai->jobs)) - airo_read_stats(ai); + airo_read_stats(dev); else if (test_bit(JOB_WSTATS, &ai->jobs)) airo_read_wireless_stats(ai); else if (test_bit(JOB_PROMISC, &ai->jobs)) @@ -3177,328 +3153,380 @@ static int airo_thread(void *data) { return 0; } -static irqreturn_t airo_interrupt ( int irq, void* dev_id) { - struct net_device *dev = (struct net_device *)dev_id; - u16 status; - u16 fid; - struct airo_info *apriv = dev->priv; - u16 savedInterrupts = 0; - int handled = 0; +static int header_len(__le16 ctl) +{ + u16 fc = le16_to_cpu(ctl); + switch (fc & 0xc) { + case 4: + if ((fc & 0xe0) == 0xc0) + return 10; /* one-address control packet */ + return 16; /* two-address control packet */ + case 8: + if ((fc & 0x300) == 0x300) + return 30; /* WDS packet */ + } + return 24; +} - if (!netif_device_present(dev)) - return IRQ_NONE; +static void airo_handle_cisco_mic(struct airo_info *ai) +{ + if (test_bit(FLAG_MIC_CAPABLE, &ai->flags)) { + set_bit(JOB_MIC, &ai->jobs); + wake_up_interruptible(&ai->thr_wait); + } +} - for (;;) { - status = IN4500( apriv, EVSTAT ); - if ( !(status & STATUS_INTS) || status == 0xffff ) break; +/* Airo Status codes */ +#define STAT_NOBEACON 0x8000 /* Loss of sync - missed beacons */ +#define STAT_MAXRETRIES 0x8001 /* Loss of sync - max retries */ +#define STAT_MAXARL 0x8002 /* Loss of sync - average retry level exceeded*/ +#define STAT_FORCELOSS 0x8003 /* Loss of sync - host request */ +#define STAT_TSFSYNC 0x8004 /* Loss of sync - TSF synchronization */ +#define STAT_DEAUTH 0x8100 /* low byte is 802.11 reason code */ +#define STAT_DISASSOC 0x8200 /* low byte is 802.11 reason code */ +#define STAT_ASSOC_FAIL 0x8400 /* low byte is 802.11 reason code */ +#define STAT_AUTH_FAIL 0x0300 /* low byte is 802.11 reason code */ +#define STAT_ASSOC 0x0400 /* Associated */ +#define STAT_REASSOC 0x0600 /* Reassociated? Only on firmware >= 5.30.17 */ - handled = 1; +static void airo_print_status(const char *devname, u16 status) +{ + u8 reason = status & 0xFF; - if ( status & EV_AWAKE ) { - OUT4500( apriv, EVACK, EV_AWAKE ); - OUT4500( apriv, EVACK, EV_AWAKE ); + switch (status & 0xFF00) { + case STAT_NOBEACON: + switch (status) { + case STAT_NOBEACON: + airo_print_dbg(devname, "link lost (missed beacons)"); + break; + case STAT_MAXRETRIES: + case STAT_MAXARL: + airo_print_dbg(devname, "link lost (max retries)"); + break; + case STAT_FORCELOSS: + airo_print_dbg(devname, "link lost (local choice)"); + break; + case STAT_TSFSYNC: + airo_print_dbg(devname, "link lost (TSF sync lost)"); + break; + default: + airo_print_dbg(devname, "unknow status %x\n", status); + break; } + break; + case STAT_DEAUTH: + airo_print_dbg(devname, "deauthenticated (reason: %d)", reason); + break; + case STAT_DISASSOC: + airo_print_dbg(devname, "disassociated (reason: %d)", reason); + break; + case STAT_ASSOC_FAIL: + airo_print_dbg(devname, "association failed (reason: %d)", + reason); + break; + case STAT_AUTH_FAIL: + airo_print_dbg(devname, "authentication failed (reason: %d)", + reason); + break; + case STAT_ASSOC: + case STAT_REASSOC: + break; + default: + airo_print_dbg(devname, "unknow status %x\n", status); + break; + } +} - if (!savedInterrupts) { - savedInterrupts = IN4500( apriv, EVINTEN ); - OUT4500( apriv, EVINTEN, 0 ); - } +static void airo_handle_link(struct airo_info *ai) +{ + union iwreq_data wrqu; + int scan_forceloss = 0; + u16 status; - if ( status & EV_MIC ) { - OUT4500( apriv, EVACK, EV_MIC ); - if (test_bit(FLAG_MIC_CAPABLE, &apriv->flags)) { - set_bit(JOB_MIC, &apriv->jobs); - wake_up_interruptible(&apriv->thr_wait); - } - } - if ( status & EV_LINK ) { - union iwreq_data wrqu; - int scan_forceloss = 0; - /* The link status has changed, if you want to put a - monitor hook in, do it here. (Remember that - interrupts are still disabled!) - */ - u16 newStatus = IN4500(apriv, LINKSTAT); - OUT4500( apriv, EVACK, EV_LINK); - /* Here is what newStatus means: */ -#define NOBEACON 0x8000 /* Loss of sync - missed beacons */ -#define MAXRETRIES 0x8001 /* Loss of sync - max retries */ -#define MAXARL 0x8002 /* Loss of sync - average retry level exceeded*/ -#define FORCELOSS 0x8003 /* Loss of sync - host request */ -#define TSFSYNC 0x8004 /* Loss of sync - TSF synchronization */ -#define DEAUTH 0x8100 /* Deauthentication (low byte is reason code) */ -#define DISASS 0x8200 /* Disassociation (low byte is reason code) */ -#define ASSFAIL 0x8400 /* Association failure (low byte is reason - code) */ -#define AUTHFAIL 0x0300 /* Authentication failure (low byte is reason - code) */ -#define ASSOCIATED 0x0400 /* Associated */ -#define REASSOCIATED 0x0600 /* Reassociated? Only on firmware >= 5.30.17 */ -#define RC_RESERVED 0 /* Reserved return code */ -#define RC_NOREASON 1 /* Unspecified reason */ -#define RC_AUTHINV 2 /* Previous authentication invalid */ -#define RC_DEAUTH 3 /* Deauthenticated because sending station is - leaving */ -#define RC_NOACT 4 /* Disassociated due to inactivity */ -#define RC_MAXLOAD 5 /* Disassociated because AP is unable to handle - all currently associated stations */ -#define RC_BADCLASS2 6 /* Class 2 frame received from - non-Authenticated station */ -#define RC_BADCLASS3 7 /* Class 3 frame received from - non-Associated station */ -#define RC_STATLEAVE 8 /* Disassociated because sending station is - leaving BSS */ -#define RC_NOAUTH 9 /* Station requesting (Re)Association is not - Authenticated with the responding station */ - if (newStatus == FORCELOSS && apriv->scan_timeout > 0) - scan_forceloss = 1; - if(newStatus == ASSOCIATED || newStatus == REASSOCIATED) { - if (auto_wep) - apriv->expires = 0; - if (apriv->list_bss_task) - wake_up_process(apriv->list_bss_task); - set_bit(FLAG_UPDATE_UNI, &apriv->flags); - set_bit(FLAG_UPDATE_MULTI, &apriv->flags); - - if (down_trylock(&apriv->sem) != 0) { - set_bit(JOB_EVENT, &apriv->jobs); - wake_up_interruptible(&apriv->thr_wait); - } else - airo_send_event(dev); - } else if (!scan_forceloss) { - if (auto_wep && !apriv->expires) { - apriv->expires = RUN_AT(3*HZ); - wake_up_interruptible(&apriv->thr_wait); - } + /* Get new status and acknowledge the link change */ + status = le16_to_cpu(IN4500(ai, LINKSTAT)); + OUT4500(ai, EVACK, EV_LINK); - /* Send event to user space */ - memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(dev, SIOCGIWAP, &wrqu,NULL); - } + if ((status == STAT_FORCELOSS) && (ai->scan_timeout > 0)) + scan_forceloss = 1; + + airo_print_status(ai->dev->name, status); + + if ((status == STAT_ASSOC) || (status == STAT_REASSOC)) { + if (auto_wep) + ai->expires = 0; + if (ai->list_bss_task) + wake_up_process(ai->list_bss_task); + set_bit(FLAG_UPDATE_UNI, &ai->flags); + set_bit(FLAG_UPDATE_MULTI, &ai->flags); + + if (down_trylock(&ai->sem) != 0) { + set_bit(JOB_EVENT, &ai->jobs); + wake_up_interruptible(&ai->thr_wait); + } else + airo_send_event(ai->dev); + } else if (!scan_forceloss) { + if (auto_wep && !ai->expires) { + ai->expires = RUN_AT(3*HZ); + wake_up_interruptible(&ai->thr_wait); } - /* Check to see if there is something to receive */ - if ( status & EV_RX ) { - struct sk_buff *skb = NULL; - u16 fc, len, hdrlen = 0; -#pragma pack(1) - struct { - u16 status, len; - u8 rssi[2]; - u8 rate; - u8 freq; - u16 tmp[4]; - } hdr; -#pragma pack() - u16 gap; - u16 tmpbuf[4]; - u16 *buffer; - - if (test_bit(FLAG_MPI,&apriv->flags)) { - if (test_bit(FLAG_802_11, &apriv->flags)) - mpi_receive_802_11(apriv); - else - mpi_receive_802_3(apriv); - OUT4500(apriv, EVACK, EV_RX); - goto exitrx; - } + /* Send event to user space */ + memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + wireless_send_event(ai->dev, SIOCGIWAP, &wrqu, NULL); + } +} + +static void airo_handle_rx(struct airo_info *ai) +{ + struct sk_buff *skb = NULL; + __le16 fc, v, *buffer, tmpbuf[4]; + u16 len, hdrlen = 0, gap, fid; + struct rx_hdr hdr; + int success = 0; + + if (test_bit(FLAG_MPI, &ai->flags)) { + if (test_bit(FLAG_802_11, &ai->flags)) + mpi_receive_802_11(ai); + else + mpi_receive_802_3(ai); + OUT4500(ai, EVACK, EV_RX); + return; + } + + fid = IN4500(ai, RXFID); + + /* Get the packet length */ + if (test_bit(FLAG_802_11, &ai->flags)) { + bap_setup (ai, fid, 4, BAP0); + bap_read (ai, (__le16*)&hdr, sizeof(hdr), BAP0); + /* Bad CRC. Ignore packet */ + if (le16_to_cpu(hdr.status) & 2) + hdr.len = 0; + if (ai->wifidev == NULL) + hdr.len = 0; + } else { + bap_setup(ai, fid, 0x36, BAP0); + bap_read(ai, &hdr.len, 2, BAP0); + } + len = le16_to_cpu(hdr.len); + + if (len > AIRO_DEF_MTU) { + airo_print_err(ai->dev->name, "Bad size %d", len); + goto done; + } + if (len == 0) + goto done; - fid = IN4500( apriv, RXFID ); - - /* Get the packet length */ - if (test_bit(FLAG_802_11, &apriv->flags)) { - bap_setup (apriv, fid, 4, BAP0); - bap_read (apriv, (u16*)&hdr, sizeof(hdr), BAP0); - /* Bad CRC. Ignore packet */ - if (le16_to_cpu(hdr.status) & 2) - hdr.len = 0; - if (apriv->wifidev == NULL) - hdr.len = 0; + if (test_bit(FLAG_802_11, &ai->flags)) { + bap_read(ai, &fc, sizeof (fc), BAP0); + hdrlen = header_len(fc); + } else + hdrlen = ETH_ALEN * 2; + + skb = dev_alloc_skb(len + hdrlen + 2 + 2); + if (!skb) { + ai->dev->stats.rx_dropped++; + goto done; + } + + skb_reserve(skb, 2); /* This way the IP header is aligned */ + buffer = (__le16 *) skb_put(skb, len + hdrlen); + if (test_bit(FLAG_802_11, &ai->flags)) { + buffer[0] = fc; + bap_read(ai, buffer + 1, hdrlen - 2, BAP0); + if (hdrlen == 24) + bap_read(ai, tmpbuf, 6, BAP0); + + bap_read(ai, &v, sizeof(v), BAP0); + gap = le16_to_cpu(v); + if (gap) { + if (gap <= 8) { + bap_read(ai, tmpbuf, gap, BAP0); } else { - bap_setup (apriv, fid, 0x36, BAP0); - bap_read (apriv, (u16*)&hdr.len, 2, BAP0); + airo_print_err(ai->dev->name, "gaplen too " + "big. Problems will follow..."); } - len = le16_to_cpu(hdr.len); + } + bap_read(ai, buffer + hdrlen/2, len, BAP0); + } else { + MICBuffer micbuf; - if (len > AIRO_DEF_MTU) { - airo_print_err(apriv->dev->name, "Bad size %d", len); - goto badrx; - } - if (len == 0) - goto badrx; - - if (test_bit(FLAG_802_11, &apriv->flags)) { - bap_read (apriv, (u16*)&fc, sizeof(fc), BAP0); - fc = le16_to_cpu(fc); - switch (fc & 0xc) { - case 4: - if ((fc & 0xe0) == 0xc0) - hdrlen = 10; - else - hdrlen = 16; - break; - case 8: - if ((fc&0x300)==0x300){ - hdrlen = 30; - break; - } - default: - hdrlen = 24; + bap_read(ai, buffer, ETH_ALEN * 2, BAP0); + if (ai->micstats.enabled) { + bap_read(ai, (__le16 *) &micbuf, sizeof (micbuf), BAP0); + if (ntohs(micbuf.typelen) > 0x05DC) + bap_setup(ai, fid, 0x44, BAP0); + else { + if (len <= sizeof (micbuf)) { + dev_kfree_skb_irq(skb); + goto done; } - } else - hdrlen = ETH_ALEN * 2; - skb = dev_alloc_skb( len + hdrlen + 2 + 2 ); - if ( !skb ) { - apriv->stats.rx_dropped++; - goto badrx; - } - skb_reserve(skb, 2); /* This way the IP header is aligned */ - buffer = (u16*)skb_put (skb, len + hdrlen); - if (test_bit(FLAG_802_11, &apriv->flags)) { - buffer[0] = fc; - bap_read (apriv, buffer + 1, hdrlen - 2, BAP0); - if (hdrlen == 24) - bap_read (apriv, tmpbuf, 6, BAP0); - - bap_read (apriv, &gap, sizeof(gap), BAP0); - gap = le16_to_cpu(gap); - if (gap) { - if (gap <= 8) { - bap_read (apriv, tmpbuf, gap, BAP0); - } else { - airo_print_err(apriv->dev->name, "gaplen too " - "big. Problems will follow..."); - } - } - bap_read (apriv, buffer + hdrlen/2, len, BAP0); - } else { - MICBuffer micbuf; - bap_read (apriv, buffer, ETH_ALEN*2, BAP0); - if (apriv->micstats.enabled) { - bap_read (apriv,(u16*)&micbuf,sizeof(micbuf),BAP0); - if (ntohs(micbuf.typelen) > 0x05DC) - bap_setup (apriv, fid, 0x44, BAP0); - else { - if (len <= sizeof(micbuf)) - goto badmic; - - len -= sizeof(micbuf); - skb_trim (skb, len + hdrlen); - } - } - bap_read(apriv,buffer+ETH_ALEN,len,BAP0); - if (decapsulate(apriv,&micbuf,(etherHead*)buffer,len)) { -badmic: - dev_kfree_skb_irq (skb); -badrx: - OUT4500( apriv, EVACK, EV_RX); - goto exitrx; - } + len -= sizeof(micbuf); + skb_trim(skb, len + hdrlen); } + } + + bap_read(ai, buffer + ETH_ALEN, len, BAP0); + if (decapsulate(ai, &micbuf, (etherHead*) buffer, len)) + dev_kfree_skb_irq (skb); + else + success = 1; + } + #ifdef WIRELESS_SPY - if (apriv->spy_data.spy_number > 0) { - char *sa; - struct iw_quality wstats; - /* Prepare spy data : addr + qual */ - if (!test_bit(FLAG_802_11, &apriv->flags)) { - sa = (char*)buffer + 6; - bap_setup (apriv, fid, 8, BAP0); - bap_read (apriv, (u16*)hdr.rssi, 2, BAP0); - } else - sa = (char*)buffer + 10; - wstats.qual = hdr.rssi[0]; - if (apriv->rssi) - wstats.level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm; - else - wstats.level = (hdr.rssi[1] + 321) / 2; - wstats.noise = apriv->wstats.qual.noise; - wstats.updated = IW_QUAL_LEVEL_UPDATED - | IW_QUAL_QUAL_UPDATED - | IW_QUAL_DBM; - /* Update spy records */ - wireless_spy_update(dev, sa, &wstats); - } + if (success && (ai->spy_data.spy_number > 0)) { + char *sa; + struct iw_quality wstats; + + /* Prepare spy data : addr + qual */ + if (!test_bit(FLAG_802_11, &ai->flags)) { + sa = (char *) buffer + 6; + bap_setup(ai, fid, 8, BAP0); + bap_read(ai, (__le16 *) hdr.rssi, 2, BAP0); + } else + sa = (char *) buffer + 10; + wstats.qual = hdr.rssi[0]; + if (ai->rssi) + wstats.level = 0x100 - ai->rssi[hdr.rssi[1]].rssidBm; + else + wstats.level = (hdr.rssi[1] + 321) / 2; + wstats.noise = ai->wstats.qual.noise; + wstats.updated = IW_QUAL_LEVEL_UPDATED + | IW_QUAL_QUAL_UPDATED + | IW_QUAL_DBM; + /* Update spy records */ + wireless_spy_update(ai->dev, sa, &wstats); + } #endif /* WIRELESS_SPY */ - OUT4500( apriv, EVACK, EV_RX); - if (test_bit(FLAG_802_11, &apriv->flags)) { - skb_reset_mac_header(skb); - skb->pkt_type = PACKET_OTHERHOST; - skb->dev = apriv->wifidev; - skb->protocol = htons(ETH_P_802_2); - } else - skb->protocol = eth_type_trans(skb,dev); - skb->dev->last_rx = jiffies; - skb->ip_summed = CHECKSUM_NONE; +done: + OUT4500(ai, EVACK, EV_RX); + + if (success) { + if (test_bit(FLAG_802_11, &ai->flags)) { + skb_reset_mac_header(skb); + skb->pkt_type = PACKET_OTHERHOST; + skb->dev = ai->wifidev; + skb->protocol = htons(ETH_P_802_2); + } else + skb->protocol = eth_type_trans(skb, ai->dev); + skb->ip_summed = CHECKSUM_NONE; - netif_rx( skb ); + netif_rx(skb); + } +} + +static void airo_handle_tx(struct airo_info *ai, u16 status) +{ + int i, len = 0, index = -1; + u16 fid; + + if (test_bit(FLAG_MPI, &ai->flags)) { + unsigned long flags; + + if (status & EV_TXEXC) + get_tx_error(ai, -1); + + spin_lock_irqsave(&ai->aux_lock, flags); + if (!skb_queue_empty(&ai->txq)) { + spin_unlock_irqrestore(&ai->aux_lock,flags); + mpi_send_packet(ai->dev); + } else { + clear_bit(FLAG_PENDING_XMIT, &ai->flags); + spin_unlock_irqrestore(&ai->aux_lock,flags); + netif_wake_queue(ai->dev); } -exitrx: + OUT4500(ai, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC)); + return; + } - /* Check to see if a packet has been transmitted */ - if ( status & ( EV_TX|EV_TXCPY|EV_TXEXC ) ) { - int i; - int len = 0; - int index = -1; - - if (test_bit(FLAG_MPI,&apriv->flags)) { - unsigned long flags; - - if (status & EV_TXEXC) - get_tx_error(apriv, -1); - spin_lock_irqsave(&apriv->aux_lock, flags); - if (!skb_queue_empty(&apriv->txq)) { - spin_unlock_irqrestore(&apriv->aux_lock,flags); - mpi_send_packet (dev); - } else { - clear_bit(FLAG_PENDING_XMIT, &apriv->flags); - spin_unlock_irqrestore(&apriv->aux_lock,flags); - netif_wake_queue (dev); - } - OUT4500( apriv, EVACK, - status & (EV_TX|EV_TXCPY|EV_TXEXC)); - goto exittx; - } + fid = IN4500(ai, TXCOMPLFID); - fid = IN4500(apriv, TXCOMPLFID); + for(i = 0; i < MAX_FIDS; i++) { + if ((ai->fids[i] & 0xffff) == fid) { + len = ai->fids[i] >> 16; + index = i; + } + } - for( i = 0; i < MAX_FIDS; i++ ) { - if ( ( apriv->fids[i] & 0xffff ) == fid ) { - len = apriv->fids[i] >> 16; - index = i; - } - } - if (index != -1) { - if (status & EV_TXEXC) - get_tx_error(apriv, index); - OUT4500( apriv, EVACK, status & (EV_TX | EV_TXEXC)); - /* Set up to be used again */ - apriv->fids[index] &= 0xffff; - if (index < MAX_FIDS / 2) { - if (!test_bit(FLAG_PENDING_XMIT, &apriv->flags)) - netif_wake_queue(dev); - } else { - if (!test_bit(FLAG_PENDING_XMIT11, &apriv->flags)) - netif_wake_queue(apriv->wifidev); - } - } else { - OUT4500( apriv, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC)); - airo_print_err(apriv->dev->name, "Unallocated FID was " - "used to xmit" ); - } + if (index != -1) { + if (status & EV_TXEXC) + get_tx_error(ai, index); + + OUT4500(ai, EVACK, status & (EV_TX | EV_TXEXC)); + + /* Set up to be used again */ + ai->fids[index] &= 0xffff; + if (index < MAX_FIDS / 2) { + if (!test_bit(FLAG_PENDING_XMIT, &ai->flags)) + netif_wake_queue(ai->dev); + } else { + if (!test_bit(FLAG_PENDING_XMIT11, &ai->flags)) + netif_wake_queue(ai->wifidev); + } + } else { + OUT4500(ai, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC)); + airo_print_err(ai->dev->name, "Unallocated FID was used to xmit"); + } +} + +static irqreturn_t airo_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + u16 status, savedInterrupts = 0; + struct airo_info *ai = dev->ml_priv; + int handled = 0; + + if (!netif_device_present(dev)) + return IRQ_NONE; + + for (;;) { + status = IN4500(ai, EVSTAT); + if (!(status & STATUS_INTS) || (status == 0xffff)) + break; + + handled = 1; + + if (status & EV_AWAKE) { + OUT4500(ai, EVACK, EV_AWAKE); + OUT4500(ai, EVACK, EV_AWAKE); + } + + if (!savedInterrupts) { + savedInterrupts = IN4500(ai, EVINTEN); + OUT4500(ai, EVINTEN, 0); + } + + if (status & EV_MIC) { + OUT4500(ai, EVACK, EV_MIC); + airo_handle_cisco_mic(ai); } -exittx: - if ( status & ~STATUS_INTS & ~IGNORE_INTS ) - airo_print_warn(apriv->dev->name, "Got weird status %x", + + if (status & EV_LINK) { + /* Link status changed */ + airo_handle_link(ai); + } + + /* Check to see if there is something to receive */ + if (status & EV_RX) + airo_handle_rx(ai); + + /* Check to see if a packet has been transmitted */ + if (status & (EV_TX | EV_TXCPY | EV_TXEXC)) + airo_handle_tx(ai, status); + + if ( status & ~STATUS_INTS & ~IGNORE_INTS ) { + airo_print_warn(ai->dev->name, "Got weird status %x", status & ~STATUS_INTS & ~IGNORE_INTS ); + } } if (savedInterrupts) - OUT4500( apriv, EVINTEN, savedInterrupts ); + OUT4500(ai, EVINTEN, savedInterrupts); - /* done.. */ return IRQ_RETVAL(handled); } @@ -3619,7 +3647,7 @@ static void mpi_receive_802_3(struct airo_info *ai) skb = dev_alloc_skb(len); if (!skb) { - ai->stats.rx_dropped++; + ai->dev->stats.rx_dropped++; goto badrx; } buffer = skb_put(skb,len); @@ -3660,7 +3688,6 @@ badmic: skb->ip_summed = CHECKSUM_NONE; skb->protocol = eth_type_trans(skb, ai->dev); - skb->dev->last_rx = jiffies; netif_rx(skb); } badrx: @@ -3672,23 +3699,16 @@ badrx: } } -void mpi_receive_802_11 (struct airo_info *ai) +static void mpi_receive_802_11(struct airo_info *ai) { RxFid rxd; struct sk_buff *skb = NULL; - u16 fc, len, hdrlen = 0; -#pragma pack(1) - struct { - u16 status, len; - u8 rssi[2]; - u8 rate; - u8 freq; - u16 tmp[4]; - } hdr; -#pragma pack() + u16 len, hdrlen = 0; + __le16 fc; + struct rx_hdr hdr; u16 gap; u16 *buffer; - char *ptr = ai->rxfids[0].virtual_host_addr+4; + char *ptr = ai->rxfids[0].virtual_host_addr + 4; memcpy_fromio(&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd)); memcpy ((char *)&hdr, ptr, sizeof(hdr)); @@ -3706,27 +3726,12 @@ void mpi_receive_802_11 (struct airo_info *ai) if (len == 0) goto badrx; - memcpy ((char *)&fc, ptr, sizeof(fc)); - fc = le16_to_cpu(fc); - switch (fc & 0xc) { - case 4: - if ((fc & 0xe0) == 0xc0) - hdrlen = 10; - else - hdrlen = 16; - break; - case 8: - if ((fc&0x300)==0x300){ - hdrlen = 30; - break; - } - default: - hdrlen = 24; - } + fc = get_unaligned((__le16 *)ptr); + hdrlen = header_len(fc); skb = dev_alloc_skb( len + hdrlen + 2 ); if ( !skb ) { - ai->stats.rx_dropped++; + ai->dev->stats.rx_dropped++; goto badrx; } buffer = (u16*)skb_put (skb, len + hdrlen); @@ -3734,9 +3739,8 @@ void mpi_receive_802_11 (struct airo_info *ai) ptr += hdrlen; if (hdrlen == 24) ptr += 6; - memcpy ((char *)&gap, ptr, sizeof(gap)); - ptr += sizeof(gap); - gap = le16_to_cpu(gap); + gap = get_unaligned_le16(ptr); + ptr += sizeof(__le16); if (gap) { if (gap <= 8) ptr += gap; @@ -3769,9 +3773,9 @@ void mpi_receive_802_11 (struct airo_info *ai) skb->pkt_type = PACKET_OTHERHOST; skb->dev = ai->wifidev; skb->protocol = htons(ETH_P_802_2); - skb->dev->last_rx = jiffies; skb->ip_summed = CHECKSUM_NONE; netif_rx( skb ); + badrx: if (rxd.valid == 0) { rxd.valid = 1; @@ -3786,9 +3790,8 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) Cmd cmd; Resp rsp; int status; - int i; SsidRid mySsid; - u16 lastindex; + __le16 lastindex; WepKeyRid wkr; int rc; @@ -3828,6 +3831,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) if (lock) up(&ai->sem); if (ai->config.len == 0) { + int i; tdsRssiRid rssi_rid; CapabilityRid cap_rid; @@ -3850,7 +3854,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) else { kfree(ai->rssi); ai->rssi = NULL; - if (cap_rid.softCap & 8) + if (cap_rid.softCap & cpu_to_le16(8)) ai->config.rmode |= RXMODE_NORMALIZED_RSSI; else airo_print_warn(ai->dev->name, "unknown received signal " @@ -3860,8 +3864,9 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) ai->config.authType = AUTH_OPEN; ai->config.modulation = MOD_CCK; - if ((cap_rid.len>=sizeof(cap_rid)) && (cap_rid.extSoftCap&1) && - (micsetup(ai) == SUCCESS)) { + if (le16_to_cpu(cap_rid.len) >= sizeof(cap_rid) && + (cap_rid.extSoftCap & cpu_to_le16(1)) && + micsetup(ai) == SUCCESS) { ai->config.opmode |= MODE_MIC; set_bit(FLAG_MIC_CAPABLE, &ai->flags); } @@ -3874,22 +3879,11 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) /* Check to see if there are any insmod configured rates to add */ if ( rates[0] ) { - int i = 0; memset(ai->config.rates,0,sizeof(ai->config.rates)); for( i = 0; i < 8 && rates[i]; i++ ) { ai->config.rates[i] = rates[i]; } } - if ( basic_rate > 0 ) { - int i; - for( i = 0; i < 8; i++ ) { - if ( ai->config.rates[i] == basic_rate || - !ai->config.rates ) { - ai->config.rates[i] = basic_rate | 0x80; - break; - } - } - } set_bit (FLAG_COMMIT, &ai->flags); } @@ -3897,13 +3891,13 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) if ( ssids[0] ) { int i; for( i = 0; i < 3 && ssids[i]; i++ ) { - mySsid.ssids[i].len = strlen(ssids[i]); - if ( mySsid.ssids[i].len > 32 ) - mySsid.ssids[i].len = 32; - memcpy(mySsid.ssids[i].ssid, ssids[i], - mySsid.ssids[i].len); + size_t len = strlen(ssids[i]); + if (len > 32) + len = 32; + mySsid.ssids[i].len = cpu_to_le16(len); + memcpy(mySsid.ssids[i].ssid, ssids[i], len); } - mySsid.len = sizeof(mySsid); + mySsid.len = cpu_to_le16(sizeof(mySsid)); } status = writeConfigRid(ai, lock); @@ -3923,7 +3917,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) rc = readWepKeyRid(ai, &wkr, 1, lock); if (rc == SUCCESS) do { lastindex = wkr.kindex; - if (wkr.kindex == 0xffff) { + if (wkr.kindex == cpu_to_le16(0xffff)) { ai->defindex = wkr.mac[0]; } rc = readWepKeyRid(ai, &wkr, 0, lock); @@ -3956,7 +3950,7 @@ static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) { if ( max_tries == -1 ) { airo_print_err(ai->dev->name, - "Max tries exceeded when issueing command"); + "Max tries exceeded when issuing command"); if (IN4500(ai, COMMAND) & COMMAND_BUSY) OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY); return ERROR; @@ -4038,7 +4032,7 @@ static u16 aux_setup(struct airo_info *ai, u16 page, } /* requires call to bap_setup() first */ -static int aux_bap_read(struct airo_info *ai, u16 *pu16Dst, +static int aux_bap_read(struct airo_info *ai, __le16 *pu16Dst, int bytelen, int whichbap) { u16 len; @@ -4075,7 +4069,7 @@ static int aux_bap_read(struct airo_info *ai, u16 *pu16Dst, /* requires call to bap_setup() first */ -static int fast_bap_read(struct airo_info *ai, u16 *pu16Dst, +static int fast_bap_read(struct airo_info *ai, __le16 *pu16Dst, int bytelen, int whichbap) { bytelen = (bytelen + 1) & (~1); // round up to even value @@ -4087,7 +4081,7 @@ static int fast_bap_read(struct airo_info *ai, u16 *pu16Dst, } /* requires call to bap_setup() first */ -static int bap_write(struct airo_info *ai, const u16 *pu16Src, +static int bap_write(struct airo_info *ai, const __le16 *pu16Src, int bytelen, int whichbap) { bytelen = (bytelen + 1) & (~1); // round up to even value @@ -4163,7 +4157,7 @@ static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len, in // read the rid length field bap_read(ai, pBuf, 2, BAP1); // length for remaining part of rid - len = min(len, (int)le16_to_cpu(*(u16*)pBuf)) - 2; + len = min(len, (int)le16_to_cpu(*(__le16*)pBuf)) - 2; if ( len <= 2 ) { airo_print_err(ai->dev->name, @@ -4173,7 +4167,7 @@ static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len, in goto done; } // read remainder of the rid - rc = bap_read(ai, ((u16*)pBuf)+1, len, BAP1); + rc = bap_read(ai, ((__le16*)pBuf)+1, len, BAP1); } done: if (lock) @@ -4182,14 +4176,14 @@ done: } /* Note, that we are using BAP1 which is also used by transmit, so - * make sure this isnt called when a transmit is happening */ + * make sure this isn't called when a transmit is happening */ static int PC4500_writerid(struct airo_info *ai, u16 rid, const void *pBuf, int len, int lock) { u16 status; int rc = SUCCESS; - *(u16*)pBuf = cpu_to_le16((u16)len); + *(__le16*)pBuf = cpu_to_le16((u16)len); if (lock) { if (down_interruptible(&ai->sem)) @@ -4202,7 +4196,7 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid, if (test_bit(FLAG_ENABLED, &ai->flags) && (RID_WEP_TEMP != rid)) airo_print_err(ai->dev->name, "%s: MAC should be disabled (rid=%04x)", - __FUNCTION__, rid); + __func__, rid); memset(&cmd, 0, sizeof(cmd)); memset(&rsp, 0, sizeof(rsp)); @@ -4217,18 +4211,18 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid, &ai->config_desc.rid_desc, sizeof(Rid)); if (len < 4 || len > 2047) { - airo_print_err(ai->dev->name, "%s: len=%d", __FUNCTION__, len); + airo_print_err(ai->dev->name, "%s: len=%d", __func__, len); rc = -1; } else { - memcpy((char *)ai->config_desc.virtual_host_addr, + memcpy(ai->config_desc.virtual_host_addr, pBuf, len); rc = issuecommand(ai, &cmd, &rsp); if ((rc & 0xff00) != 0) { airo_print_err(ai->dev->name, "%s: Write rid Error %d", - __FUNCTION__, rc); + __func__, rc); airo_print_err(ai->dev->name, "%s: Cmd=%04x", - __FUNCTION__, cmd.cmd); + __func__, cmd.cmd); } if ((rsp.status & 0x7f00)) @@ -4263,7 +4257,7 @@ static u16 transmit_allocate(struct airo_info *ai, int lenPayload, int raw) Cmd cmd; Resp rsp; u16 txFid; - u16 txControl; + __le16 txControl; cmd.cmd = CMD_ALLOCATETX; cmd.parm0 = lenPayload; @@ -4317,7 +4311,7 @@ done: Make sure the BAP1 spinlock is held when this is called. */ static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket) { - u16 payloadLen; + __le16 payloadLen; Cmd cmd; Resp rsp; int miclen = 0; @@ -4333,7 +4327,7 @@ static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket) len -= ETH_ALEN * 2; if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled && - (ntohs(((u16 *)pPacket)[6]) != 0x888E)) { + (ntohs(((__be16 *)pPacket)[6]) != 0x888E)) { if (encapsulate(ai,(etherHead *)pPacket,&pMic,len) != SUCCESS) return ERROR; miclen = sizeof(pMic); @@ -4345,10 +4339,10 @@ static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket) * we have to subtract the 12 bytes for the addresses off */ payloadLen = cpu_to_le16(len + miclen); bap_write(ai, &payloadLen, sizeof(payloadLen),BAP1); - bap_write(ai, (const u16*)pPacket, sizeof(etherHead), BAP1); + bap_write(ai, (__le16*)pPacket, sizeof(etherHead), BAP1); if (miclen) - bap_write(ai, (const u16*)&pMic, miclen, BAP1); - bap_write(ai, (const u16*)(pPacket + sizeof(etherHead)), len, BAP1); + bap_write(ai, (__le16*)&pMic, miclen, BAP1); + bap_write(ai, (__le16*)(pPacket + sizeof(etherHead)), len, BAP1); // issue the transmit command memset( &cmd, 0, sizeof( cmd ) ); cmd.cmd = CMD_TRANSMIT; @@ -4360,35 +4354,17 @@ static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket) static int transmit_802_11_packet(struct airo_info *ai, int len, char *pPacket) { - u16 fc, payloadLen; + __le16 fc, payloadLen; Cmd cmd; Resp rsp; int hdrlen; - struct { - u8 addr4[ETH_ALEN]; - u16 gaplen; - u8 gap[6]; - } gap; + static u8 tail[(30-10) + 2 + 6] = {[30-10] = 6}; + /* padding of header to full size + le16 gaplen (6) + gaplen bytes */ u16 txFid = len; len >>= 16; - gap.gaplen = 6; - fc = le16_to_cpu(*(const u16*)pPacket); - switch (fc & 0xc) { - case 4: - if ((fc & 0xe0) == 0xc0) - hdrlen = 10; - else - hdrlen = 16; - break; - case 8: - if ((fc&0x300)==0x300){ - hdrlen = 30; - break; - } - default: - hdrlen = 24; - } + fc = *(__le16*)pPacket; + hdrlen = header_len(fc); if (len < hdrlen) { airo_print_warn(ai->dev->name, "Short packet %d", len); @@ -4403,11 +4379,10 @@ static int transmit_802_11_packet(struct airo_info *ai, int len, char *pPacket) payloadLen = cpu_to_le16(len-hdrlen); bap_write(ai, &payloadLen, sizeof(payloadLen),BAP1); if (bap_setup(ai, txFid, 0x0014, BAP1) != SUCCESS) return ERROR; - bap_write(ai, (const u16*)pPacket, hdrlen, BAP1); - bap_write(ai, hdrlen == 30 ? - (const u16*)&gap.gaplen : (const u16*)&gap, 38 - hdrlen, BAP1); + bap_write(ai, (__le16 *)pPacket, hdrlen, BAP1); + bap_write(ai, (__le16 *)(tail + (hdrlen - 10)), 38 - hdrlen, BAP1); - bap_write(ai, (const u16*)(pPacket + hdrlen), len - hdrlen, BAP1); + bap_write(ai, (__le16 *)(pPacket + hdrlen), len - hdrlen, BAP1); // issue the transmit command memset( &cmd, 0, sizeof( cmd ) ); cmd.cmd = CMD_TRANSMIT; @@ -4443,56 +4418,72 @@ static int proc_config_open( struct inode *inode, struct file *file ); static int proc_wepkey_open( struct inode *inode, struct file *file ); static const struct file_operations proc_statsdelta_ops = { + .owner = THIS_MODULE, .read = proc_read, .open = proc_statsdelta_open, - .release = proc_close + .release = proc_close, + .llseek = default_llseek, }; static const struct file_operations proc_stats_ops = { + .owner = THIS_MODULE, .read = proc_read, .open = proc_stats_open, - .release = proc_close + .release = proc_close, + .llseek = default_llseek, }; static const struct file_operations proc_status_ops = { + .owner = THIS_MODULE, .read = proc_read, .open = proc_status_open, - .release = proc_close + .release = proc_close, + .llseek = default_llseek, }; static const struct file_operations proc_SSID_ops = { + .owner = THIS_MODULE, .read = proc_read, .write = proc_write, .open = proc_SSID_open, - .release = proc_close + .release = proc_close, + .llseek = default_llseek, }; static const struct file_operations proc_BSSList_ops = { + .owner = THIS_MODULE, .read = proc_read, .write = proc_write, .open = proc_BSSList_open, - .release = proc_close + .release = proc_close, + .llseek = default_llseek, }; static const struct file_operations proc_APList_ops = { + .owner = THIS_MODULE, .read = proc_read, .write = proc_write, .open = proc_APList_open, - .release = proc_close + .release = proc_close, + .llseek = default_llseek, }; static const struct file_operations proc_config_ops = { + .owner = THIS_MODULE, .read = proc_read, .write = proc_write, .open = proc_config_open, - .release = proc_close + .release = proc_close, + .llseek = default_llseek, }; static const struct file_operations proc_wepkey_ops = { + .owner = THIS_MODULE, .read = proc_read, .write = proc_write, .open = proc_wepkey_open, - .release = proc_close + .release = proc_close, + .llseek = default_llseek, }; static struct proc_dir_entry *airo_entry; @@ -4507,154 +4498,84 @@ struct proc_data { void (*on_close) (struct inode *, struct file *); }; -#ifndef SETPROC_OPS -#define SETPROC_OPS(entry, ops) (entry)->proc_fops = &(ops) -#endif - static int setup_proc_entry( struct net_device *dev, struct airo_info *apriv ) { struct proc_dir_entry *entry; + /* First setup the device directory */ strcpy(apriv->proc_name,dev->name); - apriv->proc_entry = create_proc_entry(apriv->proc_name, - S_IFDIR|airo_perm, - airo_entry); + apriv->proc_entry = proc_mkdir_mode(apriv->proc_name, airo_perm, + airo_entry); if (!apriv->proc_entry) - goto fail; - apriv->proc_entry->uid = proc_uid; - apriv->proc_entry->gid = proc_gid; - apriv->proc_entry->owner = THIS_MODULE; + return -ENOMEM; + proc_set_user(apriv->proc_entry, proc_kuid, proc_kgid); /* Setup the StatsDelta */ - entry = create_proc_entry("StatsDelta", - S_IFREG | (S_IRUGO&proc_perm), - apriv->proc_entry); + entry = proc_create_data("StatsDelta", S_IRUGO & proc_perm, + apriv->proc_entry, &proc_statsdelta_ops, dev); if (!entry) - goto fail_stats_delta; - entry->uid = proc_uid; - entry->gid = proc_gid; - entry->data = dev; - entry->owner = THIS_MODULE; - SETPROC_OPS(entry, proc_statsdelta_ops); + goto fail; + proc_set_user(entry, proc_kuid, proc_kgid); /* Setup the Stats */ - entry = create_proc_entry("Stats", - S_IFREG | (S_IRUGO&proc_perm), - apriv->proc_entry); + entry = proc_create_data("Stats", S_IRUGO & proc_perm, + apriv->proc_entry, &proc_stats_ops, dev); if (!entry) - goto fail_stats; - entry->uid = proc_uid; - entry->gid = proc_gid; - entry->data = dev; - entry->owner = THIS_MODULE; - SETPROC_OPS(entry, proc_stats_ops); + goto fail; + proc_set_user(entry, proc_kuid, proc_kgid); /* Setup the Status */ - entry = create_proc_entry("Status", - S_IFREG | (S_IRUGO&proc_perm), - apriv->proc_entry); + entry = proc_create_data("Status", S_IRUGO & proc_perm, + apriv->proc_entry, &proc_status_ops, dev); if (!entry) - goto fail_status; - entry->uid = proc_uid; - entry->gid = proc_gid; - entry->data = dev; - entry->owner = THIS_MODULE; - SETPROC_OPS(entry, proc_status_ops); + goto fail; + proc_set_user(entry, proc_kuid, proc_kgid); /* Setup the Config */ - entry = create_proc_entry("Config", - S_IFREG | proc_perm, - apriv->proc_entry); + entry = proc_create_data("Config", proc_perm, + apriv->proc_entry, &proc_config_ops, dev); if (!entry) - goto fail_config; - entry->uid = proc_uid; - entry->gid = proc_gid; - entry->data = dev; - entry->owner = THIS_MODULE; - SETPROC_OPS(entry, proc_config_ops); + goto fail; + proc_set_user(entry, proc_kuid, proc_kgid); /* Setup the SSID */ - entry = create_proc_entry("SSID", - S_IFREG | proc_perm, - apriv->proc_entry); + entry = proc_create_data("SSID", proc_perm, + apriv->proc_entry, &proc_SSID_ops, dev); if (!entry) - goto fail_ssid; - entry->uid = proc_uid; - entry->gid = proc_gid; - entry->data = dev; - entry->owner = THIS_MODULE; - SETPROC_OPS(entry, proc_SSID_ops); + goto fail; + proc_set_user(entry, proc_kuid, proc_kgid); /* Setup the APList */ - entry = create_proc_entry("APList", - S_IFREG | proc_perm, - apriv->proc_entry); + entry = proc_create_data("APList", proc_perm, + apriv->proc_entry, &proc_APList_ops, dev); if (!entry) - goto fail_aplist; - entry->uid = proc_uid; - entry->gid = proc_gid; - entry->data = dev; - entry->owner = THIS_MODULE; - SETPROC_OPS(entry, proc_APList_ops); + goto fail; + proc_set_user(entry, proc_kuid, proc_kgid); /* Setup the BSSList */ - entry = create_proc_entry("BSSList", - S_IFREG | proc_perm, - apriv->proc_entry); + entry = proc_create_data("BSSList", proc_perm, + apriv->proc_entry, &proc_BSSList_ops, dev); if (!entry) - goto fail_bsslist; - entry->uid = proc_uid; - entry->gid = proc_gid; - entry->data = dev; - entry->owner = THIS_MODULE; - SETPROC_OPS(entry, proc_BSSList_ops); + goto fail; + proc_set_user(entry, proc_kuid, proc_kgid); /* Setup the WepKey */ - entry = create_proc_entry("WepKey", - S_IFREG | proc_perm, - apriv->proc_entry); + entry = proc_create_data("WepKey", proc_perm, + apriv->proc_entry, &proc_wepkey_ops, dev); if (!entry) - goto fail_wepkey; - entry->uid = proc_uid; - entry->gid = proc_gid; - entry->data = dev; - entry->owner = THIS_MODULE; - SETPROC_OPS(entry, proc_wepkey_ops); - + goto fail; + proc_set_user(entry, proc_kuid, proc_kgid); return 0; -fail_wepkey: - remove_proc_entry("BSSList", apriv->proc_entry); -fail_bsslist: - remove_proc_entry("APList", apriv->proc_entry); -fail_aplist: - remove_proc_entry("SSID", apriv->proc_entry); -fail_ssid: - remove_proc_entry("Config", apriv->proc_entry); -fail_config: - remove_proc_entry("Status", apriv->proc_entry); -fail_status: - remove_proc_entry("Stats", apriv->proc_entry); -fail_stats: - remove_proc_entry("StatsDelta", apriv->proc_entry); -fail_stats_delta: - remove_proc_entry(apriv->proc_name, airo_entry); fail: + remove_proc_subtree(apriv->proc_name, airo_entry); return -ENOMEM; } static int takedown_proc_entry( struct net_device *dev, - struct airo_info *apriv ) { - if ( !apriv->proc_entry->namelen ) return 0; - remove_proc_entry("Stats",apriv->proc_entry); - remove_proc_entry("StatsDelta",apriv->proc_entry); - remove_proc_entry("Status",apriv->proc_entry); - remove_proc_entry("Config",apriv->proc_entry); - remove_proc_entry("SSID",apriv->proc_entry); - remove_proc_entry("APList",apriv->proc_entry); - remove_proc_entry("BSSList",apriv->proc_entry); - remove_proc_entry("WepKey",apriv->proc_entry); - remove_proc_entry(apriv->proc_name,airo_entry); + struct airo_info *apriv ) +{ + remove_proc_subtree(apriv->proc_name, airo_entry); return 0; } @@ -4675,22 +4596,13 @@ static ssize_t proc_read( struct file *file, size_t len, loff_t *offset ) { - loff_t pos = *offset; - struct proc_data *priv = (struct proc_data*)file->private_data; + struct proc_data *priv = file->private_data; if (!priv->rbuffer) return -EINVAL; - if (pos < 0) - return -EINVAL; - if (pos >= priv->readlen) - return 0; - if (len > priv->readlen - pos) - len = priv->readlen - pos; - if (copy_to_user(buffer, priv->rbuffer + pos, len)) - return -EFAULT; - *offset = pos + len; - return len; + return simple_read_from_buffer(buffer, len, offset, priv->rbuffer, + priv->readlen); } /* @@ -4702,38 +4614,33 @@ static ssize_t proc_write( struct file *file, size_t len, loff_t *offset ) { - loff_t pos = *offset; - struct proc_data *priv = (struct proc_data*)file->private_data; + ssize_t ret; + struct proc_data *priv = file->private_data; if (!priv->wbuffer) return -EINVAL; - if (pos < 0) - return -EINVAL; - if (pos >= priv->maxwritelen) - return 0; - if (len > priv->maxwritelen - pos) - len = priv->maxwritelen - pos; - if (copy_from_user(priv->wbuffer + pos, buffer, len)) - return -EFAULT; - if ( pos + len > priv->writelen ) - priv->writelen = len + file->f_pos; - *offset = pos + len; - return len; + ret = simple_write_to_buffer(priv->wbuffer, priv->maxwritelen, offset, + buffer, len); + if (ret > 0) + priv->writelen = max_t(int, priv->writelen, *offset); + + return ret; } -static int proc_status_open( struct inode *inode, struct file *file ) { +static int proc_status_open(struct inode *inode, struct file *file) +{ struct proc_data *data; - struct proc_dir_entry *dp = PDE(inode); - struct net_device *dev = dp->data; - struct airo_info *apriv = dev->priv; + struct net_device *dev = PDE_DATA(inode); + struct airo_info *apriv = dev->ml_priv; CapabilityRid cap_rid; StatusRid status_rid; + u16 mode; int i; if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; - data = (struct proc_data *)file->private_data; + data = file->private_data; if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) { kfree (file->private_data); return -ENOMEM; @@ -4742,16 +4649,18 @@ static int proc_status_open( struct inode *inode, struct file *file ) { readStatusRid(apriv, &status_rid, 1); readCapabilityRid(apriv, &cap_rid, 1); + mode = le16_to_cpu(status_rid.mode); + i = sprintf(data->rbuffer, "Status: %s%s%s%s%s%s%s%s%s\n", - status_rid.mode & 1 ? "CFG ": "", - status_rid.mode & 2 ? "ACT ": "", - status_rid.mode & 0x10 ? "SYN ": "", - status_rid.mode & 0x20 ? "LNK ": "", - status_rid.mode & 0x40 ? "LEAP ": "", - status_rid.mode & 0x80 ? "PRIV ": "", - status_rid.mode & 0x100 ? "KEY ": "", - status_rid.mode & 0x200 ? "WEP ": "", - status_rid.mode & 0x8000 ? "ERR ": ""); + mode & 1 ? "CFG ": "", + mode & 2 ? "ACT ": "", + mode & 0x10 ? "SYN ": "", + mode & 0x20 ? "LNK ": "", + mode & 0x40 ? "LEAP ": "", + mode & 0x80 ? "PRIV ": "", + mode & 0x100 ? "KEY ": "", + mode & 0x200 ? "WEP ": "", + mode & 0x8000 ? "ERR ": ""); sprintf( data->rbuffer+i, "Mode: %x\n" "Signal Strength: %d\n" "Signal Quality: %d\n" @@ -4764,24 +4673,24 @@ static int proc_status_open( struct inode *inode, struct file *file ) { "Radio type: %x\nCountry: %x\nHardware Version: %x\n" "Software Version: %x\nSoftware Subversion: %x\n" "Boot block version: %x\n", - (int)status_rid.mode, - (int)status_rid.normalizedSignalStrength, - (int)status_rid.signalQuality, - (int)status_rid.SSIDlen, + le16_to_cpu(status_rid.mode), + le16_to_cpu(status_rid.normalizedSignalStrength), + le16_to_cpu(status_rid.signalQuality), + le16_to_cpu(status_rid.SSIDlen), status_rid.SSID, status_rid.apName, - (int)status_rid.channel, - (int)status_rid.currentXmitRate/2, + le16_to_cpu(status_rid.channel), + le16_to_cpu(status_rid.currentXmitRate) / 2, version, cap_rid.prodName, cap_rid.manName, cap_rid.prodVer, - cap_rid.radioType, - cap_rid.country, - cap_rid.hardVer, - (int)cap_rid.softVer, - (int)cap_rid.softSubVer, - (int)cap_rid.bootBlockVer ); + le16_to_cpu(cap_rid.radioType), + le16_to_cpu(cap_rid.country), + le16_to_cpu(cap_rid.hardVer), + le16_to_cpu(cap_rid.softVer), + le16_to_cpu(cap_rid.softSubVer), + le16_to_cpu(cap_rid.bootBlockVer)); data->readlen = strlen( data->rbuffer ); return 0; } @@ -4801,37 +4710,39 @@ static int proc_stats_open( struct inode *inode, struct file *file ) { static int proc_stats_rid_open( struct inode *inode, struct file *file, - u16 rid ) { + u16 rid ) +{ struct proc_data *data; - struct proc_dir_entry *dp = PDE(inode); - struct net_device *dev = dp->data; - struct airo_info *apriv = dev->priv; + struct net_device *dev = PDE_DATA(inode); + struct airo_info *apriv = dev->ml_priv; StatsRid stats; int i, j; - u32 *vals = stats.vals; + __le32 *vals = stats.vals; + int len; if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; - data = (struct proc_data *)file->private_data; + data = file->private_data; if ((data->rbuffer = kmalloc( 4096, GFP_KERNEL )) == NULL) { kfree (file->private_data); return -ENOMEM; } readStatsRid(apriv, &stats, rid, 1); + len = le16_to_cpu(stats.len); j = 0; - for(i=0; statsLabels[i]!=(char *)-1 && - i*4<stats.len; i++){ + for(i=0; statsLabels[i]!=(char *)-1 && i*4<len; i++) { if (!statsLabels[i]) continue; if (j+strlen(statsLabels[i])+16>4096) { airo_print_warn(apriv->dev->name, - "Potentially disasterous buffer overflow averted!"); + "Potentially disastrous buffer overflow averted!"); break; } - j+=sprintf(data->rbuffer+j, "%s: %u\n", statsLabels[i], vals[i]); + j+=sprintf(data->rbuffer+j, "%s: %u\n", statsLabels[i], + le32_to_cpu(vals[i])); } - if (i*4>=stats.len){ + if (i*4 >= len) { airo_print_warn(apriv->dev->name, "Got a short rid"); } data->readlen = j; @@ -4841,9 +4752,8 @@ static int proc_stats_rid_open( struct inode *inode, static int get_dec_u16( char *buffer, int *start, int limit ) { u16 value; int valid = 0; - for( value = 0; buffer[*start] >= '0' && - buffer[*start] <= '9' && - *start < limit; (*start)++ ) { + for (value = 0; *start < limit && buffer[*start] >= '0' && + buffer[*start] <= '9'; (*start)++) { valid = 1; value *= 10; value += buffer[*start] - '0'; @@ -4856,11 +4766,17 @@ static int airo_config_commit(struct net_device *dev, struct iw_request_info *info, void *zwrq, char *extra); -static void proc_config_on_close( struct inode *inode, struct file *file ) { +static inline int sniffing_mode(struct airo_info *ai) +{ + return (le16_to_cpu(ai->config.rmode) & le16_to_cpu(RXMODE_MASK)) >= + le16_to_cpu(RXMODE_RFMON); +} + +static void proc_config_on_close(struct inode *inode, struct file *file) +{ struct proc_data *data = file->private_data; - struct proc_dir_entry *dp = PDE(inode); - struct net_device *dev = dp->data; - struct airo_info *ai = dev->priv; + struct net_device *dev = PDE_DATA(inode); + struct airo_info *ai = dev->ml_priv; char *line; if ( !data->writelen ) return; @@ -4873,16 +4789,16 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { /*** Mode processing */ if ( !strncmp( line, "Mode: ", 6 ) ) { line += 6; - if ((ai->config.rmode & 0xff) >= RXMODE_RFMON) - set_bit (FLAG_RESET, &ai->flags); - ai->config.rmode &= 0xfe00; + if (sniffing_mode(ai)) + set_bit (FLAG_RESET, &ai->flags); + ai->config.rmode &= ~RXMODE_FULL_MASK; clear_bit (FLAG_802_11, &ai->flags); - ai->config.opmode &= 0xFF00; + ai->config.opmode &= ~MODE_CFG_MASK; ai->config.scanMode = SCANMODE_ACTIVE; if ( line[0] == 'a' ) { - ai->config.opmode |= 0; + ai->config.opmode |= MODE_STA_IBSS; } else { - ai->config.opmode |= 1; + ai->config.opmode |= MODE_STA_ESS; if ( line[0] == 'r' ) { ai->config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER; ai->config.scanMode = SCANMODE_PASSIVE; @@ -4948,7 +4864,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { line += 9; v = get_dec_u16(line, &i, i+3); if ( v != -1 ) { - ai->config.channelSet = (u16)v; + ai->config.channelSet = cpu_to_le16(v); set_bit (FLAG_COMMIT, &ai->flags); } } else if ( !strncmp( line, "XmitPower: ", 11 ) ) { @@ -4956,20 +4872,20 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { line += 11; v = get_dec_u16(line, &i, i+3); if ( v != -1 ) { - ai->config.txPower = (u16)v; + ai->config.txPower = cpu_to_le16(v); set_bit (FLAG_COMMIT, &ai->flags); } } else if ( !strncmp( line, "WEP: ", 5 ) ) { line += 5; switch( line[0] ) { case 's': - ai->config.authType = (u16)AUTH_SHAREDKEY; + ai->config.authType = AUTH_SHAREDKEY; break; case 'e': - ai->config.authType = (u16)AUTH_ENCRYPT; + ai->config.authType = AUTH_ENCRYPT; break; default: - ai->config.authType = (u16)AUTH_OPEN; + ai->config.authType = AUTH_OPEN; break; } set_bit (FLAG_COMMIT, &ai->flags); @@ -4979,7 +4895,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { line += 16; v = get_dec_u16(line, &i, 3); v = (v<0) ? 0 : ((v>255) ? 255 : v); - ai->config.longRetryLimit = (u16)v; + ai->config.longRetryLimit = cpu_to_le16(v); set_bit (FLAG_COMMIT, &ai->flags); } else if ( !strncmp( line, "ShortRetryLimit: ", 17 ) ) { int v, i = 0; @@ -4987,7 +4903,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { line += 17; v = get_dec_u16(line, &i, 3); v = (v<0) ? 0 : ((v>255) ? 255 : v); - ai->config.shortRetryLimit = (u16)v; + ai->config.shortRetryLimit = cpu_to_le16(v); set_bit (FLAG_COMMIT, &ai->flags); } else if ( !strncmp( line, "RTSThreshold: ", 14 ) ) { int v, i = 0; @@ -4995,7 +4911,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { line += 14; v = get_dec_u16(line, &i, 4); v = (v<0) ? 0 : ((v>AIRO_DEF_MTU) ? AIRO_DEF_MTU : v); - ai->config.rtsThres = (u16)v; + ai->config.rtsThres = cpu_to_le16(v); set_bit (FLAG_COMMIT, &ai->flags); } else if ( !strncmp( line, "TXMSDULifetime: ", 16 ) ) { int v, i = 0; @@ -5003,7 +4919,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { line += 16; v = get_dec_u16(line, &i, 5); v = (v<0) ? 0 : v; - ai->config.txLifetime = (u16)v; + ai->config.txLifetime = cpu_to_le16(v); set_bit (FLAG_COMMIT, &ai->flags); } else if ( !strncmp( line, "RXMSDULifetime: ", 16 ) ) { int v, i = 0; @@ -5011,7 +4927,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { line += 16; v = get_dec_u16(line, &i, 5); v = (v<0) ? 0 : v; - ai->config.rxLifetime = (u16)v; + ai->config.rxLifetime = cpu_to_le16(v); set_bit (FLAG_COMMIT, &ai->flags); } else if ( !strncmp( line, "TXDiversity: ", 13 ) ) { ai->config.txDiversity = @@ -5030,7 +4946,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { v = get_dec_u16(line, &i, 4); v = (v<256) ? 256 : ((v>AIRO_DEF_MTU) ? AIRO_DEF_MTU : v); v = v & 0xfffe; /* Make sure its even */ - ai->config.fragThresh = (u16)v; + ai->config.fragThresh = cpu_to_le16(v); set_bit (FLAG_COMMIT, &ai->flags); } else if (!strncmp(line, "Modulation: ", 12)) { line += 12; @@ -5057,8 +4973,9 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { airo_config_commit(dev, NULL, NULL, NULL); } -static char *get_rmode(u16 mode) { - switch(mode&0xff) { +static const char *get_rmode(__le16 mode) +{ + switch(mode & RXMODE_MASK) { case RXMODE_RFMON: return "rfmon"; case RXMODE_RFMON_ANYBSS: return "yna (any) bss rfmon"; case RXMODE_LANMON: return "lanmon"; @@ -5066,16 +4983,17 @@ static char *get_rmode(u16 mode) { return "ESS"; } -static int proc_config_open( struct inode *inode, struct file *file ) { +static int proc_config_open(struct inode *inode, struct file *file) +{ struct proc_data *data; - struct proc_dir_entry *dp = PDE(inode); - struct net_device *dev = dp->data; - struct airo_info *ai = dev->priv; + struct net_device *dev = PDE_DATA(inode); + struct airo_info *ai = dev->ml_priv; int i; + __le16 mode; if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; - data = (struct proc_data *)file->private_data; + data = file->private_data; if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) { kfree (file->private_data); return -ENOMEM; @@ -5090,6 +5008,7 @@ static int proc_config_open( struct inode *inode, struct file *file ) { readConfigRid(ai, 1); + mode = ai->config.opmode & MODE_CFG_MASK; i = sprintf( data->rbuffer, "Mode: %s\n" "Radio: %s\n" @@ -5098,15 +5017,16 @@ static int proc_config_open( struct inode *inode, struct file *file ) { "DataRates: %d %d %d %d %d %d %d %d\n" "Channel: %d\n" "XmitPower: %d\n", - (ai->config.opmode & 0xFF) == 0 ? "adhoc" : - (ai->config.opmode & 0xFF) == 1 ? get_rmode(ai->config.rmode): - (ai->config.opmode & 0xFF) == 2 ? "AP" : - (ai->config.opmode & 0xFF) == 3 ? "AP RPTR" : "Error", + mode == MODE_STA_IBSS ? "adhoc" : + mode == MODE_STA_ESS ? get_rmode(ai->config.rmode): + mode == MODE_AP ? "AP" : + mode == MODE_AP_RPTR ? "AP RPTR" : "Error", test_bit(FLAG_RADIO_OFF, &ai->flags) ? "off" : "on", ai->config.nodeName, - ai->config.powerSaveMode == 0 ? "CAM" : - ai->config.powerSaveMode == 1 ? "PSP" : - ai->config.powerSaveMode == 2 ? "PSPCAM" : "Error", + ai->config.powerSaveMode == POWERSAVE_CAM ? "CAM" : + ai->config.powerSaveMode == POWERSAVE_PSP ? "PSP" : + ai->config.powerSaveMode == POWERSAVE_PSPCAM ? "PSPCAM" : + "Error", (int)ai->config.rates[0], (int)ai->config.rates[1], (int)ai->config.rates[2], @@ -5115,8 +5035,8 @@ static int proc_config_open( struct inode *inode, struct file *file ) { (int)ai->config.rates[5], (int)ai->config.rates[6], (int)ai->config.rates[7], - (int)ai->config.channelSet, - (int)ai->config.txPower + le16_to_cpu(ai->config.channelSet), + le16_to_cpu(ai->config.txPower) ); sprintf( data->rbuffer + i, "LongRetryLimit: %d\n" @@ -5130,19 +5050,19 @@ static int proc_config_open( struct inode *inode, struct file *file ) { "WEP: %s\n" "Modulation: %s\n" "Preamble: %s\n", - (int)ai->config.longRetryLimit, - (int)ai->config.shortRetryLimit, - (int)ai->config.rtsThres, - (int)ai->config.txLifetime, - (int)ai->config.rxLifetime, + le16_to_cpu(ai->config.longRetryLimit), + le16_to_cpu(ai->config.shortRetryLimit), + le16_to_cpu(ai->config.rtsThres), + le16_to_cpu(ai->config.txLifetime), + le16_to_cpu(ai->config.rxLifetime), ai->config.txDiversity == 1 ? "left" : ai->config.txDiversity == 2 ? "right" : "both", ai->config.rxDiversity == 1 ? "left" : ai->config.rxDiversity == 2 ? "right" : "both", - (int)ai->config.fragThresh, + le16_to_cpu(ai->config.fragThresh), ai->config.authType == AUTH_ENCRYPT ? "encrypt" : ai->config.authType == AUTH_SHAREDKEY ? "shared" : "open", - ai->config.modulation == 0 ? "default" : + ai->config.modulation == MOD_DEFAULT ? "default" : ai->config.modulation == MOD_CCK ? "cck" : ai->config.modulation == MOD_MOK ? "mok" : "error", ai->config.preamble == PREAMBLE_AUTO ? "auto" : @@ -5153,58 +5073,53 @@ static int proc_config_open( struct inode *inode, struct file *file ) { return 0; } -static void proc_SSID_on_close( struct inode *inode, struct file *file ) { - struct proc_data *data = (struct proc_data *)file->private_data; - struct proc_dir_entry *dp = PDE(inode); - struct net_device *dev = dp->data; - struct airo_info *ai = dev->priv; +static void proc_SSID_on_close(struct inode *inode, struct file *file) +{ + struct proc_data *data = file->private_data; + struct net_device *dev = PDE_DATA(inode); + struct airo_info *ai = dev->ml_priv; SsidRid SSID_rid; int i; - int offset = 0; + char *p = data->wbuffer; + char *end = p + data->writelen; - if ( !data->writelen ) return; + if (!data->writelen) + return; - memset( &SSID_rid, 0, sizeof( SSID_rid ) ); + *end = '\n'; /* sentinel; we have space for it */ - for( i = 0; i < 3; i++ ) { - int j; - for( j = 0; j+offset < data->writelen && j < 32 && - data->wbuffer[offset+j] != '\n'; j++ ) { - SSID_rid.ssids[i].ssid[j] = data->wbuffer[offset+j]; - } - if ( j == 0 ) break; - SSID_rid.ssids[i].len = j; - offset += j; - while( data->wbuffer[offset] != '\n' && - offset < data->writelen ) offset++; - offset++; + memset(&SSID_rid, 0, sizeof(SSID_rid)); + + for (i = 0; i < 3 && p < end; i++) { + int j = 0; + /* copy up to 32 characters from this line */ + while (*p != '\n' && j < 32) + SSID_rid.ssids[i].ssid[j++] = *p++; + if (j == 0) + break; + SSID_rid.ssids[i].len = cpu_to_le16(j); + /* skip to the beginning of the next line */ + while (*p++ != '\n') + ; } if (i) - SSID_rid.len = sizeof(SSID_rid); + SSID_rid.len = cpu_to_le16(sizeof(SSID_rid)); disable_MAC(ai, 1); writeSsidRid(ai, &SSID_rid, 1); enable_MAC(ai, 1); } -static inline u8 hexVal(char c) { - if (c>='0' && c<='9') return c -= '0'; - if (c>='a' && c<='f') return c -= 'a'-10; - if (c>='A' && c<='F') return c -= 'A'-10; - return 0; -} - static void proc_APList_on_close( struct inode *inode, struct file *file ) { - struct proc_data *data = (struct proc_data *)file->private_data; - struct proc_dir_entry *dp = PDE(inode); - struct net_device *dev = dp->data; - struct airo_info *ai = dev->priv; + struct proc_data *data = file->private_data; + struct net_device *dev = PDE_DATA(inode); + struct airo_info *ai = dev->ml_priv; APListRid APList_rid; int i; if ( !data->writelen ) return; memset( &APList_rid, 0, sizeof(APList_rid) ); - APList_rid.len = sizeof(APList_rid); + APList_rid.len = cpu_to_le16(sizeof(APList_rid)); for( i = 0; i < 4 && data->writelen >= (i+1)*6*3; i++ ) { int j; @@ -5212,11 +5127,11 @@ static void proc_APList_on_close( struct inode *inode, struct file *file ) { switch(j%3) { case 0: APList_rid.ap[i][j/3]= - hexVal(data->wbuffer[j+i*6*3])<<4; + hex_to_bin(data->wbuffer[j+i*6*3])<<4; break; case 1: APList_rid.ap[i][j/3]|= - hexVal(data->wbuffer[j+i*6*3]); + hex_to_bin(data->wbuffer[j+i*6*3]); break; } } @@ -5237,76 +5152,121 @@ static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data, return rc; } -/* Returns the length of the key at the index. If index == 0xffff - * the index of the transmit key is returned. If the key doesn't exist, - * -1 will be returned. +/* Returns the WEP key at the specified index, or -1 if that key does + * not exist. The buffer is assumed to be at least 16 bytes in length. */ -static int get_wep_key(struct airo_info *ai, u16 index) { +static int get_wep_key(struct airo_info *ai, u16 index, char *buf, u16 buflen) +{ WepKeyRid wkr; int rc; - u16 lastindex; + __le16 lastindex; rc = readWepKeyRid(ai, &wkr, 1, 1); - if (rc == SUCCESS) do { + if (rc != SUCCESS) + return -1; + do { lastindex = wkr.kindex; - if (wkr.kindex == index) { - if (index == 0xffff) { - return wkr.mac[0]; - } - return wkr.klen; + if (le16_to_cpu(wkr.kindex) == index) { + int klen = min_t(int, buflen, le16_to_cpu(wkr.klen)); + memcpy(buf, wkr.key, klen); + return klen; } - readWepKeyRid(ai, &wkr, 0, 1); - } while(lastindex != wkr.kindex); + rc = readWepKeyRid(ai, &wkr, 0, 1); + if (rc != SUCCESS) + return -1; + } while (lastindex != wkr.kindex); return -1; } -static int set_wep_key(struct airo_info *ai, u16 index, - const char *key, u16 keylen, int perm, int lock ) { +static int get_wep_tx_idx(struct airo_info *ai) +{ + WepKeyRid wkr; + int rc; + __le16 lastindex; + + rc = readWepKeyRid(ai, &wkr, 1, 1); + if (rc != SUCCESS) + return -1; + do { + lastindex = wkr.kindex; + if (wkr.kindex == cpu_to_le16(0xffff)) + return wkr.mac[0]; + rc = readWepKeyRid(ai, &wkr, 0, 1); + if (rc != SUCCESS) + return -1; + } while (lastindex != wkr.kindex); + return -1; +} + +static int set_wep_key(struct airo_info *ai, u16 index, const char *key, + u16 keylen, int perm, int lock) +{ static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 }; WepKeyRid wkr; + int rc; + + if (WARN_ON(keylen == 0)) + return -1; memset(&wkr, 0, sizeof(wkr)); - if (keylen == 0) { -// We are selecting which key to use - wkr.len = sizeof(wkr); - wkr.kindex = 0xffff; - wkr.mac[0] = (char)index; - if (perm) ai->defindex = (char)index; - } else { -// We are actually setting the key - wkr.len = sizeof(wkr); - wkr.kindex = index; - wkr.klen = keylen; - memcpy( wkr.key, key, keylen ); - memcpy( wkr.mac, macaddr, ETH_ALEN ); - } + wkr.len = cpu_to_le16(sizeof(wkr)); + wkr.kindex = cpu_to_le16(index); + wkr.klen = cpu_to_le16(keylen); + memcpy(wkr.key, key, keylen); + memcpy(wkr.mac, macaddr, ETH_ALEN); if (perm) disable_MAC(ai, lock); - writeWepKeyRid(ai, &wkr, perm, lock); + rc = writeWepKeyRid(ai, &wkr, perm, lock); if (perm) enable_MAC(ai, lock); - return 0; + return rc; +} + +static int set_wep_tx_idx(struct airo_info *ai, u16 index, int perm, int lock) +{ + WepKeyRid wkr; + int rc; + + memset(&wkr, 0, sizeof(wkr)); + wkr.len = cpu_to_le16(sizeof(wkr)); + wkr.kindex = cpu_to_le16(0xffff); + wkr.mac[0] = (char)index; + + if (perm) { + ai->defindex = (char)index; + disable_MAC(ai, lock); + } + + rc = writeWepKeyRid(ai, &wkr, perm, lock); + + if (perm) + enable_MAC(ai, lock); + return rc; } static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { struct proc_data *data; - struct proc_dir_entry *dp = PDE(inode); - struct net_device *dev = dp->data; - struct airo_info *ai = dev->priv; - int i; + struct net_device *dev = PDE_DATA(inode); + struct airo_info *ai = dev->ml_priv; + int i, rc; char key[16]; u16 index = 0; int j = 0; memset(key, 0, sizeof(key)); - data = (struct proc_data *)file->private_data; + data = file->private_data; if ( !data->writelen ) return; if (data->wbuffer[0] >= '0' && data->wbuffer[0] <= '3' && (data->wbuffer[1] == ' ' || data->wbuffer[1] == '\n')) { index = data->wbuffer[0] - '0'; if (data->wbuffer[1] == '\n') { - set_wep_key(ai, index, NULL, 0, 1, 1); + rc = set_wep_tx_idx(ai, index, 1, 1); + if (rc < 0) { + airo_print_err(ai->dev->name, "failed to set " + "WEP transmit index to %d: %d.", + index, rc); + } return; } j = 2; @@ -5318,31 +5278,36 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { for( i = 0; i < 16*3 && data->wbuffer[i+j]; i++ ) { switch(i%3) { case 0: - key[i/3] = hexVal(data->wbuffer[i+j])<<4; + key[i/3] = hex_to_bin(data->wbuffer[i+j])<<4; break; case 1: - key[i/3] |= hexVal(data->wbuffer[i+j]); + key[i/3] |= hex_to_bin(data->wbuffer[i+j]); break; } } - set_wep_key(ai, index, key, i/3, 1, 1); + + rc = set_wep_key(ai, index, key, i/3, 1, 1); + if (rc < 0) { + airo_print_err(ai->dev->name, "failed to set WEP key at index " + "%d: %d.", index, rc); + } } -static int proc_wepkey_open( struct inode *inode, struct file *file ) { +static int proc_wepkey_open( struct inode *inode, struct file *file ) +{ struct proc_data *data; - struct proc_dir_entry *dp = PDE(inode); - struct net_device *dev = dp->data; - struct airo_info *ai = dev->priv; + struct net_device *dev = PDE_DATA(inode); + struct airo_info *ai = dev->ml_priv; char *ptr; WepKeyRid wkr; - u16 lastindex; + __le16 lastindex; int j=0; int rc; if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; memset(&wkr, 0, sizeof(wkr)); - data = (struct proc_data *)file->private_data; + data = file->private_data; if ((data->rbuffer = kzalloc( 180, GFP_KERNEL )) == NULL) { kfree (file->private_data); return -ENOMEM; @@ -5361,12 +5326,13 @@ static int proc_wepkey_open( struct inode *inode, struct file *file ) { rc = readWepKeyRid(ai, &wkr, 1, 1); if (rc == SUCCESS) do { lastindex = wkr.kindex; - if (wkr.kindex == 0xffff) { + if (wkr.kindex == cpu_to_le16(0xffff)) { j += sprintf(ptr+j, "Tx key = %d\n", (int)wkr.mac[0]); } else { j += sprintf(ptr+j, "Key %d set with length = %d\n", - (int)wkr.kindex, (int)wkr.klen); + le16_to_cpu(wkr.kindex), + le16_to_cpu(wkr.klen)); } readWepKeyRid(ai, &wkr, 0, 1); } while((lastindex != wkr.kindex) && (j < 180-30)); @@ -5375,25 +5341,26 @@ static int proc_wepkey_open( struct inode *inode, struct file *file ) { return 0; } -static int proc_SSID_open( struct inode *inode, struct file *file ) { +static int proc_SSID_open(struct inode *inode, struct file *file) +{ struct proc_data *data; - struct proc_dir_entry *dp = PDE(inode); - struct net_device *dev = dp->data; - struct airo_info *ai = dev->priv; + struct net_device *dev = PDE_DATA(inode); + struct airo_info *ai = dev->ml_priv; int i; char *ptr; SsidRid SSID_rid; if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; - data = (struct proc_data *)file->private_data; + data = file->private_data; if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) { kfree (file->private_data); return -ENOMEM; } data->writelen = 0; data->maxwritelen = 33*3; - if ((data->wbuffer = kzalloc( 33*3, GFP_KERNEL )) == NULL) { + /* allocate maxwritelen + 1; we'll want a sentinel */ + if ((data->wbuffer = kzalloc(33*3 + 1, GFP_KERNEL)) == NULL) { kfree (data->rbuffer); kfree (file->private_data); return -ENOMEM; @@ -5402,14 +5369,15 @@ static int proc_SSID_open( struct inode *inode, struct file *file ) { readSsidRid(ai, &SSID_rid); ptr = data->rbuffer; - for( i = 0; i < 3; i++ ) { + for (i = 0; i < 3; i++) { int j; - if ( !SSID_rid.ssids[i].len ) break; - for( j = 0; j < 32 && - j < SSID_rid.ssids[i].len && - SSID_rid.ssids[i].ssid[j]; j++ ) { + size_t len = le16_to_cpu(SSID_rid.ssids[i].len); + if (!len) + break; + if (len > 32) + len = 32; + for (j = 0; j < len && SSID_rid.ssids[i].ssid[j]; j++) *ptr++ = SSID_rid.ssids[i].ssid[j]; - } *ptr++ = '\n'; } *ptr = '\0'; @@ -5419,17 +5387,15 @@ static int proc_SSID_open( struct inode *inode, struct file *file ) { static int proc_APList_open( struct inode *inode, struct file *file ) { struct proc_data *data; - struct proc_dir_entry *dp = PDE(inode); - struct net_device *dev = dp->data; - struct airo_info *ai = dev->priv; + struct net_device *dev = PDE_DATA(inode); + struct airo_info *ai = dev->ml_priv; int i; char *ptr; APListRid APList_rid; - DECLARE_MAC_BUF(mac); if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; - data = (struct proc_data *)file->private_data; + data = file->private_data; if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) { kfree (file->private_data); return -ENOMEM; @@ -5449,8 +5415,7 @@ static int proc_APList_open( struct inode *inode, struct file *file ) { // We end when we find a zero MAC if ( !*(int*)APList_rid.ap[i] && !*(int*)&APList_rid.ap[i][2]) break; - ptr += sprintf(ptr, "%s\n", - print_mac(mac, APList_rid.ap[i])); + ptr += sprintf(ptr, "%pM\n", APList_rid.ap[i]); } if (i==0) ptr += sprintf(ptr, "Not using specific APs\n"); @@ -5461,19 +5426,17 @@ static int proc_APList_open( struct inode *inode, struct file *file ) { static int proc_BSSList_open( struct inode *inode, struct file *file ) { struct proc_data *data; - struct proc_dir_entry *dp = PDE(inode); - struct net_device *dev = dp->data; - struct airo_info *ai = dev->priv; + struct net_device *dev = PDE_DATA(inode); + struct airo_info *ai = dev->ml_priv; char *ptr; BSSListRid BSSList_rid; int rc; /* If doLoseSync is not 1, we won't do a Lose Sync */ int doLoseSync = -1; - DECLARE_MAC_BUF(mac); if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; - data = (struct proc_data *)file->private_data; + data = file->private_data; if ((data->rbuffer = kmalloc( 1024, GFP_KERNEL )) == NULL) { kfree (file->private_data); return -ENOMEM; @@ -5505,14 +5468,14 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) { Since it is a rare condition, we'll just live with it, otherwise we have to add a spin lock... */ rc = readBSSListRid(ai, doLoseSync, &BSSList_rid); - while(rc == 0 && BSSList_rid.index != 0xffff) { - ptr += sprintf(ptr, "%s %*s rssi = %d", - print_mac(mac, BSSList_rid.bssid), + while(rc == 0 && BSSList_rid.index != cpu_to_le16(0xffff)) { + ptr += sprintf(ptr, "%pM %*s rssi = %d", + BSSList_rid.bssid, (int)BSSList_rid.ssidLen, BSSList_rid.ssid, - (int)BSSList_rid.dBm); + le16_to_cpu(BSSList_rid.dBm)); ptr += sprintf(ptr, " channel = %d %s %s %s %s\n", - (int)BSSList_rid.dsChannel, + le16_to_cpu(BSSList_rid.dsChannel), BSSList_rid.cap & CAP_ESS ? "ESS" : "", BSSList_rid.cap & CAP_IBSS ? "adhoc" : "", BSSList_rid.cap & CAP_PRIVACY ? "wep" : "", @@ -5542,7 +5505,7 @@ static int proc_close( struct inode *inode, struct file *file ) associated we will check every minute to see if anything has changed. */ static void timer_func( struct net_device *dev ) { - struct airo_info *apriv = dev->priv; + struct airo_info *apriv = dev->ml_priv; /* We don't have a link so try changing the authtype */ readConfigRid(apriv, 0); @@ -5554,13 +5517,13 @@ static void timer_func( struct net_device *dev ) { break; case AUTH_SHAREDKEY: if (apriv->keyindex < auto_wep) { - set_wep_key(apriv, apriv->keyindex, NULL, 0, 0, 0); + set_wep_tx_idx(apriv, apriv->keyindex, 0, 0); apriv->config.authType = AUTH_SHAREDKEY; apriv->keyindex++; } else { /* Drop to ENCRYPT */ apriv->keyindex = 0; - set_wep_key(apriv, apriv->defindex, NULL, 0, 0, 0); + set_wep_tx_idx(apriv, apriv->defindex, 0, 0); apriv->config.authType = AUTH_ENCRYPT; } break; @@ -5578,7 +5541,7 @@ static void timer_func( struct net_device *dev ) { } #ifdef CONFIG_PCI -static int __devinit airo_pci_probe(struct pci_dev *pdev, +static int airo_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pent) { struct net_device *dev; @@ -5600,28 +5563,29 @@ static int __devinit airo_pci_probe(struct pci_dev *pdev, return 0; } -static void __devexit airo_pci_remove(struct pci_dev *pdev) +static void airo_pci_remove(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); airo_print_info(dev->name, "Unregistering..."); stop_airo_card(dev, 1); pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); } static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state) { struct net_device *dev = pci_get_drvdata(pdev); - struct airo_info *ai = dev->priv; + struct airo_info *ai = dev->ml_priv; Cmd cmd; Resp rsp; - if ((ai->APList == NULL) && - (ai->APList = kmalloc(sizeof(APListRid), GFP_KERNEL)) == NULL) + if (!ai->APList) + ai->APList = kmalloc(sizeof(APListRid), GFP_KERNEL); + if (!ai->APList) return -ENOMEM; - if ((ai->SSID == NULL) && - (ai->SSID = kmalloc(sizeof(SsidRid), GFP_KERNEL)) == NULL) + if (!ai->SSID) + ai->SSID = kmalloc(sizeof(SsidRid), GFP_KERNEL); + if (!ai->SSID) return -ENOMEM; readAPListRid(ai, ai->APList); readSsidRid(ai, ai->SSID); @@ -5632,18 +5596,19 @@ static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state) disable_MAC(ai, 0); netif_device_detach(dev); ai->power = state; - cmd.cmd=HOSTSLEEP; + cmd.cmd = HOSTSLEEP; issuecommand(ai, &cmd, &rsp); pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); pci_save_state(pdev); - return pci_set_power_state(pdev, pci_choose_state(pdev, state)); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + return 0; } static int airo_pci_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct airo_info *ai = dev->priv; + struct airo_info *ai = dev->ml_priv; pci_power_t prev_state = pdev->current_state; pci_set_power_state(pdev, PCI_D0); @@ -5662,7 +5627,7 @@ static int airo_pci_resume(struct pci_dev *pdev) msleep(100); } - set_bit (FLAG_COMMIT, &ai->flags); + set_bit(FLAG_COMMIT, &ai->flags); disable_MAC(ai, 0); msleep(200); if (ai->SSID) { @@ -5689,28 +5654,22 @@ static int airo_pci_resume(struct pci_dev *pdev) static int __init airo_init_module( void ) { int i; -#if 0 - int have_isa_dev = 0; -#endif - airo_entry = create_proc_entry("aironet", - S_IFDIR | airo_perm, - proc_root_driver); + proc_kuid = make_kuid(&init_user_ns, proc_uid); + proc_kgid = make_kgid(&init_user_ns, proc_gid); + if (!uid_valid(proc_kuid) || !gid_valid(proc_kgid)) + return -EINVAL; - if (airo_entry) { - airo_entry->uid = proc_uid; - airo_entry->gid = proc_gid; - } + airo_entry = proc_mkdir_mode("driver/aironet", airo_perm, NULL); + + if (airo_entry) + proc_set_user(airo_entry, proc_kuid, proc_kgid); - for( i = 0; i < 4 && io[i] && irq[i]; i++ ) { + for (i = 0; i < 4 && io[i] && irq[i]; i++) { airo_print_info("", "Trying to configure ISA adapter at irq=%d " "io=0x%x", irq[i], io[i] ); if (init_airo_card( irq[i], io[i], 0, NULL )) -#if 0 - have_isa_dev = 1; -#else /* do nothing */ ; -#endif } #ifdef CONFIG_PCI @@ -5719,7 +5678,7 @@ static int __init airo_init_module( void ) airo_print_info("", "Finished probing for PCI adapters"); if (i) { - remove_proc_entry("aironet", proc_root_driver); + remove_proc_entry("driver/aironet", NULL); return i; } #endif @@ -5741,7 +5700,7 @@ static void __exit airo_cleanup_module( void ) #ifdef CONFIG_PCI pci_unregister_driver(&airo_driver); #endif - remove_proc_entry("aironet", proc_root_driver); + remove_proc_entry("driver/aironet", NULL); } /* @@ -5756,7 +5715,7 @@ static void __exit airo_cleanup_module( void ) static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi) { - if( !rssi_rid ) + if (!rssi_rid) return 0; return (0x100 - rssi_rid[rssi].rssidBm); @@ -5766,10 +5725,10 @@ static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm) { int i; - if( !rssi_rid ) + if (!rssi_rid) return 0; - for( i = 0; i < 256; i++ ) + for (i = 0; i < 256; i++) if (rssi_rid[i].rssidBm == dbm) return rssi_rid[i].rssipct; @@ -5780,21 +5739,27 @@ static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm) static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid) { int quality = 0; + u16 sq; - if ((status_rid->mode & 0x3f) == 0x3f && (cap_rid->hardCap & 8)) { - if (memcmp(cap_rid->prodName, "350", 3)) - if (status_rid->signalQuality > 0x20) - quality = 0; - else - quality = 0x20 - status_rid->signalQuality; + if ((status_rid->mode & cpu_to_le16(0x3f)) != cpu_to_le16(0x3f)) + return 0; + + if (!(cap_rid->hardCap & cpu_to_le16(8))) + return 0; + + sq = le16_to_cpu(status_rid->signalQuality); + if (memcmp(cap_rid->prodName, "350", 3)) + if (sq > 0x20) + quality = 0; else - if (status_rid->signalQuality > 0xb0) - quality = 0; - else if (status_rid->signalQuality < 0x10) - quality = 0xa0; - else - quality = 0xb0 - status_rid->signalQuality; - } + quality = 0x20 - sq; + else + if (sq > 0xb0) + quality = 0; + else if (sq < 0x10) + quality = 0xa0; + else + quality = 0xb0 - sq; return quality; } @@ -5823,20 +5788,16 @@ static int airo_set_freq(struct net_device *dev, struct iw_freq *fwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; int rc = -EINPROGRESS; /* Call commit handler */ /* If setting by frequency, convert to a channel */ - if((fwrq->e == 1) && - (fwrq->m >= (int) 2.412e8) && - (fwrq->m <= (int) 2.487e8)) { + if(fwrq->e == 1) { int f = fwrq->m / 100000; - int c = 0; - while((c < 14) && (f != frequency_list[c])) - c++; + /* Hack to fall through... */ fwrq->e = 0; - fwrq->m = c + 1; + fwrq->m = ieee80211_frequency_to_channel(f); } /* Setting by channel number */ if((fwrq->m > 1000) || (fwrq->e > 0)) @@ -5852,7 +5813,7 @@ static int airo_set_freq(struct net_device *dev, } else { readConfigRid(local, 1); /* Yes ! We can set it !!! */ - local->config.channelSet = (u16) channel; + local->config.channelSet = cpu_to_le16(channel); set_bit (FLAG_COMMIT, &local->flags); } } @@ -5868,19 +5829,20 @@ static int airo_get_freq(struct net_device *dev, struct iw_freq *fwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; StatusRid status_rid; /* Card status info */ int ch; readConfigRid(local, 1); - if ((local->config.opmode & 0xFF) == MODE_STA_ESS) + if ((local->config.opmode & MODE_CFG_MASK) == MODE_STA_ESS) status_rid.channel = local->config.channelSet; else readStatusRid(local, &status_rid, 1); - ch = (int)status_rid.channel; + ch = le16_to_cpu(status_rid.channel); if((ch > 0) && (ch < 15)) { - fwrq->m = frequency_list[ch - 1] * 100000; + fwrq->m = 100000 * + ieee80211_channel_to_frequency(ch, IEEE80211_BAND_2GHZ); fwrq->e = 1; } else { fwrq->m = ch; @@ -5899,35 +5861,34 @@ static int airo_set_essid(struct net_device *dev, struct iw_point *dwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; SsidRid SSID_rid; /* SSIDs */ /* Reload the list of current SSID */ readSsidRid(local, &SSID_rid); /* Check if we asked for `any' */ - if(dwrq->flags == 0) { + if (dwrq->flags == 0) { /* Just send an empty SSID list */ memset(&SSID_rid, 0, sizeof(SSID_rid)); } else { - int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; + unsigned index = (dwrq->flags & IW_ENCODE_INDEX) - 1; /* Check the size of the string */ - if(dwrq->length > IW_ESSID_MAX_SIZE) { + if (dwrq->length > IW_ESSID_MAX_SIZE) return -E2BIG ; - } + /* Check if index is valid */ - if((index < 0) || (index >= 4)) { + if (index >= ARRAY_SIZE(SSID_rid.ssids)) return -EINVAL; - } /* Set the SSID */ memset(SSID_rid.ssids[index].ssid, 0, sizeof(SSID_rid.ssids[index].ssid)); memcpy(SSID_rid.ssids[index].ssid, extra, dwrq->length); - SSID_rid.ssids[index].len = dwrq->length; + SSID_rid.ssids[index].len = cpu_to_le16(dwrq->length); } - SSID_rid.len = sizeof(SSID_rid); + SSID_rid.len = cpu_to_le16(sizeof(SSID_rid)); /* Write it to the card */ disable_MAC(local, 1); writeSsidRid(local, &SSID_rid, 1); @@ -5945,7 +5906,7 @@ static int airo_get_essid(struct net_device *dev, struct iw_point *dwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; StatusRid status_rid; /* Card status info */ readStatusRid(local, &status_rid, 1); @@ -5954,11 +5915,11 @@ static int airo_get_essid(struct net_device *dev, * get the relevant SSID from the SSID list... */ /* Get the current SSID */ - memcpy(extra, status_rid.SSID, status_rid.SSIDlen); + memcpy(extra, status_rid.SSID, le16_to_cpu(status_rid.SSIDlen)); /* If none, we may want to get the one that was set */ /* Push it out ! */ - dwrq->length = status_rid.SSIDlen; + dwrq->length = le16_to_cpu(status_rid.SSIDlen); dwrq->flags = 1; /* active */ return 0; @@ -5973,17 +5934,15 @@ static int airo_set_wap(struct net_device *dev, struct sockaddr *awrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; Cmd cmd; Resp rsp; APListRid APList_rid; - static const u8 any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - static const u8 off[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; if (awrq->sa_family != ARPHRD_ETHER) return -EINVAL; - else if (!memcmp(any, awrq->sa_data, ETH_ALEN) || - !memcmp(off, awrq->sa_data, ETH_ALEN)) { + else if (is_broadcast_ether_addr(awrq->sa_data) || + is_zero_ether_addr(awrq->sa_data)) { memset(&cmd, 0, sizeof(cmd)); cmd.cmd=CMD_LOSE_SYNC; if (down_interruptible(&local->sem)) @@ -5992,7 +5951,7 @@ static int airo_set_wap(struct net_device *dev, up(&local->sem); } else { memset(&APList_rid, 0, sizeof(APList_rid)); - APList_rid.len = sizeof(APList_rid); + APList_rid.len = cpu_to_le16(sizeof(APList_rid)); memcpy(APList_rid.ap[0], awrq->sa_data, ETH_ALEN); disable_MAC(local, 1); writeAPListRid(local, &APList_rid, 1); @@ -6010,7 +5969,7 @@ static int airo_get_wap(struct net_device *dev, struct sockaddr *awrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; StatusRid status_rid; /* Card status info */ readStatusRid(local, &status_rid, 1); @@ -6031,7 +5990,7 @@ static int airo_set_nick(struct net_device *dev, struct iw_point *dwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; /* Check the size of the string */ if(dwrq->length > 16) { @@ -6054,7 +6013,7 @@ static int airo_get_nick(struct net_device *dev, struct iw_point *dwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; readConfigRid(local, 1); strncpy(extra, local->config.nodeName, 16); @@ -6073,7 +6032,7 @@ static int airo_set_rate(struct net_device *dev, struct iw_param *vwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; CapabilityRid cap_rid; /* Card capability info */ u8 brate = 0; int i; @@ -6143,12 +6102,12 @@ static int airo_get_rate(struct net_device *dev, struct iw_param *vwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; StatusRid status_rid; /* Card status info */ readStatusRid(local, &status_rid, 1); - vwrq->value = status_rid.currentXmitRate * 500000; + vwrq->value = le16_to_cpu(status_rid.currentXmitRate) * 500000; /* If more than one rate, set auto */ readConfigRid(local, 1); vwrq->fixed = (local->config.rates[1] == 0); @@ -6165,7 +6124,7 @@ static int airo_set_rts(struct net_device *dev, struct iw_param *vwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; int rthr = vwrq->value; if(vwrq->disabled) @@ -6174,7 +6133,7 @@ static int airo_set_rts(struct net_device *dev, return -EINVAL; } readConfigRid(local, 1); - local->config.rtsThres = rthr; + local->config.rtsThres = cpu_to_le16(rthr); set_bit (FLAG_COMMIT, &local->flags); return -EINPROGRESS; /* Call commit handler */ @@ -6189,10 +6148,10 @@ static int airo_get_rts(struct net_device *dev, struct iw_param *vwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; readConfigRid(local, 1); - vwrq->value = local->config.rtsThres; + vwrq->value = le16_to_cpu(local->config.rtsThres); vwrq->disabled = (vwrq->value >= AIRO_DEF_MTU); vwrq->fixed = 1; @@ -6208,7 +6167,7 @@ static int airo_set_frag(struct net_device *dev, struct iw_param *vwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; int fthr = vwrq->value; if(vwrq->disabled) @@ -6218,7 +6177,7 @@ static int airo_set_frag(struct net_device *dev, } fthr &= ~0x1; /* Get an even value - is it really needed ??? */ readConfigRid(local, 1); - local->config.fragThresh = (u16)fthr; + local->config.fragThresh = cpu_to_le16(fthr); set_bit (FLAG_COMMIT, &local->flags); return -EINPROGRESS; /* Call commit handler */ @@ -6233,10 +6192,10 @@ static int airo_get_frag(struct net_device *dev, struct iw_param *vwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; readConfigRid(local, 1); - vwrq->value = local->config.fragThresh; + vwrq->value = le16_to_cpu(local->config.fragThresh); vwrq->disabled = (vwrq->value >= AIRO_DEF_MTU); vwrq->fixed = 1; @@ -6252,46 +6211,46 @@ static int airo_set_mode(struct net_device *dev, __u32 *uwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; int reset = 0; readConfigRid(local, 1); - if ((local->config.rmode & 0xff) >= RXMODE_RFMON) + if (sniffing_mode(local)) reset = 1; switch(*uwrq) { case IW_MODE_ADHOC: - local->config.opmode &= 0xFF00; + local->config.opmode &= ~MODE_CFG_MASK; local->config.opmode |= MODE_STA_IBSS; - local->config.rmode &= 0xfe00; + local->config.rmode &= ~RXMODE_FULL_MASK; local->config.scanMode = SCANMODE_ACTIVE; clear_bit (FLAG_802_11, &local->flags); break; case IW_MODE_INFRA: - local->config.opmode &= 0xFF00; + local->config.opmode &= ~MODE_CFG_MASK; local->config.opmode |= MODE_STA_ESS; - local->config.rmode &= 0xfe00; + local->config.rmode &= ~RXMODE_FULL_MASK; local->config.scanMode = SCANMODE_ACTIVE; clear_bit (FLAG_802_11, &local->flags); break; case IW_MODE_MASTER: - local->config.opmode &= 0xFF00; + local->config.opmode &= ~MODE_CFG_MASK; local->config.opmode |= MODE_AP; - local->config.rmode &= 0xfe00; + local->config.rmode &= ~RXMODE_FULL_MASK; local->config.scanMode = SCANMODE_ACTIVE; clear_bit (FLAG_802_11, &local->flags); break; case IW_MODE_REPEAT: - local->config.opmode &= 0xFF00; + local->config.opmode &= ~MODE_CFG_MASK; local->config.opmode |= MODE_AP_RPTR; - local->config.rmode &= 0xfe00; + local->config.rmode &= ~RXMODE_FULL_MASK; local->config.scanMode = SCANMODE_ACTIVE; clear_bit (FLAG_802_11, &local->flags); break; case IW_MODE_MONITOR: - local->config.opmode &= 0xFF00; + local->config.opmode &= ~MODE_CFG_MASK; local->config.opmode |= MODE_STA_ESS; - local->config.rmode &= 0xfe00; + local->config.rmode &= ~RXMODE_FULL_MASK; local->config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER; local->config.scanMode = SCANMODE_PASSIVE; set_bit (FLAG_802_11, &local->flags); @@ -6315,11 +6274,11 @@ static int airo_get_mode(struct net_device *dev, __u32 *uwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; readConfigRid(local, 1); /* If not managed, assume it's ad-hoc */ - switch (local->config.opmode & 0xFF) { + switch (local->config.opmode & MODE_CFG_MASK) { case MODE_STA_ESS: *uwrq = IW_MODE_INFRA; break; @@ -6336,6 +6295,11 @@ static int airo_get_mode(struct net_device *dev, return 0; } +static inline int valid_index(struct airo_info *ai, int index) +{ + return (index >= 0) && (index <= ai->max_wep_idx); +} + /*------------------------------------------------------------------*/ /* * Wireless Handler : set Encryption Key @@ -6345,17 +6309,14 @@ static int airo_set_encode(struct net_device *dev, struct iw_point *dwrq, char *extra) { - struct airo_info *local = dev->priv; - CapabilityRid cap_rid; /* Card capability info */ - int perm = ( dwrq->flags & IW_ENCODE_TEMP ? 0 : 1 ); - u16 currentAuthType = local->config.authType; + struct airo_info *local = dev->ml_priv; + int perm = (dwrq->flags & IW_ENCODE_TEMP ? 0 : 1); + __le16 currentAuthType = local->config.authType; + int rc = 0; - /* Is WEP supported ? */ - readCapabilityRid(local, &cap_rid, 1); - /* Older firmware doesn't support this... - if(!(cap_rid.softCap & 2)) { + if (!local->wep_capable) return -EOPNOTSUPP; - } */ + readConfigRid(local, 1); /* Basic checking: do we have a key to set ? @@ -6367,23 +6328,26 @@ static int airo_set_encode(struct net_device *dev, if (dwrq->length > 0) { wep_key_t key; int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - int current_index = get_wep_key(local, 0xffff); + int current_index; + /* Check the size of the key */ if (dwrq->length > MAX_KEY_SIZE) { return -EINVAL; } + + current_index = get_wep_tx_idx(local); + if (current_index < 0) + current_index = 0; + /* Check the index (none -> use current) */ - if ((index < 0) || (index >= ((cap_rid.softCap & 0x80) ? 4:1))) + if (!valid_index(local, index)) index = current_index; + /* Set the length */ if (dwrq->length > MIN_KEY_SIZE) key.len = MAX_KEY_SIZE; else - if (dwrq->length > 0) - key.len = MIN_KEY_SIZE; - else - /* Disable the key */ - key.len = 0; + key.len = MIN_KEY_SIZE; /* Check if the key is not marked as invalid */ if(!(dwrq->flags & IW_ENCODE_NOKEY)) { /* Cleanup */ @@ -6391,7 +6355,13 @@ static int airo_set_encode(struct net_device *dev, /* Copy the key in the driver */ memcpy(key.key, extra, dwrq->length); /* Send the key to the card */ - set_wep_key(local, index, key.key, key.len, perm, 1); + rc = set_wep_key(local, index, key.key, key.len, perm, 1); + if (rc < 0) { + airo_print_err(local->dev->name, "failed to set" + " WEP key at index %d: %d.", + index, rc); + return rc; + } } /* WE specify that if a valid key is set, encryption * should be enabled (user may turn it off later) @@ -6403,13 +6373,19 @@ static int airo_set_encode(struct net_device *dev, } else { /* Do we want to just set the transmit key index ? */ int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - if ((index >= 0) && (index < ((cap_rid.softCap & 0x80)?4:1))) { - set_wep_key(local, index, NULL, 0, perm, 1); - } else + if (valid_index(local, index)) { + rc = set_wep_tx_idx(local, index, perm, 1); + if (rc < 0) { + airo_print_err(local->dev->name, "failed to set" + " WEP transmit index to %d: %d.", + index, rc); + return rc; + } + } else { /* Don't complain if only change the mode */ - if(!dwrq->flags & IW_ENCODE_MODE) { + if (!(dwrq->flags & IW_ENCODE_MODE)) return -EINVAL; - } + } } /* Read the flags */ if(dwrq->flags & IW_ENCODE_DISABLED) @@ -6433,16 +6409,16 @@ static int airo_get_encode(struct net_device *dev, struct iw_point *dwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - CapabilityRid cap_rid; /* Card capability info */ + int wep_key_len; + u8 buf[16]; - /* Is it supported ? */ - readCapabilityRid(local, &cap_rid, 1); - if(!(cap_rid.softCap & 2)) { + if (!local->wep_capable) return -EOPNOTSUPP; - } + readConfigRid(local, 1); + /* Check encryption mode */ switch(local->config.authType) { case AUTH_ENCRYPT: @@ -6461,14 +6437,22 @@ static int airo_get_encode(struct net_device *dev, memset(extra, 0, 16); /* Which key do we want ? -1 -> tx index */ - if ((index < 0) || (index >= ((cap_rid.softCap & 0x80) ? 4 : 1))) - index = get_wep_key(local, 0xffff); + if (!valid_index(local, index)) { + index = get_wep_tx_idx(local); + if (index < 0) + index = 0; + } dwrq->flags |= index + 1; + /* Copy the key to the user buffer */ - dwrq->length = get_wep_key(local, index); - if (dwrq->length > 16) { - dwrq->length=0; + wep_key_len = get_wep_key(local, index, &buf[0], sizeof(buf)); + if (wep_key_len < 0) { + dwrq->length = 0; + } else { + dwrq->length = wep_key_len; + memcpy(extra, buf, dwrq->length); } + return 0; } @@ -6481,31 +6465,30 @@ static int airo_set_encodeext(struct net_device *dev, union iwreq_data *wrqu, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; struct iw_point *encoding = &wrqu->encoding; struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - CapabilityRid cap_rid; /* Card capability info */ int perm = ( encoding->flags & IW_ENCODE_TEMP ? 0 : 1 ); - u16 currentAuthType = local->config.authType; - int idx, key_len, alg = ext->alg, set_key = 1; + __le16 currentAuthType = local->config.authType; + int idx, key_len, alg = ext->alg, set_key = 1, rc; wep_key_t key; - /* Is WEP supported ? */ - readCapabilityRid(local, &cap_rid, 1); - /* Older firmware doesn't support this... - if(!(cap_rid.softCap & 2)) { + if (!local->wep_capable) return -EOPNOTSUPP; - } */ + readConfigRid(local, 1); /* Determine and validate the key index */ idx = encoding->flags & IW_ENCODE_INDEX; if (idx) { - if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1)) + if (!valid_index(local, idx - 1)) return -EINVAL; idx--; - } else - idx = get_wep_key(local, 0xffff); + } else { + idx = get_wep_tx_idx(local); + if (idx < 0) + idx = 0; + } if (encoding->flags & IW_ENCODE_DISABLED) alg = IW_ENCODE_ALG_NONE; @@ -6514,7 +6497,13 @@ static int airo_set_encodeext(struct net_device *dev, /* Only set transmit key index here, actual * key is set below if needed. */ - set_wep_key(local, idx, NULL, 0, perm, 1); + rc = set_wep_tx_idx(local, idx, perm, 1); + if (rc < 0) { + airo_print_err(local->dev->name, "failed to set " + "WEP transmit index to %d: %d.", + idx, rc); + return rc; + } set_key = ext->key_len > 0 ? 1 : 0; } @@ -6539,8 +6528,23 @@ static int airo_set_encodeext(struct net_device *dev, default: return -EINVAL; } - /* Send the key to the card */ - set_wep_key(local, idx, key.key, key.len, perm, 1); + if (key.len == 0) { + rc = set_wep_tx_idx(local, idx, perm, 1); + if (rc < 0) { + airo_print_err(local->dev->name, + "failed to set WEP transmit index to %d: %d.", + idx, rc); + return rc; + } + } else { + rc = set_wep_key(local, idx, key.key, key.len, perm, 1); + if (rc < 0) { + airo_print_err(local->dev->name, + "failed to set WEP key at index %d: %d.", + idx, rc); + return rc; + } + } } /* Read the flags */ @@ -6567,17 +6571,15 @@ static int airo_get_encodeext(struct net_device *dev, union iwreq_data *wrqu, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; struct iw_point *encoding = &wrqu->encoding; struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - CapabilityRid cap_rid; /* Card capability info */ - int idx, max_key_len; + int idx, max_key_len, wep_key_len; + u8 buf[16]; - /* Is it supported ? */ - readCapabilityRid(local, &cap_rid, 1); - if(!(cap_rid.softCap & 2)) { + if (!local->wep_capable) return -EOPNOTSUPP; - } + readConfigRid(local, 1); max_key_len = encoding->length - sizeof(*ext); @@ -6586,11 +6588,14 @@ static int airo_get_encodeext(struct net_device *dev, idx = encoding->flags & IW_ENCODE_INDEX; if (idx) { - if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1)) + if (!valid_index(local, idx - 1)) return -EINVAL; idx--; - } else - idx = get_wep_key(local, 0xffff); + } else { + idx = get_wep_tx_idx(local); + if (idx < 0) + idx = 0; + } encoding->flags = idx + 1; memset(ext, 0, sizeof(*ext)); @@ -6613,9 +6618,12 @@ static int airo_get_encodeext(struct net_device *dev, memset(extra, 0, 16); /* Copy the key to the user buffer */ - ext->key_len = get_wep_key(local, idx); - if (ext->key_len > 16) { - ext->key_len=0; + wep_key_len = get_wep_key(local, idx, &buf[0], sizeof(buf)); + if (wep_key_len < 0) { + ext->key_len = 0; + } else { + ext->key_len = wep_key_len; + memcpy(extra, buf, ext->key_len); } return 0; @@ -6630,9 +6638,9 @@ static int airo_set_auth(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; struct iw_param *param = &wrqu->param; - u16 currentAuthType = local->config.authType; + __le16 currentAuthType = local->config.authType; switch (param->flags & IW_AUTH_INDEX) { case IW_AUTH_WPA_VERSION: @@ -6670,11 +6678,11 @@ static int airo_set_auth(struct net_device *dev, local->config.authType = AUTH_ENCRYPT; } else return -EINVAL; - break; /* Commit the changes to flags if needed */ if (local->config.authType != currentAuthType) set_bit (FLAG_COMMIT, &local->flags); + break; } case IW_AUTH_WPA_ENABLED: @@ -6698,9 +6706,9 @@ static int airo_get_auth(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; struct iw_param *param = &wrqu->param; - u16 currentAuthType = local->config.authType; + __le16 currentAuthType = local->config.authType; switch (param->flags & IW_AUTH_INDEX) { case IW_AUTH_DROP_UNENCRYPTED: @@ -6747,10 +6755,11 @@ static int airo_set_txpow(struct net_device *dev, struct iw_param *vwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; CapabilityRid cap_rid; /* Card capability info */ int i; int rc = -EINVAL; + __le16 v = cpu_to_le16(vwrq->value); readCapabilityRid(local, &cap_rid, 1); @@ -6763,10 +6772,10 @@ static int airo_set_txpow(struct net_device *dev, return -EINVAL; } clear_bit (FLAG_RADIO_OFF, &local->flags); - for (i = 0; cap_rid.txPowerLevels[i] && (i < 8); i++) - if ((vwrq->value==cap_rid.txPowerLevels[i])) { + for (i = 0; i < 8 && cap_rid.txPowerLevels[i]; i++) + if (v == cap_rid.txPowerLevels[i]) { readConfigRid(local, 1); - local->config.txPower = vwrq->value; + local->config.txPower = v; set_bit (FLAG_COMMIT, &local->flags); rc = -EINPROGRESS; /* Call commit handler */ break; @@ -6783,10 +6792,10 @@ static int airo_get_txpow(struct net_device *dev, struct iw_param *vwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; readConfigRid(local, 1); - vwrq->value = local->config.txPower; + vwrq->value = le16_to_cpu(local->config.txPower); vwrq->fixed = 1; /* No power control */ vwrq->disabled = test_bit(FLAG_RADIO_OFF, &local->flags); vwrq->flags = IW_TXPOW_MWATT; @@ -6803,7 +6812,7 @@ static int airo_set_retry(struct net_device *dev, struct iw_param *vwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; int rc = -EINVAL; if(vwrq->disabled) { @@ -6811,20 +6820,21 @@ static int airo_set_retry(struct net_device *dev, } readConfigRid(local, 1); if(vwrq->flags & IW_RETRY_LIMIT) { + __le16 v = cpu_to_le16(vwrq->value); if(vwrq->flags & IW_RETRY_LONG) - local->config.longRetryLimit = vwrq->value; + local->config.longRetryLimit = v; else if (vwrq->flags & IW_RETRY_SHORT) - local->config.shortRetryLimit = vwrq->value; + local->config.shortRetryLimit = v; else { /* No modifier : set both */ - local->config.longRetryLimit = vwrq->value; - local->config.shortRetryLimit = vwrq->value; + local->config.longRetryLimit = v; + local->config.shortRetryLimit = v; } set_bit (FLAG_COMMIT, &local->flags); rc = -EINPROGRESS; /* Call commit handler */ } if(vwrq->flags & IW_RETRY_LIFETIME) { - local->config.txLifetime = vwrq->value / 1024; + local->config.txLifetime = cpu_to_le16(vwrq->value / 1024); set_bit (FLAG_COMMIT, &local->flags); rc = -EINPROGRESS; /* Call commit handler */ } @@ -6840,7 +6850,7 @@ static int airo_get_retry(struct net_device *dev, struct iw_param *vwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; vwrq->disabled = 0; /* Can't be disabled */ @@ -6848,14 +6858,14 @@ static int airo_get_retry(struct net_device *dev, /* Note : by default, display the min retry number */ if((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { vwrq->flags = IW_RETRY_LIFETIME; - vwrq->value = (int)local->config.txLifetime * 1024; + vwrq->value = le16_to_cpu(local->config.txLifetime) * 1024; } else if((vwrq->flags & IW_RETRY_LONG)) { vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG; - vwrq->value = (int)local->config.longRetryLimit; + vwrq->value = le16_to_cpu(local->config.longRetryLimit); } else { vwrq->flags = IW_RETRY_LIMIT; - vwrq->value = (int)local->config.shortRetryLimit; - if((int)local->config.shortRetryLimit != (int)local->config.longRetryLimit) + vwrq->value = le16_to_cpu(local->config.shortRetryLimit); + if(local->config.shortRetryLimit != local->config.longRetryLimit) vwrq->flags |= IW_RETRY_SHORT; } @@ -6871,7 +6881,7 @@ static int airo_get_range(struct net_device *dev, struct iw_point *dwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; struct iw_range *range = (struct iw_range *) extra; CapabilityRid cap_rid; /* Card capability info */ int i; @@ -6889,8 +6899,9 @@ static int airo_get_range(struct net_device *dev, k = 0; for(i = 0; i < 14; i++) { range->freq[k].i = i + 1; /* List index */ - range->freq[k].m = frequency_list[i] * 100000; - range->freq[k++].e = 1; /* Values in table in MHz -> * 10^5 * 10 */ + range->freq[k].m = 100000 * + ieee80211_channel_to_frequency(i + 1, IEEE80211_BAND_2GHZ); + range->freq[k++].e = 1; /* Values in MHz -> * 10^5 * 10 */ } range->num_frequency = k; @@ -6936,16 +6947,17 @@ static int airo_get_range(struct net_device *dev, range->min_frag = 256; range->max_frag = AIRO_DEF_MTU; - if(cap_rid.softCap & 2) { + if(cap_rid.softCap & cpu_to_le16(2)) { // WEP: RC4 40 bits range->encoding_size[0] = 5; // RC4 ~128 bits - if (cap_rid.softCap & 0x100) { + if (cap_rid.softCap & cpu_to_le16(0x100)) { range->encoding_size[1] = 13; range->num_encoding_sizes = 2; } else range->num_encoding_sizes = 1; - range->max_encoding_tokens = (cap_rid.softCap & 0x80) ? 4 : 1; + range->max_encoding_tokens = + cap_rid.softCap & cpu_to_le16(0x80) ? 4 : 1; } else { range->num_encoding_sizes = 0; range->max_encoding_tokens = 0; @@ -6960,7 +6972,7 @@ static int airo_get_range(struct net_device *dev, /* Transmit Power - values are in mW */ for(i = 0 ; i < 8 ; i++) { - range->txpower[i] = cap_rid.txPowerLevels[i]; + range->txpower[i] = le16_to_cpu(cap_rid.txPowerLevels[i]); if(range->txpower[i] == 0) break; } @@ -6995,42 +7007,41 @@ static int airo_set_power(struct net_device *dev, struct iw_param *vwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; readConfigRid(local, 1); if (vwrq->disabled) { - if ((local->config.rmode & 0xFF) >= RXMODE_RFMON) { + if (sniffing_mode(local)) return -EINVAL; - } local->config.powerSaveMode = POWERSAVE_CAM; - local->config.rmode &= 0xFF00; + local->config.rmode &= ~RXMODE_MASK; local->config.rmode |= RXMODE_BC_MC_ADDR; set_bit (FLAG_COMMIT, &local->flags); return -EINPROGRESS; /* Call commit handler */ } if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { - local->config.fastListenDelay = (vwrq->value + 500) / 1024; + local->config.fastListenDelay = cpu_to_le16((vwrq->value + 500) / 1024); local->config.powerSaveMode = POWERSAVE_PSPCAM; set_bit (FLAG_COMMIT, &local->flags); } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) { - local->config.fastListenInterval = local->config.listenInterval = (vwrq->value + 500) / 1024; + local->config.fastListenInterval = + local->config.listenInterval = + cpu_to_le16((vwrq->value + 500) / 1024); local->config.powerSaveMode = POWERSAVE_PSPCAM; set_bit (FLAG_COMMIT, &local->flags); } switch (vwrq->flags & IW_POWER_MODE) { case IW_POWER_UNICAST_R: - if ((local->config.rmode & 0xFF) >= RXMODE_RFMON) { + if (sniffing_mode(local)) return -EINVAL; - } - local->config.rmode &= 0xFF00; + local->config.rmode &= ~RXMODE_MASK; local->config.rmode |= RXMODE_ADDR; set_bit (FLAG_COMMIT, &local->flags); break; case IW_POWER_ALL_R: - if ((local->config.rmode & 0xFF) >= RXMODE_RFMON) { + if (sniffing_mode(local)) return -EINVAL; - } - local->config.rmode &= 0xFF00; + local->config.rmode &= ~RXMODE_MASK; local->config.rmode |= RXMODE_BC_MC_ADDR; set_bit (FLAG_COMMIT, &local->flags); case IW_POWER_ON: @@ -7053,21 +7064,21 @@ static int airo_get_power(struct net_device *dev, struct iw_param *vwrq, char *extra) { - struct airo_info *local = dev->priv; - int mode; + struct airo_info *local = dev->ml_priv; + __le16 mode; readConfigRid(local, 1); mode = local->config.powerSaveMode; if ((vwrq->disabled = (mode == POWERSAVE_CAM))) return 0; if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { - vwrq->value = (int)local->config.fastListenDelay * 1024; + vwrq->value = le16_to_cpu(local->config.fastListenDelay) * 1024; vwrq->flags = IW_POWER_TIMEOUT; } else { - vwrq->value = (int)local->config.fastListenInterval * 1024; + vwrq->value = le16_to_cpu(local->config.fastListenInterval) * 1024; vwrq->flags = IW_POWER_PERIOD; } - if ((local->config.rmode & 0xFF) == RXMODE_ADDR) + if ((local->config.rmode & RXMODE_MASK) == RXMODE_ADDR) vwrq->flags |= IW_POWER_UNICAST_R; else vwrq->flags |= IW_POWER_ALL_R; @@ -7084,10 +7095,11 @@ static int airo_set_sens(struct net_device *dev, struct iw_param *vwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; readConfigRid(local, 1); - local->config.rssiThreshold = vwrq->disabled ? RSSI_DEFAULT : vwrq->value; + local->config.rssiThreshold = + cpu_to_le16(vwrq->disabled ? RSSI_DEFAULT : vwrq->value); set_bit (FLAG_COMMIT, &local->flags); return -EINPROGRESS; /* Call commit handler */ @@ -7102,10 +7114,10 @@ static int airo_get_sens(struct net_device *dev, struct iw_param *vwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; readConfigRid(local, 1); - vwrq->value = local->config.rssiThreshold; + vwrq->value = le16_to_cpu(local->config.rssiThreshold); vwrq->disabled = (vwrq->value == 0); vwrq->fixed = 1; @@ -7122,34 +7134,40 @@ static int airo_get_aplist(struct net_device *dev, struct iw_point *dwrq, char *extra) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; struct sockaddr *address = (struct sockaddr *) extra; - struct iw_quality qual[IW_MAX_AP]; + struct iw_quality *qual; BSSListRid BSSList; int i; int loseSync = capable(CAP_NET_ADMIN) ? 1: -1; + qual = kmalloc(IW_MAX_AP * sizeof(*qual), GFP_KERNEL); + if (!qual) + return -ENOMEM; + for (i = 0; i < IW_MAX_AP; i++) { + u16 dBm; if (readBSSListRid(local, loseSync, &BSSList)) break; loseSync = 0; memcpy(address[i].sa_data, BSSList.bssid, ETH_ALEN); address[i].sa_family = ARPHRD_ETHER; + dBm = le16_to_cpu(BSSList.dBm); if (local->rssi) { - qual[i].level = 0x100 - BSSList.dBm; - qual[i].qual = airo_dbm_to_pct( local->rssi, BSSList.dBm ); + qual[i].level = 0x100 - dBm; + qual[i].qual = airo_dbm_to_pct(local->rssi, dBm); qual[i].updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_DBM; } else { - qual[i].level = (BSSList.dBm + 321) / 2; + qual[i].level = (dBm + 321) / 2; qual[i].qual = 0; qual[i].updated = IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED | IW_QUAL_DBM; } qual[i].noise = local->wstats.qual.noise; - if (BSSList.index == 0xffff) + if (BSSList.index == cpu_to_le16(0xffff)) break; } if (!i) { @@ -7176,11 +7194,12 @@ static int airo_get_aplist(struct net_device *dev, } } else { dwrq->flags = 1; /* Should be define'd */ - memcpy(extra + sizeof(struct sockaddr)*i, - &qual, sizeof(struct iw_quality)*i); + memcpy(extra + sizeof(struct sockaddr) * i, qual, + sizeof(struct iw_quality) * i); } dwrq->length = i; + kfree(qual); return 0; } @@ -7190,10 +7209,10 @@ static int airo_get_aplist(struct net_device *dev, */ static int airo_set_scan(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, + struct iw_point *dwrq, char *extra) { - struct airo_info *ai = dev->priv; + struct airo_info *ai = dev->ml_priv; Cmd cmd; Resp rsp; int wake = 0; @@ -7234,22 +7253,25 @@ out: * format that the Wireless Tools will understand - Jean II */ static inline char *airo_translate_scan(struct net_device *dev, + struct iw_request_info *info, char *current_ev, char *end_buf, BSSListRid *bss) { - struct airo_info *ai = dev->priv; + struct airo_info *ai = dev->ml_priv; struct iw_event iwe; /* Temporary buffer */ - u16 capabilities; + __le16 capabilities; char * current_val; /* For rates */ int i; char * buf; + u16 dBm; /* First entry *MUST* be the AP MAC address */ iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN); - current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); + current_ev = iwe_stream_add_event(info, current_ev, end_buf, + &iwe, IW_EV_ADDR_LEN); /* Other entries will be displayed in the order we give them */ @@ -7259,46 +7281,50 @@ static inline char *airo_translate_scan(struct net_device *dev, iwe.u.data.length = 32; iwe.cmd = SIOCGIWESSID; iwe.u.data.flags = 1; - current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid); + current_ev = iwe_stream_add_point(info, current_ev, end_buf, + &iwe, bss->ssid); /* Add mode */ iwe.cmd = SIOCGIWMODE; - capabilities = le16_to_cpu(bss->cap); + capabilities = bss->cap; if(capabilities & (CAP_ESS | CAP_IBSS)) { if(capabilities & CAP_ESS) iwe.u.mode = IW_MODE_MASTER; else iwe.u.mode = IW_MODE_ADHOC; - current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_UINT_LEN); + current_ev = iwe_stream_add_event(info, current_ev, end_buf, + &iwe, IW_EV_UINT_LEN); } /* Add frequency */ iwe.cmd = SIOCGIWFREQ; iwe.u.freq.m = le16_to_cpu(bss->dsChannel); - /* iwe.u.freq.m containt the channel (starting 1), our - * frequency_list array start at index 0... - */ - iwe.u.freq.m = frequency_list[iwe.u.freq.m - 1] * 100000; + iwe.u.freq.m = 100000 * + ieee80211_channel_to_frequency(iwe.u.freq.m, IEEE80211_BAND_2GHZ); iwe.u.freq.e = 1; - current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); + current_ev = iwe_stream_add_event(info, current_ev, end_buf, + &iwe, IW_EV_FREQ_LEN); + + dBm = le16_to_cpu(bss->dBm); /* Add quality statistics */ iwe.cmd = IWEVQUAL; if (ai->rssi) { - iwe.u.qual.level = 0x100 - bss->dBm; - iwe.u.qual.qual = airo_dbm_to_pct( ai->rssi, bss->dBm ); + iwe.u.qual.level = 0x100 - dBm; + iwe.u.qual.qual = airo_dbm_to_pct(ai->rssi, dBm); iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_DBM; } else { - iwe.u.qual.level = (bss->dBm + 321) / 2; + iwe.u.qual.level = (dBm + 321) / 2; iwe.u.qual.qual = 0; iwe.u.qual.updated = IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED | IW_QUAL_DBM; } iwe.u.qual.noise = ai->wstats.qual.noise; - current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); + current_ev = iwe_stream_add_event(info, current_ev, end_buf, + &iwe, IW_EV_QUAL_LEN); /* Add encryption capability */ iwe.cmd = SIOCGIWENCODE; @@ -7307,11 +7333,12 @@ static inline char *airo_translate_scan(struct net_device *dev, else iwe.u.data.flags = IW_ENCODE_DISABLED; iwe.u.data.length = 0; - current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid); + current_ev = iwe_stream_add_point(info, current_ev, end_buf, + &iwe, bss->ssid); /* Rate : stuffing multiple values in a single event require a bit * more of magic - Jean II */ - current_val = current_ev + IW_EV_LCP_LEN; + current_val = current_ev + iwe_stream_lcp_len(info); iwe.cmd = SIOCGIWRATE; /* Those two flags are ignored... */ @@ -7324,10 +7351,12 @@ static inline char *airo_translate_scan(struct net_device *dev, /* Bit rate given in 500 kb/s units (+ 0x80) */ iwe.u.bitrate.value = ((bss->rates[i] & 0x7f) * 500000); /* Add new value to event */ - current_val = iwe_stream_add_value(current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); + current_val = iwe_stream_add_value(info, current_ev, + current_val, end_buf, + &iwe, IW_EV_PARAM_LEN); } /* Check if we added any event */ - if((current_val - current_ev) > IW_EV_LCP_LEN) + if ((current_val - current_ev) > iwe_stream_lcp_len(info)) current_ev = current_val; /* Beacon interval */ @@ -7336,7 +7365,8 @@ static inline char *airo_translate_scan(struct net_device *dev, iwe.cmd = IWEVCUSTOM; sprintf(buf, "bcn_int=%d", bss->beaconInterval); iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf); + current_ev = iwe_stream_add_point(info, current_ev, end_buf, + &iwe, buf); kfree(buf); } @@ -7344,53 +7374,53 @@ static inline char *airo_translate_scan(struct net_device *dev, if (test_bit(FLAG_WPA_CAPABLE, &ai->flags)) { unsigned int num_null_ies = 0; u16 length = sizeof (bss->extra.iep); - struct ieee80211_info_element *info_element = - (struct ieee80211_info_element *) &bss->extra.iep; + u8 *ie = (void *)&bss->extra.iep; - while ((length >= sizeof(*info_element)) && (num_null_ies < 2)) { - if (sizeof(*info_element) + info_element->len > length) { + while ((length >= 2) && (num_null_ies < 2)) { + if (2 + ie[1] > length) { /* Invalid element, don't continue parsing IE */ break; } - switch (info_element->id) { - case MFIE_TYPE_SSID: + switch (ie[0]) { + case WLAN_EID_SSID: /* Two zero-length SSID elements * mean we're done parsing elements */ - if (!info_element->len) + if (!ie[1]) num_null_ies++; break; - case MFIE_TYPE_GENERIC: - if (info_element->len >= 4 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x50 && - info_element->data[2] == 0xf2 && - info_element->data[3] == 0x01) { + case WLAN_EID_VENDOR_SPECIFIC: + if (ie[1] >= 4 && + ie[2] == 0x00 && + ie[3] == 0x50 && + ie[4] == 0xf2 && + ie[5] == 0x01) { iwe.cmd = IWEVGENIE; - iwe.u.data.length = min(info_element->len + 2, - MAX_WPA_IE_LEN); - current_ev = iwe_stream_add_point(current_ev, end_buf, - &iwe, (char *) info_element); + /* 64 is an arbitrary cut-off */ + iwe.u.data.length = min(ie[1] + 2, + 64); + current_ev = iwe_stream_add_point( + info, current_ev, + end_buf, &iwe, ie); } break; - case MFIE_TYPE_RSN: + case WLAN_EID_RSN: iwe.cmd = IWEVGENIE; - iwe.u.data.length = min(info_element->len + 2, - MAX_WPA_IE_LEN); - current_ev = iwe_stream_add_point(current_ev, end_buf, - &iwe, (char *) info_element); + /* 64 is an arbitrary cut-off */ + iwe.u.data.length = min(ie[1] + 2, 64); + current_ev = iwe_stream_add_point( + info, current_ev, end_buf, + &iwe, ie); break; default: break; } - length -= sizeof(*info_element) + info_element->len; - info_element = - (struct ieee80211_info_element *)&info_element-> - data[info_element->len]; + length -= 2 + ie[1]; + ie += 2 + ie[1]; } } return current_ev; @@ -7405,7 +7435,7 @@ static int airo_get_scan(struct net_device *dev, struct iw_point *dwrq, char *extra) { - struct airo_info *ai = dev->priv; + struct airo_info *ai = dev->ml_priv; BSSListElement *net; int err = 0; char *current_ev = extra; @@ -7419,7 +7449,7 @@ static int airo_get_scan(struct net_device *dev, list_for_each_entry (net, &ai->network_list, list) { /* Translate to WE format this entry */ - current_ev = airo_translate_scan(dev, current_ev, + current_ev = airo_translate_scan(dev, info, current_ev, extra + dwrq->length, &net->bss); @@ -7449,7 +7479,7 @@ static int airo_config_commit(struct net_device *dev, void *zwrq, /* NULL */ char *extra) /* NULL */ { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; if (!test_bit (FLAG_COMMIT, &local->flags)) return 0; @@ -7594,7 +7624,7 @@ static const struct iw_handler_def airo_handler_def = static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { int rc = 0; - struct airo_info *ai = (struct airo_info *)dev->priv; + struct airo_info *ai = dev->ml_priv; if (ai->power.event) return 0; @@ -7670,7 +7700,7 @@ static void airo_read_wireless_stats(struct airo_info *local) StatusRid status_rid; StatsRid stats_rid; CapabilityRid cap_rid; - u32 *vals = stats_rid.vals; + __le32 *vals = stats_rid.vals; /* Get stats out of the card */ clear_bit(JOB_WSTATS, &local->jobs); @@ -7684,18 +7714,22 @@ static void airo_read_wireless_stats(struct airo_info *local) up(&local->sem); /* The status */ - local->wstats.status = status_rid.mode; + local->wstats.status = le16_to_cpu(status_rid.mode); /* Signal quality and co */ if (local->rssi) { - local->wstats.qual.level = airo_rssi_to_dbm( local->rssi, status_rid.sigQuality ); + local->wstats.qual.level = + airo_rssi_to_dbm(local->rssi, + le16_to_cpu(status_rid.sigQuality)); /* normalizedSignalStrength appears to be a percentage */ - local->wstats.qual.qual = status_rid.normalizedSignalStrength; + local->wstats.qual.qual = + le16_to_cpu(status_rid.normalizedSignalStrength); } else { - local->wstats.qual.level = (status_rid.normalizedSignalStrength + 321) / 2; + local->wstats.qual.level = + (le16_to_cpu(status_rid.normalizedSignalStrength) + 321) / 2; local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid); } - if (status_rid.len >= 124) { + if (le16_to_cpu(status_rid.len) >= 124) { local->wstats.qual.noise = 0x100 - status_rid.noisedBm; local->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; } else { @@ -7705,17 +7739,20 @@ static void airo_read_wireless_stats(struct airo_info *local) /* Packets discarded in the wireless adapter due to wireless * specific problems */ - local->wstats.discard.nwid = vals[56] + vals[57] + vals[58];/* SSID Mismatch */ - local->wstats.discard.code = vals[6];/* RxWepErr */ - local->wstats.discard.fragment = vals[30]; - local->wstats.discard.retries = vals[10]; - local->wstats.discard.misc = vals[1] + vals[32]; - local->wstats.miss.beacon = vals[34]; + local->wstats.discard.nwid = le32_to_cpu(vals[56]) + + le32_to_cpu(vals[57]) + + le32_to_cpu(vals[58]); /* SSID Mismatch */ + local->wstats.discard.code = le32_to_cpu(vals[6]);/* RxWepErr */ + local->wstats.discard.fragment = le32_to_cpu(vals[30]); + local->wstats.discard.retries = le32_to_cpu(vals[10]); + local->wstats.discard.misc = le32_to_cpu(vals[1]) + + le32_to_cpu(vals[32]); + local->wstats.miss.beacon = le32_to_cpu(vals[34]); } static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev) { - struct airo_info *local = dev->priv; + struct airo_info *local = dev->ml_priv; if (!test_bit(JOB_WSTATS, &local->jobs)) { /* Get stats out of the card if available */ @@ -7740,7 +7777,7 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) { unsigned short ridcode; unsigned char *iobuf; int len; - struct airo_info *ai = dev->priv; + struct airo_info *ai = dev->ml_priv; if (test_bit(FLAG_FLASHING, &ai->flags)) return -EIO; @@ -7806,7 +7843,7 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) { */ static int writerids(struct net_device *dev, aironet_ioctl *comp) { - struct airo_info *ai = dev->priv; + struct airo_info *ai = dev->ml_priv; int ridcode; int enabled; static int (* writer)(struct airo_info *, u16 rid, const void *, int, int); @@ -7896,7 +7933,7 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) { if (test_bit(FLAG_MIC_CAPABLE, &ai->flags)) cfg->opmode |= MODE_MIC; - if ((cfg->opmode & 0xFF) == MODE_STA_IBSS) + if ((cfg->opmode & MODE_CFG_MASK) == MODE_STA_IBSS) set_bit (FLAG_ADHOC, &ai->flags); else clear_bit (FLAG_ADHOC, &ai->flags); @@ -7929,41 +7966,41 @@ static int flashcard(struct net_device *dev, aironet_ioctl *comp) { switch(comp->command) { case AIROFLSHRST: - return cmdreset((struct airo_info *)dev->priv); + return cmdreset((struct airo_info *)dev->ml_priv); case AIROFLSHSTFL: - if (!((struct airo_info *)dev->priv)->flash && - (((struct airo_info *)dev->priv)->flash = kmalloc (FLASHSIZE, GFP_KERNEL)) == NULL) + if (!AIRO_FLASH(dev) && + (AIRO_FLASH(dev) = kmalloc(FLASHSIZE, GFP_KERNEL)) == NULL) return -ENOMEM; - return setflashmode((struct airo_info *)dev->priv); + return setflashmode((struct airo_info *)dev->ml_priv); case AIROFLSHGCHR: /* Get char from aux */ if(comp->len != sizeof(int)) return -EINVAL; if (copy_from_user(&z,comp->data,comp->len)) return -EFAULT; - return flashgchar((struct airo_info *)dev->priv,z,8000); + return flashgchar((struct airo_info *)dev->ml_priv, z, 8000); case AIROFLSHPCHR: /* Send char to card. */ if(comp->len != sizeof(int)) return -EINVAL; if (copy_from_user(&z,comp->data,comp->len)) return -EFAULT; - return flashpchar((struct airo_info *)dev->priv,z,8000); + return flashpchar((struct airo_info *)dev->ml_priv, z, 8000); case AIROFLPUTBUF: /* Send 32k to card */ - if (!((struct airo_info *)dev->priv)->flash) + if (!AIRO_FLASH(dev)) return -ENOMEM; if(comp->len > FLASHSIZE) return -EINVAL; - if(copy_from_user(((struct airo_info *)dev->priv)->flash,comp->data,comp->len)) + if (copy_from_user(AIRO_FLASH(dev), comp->data, comp->len)) return -EFAULT; - flashputbuf((struct airo_info *)dev->priv); + flashputbuf((struct airo_info *)dev->ml_priv); return 0; case AIRORESTART: - if(flashrestart((struct airo_info *)dev->priv,dev)) + if (flashrestart((struct airo_info *)dev->ml_priv, dev)) return -EIO; return 0; } |
