Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
9b7c8489
Commit
9b7c8489
authored
Mar 23, 2006
by
Jeff Garzik
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'upstream' of
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6
parents
eff4b1fe
4edac92f
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
1264 additions
and
301 deletions
+1264
-301
drivers/net/wireless/Kconfig
drivers/net/wireless/Kconfig
+9
-0
drivers/net/wireless/airo.c
drivers/net/wireless/airo.c
+294
-161
drivers/net/wireless/hostap/hostap_ap.c
drivers/net/wireless/hostap/hostap_ap.c
+1
-1
drivers/net/wireless/hostap/hostap_cs.c
drivers/net/wireless/hostap/hostap_cs.c
+0
-2
drivers/net/wireless/hostap/hostap_hw.c
drivers/net/wireless/hostap/hostap_hw.c
+4
-4
drivers/net/wireless/hostap/hostap_ioctl.c
drivers/net/wireless/hostap/hostap_ioctl.c
+0
-4
drivers/net/wireless/hostap/hostap_pci.c
drivers/net/wireless/hostap/hostap_pci.c
+3
-1
drivers/net/wireless/hostap/hostap_plx.c
drivers/net/wireless/hostap/hostap_plx.c
+7
-6
include/linux/wireless.h
include/linux/wireless.h
+7
-3
include/net/iw_handler.h
include/net/iw_handler.h
+11
-1
net/core/rtnetlink.c
net/core/rtnetlink.c
+97
-1
net/core/wireless.c
net/core/wireless.c
+823
-88
net/ieee80211/softmac/ieee80211softmac_assoc.c
net/ieee80211/softmac/ieee80211softmac_assoc.c
+1
-8
net/ieee80211/softmac/ieee80211softmac_auth.c
net/ieee80211/softmac/ieee80211softmac_auth.c
+0
-12
net/ieee80211/softmac/ieee80211softmac_priv.h
net/ieee80211/softmac/ieee80211softmac_priv.h
+0
-9
net/ieee80211/softmac/ieee80211softmac_scan.c
net/ieee80211/softmac/ieee80211softmac_scan.c
+7
-0
No files found.
drivers/net/wireless/Kconfig
View file @
9b7c8489
...
@@ -25,6 +25,15 @@ config NET_RADIO
...
@@ -25,6 +25,15 @@ config NET_RADIO
the tools from
the tools from
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
config NET_WIRELESS_RTNETLINK
bool "Wireless Extension API over RtNetlink"
---help---
Support the Wireless Extension API over the RtNetlink socket
in addition to the traditional ioctl interface (selected above).
For now, few tools use this facility, but it might grow in the
future. The only downside is that it adds 4.5 kB to your kernel.
# Note : the cards are obsolete (can't buy them anymore), but the drivers
# Note : the cards are obsolete (can't buy them anymore), but the drivers
# are not, as people are still using them...
# are not, as people are still using them...
comment "Obsolete Wireless cards support (pre-802.11)"
comment "Obsolete Wireless cards support (pre-802.11)"
...
...
drivers/net/wireless/airo.c
View file @
9b7c8489
...
@@ -769,6 +769,11 @@ typedef struct {
...
@@ -769,6 +769,11 @@ typedef struct {
u16
atimWindow
;
u16
atimWindow
;
}
BSSListRid
;
}
BSSListRid
;
typedef
struct
{
BSSListRid
bss
;
struct
list_head
list
;
}
BSSListElement
;
typedef
struct
{
typedef
struct
{
u8
rssipct
;
u8
rssipct
;
u8
rssidBm
;
u8
rssidBm
;
...
@@ -902,6 +907,7 @@ static char swversion[] = "2.1";
...
@@ -902,6 +907,7 @@ static char swversion[] = "2.1";
#define NUM_MODULES 2
#define NUM_MODULES 2
#define MIC_MSGLEN_MAX 2400
#define MIC_MSGLEN_MAX 2400
#define EMMH32_MSGLEN_MAX MIC_MSGLEN_MAX
#define EMMH32_MSGLEN_MAX MIC_MSGLEN_MAX
#define AIRO_DEF_MTU 2312
typedef
struct
{
typedef
struct
{
u32
size
;
// size
u32
size
;
// size
...
@@ -1119,6 +1125,8 @@ static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *pPacket,
...
@@ -1119,6 +1125,8 @@ static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *pPacket,
static
u8
airo_rssi_to_dbm
(
tdsRssiEntry
*
rssi_rid
,
u8
rssi
);
static
u8
airo_rssi_to_dbm
(
tdsRssiEntry
*
rssi_rid
,
u8
rssi
);
static
u8
airo_dbm_to_pct
(
tdsRssiEntry
*
rssi_rid
,
u8
dbm
);
static
u8
airo_dbm_to_pct
(
tdsRssiEntry
*
rssi_rid
,
u8
dbm
);
static
void
airo_networks_free
(
struct
airo_info
*
ai
);
struct
airo_info
{
struct
airo_info
{
struct
net_device_stats
stats
;
struct
net_device_stats
stats
;
struct
net_device
*
dev
;
struct
net_device
*
dev
;
...
@@ -1150,7 +1158,7 @@ struct airo_info {
...
@@ -1150,7 +1158,7 @@ struct airo_info {
#define FLAG_COMMIT 13
#define FLAG_COMMIT 13
#define FLAG_RESET 14
#define FLAG_RESET 14
#define FLAG_FLASHING 15
#define FLAG_FLASHING 15
#define JOB_MASK 0x
1
ff0000
#define JOB_MASK 0x
2
ff0000
#define JOB_DIE 16
#define JOB_DIE 16
#define JOB_XMIT 17
#define JOB_XMIT 17
#define JOB_XMIT11 18
#define JOB_XMIT11 18
...
@@ -1160,6 +1168,7 @@ struct airo_info {
...
@@ -1160,6 +1168,7 @@ struct airo_info {
#define JOB_EVENT 22
#define JOB_EVENT 22
#define JOB_AUTOWEP 23
#define JOB_AUTOWEP 23
#define JOB_WSTATS 24
#define JOB_WSTATS 24
#define JOB_SCAN_RESULTS 25
int
(
*
bap_read
)(
struct
airo_info
*
,
u16
*
pu16Dst
,
int
bytelen
,
int
(
*
bap_read
)(
struct
airo_info
*
,
u16
*
pu16Dst
,
int
bytelen
,
int
whichbap
);
int
whichbap
);
unsigned
short
*
flash
;
unsigned
short
*
flash
;
...
@@ -1176,7 +1185,7 @@ struct airo_info {
...
@@ -1176,7 +1185,7 @@ struct airo_info {
}
xmit
,
xmit11
;
}
xmit
,
xmit11
;
struct
net_device
*
wifidev
;
struct
net_device
*
wifidev
;
struct
iw_statistics
wstats
;
// wireless stats
struct
iw_statistics
wstats
;
// wireless stats
unsigned
long
scan_time
stamp
;
/* Time started to scan
*/
unsigned
long
scan_time
out
;
/* Time scan should be read
*/
struct
iw_spy_data
spy_data
;
struct
iw_spy_data
spy_data
;
struct
iw_public_data
wireless_data
;
struct
iw_public_data
wireless_data
;
/* MIC stuff */
/* MIC stuff */
...
@@ -1198,6 +1207,10 @@ struct airo_info {
...
@@ -1198,6 +1207,10 @@ struct airo_info {
APListRid
*
APList
;
APListRid
*
APList
;
#define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE
#define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE
char
proc_name
[
IFNAMSIZ
];
char
proc_name
[
IFNAMSIZ
];
struct
list_head
network_list
;
struct
list_head
network_free_list
;
BSSListElement
*
networks
;
};
};
static
inline
int
bap_read
(
struct
airo_info
*
ai
,
u16
*
pu16Dst
,
int
bytelen
,
static
inline
int
bap_read
(
struct
airo_info
*
ai
,
u16
*
pu16Dst
,
int
bytelen
,
...
@@ -1216,6 +1229,22 @@ static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime);
...
@@ -1216,6 +1229,22 @@ static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime);
static
int
flashputbuf
(
struct
airo_info
*
ai
);
static
int
flashputbuf
(
struct
airo_info
*
ai
);
static
int
flashrestart
(
struct
airo_info
*
ai
,
struct
net_device
*
dev
);
static
int
flashrestart
(
struct
airo_info
*
ai
,
struct
net_device
*
dev
);
#define airo_print(type, name, fmt, args...) \
{ printk(type "airo(%s): " fmt "\n", name, ##args); }
#define airo_print_info(name, fmt, args...) \
airo_print(KERN_INFO, name, fmt, ##args)
#define airo_print_dbg(name, fmt, args...) \
airo_print(KERN_DEBUG, name, fmt, ##args)
#define airo_print_warn(name, fmt, args...) \
airo_print(KERN_WARNING, name, fmt, ##args)
#define airo_print_err(name, fmt, args...) \
airo_print(KERN_ERR, name, fmt, ##args)
/***********************************************************************
/***********************************************************************
* MIC ROUTINES *
* MIC ROUTINES *
***********************************************************************
***********************************************************************
...
@@ -1294,7 +1323,7 @@ static int micsetup(struct airo_info *ai) {
...
@@ -1294,7 +1323,7 @@ static int micsetup(struct airo_info *ai) {
ai
->
tfm
=
crypto_alloc_tfm
(
"aes"
,
CRYPTO_TFM_REQ_MAY_SLEEP
);
ai
->
tfm
=
crypto_alloc_tfm
(
"aes"
,
CRYPTO_TFM_REQ_MAY_SLEEP
);
if
(
ai
->
tfm
==
NULL
)
{
if
(
ai
->
tfm
==
NULL
)
{
printk
(
KERN_ERR
"airo: failed to load transform for AES
\n
"
);
airo_print_err
(
ai
->
dev
->
name
,
"failed to load transform for AES
"
);
return
ERROR
;
return
ERROR
;
}
}
...
@@ -1726,11 +1755,11 @@ static int writeWepKeyRid(struct airo_info*ai, WepKeyRid *pwkr, int perm, int lo
...
@@ -1726,11 +1755,11 @@ static int writeWepKeyRid(struct airo_info*ai, WepKeyRid *pwkr, int perm, int lo
wkr
.
kindex
=
cpu_to_le16
(
wkr
.
kindex
);
wkr
.
kindex
=
cpu_to_le16
(
wkr
.
kindex
);
wkr
.
klen
=
cpu_to_le16
(
wkr
.
klen
);
wkr
.
klen
=
cpu_to_le16
(
wkr
.
klen
);
rc
=
PC4500_writerid
(
ai
,
RID_WEP_TEMP
,
&
wkr
,
sizeof
(
wkr
),
lock
);
rc
=
PC4500_writerid
(
ai
,
RID_WEP_TEMP
,
&
wkr
,
sizeof
(
wkr
),
lock
);
if
(
rc
!=
SUCCESS
)
printk
(
KERN_ERR
"airo: WEP_TEMP set %x
\n
"
,
rc
);
if
(
rc
!=
SUCCESS
)
airo_print_err
(
ai
->
dev
->
name
,
"WEP_TEMP set %x
"
,
rc
);
if
(
perm
)
{
if
(
perm
)
{
rc
=
PC4500_writerid
(
ai
,
RID_WEP_PERM
,
&
wkr
,
sizeof
(
wkr
),
lock
);
rc
=
PC4500_writerid
(
ai
,
RID_WEP_PERM
,
&
wkr
,
sizeof
(
wkr
),
lock
);
if
(
rc
!=
SUCCESS
)
{
if
(
rc
!=
SUCCESS
)
{
printk
(
KERN_ERR
"airo: WEP_PERM set %x
\n
"
,
rc
);
airo_print_err
(
ai
->
dev
->
name
,
"WEP_PERM set %x
"
,
rc
);
}
}
}
}
return
rc
;
return
rc
;
...
@@ -1909,7 +1938,7 @@ static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) {
...
@@ -1909,7 +1938,7 @@ static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) {
struct
airo_info
*
ai
=
dev
->
priv
;
struct
airo_info
*
ai
=
dev
->
priv
;
if
(
!
skb
)
{
if
(
!
skb
)
{
printk
(
KERN_ERR
"airo: %s: skb==NULL
\n
"
,
__FUNCTION__
);
airo_print_err
(
dev
->
name
,
"%s: skb == NULL!
"
,
__FUNCTION__
);
return
0
;
return
0
;
}
}
npacks
=
skb_queue_len
(
&
ai
->
txq
);
npacks
=
skb_queue_len
(
&
ai
->
txq
);
...
@@ -1955,8 +1984,8 @@ static int mpi_send_packet (struct net_device *dev)
...
@@ -1955,8 +1984,8 @@ static int mpi_send_packet (struct net_device *dev)
/* get a packet to send */
/* get a packet to send */
if
((
skb
=
skb_dequeue
(
&
ai
->
txq
))
==
0
)
{
if
((
skb
=
skb_dequeue
(
&
ai
->
txq
))
==
0
)
{
printk
(
KERN_ERR
airo_print_err
(
dev
->
name
,
"
airo: %s: Dequeue'd zero in send_packet()
\n
"
,
"
%s: Dequeue'd zero in send_packet()
"
,
__FUNCTION__
);
__FUNCTION__
);
return
0
;
return
0
;
}
}
...
@@ -2108,7 +2137,7 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
...
@@ -2108,7 +2137,7 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
u32
*
fids
=
priv
->
fids
;
u32
*
fids
=
priv
->
fids
;
if
(
skb
==
NULL
)
{
if
(
skb
==
NULL
)
{
printk
(
KERN_ERR
"airo: skb == NULL!!!
\n
"
);
airo_print_err
(
dev
->
name
,
"%s: skb == NULL!"
,
__FUNCTION__
);
return
0
;
return
0
;
}
}
...
@@ -2179,7 +2208,7 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
...
@@ -2179,7 +2208,7 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
}
}
if
(
skb
==
NULL
)
{
if
(
skb
==
NULL
)
{
printk
(
KERN_ERR
"airo: skb == NULL!!!
\n
"
);
airo_print_err
(
dev
->
name
,
"%s: skb == NULL!"
,
__FUNCTION__
);
return
0
;
return
0
;
}
}
...
@@ -2364,6 +2393,8 @@ void stop_airo_card( struct net_device *dev, int freeres )
...
@@ -2364,6 +2393,8 @@ void stop_airo_card( struct net_device *dev, int freeres )
dev_kfree_skb
(
skb
);
dev_kfree_skb
(
skb
);
}
}
airo_networks_free
(
ai
);
kfree
(
ai
->
flash
);
kfree
(
ai
->
flash
);
kfree
(
ai
->
rssi
);
kfree
(
ai
->
rssi
);
kfree
(
ai
->
APList
);
kfree
(
ai
->
APList
);
...
@@ -2434,7 +2465,7 @@ static int mpi_init_descriptors (struct airo_info *ai)
...
@@ -2434,7 +2465,7 @@ static int mpi_init_descriptors (struct airo_info *ai)
cmd
.
parm2
=
MPI_MAX_FIDS
;
cmd
.
parm2
=
MPI_MAX_FIDS
;
rc
=
issuecommand
(
ai
,
&
cmd
,
&
rsp
);
rc
=
issuecommand
(
ai
,
&
cmd
,
&
rsp
);
if
(
rc
!=
SUCCESS
)
{
if
(
rc
!=
SUCCESS
)
{
printk
(
KERN_ERR
"airo: Couldn't allocate RX FID
\n
"
);
airo_print_err
(
ai
->
dev
->
name
,
"Couldn't allocate RX FID
"
);
return
rc
;
return
rc
;
}
}
...
@@ -2462,7 +2493,7 @@ static int mpi_init_descriptors (struct airo_info *ai)
...
@@ -2462,7 +2493,7 @@ static int mpi_init_descriptors (struct airo_info *ai)
rc
=
issuecommand
(
ai
,
&
cmd
,
&
rsp
);
rc
=
issuecommand
(
ai
,
&
cmd
,
&
rsp
);
if
(
rc
!=
SUCCESS
)
{
if
(
rc
!=
SUCCESS
)
{
printk
(
KERN_ERR
"airo: Couldn't allocate TX FID
\n
"
);
airo_print_err
(
ai
->
dev
->
name
,
"Couldn't allocate TX FID
"
);
return
rc
;
return
rc
;
}
}
...
@@ -2476,7 +2507,7 @@ static int mpi_init_descriptors (struct airo_info *ai)
...
@@ -2476,7 +2507,7 @@ static int mpi_init_descriptors (struct airo_info *ai)
cmd
.
parm2
=
1
;
/* Magic number... */
cmd
.
parm2
=
1
;
/* Magic number... */
rc
=
issuecommand
(
ai
,
&
cmd
,
&
rsp
);
rc
=
issuecommand
(
ai
,
&
cmd
,
&
rsp
);
if
(
rc
!=
SUCCESS
)
{
if
(
rc
!=
SUCCESS
)
{
printk
(
KERN_ERR
"airo: Couldn't allocate RID
\n
"
);
airo_print_err
(
ai
->
dev
->
name
,
"Couldn't allocate RID
"
);
return
rc
;
return
rc
;
}
}
...
@@ -2508,25 +2539,25 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
...
@@ -2508,25 +2539,25 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
aux_len
=
AUXMEMSIZE
;
aux_len
=
AUXMEMSIZE
;
if
(
!
request_mem_region
(
mem_start
,
mem_len
,
name
))
{
if
(
!
request_mem_region
(
mem_start
,
mem_len
,
name
))
{
printk
(
KERN_ERR
"airo: Couldn't get region %x[%x] for %s
\n
"
,
airo_print_err
(
ai
->
dev
->
name
,
"Couldn't get region %x[%x] for %s
"
,
(
int
)
mem_start
,
(
int
)
mem_len
,
name
);
(
int
)
mem_start
,
(
int
)
mem_len
,
name
);
goto
out
;
goto
out
;
}
}
if
(
!
request_mem_region
(
aux_start
,
aux_len
,
name
))
{
if
(
!
request_mem_region
(
aux_start
,
aux_len
,
name
))
{
printk
(
KERN_ERR
"airo: Couldn't get region %x[%x] for %s
\n
"
,
airo_print_err
(
ai
->
dev
->
name
,
"Couldn't get region %x[%x] for %s
"
,
(
int
)
aux_start
,
(
int
)
aux_len
,
name
);
(
int
)
aux_start
,
(
int
)
aux_len
,
name
);
goto
free_region1
;
goto
free_region1
;
}
}
ai
->
pcimem
=
ioremap
(
mem_start
,
mem_len
);
ai
->
pcimem
=
ioremap
(
mem_start
,
mem_len
);
if
(
!
ai
->
pcimem
)
{
if
(
!
ai
->
pcimem
)
{
printk
(
KERN_ERR
"airo: Couldn't map region %x[%x] for %s
\n
"
,
airo_print_err
(
ai
->
dev
->
name
,
"Couldn't map region %x[%x] for %s
"
,
(
int
)
mem_start
,
(
int
)
mem_len
,
name
);
(
int
)
mem_start
,
(
int
)
mem_len
,
name
);
goto
free_region2
;
goto
free_region2
;
}
}
ai
->
pciaux
=
ioremap
(
aux_start
,
aux_len
);
ai
->
pciaux
=
ioremap
(
aux_start
,
aux_len
);
if
(
!
ai
->
pciaux
)
{
if
(
!
ai
->
pciaux
)
{
printk
(
KERN_ERR
"airo: Couldn't map region %x[%x] for %s
\n
"
,
airo_print_err
(
ai
->
dev
->
name
,
"Couldn't map region %x[%x] for %s
"
,
(
int
)
aux_start
,
(
int
)
aux_len
,
name
);
(
int
)
aux_start
,
(
int
)
aux_len
,
name
);
goto
free_memmap
;
goto
free_memmap
;
}
}
...
@@ -2534,7 +2565,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
...
@@ -2534,7 +2565,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
/* Reserve PKTSIZE for each fid and 2K for the Rids */
/* Reserve PKTSIZE for each fid and 2K for the Rids */
ai
->
shared
=
pci_alloc_consistent
(
pci
,
PCI_SHARED_LEN
,
&
ai
->
shared_dma
);
ai
->
shared
=
pci_alloc_consistent
(
pci
,
PCI_SHARED_LEN
,
&
ai
->
shared_dma
);
if
(
!
ai
->
shared
)
{
if
(
!
ai
->
shared
)
{
printk
(
KERN_ERR
"airo: Couldn't alloc_consistent %d
\n
"
,
airo_print_err
(
ai
->
dev
->
name
,
"Couldn't alloc_consistent %d
"
,
PCI_SHARED_LEN
);
PCI_SHARED_LEN
);
goto
free_auxmap
;
goto
free_auxmap
;
}
}
...
@@ -2626,7 +2657,7 @@ static void wifi_setup(struct net_device *dev)
...
@@ -2626,7 +2657,7 @@ static void wifi_setup(struct net_device *dev)
dev
->
type
=
ARPHRD_IEEE80211
;
dev
->
type
=
ARPHRD_IEEE80211
;
dev
->
hard_header_len
=
ETH_HLEN
;
dev
->
hard_header_len
=
ETH_HLEN
;
dev
->
mtu
=
2312
;
dev
->
mtu
=
AIRO_DEF_MTU
;
dev
->
addr_len
=
ETH_ALEN
;
dev
->
addr_len
=
ETH_ALEN
;
dev
->
tx_queue_len
=
100
;
dev
->
tx_queue_len
=
100
;
...
@@ -2670,6 +2701,42 @@ static int reset_card( struct net_device *dev , int lock) {
...
@@ -2670,6 +2701,42 @@ static int reset_card( struct net_device *dev , int lock) {
return
0
;
return
0
;
}
}
#define MAX_NETWORK_COUNT 64
static
int
airo_networks_allocate
(
struct
airo_info
*
ai
)
{
if
(
ai
->
networks
)
return
0
;
ai
->
networks
=
kzalloc
(
MAX_NETWORK_COUNT
*
sizeof
(
BSSListElement
),
GFP_KERNEL
);
if
(
!
ai
->
networks
)
{
airo_print_warn
(
ai
->
dev
->
name
,
"Out of memory allocating beacons"
);
return
-
ENOMEM
;
}
return
0
;
}
static
void
airo_networks_free
(
struct
airo_info
*
ai
)
{
if
(
!
ai
->
networks
)
return
;
kfree
(
ai
->
networks
);
ai
->
networks
=
NULL
;
}
static
void
airo_networks_initialize
(
struct
airo_info
*
ai
)
{
int
i
;
INIT_LIST_HEAD
(
&
ai
->
network_free_list
);
INIT_LIST_HEAD
(
&
ai
->
network_list
);
for
(
i
=
0
;
i
<
MAX_NETWORK_COUNT
;
i
++
)
list_add_tail
(
&
ai
->
networks
[
i
].
list
,
&
ai
->
network_free_list
);
}
static
struct
net_device
*
_init_airo_card
(
unsigned
short
irq
,
int
port
,
static
struct
net_device
*
_init_airo_card
(
unsigned
short
irq
,
int
port
,
int
is_pcmcia
,
struct
pci_dev
*
pci
,
int
is_pcmcia
,
struct
pci_dev
*
pci
,
struct
device
*
dmdev
)
struct
device
*
dmdev
)
...
@@ -2681,22 +2748,22 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
...
@@ -2681,22 +2748,22 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
/* Create the network device object. */
/* Create the network device object. */
dev
=
alloc_etherdev
(
sizeof
(
*
ai
));
dev
=
alloc_etherdev
(
sizeof
(
*
ai
));
if
(
!
dev
)
{
if
(
!
dev
)
{
printk
(
KERN_ERR
"airo: Couldn't alloc_etherdev
\n
"
);
airo_print_err
(
""
,
"Couldn't alloc_etherdev
"
);
return
NULL
;
return
NULL
;
}
}
if
(
dev_alloc_name
(
dev
,
dev
->
name
)
<
0
)
{
if
(
dev_alloc_name
(
dev
,
dev
->
name
)
<
0
)
{
printk
(
KERN_ERR
"airo: Couldn't get name!
\n
"
);
airo_print_err
(
""
,
"Couldn't get name!
"
);
goto
err_out_free
;
goto
err_out_free
;
}
}
ai
=
dev
->
priv
;
ai
=
dev
->
priv
;
ai
->
wifidev
=
NULL
;
ai
->
wifidev
=
NULL
;
ai
->
flags
=
0
;
ai
->
flags
=
0
;
ai
->
dev
=
dev
;
if
(
pci
&&
(
pci
->
device
==
0x5000
||
pci
->
device
==
0xa504
))
{
if
(
pci
&&
(
pci
->
device
==
0x5000
||
pci
->
device
==
0xa504
))
{
printk
(
KERN_DEBUG
"airo: Found an MPI350 card
\n
"
);
airo_print_dbg
(
dev
->
name
,
"Found an MPI350 card
"
);
set_bit
(
FLAG_MPI
,
&
ai
->
flags
);
set_bit
(
FLAG_MPI
,
&
ai
->
flags
);
}
}
ai
->
dev
=
dev
;
spin_lock_init
(
&
ai
->
aux_lock
);
spin_lock_init
(
&
ai
->
aux_lock
);
sema_init
(
&
ai
->
sem
,
1
);
sema_init
(
&
ai
->
sem
,
1
);
ai
->
config
.
len
=
0
;
ai
->
config
.
len
=
0
;
...
@@ -2711,6 +2778,10 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
...
@@ -2711,6 +2778,10 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
if
(
rc
)
if
(
rc
)
goto
err_out_thr
;
goto
err_out_thr
;
if
(
airo_networks_allocate
(
ai
))
goto
err_out_unlink
;
airo_networks_initialize
(
ai
);
/* The Airo-specific entries in the device structure. */
/* The Airo-specific entries in the device structure. */
if
(
test_bit
(
FLAG_MPI
,
&
ai
->
flags
))
{
if
(
test_bit
(
FLAG_MPI
,
&
ai
->
flags
))
{
skb_queue_head_init
(
&
ai
->
txq
);
skb_queue_head_init
(
&
ai
->
txq
);
...
@@ -2732,33 +2803,33 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
...
@@ -2732,33 +2803,33 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
SET_NETDEV_DEV
(
dev
,
dmdev
);
SET_NETDEV_DEV
(
dev
,
dmdev
);
reset_card
(
dev
,
1
);
reset_card
(
dev
,
1
);
msleep
(
400
);
msleep
(
400
);
rc
=
request_irq
(
dev
->
irq
,
airo_interrupt
,
SA_SHIRQ
,
dev
->
name
,
dev
);
rc
=
request_irq
(
dev
->
irq
,
airo_interrupt
,
SA_SHIRQ
,
dev
->
name
,
dev
);
if
(
rc
)
{
if
(
rc
)
{
printk
(
KERN_ERR
"airo: register interrupt %d failed, rc %d
\n
"
,
irq
,
rc
);
airo_print_err
(
dev
->
name
,
"register interrupt %d failed, rc %d"
,
irq
,
rc
);
goto
err_out_unlink
;
goto
err_out_unlink
;
}
}
if
(
!
is_pcmcia
)
{
if
(
!
is_pcmcia
)
{
if
(
!
request_region
(
dev
->
base_addr
,
64
,
dev
->
name
))
{
if
(
!
request_region
(
dev
->
base_addr
,
64
,
dev
->
name
))
{
rc
=
-
EBUSY
;
rc
=
-
EBUSY
;
printk
(
KERN_ERR
"airo: Couldn't request region
\
n
"
);
airo_print_err
(
dev
->
name
,
"Couldn't request regio
n"
);
goto
err_out_irq
;
goto
err_out_irq
;
}
}
}
}
if
(
test_bit
(
FLAG_MPI
,
&
ai
->
flags
))
{
if
(
test_bit
(
FLAG_MPI
,
&
ai
->
flags
))
{
if
(
mpi_map_card
(
ai
,
pci
,
dev
->
name
))
{
if
(
mpi_map_card
(
ai
,
pci
,
dev
->
name
))
{
printk
(
KERN_ERR
"airo: Could not map memory
\n
"
);
airo_print_err
(
dev
->
name
,
"Could not map memory
"
);
goto
err_out_res
;
goto
err_out_res
;
}
}
}
}
if
(
probe
)
{
if
(
probe
)
{
if
(
setup_card
(
ai
,
dev
->
dev_addr
,
1
)
!=
SUCCESS
)
{
if
(
setup_card
(
ai
,
dev
->
dev_addr
,
1
)
!=
SUCCESS
)
{
printk
(
KERN_ERR
"airo: MAC could not be enabled
\n
"
);
airo_print_err
(
dev
->
name
,
"MAC could not be enabled
"
);
rc
=
-
EIO
;
rc
=
-
EIO
;
goto
err_out_map
;
goto
err_out_map
;
}
}
...
@@ -2769,21 +2840,20 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
...
@@ -2769,21 +2840,20 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
rc
=
register_netdev
(
dev
);
rc
=
register_netdev
(
dev
);
if
(
rc
)
{
if
(
rc
)
{
printk
(
KERN_ERR
"airo: Couldn't register_netdev
\n
"
);
airo_print_err
(
dev
->
name
,
"Couldn't register_netdev
"
);
goto
err_out_map
;
goto
err_out_map
;
}
}
ai
->
wifidev
=
init_wifidev
(
ai
,
dev
);
ai
->
wifidev
=
init_wifidev
(
ai
,
dev
);
set_bit
(
FLAG_REGISTERED
,
&
ai
->
flags
);
set_bit
(
FLAG_REGISTERED
,
&
ai
->
flags
);
printk
(
KERN_INFO
"airo: MAC enabled %s %x:%x:%x:%x:%x:%x
\n
"
,
airo_print_info
(
dev
->
name
,
"MAC enabled %x:%x:%x:%x:%x:%x"
,
dev
->
name
,
dev
->
dev_addr
[
0
],
dev
->
dev_addr
[
1
],
dev
->
dev_addr
[
2
],
dev
->
dev_addr
[
0
],
dev
->
dev_addr
[
1
],
dev
->
dev_addr
[
2
],
dev
->
dev_addr
[
3
],
dev
->
dev_addr
[
4
],
dev
->
dev_addr
[
5
]
);
dev
->
dev_addr
[
3
],
dev
->
dev_addr
[
4
],
dev
->
dev_addr
[
5
]
);
/* Allocate the transmit buffers */
/* Allocate the transmit buffers */
if
(
probe
&&
!
test_bit
(
FLAG_MPI
,
&
ai
->
flags
))
if
(
probe
&&
!
test_bit
(
FLAG_MPI
,
&
ai
->
flags
))
for
(
i
=
0
;
i
<
MAX_FIDS
;
i
++
)
for
(
i
=
0
;
i
<
MAX_FIDS
;
i
++
)
ai
->
fids
[
i
]
=
transmit_allocate
(
ai
,
2312
,
i
>=
MAX_FIDS
/
2
);
ai
->
fids
[
i
]
=
transmit_allocate
(
ai
,
AIRO_DEF_MTU
,
i
>=
MAX_FIDS
/
2
);
setup_proc_entry
(
dev
,
dev
->
priv
);
/* XXX check for failure */
setup_proc_entry
(
dev
,
dev
->
priv
);
/* XXX check for failure */
netif_start_queue
(
dev
);
netif_start_queue
(
dev
);
...
@@ -2840,16 +2910,16 @@ int reset_airo_card( struct net_device *dev )
...
@@ -2840,16 +2910,16 @@ int reset_airo_card( struct net_device *dev )
return
-
1
;
return
-
1
;
if
(
setup_card
(
ai
,
dev
->
dev_addr
,
1
)
!=
SUCCESS
)
{
if
(
setup_card
(
ai
,
dev
->
dev_addr
,
1
)
!=
SUCCESS
)
{
printk
(
KERN_ERR
"airo: MAC could not be enabled
\n
"
);
airo_print_err
(
dev
->
name
,
"MAC could not be enabled"
);
return
-
1
;
return
-
1
;
}
}
printk
(
KERN_INFO
"airo: MAC enabled %s %x:%x:%x:%x:%x:%x
\n
"
,
dev
->
name
,
airo_print_info
(
dev
->
name
,
"MAC enabled %x:%x:%x:%x:%x:%x"
,
dev
->
dev_addr
[
0
],
dev
->
dev_addr
[
1
],
dev
->
dev_addr
[
2
],
dev
->
dev_addr
[
0
],
dev
->
dev_addr
[
1
],
dev
->
dev_addr
[
2
],
dev
->
dev_addr
[
3
],
dev
->
dev_addr
[
4
],
dev
->
dev_addr
[
5
]);
dev
->
dev_addr
[
3
],
dev
->
dev_addr
[
4
],
dev
->
dev_addr
[
5
]);
/* Allocate the transmit buffers if needed */
/* Allocate the transmit buffers if needed */
if
(
!
test_bit
(
FLAG_MPI
,
&
ai
->
flags
))
if
(
!
test_bit
(
FLAG_MPI
,
&
ai
->
flags
))
for
(
i
=
0
;
i
<
MAX_FIDS
;
i
++
)
for
(
i
=
0
;
i
<
MAX_FIDS
;
i
++
)
ai
->
fids
[
i
]
=
transmit_allocate
(
ai
,
2312
,
i
>=
MAX_FIDS
/
2
);
ai
->
fids
[
i
]
=
transmit_allocate
(
ai
,
AIRO_DEF_MTU
,
i
>=
MAX_FIDS
/
2
);
enable_interrupts
(
ai
);
enable_interrupts
(
ai
);
netif_wake_queue
(
dev
);
netif_wake_queue
(
dev
);
...
@@ -2875,6 +2945,65 @@ static void airo_send_event(struct net_device *dev) {
...
@@ -2875,6 +2945,65 @@ static void airo_send_event(struct net_device *dev) {
wireless_send_event
(
dev
,
SIOCGIWAP
,
&
wrqu
,
NULL
);
wireless_send_event
(
dev
,
SIOCGIWAP
,
&
wrqu
,
NULL
);
}
}
static
void
airo_process_scan_results
(
struct
airo_info
*
ai
)
{
union
iwreq_data
wrqu
;
BSSListRid
BSSList
;
int
rc
;
BSSListElement
*
loop_net
;
BSSListElement
*
tmp_net
;
/* Blow away current list of scan results */
list_for_each_entry_safe
(
loop_net
,
tmp_net
,
&
ai
->
network_list
,
list
)
{
list_move_tail
(
&
loop_net
->
list
,
&
ai
->
network_free_list
);
/* Don't blow away ->list, just BSS data */
memset
(
loop_net
,
0
,
sizeof
(
loop_net
->
bss
));
}
/* Try to read the first entry of the scan result */
rc
=
PC4500_readrid
(
ai
,
RID_BSSLISTFIRST
,
&
BSSList
,
sizeof
(
BSSList
),
0
);
if
((
rc
)
||
(
BSSList
.
index
==
0xffff
))
{
/* No scan results */
goto
out
;
}
/* Read and parse all entries */
tmp_net
=
NULL
;
while
((
!
rc
)
&&
(
BSSList
.
index
!=
0xffff
))
{
/* Grab a network off the free list */
if
(
!
list_empty
(
&
ai
->
network_free_list
))
{
tmp_net
=
list_entry
(
ai
->
network_free_list
.
next
,
BSSListElement
,
list
);
list_del
(
ai
->
network_free_list
.
next
);
}
if
(
tmp_net
!=
NULL
)
{
memcpy
(
tmp_net
,
&
BSSList
,
sizeof
(
tmp_net
->
bss
));
list_add_tail
(
&
tmp_net
->
list
,
&
ai
->
network_list
);
tmp_net
=
NULL
;
}
/* Read next entry */
rc
=
PC4500_readrid
(
ai
,
RID_BSSLISTNEXT
,
&
BSSList
,
sizeof
(
BSSList
),
0
);
}
out:
ai
->
scan_timeout
=
0
;
clear_bit
(
JOB_SCAN_RESULTS
,
&
ai
->
flags
);
up
(
&
ai
->
sem
);
/* Send an empty event to user space.
* We don't send the received data on
* the event because it would require
* us to do complex transcoding, and
* we want to minimise the work done in
* the irq handler. Use a request to
* extract the data - Jean II */
wrqu
.
data
.
length
=
0
;
wrqu
.
data
.
flags
=
0
;
wireless_send_event
(
ai
->
dev
,
SIOCGIWSCAN
,
&
wrqu
,
NULL
);
}
static
int
airo_thread
(
void
*
data
)
{
static
int
airo_thread
(
void
*
data
)
{
struct
net_device
*
dev
=
data
;
struct
net_device
*
dev
=
data
;
struct
airo_info
*
ai
=
dev
->
priv
;
struct
airo_info
*
ai
=
dev
->
priv
;
...
@@ -2904,13 +3033,26 @@ static int airo_thread(void *data) {
...
@@ -2904,13 +3033,26 @@ static int airo_thread(void *data) {
set_current_state
(
TASK_INTERRUPTIBLE
);
set_current_state
(
TASK_INTERRUPTIBLE
);
if
(
ai
->
flags
&
JOB_MASK
)
if
(
ai
->
flags
&
JOB_MASK
)
break
;
break
;
if
(
ai
->
expires
)
{
if
(
ai
->
expires
||
ai
->
scan_timeout
)
{
if
(
time_after_eq
(
jiffies
,
ai
->
expires
)){
if
(
ai
->
scan_timeout
&&
time_after_eq
(
jiffies
,
ai
->
scan_timeout
)){
set_bit
(
JOB_SCAN_RESULTS
,
&
ai
->
flags
);
break
;
}
else
if
(
ai
->
expires
&&
time_after_eq
(
jiffies
,
ai
->
expires
)){
set_bit
(
JOB_AUTOWEP
,
&
ai
->
flags
);
set_bit
(
JOB_AUTOWEP
,
&
ai
->
flags
);
break
;
break
;
}
}
if
(
!
signal_pending
(
current
))
{
if
(
!
signal_pending
(
current
))
{
schedule_timeout
(
ai
->
expires
-
jiffies
);
unsigned
long
wake_at
;
if
(
!
ai
->
expires
||
!
ai
->
scan_timeout
)
{
wake_at
=
max
(
ai
->
expires
,
ai
->
scan_timeout
);
}
else
{
wake_at
=
min
(
ai
->
expires
,
ai
->
scan_timeout
);
}
schedule_timeout
(
wake_at
-
jiffies
);
continue
;
continue
;
}
}
}
else
if
(
!
signal_pending
(
current
))
{
}
else
if
(
!
signal_pending
(
current
))
{
...
@@ -2953,6 +3095,10 @@ static int airo_thread(void *data) {
...
@@ -2953,6 +3095,10 @@ static int airo_thread(void *data) {
airo_send_event
(
dev
);
airo_send_event
(
dev
);
else
if
(
test_bit
(
JOB_AUTOWEP
,
&
ai
->
flags
))
else
if
(
test_bit
(
JOB_AUTOWEP
,
&
ai
->
flags
))
timer_func
(
dev
);
timer_func
(
dev
);
else
if
(
test_bit
(
JOB_SCAN_RESULTS
,
&
ai
->
flags
))
airo_process_scan_results
(
ai
);
else
/* Shouldn't get here, but we make sure to unlock */
up
(
&
ai
->
sem
);
}
}
complete_and_exit
(
&
ai
->
thr_exited
,
0
);
complete_and_exit
(
&
ai
->
thr_exited
,
0
);
}
}
...
@@ -3047,19 +3193,15 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
...
@@ -3047,19 +3193,15 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
* and reassociations as valid status
* and reassociations as valid status
* Jean II */
* Jean II */
if
(
newStatus
==
ASSOCIATED
)
{
if
(
newStatus
==
ASSOCIATED
)
{
if
(
apriv
->
scan_timestamp
)
{
#if 0
/* Send an empty event to user space.
/* FIXME: Grabbing scan results here
* We don't send the received data on
* seems to be too early??? Just wait for
* the event because it would require
* timeout instead. */
* us to do complex transcoding, and
if (apriv->scan_timeout > 0) {
* we want to minimise the work done in
set_bit(JOB_SCAN_RESULTS, &apriv->flags);
* the irq handler. Use a request to
wake_up_interruptible(&apriv->thr_wait);
* extract the data - Jean II */
wrqu
.
data
.
length
=
0
;
wrqu
.
data
.
flags
=
0
;
wireless_send_event
(
dev
,
SIOCGIWSCAN
,
&
wrqu
,
NULL
);
apriv
->
scan_timestamp
=
0
;
}
}
#endif
if
(
down_trylock
(
&
apriv
->
sem
)
!=
0
)
{
if
(
down_trylock
(
&
apriv
->
sem
)
!=
0
)
{
set_bit
(
JOB_EVENT
,
&
apriv
->
flags
);
set_bit
(
JOB_EVENT
,
&
apriv
->
flags
);
wake_up_interruptible
(
&
apriv
->
thr_wait
);
wake_up_interruptible
(
&
apriv
->
thr_wait
);
...
@@ -3117,8 +3259,8 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
...
@@ -3117,8 +3259,8 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
}
}
len
=
le16_to_cpu
(
hdr
.
len
);
len
=
le16_to_cpu
(
hdr
.
len
);
if
(
len
>
2312
)
{
if
(
len
>
AIRO_DEF_MTU
)
{
printk
(
KERN_ERR
"airo: Bad size %d
\n
"
,
len
);
airo_print_err
(
apriv
->
dev
->
name
,
"Bad size %d"
,
len
);
goto
badrx
;
goto
badrx
;
}
}
if
(
len
==
0
)
if
(
len
==
0
)
...
@@ -3161,10 +3303,12 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
...
@@ -3161,10 +3303,12 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
bap_read
(
apriv
,
&
gap
,
sizeof
(
gap
),
BAP0
);
bap_read
(
apriv
,
&
gap
,
sizeof
(
gap
),
BAP0
);
gap
=
le16_to_cpu
(
gap
);
gap
=
le16_to_cpu
(
gap
);
if
(
gap
)
{
if
(
gap
)
{
if
(
gap
<=
8
)
if
(
gap
<=
8
)
{
bap_read
(
apriv
,
tmpbuf
,
gap
,
BAP0
);
bap_read
(
apriv
,
tmpbuf
,
gap
,
BAP0
);
else
}
else
{
printk
(
KERN_ERR
"airo: gaplen too big. Problems will follow...
\n
"
);
airo_print_err
(
apriv
->
dev
->
name
,
"gaplen too "
"big. Problems will follow..."
);
}
}
}
bap_read
(
apriv
,
buffer
+
hdrlen
/
2
,
len
,
BAP0
);
bap_read
(
apriv
,
buffer
+
hdrlen
/
2
,
len
,
BAP0
);
}
else
{
}
else
{
...
@@ -3281,12 +3425,13 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
...
@@ -3281,12 +3425,13 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
}
}
}
else
{
}
else
{
OUT4500
(
apriv
,
EVACK
,
status
&
(
EV_TX
|
EV_TXCPY
|
EV_TXEXC
));
OUT4500
(
apriv
,
EVACK
,
status
&
(
EV_TX
|
EV_TXCPY
|
EV_TXEXC
));
printk
(
KERN_ERR
"airo: Unallocated FID was used to xmit
\n
"
);
airo_print_err
(
apriv
->
dev
->
name
,
"Unallocated FID was "
"used to xmit"
);
}
}
}
}
exittx:
exittx:
if
(
status
&
~
STATUS_INTS
&
~
IGNORE_INTS
)
if
(
status
&
~
STATUS_INTS
&
~
IGNORE_INTS
)
printk
(
KERN_WARNING
"airo: Got weird status %x
\n
"
,
airo_print_warn
(
apriv
->
dev
->
name
,
"Got weird status %x
"
,
status
&
~
STATUS_INTS
&
~
IGNORE_INTS
);
status
&
~
STATUS_INTS
&
~
IGNORE_INTS
);
}
}
...
@@ -3359,8 +3504,8 @@ static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ) {
...
@@ -3359,8 +3504,8 @@ static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ) {
up
(
&
ai
->
sem
);
up
(
&
ai
->
sem
);
if
(
rc
)
if
(
rc
)
printk
(
KERN_ERR
"%s: Cannot enable MAC, err=%d
\n
"
,
airo_print_err
(
ai
->
dev
->
name
,
"%s: Cannot enable MAC, err=%d
"
,
__FUNCTION__
,
rc
);
__FUNCTION__
,
rc
);
return
rc
;
return
rc
;
}
}
...
@@ -3489,8 +3634,8 @@ void mpi_receive_802_11 (struct airo_info *ai)
...
@@ -3489,8 +3634,8 @@ void mpi_receive_802_11 (struct airo_info *ai)
if
(
ai
->
wifidev
==
NULL
)
if
(
ai
->
wifidev
==
NULL
)
hdr
.
len
=
0
;
hdr
.
len
=
0
;
len
=
le16_to_cpu
(
hdr
.
len
);
len
=
le16_to_cpu
(
hdr
.
len
);
if
(
len
>
2312
)
{
if
(
len
>
AIRO_DEF_MTU
)
{
printk
(
KERN_ERR
"airo: Bad size %d
\n
"
,
len
);
airo_print_err
(
ai
->
dev
->
name
,
"Bad size %d"
,
len
);
goto
badrx
;
goto
badrx
;
}
}
if
(
len
==
0
)
if
(
len
==
0
)
...
@@ -3531,8 +3676,8 @@ void mpi_receive_802_11 (struct airo_info *ai)
...
@@ -3531,8 +3676,8 @@ void mpi_receive_802_11 (struct airo_info *ai)
if
(
gap
<=
8
)
if
(
gap
<=
8
)
ptr
+=
gap
;
ptr
+=
gap
;
else
else
printk
(
KERN_ERR
airo_print_err
(
ai
->
dev
->
name
,
"
airo: gaplen too big. Problems will follow...
\n
"
);
"
gaplen too big. Problems will follow...
"
);
}
}
memcpy
((
char
*
)
buffer
+
hdrlen
,
ptr
,
len
);
memcpy
((
char
*
)
buffer
+
hdrlen
,
ptr
,
len
);
ptr
+=
len
;
ptr
+=
len
;
...
@@ -3604,15 +3749,15 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
...
@@ -3604,15 +3749,15 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
if
(
issuecommand
(
ai
,
&
cmd
,
&
rsp
)
!=
SUCCESS
)
{
if
(
issuecommand
(
ai
,
&
cmd
,
&
rsp
)
!=
SUCCESS
)
{
if
(
lock
)
if
(
lock
)
up
(
&
ai
->
sem
);
up
(
&
ai
->
sem
);
printk
(
KERN_ERR
"airo: Error checking for AUX port
\n
"
);
airo_print_err
(
ai
->
dev
->
name
,
"Error checking for AUX port
"
);
return
ERROR
;
return
ERROR
;
}
}
if
(
!
aux_bap
||
rsp
.
status
&
0xff00
)
{
if
(
!
aux_bap
||
rsp
.
status
&
0xff00
)
{
ai
->
bap_read
=
fast_bap_read
;
ai
->
bap_read
=
fast_bap_read
;
printk
(
KERN_DEBUG
"airo: Doing fast bap_reads
\n
"
);
airo_print_dbg
(
ai
->
dev
->
name
,
"Doing fast bap_reads
"
);
}
else
{
}
else
{
ai
->
bap_read
=
aux_bap_read
;
ai
->
bap_read
=
aux_bap_read
;
printk
(
KERN_DEBUG
"airo: Doing AUX bap_reads
\n
"
);
airo_print_dbg
(
ai
->
dev
->
name
,
"Doing AUX bap_reads
"
);
}
}
}
}
if
(
lock
)
if
(
lock
)
...
@@ -3643,7 +3788,8 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
...
@@ -3643,7 +3788,8 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
if
(
cap_rid
.
softCap
&
8
)
if
(
cap_rid
.
softCap
&
8
)
ai
->
config
.
rmode
|=
RXMODE_NORMALIZED_RSSI
;
ai
->
config
.
rmode
|=
RXMODE_NORMALIZED_RSSI
;
else
else
printk
(
KERN_WARNING
"airo: unknown received signal level scale
\n
"
);
airo_print_warn
(
ai
->
dev
->
name
,
"unknown received signal "
"level scale"
);
}
}
ai
->
config
.
opmode
=
adhoc
?
MODE_STA_IBSS
:
MODE_STA_ESS
;
ai
->
config
.
opmode
=
adhoc
?
MODE_STA_IBSS
:
MODE_STA_ESS
;
ai
->
config
.
authType
=
AUTH_OPEN
;
ai
->
config
.
authType
=
AUTH_OPEN
;
...
@@ -3706,7 +3852,8 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
...
@@ -3706,7 +3852,8 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
status
=
enable_MAC
(
ai
,
&
rsp
,
lock
);
status
=
enable_MAC
(
ai
,
&
rsp
,
lock
);
if
(
status
!=
SUCCESS
||
(
rsp
.
status
&
0xFF00
)
!=
0
)
{
if
(
status
!=
SUCCESS
||
(
rsp
.
status
&
0xFF00
)
!=
0
)
{
printk
(
KERN_ERR
"airo: Bad MAC enable reason = %x, rid = %x, offset = %d
\n
"
,
rsp
.
rsp0
,
rsp
.
rsp1
,
rsp
.
rsp2
);
airo_print_err
(
ai
->
dev
->
name
,
"Bad MAC enable reason = %x, rid = %x,"
" offset = %d"
,
rsp
.
rsp0
,
rsp
.
rsp1
,
rsp
.
rsp2
);
return
ERROR
;
return
ERROR
;
}
}
...
@@ -3749,8 +3896,8 @@ static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) {
...
@@ -3749,8 +3896,8 @@ static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) {
}
}
if
(
max_tries
==
-
1
)
{
if
(
max_tries
==
-
1
)
{
printk
(
KERN_ERR
airo_print_err
(
ai
->
dev
->
name
,
"
airo: Max tries exceeded when issueing command
\n
"
);
"
Max tries exceeded when issueing command"
);
if
(
IN4500
(
ai
,
COMMAND
)
&
COMMAND_BUSY
)
if
(
IN4500
(
ai
,
COMMAND
)
&
COMMAND_BUSY
)
OUT4500
(
ai
,
EVACK
,
EV_CLEARCOMMANDBUSY
);
OUT4500
(
ai
,
EVACK
,
EV_CLEARCOMMANDBUSY
);
return
ERROR
;
return
ERROR
;
...
@@ -3762,11 +3909,11 @@ static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) {
...
@@ -3762,11 +3909,11 @@ static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) {
pRsp
->
rsp1
=
IN4500
(
ai
,
RESP1
);
pRsp
->
rsp1
=
IN4500
(
ai
,
RESP1
);
pRsp
->
rsp2
=
IN4500
(
ai
,
RESP2
);
pRsp
->
rsp2
=
IN4500
(
ai
,
RESP2
);
if
((
pRsp
->
status
&
0xff00
)
!=
0
&&
pCmd
->
cmd
!=
CMD_SOFTRESET
)
{
if
((
pRsp
->
status
&
0xff00
)
!=
0
&&
pCmd
->
cmd
!=
CMD_SOFTRESET
)
{
printk
(
KERN_ERR
"airo:
cmd= %x
\n
"
,
pCmd
->
cmd
);
airo_print_err
(
ai
->
dev
->
name
,
"
cmd= %x
\n
"
,
pCmd
->
cmd
);
printk
(
KERN_ERR
"airo:
status= %x
\n
"
,
pRsp
->
status
);
airo_print_err
(
ai
->
dev
->
name
,
"
status= %x
\n
"
,
pRsp
->
status
);
printk
(
KERN_ERR
"airo:
Rsp0= %x
\n
"
,
pRsp
->
rsp0
);
airo_print_err
(
ai
->
dev
->
name
,
"
Rsp0= %x
\n
"
,
pRsp
->
rsp0
);
printk
(
KERN_ERR
"airo:
Rsp1= %x
\n
"
,
pRsp
->
rsp1
);
airo_print_err
(
ai
->
dev
->
name
,
"
Rsp1= %x
\n
"
,
pRsp
->
rsp1
);
printk
(
KERN_ERR
"airo:
Rsp2= %x
\n
"
,
pRsp
->
rsp2
);
airo_print_err
(
ai
->
dev
->
name
,
"
Rsp2= %x
\n
"
,
pRsp
->
rsp2
);
}
}
// clear stuck command busy if necessary
// clear stuck command busy if necessary
...
@@ -3799,15 +3946,15 @@ static int bap_setup(struct airo_info *ai, u16 rid, u16 offset, int whichbap )
...
@@ -3799,15 +3946,15 @@ static int bap_setup(struct airo_info *ai, u16 rid, u16 offset, int whichbap )
}
}
}
else
if
(
status
&
BAP_ERR
)
{
}
else
if
(
status
&
BAP_ERR
)
{
/* invalid rid or offset */
/* invalid rid or offset */
printk
(
KERN_ERR
"airo: BAP error %x %d
\n
"
,
airo_print_err
(
ai
->
dev
->
name
,
"BAP error %x %d
"
,
status
,
whichbap
);
status
,
whichbap
);
return
ERROR
;
return
ERROR
;
}
else
if
(
status
&
BAP_DONE
)
{
// success
}
else
if
(
status
&
BAP_DONE
)
{
// success
return
SUCCESS
;
return
SUCCESS
;
}
}
if
(
!
(
max_tries
--
)
)
{
if
(
!
(
max_tries
--
)
)
{
printk
(
KERN_ERR
airo_print_err
(
ai
->
dev
->
name
,
"airo: BAP setup error too many retries
\n
"
);
"airo: BAP setup error too many retries
\n
"
);
return
ERROR
;
return
ERROR
;
}
}
// -- PC4500 missed it, try again
// -- PC4500 missed it, try again
...
@@ -3962,8 +4109,8 @@ static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len, in
...
@@ -3962,8 +4109,8 @@ static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len, in
len
=
min
(
len
,
(
int
)
le16_to_cpu
(
*
(
u16
*
)
pBuf
))
-
2
;
len
=
min
(
len
,
(
int
)
le16_to_cpu
(
*
(
u16
*
)
pBuf
))
-
2
;
if
(
len
<=
2
)
{
if
(
len
<=
2
)
{
printk
(
KERN_ERR
airo_print_err
(
ai
->
dev
->
name
,
"airo: Rid %x has a length of %d which is too short
\n
"
,
"Rid %x has a length of %d which is too short
"
,
(
int
)
rid
,
(
int
)
len
);
(
int
)
rid
,
(
int
)
len
);
rc
=
ERROR
;
rc
=
ERROR
;
goto
done
;
goto
done
;
...
@@ -3996,8 +4143,8 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
...
@@ -3996,8 +4143,8 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
Resp
rsp
;
Resp
rsp
;
if
(
test_bit
(
FLAG_ENABLED
,
&
ai
->
flags
)
&&
(
RID_WEP_TEMP
!=
rid
))
if
(
test_bit
(
FLAG_ENABLED
,
&
ai
->
flags
)
&&
(
RID_WEP_TEMP
!=
rid
))
printk
(
KERN_ERR
airo_print_err
(
ai
->
dev
->
name
,
"%s: MAC should be disabled (rid=%04x)
\n
"
,
"%s: MAC should be disabled (rid=%04x)"
,
__FUNCTION__
,
rid
);
__FUNCTION__
,
rid
);
memset
(
&
cmd
,
0
,
sizeof
(
cmd
));
memset
(
&
cmd
,
0
,
sizeof
(
cmd
));
memset
(
&
rsp
,
0
,
sizeof
(
rsp
));
memset
(
&
rsp
,
0
,
sizeof
(
rsp
));
...
@@ -4013,7 +4160,7 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
...
@@ -4013,7 +4160,7 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
&
ai
->
config_desc
.
rid_desc
,
sizeof
(
Rid
));
&
ai
->
config_desc
.
rid_desc
,
sizeof
(
Rid
));
if
(
len
<
4
||
len
>
2047
)
{
if
(
len
<
4
||
len
>
2047
)
{
printk
(
KERN_ERR
"%s: len=%d
\n
"
,
__FUNCTION__
,
len
);
airo_print_err
(
ai
->
dev
->
name
,
"%s: len=%d"
,
__FUNCTION__
,
len
);
rc
=
-
1
;
rc
=
-
1
;
}
else
{
}
else
{
memcpy
((
char
*
)
ai
->
config_desc
.
virtual_host_addr
,
memcpy
((
char
*
)
ai
->
config_desc
.
virtual_host_addr
,
...
@@ -4021,10 +4168,10 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
...
@@ -4021,10 +4168,10 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
rc
=
issuecommand
(
ai
,
&
cmd
,
&
rsp
);
rc
=
issuecommand
(
ai
,
&
cmd
,
&
rsp
);
if
((
rc
&
0xff00
)
!=
0
)
{
if
((
rc
&
0xff00
)
!=
0
)
{
printk
(
KERN_ERR
"%s: Write rid Error %d
\n
"
,
airo_print_err
(
ai
->
dev
->
name
,
"%s: Write rid Error %d
"
,
__FUNCTION__
,
rc
);
__FUNCTION__
,
rc
);
printk
(
KERN_ERR
"%s: Cmd=%04x
\n
"
,
airo_print_err
(
ai
->
dev
->
name
,
"%s: Cmd=%04x
"
,
__FUNCTION__
,
cmd
.
cmd
);
__FUNCTION__
,
cmd
.
cmd
);
}
}
if
((
rsp
.
status
&
0x7f00
))
if
((
rsp
.
status
&
0x7f00
))
...
@@ -4123,7 +4270,7 @@ static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket)
...
@@ -4123,7 +4270,7 @@ static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket)
len
>>=
16
;
len
>>=
16
;
if
(
len
<=
ETH_ALEN
*
2
)
{
if
(
len
<=
ETH_ALEN
*
2
)
{
printk
(
KERN_WARNING
"Short packet %d
\n
"
,
len
);
airo_print_warn
(
ai
->
dev
->
name
,
"Short packet %d"
,
len
);
return
ERROR
;
return
ERROR
;
}
}
len
-=
ETH_ALEN
*
2
;
len
-=
ETH_ALEN
*
2
;
...
@@ -4187,7 +4334,7 @@ static int transmit_802_11_packet(struct airo_info *ai, int len, char *pPacket)
...
@@ -4187,7 +4334,7 @@ static int transmit_802_11_packet(struct airo_info *ai, int len, char *pPacket)
}
}
if
(
len
<
hdrlen
)
{
if
(
len
<
hdrlen
)
{
printk
(
KERN_WARNING
"Short packet %d
\n
"
,
len
);
airo_print_warn
(
ai
->
dev
->
name
,
"Short packet %d"
,
len
);
return
ERROR
;
return
ERROR
;
}
}
...
@@ -4584,15 +4731,14 @@ static int proc_stats_rid_open( struct inode *inode,
...
@@ -4584,15 +4731,14 @@ static int proc_stats_rid_open( struct inode *inode,
i
*
4
<
stats
.
len
;
i
++
){
i
*
4
<
stats
.
len
;
i
++
){
if
(
!
statsLabels
[
i
])
continue
;
if
(
!
statsLabels
[
i
])
continue
;
if
(
j
+
strlen
(
statsLabels
[
i
])
+
16
>
4096
)
{
if
(
j
+
strlen
(
statsLabels
[
i
])
+
16
>
4096
)
{
printk
(
KERN_WARNING
airo_print_warn
(
apriv
->
dev
->
name
,
"
airo: Potentially disasterous buffer overflow averted!
\n
"
);
"
Potentially disasterous buffer overflow averted!
"
);
break
;
break
;
}
}
j
+=
sprintf
(
data
->
rbuffer
+
j
,
"%s: %u
\n
"
,
statsLabels
[
i
],
vals
[
i
]);
j
+=
sprintf
(
data
->
rbuffer
+
j
,
"%s: %u
\n
"
,
statsLabels
[
i
],
vals
[
i
]);
}
}
if
(
i
*
4
>=
stats
.
len
){
if
(
i
*
4
>=
stats
.
len
){
printk
(
KERN_WARNING
airo_print_warn
(
apriv
->
dev
->
name
,
"Got a short rid"
);
"airo: Got a short rid
\n
"
);
}
}
data
->
readlen
=
j
;
data
->
readlen
=
j
;
return
0
;
return
0
;
...
@@ -4754,7 +4900,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
...
@@ -4754,7 +4900,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
line
+=
14
;
line
+=
14
;
v
=
get_dec_u16
(
line
,
&
i
,
4
);
v
=
get_dec_u16
(
line
,
&
i
,
4
);
v
=
(
v
<
0
)
?
0
:
((
v
>
2312
)
?
2312
:
v
);
v
=
(
v
<
0
)
?
0
:
((
v
>
AIRO_DEF_MTU
)
?
AIRO_DEF_MTU
:
v
);
ai
->
config
.
rtsThres
=
(
u16
)
v
;
ai
->
config
.
rtsThres
=
(
u16
)
v
;
set_bit
(
FLAG_COMMIT
,
&
ai
->
flags
);
set_bit
(
FLAG_COMMIT
,
&
ai
->
flags
);
}
else
if
(
!
strncmp
(
line
,
"TXMSDULifetime: "
,
16
)
)
{
}
else
if
(
!
strncmp
(
line
,
"TXMSDULifetime: "
,
16
)
)
{
...
@@ -4788,7 +4934,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
...
@@ -4788,7 +4934,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
line
+=
15
;
line
+=
15
;
v
=
get_dec_u16
(
line
,
&
i
,
4
);
v
=
get_dec_u16
(
line
,
&
i
,
4
);
v
=
(
v
<
256
)
?
256
:
((
v
>
2312
)
?
2312
:
v
);
v
=
(
v
<
256
)
?
256
:
((
v
>
AIRO_DEF_MTU
)
?
AIRO_DEF_MTU
:
v
);
v
=
v
&
0xfffe
;
/* Make sure its even */
v
=
v
&
0xfffe
;
/* Make sure its even */
ai
->
config
.
fragThresh
=
(
u16
)
v
;
ai
->
config
.
fragThresh
=
(
u16
)
v
;
set_bit
(
FLAG_COMMIT
,
&
ai
->
flags
);
set_bit
(
FLAG_COMMIT
,
&
ai
->
flags
);
...
@@ -4798,8 +4944,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
...
@@ -4798,8 +4944,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
case
'd'
:
ai
->
config
.
modulation
=
MOD_DEFAULT
;
set_bit
(
FLAG_COMMIT
,
&
ai
->
flags
);
break
;
case
'd'
:
ai
->
config
.
modulation
=
MOD_DEFAULT
;
set_bit
(
FLAG_COMMIT
,
&
ai
->
flags
);
break
;
case
'c'
:
ai
->
config
.
modulation
=
MOD_CCK
;
set_bit
(
FLAG_COMMIT
,
&
ai
->
flags
);
break
;
case
'c'
:
ai
->
config
.
modulation
=
MOD_CCK
;
set_bit
(
FLAG_COMMIT
,
&
ai
->
flags
);
break
;
case
'm'
:
ai
->
config
.
modulation
=
MOD_MOK
;
set_bit
(
FLAG_COMMIT
,
&
ai
->
flags
);
break
;
case
'm'
:
ai
->
config
.
modulation
=
MOD_MOK
;
set_bit
(
FLAG_COMMIT
,
&
ai
->
flags
);
break
;
default:
default:
airo_print_warn
(
ai
->
dev
->
name
,
"Unknown modulation"
);
printk
(
KERN_WARNING
"airo: Unknown modulation
\n
"
);
}
}
}
else
if
(
!
strncmp
(
line
,
"Preamble: "
,
10
))
{
}
else
if
(
!
strncmp
(
line
,
"Preamble: "
,
10
))
{
line
+=
10
;
line
+=
10
;
...
@@ -4807,10 +4952,10 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
...
@@ -4807,10 +4952,10 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
case
'a'
:
ai
->
config
.
preamble
=
PREAMBLE_AUTO
;
set_bit
(
FLAG_COMMIT
,
&
ai
->
flags
);
break
;
case
'a'
:
ai
->
config
.
preamble
=
PREAMBLE_AUTO
;
set_bit
(
FLAG_COMMIT
,
&
ai
->
flags
);
break
;
case
'l'
:
ai
->
config
.
preamble
=
PREAMBLE_LONG
;
set_bit
(
FLAG_COMMIT
,
&
ai
->
flags
);
break
;
case
'l'
:
ai
->
config
.
preamble
=
PREAMBLE_LONG
;
set_bit
(
FLAG_COMMIT
,
&
ai
->
flags
);
break
;
case
's'
:
ai
->
config
.
preamble
=
PREAMBLE_SHORT
;
set_bit
(
FLAG_COMMIT
,
&
ai
->
flags
);
break
;
case
's'
:
ai
->
config
.
preamble
=
PREAMBLE_SHORT
;
set_bit
(
FLAG_COMMIT
,
&
ai
->
flags
);
break
;
default:
printk
(
KERN_WARNING
"airo: Unknown preamble
\n
"
);
default:
airo_print_warn
(
ai
->
dev
->
name
,
"Unknown preamble
"
);
}
}
}
else
{
}
else
{
printk
(
KERN_WARNING
"Couldn't figure out %s
\n
"
,
line
);
airo_print_warn
(
ai
->
dev
->
name
,
"Couldn't figure out %s"
,
line
);
}
}
while
(
line
[
0
]
&&
line
[
0
]
!=
'\n'
)
line
++
;
while
(
line
[
0
]
&&
line
[
0
]
!=
'\n'
)
line
++
;
if
(
line
[
0
]
)
line
++
;
if
(
line
[
0
]
)
line
++
;
...
@@ -5076,7 +5221,7 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
...
@@ -5076,7 +5221,7 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
}
}
j
=
2
;
j
=
2
;
}
else
{
}
else
{
printk
(
KERN_ERR
"airo: WepKey passed invalid key index
\n
"
);
airo_print_err
(
ai
->
dev
->
name
,
"WepKey passed invalid key index
"
);
return
;
return
;
}
}
...
@@ -5489,17 +5634,16 @@ static int __init airo_init_module( void )
...
@@ -5489,17 +5634,16 @@ static int __init airo_init_module( void )
airo_entry
->
gid
=
proc_gid
;
airo_entry
->
gid
=
proc_gid
;
for
(
i
=
0
;
i
<
4
&&
io
[
i
]
&&
irq
[
i
];
i
++
)
{
for
(
i
=
0
;
i
<
4
&&
io
[
i
]
&&
irq
[
i
];
i
++
)
{
printk
(
KERN_INFO
airo_print_info
(
""
,
"Trying to configure ISA adapter at irq=%d "
"airo: Trying to configure ISA adapter at irq=%d io=0x%x
\n
"
,
"io=0x%x"
,
irq
[
i
],
io
[
i
]
);
irq
[
i
],
io
[
i
]
);
if
(
init_airo_card
(
irq
[
i
],
io
[
i
],
0
,
NULL
))
if
(
init_airo_card
(
irq
[
i
],
io
[
i
],
0
,
NULL
))
have_isa_dev
=
1
;
have_isa_dev
=
1
;
}
}
#ifdef CONFIG_PCI
#ifdef CONFIG_PCI
printk
(
KERN_INFO
"airo: Probing for PCI adapters
\n
"
);
airo_print_info
(
""
,
"Probing for PCI adapters"
);
pci_register_driver
(
&
airo_driver
);
pci_register_driver
(
&
airo_driver
);
printk
(
KERN_INFO
"airo: Finished probing for PCI adapters
\n
"
);
airo_print_info
(
""
,
"Finished probing for PCI adapters"
);
#endif
#endif
/* Always exit with success, as we are a library module
/* Always exit with success, as we are a library module
...
@@ -5511,7 +5655,7 @@ static int __init airo_init_module( void )
...
@@ -5511,7 +5655,7 @@ static int __init airo_init_module( void )
static
void
__exit
airo_cleanup_module
(
void
)
static
void
__exit
airo_cleanup_module
(
void
)
{
{
while
(
airo_devices
)
{
while
(
airo_devices
)
{
printk
(
KERN_INFO
"airo: Unregistering %s
\n
"
,
airo_devices
->
dev
->
name
);
airo_print_info
(
airo_devices
->
dev
->
name
,
"Unregistering...
\n
"
);
stop_airo_card
(
airo_devices
->
dev
,
1
);
stop_airo_card
(
airo_devices
->
dev
,
1
);
}
}
#ifdef CONFIG_PCI
#ifdef CONFIG_PCI
...
@@ -5622,7 +5766,8 @@ static int airo_set_freq(struct net_device *dev,
...
@@ -5622,7 +5766,8 @@ static int airo_set_freq(struct net_device *dev,
/* We should do a better check than that,
/* We should do a better check than that,
* based on the card capability !!! */
* based on the card capability !!! */
if
((
channel
<
1
)
||
(
channel
>
14
))
{
if
((
channel
<
1
)
||
(
channel
>
14
))
{
printk
(
KERN_DEBUG
"%s: New channel value of %d is invalid!
\n
"
,
dev
->
name
,
fwrq
->
m
);
airo_print_dbg
(
dev
->
name
,
"New channel value of %d is invalid!"
,
fwrq
->
m
);
rc
=
-
EINVAL
;
rc
=
-
EINVAL
;
}
else
{
}
else
{
readConfigRid
(
local
,
1
);
readConfigRid
(
local
,
1
);
...
@@ -5946,8 +6091,8 @@ static int airo_set_rts(struct net_device *dev,
...
@@ -5946,8 +6091,8 @@ static int airo_set_rts(struct net_device *dev,
int
rthr
=
vwrq
->
value
;
int
rthr
=
vwrq
->
value
;
if
(
vwrq
->
disabled
)
if
(
vwrq
->
disabled
)
rthr
=
2312
;
rthr
=
AIRO_DEF_MTU
;
if
((
rthr
<
0
)
||
(
rthr
>
2312
))
{
if
((
rthr
<
0
)
||
(
rthr
>
AIRO_DEF_MTU
))
{
return
-
EINVAL
;
return
-
EINVAL
;
}
}
readConfigRid
(
local
,
1
);
readConfigRid
(
local
,
1
);
...
@@ -5970,7 +6115,7 @@ static int airo_get_rts(struct net_device *dev,
...
@@ -5970,7 +6115,7 @@ static int airo_get_rts(struct net_device *dev,
readConfigRid
(
local
,
1
);
readConfigRid
(
local
,
1
);
vwrq
->
value
=
local
->
config
.
rtsThres
;
vwrq
->
value
=
local
->
config
.
rtsThres
;
vwrq
->
disabled
=
(
vwrq
->
value
>=
2312
);
vwrq
->
disabled
=
(
vwrq
->
value
>=
AIRO_DEF_MTU
);
vwrq
->
fixed
=
1
;
vwrq
->
fixed
=
1
;
return
0
;
return
0
;
...
@@ -5989,8 +6134,8 @@ static int airo_set_frag(struct net_device *dev,
...
@@ -5989,8 +6134,8 @@ static int airo_set_frag(struct net_device *dev,
int
fthr
=
vwrq
->
value
;
int
fthr
=
vwrq
->
value
;
if
(
vwrq
->
disabled
)
if
(
vwrq
->
disabled
)
fthr
=
2312
;
fthr
=
AIRO_DEF_MTU
;
if
((
fthr
<
256
)
||
(
fthr
>
2312
))
{
if
((
fthr
<
256
)
||
(
fthr
>
AIRO_DEF_MTU
))
{
return
-
EINVAL
;
return
-
EINVAL
;
}
}
fthr
&=
~
0x1
;
/* Get an even value - is it really needed ??? */
fthr
&=
~
0x1
;
/* Get an even value - is it really needed ??? */
...
@@ -6014,7 +6159,7 @@ static int airo_get_frag(struct net_device *dev,
...
@@ -6014,7 +6159,7 @@ static int airo_get_frag(struct net_device *dev,
readConfigRid
(
local
,
1
);
readConfigRid
(
local
,
1
);
vwrq
->
value
=
local
->
config
.
fragThresh
;
vwrq
->
value
=
local
->
config
.
fragThresh
;
vwrq
->
disabled
=
(
vwrq
->
value
>=
2312
);
vwrq
->
disabled
=
(
vwrq
->
value
>=
AIRO_DEF_MTU
);
vwrq
->
fixed
=
1
;
vwrq
->
fixed
=
1
;
return
0
;
return
0
;
...
@@ -6709,9 +6854,9 @@ static int airo_get_range(struct net_device *dev,
...
@@ -6709,9 +6854,9 @@ static int airo_get_range(struct net_device *dev,
range
->
throughput
=
1500
*
1000
;
range
->
throughput
=
1500
*
1000
;
range
->
min_rts
=
0
;
range
->
min_rts
=
0
;
range
->
max_rts
=
2312
;
range
->
max_rts
=
AIRO_DEF_MTU
;
range
->
min_frag
=
256
;
range
->
min_frag
=
256
;
range
->
max_frag
=
2312
;
range
->
max_frag
=
AIRO_DEF_MTU
;
if
(
cap_rid
.
softCap
&
2
)
{
if
(
cap_rid
.
softCap
&
2
)
{
// WEP: RC4 40 bits
// WEP: RC4 40 bits
...
@@ -6972,6 +7117,7 @@ static int airo_set_scan(struct net_device *dev,
...
@@ -6972,6 +7117,7 @@ static int airo_set_scan(struct net_device *dev,
struct
airo_info
*
ai
=
dev
->
priv
;
struct
airo_info
*
ai
=
dev
->
priv
;
Cmd
cmd
;
Cmd
cmd
;
Resp
rsp
;
Resp
rsp
;
int
wake
=
0
;
/* Note : you may have realised that, as this is a SET operation,
/* Note : you may have realised that, as this is a SET operation,
* this is privileged and therefore a normal user can't
* this is privileged and therefore a normal user can't
...
@@ -6981,17 +7127,25 @@ static int airo_set_scan(struct net_device *dev,
...
@@ -6981,17 +7127,25 @@ static int airo_set_scan(struct net_device *dev,
* Jean II */
* Jean II */
if
(
ai
->
flags
&
FLAG_RADIO_MASK
)
return
-
ENETDOWN
;
if
(
ai
->
flags
&
FLAG_RADIO_MASK
)
return
-
ENETDOWN
;
if
(
down_interruptible
(
&
ai
->
sem
))
return
-
ERESTARTSYS
;
/* If there's already a scan in progress, don't
* trigger another one. */
if
(
ai
->
scan_timeout
>
0
)
goto
out
;
/* Initiate a scan command */
/* Initiate a scan command */
memset
(
&
cmd
,
0
,
sizeof
(
cmd
));
memset
(
&
cmd
,
0
,
sizeof
(
cmd
));
cmd
.
cmd
=
CMD_LISTBSS
;
cmd
.
cmd
=
CMD_LISTBSS
;
if
(
down_interruptible
(
&
ai
->
sem
))
return
-
ERESTARTSYS
;
issuecommand
(
ai
,
&
cmd
,
&
rsp
);
issuecommand
(
ai
,
&
cmd
,
&
rsp
);
ai
->
scan_timestamp
=
jiffies
;
ai
->
scan_timeout
=
RUN_AT
(
3
*
HZ
);
up
(
&
ai
->
sem
);
wake
=
1
;
/* At this point, just return to the user. */
out:
up
(
&
ai
->
sem
);
if
(
wake
)
wake_up_interruptible
(
&
ai
->
thr_wait
);
return
0
;
return
0
;
}
}
...
@@ -7111,59 +7265,38 @@ static int airo_get_scan(struct net_device *dev,
...
@@ -7111,59 +7265,38 @@ static int airo_get_scan(struct net_device *dev,
char
*
extra
)
char
*
extra
)
{
{
struct
airo_info
*
ai
=
dev
->
priv
;
struct
airo_info
*
ai
=
dev
->
priv
;
BSSList
Rid
BSSLis
t
;
BSSList
Element
*
ne
t
;
int
rc
;
int
err
=
0
;
char
*
current_ev
=
extra
;
char
*
current_ev
=
extra
;
/* When we are associated again, the scan has surely finished.
/* If a scan is in-progress, return -EAGAIN */
* Just in case, let's make sure enough time has elapsed since
if
(
ai
->
scan_timeout
>
0
)
* we started the scan. - Javier */
if
(
ai
->
scan_timestamp
&&
time_before
(
jiffies
,
ai
->
scan_timestamp
+
3
*
HZ
))
{
/* Important note : we don't want to block the caller
* until results are ready for various reasons.
* First, managing wait queues is complex and racy
* (there may be multiple simultaneous callers).
* Second, we grab some rtnetlink lock before comming
* here (in dev_ioctl()).
* Third, the caller can wait on the Wireless Event
* - Jean II */
return
-
EAGAIN
;
return
-
EAGAIN
;
}
ai
->
scan_timestamp
=
0
;
/* There's only a race with proc_BSSList_open(), but its
if
(
down_interruptible
(
&
ai
->
sem
))
* consequences are begnign. So I don't bother fixing it - Javier */
return
-
EAGAIN
;
/* Try to read the first entry of the scan result */
rc
=
PC4500_readrid
(
ai
,
RID_BSSLISTFIRST
,
&
BSSList
,
sizeof
(
BSSList
),
1
);
if
((
rc
)
||
(
BSSList
.
index
==
0xffff
))
{
/* Client error, no scan results...
* The caller need to restart the scan. */
return
-
ENODATA
;
}
/* Read and parse all entries */
list_for_each_entry
(
net
,
&
ai
->
network_list
,
list
)
{
while
((
!
rc
)
&&
(
BSSList
.
index
!=
0xffff
))
{
/* Translate to WE format this entry */
/* Translate to WE format this entry */
current_ev
=
airo_translate_scan
(
dev
,
current_ev
,
current_ev
=
airo_translate_scan
(
dev
,
current_ev
,
extra
+
dwrq
->
length
,
extra
+
dwrq
->
length
,
&
BSSList
);
&
net
->
bss
);
/* Check if there is space for one more entry */
/* Check if there is space for one more entry */
if
((
extra
+
dwrq
->
length
-
current_ev
)
<=
IW_EV_ADDR_LEN
)
{
if
((
extra
+
dwrq
->
length
-
current_ev
)
<=
IW_EV_ADDR_LEN
)
{
/* Ask user space to try again with a bigger buffer */
/* Ask user space to try again with a bigger buffer */
return
-
E2BIG
;
err
=
-
E2BIG
;
goto
out
;
}
}
/* Read next entry */
rc
=
PC4500_readrid
(
ai
,
RID_BSSLISTNEXT
,
&
BSSList
,
sizeof
(
BSSList
),
1
);
}
}
/* Length of data */
/* Length of data */
dwrq
->
length
=
(
current_ev
-
extra
);
dwrq
->
length
=
(
current_ev
-
extra
);
dwrq
->
flags
=
0
;
/* todo */
dwrq
->
flags
=
0
;
/* todo */
return
0
;
out:
up
(
&
ai
->
sem
);
return
err
;
}
}
/*------------------------------------------------------------------*/
/*------------------------------------------------------------------*/
...
@@ -7711,7 +7844,7 @@ static int cmdreset(struct airo_info *ai) {
...
@@ -7711,7 +7844,7 @@ static int cmdreset(struct airo_info *ai) {
disable_MAC
(
ai
,
1
);
disable_MAC
(
ai
,
1
);
if
(
!
waitbusy
(
ai
)){
if
(
!
waitbusy
(
ai
)){
printk
(
KERN_INFO
"Waitbusy hang before RESET
\n
"
);
airo_print_info
(
ai
->
dev
->
name
,
"Waitbusy hang before RESET
"
);
return
-
EBUSY
;
return
-
EBUSY
;
}
}
...
@@ -7720,7 +7853,7 @@ static int cmdreset(struct airo_info *ai) {
...
@@ -7720,7 +7853,7 @@ static int cmdreset(struct airo_info *ai) {
ssleep
(
1
);
/* WAS 600 12/7/00 */
ssleep
(
1
);
/* WAS 600 12/7/00 */
if
(
!
waitbusy
(
ai
)){
if
(
!
waitbusy
(
ai
)){
printk
(
KERN_INFO
"Waitbusy hang AFTER RESET
\n
"
);
airo_print_info
(
ai
->
dev
->
name
,
"Waitbusy hang AFTER RESET
"
);
return
-
EBUSY
;
return
-
EBUSY
;
}
}
return
0
;
return
0
;
...
@@ -7748,7 +7881,7 @@ static int setflashmode (struct airo_info *ai) {
...
@@ -7748,7 +7881,7 @@ static int setflashmode (struct airo_info *ai) {
if
(
!
waitbusy
(
ai
))
{
if
(
!
waitbusy
(
ai
))
{
clear_bit
(
FLAG_FLASHING
,
&
ai
->
flags
);
clear_bit
(
FLAG_FLASHING
,
&
ai
->
flags
);
printk
(
KERN_INFO
"Waitbusy hang after setflash mode
\n
"
);
airo_print_info
(
ai
->
dev
->
name
,
"Waitbusy hang after setflash mode
"
);
return
-
EIO
;
return
-
EIO
;
}
}
return
0
;
return
0
;
...
@@ -7777,7 +7910,7 @@ static int flashpchar(struct airo_info *ai,int byte,int dwelltime) {
...
@@ -7777,7 +7910,7 @@ static int flashpchar(struct airo_info *ai,int byte,int dwelltime) {
/* timeout for busy clear wait */
/* timeout for busy clear wait */
if
(
waittime
<=
0
){
if
(
waittime
<=
0
){
printk
(
KERN_INFO
"flash putchar busywait timeout!
\n
"
);
airo_print_info
(
ai
->
dev
->
name
,
"flash putchar busywait timeout!
"
);
return
-
EBUSY
;
return
-
EBUSY
;
}
}
...
@@ -7866,7 +7999,7 @@ static int flashrestart(struct airo_info *ai,struct net_device *dev){
...
@@ -7866,7 +7999,7 @@ static int flashrestart(struct airo_info *ai,struct net_device *dev){
if
(
!
test_bit
(
FLAG_MPI
,
&
ai
->
flags
))
if
(
!
test_bit
(
FLAG_MPI
,
&
ai
->
flags
))
for
(
i
=
0
;
i
<
MAX_FIDS
;
i
++
)
{
for
(
i
=
0
;
i
<
MAX_FIDS
;
i
++
)
{
ai
->
fids
[
i
]
=
transmit_allocate
ai
->
fids
[
i
]
=
transmit_allocate
(
ai
,
2312
,
i
>=
MAX_FIDS
/
2
);
(
ai
,
AIRO_DEF_MTU
,
i
>=
MAX_FIDS
/
2
);
}
}
ssleep
(
1
);
/* Added 12/7/00 */
ssleep
(
1
);
/* Added 12/7/00 */
...
...
drivers/net/wireless/hostap/hostap_ap.c
View file @
9b7c8489
...
@@ -3141,7 +3141,7 @@ int hostap_add_sta(struct ap_data *ap, u8 *sta_addr)
...
@@ -3141,7 +3141,7 @@ int hostap_add_sta(struct ap_data *ap, u8 *sta_addr)
if
(
ret
==
1
)
{
if
(
ret
==
1
)
{
sta
=
ap_add_sta
(
ap
,
sta_addr
);
sta
=
ap_add_sta
(
ap
,
sta_addr
);
if
(
!
sta
)
if
(
!
sta
)
ret
=
-
1
;
ret
urn
-
1
;
sta
->
flags
=
WLAN_STA_AUTH
|
WLAN_STA_ASSOC
;
sta
->
flags
=
WLAN_STA_AUTH
|
WLAN_STA_ASSOC
;
sta
->
ap
=
1
;
sta
->
ap
=
1
;
memset
(
sta
->
supported_rates
,
0
,
sizeof
(
sta
->
supported_rates
));
memset
(
sta
->
supported_rates
,
0
,
sizeof
(
sta
->
supported_rates
));
...
...
drivers/net/wireless/hostap/hostap_cs.c
View file @
9b7c8489
...
@@ -585,8 +585,6 @@ static int prism2_config(dev_link_t *link)
...
@@ -585,8 +585,6 @@ static int prism2_config(dev_link_t *link)
parse
=
kmalloc
(
sizeof
(
cisparse_t
),
GFP_KERNEL
);
parse
=
kmalloc
(
sizeof
(
cisparse_t
),
GFP_KERNEL
);
hw_priv
=
kmalloc
(
sizeof
(
*
hw_priv
),
GFP_KERNEL
);
hw_priv
=
kmalloc
(
sizeof
(
*
hw_priv
),
GFP_KERNEL
);
if
(
parse
==
NULL
||
hw_priv
==
NULL
)
{
if
(
parse
==
NULL
||
hw_priv
==
NULL
)
{
kfree
(
parse
);
kfree
(
hw_priv
);
ret
=
-
ENOMEM
;
ret
=
-
ENOMEM
;
goto
failed
;
goto
failed
;
}
}
...
...
drivers/net/wireless/hostap/hostap_hw.c
View file @
9b7c8489
...
@@ -928,15 +928,15 @@ static int hfa384x_set_rid(struct net_device *dev, u16 rid, void *buf, int len)
...
@@ -928,15 +928,15 @@ static int hfa384x_set_rid(struct net_device *dev, u16 rid, void *buf, int len)
res
=
hfa384x_cmd
(
dev
,
HFA384X_CMDCODE_ACCESS_WRITE
,
rid
,
NULL
,
NULL
);
res
=
hfa384x_cmd
(
dev
,
HFA384X_CMDCODE_ACCESS_WRITE
,
rid
,
NULL
,
NULL
);
up
(
&
local
->
rid_bap_sem
);
up
(
&
local
->
rid_bap_sem
);
if
(
res
)
{
if
(
res
)
{
printk
(
KERN_DEBUG
"%s: hfa384x_set_rid: CMDCODE_ACCESS_WRITE "
printk
(
KERN_DEBUG
"%s: hfa384x_set_rid: CMDCODE_ACCESS_WRITE "
"failed (res=%d, rid=%04x, len=%d)
\n
"
,
"failed (res=%d, rid=%04x, len=%d)
\n
"
,
dev
->
name
,
res
,
rid
,
len
);
dev
->
name
,
res
,
rid
,
len
);
return
res
;
}
if
(
res
==
-
ETIMEDOUT
)
if
(
res
==
-
ETIMEDOUT
)
prism2_hw_reset
(
dev
);
prism2_hw_reset
(
dev
);
}
return
res
;
return
res
;
}
}
...
...
drivers/net/wireless/hostap/hostap_ioctl.c
View file @
9b7c8489
...
@@ -3358,10 +3358,6 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
...
@@ -3358,10 +3358,6 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
if
(
ext
->
ext_flags
&
IW_ENCODE_EXT_SET_TX_KEY
)
{
if
(
ext
->
ext_flags
&
IW_ENCODE_EXT_SET_TX_KEY
)
{
if
(
!
sta_ptr
)
if
(
!
sta_ptr
)
local
->
tx_keyidx
=
i
;
local
->
tx_keyidx
=
i
;
else
if
(
i
)
{
ret
=
-
EINVAL
;
goto
done
;
}
}
}
...
...
drivers/net/wireless/hostap/hostap_pci.c
View file @
9b7c8489
...
@@ -307,7 +307,7 @@ static int prism2_pci_probe(struct pci_dev *pdev,
...
@@ -307,7 +307,7 @@ static int prism2_pci_probe(struct pci_dev *pdev,
memset
(
hw_priv
,
0
,
sizeof
(
*
hw_priv
));
memset
(
hw_priv
,
0
,
sizeof
(
*
hw_priv
));
if
(
pci_enable_device
(
pdev
))
if
(
pci_enable_device
(
pdev
))
return
-
EIO
;
goto
err_out_free
;
phymem
=
pci_resource_start
(
pdev
,
0
);
phymem
=
pci_resource_start
(
pdev
,
0
);
...
@@ -368,6 +368,8 @@ static int prism2_pci_probe(struct pci_dev *pdev,
...
@@ -368,6 +368,8 @@ static int prism2_pci_probe(struct pci_dev *pdev,
err_out_disable:
err_out_disable:
pci_disable_device
(
pdev
);
pci_disable_device
(
pdev
);
prism2_free_local_data
(
dev
);
prism2_free_local_data
(
dev
);
err_out_free:
kfree
(
hw_priv
);
kfree
(
hw_priv
);
return
-
ENODEV
;
return
-
ENODEV
;
...
...
drivers/net/wireless/hostap/hostap_plx.c
View file @
9b7c8489
...
@@ -368,7 +368,7 @@ static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len,
...
@@ -368,7 +368,7 @@ static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len,
switch
(
cis
[
pos
])
{
switch
(
cis
[
pos
])
{
case
CISTPL_CONFIG
:
case
CISTPL_CONFIG
:
if
(
cis
[
pos
+
1
]
<
1
)
if
(
cis
[
pos
+
1
]
<
2
)
goto
cis_error
;
goto
cis_error
;
rmsz
=
(
cis
[
pos
+
2
]
&
0x3c
)
>>
2
;
rmsz
=
(
cis
[
pos
+
2
]
&
0x3c
)
>>
2
;
rasz
=
cis
[
pos
+
2
]
&
0x03
;
rasz
=
cis
[
pos
+
2
]
&
0x03
;
...
@@ -390,7 +390,7 @@ static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len,
...
@@ -390,7 +390,7 @@ static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len,
break
;
break
;
case
CISTPL_MANFID
:
case
CISTPL_MANFID
:
if
(
cis
[
pos
+
1
]
<
4
)
if
(
cis
[
pos
+
1
]
<
5
)
goto
cis_error
;
goto
cis_error
;
manfid1
=
cis
[
pos
+
2
]
+
(
cis
[
pos
+
3
]
<<
8
);
manfid1
=
cis
[
pos
+
2
]
+
(
cis
[
pos
+
3
]
<<
8
);
manfid2
=
cis
[
pos
+
4
]
+
(
cis
[
pos
+
5
]
<<
8
);
manfid2
=
cis
[
pos
+
4
]
+
(
cis
[
pos
+
5
]
<<
8
);
...
@@ -452,7 +452,7 @@ static int prism2_plx_probe(struct pci_dev *pdev,
...
@@ -452,7 +452,7 @@ static int prism2_plx_probe(struct pci_dev *pdev,
memset
(
hw_priv
,
0
,
sizeof
(
*
hw_priv
));
memset
(
hw_priv
,
0
,
sizeof
(
*
hw_priv
));
if
(
pci_enable_device
(
pdev
))
if
(
pci_enable_device
(
pdev
))
return
-
EIO
;
goto
err_out_free
;
/* National Datacomm NCP130 based on TMD7160, not PLX9052. */
/* National Datacomm NCP130 based on TMD7160, not PLX9052. */
tmd7160
=
(
pdev
->
vendor
==
0x15e8
)
&&
(
pdev
->
device
==
0x0131
);
tmd7160
=
(
pdev
->
vendor
==
0x15e8
)
&&
(
pdev
->
device
==
0x0131
);
...
@@ -567,9 +567,6 @@ static int prism2_plx_probe(struct pci_dev *pdev,
...
@@ -567,9 +567,6 @@ static int prism2_plx_probe(struct pci_dev *pdev,
return
hostap_hw_ready
(
dev
);
return
hostap_hw_ready
(
dev
);
fail:
fail:
prism2_free_local_data
(
dev
);
kfree
(
hw_priv
);
if
(
irq_registered
&&
dev
)
if
(
irq_registered
&&
dev
)
free_irq
(
dev
->
irq
,
dev
);
free_irq
(
dev
->
irq
,
dev
);
...
@@ -577,6 +574,10 @@ static int prism2_plx_probe(struct pci_dev *pdev,
...
@@ -577,6 +574,10 @@ static int prism2_plx_probe(struct pci_dev *pdev,
iounmap
(
attr_mem
);
iounmap
(
attr_mem
);
pci_disable_device
(
pdev
);
pci_disable_device
(
pdev
);
prism2_free_local_data
(
dev
);
err_out_free:
kfree
(
hw_priv
);
return
-
ENODEV
;
return
-
ENODEV
;
}
}
...
...
include/linux/wireless.h
View file @
9b7c8489
/*
/*
* This file define a set of standard wireless extensions
* This file define a set of standard wireless extensions
*
*
* Version :
19 18.3.05
* Version :
20 17.2.06
*
*
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
* Copyright (c) 1997-200
5
Jean Tourrilhes, All Rights Reserved.
* Copyright (c) 1997-200
6
Jean Tourrilhes, All Rights Reserved.
*/
*/
#ifndef _LINUX_WIRELESS_H
#ifndef _LINUX_WIRELESS_H
...
@@ -80,7 +80,7 @@
...
@@ -80,7 +80,7 @@
* (there is some stuff that will be added in the future...)
* (there is some stuff that will be added in the future...)
* I just plan to increment with each new version.
* I just plan to increment with each new version.
*/
*/
#define WIRELESS_EXT
19
#define WIRELESS_EXT
20
/*
/*
* Changes :
* Changes :
...
@@ -204,6 +204,10 @@
...
@@ -204,6 +204,10 @@
* - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros
* - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros
* - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM
* - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM
* - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros
* - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros
*
* V19 to V20
* ----------
* - RtNetlink requests support (SET/GET)
*/
*/
/**************************** CONSTANTS ****************************/
/**************************** CONSTANTS ****************************/
...
...
include/net/iw_handler.h
View file @
9b7c8489
...
@@ -4,7 +4,7 @@
...
@@ -4,7 +4,7 @@
* Version : 7 18.3.05
* Version : 7 18.3.05
*
*
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
* Copyright (c) 2001-200
5
Jean Tourrilhes, All Rights Reserved.
* Copyright (c) 2001-200
6
Jean Tourrilhes, All Rights Reserved.
*/
*/
#ifndef _IW_HANDLER_H
#ifndef _IW_HANDLER_H
...
@@ -436,6 +436,16 @@ extern int dev_get_wireless_info(char * buffer, char **start, off_t offset,
...
@@ -436,6 +436,16 @@ extern int dev_get_wireless_info(char * buffer, char **start, off_t offset,
/* Handle IOCTLs, called in net/core/dev.c */
/* Handle IOCTLs, called in net/core/dev.c */
extern
int
wireless_process_ioctl
(
struct
ifreq
*
ifr
,
unsigned
int
cmd
);
extern
int
wireless_process_ioctl
(
struct
ifreq
*
ifr
,
unsigned
int
cmd
);
/* Handle RtNetlink requests, called in net/core/rtnetlink.c */
extern
int
wireless_rtnetlink_set
(
struct
net_device
*
dev
,
char
*
data
,
int
len
);
extern
int
wireless_rtnetlink_get
(
struct
net_device
*
dev
,
char
*
data
,
int
len
,
char
**
p_buf
,
int
*
p_len
);
/* Second : functions that may be called by driver modules */
/* Second : functions that may be called by driver modules */
/* Send a single event to user space */
/* Send a single event to user space */
...
...
net/core/rtnetlink.c
View file @
9b7c8489
...
@@ -51,6 +51,10 @@
...
@@ -51,6 +51,10 @@
#include <net/sock.h>
#include <net/sock.h>
#include <net/pkt_sched.h>
#include <net/pkt_sched.h>
#include <net/netlink.h>
#include <net/netlink.h>
#ifdef CONFIG_NET_WIRELESS_RTNETLINK
#include <linux/wireless.h>
#include <net/iw_handler.h>
#endif
/* CONFIG_NET_WIRELESS_RTNETLINK */
static
DEFINE_MUTEX
(
rtnl_mutex
);
static
DEFINE_MUTEX
(
rtnl_mutex
);
...
@@ -467,6 +471,17 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
...
@@ -467,6 +471,17 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
goto
out
;
goto
out
;
}
}
#ifdef CONFIG_NET_WIRELESS_RTNETLINK
if
(
ida
[
IFLA_WIRELESS
-
1
])
{
/* Call Wireless Extensions.
* Various stuff checked in there... */
err
=
wireless_rtnetlink_set
(
dev
,
RTA_DATA
(
ida
[
IFLA_WIRELESS
-
1
]),
ida
[
IFLA_WIRELESS
-
1
]
->
rta_len
);
if
(
err
)
goto
out
;
}
#endif
/* CONFIG_NET_WIRELESS_RTNETLINK */
err
=
0
;
err
=
0
;
out:
out:
...
@@ -477,6 +492,83 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
...
@@ -477,6 +492,83 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
return
err
;
return
err
;
}
}
#ifdef CONFIG_NET_WIRELESS_RTNETLINK
static
int
do_getlink
(
struct
sk_buff
*
in_skb
,
struct
nlmsghdr
*
in_nlh
,
void
*
arg
)
{
struct
ifinfomsg
*
ifm
=
NLMSG_DATA
(
in_nlh
);
struct
rtattr
**
ida
=
arg
;
struct
net_device
*
dev
;
struct
ifinfomsg
*
r
;
struct
nlmsghdr
*
nlh
;
int
err
=
-
ENOBUFS
;
struct
sk_buff
*
skb
;
unsigned
char
*
b
;
char
*
iw_buf
=
NULL
;
int
iw_buf_len
=
0
;
if
(
ifm
->
ifi_index
>=
0
)
dev
=
dev_get_by_index
(
ifm
->
ifi_index
);
else
return
-
EINVAL
;
if
(
!
dev
)
return
-
ENODEV
;
#ifdef CONFIG_NET_WIRELESS_RTNETLINK
if
(
ida
[
IFLA_WIRELESS
-
1
])
{
/* Call Wireless Extensions. We need to know the size before
* we can alloc. Various stuff checked in there... */
err
=
wireless_rtnetlink_get
(
dev
,
RTA_DATA
(
ida
[
IFLA_WIRELESS
-
1
]),
ida
[
IFLA_WIRELESS
-
1
]
->
rta_len
,
&
iw_buf
,
&
iw_buf_len
);
if
(
err
)
goto
out
;
}
#endif
/* CONFIG_NET_WIRELESS_RTNETLINK */
/* Create a skb big enough to include all the data.
* Some requests are way bigger than 4k... Jean II */
skb
=
alloc_skb
((
NLMSG_LENGTH
(
sizeof
(
*
r
)))
+
(
RTA_SPACE
(
iw_buf_len
)),
GFP_KERNEL
);
if
(
!
skb
)
goto
out
;
b
=
skb
->
tail
;
/* Put in the message the usual good stuff */
nlh
=
NLMSG_PUT
(
skb
,
NETLINK_CB
(
in_skb
).
pid
,
in_nlh
->
nlmsg_seq
,
RTM_NEWLINK
,
sizeof
(
*
r
));
r
=
NLMSG_DATA
(
nlh
);
r
->
ifi_family
=
AF_UNSPEC
;
r
->
__ifi_pad
=
0
;
r
->
ifi_type
=
dev
->
type
;
r
->
ifi_index
=
dev
->
ifindex
;
r
->
ifi_flags
=
dev
->
flags
;
r
->
ifi_change
=
0
;
/* Put the wireless payload if it exist */
if
(
iw_buf
!=
NULL
)
RTA_PUT
(
skb
,
IFLA_WIRELESS
,
iw_buf_len
,
iw_buf
+
IW_EV_POINT_OFF
);
nlh
->
nlmsg_len
=
skb
->
tail
-
b
;
/* Needed ? */
NETLINK_CB
(
skb
).
dst_pid
=
NETLINK_CB
(
in_skb
).
pid
;
err
=
netlink_unicast
(
rtnl
,
skb
,
NETLINK_CB
(
in_skb
).
pid
,
MSG_DONTWAIT
);
if
(
err
>
0
)
err
=
0
;
out:
if
(
iw_buf
!=
NULL
)
kfree
(
iw_buf
);
dev_put
(
dev
);
return
err
;
rtattr_failure:
nlmsg_failure:
kfree_skb
(
skb
);
goto
out
;
}
#endif
/* CONFIG_NET_WIRELESS_RTNETLINK */
static
int
rtnetlink_dump_all
(
struct
sk_buff
*
skb
,
struct
netlink_callback
*
cb
)
static
int
rtnetlink_dump_all
(
struct
sk_buff
*
skb
,
struct
netlink_callback
*
cb
)
{
{
int
idx
;
int
idx
;
...
@@ -642,7 +734,11 @@ static void rtnetlink_rcv(struct sock *sk, int len)
...
@@ -642,7 +734,11 @@ static void rtnetlink_rcv(struct sock *sk, int len)
static
struct
rtnetlink_link
link_rtnetlink_table
[
RTM_NR_MSGTYPES
]
=
static
struct
rtnetlink_link
link_rtnetlink_table
[
RTM_NR_MSGTYPES
]
=
{
{
[
RTM_GETLINK
-
RTM_BASE
]
=
{
.
dumpit
=
rtnetlink_dump_ifinfo
},
[
RTM_GETLINK
-
RTM_BASE
]
=
{
#ifdef CONFIG_NET_WIRELESS_RTNETLINK
.
doit
=
do_getlink
,
#endif
/* CONFIG_NET_WIRELESS_RTNETLINK */
.
dumpit
=
rtnetlink_dump_ifinfo
},
[
RTM_SETLINK
-
RTM_BASE
]
=
{
.
doit
=
do_setlink
},
[
RTM_SETLINK
-
RTM_BASE
]
=
{
.
doit
=
do_setlink
},
[
RTM_GETADDR
-
RTM_BASE
]
=
{
.
dumpit
=
rtnetlink_dump_all
},
[
RTM_GETADDR
-
RTM_BASE
]
=
{
.
dumpit
=
rtnetlink_dump_all
},
[
RTM_GETROUTE
-
RTM_BASE
]
=
{
.
dumpit
=
rtnetlink_dump_all
},
[
RTM_GETROUTE
-
RTM_BASE
]
=
{
.
dumpit
=
rtnetlink_dump_all
},
...
...
net/core/wireless.c
View file @
9b7c8489
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
* This file implement the Wireless Extensions APIs.
* This file implement the Wireless Extensions APIs.
*
*
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
* Copyright (c) 1997-200
5
Jean Tourrilhes, All Rights Reserved.
* Copyright (c) 1997-200
6
Jean Tourrilhes, All Rights Reserved.
*
*
* (As all part of the Linux kernel, this file is GPL)
* (As all part of the Linux kernel, this file is GPL)
*/
*/
...
@@ -65,6 +65,9 @@
...
@@ -65,6 +65,9 @@
* o Start deprecating dev->get_wireless_stats, output a warning
* o Start deprecating dev->get_wireless_stats, output a warning
* o If IW_QUAL_DBM is set, show dBm values in /proc/net/wireless
* o If IW_QUAL_DBM is set, show dBm values in /proc/net/wireless
* o Don't loose INVALID/DBM flags when clearing UPDATED flags (iwstats)
* o Don't loose INVALID/DBM flags when clearing UPDATED flags (iwstats)
*
* v8 - 17.02.06 - Jean II
* o RtNetlink requests support (SET/GET)
*/
*/
/***************************** INCLUDES *****************************/
/***************************** INCLUDES *****************************/
...
@@ -89,11 +92,13 @@
...
@@ -89,11 +92,13 @@
/* Debugging stuff */
/* Debugging stuff */
#undef WE_IOCTL_DEBUG
/* Debug IOCTL API */
#undef WE_IOCTL_DEBUG
/* Debug IOCTL API */
#undef WE_RTNETLINK_DEBUG
/* Debug RtNetlink API */
#undef WE_EVENT_DEBUG
/* Debug Event dispatcher */
#undef WE_EVENT_DEBUG
/* Debug Event dispatcher */
#undef WE_SPY_DEBUG
/* Debug enhanced spy support */
#undef WE_SPY_DEBUG
/* Debug enhanced spy support */
/* Options */
/* Options */
#define WE_EVENT_NETLINK
/* Propagate events using rtnetlink */
//CONFIG_NET_WIRELESS_RTNETLINK /* Wireless requests over RtNetlink */
#define WE_EVENT_RTNETLINK
/* Propagate events using RtNetlink */
#define WE_SET_EVENT
/* Generate an event on some set commands */
#define WE_SET_EVENT
/* Generate an event on some set commands */
/************************* GLOBAL VARIABLES *************************/
/************************* GLOBAL VARIABLES *************************/
...
@@ -156,13 +161,18 @@ static const struct iw_ioctl_description standard_ioctl[] = {
...
@@ -156,13 +161,18 @@ static const struct iw_ioctl_description standard_ioctl[] = {
.
header_type
=
IW_HEADER_TYPE_NULL
,
.
header_type
=
IW_HEADER_TYPE_NULL
,
},
},
[
SIOCGIWPRIV
-
SIOCIWFIRST
]
=
{
/* (handled directly by us) */
[
SIOCGIWPRIV
-
SIOCIWFIRST
]
=
{
/* (handled directly by us) */
.
header_type
=
IW_HEADER_TYPE_NULL
,
.
header_type
=
IW_HEADER_TYPE_POINT
,
.
token_size
=
sizeof
(
struct
iw_priv_args
),
.
max_tokens
=
16
,
.
flags
=
IW_DESCR_FLAG_NOMAX
,
},
},
[
SIOCSIWSTATS
-
SIOCIWFIRST
]
=
{
[
SIOCSIWSTATS
-
SIOCIWFIRST
]
=
{
.
header_type
=
IW_HEADER_TYPE_NULL
,
.
header_type
=
IW_HEADER_TYPE_NULL
,
},
},
[
SIOCGIWSTATS
-
SIOCIWFIRST
]
=
{
/* (handled directly by us) */
[
SIOCGIWSTATS
-
SIOCIWFIRST
]
=
{
/* (handled directly by us) */
.
header_type
=
IW_HEADER_TYPE_NULL
,
.
header_type
=
IW_HEADER_TYPE_POINT
,
.
token_size
=
1
,
.
max_tokens
=
sizeof
(
struct
iw_statistics
),
.
flags
=
IW_DESCR_FLAG_DUMP
,
.
flags
=
IW_DESCR_FLAG_DUMP
,
},
},
[
SIOCSIWSPY
-
SIOCIWFIRST
]
=
{
[
SIOCSIWSPY
-
SIOCIWFIRST
]
=
{
...
@@ -529,6 +539,70 @@ static inline int adjust_priv_size(__u16 args,
...
@@ -529,6 +539,70 @@ static inline int adjust_priv_size(__u16 args,
return
num
*
iw_priv_type_size
[
type
];
return
num
*
iw_priv_type_size
[
type
];
}
}
/* ---------------------------------------------------------------- */
/*
* Standard Wireless Handler : get wireless stats
* Allow programatic access to /proc/net/wireless even if /proc
* doesn't exist... Also more efficient...
*/
static
int
iw_handler_get_iwstats
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
/* Get stats from the driver */
struct
iw_statistics
*
stats
;
stats
=
get_wireless_stats
(
dev
);
if
(
stats
!=
(
struct
iw_statistics
*
)
NULL
)
{
/* Copy statistics to extra */
memcpy
(
extra
,
stats
,
sizeof
(
struct
iw_statistics
));
wrqu
->
data
.
length
=
sizeof
(
struct
iw_statistics
);
/* Check if we need to clear the updated flag */
if
(
wrqu
->
data
.
flags
!=
0
)
stats
->
qual
.
updated
&=
~
IW_QUAL_ALL_UPDATED
;
return
0
;
}
else
return
-
EOPNOTSUPP
;
}
/* ---------------------------------------------------------------- */
/*
* Standard Wireless Handler : get iwpriv definitions
* Export the driver private handler definition
* They will be picked up by tools like iwpriv...
*/
static
int
iw_handler_get_private
(
struct
net_device
*
dev
,
struct
iw_request_info
*
info
,
union
iwreq_data
*
wrqu
,
char
*
extra
)
{
/* Check if the driver has something to export */
if
((
dev
->
wireless_handlers
->
num_private_args
==
0
)
||
(
dev
->
wireless_handlers
->
private_args
==
NULL
))
return
-
EOPNOTSUPP
;
/* Check if there is enough buffer up there */
if
(
wrqu
->
data
.
length
<
dev
->
wireless_handlers
->
num_private_args
)
{
/* User space can't know in advance how large the buffer
* needs to be. Give it a hint, so that we can support
* any size buffer we want somewhat efficiently... */
wrqu
->
data
.
length
=
dev
->
wireless_handlers
->
num_private_args
;
return
-
E2BIG
;
}
/* Set the number of available ioctls. */
wrqu
->
data
.
length
=
dev
->
wireless_handlers
->
num_private_args
;
/* Copy structure to the user buffer. */
memcpy
(
extra
,
dev
->
wireless_handlers
->
private_args
,
sizeof
(
struct
iw_priv_args
)
*
wrqu
->
data
.
length
);
return
0
;
}
/******************** /proc/net/wireless SUPPORT ********************/
/******************** /proc/net/wireless SUPPORT ********************/
/*
/*
...
@@ -628,83 +702,16 @@ int __init wireless_proc_init(void)
...
@@ -628,83 +702,16 @@ int __init wireless_proc_init(void)
* or just call the driver ioctl handler.
* or just call the driver ioctl handler.
*/
*/
/* ---------------------------------------------------------------- */
/*
* Allow programatic access to /proc/net/wireless even if /proc
* doesn't exist... Also more efficient...
*/
static
inline
int
dev_iwstats
(
struct
net_device
*
dev
,
struct
ifreq
*
ifr
)
{
/* Get stats from the driver */
struct
iw_statistics
*
stats
;
stats
=
get_wireless_stats
(
dev
);
if
(
stats
!=
(
struct
iw_statistics
*
)
NULL
)
{
struct
iwreq
*
wrq
=
(
struct
iwreq
*
)
ifr
;
/* Copy statistics to the user buffer */
if
(
copy_to_user
(
wrq
->
u
.
data
.
pointer
,
stats
,
sizeof
(
struct
iw_statistics
)))
return
-
EFAULT
;
/* Check if we need to clear the updated flag */
if
(
wrq
->
u
.
data
.
flags
!=
0
)
stats
->
qual
.
updated
&=
~
IW_QUAL_ALL_UPDATED
;
return
0
;
}
else
return
-
EOPNOTSUPP
;
}
/* ---------------------------------------------------------------- */
/*
* Export the driver private handler definition
* They will be picked up by tools like iwpriv...
*/
static
inline
int
ioctl_export_private
(
struct
net_device
*
dev
,
struct
ifreq
*
ifr
)
{
struct
iwreq
*
iwr
=
(
struct
iwreq
*
)
ifr
;
/* Check if the driver has something to export */
if
((
dev
->
wireless_handlers
->
num_private_args
==
0
)
||
(
dev
->
wireless_handlers
->
private_args
==
NULL
))
return
-
EOPNOTSUPP
;
/* Check NULL pointer */
if
(
iwr
->
u
.
data
.
pointer
==
NULL
)
return
-
EFAULT
;
/* Check if there is enough buffer up there */
if
(
iwr
->
u
.
data
.
length
<
dev
->
wireless_handlers
->
num_private_args
)
{
/* User space can't know in advance how large the buffer
* needs to be. Give it a hint, so that we can support
* any size buffer we want somewhat efficiently... */
iwr
->
u
.
data
.
length
=
dev
->
wireless_handlers
->
num_private_args
;
return
-
E2BIG
;
}
/* Set the number of available ioctls. */
iwr
->
u
.
data
.
length
=
dev
->
wireless_handlers
->
num_private_args
;
/* Copy structure to the user buffer. */
if
(
copy_to_user
(
iwr
->
u
.
data
.
pointer
,
dev
->
wireless_handlers
->
private_args
,
sizeof
(
struct
iw_priv_args
)
*
iwr
->
u
.
data
.
length
))
return
-
EFAULT
;
return
0
;
}
/* ---------------------------------------------------------------- */
/* ---------------------------------------------------------------- */
/*
/*
* Wrapper to call a standard Wireless Extension handler.
* Wrapper to call a standard Wireless Extension handler.
* We do various checks and also take care of moving data between
* We do various checks and also take care of moving data between
* user space and kernel space.
* user space and kernel space.
*/
*/
static
in
line
in
t
ioctl_standard_call
(
struct
net_device
*
dev
,
static
int
ioctl_standard_call
(
struct
net_device
*
dev
,
struct
ifreq
*
ifr
,
struct
ifreq
*
ifr
,
unsigned
int
cmd
,
unsigned
int
cmd
,
iw_handler
handler
)
iw_handler
handler
)
{
{
struct
iwreq
*
iwr
=
(
struct
iwreq
*
)
ifr
;
struct
iwreq
*
iwr
=
(
struct
iwreq
*
)
ifr
;
const
struct
iw_ioctl_description
*
descr
;
const
struct
iw_ioctl_description
*
descr
;
...
@@ -1048,14 +1055,20 @@ int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd)
...
@@ -1048,14 +1055,20 @@ int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd)
{
{
case
SIOCGIWSTATS
:
case
SIOCGIWSTATS
:
/* Get Wireless Stats */
/* Get Wireless Stats */
return
dev_iwstats
(
dev
,
ifr
);
return
ioctl_standard_call
(
dev
,
ifr
,
cmd
,
&
iw_handler_get_iwstats
);
case
SIOCGIWPRIV
:
case
SIOCGIWPRIV
:
/* Check if we have some wireless handlers defined */
/* Check if we have some wireless handlers defined */
if
(
dev
->
wireless_handlers
!=
NULL
)
{
if
(
dev
->
wireless_handlers
!=
NULL
)
{
/* We export to user space the definition of
/* We export to user space the definition of
* the private handler ourselves */
* the private handler ourselves */
return
ioctl_export_private
(
dev
,
ifr
);
return
ioctl_standard_call
(
dev
,
ifr
,
cmd
,
&
iw_handler_get_private
);
}
}
// ## Fall-through for old API ##
// ## Fall-through for old API ##
default:
default:
...
@@ -1088,16 +1101,739 @@ int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd)
...
@@ -1088,16 +1101,739 @@ int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd)
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/********************** RTNETLINK REQUEST API **********************/
/*
* The alternate user space API to configure all those Wireless Extensions
* is through RtNetlink.
* This API support only the new driver API (iw_handler).
*
* This RtNetlink API use the same query/reply model as the ioctl API.
* Maximum effort has been done to fit in the RtNetlink model, and
* we support both RtNetlink Set and RtNelink Get operations.
* On the other hand, we don't offer Dump operations because of the
* following reasons :
* o Large number of parameters, most optional
* o Large size of some parameters (> 100 bytes)
* o Each parameters need to be extracted from hardware
* o Scan requests can take seconds and disable network activity.
* Because of this high cost/overhead, we want to return only the
* parameters the user application is really interested in.
* We could offer partial Dump using the IW_DESCR_FLAG_DUMP flag.
*
* The API uses the standard RtNetlink socket. When the RtNetlink code
* find a IFLA_WIRELESS field in a RtNetlink SET_LINK request,
* it calls here.
*/
#ifdef CONFIG_NET_WIRELESS_RTNETLINK
/* ---------------------------------------------------------------- */
/*
* Wrapper to call a standard Wireless Extension GET handler.
* We do various checks and call the handler with the proper args.
*/
static
int
rtnetlink_standard_get
(
struct
net_device
*
dev
,
struct
iw_event
*
request
,
int
request_len
,
iw_handler
handler
,
char
**
p_buf
,
int
*
p_len
)
{
const
struct
iw_ioctl_description
*
descr
=
NULL
;
unsigned
int
cmd
;
union
iwreq_data
*
wrqu
;
int
hdr_len
;
struct
iw_request_info
info
;
char
*
buffer
=
NULL
;
int
buffer_size
=
0
;
int
ret
=
-
EINVAL
;
/* Get the description of the Request */
cmd
=
request
->
cmd
;
if
((
cmd
-
SIOCIWFIRST
)
>=
standard_ioctl_num
)
return
-
EOPNOTSUPP
;
descr
=
&
(
standard_ioctl
[
cmd
-
SIOCIWFIRST
]);
#ifdef WE_RTNETLINK_DEBUG
printk
(
KERN_DEBUG
"%s (WE.r) : Found standard handler for 0x%04X
\n
"
,
dev
->
name
,
cmd
);
printk
(
KERN_DEBUG
"%s (WE.r) : Header type : %d, Token type : %d, size : %d, token : %d
\n
"
,
dev
->
name
,
descr
->
header_type
,
descr
->
token_type
,
descr
->
token_size
,
descr
->
max_tokens
);
#endif
/* WE_RTNETLINK_DEBUG */
/* Check if wrqu is complete */
hdr_len
=
event_type_size
[
descr
->
header_type
];
if
(
request_len
<
hdr_len
)
{
#ifdef WE_RTNETLINK_DEBUG
printk
(
KERN_DEBUG
"%s (WE.r) : Wireless request too short (%d)
\n
"
,
dev
->
name
,
request_len
);
#endif
/* WE_RTNETLINK_DEBUG */
return
-
EINVAL
;
}
/* Prepare the call */
info
.
cmd
=
cmd
;
info
.
flags
=
0
;
/* Check if we have extra data in the reply or not */
if
(
descr
->
header_type
!=
IW_HEADER_TYPE_POINT
)
{
/* Create the kernel buffer that we will return.
* It's at an offset to match the TYPE_POINT case... */
buffer_size
=
request_len
+
IW_EV_POINT_OFF
;
buffer
=
kmalloc
(
buffer_size
,
GFP_KERNEL
);
if
(
buffer
==
NULL
)
{
return
-
ENOMEM
;
}
/* Copy event data */
memcpy
(
buffer
+
IW_EV_POINT_OFF
,
request
,
request_len
);
/* Use our own copy of wrqu */
wrqu
=
(
union
iwreq_data
*
)
(
buffer
+
IW_EV_POINT_OFF
+
IW_EV_LCP_LEN
);
/* No extra arguments. Trivial to handle */
ret
=
handler
(
dev
,
&
info
,
wrqu
,
NULL
);
}
else
{
union
iwreq_data
wrqu_point
;
char
*
extra
=
NULL
;
int
extra_size
=
0
;
/* Get a temp copy of wrqu (skip pointer) */
memcpy
(((
char
*
)
&
wrqu_point
)
+
IW_EV_POINT_OFF
,
((
char
*
)
request
)
+
IW_EV_LCP_LEN
,
IW_EV_POINT_LEN
-
IW_EV_LCP_LEN
);
/* Calculate space needed by arguments. Always allocate
* for max space. Easier, and won't last long... */
extra_size
=
descr
->
max_tokens
*
descr
->
token_size
;
/* Support for very large requests */
if
((
descr
->
flags
&
IW_DESCR_FLAG_NOMAX
)
&&
(
wrqu_point
.
data
.
length
>
descr
->
max_tokens
))
extra_size
=
(
wrqu_point
.
data
.
length
*
descr
->
token_size
);
buffer_size
=
extra_size
+
IW_EV_POINT_LEN
+
IW_EV_POINT_OFF
;
#ifdef WE_RTNETLINK_DEBUG
printk
(
KERN_DEBUG
"%s (WE.r) : Malloc %d bytes (%d bytes)
\n
"
,
dev
->
name
,
extra_size
,
buffer_size
);
#endif
/* WE_RTNETLINK_DEBUG */
/* Create the kernel buffer that we will return */
buffer
=
kmalloc
(
buffer_size
,
GFP_KERNEL
);
if
(
buffer
==
NULL
)
{
return
-
ENOMEM
;
}
/* Put wrqu in the right place (just before extra).
* Leave space for IWE header and dummy pointer...
* Note that IW_EV_LCP_LEN==4 bytes, so it's still aligned...
*/
memcpy
(
buffer
+
IW_EV_LCP_LEN
+
IW_EV_POINT_OFF
,
((
char
*
)
&
wrqu_point
)
+
IW_EV_POINT_OFF
,
IW_EV_POINT_LEN
-
IW_EV_LCP_LEN
);
wrqu
=
(
union
iwreq_data
*
)
(
buffer
+
IW_EV_LCP_LEN
);
/* Extra comes logically after that. Offset +12 bytes. */
extra
=
buffer
+
IW_EV_POINT_OFF
+
IW_EV_POINT_LEN
;
/* Call the handler */
ret
=
handler
(
dev
,
&
info
,
wrqu
,
extra
);
/* Calculate real returned length */
extra_size
=
(
wrqu
->
data
.
length
*
descr
->
token_size
);
/* Re-adjust reply size */
request
->
len
=
extra_size
+
IW_EV_POINT_LEN
;
/* Put the iwe header where it should, i.e. scrap the
* dummy pointer. */
memcpy
(
buffer
+
IW_EV_POINT_OFF
,
request
,
IW_EV_LCP_LEN
);
#ifdef WE_RTNETLINK_DEBUG
printk
(
KERN_DEBUG
"%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d
\n
"
,
dev
->
name
,
cmd
,
hdr_len
,
wrqu
->
data
.
length
,
extra_size
,
buffer_size
);
#endif
/* WE_RTNETLINK_DEBUG */
/* Check if there is enough buffer up there */
if
(
wrqu_point
.
data
.
length
<
wrqu
->
data
.
length
)
ret
=
-
E2BIG
;
}
/* Return the buffer to the caller */
if
(
!
ret
)
{
*
p_buf
=
buffer
;
*
p_len
=
request
->
len
;
}
else
{
/* Cleanup */
if
(
buffer
)
kfree
(
buffer
);
}
return
ret
;
}
/* ---------------------------------------------------------------- */
/*
* Wrapper to call a standard Wireless Extension SET handler.
* We do various checks and call the handler with the proper args.
*/
static
inline
int
rtnetlink_standard_set
(
struct
net_device
*
dev
,
struct
iw_event
*
request
,
int
request_len
,
iw_handler
handler
)
{
const
struct
iw_ioctl_description
*
descr
=
NULL
;
unsigned
int
cmd
;
union
iwreq_data
*
wrqu
;
union
iwreq_data
wrqu_point
;
int
hdr_len
;
char
*
extra
=
NULL
;
int
extra_size
=
0
;
struct
iw_request_info
info
;
int
ret
=
-
EINVAL
;
/* Get the description of the Request */
cmd
=
request
->
cmd
;
if
((
cmd
-
SIOCIWFIRST
)
>=
standard_ioctl_num
)
return
-
EOPNOTSUPP
;
descr
=
&
(
standard_ioctl
[
cmd
-
SIOCIWFIRST
]);
#ifdef WE_RTNETLINK_DEBUG
printk
(
KERN_DEBUG
"%s (WE.r) : Found standard SET handler for 0x%04X
\n
"
,
dev
->
name
,
cmd
);
printk
(
KERN_DEBUG
"%s (WE.r) : Header type : %d, Token type : %d, size : %d, token : %d
\n
"
,
dev
->
name
,
descr
->
header_type
,
descr
->
token_type
,
descr
->
token_size
,
descr
->
max_tokens
);
#endif
/* WE_RTNETLINK_DEBUG */
/* Extract fixed header from request. This is properly aligned. */
wrqu
=
&
request
->
u
;
/* Check if wrqu is complete */
hdr_len
=
event_type_size
[
descr
->
header_type
];
if
(
request_len
<
hdr_len
)
{
#ifdef WE_RTNETLINK_DEBUG
printk
(
KERN_DEBUG
"%s (WE.r) : Wireless request too short (%d)
\n
"
,
dev
->
name
,
request_len
);
#endif
/* WE_RTNETLINK_DEBUG */
return
-
EINVAL
;
}
/* Prepare the call */
info
.
cmd
=
cmd
;
info
.
flags
=
0
;
/* Check if we have extra data in the request or not */
if
(
descr
->
header_type
!=
IW_HEADER_TYPE_POINT
)
{
/* No extra arguments. Trivial to handle */
ret
=
handler
(
dev
,
&
info
,
wrqu
,
NULL
);
}
else
{
int
extra_len
;
/* Put wrqu in the right place (skip pointer) */
memcpy
(((
char
*
)
&
wrqu_point
)
+
IW_EV_POINT_OFF
,
wrqu
,
IW_EV_POINT_LEN
-
IW_EV_LCP_LEN
);
/* Don't forget about the event code... */
wrqu
=
&
wrqu_point
;
/* Check if number of token fits within bounds */
if
(
wrqu_point
.
data
.
length
>
descr
->
max_tokens
)
return
-
E2BIG
;
if
(
wrqu_point
.
data
.
length
<
descr
->
min_tokens
)
return
-
EINVAL
;
/* Real length of payload */
extra_len
=
wrqu_point
.
data
.
length
*
descr
->
token_size
;
/* Check if request is self consistent */
if
((
request_len
-
hdr_len
)
<
extra_len
)
{
#ifdef WE_RTNETLINK_DEBUG
printk
(
KERN_DEBUG
"%s (WE.r) : Wireless request data too short (%d)
\n
"
,
dev
->
name
,
extra_size
);
#endif
/* WE_RTNETLINK_DEBUG */
return
-
EINVAL
;
}
#ifdef WE_RTNETLINK_DEBUG
printk
(
KERN_DEBUG
"%s (WE.r) : Malloc %d bytes
\n
"
,
dev
->
name
,
extra_size
);
#endif
/* WE_RTNETLINK_DEBUG */
/* Always allocate for max space. Easier, and won't last
* long... */
extra_size
=
descr
->
max_tokens
*
descr
->
token_size
;
extra
=
kmalloc
(
extra_size
,
GFP_KERNEL
);
if
(
extra
==
NULL
)
return
-
ENOMEM
;
/* Copy extra in aligned buffer */
memcpy
(
extra
,
((
char
*
)
request
)
+
hdr_len
,
extra_len
);
/* Call the handler */
ret
=
handler
(
dev
,
&
info
,
&
wrqu_point
,
extra
);
}
#ifdef WE_SET_EVENT
/* Generate an event to notify listeners of the change */
if
((
descr
->
flags
&
IW_DESCR_FLAG_EVENT
)
&&
((
ret
==
0
)
||
(
ret
==
-
EIWCOMMIT
)))
{
if
(
descr
->
flags
&
IW_DESCR_FLAG_RESTRICT
)
/* If the event is restricted, don't
* export the payload */
wireless_send_event
(
dev
,
cmd
,
wrqu
,
NULL
);
else
wireless_send_event
(
dev
,
cmd
,
wrqu
,
extra
);
}
#endif
/* WE_SET_EVENT */
/* Cleanup - I told you it wasn't that long ;-) */
if
(
extra
)
kfree
(
extra
);
/* Call commit handler if needed and defined */
if
(
ret
==
-
EIWCOMMIT
)
ret
=
call_commit_handler
(
dev
);
return
ret
;
}
/* ---------------------------------------------------------------- */
/*
* Wrapper to call a private Wireless Extension GET handler.
* Same as above...
* It's not as nice and slimline as the standard wrapper. The cause
* is struct iw_priv_args, which was not really designed for the
* job we are going here.
*
* IMPORTANT : This function prevent to set and get data on the same
* IOCTL and enforce the SET/GET convention. Not doing it would be
* far too hairy...
* If you need to set and get data at the same time, please don't use
* a iw_handler but process it in your ioctl handler (i.e. use the
* old driver API).
*/
static
inline
int
rtnetlink_private_get
(
struct
net_device
*
dev
,
struct
iw_event
*
request
,
int
request_len
,
iw_handler
handler
,
char
**
p_buf
,
int
*
p_len
)
{
const
struct
iw_priv_args
*
descr
=
NULL
;
unsigned
int
cmd
;
union
iwreq_data
*
wrqu
;
int
hdr_len
;
struct
iw_request_info
info
;
int
extra_size
=
0
;
int
i
;
char
*
buffer
=
NULL
;
int
buffer_size
=
0
;
int
ret
=
-
EINVAL
;
/* Get the description of the Request */
cmd
=
request
->
cmd
;
for
(
i
=
0
;
i
<
dev
->
wireless_handlers
->
num_private_args
;
i
++
)
if
(
cmd
==
dev
->
wireless_handlers
->
private_args
[
i
].
cmd
)
{
descr
=
&
(
dev
->
wireless_handlers
->
private_args
[
i
]);
break
;
}
if
(
descr
==
NULL
)
return
-
EOPNOTSUPP
;
#ifdef WE_RTNETLINK_DEBUG
printk
(
KERN_DEBUG
"%s (WE.r) : Found private handler for 0x%04X
\n
"
,
dev
->
name
,
cmd
);
printk
(
KERN_DEBUG
"%s (WE.r) : Name %s, set %X, get %X
\n
"
,
dev
->
name
,
descr
->
name
,
descr
->
set_args
,
descr
->
get_args
);
#endif
/* WE_RTNETLINK_DEBUG */
/* Compute the max size of the get arguments */
extra_size
=
get_priv_size
(
descr
->
get_args
);
/* Does it fits in wrqu ? */
if
((
descr
->
get_args
&
IW_PRIV_SIZE_FIXED
)
&&
(
extra_size
<=
IFNAMSIZ
))
{
hdr_len
=
extra_size
;
extra_size
=
0
;
}
else
{
hdr_len
=
IW_EV_POINT_LEN
;
}
/* Check if wrqu is complete */
if
(
request_len
<
hdr_len
)
{
#ifdef WE_RTNETLINK_DEBUG
printk
(
KERN_DEBUG
"%s (WE.r) : Wireless request too short (%d)
\n
"
,
dev
->
name
,
request_len
);
#endif
/* WE_RTNETLINK_DEBUG */
return
-
EINVAL
;
}
/* Prepare the call */
info
.
cmd
=
cmd
;
info
.
flags
=
0
;
/* Check if we have a pointer to user space data or not. */
if
(
extra_size
==
0
)
{
/* Create the kernel buffer that we will return.
* It's at an offset to match the TYPE_POINT case... */
buffer_size
=
request_len
+
IW_EV_POINT_OFF
;
buffer
=
kmalloc
(
buffer_size
,
GFP_KERNEL
);
if
(
buffer
==
NULL
)
{
return
-
ENOMEM
;
}
/* Copy event data */
memcpy
(
buffer
+
IW_EV_POINT_OFF
,
request
,
request_len
);
/* Use our own copy of wrqu */
wrqu
=
(
union
iwreq_data
*
)
(
buffer
+
IW_EV_POINT_OFF
+
IW_EV_LCP_LEN
);
/* No extra arguments. Trivial to handle */
ret
=
handler
(
dev
,
&
info
,
wrqu
,
(
char
*
)
wrqu
);
}
else
{
char
*
extra
;
/* Buffer for full reply */
buffer_size
=
extra_size
+
IW_EV_POINT_LEN
+
IW_EV_POINT_OFF
;
#ifdef WE_RTNETLINK_DEBUG
printk
(
KERN_DEBUG
"%s (WE.r) : Malloc %d bytes (%d bytes)
\n
"
,
dev
->
name
,
extra_size
,
buffer_size
);
#endif
/* WE_RTNETLINK_DEBUG */
/* Create the kernel buffer that we will return */
buffer
=
kmalloc
(
buffer_size
,
GFP_KERNEL
);
if
(
buffer
==
NULL
)
{
return
-
ENOMEM
;
}
/* Put wrqu in the right place (just before extra).
* Leave space for IWE header and dummy pointer...
* Note that IW_EV_LCP_LEN==4 bytes, so it's still aligned...
*/
memcpy
(
buffer
+
IW_EV_LCP_LEN
+
IW_EV_POINT_OFF
,
((
char
*
)
request
)
+
IW_EV_LCP_LEN
,
IW_EV_POINT_LEN
-
IW_EV_LCP_LEN
);
wrqu
=
(
union
iwreq_data
*
)
(
buffer
+
IW_EV_LCP_LEN
);
/* Extra comes logically after that. Offset +12 bytes. */
extra
=
buffer
+
IW_EV_POINT_OFF
+
IW_EV_POINT_LEN
;
/* Call the handler */
ret
=
handler
(
dev
,
&
info
,
wrqu
,
extra
);
/* Adjust for the actual length if it's variable,
* avoid leaking kernel bits outside. */
if
(
!
(
descr
->
get_args
&
IW_PRIV_SIZE_FIXED
))
extra_size
=
adjust_priv_size
(
descr
->
get_args
,
wrqu
);
/* Re-adjust reply size */
request
->
len
=
extra_size
+
IW_EV_POINT_LEN
;
/* Put the iwe header where it should, i.e. scrap the
* dummy pointer. */
memcpy
(
buffer
+
IW_EV_POINT_OFF
,
request
,
IW_EV_LCP_LEN
);
#ifdef WE_RTNETLINK_DEBUG
printk
(
KERN_DEBUG
"%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d
\n
"
,
dev
->
name
,
cmd
,
hdr_len
,
wrqu
->
data
.
length
,
extra_size
,
buffer_size
);
#endif
/* WE_RTNETLINK_DEBUG */
}
/* Return the buffer to the caller */
if
(
!
ret
)
{
*
p_buf
=
buffer
;
*
p_len
=
request
->
len
;
}
else
{
/* Cleanup */
if
(
buffer
)
kfree
(
buffer
);
}
return
ret
;
}
/* ---------------------------------------------------------------- */
/*
* Wrapper to call a private Wireless Extension SET handler.
* Same as above...
* It's not as nice and slimline as the standard wrapper. The cause
* is struct iw_priv_args, which was not really designed for the
* job we are going here.
*
* IMPORTANT : This function prevent to set and get data on the same
* IOCTL and enforce the SET/GET convention. Not doing it would be
* far too hairy...
* If you need to set and get data at the same time, please don't use
* a iw_handler but process it in your ioctl handler (i.e. use the
* old driver API).
*/
static
inline
int
rtnetlink_private_set
(
struct
net_device
*
dev
,
struct
iw_event
*
request
,
int
request_len
,
iw_handler
handler
)
{
const
struct
iw_priv_args
*
descr
=
NULL
;
unsigned
int
cmd
;
union
iwreq_data
*
wrqu
;
union
iwreq_data
wrqu_point
;
int
hdr_len
;
char
*
extra
=
NULL
;
int
extra_size
=
0
;
int
offset
=
0
;
/* For sub-ioctls */
struct
iw_request_info
info
;
int
i
;
int
ret
=
-
EINVAL
;
/* Get the description of the Request */
cmd
=
request
->
cmd
;
for
(
i
=
0
;
i
<
dev
->
wireless_handlers
->
num_private_args
;
i
++
)
if
(
cmd
==
dev
->
wireless_handlers
->
private_args
[
i
].
cmd
)
{
descr
=
&
(
dev
->
wireless_handlers
->
private_args
[
i
]);
break
;
}
if
(
descr
==
NULL
)
return
-
EOPNOTSUPP
;
#ifdef WE_RTNETLINK_DEBUG
printk
(
KERN_DEBUG
"%s (WE.r) : Found private handler for 0x%04X
\n
"
,
ifr
->
ifr_name
,
cmd
);
printk
(
KERN_DEBUG
"%s (WE.r) : Name %s, set %X, get %X
\n
"
,
dev
->
name
,
descr
->
name
,
descr
->
set_args
,
descr
->
get_args
);
#endif
/* WE_RTNETLINK_DEBUG */
/* Compute the size of the set arguments */
/* Check for sub-ioctl handler */
if
(
descr
->
name
[
0
]
==
'\0'
)
/* Reserve one int for sub-ioctl index */
offset
=
sizeof
(
__u32
);
/* Size of set arguments */
extra_size
=
get_priv_size
(
descr
->
set_args
);
/* Does it fits in wrqu ? */
if
((
descr
->
set_args
&
IW_PRIV_SIZE_FIXED
)
&&
(
extra_size
<=
IFNAMSIZ
))
{
hdr_len
=
IW_EV_LCP_LEN
+
extra_size
;
extra_size
=
0
;
}
else
{
hdr_len
=
IW_EV_POINT_LEN
;
}
/* Extract fixed header from request. This is properly aligned. */
wrqu
=
&
request
->
u
;
/* Check if wrqu is complete */
if
(
request_len
<
hdr_len
)
{
#ifdef WE_RTNETLINK_DEBUG
printk
(
KERN_DEBUG
"%s (WE.r) : Wireless request too short (%d)
\n
"
,
dev
->
name
,
request_len
);
#endif
/* WE_RTNETLINK_DEBUG */
return
-
EINVAL
;
}
/* Prepare the call */
info
.
cmd
=
cmd
;
info
.
flags
=
0
;
/* Check if we have a pointer to user space data or not. */
if
(
extra_size
==
0
)
{
/* No extra arguments. Trivial to handle */
ret
=
handler
(
dev
,
&
info
,
wrqu
,
(
char
*
)
wrqu
);
}
else
{
int
extra_len
;
/* Put wrqu in the right place (skip pointer) */
memcpy
(((
char
*
)
&
wrqu_point
)
+
IW_EV_POINT_OFF
,
wrqu
,
IW_EV_POINT_LEN
-
IW_EV_LCP_LEN
);
/* Does it fits within bounds ? */
if
(
wrqu_point
.
data
.
length
>
(
descr
->
set_args
&
IW_PRIV_SIZE_MASK
))
return
-
E2BIG
;
/* Real length of payload */
extra_len
=
adjust_priv_size
(
descr
->
set_args
,
&
wrqu_point
);
/* Check if request is self consistent */
if
((
request_len
-
hdr_len
)
<
extra_len
)
{
#ifdef WE_RTNETLINK_DEBUG
printk
(
KERN_DEBUG
"%s (WE.r) : Wireless request data too short (%d)
\n
"
,
dev
->
name
,
extra_size
);
#endif
/* WE_RTNETLINK_DEBUG */
return
-
EINVAL
;
}
#ifdef WE_RTNETLINK_DEBUG
printk
(
KERN_DEBUG
"%s (WE.r) : Malloc %d bytes
\n
"
,
dev
->
name
,
extra_size
);
#endif
/* WE_RTNETLINK_DEBUG */
/* Always allocate for max space. Easier, and won't last
* long... */
extra
=
kmalloc
(
extra_size
,
GFP_KERNEL
);
if
(
extra
==
NULL
)
return
-
ENOMEM
;
/* Copy extra in aligned buffer */
memcpy
(
extra
,
((
char
*
)
request
)
+
hdr_len
,
extra_len
);
/* Call the handler */
ret
=
handler
(
dev
,
&
info
,
&
wrqu_point
,
extra
);
/* Cleanup - I told you it wasn't that long ;-) */
kfree
(
extra
);
}
/* Call commit handler if needed and defined */
if
(
ret
==
-
EIWCOMMIT
)
ret
=
call_commit_handler
(
dev
);
return
ret
;
}
/* ---------------------------------------------------------------- */
/*
* Main RtNetlink dispatcher. Called from the main networking code
* (do_getlink() in net/core/rtnetlink.c).
* Check the type of Request and call the appropriate wrapper...
*/
int
wireless_rtnetlink_get
(
struct
net_device
*
dev
,
char
*
data
,
int
len
,
char
**
p_buf
,
int
*
p_len
)
{
struct
iw_event
*
request
=
(
struct
iw_event
*
)
data
;
iw_handler
handler
;
/* Check length */
if
(
len
<
IW_EV_LCP_LEN
)
{
printk
(
KERN_DEBUG
"%s (WE.r) : RtNetlink request too short (%d)
\n
"
,
dev
->
name
,
len
);
return
-
EINVAL
;
}
/* ReCheck length (len may have padding) */
if
(
request
->
len
>
len
)
{
printk
(
KERN_DEBUG
"%s (WE.r) : RtNetlink request len invalid (%d-%d)
\n
"
,
dev
->
name
,
request
->
len
,
len
);
return
-
EINVAL
;
}
/* Only accept GET requests in here */
if
(
!
IW_IS_GET
(
request
->
cmd
))
return
-
EOPNOTSUPP
;
/* Special cases */
if
(
request
->
cmd
==
SIOCGIWSTATS
)
/* Get Wireless Stats */
return
rtnetlink_standard_get
(
dev
,
request
,
request
->
len
,
&
iw_handler_get_iwstats
,
p_buf
,
p_len
);
if
(
request
->
cmd
==
SIOCGIWPRIV
)
{
/* Check if we have some wireless handlers defined */
if
(
dev
->
wireless_handlers
==
NULL
)
return
-
EOPNOTSUPP
;
/* Get Wireless Stats */
return
rtnetlink_standard_get
(
dev
,
request
,
request
->
len
,
&
iw_handler_get_private
,
p_buf
,
p_len
);
}
/* Basic check */
if
(
!
netif_device_present
(
dev
))
return
-
ENODEV
;
/* Try to find the handler */
handler
=
get_handler
(
dev
,
request
->
cmd
);
if
(
handler
!=
NULL
)
{
/* Standard and private are not the same */
if
(
request
->
cmd
<
SIOCIWFIRSTPRIV
)
return
rtnetlink_standard_get
(
dev
,
request
,
request
->
len
,
handler
,
p_buf
,
p_len
);
else
return
rtnetlink_private_get
(
dev
,
request
,
request
->
len
,
handler
,
p_buf
,
p_len
);
}
return
-
EOPNOTSUPP
;
}
/* ---------------------------------------------------------------- */
/*
* Main RtNetlink dispatcher. Called from the main networking code
* (do_setlink() in net/core/rtnetlink.c).
* Check the type of Request and call the appropriate wrapper...
*/
int
wireless_rtnetlink_set
(
struct
net_device
*
dev
,
char
*
data
,
int
len
)
{
struct
iw_event
*
request
=
(
struct
iw_event
*
)
data
;
iw_handler
handler
;
/* Check length */
if
(
len
<
IW_EV_LCP_LEN
)
{
printk
(
KERN_DEBUG
"%s (WE.r) : RtNetlink request too short (%d)
\n
"
,
dev
->
name
,
len
);
return
-
EINVAL
;
}
/* ReCheck length (len may have padding) */
if
(
request
->
len
>
len
)
{
printk
(
KERN_DEBUG
"%s (WE.r) : RtNetlink request len invalid (%d-%d)
\n
"
,
dev
->
name
,
request
->
len
,
len
);
return
-
EINVAL
;
}
/* Only accept SET requests in here */
if
(
!
IW_IS_SET
(
request
->
cmd
))
return
-
EOPNOTSUPP
;
/* Basic check */
if
(
!
netif_device_present
(
dev
))
return
-
ENODEV
;
/* New driver API : try to find the handler */
handler
=
get_handler
(
dev
,
request
->
cmd
);
if
(
handler
!=
NULL
)
{
/* Standard and private are not the same */
if
(
request
->
cmd
<
SIOCIWFIRSTPRIV
)
return
rtnetlink_standard_set
(
dev
,
request
,
request
->
len
,
handler
);
else
return
rtnetlink_private_set
(
dev
,
request
,
request
->
len
,
handler
);
}
return
-
EOPNOTSUPP
;
}
#endif
/* CONFIG_NET_WIRELESS_RTNETLINK */
/************************* EVENT PROCESSING *************************/
/************************* EVENT PROCESSING *************************/
/*
/*
* Process events generated by the wireless layer or the driver.
* Process events generated by the wireless layer or the driver.
* Most often, the event will be propagated through rtnetlink
* Most often, the event will be propagated through rtnetlink
*/
*/
#ifdef WE_EVENT_NETLINK
#ifdef WE_EVENT_RTNETLINK
/* "rtnl" is defined in net/core/rtnetlink.c, but we need it here.
* It is declared in <linux/rtnetlink.h> */
/* ---------------------------------------------------------------- */
/* ---------------------------------------------------------------- */
/*
/*
* Fill a rtnetlink message with our event data.
* Fill a rtnetlink message with our event data.
...
@@ -1121,12 +1857,11 @@ static inline int rtnetlink_fill_iwinfo(struct sk_buff * skb,
...
@@ -1121,12 +1857,11 @@ static inline int rtnetlink_fill_iwinfo(struct sk_buff * skb,
r
->
__ifi_pad
=
0
;
r
->
__ifi_pad
=
0
;
r
->
ifi_type
=
dev
->
type
;
r
->
ifi_type
=
dev
->
type
;
r
->
ifi_index
=
dev
->
ifindex
;
r
->
ifi_index
=
dev
->
ifindex
;
r
->
ifi_flags
=
dev
->
flags
;
r
->
ifi_flags
=
dev
_get_flags
(
dev
)
;
r
->
ifi_change
=
0
;
/* Wireless changes don't affect those flags */
r
->
ifi_change
=
0
;
/* Wireless changes don't affect those flags */
/* Add the wireless events in the netlink packet */
/* Add the wireless events in the netlink packet */
RTA_PUT
(
skb
,
IFLA_WIRELESS
,
RTA_PUT
(
skb
,
IFLA_WIRELESS
,
event_len
,
event
);
event_len
,
event
);
nlh
->
nlmsg_len
=
skb
->
tail
-
b
;
nlh
->
nlmsg_len
=
skb
->
tail
-
b
;
return
skb
->
len
;
return
skb
->
len
;
...
@@ -1163,7 +1898,7 @@ static inline void rtmsg_iwinfo(struct net_device * dev,
...
@@ -1163,7 +1898,7 @@ static inline void rtmsg_iwinfo(struct net_device * dev,
NETLINK_CB
(
skb
).
dst_group
=
RTNLGRP_LINK
;
NETLINK_CB
(
skb
).
dst_group
=
RTNLGRP_LINK
;
netlink_broadcast
(
rtnl
,
skb
,
0
,
RTNLGRP_LINK
,
GFP_ATOMIC
);
netlink_broadcast
(
rtnl
,
skb
,
0
,
RTNLGRP_LINK
,
GFP_ATOMIC
);
}
}
#endif
/* WE_EVENT_NETLINK */
#endif
/* WE_EVENT_
RT
NETLINK */
/* ---------------------------------------------------------------- */
/* ---------------------------------------------------------------- */
/*
/*
...
@@ -1255,10 +1990,10 @@ void wireless_send_event(struct net_device * dev,
...
@@ -1255,10 +1990,10 @@ void wireless_send_event(struct net_device * dev,
if
(
extra
!=
NULL
)
if
(
extra
!=
NULL
)
memcpy
(((
char
*
)
event
)
+
hdr_len
,
extra
,
extra_len
);
memcpy
(((
char
*
)
event
)
+
hdr_len
,
extra
,
extra_len
);
#ifdef WE_EVENT_NETLINK
#ifdef WE_EVENT_
RT
NETLINK
/*
rtn
etlink event channel */
/*
Send via the RtN
etlink event channel */
rtmsg_iwinfo
(
dev
,
(
char
*
)
event
,
event_len
);
rtmsg_iwinfo
(
dev
,
(
char
*
)
event
,
event_len
);
#endif
/* WE_EVENT_NETLINK */
#endif
/* WE_EVENT_
RT
NETLINK */
/* Cleanup */
/* Cleanup */
kfree
(
event
);
kfree
(
event
);
...
...
net/ieee80211/softmac/ieee80211softmac_assoc.c
View file @
9b7c8489
...
@@ -38,7 +38,7 @@ static void
...
@@ -38,7 +38,7 @@ static void
ieee80211softmac_assoc
(
struct
ieee80211softmac_device
*
mac
,
struct
ieee80211softmac_network
*
net
)
ieee80211softmac_assoc
(
struct
ieee80211softmac_device
*
mac
,
struct
ieee80211softmac_network
*
net
)
{
{
unsigned
long
flags
;
unsigned
long
flags
;
function_enter
();
/* Switch to correct channel for this network */
/* Switch to correct channel for this network */
mac
->
set_channel
(
mac
->
dev
,
net
->
channel
);
mac
->
set_channel
(
mac
->
dev
,
net
->
channel
);
...
@@ -64,8 +64,6 @@ ieee80211softmac_assoc_timeout(void *d)
...
@@ -64,8 +64,6 @@ ieee80211softmac_assoc_timeout(void *d)
struct
ieee80211softmac_device
*
mac
=
(
struct
ieee80211softmac_device
*
)
d
;
struct
ieee80211softmac_device
*
mac
=
(
struct
ieee80211softmac_device
*
)
d
;
unsigned
long
flags
;
unsigned
long
flags
;
function_enter
();
spin_lock_irqsave
(
&
mac
->
lock
,
flags
);
spin_lock_irqsave
(
&
mac
->
lock
,
flags
);
/* we might race against ieee80211softmac_handle_assoc_response,
/* we might race against ieee80211softmac_handle_assoc_response,
* so make sure only one of us does something */
* so make sure only one of us does something */
...
@@ -89,7 +87,6 @@ ieee80211softmac_disassoc(struct ieee80211softmac_device *mac, u16 reason)
...
@@ -89,7 +87,6 @@ ieee80211softmac_disassoc(struct ieee80211softmac_device *mac, u16 reason)
{
{
unsigned
long
flags
;
unsigned
long
flags
;
struct
ieee80211softmac_network
*
found
;
struct
ieee80211softmac_network
*
found
;
function_enter
();
if
(
mac
->
associnfo
.
bssvalid
&&
mac
->
associated
)
{
if
(
mac
->
associnfo
.
bssvalid
&&
mac
->
associated
)
{
found
=
ieee80211softmac_get_network_by_bssid
(
mac
,
mac
->
associnfo
.
bssid
);
found
=
ieee80211softmac_get_network_by_bssid
(
mac
,
mac
->
associnfo
.
bssid
);
...
@@ -173,8 +170,6 @@ ieee80211softmac_assoc_work(void *d)
...
@@ -173,8 +170,6 @@ ieee80211softmac_assoc_work(void *d)
struct
ieee80211_network
*
net
=
NULL
,
*
best
=
NULL
;
struct
ieee80211_network
*
net
=
NULL
,
*
best
=
NULL
;
unsigned
long
flags
;
unsigned
long
flags
;
function_enter
();
/* meh */
/* meh */
if
(
mac
->
associated
)
if
(
mac
->
associated
)
ieee80211softmac_disassoc
(
mac
,
WLAN_REASON_DISASSOC_STA_HAS_LEFT
);
ieee80211softmac_disassoc
(
mac
,
WLAN_REASON_DISASSOC_STA_HAS_LEFT
);
...
@@ -391,8 +386,6 @@ ieee80211softmac_handle_reassoc_req(struct net_device * dev,
...
@@ -391,8 +386,6 @@ ieee80211softmac_handle_reassoc_req(struct net_device * dev,
struct
ieee80211softmac_device
*
mac
=
ieee80211_priv
(
dev
);
struct
ieee80211softmac_device
*
mac
=
ieee80211_priv
(
dev
);
struct
ieee80211softmac_network
*
network
;
struct
ieee80211softmac_network
*
network
;
function_enter
();
network
=
ieee80211softmac_get_network_by_bssid
(
mac
,
resp
->
header
.
addr3
);
network
=
ieee80211softmac_get_network_by_bssid
(
mac
,
resp
->
header
.
addr3
);
if
(
!
network
)
{
if
(
!
network
)
{
dprintkl
(
KERN_INFO
PFX
"reassoc request from unknown network
\n
"
);
dprintkl
(
KERN_INFO
PFX
"reassoc request from unknown network
\n
"
);
...
...
net/ieee80211/softmac/ieee80211softmac_auth.c
View file @
9b7c8489
...
@@ -36,8 +36,6 @@ ieee80211softmac_auth_req(struct ieee80211softmac_device *mac,
...
@@ -36,8 +36,6 @@ ieee80211softmac_auth_req(struct ieee80211softmac_device *mac,
struct
ieee80211softmac_auth_queue_item
*
auth
;
struct
ieee80211softmac_auth_queue_item
*
auth
;
unsigned
long
flags
;
unsigned
long
flags
;
function_enter
();
if
(
net
->
authenticating
)
if
(
net
->
authenticating
)
return
0
;
return
0
;
...
@@ -78,8 +76,6 @@ ieee80211softmac_auth_queue(void *data)
...
@@ -78,8 +76,6 @@ ieee80211softmac_auth_queue(void *data)
struct
ieee80211softmac_network
*
net
;
struct
ieee80211softmac_network
*
net
;
unsigned
long
flags
;
unsigned
long
flags
;
function_enter
();
auth
=
(
struct
ieee80211softmac_auth_queue_item
*
)
data
;
auth
=
(
struct
ieee80211softmac_auth_queue_item
*
)
data
;
net
=
auth
->
net
;
net
=
auth
->
net
;
mac
=
auth
->
mac
;
mac
=
auth
->
mac
;
...
@@ -128,8 +124,6 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
...
@@ -128,8 +124,6 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
unsigned
long
flags
;
unsigned
long
flags
;
u8
*
data
;
u8
*
data
;
function_enter
();
/* Find correct auth queue item */
/* Find correct auth queue item */
spin_lock_irqsave
(
&
mac
->
lock
,
flags
);
spin_lock_irqsave
(
&
mac
->
lock
,
flags
);
list_for_each
(
list_ptr
,
&
mac
->
auth_queue
)
{
list_for_each
(
list_ptr
,
&
mac
->
auth_queue
)
{
...
@@ -277,8 +271,6 @@ ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac,
...
@@ -277,8 +271,6 @@ ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac,
struct
list_head
*
list_ptr
;
struct
list_head
*
list_ptr
;
unsigned
long
flags
;
unsigned
long
flags
;
function_enter
();
/* Lock and reset status flags */
/* Lock and reset status flags */
spin_lock_irqsave
(
&
mac
->
lock
,
flags
);
spin_lock_irqsave
(
&
mac
->
lock
,
flags
);
net
->
authenticating
=
0
;
net
->
authenticating
=
0
;
...
@@ -320,8 +312,6 @@ ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac,
...
@@ -320,8 +312,6 @@ ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac,
{
{
int
ret
;
int
ret
;
function_enter
();
/* Make sure the network is authenticated */
/* Make sure the network is authenticated */
if
(
!
net
->
authenticated
)
if
(
!
net
->
authenticated
)
{
{
...
@@ -348,8 +338,6 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de
...
@@ -348,8 +338,6 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de
struct
ieee80211softmac_network
*
net
=
NULL
;
struct
ieee80211softmac_network
*
net
=
NULL
;
struct
ieee80211softmac_device
*
mac
=
ieee80211_priv
(
dev
);
struct
ieee80211softmac_device
*
mac
=
ieee80211_priv
(
dev
);
function_enter
();
if
(
!
deauth
)
{
if
(
!
deauth
)
{
dprintk
(
"deauth without deauth packet. eek!
\n
"
);
dprintk
(
"deauth without deauth packet. eek!
\n
"
);
return
0
;
return
0
;
...
...
net/ieee80211/softmac/ieee80211softmac_priv.h
View file @
9b7c8489
...
@@ -75,15 +75,6 @@
...
@@ -75,15 +75,6 @@
# define dprintk(f, x...) do {
/* nothing */
} while (0)
# define dprintk(f, x...) do {
/* nothing */
} while (0)
#endif
#endif
#ifdef function_enter
# undef function_enter
#endif
#ifdef CONFIG_IEEE80211_SOFTMAC_DEBUG
# define function_enter() do { printk(KERN_DEBUG PFX "%s:%d:%s()\n", __FILE__, __LINE__, __FUNCTION__); } while (0)
#else
# define function_enter() do {
/* nothing */
} while (0)
#endif
/* private definitions and prototypes */
/* private definitions and prototypes */
/*** prototypes from _scan.c */
/*** prototypes from _scan.c */
...
...
net/ieee80211/softmac/ieee80211softmac_scan.c
View file @
9b7c8489
...
@@ -232,6 +232,13 @@ void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm)
...
@@ -232,6 +232,13 @@ void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm)
sm
->
scanning
=
0
;
sm
->
scanning
=
0
;
spin_unlock_irqrestore
(
&
sm
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
sm
->
lock
,
flags
);
if
(
sm
->
associnfo
.
bssvalid
)
{
struct
ieee80211softmac_network
*
net
;
net
=
ieee80211softmac_get_network_by_bssid
(
sm
,
sm
->
associnfo
.
bssid
);
if
(
net
)
sm
->
set_channel
(
sm
->
dev
,
net
->
channel
);
}
ieee80211softmac_call_events
(
sm
,
IEEE80211SOFTMAC_EVENT_SCAN_FINISHED
,
NULL
);
ieee80211softmac_call_events
(
sm
,
IEEE80211SOFTMAC_EVENT_SCAN_FINISHED
,
NULL
);
}
}
EXPORT_SYMBOL_GPL
(
ieee80211softmac_scan_finished
);
EXPORT_SYMBOL_GPL
(
ieee80211softmac_scan_finished
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment