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
f589cf4f
Commit
f589cf4f
authored
Dec 08, 2011
by
Luciano Coelho
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'wl12xx-next' into for-linville
parents
0052d812
1b04b739
Changes
33
Hide whitespace changes
Inline
Side-by-side
Showing
33 changed files
with
2955 additions
and
2726 deletions
+2955
-2726
drivers/net/wireless/wl12xx/Kconfig
drivers/net/wireless/wl12xx/Kconfig
+0
-10
drivers/net/wireless/wl12xx/Makefile
drivers/net/wireless/wl12xx/Makefile
+0
-3
drivers/net/wireless/wl12xx/acx.c
drivers/net/wireless/wl12xx/acx.c
+82
-64
drivers/net/wireless/wl12xx/acx.h
drivers/net/wireless/wl12xx/acx.h
+48
-35
drivers/net/wireless/wl12xx/boot.c
drivers/net/wireless/wl12xx/boot.c
+15
-0
drivers/net/wireless/wl12xx/cmd.c
drivers/net/wireless/wl12xx/cmd.c
+231
-137
drivers/net/wireless/wl12xx/cmd.h
drivers/net/wireless/wl12xx/cmd.h
+31
-19
drivers/net/wireless/wl12xx/conf.h
drivers/net/wireless/wl12xx/conf.h
+4
-0
drivers/net/wireless/wl12xx/debug.h
drivers/net/wireless/wl12xx/debug.h
+101
-0
drivers/net/wireless/wl12xx/debugfs.c
drivers/net/wireless/wl12xx/debugfs.c
+123
-18
drivers/net/wireless/wl12xx/event.c
drivers/net/wireless/wl12xx/event.c
+132
-82
drivers/net/wireless/wl12xx/event.h
drivers/net/wireless/wl12xx/event.h
+0
-3
drivers/net/wireless/wl12xx/init.c
drivers/net/wireless/wl12xx/init.c
+249
-209
drivers/net/wireless/wl12xx/init.h
drivers/net/wireless/wl12xx/init.h
+4
-3
drivers/net/wireless/wl12xx/io.c
drivers/net/wireless/wl12xx/io.c
+7
-5
drivers/net/wireless/wl12xx/io.h
drivers/net/wireless/wl12xx/io.h
+6
-17
drivers/net/wireless/wl12xx/main.c
drivers/net/wireless/wl12xx/main.c
+1139
-828
drivers/net/wireless/wl12xx/ps.c
drivers/net/wireless/wl12xx/ps.c
+32
-24
drivers/net/wireless/wl12xx/ps.h
drivers/net/wireless/wl12xx/ps.h
+5
-4
drivers/net/wireless/wl12xx/reg.h
drivers/net/wireless/wl12xx/reg.h
+1
-1
drivers/net/wireless/wl12xx/rx.c
drivers/net/wireless/wl12xx/rx.c
+14
-20
drivers/net/wireless/wl12xx/scan.c
drivers/net/wireless/wl12xx/scan.c
+64
-38
drivers/net/wireless/wl12xx/scan.h
drivers/net/wireless/wl12xx/scan.h
+5
-3
drivers/net/wireless/wl12xx/sdio.c
drivers/net/wireless/wl12xx/sdio.c
+109
-150
drivers/net/wireless/wl12xx/sdio_test.c
drivers/net/wireless/wl12xx/sdio_test.c
+0
-543
drivers/net/wireless/wl12xx/spi.c
drivers/net/wireless/wl12xx/spi.c
+81
-133
drivers/net/wireless/wl12xx/testmode.c
drivers/net/wireless/wl12xx/testmode.c
+57
-19
drivers/net/wireless/wl12xx/tx.c
drivers/net/wireless/wl12xx/tx.c
+212
-159
drivers/net/wireless/wl12xx/tx.h
drivers/net/wireless/wl12xx/tx.h
+8
-3
drivers/net/wireless/wl12xx/wl12xx.h
drivers/net/wireless/wl12xx/wl12xx.h
+189
-188
drivers/net/wireless/wl12xx/wl12xx_80211.h
drivers/net/wireless/wl12xx/wl12xx_80211.h
+0
-5
drivers/net/wireless/wl12xx/wl12xx_platform_data.c
drivers/net/wireless/wl12xx/wl12xx_platform_data.c
+2
-2
include/linux/wl12xx.h
include/linux/wl12xx.h
+4
-1
No files found.
drivers/net/wireless/wl12xx/Kconfig
View file @
f589cf4f
...
...
@@ -42,16 +42,6 @@ config WL12XX_SDIO
If you choose to build a module, it'll be called wl12xx_sdio.
Say N if unsure.
config WL12XX_SDIO_TEST
tristate "TI wl12xx SDIO testing support"
depends on WL12XX && MMC && WL12XX_SDIO
default n
---help---
This module adds support for the SDIO bus testing with the
TI wl12xx chipsets. You probably don't want this unless you are
testing a new hardware platform. Select this if you want to test the
SDIO bus which is connected to the wl12xx chip.
config WL12XX_PLATFORM_DATA
bool
depends on WL12XX_SDIO != n || WL1251_SDIO != n
...
...
drivers/net/wireless/wl12xx/Makefile
View file @
f589cf4f
...
...
@@ -3,14 +3,11 @@ wl12xx-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \
wl12xx_spi-objs
=
spi.o
wl12xx_sdio-objs
=
sdio.o
wl12xx_sdio_test-objs
=
sdio_test.o
wl12xx-$(CONFIG_NL80211_TESTMODE)
+=
testmode.o
obj-$(CONFIG_WL12XX)
+=
wl12xx.o
obj-$(CONFIG_WL12XX_SPI)
+=
wl12xx_spi.o
obj-$(CONFIG_WL12XX_SDIO)
+=
wl12xx_sdio.o
obj-$(CONFIG_WL12XX_SDIO_TEST)
+=
wl12xx_sdio_test.o
# small builtin driver bit
obj-$(CONFIG_WL12XX_PLATFORM_DATA)
+=
wl12xx_platform_data.o
drivers/net/wireless/wl12xx/acx.c
View file @
f589cf4f
...
...
@@ -29,11 +29,12 @@
#include <linux/slab.h>
#include "wl12xx.h"
#include "debug.h"
#include "wl12xx_80211.h"
#include "reg.h"
#include "ps.h"
int
wl1271_acx_wake_up_conditions
(
struct
wl1271
*
wl
)
int
wl1271_acx_wake_up_conditions
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
acx_wake_up_condition
*
wake_up
;
int
ret
;
...
...
@@ -46,7 +47,7 @@ int wl1271_acx_wake_up_conditions(struct wl1271 *wl)
goto
out
;
}
wake_up
->
role_id
=
wl
->
role_id
;
wake_up
->
role_id
=
wl
vif
->
role_id
;
wake_up
->
wake_up_event
=
wl
->
conf
.
conn
.
wake_up_event
;
wake_up
->
listen_interval
=
wl
->
conf
.
conn
.
listen_interval
;
...
...
@@ -84,7 +85,8 @@ int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth)
return
ret
;
}
int
wl1271_acx_tx_power
(
struct
wl1271
*
wl
,
int
power
)
int
wl1271_acx_tx_power
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
int
power
)
{
struct
acx_current_tx_power
*
acx
;
int
ret
;
...
...
@@ -100,7 +102,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power)
goto
out
;
}
acx
->
role_id
=
wl
->
role_id
;
acx
->
role_id
=
wl
vif
->
role_id
;
acx
->
current_tx_power
=
power
*
10
;
ret
=
wl1271_cmd_configure
(
wl
,
DOT11_CUR_TX_PWR
,
acx
,
sizeof
(
*
acx
));
...
...
@@ -114,7 +116,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power)
return
ret
;
}
int
wl1271_acx_feature_cfg
(
struct
wl1271
*
wl
)
int
wl1271_acx_feature_cfg
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
acx_feature_config
*
feature
;
int
ret
;
...
...
@@ -128,7 +130,7 @@ int wl1271_acx_feature_cfg(struct wl1271 *wl)
}
/* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
feature
->
role_id
=
wl
->
role_id
;
feature
->
role_id
=
wl
vif
->
role_id
;
feature
->
data_flow_options
=
0
;
feature
->
options
=
0
;
...
...
@@ -210,7 +212,8 @@ int wl1271_acx_pd_threshold(struct wl1271 *wl)
return
ret
;
}
int
wl1271_acx_slot
(
struct
wl1271
*
wl
,
enum
acx_slot_type
slot_time
)
int
wl1271_acx_slot
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
enum
acx_slot_type
slot_time
)
{
struct
acx_slot
*
slot
;
int
ret
;
...
...
@@ -223,7 +226,7 @@ int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time)
goto
out
;
}
slot
->
role_id
=
wl
->
role_id
;
slot
->
role_id
=
wl
vif
->
role_id
;
slot
->
wone_index
=
STATION_WONE_INDEX
;
slot
->
slot_time
=
slot_time
;
...
...
@@ -238,8 +241,8 @@ int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time)
return
ret
;
}
int
wl1271_acx_group_address_tbl
(
struct
wl1271
*
wl
,
bool
enable
,
void
*
mc_list
,
u32
mc_list_len
)
int
wl1271_acx_group_address_tbl
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
bool
enable
,
void
*
mc_list
,
u32
mc_list_len
)
{
struct
acx_dot11_grp_addr_tbl
*
acx
;
int
ret
;
...
...
@@ -253,7 +256,7 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable,
}
/* MAC filtering */
acx
->
role_id
=
wl
->
role_id
;
acx
->
role_id
=
wl
vif
->
role_id
;
acx
->
enabled
=
enable
;
acx
->
num_groups
=
mc_list_len
;
memcpy
(
acx
->
mac_table
,
mc_list
,
mc_list_len
*
ETH_ALEN
);
...
...
@@ -270,7 +273,8 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable,
return
ret
;
}
int
wl1271_acx_service_period_timeout
(
struct
wl1271
*
wl
)
int
wl1271_acx_service_period_timeout
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
acx_rx_timeout
*
rx_timeout
;
int
ret
;
...
...
@@ -283,7 +287,7 @@ int wl1271_acx_service_period_timeout(struct wl1271 *wl)
wl1271_debug
(
DEBUG_ACX
,
"acx service period timeout"
);
rx_timeout
->
role_id
=
wl
->
role_id
;
rx_timeout
->
role_id
=
wl
vif
->
role_id
;
rx_timeout
->
ps_poll_timeout
=
cpu_to_le16
(
wl
->
conf
.
rx
.
ps_poll_timeout
);
rx_timeout
->
upsd_timeout
=
cpu_to_le16
(
wl
->
conf
.
rx
.
upsd_timeout
);
...
...
@@ -300,7 +304,8 @@ int wl1271_acx_service_period_timeout(struct wl1271 *wl)
return
ret
;
}
int
wl1271_acx_rts_threshold
(
struct
wl1271
*
wl
,
u32
rts_threshold
)
int
wl1271_acx_rts_threshold
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u32
rts_threshold
)
{
struct
acx_rts_threshold
*
rts
;
int
ret
;
...
...
@@ -320,7 +325,7 @@ int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold)
goto
out
;
}
rts
->
role_id
=
wl
->
role_id
;
rts
->
role_id
=
wl
vif
->
role_id
;
rts
->
threshold
=
cpu_to_le16
((
u16
)
rts_threshold
);
ret
=
wl1271_cmd_configure
(
wl
,
DOT11_RTS_THRESHOLD
,
rts
,
sizeof
(
*
rts
));
...
...
@@ -363,7 +368,8 @@ int wl1271_acx_dco_itrim_params(struct wl1271 *wl)
return
ret
;
}
int
wl1271_acx_beacon_filter_opt
(
struct
wl1271
*
wl
,
bool
enable_filter
)
int
wl1271_acx_beacon_filter_opt
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
bool
enable_filter
)
{
struct
acx_beacon_filter_option
*
beacon_filter
=
NULL
;
int
ret
=
0
;
...
...
@@ -380,7 +386,7 @@ int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter)
goto
out
;
}
beacon_filter
->
role_id
=
wl
->
role_id
;
beacon_filter
->
role_id
=
wl
vif
->
role_id
;
beacon_filter
->
enable
=
enable_filter
;
/*
...
...
@@ -401,7 +407,8 @@ int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter)
return
ret
;
}
int
wl1271_acx_beacon_filter_table
(
struct
wl1271
*
wl
)
int
wl1271_acx_beacon_filter_table
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
acx_beacon_filter_ie_table
*
ie_table
;
int
i
,
idx
=
0
;
...
...
@@ -417,7 +424,7 @@ int wl1271_acx_beacon_filter_table(struct wl1271 *wl)
}
/* configure default beacon pass-through rules */
ie_table
->
role_id
=
wl
->
role_id
;
ie_table
->
role_id
=
wl
vif
->
role_id
;
ie_table
->
num_ie
=
0
;
for
(
i
=
0
;
i
<
wl
->
conf
.
conn
.
bcn_filt_ie_count
;
i
++
)
{
struct
conf_bcn_filt_rule
*
r
=
&
(
wl
->
conf
.
conn
.
bcn_filt_ie
[
i
]);
...
...
@@ -458,7 +465,8 @@ int wl1271_acx_beacon_filter_table(struct wl1271 *wl)
#define ACX_CONN_MONIT_DISABLE_VALUE 0xffffffff
int
wl1271_acx_conn_monit_params
(
struct
wl1271
*
wl
,
bool
enable
)
int
wl1271_acx_conn_monit_params
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
bool
enable
)
{
struct
acx_conn_monit_params
*
acx
;
u32
threshold
=
ACX_CONN_MONIT_DISABLE_VALUE
;
...
...
@@ -479,7 +487,7 @@ int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable)
timeout
=
wl
->
conf
.
conn
.
bss_lose_timeout
;
}
acx
->
role_id
=
wl
->
role_id
;
acx
->
role_id
=
wl
vif
->
role_id
;
acx
->
synch_fail_thold
=
cpu_to_le32
(
threshold
);
acx
->
bss_lose_timeout
=
cpu_to_le32
(
timeout
);
...
...
@@ -582,7 +590,7 @@ int wl1271_acx_cca_threshold(struct wl1271 *wl)
return
ret
;
}
int
wl1271_acx_bcn_dtim_options
(
struct
wl1271
*
wl
)
int
wl1271_acx_bcn_dtim_options
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
acx_beacon_broadcast
*
bb
;
int
ret
;
...
...
@@ -595,7 +603,7 @@ int wl1271_acx_bcn_dtim_options(struct wl1271 *wl)
goto
out
;
}
bb
->
role_id
=
wl
->
role_id
;
bb
->
role_id
=
wl
vif
->
role_id
;
bb
->
beacon_rx_timeout
=
cpu_to_le16
(
wl
->
conf
.
conn
.
beacon_rx_timeout
);
bb
->
broadcast_timeout
=
cpu_to_le16
(
wl
->
conf
.
conn
.
broadcast_timeout
);
bb
->
rx_broadcast_in_ps
=
wl
->
conf
.
conn
.
rx_broadcast_in_ps
;
...
...
@@ -612,7 +620,7 @@ int wl1271_acx_bcn_dtim_options(struct wl1271 *wl)
return
ret
;
}
int
wl1271_acx_aid
(
struct
wl1271
*
wl
,
u16
aid
)
int
wl1271_acx_aid
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u16
aid
)
{
struct
acx_aid
*
acx_aid
;
int
ret
;
...
...
@@ -625,7 +633,7 @@ int wl1271_acx_aid(struct wl1271 *wl, u16 aid)
goto
out
;
}
acx_aid
->
role_id
=
wl
->
role_id
;
acx_aid
->
role_id
=
wl
vif
->
role_id
;
acx_aid
->
aid
=
cpu_to_le16
(
aid
);
ret
=
wl1271_cmd_configure
(
wl
,
ACX_AID
,
acx_aid
,
sizeof
(
*
acx_aid
));
...
...
@@ -668,7 +676,8 @@ int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask)
return
ret
;
}
int
wl1271_acx_set_preamble
(
struct
wl1271
*
wl
,
enum
acx_preamble_type
preamble
)
int
wl1271_acx_set_preamble
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
enum
acx_preamble_type
preamble
)
{
struct
acx_preamble
*
acx
;
int
ret
;
...
...
@@ -681,7 +690,7 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble)
goto
out
;
}
acx
->
role_id
=
wl
->
role_id
;
acx
->
role_id
=
wl
vif
->
role_id
;
acx
->
preamble
=
preamble
;
ret
=
wl1271_cmd_configure
(
wl
,
ACX_PREAMBLE_TYPE
,
acx
,
sizeof
(
*
acx
));
...
...
@@ -695,7 +704,7 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble)
return
ret
;
}
int
wl1271_acx_cts_protect
(
struct
wl1271
*
wl
,
int
wl1271_acx_cts_protect
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
enum
acx_ctsprotect_type
ctsprotect
)
{
struct
acx_ctsprotect
*
acx
;
...
...
@@ -709,7 +718,7 @@ int wl1271_acx_cts_protect(struct wl1271 *wl,
goto
out
;
}
acx
->
role_id
=
wl
->
role_id
;
acx
->
role_id
=
wl
vif
->
role_id
;
acx
->
ctsprotect
=
ctsprotect
;
ret
=
wl1271_cmd_configure
(
wl
,
ACX_CTS_PROTECTION
,
acx
,
sizeof
(
*
acx
));
...
...
@@ -739,7 +748,7 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats)
return
0
;
}
int
wl1271_acx_sta_rate_policies
(
struct
wl1271
*
wl
)
int
wl1271_acx_sta_rate_policies
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
acx_rate_policy
*
acx
;
struct
conf_tx_rate_class
*
c
=
&
wl
->
conf
.
tx
.
sta_rc_conf
;
...
...
@@ -755,11 +764,11 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl)
}
wl1271_debug
(
DEBUG_ACX
,
"basic_rate: 0x%x, full_rate: 0x%x"
,
wl
->
basic_rate
,
wl
->
rate_set
);
wl
vif
->
basic_rate
,
wlvif
->
rate_set
);
/* configure one basic rate class */
acx
->
rate_policy_idx
=
cpu_to_le32
(
ACX_TX_BASIC_RATE
);
acx
->
rate_policy
.
enabled_rates
=
cpu_to_le32
(
wl
->
basic_rate
);
acx
->
rate_policy_idx
=
cpu_to_le32
(
wlvif
->
sta
.
basic_rate_idx
);
acx
->
rate_policy
.
enabled_rates
=
cpu_to_le32
(
wl
vif
->
basic_rate
);
acx
->
rate_policy
.
short_retry_limit
=
c
->
short_retry_limit
;
acx
->
rate_policy
.
long_retry_limit
=
c
->
long_retry_limit
;
acx
->
rate_policy
.
aflags
=
c
->
aflags
;
...
...
@@ -771,8 +780,8 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl)
}
/* configure one AP supported rate class */
acx
->
rate_policy_idx
=
cpu_to_le32
(
ACX_TX_AP_FULL_RATE
);
acx
->
rate_policy
.
enabled_rates
=
cpu_to_le32
(
wl
->
rate_set
);
acx
->
rate_policy_idx
=
cpu_to_le32
(
wlvif
->
sta
.
ap_rate_idx
);
acx
->
rate_policy
.
enabled_rates
=
cpu_to_le32
(
wl
vif
->
rate_set
);
acx
->
rate_policy
.
short_retry_limit
=
c
->
short_retry_limit
;
acx
->
rate_policy
.
long_retry_limit
=
c
->
long_retry_limit
;
acx
->
rate_policy
.
aflags
=
c
->
aflags
;
...
...
@@ -788,7 +797,7 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl)
* (p2p packets should always go out with OFDM rates, even
* if we are currently connected to 11b AP)
*/
acx
->
rate_policy_idx
=
cpu_to_le32
(
ACX_TX_BASIC_RATE_P2P
);
acx
->
rate_policy_idx
=
cpu_to_le32
(
wlvif
->
sta
.
p2p_rate_idx
);
acx
->
rate_policy
.
enabled_rates
=
cpu_to_le32
(
CONF_TX_RATE_MASK_BASIC_P2P
);
acx
->
rate_policy
.
short_retry_limit
=
c
->
short_retry_limit
;
...
...
@@ -839,8 +848,8 @@ int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c,
return
ret
;
}
int
wl1271_acx_ac_cfg
(
struct
wl1271
*
wl
,
u8
ac
,
u8
cw_min
,
u16
cw_max
,
u8
aifsn
,
u16
txop
)
int
wl1271_acx_ac_cfg
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
a
c
,
u8
cw_min
,
u16
cw_max
,
u8
a
ifsn
,
u16
txop
)
{
struct
acx_ac_cfg
*
acx
;
int
ret
=
0
;
...
...
@@ -855,7 +864,7 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
goto
out
;
}
acx
->
role_id
=
wl
->
role_id
;
acx
->
role_id
=
wl
vif
->
role_id
;
acx
->
ac
=
ac
;
acx
->
cw_min
=
cw_min
;
acx
->
cw_max
=
cpu_to_le16
(
cw_max
);
...
...
@@ -873,7 +882,8 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
return
ret
;
}
int
wl1271_acx_tid_cfg
(
struct
wl1271
*
wl
,
u8
queue_id
,
u8
channel_type
,
int
wl1271_acx_tid_cfg
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
queue_id
,
u8
channel_type
,
u8
tsid
,
u8
ps_scheme
,
u8
ack_policy
,
u32
apsd_conf0
,
u32
apsd_conf1
)
{
...
...
@@ -889,7 +899,7 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
goto
out
;
}
acx
->
role_id
=
wl
->
role_id
;
acx
->
role_id
=
wl
vif
->
role_id
;
acx
->
queue_id
=
queue_id
;
acx
->
channel_type
=
channel_type
;
acx
->
tsid
=
tsid
;
...
...
@@ -1098,7 +1108,8 @@ int wl1271_acx_init_rx_interrupt(struct wl1271 *wl)
return
ret
;
}
int
wl1271_acx_bet_enable
(
struct
wl1271
*
wl
,
bool
enable
)
int
wl1271_acx_bet_enable
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
bool
enable
)
{
struct
wl1271_acx_bet_enable
*
acx
=
NULL
;
int
ret
=
0
;
...
...
@@ -1114,7 +1125,7 @@ int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable)
goto
out
;
}
acx
->
role_id
=
wl
->
role_id
;
acx
->
role_id
=
wl
vif
->
role_id
;
acx
->
enable
=
enable
?
CONF_BET_MODE_ENABLE
:
CONF_BET_MODE_DISABLE
;
acx
->
max_consecutive
=
wl
->
conf
.
conn
.
bet_max_consecutive
;
...
...
@@ -1129,7 +1140,8 @@ int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable)
return
ret
;
}
int
wl1271_acx_arp_ip_filter
(
struct
wl1271
*
wl
,
u8
enable
,
__be32
address
)
int
wl1271_acx_arp_ip_filter
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
enable
,
__be32
address
)
{
struct
wl1271_acx_arp_filter
*
acx
;
int
ret
;
...
...
@@ -1142,7 +1154,7 @@ int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address)
goto
out
;
}
acx
->
role_id
=
wl
->
role_id
;
acx
->
role_id
=
wl
vif
->
role_id
;
acx
->
version
=
ACX_IPV4_VERSION
;
acx
->
enable
=
enable
;
...
...
@@ -1189,7 +1201,8 @@ int wl1271_acx_pm_config(struct wl1271 *wl)
return
ret
;
}
int
wl1271_acx_keep_alive_mode
(
struct
wl1271
*
wl
,
bool
enable
)
int
wl1271_acx_keep_alive_mode
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
bool
enable
)
{
struct
wl1271_acx_keep_alive_mode
*
acx
=
NULL
;
int
ret
=
0
;
...
...
@@ -1202,7 +1215,7 @@ int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable)
goto
out
;
}
acx
->
role_id
=
wl
->
role_id
;
acx
->
role_id
=
wl
vif
->
role_id
;
acx
->
enabled
=
enable
;
ret
=
wl1271_cmd_configure
(
wl
,
ACX_KEEP_ALIVE_MODE
,
acx
,
sizeof
(
*
acx
));
...
...
@@ -1216,7 +1229,8 @@ int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable)
return
ret
;
}
int
wl1271_acx_keep_alive_config
(
struct
wl1271
*
wl
,
u8
index
,
u8
tpl_valid
)
int
wl1271_acx_keep_alive_config
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
index
,
u8
tpl_valid
)
{
struct
wl1271_acx_keep_alive_config
*
acx
=
NULL
;
int
ret
=
0
;
...
...
@@ -1229,7 +1243,7 @@ int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid)
goto
out
;
}
acx
->
role_id
=
wl
->
role_id
;
acx
->
role_id
=
wl
vif
->
role_id
;
acx
->
period
=
cpu_to_le32
(
wl
->
conf
.
conn
.
keep_alive_interval
);
acx
->
index
=
index
;
acx
->
tpl_validation
=
tpl_valid
;
...
...
@@ -1247,8 +1261,8 @@ int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid)
return
ret
;
}
int
wl1271_acx_rssi_snr_trigger
(
struct
wl1271
*
wl
,
bool
enable
,
s16
thold
,
u8
hyst
)
int
wl1271_acx_rssi_snr_trigger
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
bool
enable
,
s16
thold
,
u8
hyst
)
{
struct
wl1271_acx_rssi_snr_trigger
*
acx
=
NULL
;
int
ret
=
0
;
...
...
@@ -1261,9 +1275,9 @@ int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable,
goto
out
;
}
wl
->
last_rssi_event
=
-
1
;
wl
vif
->
last_rssi_event
=
-
1
;
acx
->
role_id
=
wl
->
role_id
;
acx
->
role_id
=
wl
vif
->
role_id
;
acx
->
pacing
=
cpu_to_le16
(
wl
->
conf
.
roam_trigger
.
trigger_pacing
);
acx
->
metric
=
WL1271_ACX_TRIG_METRIC_RSSI_BEACON
;
acx
->
type
=
WL1271_ACX_TRIG_TYPE_EDGE
;
...
...
@@ -1288,7 +1302,8 @@ int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable,
return
ret
;
}
int
wl1271_acx_rssi_snr_avg_weights
(
struct
wl1271
*
wl
)
int
wl1271_acx_rssi_snr_avg_weights
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
wl1271_acx_rssi_snr_avg_weights
*
acx
=
NULL
;
struct
conf_roam_trigger_settings
*
c
=
&
wl
->
conf
.
roam_trigger
;
...
...
@@ -1302,7 +1317,7 @@ int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl)
goto
out
;
}
acx
->
role_id
=
wl
->
role_id
;
acx
->
role_id
=
wl
vif
->
role_id
;
acx
->
rssi_beacon
=
c
->
avg_weight_rssi_beacon
;
acx
->
rssi_data
=
c
->
avg_weight_rssi_data
;
acx
->
snr_beacon
=
c
->
avg_weight_snr_beacon
;
...
...
@@ -1367,6 +1382,7 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
}
int
wl1271_acx_set_ht_information
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u16
ht_operation_mode
)
{
struct
wl1271_acx_ht_information
*
acx
;
...
...
@@ -1380,7 +1396,7 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl,
goto
out
;
}
acx
->
role_id
=
wl
->
role_id
;
acx
->
role_id
=
wl
vif
->
role_id
;
acx
->
ht_protection
=
(
u8
)(
ht_operation_mode
&
IEEE80211_HT_OP_MODE_PROTECTION
);
acx
->
rifs_mode
=
0
;
...
...
@@ -1402,7 +1418,8 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl,
}
/* Configure BA session initiator/receiver parameters setting in the FW. */
int
wl12xx_acx_set_ba_initiator_policy
(
struct
wl1271
*
wl
)
int
wl12xx_acx_set_ba_initiator_policy
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
wl1271_acx_ba_initiator_policy
*
acx
;
int
ret
;
...
...
@@ -1416,7 +1433,7 @@ int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl)
}
/* set for the current role */
acx
->
role_id
=
wl
->
role_id
;
acx
->
role_id
=
wl
vif
->
role_id
;
acx
->
tid_bitmap
=
wl
->
conf
.
ht
.
tx_ba_tid_bitmap
;
acx
->
win_size
=
wl
->
conf
.
ht
.
tx_ba_win_size
;
acx
->
inactivity_timeout
=
wl
->
conf
.
ht
.
inactivity_timeout
;
...
...
@@ -1494,7 +1511,8 @@ int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime)
return
ret
;
}
int
wl1271_acx_ps_rx_streaming
(
struct
wl1271
*
wl
,
bool
enable
)
int
wl1271_acx_ps_rx_streaming
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
bool
enable
)
{
struct
wl1271_acx_ps_rx_streaming
*
rx_streaming
;
u32
conf_queues
,
enable_queues
;
...
...
@@ -1523,7 +1541,7 @@ int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable)
if
(
!
(
conf_queues
&
BIT
(
i
)))
continue
;
rx_streaming
->
role_id
=
wl
->
role_id
;
rx_streaming
->
role_id
=
wl
vif
->
role_id
;
rx_streaming
->
tid
=
i
;
rx_streaming
->
enable
=
enable_queues
&
BIT
(
i
);
rx_streaming
->
period
=
wl
->
conf
.
rx_streaming
.
interval
;
...
...
@@ -1542,7 +1560,7 @@ int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable)
return
ret
;
}
int
wl1271_acx_ap_max_tx_retry
(
struct
wl1271
*
wl
)
int
wl1271_acx_ap_max_tx_retry
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
wl1271_acx_ap_max_tx_retry
*
acx
=
NULL
;
int
ret
;
...
...
@@ -1553,7 +1571,7 @@ int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl)
if
(
!
acx
)
return
-
ENOMEM
;
acx
->
role_id
=
wl
->
role_id
;
acx
->
role_id
=
wl
vif
->
role_id
;
acx
->
max_tx_retry
=
cpu_to_le16
(
wl
->
conf
.
tx
.
max_tx_retries
);
ret
=
wl1271_cmd_configure
(
wl
,
ACX_MAX_TX_FAILURE
,
acx
,
sizeof
(
*
acx
));
...
...
@@ -1567,7 +1585,7 @@ int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl)
return
ret
;
}
int
wl12
71_acx_config_ps
(
struct
wl1271
*
wl
)
int
wl12
xx_acx_config_ps
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
wl1271_acx_config_ps
*
config_ps
;
int
ret
;
...
...
@@ -1582,7 +1600,7 @@ int wl1271_acx_config_ps(struct wl1271 *wl)
config_ps
->
exit_retries
=
wl
->
conf
.
conn
.
psm_exit_retries
;
config_ps
->
enter_retries
=
wl
->
conf
.
conn
.
psm_entry_retries
;
config_ps
->
null_data_rate
=
cpu_to_le32
(
wl
->
basic_rate
);
config_ps
->
null_data_rate
=
cpu_to_le32
(
wl
vif
->
basic_rate
);
ret
=
wl1271_cmd_configure
(
wl
,
ACX_CONFIG_PS
,
config_ps
,
sizeof
(
*
config_ps
));
...
...
drivers/net/wireless/wl12xx/acx.h
View file @
f589cf4f
...
...
@@ -654,11 +654,6 @@ struct acx_rate_class {
u8
reserved
;
};
#define ACX_TX_BASIC_RATE 0
#define ACX_TX_AP_FULL_RATE 1
#define ACX_TX_BASIC_RATE_P2P 2
#define ACX_TX_AP_MODE_MGMT_RATE 4
#define ACX_TX_AP_MODE_BCST_RATE 5
struct
acx_rate_policy
{
struct
acx_header
header
;
...
...
@@ -1234,39 +1229,49 @@ enum {
};
int
wl1271_acx_wake_up_conditions
(
struct
wl1271
*
wl
);
int
wl1271_acx_wake_up_conditions
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl1271_acx_sleep_auth
(
struct
wl1271
*
wl
,
u8
sleep_auth
);
int
wl1271_acx_tx_power
(
struct
wl1271
*
wl
,
int
power
);
int
wl1271_acx_feature_cfg
(
struct
wl1271
*
wl
);
int
wl1271_acx_tx_power
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
int
power
);
int
wl1271_acx_feature_cfg
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl1271_acx_mem_map
(
struct
wl1271
*
wl
,
struct
acx_header
*
mem_map
,
size_t
len
);
int
wl1271_acx_rx_msdu_life_time
(
struct
wl1271
*
wl
);
int
wl1271_acx_pd_threshold
(
struct
wl1271
*
wl
);
int
wl1271_acx_slot
(
struct
wl1271
*
wl
,
enum
acx_slot_type
slot_time
);
int
wl1271_acx_group_address_tbl
(
struct
wl1271
*
wl
,
bool
enable
,
void
*
mc_list
,
u32
mc_list_len
);
int
wl1271_acx_service_period_timeout
(
struct
wl1271
*
wl
);
int
wl1271_acx_rts_threshold
(
struct
wl1271
*
wl
,
u32
rts_threshold
);
int
wl1271_acx_slot
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
enum
acx_slot_type
slot_time
);
int
wl1271_acx_group_address_tbl
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
bool
enable
,
void
*
mc_list
,
u32
mc_list_len
);
int
wl1271_acx_service_period_timeout
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl1271_acx_rts_threshold
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u32
rts_threshold
);
int
wl1271_acx_dco_itrim_params
(
struct
wl1271
*
wl
);
int
wl1271_acx_beacon_filter_opt
(
struct
wl1271
*
wl
,
bool
enable_filter
);
int
wl1271_acx_beacon_filter_table
(
struct
wl1271
*
wl
);
int
wl1271_acx_conn_monit_params
(
struct
wl1271
*
wl
,
bool
enable
);
int
wl1271_acx_beacon_filter_opt
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
bool
enable_filter
);
int
wl1271_acx_beacon_filter_table
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl1271_acx_conn_monit_params
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
bool
enable
);
int
wl1271_acx_sg_enable
(
struct
wl1271
*
wl
,
bool
enable
);
int
wl12xx_acx_sg_cfg
(
struct
wl1271
*
wl
);
int
wl1271_acx_cca_threshold
(
struct
wl1271
*
wl
);
int
wl1271_acx_bcn_dtim_options
(
struct
wl1271
*
wl
);
int
wl1271_acx_aid
(
struct
wl1271
*
wl
,
u16
aid
);
int
wl1271_acx_bcn_dtim_options
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl1271_acx_aid
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u16
aid
);
int
wl1271_acx_event_mbox_mask
(
struct
wl1271
*
wl
,
u32
event_mask
);
int
wl1271_acx_set_preamble
(
struct
wl1271
*
wl
,
enum
acx_preamble_type
preamble
);
int
wl1271_acx_cts_protect
(
struct
wl1271
*
wl
,
int
wl1271_acx_set_preamble
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
enum
acx_preamble_type
preamble
);
int
wl1271_acx_cts_protect
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
enum
acx_ctsprotect_type
ctsprotect
);
int
wl1271_acx_statistics
(
struct
wl1271
*
wl
,
struct
acx_statistics
*
stats
);
int
wl1271_acx_sta_rate_policies
(
struct
wl1271
*
wl
);
int
wl1271_acx_sta_rate_policies
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl1271_acx_ap_rate_policy
(
struct
wl1271
*
wl
,
struct
conf_tx_rate_class
*
c
,
u8
idx
);
int
wl1271_acx_ac_cfg
(
struct
wl1271
*
wl
,
u8
ac
,
u8
cw_min
,
u16
cw_max
,
u8
aifsn
,
u16
txop
);
int
wl1271_acx_tid_cfg
(
struct
wl1271
*
wl
,
u8
queue_id
,
u8
channel_type
,
int
wl1271_acx_ac_cfg
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
ac
,
u8
cw_min
,
u16
cw_max
,
u8
aifsn
,
u16
txop
);
int
wl1271_acx_tid_cfg
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
queue_id
,
u8
channel_type
,
u8
tsid
,
u8
ps_scheme
,
u8
ack_policy
,
u32
apsd_conf0
,
u32
apsd_conf1
);
int
wl1271_acx_frag_threshold
(
struct
wl1271
*
wl
,
u32
frag_threshold
);
...
...
@@ -1276,26 +1281,34 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl);
int
wl1271_acx_host_if_cfg_bitmap
(
struct
wl1271
*
wl
,
u32
host_cfg_bitmap
);
int
wl1271_acx_init_rx_interrupt
(
struct
wl1271
*
wl
);
int
wl1271_acx_smart_reflex
(
struct
wl1271
*
wl
);
int
wl1271_acx_bet_enable
(
struct
wl1271
*
wl
,
bool
enable
);
int
wl1271_acx_arp_ip_filter
(
struct
wl1271
*
wl
,
u8
enable
,
__be32
address
);
int
wl1271_acx_bet_enable
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
bool
enable
);
int
wl1271_acx_arp_ip_filter
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
enable
,
__be32
address
);
int
wl1271_acx_pm_config
(
struct
wl1271
*
wl
);
int
wl1271_acx_keep_alive_mode
(
struct
wl1271
*
wl
,
bool
enable
);
int
wl1271_acx_keep_alive_config
(
struct
wl1271
*
wl
,
u8
index
,
u8
tpl_valid
);
int
wl1271_acx_rssi_snr_trigger
(
struct
wl1271
*
wl
,
bool
enable
,
s16
thold
,
u8
hyst
);
int
wl1271_acx_rssi_snr_avg_weights
(
struct
wl1271
*
wl
);
int
wl1271_acx_keep_alive_mode
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
vif
,
bool
enable
);
int
wl1271_acx_keep_alive_config
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
index
,
u8
tpl_valid
);
int
wl1271_acx_rssi_snr_trigger
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
bool
enable
,
s16
thold
,
u8
hyst
);
int
wl1271_acx_rssi_snr_avg_weights
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl1271_acx_set_ht_capabilities
(
struct
wl1271
*
wl
,
struct
ieee80211_sta_ht_cap
*
ht_cap
,
bool
allow_ht_operation
,
u8
hlid
);
int
wl1271_acx_set_ht_information
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u16
ht_operation_mode
);
int
wl12xx_acx_set_ba_initiator_policy
(
struct
wl1271
*
wl
);
int
wl12xx_acx_set_ba_initiator_policy
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl12xx_acx_set_ba_receiver_session
(
struct
wl1271
*
wl
,
u8
tid_index
,
u16
ssn
,
bool
enable
,
u8
peer_hlid
);
int
wl1271_acx_tsf_info
(
struct
wl1271
*
wl
,
u64
*
mactime
);
int
wl1271_acx_ps_rx_streaming
(
struct
wl1271
*
wl
,
bool
enable
);
int
wl1271_acx_ap_max_tx_retry
(
struct
wl1271
*
wl
);
int
wl1271_acx_config_ps
(
struct
wl1271
*
wl
);
int
wl1271_acx_ps_rx_streaming
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
bool
enable
);
int
wl1271_acx_ap_max_tx_retry
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl12xx_acx_config_ps
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl1271_acx_set_inconnection_sta
(
struct
wl1271
*
wl
,
u8
*
addr
);
int
wl1271_acx_fm_coex
(
struct
wl1271
*
wl
);
int
wl12xx_acx_set_rate_mgmt_params
(
struct
wl1271
*
wl
);
...
...
drivers/net/wireless/wl12xx/boot.c
View file @
f589cf4f
...
...
@@ -25,6 +25,7 @@
#include <linux/wl12xx.h>
#include <linux/export.h>
#include "debug.h"
#include "acx.h"
#include "reg.h"
#include "boot.h"
...
...
@@ -347,6 +348,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
nvs_ptr
+=
3
;
for
(
i
=
0
;
i
<
burst_len
;
i
++
)
{
if
(
nvs_ptr
+
3
>=
(
u8
*
)
wl
->
nvs
+
nvs_len
)
goto
out_badnvs
;
val
=
(
nvs_ptr
[
0
]
|
(
nvs_ptr
[
1
]
<<
8
)
|
(
nvs_ptr
[
2
]
<<
16
)
|
(
nvs_ptr
[
3
]
<<
24
));
...
...
@@ -358,6 +362,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
nvs_ptr
+=
4
;
dest_addr
+=
4
;
}
if
(
nvs_ptr
>=
(
u8
*
)
wl
->
nvs
+
nvs_len
)
goto
out_badnvs
;
}
/*
...
...
@@ -369,6 +376,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
*/
nvs_ptr
=
(
u8
*
)
wl
->
nvs
+
ALIGN
(
nvs_ptr
-
(
u8
*
)
wl
->
nvs
+
7
,
4
);
if
(
nvs_ptr
>=
(
u8
*
)
wl
->
nvs
+
nvs_len
)
goto
out_badnvs
;
nvs_len
-=
nvs_ptr
-
(
u8
*
)
wl
->
nvs
;
/* Now we must set the partition correctly */
...
...
@@ -384,6 +395,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
kfree
(
nvs_aligned
);
return
0
;
out_badnvs:
wl1271_error
(
"nvs data is malformed"
);
return
-
EILSEQ
;
}
static
void
wl1271_boot_enable_interrupts
(
struct
wl1271
*
wl
)
...
...
drivers/net/wireless/wl12xx/cmd.c
View file @
f589cf4f
...
...
@@ -29,6 +29,7 @@
#include <linux/slab.h>
#include "wl12xx.h"
#include "debug.h"
#include "reg.h"
#include "io.h"
#include "acx.h"
...
...
@@ -120,6 +121,11 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
if
(
!
wl
->
nvs
)
return
-
ENODEV
;
if
(
gp
->
tx_bip_fem_manufacturer
>=
WL1271_INI_FEM_MODULE_COUNT
)
{
wl1271_warning
(
"FEM index from INI out of bounds"
);
return
-
EINVAL
;
}
gen_parms
=
kzalloc
(
sizeof
(
*
gen_parms
),
GFP_KERNEL
);
if
(
!
gen_parms
)
return
-
ENOMEM
;
...
...
@@ -143,6 +149,12 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
gp
->
tx_bip_fem_manufacturer
=
gen_parms
->
general_params
.
tx_bip_fem_manufacturer
;
if
(
gp
->
tx_bip_fem_manufacturer
>=
WL1271_INI_FEM_MODULE_COUNT
)
{
wl1271_warning
(
"FEM index from FW out of bounds"
);
ret
=
-
EINVAL
;
goto
out
;
}
wl1271_debug
(
DEBUG_CMD
,
"FEM autodetect: %s, manufacturer: %d
\n
"
,
answer
?
"auto"
:
"manual"
,
gp
->
tx_bip_fem_manufacturer
);
...
...
@@ -162,6 +174,11 @@ int wl128x_cmd_general_parms(struct wl1271 *wl)
if
(
!
wl
->
nvs
)
return
-
ENODEV
;
if
(
gp
->
tx_bip_fem_manufacturer
>=
WL1271_INI_FEM_MODULE_COUNT
)
{
wl1271_warning
(
"FEM index from ini out of bounds"
);
return
-
EINVAL
;
}
gen_parms
=
kzalloc
(
sizeof
(
*
gen_parms
),
GFP_KERNEL
);
if
(
!
gen_parms
)
return
-
ENOMEM
;
...
...
@@ -186,6 +203,12 @@ int wl128x_cmd_general_parms(struct wl1271 *wl)
gp
->
tx_bip_fem_manufacturer
=
gen_parms
->
general_params
.
tx_bip_fem_manufacturer
;
if
(
gp
->
tx_bip_fem_manufacturer
>=
WL1271_INI_FEM_MODULE_COUNT
)
{
wl1271_warning
(
"FEM index from FW out of bounds"
);
ret
=
-
EINVAL
;
goto
out
;
}
wl1271_debug
(
DEBUG_CMD
,
"FEM autodetect: %s, manufacturer: %d
\n
"
,
answer
?
"auto"
:
"manual"
,
gp
->
tx_bip_fem_manufacturer
);
...
...
@@ -358,7 +381,8 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
return
0
;
}
int
wl12xx_cmd_role_enable
(
struct
wl1271
*
wl
,
u8
role_type
,
u8
*
role_id
)
int
wl12xx_cmd_role_enable
(
struct
wl1271
*
wl
,
u8
*
addr
,
u8
role_type
,
u8
*
role_id
)
{
struct
wl12xx_cmd_role_enable
*
cmd
;
int
ret
;
...
...
@@ -381,7 +405,7 @@ int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 role_type, u8 *role_id)
goto
out_free
;
}
memcpy
(
cmd
->
mac_address
,
wl
->
mac_
addr
,
ETH_ALEN
);
memcpy
(
cmd
->
mac_address
,
addr
,
ETH_ALEN
);
cmd
->
role_type
=
role_type
;
ret
=
wl1271_cmd_send
(
wl
,
CMD_ROLE_ENABLE
,
cmd
,
sizeof
(
*
cmd
),
0
);
...
...
@@ -433,37 +457,41 @@ int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id)
return
ret
;
}
static
int
wl12xx_allocate_link
(
struct
wl1271
*
wl
,
u8
*
hlid
)
int
wl12xx_allocate_link
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
*
hlid
)
{
u8
link
=
find_first_zero_bit
(
wl
->
links_map
,
WL12XX_MAX_LINKS
);
if
(
link
>=
WL12XX_MAX_LINKS
)
return
-
EBUSY
;
__set_bit
(
link
,
wl
->
links_map
);
__set_bit
(
link
,
wlvif
->
links_map
);
*
hlid
=
link
;
return
0
;
}
static
void
wl12xx_free_link
(
struct
wl1271
*
wl
,
u8
*
hlid
)
void
wl12xx_free_link
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
*
hlid
)
{
if
(
*
hlid
==
WL12XX_INVALID_LINK_ID
)
return
;
__clear_bit
(
*
hlid
,
wl
->
links_map
);
__clear_bit
(
*
hlid
,
wlvif
->
links_map
);
*
hlid
=
WL12XX_INVALID_LINK_ID
;
}
static
int
wl12xx_get_new_session_id
(
struct
wl1271
*
wl
)
static
int
wl12xx_get_new_session_id
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
if
(
wl
->
session_counter
>=
SESSION_COUNTER_MAX
)
wl
->
session_counter
=
0
;
if
(
wl
vif
->
session_counter
>=
SESSION_COUNTER_MAX
)
wl
vif
->
session_counter
=
0
;
wl
->
session_counter
++
;
wl
vif
->
session_counter
++
;
return
wl
->
session_counter
;
return
wl
vif
->
session_counter
;
}
int
wl12xx_cmd_role_start_dev
(
struct
wl1271
*
wl
)
static
int
wl12xx_cmd_role_start_dev
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
wl12xx_cmd_role_start
*
cmd
;
int
ret
;
...
...
@@ -474,20 +502,20 @@ int wl12xx_cmd_role_start_dev(struct wl1271 *wl)
goto
out
;
}
wl1271_debug
(
DEBUG_CMD
,
"cmd role start dev %d"
,
wl
->
dev_role_id
);
wl1271_debug
(
DEBUG_CMD
,
"cmd role start dev %d"
,
wl
vif
->
dev_role_id
);
cmd
->
role_id
=
wl
->
dev_role_id
;
if
(
wl
->
band
==
IEEE80211_BAND_5GHZ
)
cmd
->
role_id
=
wl
vif
->
dev_role_id
;
if
(
wl
vif
->
band
==
IEEE80211_BAND_5GHZ
)
cmd
->
band
=
WL12XX_BAND_5GHZ
;
cmd
->
channel
=
wl
->
channel
;
cmd
->
channel
=
wl
vif
->
channel
;
if
(
wl
->
dev_hlid
==
WL12XX_INVALID_LINK_ID
)
{
ret
=
wl12xx_allocate_link
(
wl
,
&
wl
->
dev_hlid
);
if
(
wl
vif
->
dev_hlid
==
WL12XX_INVALID_LINK_ID
)
{
ret
=
wl12xx_allocate_link
(
wl
,
wlvif
,
&
wlvif
->
dev_hlid
);
if
(
ret
)
goto
out_free
;
}
cmd
->
device
.
hlid
=
wl
->
dev_hlid
;
cmd
->
device
.
session
=
wl
->
session_counter
;
cmd
->
device
.
hlid
=
wl
vif
->
dev_hlid
;
cmd
->
device
.
session
=
wl
vif
->
session_counter
;
wl1271_debug
(
DEBUG_CMD
,
"role start: roleid=%d, hlid=%d, session=%d"
,
cmd
->
role_id
,
cmd
->
device
.
hlid
,
cmd
->
device
.
session
);
...
...
@@ -502,9 +530,7 @@ int wl12xx_cmd_role_start_dev(struct wl1271 *wl)
err_hlid:
/* clear links on error */
__clear_bit
(
wl
->
dev_hlid
,
wl
->
links_map
);
wl
->
dev_hlid
=
WL12XX_INVALID_LINK_ID
;
wl12xx_free_link
(
wl
,
wlvif
,
&
wlvif
->
dev_hlid
);
out_free:
kfree
(
cmd
);
...
...
@@ -513,12 +539,13 @@ int wl12xx_cmd_role_start_dev(struct wl1271 *wl)
return
ret
;
}
int
wl12xx_cmd_role_stop_dev
(
struct
wl1271
*
wl
)
static
int
wl12xx_cmd_role_stop_dev
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
wl12xx_cmd_role_stop
*
cmd
;
int
ret
;
if
(
WARN_ON
(
wl
->
dev_hlid
==
WL12XX_INVALID_LINK_ID
))
if
(
WARN_ON
(
wl
vif
->
dev_hlid
==
WL12XX_INVALID_LINK_ID
))
return
-
EINVAL
;
cmd
=
kzalloc
(
sizeof
(
*
cmd
),
GFP_KERNEL
);
...
...
@@ -529,7 +556,7 @@ int wl12xx_cmd_role_stop_dev(struct wl1271 *wl)
wl1271_debug
(
DEBUG_CMD
,
"cmd role stop dev"
);
cmd
->
role_id
=
wl
->
dev_role_id
;
cmd
->
role_id
=
wl
vif
->
dev_role_id
;
cmd
->
disc_type
=
DISCONNECT_IMMEDIATE
;
cmd
->
reason
=
cpu_to_le16
(
WLAN_REASON_UNSPECIFIED
);
...
...
@@ -545,7 +572,7 @@ int wl12xx_cmd_role_stop_dev(struct wl1271 *wl)
goto
out_free
;
}
wl12xx_free_link
(
wl
,
&
wl
->
dev_hlid
);
wl12xx_free_link
(
wl
,
wlvif
,
&
wlvif
->
dev_hlid
);
out_free:
kfree
(
cmd
);
...
...
@@ -554,8 +581,9 @@ int wl12xx_cmd_role_stop_dev(struct wl1271 *wl)
return
ret
;
}
int
wl12xx_cmd_role_start_sta
(
struct
wl1271
*
wl
)
int
wl12xx_cmd_role_start_sta
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
ieee80211_vif
*
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
struct
wl12xx_cmd_role_start
*
cmd
;
int
ret
;
...
...
@@ -565,33 +593,33 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl)
goto
out
;
}
wl1271_debug
(
DEBUG_CMD
,
"cmd role start sta %d"
,
wl
->
role_id
);
wl1271_debug
(
DEBUG_CMD
,
"cmd role start sta %d"
,
wl
vif
->
role_id
);
cmd
->
role_id
=
wl
->
role_id
;
if
(
wl
->
band
==
IEEE80211_BAND_5GHZ
)
cmd
->
role_id
=
wl
vif
->
role_id
;
if
(
wl
vif
->
band
==
IEEE80211_BAND_5GHZ
)
cmd
->
band
=
WL12XX_BAND_5GHZ
;
cmd
->
channel
=
wl
->
channel
;
cmd
->
sta
.
basic_rate_set
=
cpu_to_le32
(
wl
->
basic_rate_set
);
cmd
->
sta
.
beacon_interval
=
cpu_to_le16
(
wl
->
beacon_int
);
cmd
->
channel
=
wl
vif
->
channel
;
cmd
->
sta
.
basic_rate_set
=
cpu_to_le32
(
wl
vif
->
basic_rate_set
);
cmd
->
sta
.
beacon_interval
=
cpu_to_le16
(
wl
vif
->
beacon_int
);
cmd
->
sta
.
ssid_type
=
WL12XX_SSID_TYPE_ANY
;
cmd
->
sta
.
ssid_len
=
wl
->
ssid_len
;
memcpy
(
cmd
->
sta
.
ssid
,
wl
->
ssid
,
wl
->
ssid_len
);
memcpy
(
cmd
->
sta
.
bssid
,
wl
->
bssid
,
ETH_ALEN
);
cmd
->
sta
.
local_rates
=
cpu_to_le32
(
wl
->
rate_set
);
cmd
->
sta
.
ssid_len
=
wl
vif
->
ssid_len
;
memcpy
(
cmd
->
sta
.
ssid
,
wl
vif
->
ssid
,
wlvif
->
ssid_len
);
memcpy
(
cmd
->
sta
.
bssid
,
vif
->
bss_conf
.
bssid
,
ETH_ALEN
);
cmd
->
sta
.
local_rates
=
cpu_to_le32
(
wl
vif
->
rate_set
);
if
(
wl
->
sta_
hlid
==
WL12XX_INVALID_LINK_ID
)
{
ret
=
wl12xx_allocate_link
(
wl
,
&
wl
->
sta_
hlid
);
if
(
wl
vif
->
sta
.
hlid
==
WL12XX_INVALID_LINK_ID
)
{
ret
=
wl12xx_allocate_link
(
wl
,
wlvif
,
&
wlvif
->
sta
.
hlid
);
if
(
ret
)
goto
out_free
;
}
cmd
->
sta
.
hlid
=
wl
->
sta_
hlid
;
cmd
->
sta
.
session
=
wl12xx_get_new_session_id
(
wl
);
cmd
->
sta
.
remote_rates
=
cpu_to_le32
(
wl
->
rate_set
);
cmd
->
sta
.
hlid
=
wl
vif
->
sta
.
hlid
;
cmd
->
sta
.
session
=
wl12xx_get_new_session_id
(
wl
,
wlvif
);
cmd
->
sta
.
remote_rates
=
cpu_to_le32
(
wl
vif
->
rate_set
);
wl1271_debug
(
DEBUG_CMD
,
"role start: roleid=%d, hlid=%d, session=%d "
"basic_rate_set: 0x%x, remote_rates: 0x%x"
,
wl
->
role_id
,
cmd
->
sta
.
hlid
,
cmd
->
sta
.
session
,
wl
->
basic_rate_set
,
wl
->
rate_set
);
wl
vif
->
role_id
,
cmd
->
sta
.
hlid
,
cmd
->
sta
.
session
,
wl
vif
->
basic_rate_set
,
wlvif
->
rate_set
);
ret
=
wl1271_cmd_send
(
wl
,
CMD_ROLE_START
,
cmd
,
sizeof
(
*
cmd
),
0
);
if
(
ret
<
0
)
{
...
...
@@ -603,7 +631,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl)
err_hlid:
/* clear links on error. */
wl12xx_free_link
(
wl
,
&
wl
->
sta_
hlid
);
wl12xx_free_link
(
wl
,
wlvif
,
&
wlvif
->
sta
.
hlid
);
out_free:
kfree
(
cmd
);
...
...
@@ -613,12 +641,12 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl)
}
/* use this function to stop ibss as well */
int
wl12xx_cmd_role_stop_sta
(
struct
wl1271
*
wl
)
int
wl12xx_cmd_role_stop_sta
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
wl12xx_cmd_role_stop
*
cmd
;
int
ret
;
if
(
WARN_ON
(
wl
->
sta_
hlid
==
WL12XX_INVALID_LINK_ID
))
if
(
WARN_ON
(
wl
vif
->
sta
.
hlid
==
WL12XX_INVALID_LINK_ID
))
return
-
EINVAL
;
cmd
=
kzalloc
(
sizeof
(
*
cmd
),
GFP_KERNEL
);
...
...
@@ -627,9 +655,9 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl)
goto
out
;
}
wl1271_debug
(
DEBUG_CMD
,
"cmd role stop sta %d"
,
wl
->
role_id
);
wl1271_debug
(
DEBUG_CMD
,
"cmd role stop sta %d"
,
wl
vif
->
role_id
);
cmd
->
role_id
=
wl
->
role_id
;
cmd
->
role_id
=
wl
vif
->
role_id
;
cmd
->
disc_type
=
DISCONNECT_IMMEDIATE
;
cmd
->
reason
=
cpu_to_le16
(
WLAN_REASON_UNSPECIFIED
);
...
...
@@ -639,7 +667,7 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl)
goto
out_free
;
}
wl12xx_free_link
(
wl
,
&
wl
->
sta_
hlid
);
wl12xx_free_link
(
wl
,
wlvif
,
&
wlvif
->
sta
.
hlid
);
out_free:
kfree
(
cmd
);
...
...
@@ -648,16 +676,17 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl)
return
ret
;
}
int
wl12xx_cmd_role_start_ap
(
struct
wl1271
*
wl
)
int
wl12xx_cmd_role_start_ap
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
wl12xx_cmd_role_start
*
cmd
;
struct
ieee80211_bss_conf
*
bss_conf
=
&
wl
->
vif
->
bss_conf
;
struct
ieee80211_vif
*
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
struct
ieee80211_bss_conf
*
bss_conf
=
&
vif
->
bss_conf
;
int
ret
;
wl1271_debug
(
DEBUG_CMD
,
"cmd role start ap %d"
,
wl
->
role_id
);
wl1271_debug
(
DEBUG_CMD
,
"cmd role start ap %d"
,
wl
vif
->
role_id
);
/* trying to use hidden SSID with an old hostapd version */
if
(
wl
->
ssid_len
==
0
&&
!
bss_conf
->
hidden_ssid
)
{
if
(
wl
vif
->
ssid_len
==
0
&&
!
bss_conf
->
hidden_ssid
)
{
wl1271_error
(
"got a null SSID from beacon/bss"
);
ret
=
-
EINVAL
;
goto
out
;
...
...
@@ -669,30 +698,30 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl)
goto
out
;
}
ret
=
wl12xx_allocate_link
(
wl
,
&
wl
->
ap_
global_hlid
);
ret
=
wl12xx_allocate_link
(
wl
,
wlvif
,
&
wlvif
->
ap
.
global_hlid
);
if
(
ret
<
0
)
goto
out_free
;
ret
=
wl12xx_allocate_link
(
wl
,
&
wl
->
ap_
bcast_hlid
);
ret
=
wl12xx_allocate_link
(
wl
,
wlvif
,
&
wlvif
->
ap
.
bcast_hlid
);
if
(
ret
<
0
)
goto
out_free_global
;
cmd
->
role_id
=
wl
->
role_id
;
cmd
->
role_id
=
wl
vif
->
role_id
;
cmd
->
ap
.
aging_period
=
cpu_to_le16
(
wl
->
conf
.
tx
.
ap_aging_period
);
cmd
->
ap
.
bss_index
=
WL1271_AP_BSS_INDEX
;
cmd
->
ap
.
global_hlid
=
wl
->
ap_
global_hlid
;
cmd
->
ap
.
broadcast_hlid
=
wl
->
ap_
bcast_hlid
;
cmd
->
ap
.
basic_rate_set
=
cpu_to_le32
(
wl
->
basic_rate_set
);
cmd
->
ap
.
beacon_interval
=
cpu_to_le16
(
wl
->
beacon_int
);
cmd
->
ap
.
global_hlid
=
wl
vif
->
ap
.
global_hlid
;
cmd
->
ap
.
broadcast_hlid
=
wl
vif
->
ap
.
bcast_hlid
;
cmd
->
ap
.
basic_rate_set
=
cpu_to_le32
(
wl
vif
->
basic_rate_set
);
cmd
->
ap
.
beacon_interval
=
cpu_to_le16
(
wl
vif
->
beacon_int
);
cmd
->
ap
.
dtim_interval
=
bss_conf
->
dtim_period
;
cmd
->
ap
.
beacon_expiry
=
WL1271_AP_DEF_BEACON_EXP
;
cmd
->
channel
=
wl
->
channel
;
cmd
->
channel
=
wl
vif
->
channel
;
if
(
!
bss_conf
->
hidden_ssid
)
{
/* take the SSID from the beacon for backward compatibility */
cmd
->
ap
.
ssid_type
=
WL12XX_SSID_TYPE_PUBLIC
;
cmd
->
ap
.
ssid_len
=
wl
->
ssid_len
;
memcpy
(
cmd
->
ap
.
ssid
,
wl
->
ssid
,
wl
->
ssid_len
);
cmd
->
ap
.
ssid_len
=
wl
vif
->
ssid_len
;
memcpy
(
cmd
->
ap
.
ssid
,
wl
vif
->
ssid
,
wlvif
->
ssid_len
);
}
else
{
cmd
->
ap
.
ssid_type
=
WL12XX_SSID_TYPE_HIDDEN
;
cmd
->
ap
.
ssid_len
=
bss_conf
->
ssid_len
;
...
...
@@ -701,7 +730,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl)
cmd
->
ap
.
local_rates
=
cpu_to_le32
(
0xffffffff
);
switch
(
wl
->
band
)
{
switch
(
wl
vif
->
band
)
{
case
IEEE80211_BAND_2GHZ
:
cmd
->
band
=
RADIO_BAND_2_4GHZ
;
break
;
...
...
@@ -709,7 +738,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl)
cmd
->
band
=
RADIO_BAND_5GHZ
;
break
;
default:
wl1271_warning
(
"ap start - unknown band: %d"
,
(
int
)
wl
->
band
);
wl1271_warning
(
"ap start - unknown band: %d"
,
(
int
)
wl
vif
->
band
);
cmd
->
band
=
RADIO_BAND_2_4GHZ
;
break
;
}
...
...
@@ -723,10 +752,10 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl)
goto
out_free
;
out_free_bcast:
wl12xx_free_link
(
wl
,
&
wl
->
ap_
bcast_hlid
);
wl12xx_free_link
(
wl
,
wlvif
,
&
wlvif
->
ap
.
bcast_hlid
);
out_free_global:
wl12xx_free_link
(
wl
,
&
wl
->
ap_
global_hlid
);
wl12xx_free_link
(
wl
,
wlvif
,
&
wlvif
->
ap
.
global_hlid
);
out_free:
kfree
(
cmd
);
...
...
@@ -735,7 +764,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl)
return
ret
;
}
int
wl12xx_cmd_role_stop_ap
(
struct
wl1271
*
wl
)
int
wl12xx_cmd_role_stop_ap
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
wl12xx_cmd_role_stop
*
cmd
;
int
ret
;
...
...
@@ -746,9 +775,9 @@ int wl12xx_cmd_role_stop_ap(struct wl1271 *wl)
goto
out
;
}
wl1271_debug
(
DEBUG_CMD
,
"cmd role stop ap %d"
,
wl
->
role_id
);
wl1271_debug
(
DEBUG_CMD
,
"cmd role stop ap %d"
,
wl
vif
->
role_id
);
cmd
->
role_id
=
wl
->
role_id
;
cmd
->
role_id
=
wl
vif
->
role_id
;
ret
=
wl1271_cmd_send
(
wl
,
CMD_ROLE_STOP
,
cmd
,
sizeof
(
*
cmd
),
0
);
if
(
ret
<
0
)
{
...
...
@@ -756,8 +785,8 @@ int wl12xx_cmd_role_stop_ap(struct wl1271 *wl)
goto
out_free
;
}
wl12xx_free_link
(
wl
,
&
wl
->
ap_
bcast_hlid
);
wl12xx_free_link
(
wl
,
&
wl
->
ap_
global_hlid
);
wl12xx_free_link
(
wl
,
wlvif
,
&
wlvif
->
ap
.
bcast_hlid
);
wl12xx_free_link
(
wl
,
wlvif
,
&
wlvif
->
ap
.
global_hlid
);
out_free:
kfree
(
cmd
);
...
...
@@ -766,10 +795,11 @@ int wl12xx_cmd_role_stop_ap(struct wl1271 *wl)
return
ret
;
}
int
wl12xx_cmd_role_start_ibss
(
struct
wl1271
*
wl
)
int
wl12xx_cmd_role_start_ibss
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
ieee80211_vif
*
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
struct
wl12xx_cmd_role_start
*
cmd
;
struct
ieee80211_bss_conf
*
bss_conf
=
&
wl
->
vif
->
bss_conf
;
struct
ieee80211_bss_conf
*
bss_conf
=
&
vif
->
bss_conf
;
int
ret
;
cmd
=
kzalloc
(
sizeof
(
*
cmd
),
GFP_KERNEL
);
...
...
@@ -778,35 +808,36 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl)
goto
out
;
}
wl1271_debug
(
DEBUG_CMD
,
"cmd role start ibss %d"
,
wl
->
role_id
);
wl1271_debug
(
DEBUG_CMD
,
"cmd role start ibss %d"
,
wl
vif
->
role_id
);
cmd
->
role_id
=
wl
->
role_id
;
if
(
wl
->
band
==
IEEE80211_BAND_5GHZ
)
cmd
->
role_id
=
wl
vif
->
role_id
;
if
(
wl
vif
->
band
==
IEEE80211_BAND_5GHZ
)
cmd
->
band
=
WL12XX_BAND_5GHZ
;
cmd
->
channel
=
wl
->
channel
;
cmd
->
ibss
.
basic_rate_set
=
cpu_to_le32
(
wl
->
basic_rate_set
);
cmd
->
ibss
.
beacon_interval
=
cpu_to_le16
(
wl
->
beacon_int
);
cmd
->
channel
=
wl
vif
->
channel
;
cmd
->
ibss
.
basic_rate_set
=
cpu_to_le32
(
wl
vif
->
basic_rate_set
);
cmd
->
ibss
.
beacon_interval
=
cpu_to_le16
(
wl
vif
->
beacon_int
);
cmd
->
ibss
.
dtim_interval
=
bss_conf
->
dtim_period
;
cmd
->
ibss
.
ssid_type
=
WL12XX_SSID_TYPE_ANY
;
cmd
->
ibss
.
ssid_len
=
wl
->
ssid_len
;
memcpy
(
cmd
->
ibss
.
ssid
,
wl
->
ssid
,
wl
->
ssid_len
);
memcpy
(
cmd
->
ibss
.
bssid
,
wl
->
bssid
,
ETH_ALEN
);
cmd
->
sta
.
local_rates
=
cpu_to_le32
(
wl
->
rate_set
);
cmd
->
ibss
.
ssid_len
=
wl
vif
->
ssid_len
;
memcpy
(
cmd
->
ibss
.
ssid
,
wl
vif
->
ssid
,
wlvif
->
ssid_len
);
memcpy
(
cmd
->
ibss
.
bssid
,
vif
->
bss_conf
.
bssid
,
ETH_ALEN
);
cmd
->
sta
.
local_rates
=
cpu_to_le32
(
wl
vif
->
rate_set
);
if
(
wl
->
sta_
hlid
==
WL12XX_INVALID_LINK_ID
)
{
ret
=
wl12xx_allocate_link
(
wl
,
&
wl
->
sta_
hlid
);
if
(
wl
vif
->
sta
.
hlid
==
WL12XX_INVALID_LINK_ID
)
{
ret
=
wl12xx_allocate_link
(
wl
,
wlvif
,
&
wlvif
->
sta
.
hlid
);
if
(
ret
)
goto
out_free
;
}
cmd
->
ibss
.
hlid
=
wl
->
sta_
hlid
;
cmd
->
ibss
.
remote_rates
=
cpu_to_le32
(
wl
->
rate_set
);
cmd
->
ibss
.
hlid
=
wl
vif
->
sta
.
hlid
;
cmd
->
ibss
.
remote_rates
=
cpu_to_le32
(
wl
vif
->
rate_set
);
wl1271_debug
(
DEBUG_CMD
,
"role start: roleid=%d, hlid=%d, session=%d "
"basic_rate_set: 0x%x, remote_rates: 0x%x"
,
wl
->
role_id
,
cmd
->
sta
.
hlid
,
cmd
->
sta
.
session
,
wl
->
basic_rate_set
,
wl
->
rate_set
);
wl
vif
->
role_id
,
cmd
->
sta
.
hlid
,
cmd
->
sta
.
session
,
wl
vif
->
basic_rate_set
,
wlvif
->
rate_set
);
wl1271_debug
(
DEBUG_CMD
,
"wl->bssid = %pM"
,
wl
->
bssid
);
wl1271_debug
(
DEBUG_CMD
,
"vif->bss_conf.bssid = %pM"
,
vif
->
bss_conf
.
bssid
);
ret
=
wl1271_cmd_send
(
wl
,
CMD_ROLE_START
,
cmd
,
sizeof
(
*
cmd
),
0
);
if
(
ret
<
0
)
{
...
...
@@ -818,7 +849,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl)
err_hlid:
/* clear links on error. */
wl12xx_free_link
(
wl
,
&
wl
->
sta_
hlid
);
wl12xx_free_link
(
wl
,
wlvif
,
&
wlvif
->
sta
.
hlid
);
out_free:
kfree
(
cmd
);
...
...
@@ -962,7 +993,8 @@ int wl1271_cmd_data_path(struct wl1271 *wl, bool enable)
return
ret
;
}
int
wl1271_cmd_ps_mode
(
struct
wl1271
*
wl
,
u8
ps_mode
)
int
wl1271_cmd_ps_mode
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
ps_mode
)
{
struct
wl1271_cmd_ps_params
*
ps_params
=
NULL
;
int
ret
=
0
;
...
...
@@ -975,7 +1007,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode)
goto
out
;
}
ps_params
->
role_id
=
wl
->
role_id
;
ps_params
->
role_id
=
wl
vif
->
role_id
;
ps_params
->
ps_mode
=
ps_mode
;
ret
=
wl1271_cmd_send
(
wl
,
CMD_SET_PS_MODE
,
ps_params
,
...
...
@@ -1030,7 +1062,7 @@ int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
return
ret
;
}
int
wl12
71_cmd_build_null_data
(
struct
wl1271
*
wl
)
int
wl12
xx_cmd_build_null_data
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
sk_buff
*
skb
=
NULL
;
int
size
;
...
...
@@ -1038,11 +1070,12 @@ int wl1271_cmd_build_null_data(struct wl1271 *wl)
int
ret
=
-
ENOMEM
;
if
(
wl
->
bss_type
==
BSS_TYPE_IBSS
)
{
if
(
wl
vif
->
bss_type
==
BSS_TYPE_IBSS
)
{
size
=
sizeof
(
struct
wl12xx_null_data_template
);
ptr
=
NULL
;
}
else
{
skb
=
ieee80211_nullfunc_get
(
wl
->
hw
,
wl
->
vif
);
skb
=
ieee80211_nullfunc_get
(
wl
->
hw
,
wl12xx_wlvif_to_vif
(
wlvif
));
if
(
!
skb
)
goto
out
;
size
=
skb
->
len
;
...
...
@@ -1050,7 +1083,7 @@ int wl1271_cmd_build_null_data(struct wl1271 *wl)
}
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_NULL_DATA
,
ptr
,
size
,
0
,
wl
->
basic_rate
);
wl
vif
->
basic_rate
);
out:
dev_kfree_skb
(
skb
);
...
...
@@ -1061,19 +1094,21 @@ int wl1271_cmd_build_null_data(struct wl1271 *wl)
}
int
wl1271_cmd_build_klv_null_data
(
struct
wl1271
*
wl
)
int
wl12xx_cmd_build_klv_null_data
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
ieee80211_vif
*
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
struct
sk_buff
*
skb
=
NULL
;
int
ret
=
-
ENOMEM
;
skb
=
ieee80211_nullfunc_get
(
wl
->
hw
,
wl
->
vif
);
skb
=
ieee80211_nullfunc_get
(
wl
->
hw
,
vif
);
if
(
!
skb
)
goto
out
;
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_KLV
,
skb
->
data
,
skb
->
len
,
CMD_TEMPL_KLV_IDX_NULL_DATA
,
wl
->
basic_rate
);
wl
vif
->
basic_rate
);
out:
dev_kfree_skb
(
skb
);
...
...
@@ -1084,32 +1119,35 @@ int wl1271_cmd_build_klv_null_data(struct wl1271 *wl)
}
int
wl1271_cmd_build_ps_poll
(
struct
wl1271
*
wl
,
u16
aid
)
int
wl1271_cmd_build_ps_poll
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u16
aid
)
{
struct
ieee80211_vif
*
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
struct
sk_buff
*
skb
;
int
ret
=
0
;
skb
=
ieee80211_pspoll_get
(
wl
->
hw
,
wl
->
vif
);
skb
=
ieee80211_pspoll_get
(
wl
->
hw
,
vif
);
if
(
!
skb
)
goto
out
;
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_PS_POLL
,
skb
->
data
,
skb
->
len
,
0
,
wl
->
basic_rate_set
);
skb
->
len
,
0
,
wl
vif
->
basic_rate_set
);
out:
dev_kfree_skb
(
skb
);
return
ret
;
}
int
wl1271_cmd_build_probe_req
(
struct
wl1271
*
wl
,
int
wl1271_cmd_build_probe_req
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
const
u8
*
ssid
,
size_t
ssid_len
,
const
u8
*
ie
,
size_t
ie_len
,
u8
band
)
{
struct
ieee80211_vif
*
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
struct
sk_buff
*
skb
;
int
ret
;
u32
rate
;
skb
=
ieee80211_probereq_get
(
wl
->
hw
,
wl
->
vif
,
ssid
,
ssid_len
,
skb
=
ieee80211_probereq_get
(
wl
->
hw
,
vif
,
ssid
,
ssid_len
,
ie
,
ie_len
);
if
(
!
skb
)
{
ret
=
-
ENOMEM
;
...
...
@@ -1118,7 +1156,7 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl,
wl1271_dump
(
DEBUG_SCAN
,
"PROBE REQ: "
,
skb
->
data
,
skb
->
len
);
rate
=
wl1271_tx_min_rate_get
(
wl
,
wl
->
bitrate_masks
[
band
]);
rate
=
wl1271_tx_min_rate_get
(
wl
,
wl
vif
->
bitrate_masks
[
band
]);
if
(
band
==
IEEE80211_BAND_2GHZ
)
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_CFG_PROBE_REQ_2_4
,
skb
->
data
,
skb
->
len
,
0
,
rate
);
...
...
@@ -1132,20 +1170,22 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl,
}
struct
sk_buff
*
wl1271_cmd_build_ap_probe_req
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
sk_buff
*
skb
)
{
struct
ieee80211_vif
*
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
int
ret
;
u32
rate
;
if
(
!
skb
)
skb
=
ieee80211_ap_probereq_get
(
wl
->
hw
,
wl
->
vif
);
skb
=
ieee80211_ap_probereq_get
(
wl
->
hw
,
vif
);
if
(
!
skb
)
goto
out
;
wl1271_dump
(
DEBUG_SCAN
,
"AP PROBE REQ: "
,
skb
->
data
,
skb
->
len
);
rate
=
wl1271_tx_min_rate_get
(
wl
,
wl
->
bitrate_masks
[
wl
->
band
]);
if
(
wl
->
band
==
IEEE80211_BAND_2GHZ
)
rate
=
wl1271_tx_min_rate_get
(
wl
,
wl
vif
->
bitrate_masks
[
wlvif
->
band
]);
if
(
wl
vif
->
band
==
IEEE80211_BAND_2GHZ
)
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_CFG_PROBE_REQ_2_4
,
skb
->
data
,
skb
->
len
,
0
,
rate
);
else
...
...
@@ -1159,9 +1199,11 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
return
skb
;
}
int
wl1271_cmd_build_arp_rsp
(
struct
wl1271
*
wl
,
__be32
ip_addr
)
int
wl1271_cmd_build_arp_rsp
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
__be32
ip_addr
)
{
int
ret
;
struct
ieee80211_vif
*
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
struct
wl12xx_arp_rsp_template
tmpl
;
struct
ieee80211_hdr_3addr
*
hdr
;
struct
arphdr
*
arp_hdr
;
...
...
@@ -1173,8 +1215,8 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr)
hdr
->
frame_control
=
cpu_to_le16
(
IEEE80211_FTYPE_DATA
|
IEEE80211_STYPE_DATA
|
IEEE80211_FCTL_TODS
);
memcpy
(
hdr
->
addr1
,
wl
->
vif
->
bss_conf
.
bssid
,
ETH_ALEN
);
memcpy
(
hdr
->
addr2
,
wl
->
vif
->
addr
,
ETH_ALEN
);
memcpy
(
hdr
->
addr1
,
vif
->
bss_conf
.
bssid
,
ETH_ALEN
);
memcpy
(
hdr
->
addr2
,
vif
->
addr
,
ETH_ALEN
);
memset
(
hdr
->
addr3
,
0xff
,
ETH_ALEN
);
/* llc layer */
...
...
@@ -1190,25 +1232,26 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr)
arp_hdr
->
ar_op
=
cpu_to_be16
(
ARPOP_REPLY
);
/* arp payload */
memcpy
(
tmpl
.
sender_hw
,
wl
->
vif
->
addr
,
ETH_ALEN
);
memcpy
(
tmpl
.
sender_hw
,
vif
->
addr
,
ETH_ALEN
);
tmpl
.
sender_ip
=
ip_addr
;
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_ARP_RSP
,
&
tmpl
,
sizeof
(
tmpl
),
0
,
wl
->
basic_rate
);
wl
vif
->
basic_rate
);
return
ret
;
}
int
wl1271_build_qos_null_data
(
struct
wl1271
*
wl
)
int
wl1271_build_qos_null_data
(
struct
wl1271
*
wl
,
struct
ieee80211_vif
*
vif
)
{
struct
wl12xx_vif
*
wlvif
=
wl12xx_vif_to_data
(
vif
);
struct
ieee80211_qos_hdr
template
;
memset
(
&
template
,
0
,
sizeof
(
template
));
memcpy
(
template
.
addr1
,
wl
->
bssid
,
ETH_ALEN
);
memcpy
(
template
.
addr2
,
wl
->
mac_
addr
,
ETH_ALEN
);
memcpy
(
template
.
addr3
,
wl
->
bssid
,
ETH_ALEN
);
memcpy
(
template
.
addr1
,
vif
->
bss_conf
.
bssid
,
ETH_ALEN
);
memcpy
(
template
.
addr2
,
vif
->
addr
,
ETH_ALEN
);
memcpy
(
template
.
addr3
,
vif
->
bss_conf
.
bssid
,
ETH_ALEN
);
template
.
frame_control
=
cpu_to_le16
(
IEEE80211_FTYPE_DATA
|
IEEE80211_STYPE_QOS_NULLFUNC
|
...
...
@@ -1219,7 +1262,7 @@ int wl1271_build_qos_null_data(struct wl1271 *wl)
return
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_QOS_NULL_DATA
,
&
template
,
sizeof
(
template
),
0
,
wl
->
basic_rate
);
wl
vif
->
basic_rate
);
}
int
wl12xx_cmd_set_default_wep_key
(
struct
wl1271
*
wl
,
u8
id
,
u8
hlid
)
...
...
@@ -1253,7 +1296,8 @@ int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid)
return
ret
;
}
int
wl1271_cmd_set_sta_key
(
struct
wl1271
*
wl
,
u16
action
,
u8
id
,
u8
key_type
,
int
wl1271_cmd_set_sta_key
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u16
action
,
u8
id
,
u8
key_type
,
u8
key_size
,
const
u8
*
key
,
const
u8
*
addr
,
u32
tx_seq_32
,
u16
tx_seq_16
)
{
...
...
@@ -1261,7 +1305,7 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
int
ret
=
0
;
/* hlid might have already been deleted */
if
(
wl
->
sta_
hlid
==
WL12XX_INVALID_LINK_ID
)
if
(
wl
vif
->
sta
.
hlid
==
WL12XX_INVALID_LINK_ID
)
return
0
;
cmd
=
kzalloc
(
sizeof
(
*
cmd
),
GFP_KERNEL
);
...
...
@@ -1270,7 +1314,7 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
goto
out
;
}
cmd
->
hlid
=
wl
->
sta_
hlid
;
cmd
->
hlid
=
wl
vif
->
sta
.
hlid
;
if
(
key_type
==
KEY_WEP
)
cmd
->
lid_key_type
=
WEP_DEFAULT_LID_TYPE
;
...
...
@@ -1321,9 +1365,10 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
* TODO: merge with sta/ibss into 1 set_key function.
* note there are slight diffs
*/
int
wl1271_cmd_set_ap_key
(
struct
wl1271
*
wl
,
u16
action
,
u8
id
,
u8
key_type
,
u8
key_size
,
const
u8
*
key
,
u8
hlid
,
u32
tx_seq_32
,
u16
tx_seq_16
)
int
wl1271_cmd_set_ap_key
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u16
action
,
u8
id
,
u8
key_type
,
u8
key_size
,
const
u8
*
key
,
u8
hlid
,
u32
tx_seq_32
,
u16
tx_seq_16
)
{
struct
wl1271_cmd_set_keys
*
cmd
;
int
ret
=
0
;
...
...
@@ -1333,7 +1378,7 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
if
(
!
cmd
)
return
-
ENOMEM
;
if
(
hlid
==
wl
->
ap_
bcast_hlid
)
{
if
(
hlid
==
wl
vif
->
ap
.
bcast_hlid
)
{
if
(
key_type
==
KEY_WEP
)
lid_type
=
WEP_DEFAULT_LID_TYPE
;
else
...
...
@@ -1411,7 +1456,8 @@ int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid)
return
ret
;
}
int
wl12xx_cmd_add_peer
(
struct
wl1271
*
wl
,
struct
ieee80211_sta
*
sta
,
u8
hlid
)
int
wl12xx_cmd_add_peer
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
ieee80211_sta
*
sta
,
u8
hlid
)
{
struct
wl12xx_cmd_add_peer
*
cmd
;
int
i
,
ret
;
...
...
@@ -1438,13 +1484,13 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
else
cmd
->
psd_type
[
i
]
=
WL1271_PSD_LEGACY
;
sta_rates
=
sta
->
supp_rates
[
wl
->
band
];
sta_rates
=
sta
->
supp_rates
[
wl
vif
->
band
];
if
(
sta
->
ht_cap
.
ht_supported
)
sta_rates
|=
sta
->
ht_cap
.
mcs
.
rx_mask
[
0
]
<<
HW_HT_RATES_OFFSET
;
cmd
->
supported_rates
=
cpu_to_le32
(
wl1271_tx_enabled_rates_get
(
wl
,
sta_rates
,
wl
->
band
));
wl
vif
->
band
));
wl1271_debug
(
DEBUG_CMD
,
"new peer rates=0x%x queues=0x%x"
,
cmd
->
supported_rates
,
sta
->
uapsd_queues
);
...
...
@@ -1584,12 +1630,13 @@ int wl12xx_cmd_stop_fwlog(struct wl1271 *wl)
return
ret
;
}
static
int
wl12xx_cmd_roc
(
struct
wl1271
*
wl
,
u8
role_id
)
static
int
wl12xx_cmd_roc
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
role_id
)
{
struct
wl12xx_cmd_roc
*
cmd
;
int
ret
=
0
;
wl1271_debug
(
DEBUG_CMD
,
"cmd roc %d (%d)"
,
wl
->
channel
,
role_id
);
wl1271_debug
(
DEBUG_CMD
,
"cmd roc %d (%d)"
,
wl
vif
->
channel
,
role_id
);
if
(
WARN_ON
(
role_id
==
WL12XX_INVALID_ROLE_ID
))
return
-
EINVAL
;
...
...
@@ -1601,8 +1648,8 @@ static int wl12xx_cmd_roc(struct wl1271 *wl, u8 role_id)
}
cmd
->
role_id
=
role_id
;
cmd
->
channel
=
wl
->
channel
;
switch
(
wl
->
band
)
{
cmd
->
channel
=
wl
vif
->
channel
;
switch
(
wl
vif
->
band
)
{
case
IEEE80211_BAND_2GHZ
:
cmd
->
band
=
RADIO_BAND_2_4GHZ
;
break
;
...
...
@@ -1610,7 +1657,7 @@ static int wl12xx_cmd_roc(struct wl1271 *wl, u8 role_id)
cmd
->
band
=
RADIO_BAND_5GHZ
;
break
;
default:
wl1271_error
(
"roc - unknown band: %d"
,
(
int
)
wl
->
band
);
wl1271_error
(
"roc - unknown band: %d"
,
(
int
)
wl
vif
->
band
);
ret
=
-
EINVAL
;
goto
out_free
;
}
...
...
@@ -1657,14 +1704,14 @@ static int wl12xx_cmd_croc(struct wl1271 *wl, u8 role_id)
return
ret
;
}
int
wl12xx_roc
(
struct
wl1271
*
wl
,
u8
role_id
)
int
wl12xx_roc
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
role_id
)
{
int
ret
=
0
;
if
(
WARN_ON
(
test_bit
(
role_id
,
wl
->
roc_map
)))
return
0
;
ret
=
wl12xx_cmd_roc
(
wl
,
role_id
);
ret
=
wl12xx_cmd_roc
(
wl
,
wlvif
,
role_id
);
if
(
ret
<
0
)
goto
out
;
...
...
@@ -1753,3 +1800,50 @@ int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl)
out:
return
ret
;
}
/* start dev role and roc on its channel */
int
wl12xx_start_dev
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
int
ret
;
if
(
WARN_ON
(
!
(
wlvif
->
bss_type
==
BSS_TYPE_STA_BSS
||
wlvif
->
bss_type
==
BSS_TYPE_IBSS
)))
return
-
EINVAL
;
ret
=
wl12xx_cmd_role_start_dev
(
wl
,
wlvif
);
if
(
ret
<
0
)
goto
out
;
ret
=
wl12xx_roc
(
wl
,
wlvif
,
wlvif
->
dev_role_id
);
if
(
ret
<
0
)
goto
out_stop
;
return
0
;
out_stop:
wl12xx_cmd_role_stop_dev
(
wl
,
wlvif
);
out:
return
ret
;
}
/* croc dev hlid, and stop the role */
int
wl12xx_stop_dev
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
int
ret
;
if
(
WARN_ON
(
!
(
wlvif
->
bss_type
==
BSS_TYPE_STA_BSS
||
wlvif
->
bss_type
==
BSS_TYPE_IBSS
)))
return
-
EINVAL
;
if
(
test_bit
(
wlvif
->
dev_role_id
,
wl
->
roc_map
))
{
ret
=
wl12xx_croc
(
wl
,
wlvif
->
dev_role_id
);
if
(
ret
<
0
)
goto
out
;
}
ret
=
wl12xx_cmd_role_stop_dev
(
wl
,
wlvif
);
if
(
ret
<
0
)
goto
out
;
out:
return
ret
;
}
drivers/net/wireless/wl12xx/cmd.h
View file @
f589cf4f
...
...
@@ -36,45 +36,54 @@ int wl128x_cmd_general_parms(struct wl1271 *wl);
int
wl1271_cmd_radio_parms
(
struct
wl1271
*
wl
);
int
wl128x_cmd_radio_parms
(
struct
wl1271
*
wl
);
int
wl1271_cmd_ext_radio_parms
(
struct
wl1271
*
wl
);
int
wl12xx_cmd_role_enable
(
struct
wl1271
*
wl
,
u8
role_type
,
u8
*
role_id
);
int
wl12xx_cmd_role_enable
(
struct
wl1271
*
wl
,
u8
*
addr
,
u8
role_type
,
u8
*
role_id
);
int
wl12xx_cmd_role_disable
(
struct
wl1271
*
wl
,
u8
*
role_id
);
int
wl12xx_cmd_role_start_
dev
(
struct
wl1271
*
wl
);
int
wl12xx_cmd_role_stop_
dev
(
struct
wl1271
*
wl
);
int
wl12xx_cmd_role_start_
sta
(
struct
wl1271
*
wl
);
int
wl12xx_cmd_role_stop_
sta
(
struct
wl1271
*
wl
);
int
wl12xx_cmd_role_start_
ap
(
struct
wl1271
*
wl
);
int
wl12xx_
cmd_role_stop_ap
(
struct
wl1271
*
wl
);
int
wl12xx_
cmd_role_start_ibss
(
struct
wl1271
*
wl
);
int
wl12xx_cmd_role_start_
sta
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl12xx_cmd_role_stop_
sta
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl12xx_cmd_role_start_
ap
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl12xx_cmd_role_stop_
ap
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl12xx_cmd_role_start_
ibss
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl12xx_
start_dev
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl12xx_
stop_dev
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl1271_cmd_test
(
struct
wl1271
*
wl
,
void
*
buf
,
size_t
buf_len
,
u8
answer
);
int
wl1271_cmd_interrogate
(
struct
wl1271
*
wl
,
u16
id
,
void
*
buf
,
size_t
len
);
int
wl1271_cmd_configure
(
struct
wl1271
*
wl
,
u16
id
,
void
*
buf
,
size_t
len
);
int
wl1271_cmd_data_path
(
struct
wl1271
*
wl
,
bool
enable
);
int
wl1271_cmd_ps_mode
(
struct
wl1271
*
wl
,
u8
ps_mode
);
int
wl1271_cmd_ps_mode
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
ps_mode
);
int
wl1271_cmd_read_memory
(
struct
wl1271
*
wl
,
u32
addr
,
void
*
answer
,
size_t
len
);
int
wl1271_cmd_template_set
(
struct
wl1271
*
wl
,
u16
template_id
,
void
*
buf
,
size_t
buf_len
,
int
index
,
u32
rates
);
int
wl1271_cmd_build_null_data
(
struct
wl1271
*
wl
);
int
wl1271_cmd_build_ps_poll
(
struct
wl1271
*
wl
,
u16
aid
);
int
wl1271_cmd_build_probe_req
(
struct
wl1271
*
wl
,
int
wl12xx_cmd_build_null_data
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl1271_cmd_build_ps_poll
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u16
aid
);
int
wl1271_cmd_build_probe_req
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
const
u8
*
ssid
,
size_t
ssid_len
,
const
u8
*
ie
,
size_t
ie_len
,
u8
band
);
struct
sk_buff
*
wl1271_cmd_build_ap_probe_req
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
sk_buff
*
skb
);
int
wl1271_cmd_build_arp_rsp
(
struct
wl1271
*
wl
,
__be32
ip_addr
);
int
wl1271_build_qos_null_data
(
struct
wl1271
*
wl
);
int
wl1271_cmd_build_klv_null_data
(
struct
wl1271
*
wl
);
int
wl1271_cmd_build_arp_rsp
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
__be32
ip_addr
);
int
wl1271_build_qos_null_data
(
struct
wl1271
*
wl
,
struct
ieee80211_vif
*
vif
);
int
wl12xx_cmd_build_klv_null_data
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl12xx_cmd_set_default_wep_key
(
struct
wl1271
*
wl
,
u8
id
,
u8
hlid
);
int
wl1271_cmd_set_sta_key
(
struct
wl1271
*
wl
,
u16
action
,
u8
id
,
u8
key_type
,
int
wl1271_cmd_set_sta_key
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u16
action
,
u8
id
,
u8
key_type
,
u8
key_size
,
const
u8
*
key
,
const
u8
*
addr
,
u32
tx_seq_32
,
u16
tx_seq_16
);
int
wl1271_cmd_set_ap_key
(
struct
wl1271
*
wl
,
u16
action
,
u8
id
,
u8
key_type
,
int
wl1271_cmd_set_ap_key
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u16
action
,
u8
id
,
u8
key_type
,
u8
key_size
,
const
u8
*
key
,
u8
hlid
,
u32
tx_seq_32
,
u16
tx_seq_16
);
int
wl12xx_cmd_set_peer_state
(
struct
wl1271
*
wl
,
u8
hlid
);
int
wl12xx_roc
(
struct
wl1271
*
wl
,
u8
role_id
);
int
wl12xx_roc
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
role_id
);
int
wl12xx_croc
(
struct
wl1271
*
wl
,
u8
role_id
);
int
wl12xx_cmd_add_peer
(
struct
wl1271
*
wl
,
struct
ieee80211_sta
*
sta
,
u8
hlid
);
int
wl12xx_cmd_add_peer
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
ieee80211_sta
*
sta
,
u8
hlid
);
int
wl12xx_cmd_remove_peer
(
struct
wl1271
*
wl
,
u8
hlid
);
int
wl12xx_cmd_config_fwlog
(
struct
wl1271
*
wl
);
int
wl12xx_cmd_start_fwlog
(
struct
wl1271
*
wl
);
...
...
@@ -82,6 +91,9 @@ int wl12xx_cmd_stop_fwlog(struct wl1271 *wl);
int
wl12xx_cmd_channel_switch
(
struct
wl1271
*
wl
,
struct
ieee80211_channel_switch
*
ch_switch
);
int
wl12xx_cmd_stop_channel_switch
(
struct
wl1271
*
wl
);
int
wl12xx_allocate_link
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
*
hlid
);
void
wl12xx_free_link
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
*
hlid
);
enum
wl1271_commands
{
CMD_INTERROGATE
=
1
,
/*use this to read information elements*/
...
...
drivers/net/wireless/wl12xx/conf.h
View file @
f589cf4f
...
...
@@ -440,6 +440,10 @@ struct conf_rx_settings {
CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \
CONF_HW_BIT_RATE_54MBPS)
#define CONF_TX_CCK_RATES (CONF_HW_BIT_RATE_1MBPS | \
CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | \
CONF_HW_BIT_RATE_11MBPS)
#define CONF_TX_OFDM_RATES (CONF_HW_BIT_RATE_6MBPS | \
CONF_HW_BIT_RATE_12MBPS | CONF_HW_BIT_RATE_24MBPS | \
CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \
...
...
drivers/net/wireless/wl12xx/debug.h
0 → 100644
View file @
f589cf4f
/*
* This file is part of wl12xx
*
* Copyright (C) 2011 Texas Instruments. All rights reserved.
* Copyright (C) 2008-2009 Nokia Corporation
*
* Contact: Luciano Coelho <coelho@ti.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __DEBUG_H__
#define __DEBUG_H__
#include <linux/bitops.h>
#include <linux/printk.h>
#define DRIVER_NAME "wl12xx"
#define DRIVER_PREFIX DRIVER_NAME ": "
enum
{
DEBUG_NONE
=
0
,
DEBUG_IRQ
=
BIT
(
0
),
DEBUG_SPI
=
BIT
(
1
),
DEBUG_BOOT
=
BIT
(
2
),
DEBUG_MAILBOX
=
BIT
(
3
),
DEBUG_TESTMODE
=
BIT
(
4
),
DEBUG_EVENT
=
BIT
(
5
),
DEBUG_TX
=
BIT
(
6
),
DEBUG_RX
=
BIT
(
7
),
DEBUG_SCAN
=
BIT
(
8
),
DEBUG_CRYPT
=
BIT
(
9
),
DEBUG_PSM
=
BIT
(
10
),
DEBUG_MAC80211
=
BIT
(
11
),
DEBUG_CMD
=
BIT
(
12
),
DEBUG_ACX
=
BIT
(
13
),
DEBUG_SDIO
=
BIT
(
14
),
DEBUG_FILTERS
=
BIT
(
15
),
DEBUG_ADHOC
=
BIT
(
16
),
DEBUG_AP
=
BIT
(
17
),
DEBUG_MASTER
=
(
DEBUG_ADHOC
|
DEBUG_AP
),
DEBUG_ALL
=
~
0
,
};
extern
u32
wl12xx_debug_level
;
#define DEBUG_DUMP_LIMIT 1024
#define wl1271_error(fmt, arg...) \
pr_err(DRIVER_PREFIX "ERROR " fmt "\n", ##arg)
#define wl1271_warning(fmt, arg...) \
pr_warning(DRIVER_PREFIX "WARNING " fmt "\n", ##arg)
#define wl1271_notice(fmt, arg...) \
pr_info(DRIVER_PREFIX fmt "\n", ##arg)
#define wl1271_info(fmt, arg...) \
pr_info(DRIVER_PREFIX fmt "\n", ##arg)
#define wl1271_debug(level, fmt, arg...) \
do { \
if (level & wl12xx_debug_level) \
pr_debug(DRIVER_PREFIX fmt "\n", ##arg); \
} while (0)
/* TODO: use pr_debug_hex_dump when it becomes available */
#define wl1271_dump(level, prefix, buf, len) \
do { \
if (level & wl12xx_debug_level) \
print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \
DUMP_PREFIX_OFFSET, 16, 1, \
buf, \
min_t(size_t, len, DEBUG_DUMP_LIMIT), \
0); \
} while (0)
#define wl1271_dump_ascii(level, prefix, buf, len) \
do { \
if (level & wl12xx_debug_level) \
print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \
DUMP_PREFIX_OFFSET, 16, 1, \
buf, \
min_t(size_t, len, DEBUG_DUMP_LIMIT), \
true); \
} while (0)
#endif
/* __DEBUG_H__ */
drivers/net/wireless/wl12xx/debugfs.c
View file @
f589cf4f
...
...
@@ -27,6 +27,7 @@
#include <linux/slab.h>
#include "wl12xx.h"
#include "debug.h"
#include "acx.h"
#include "ps.h"
#include "io.h"
...
...
@@ -346,29 +347,14 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
DRIVER_STATE_PRINT_INT
(
tx_results_count
);
DRIVER_STATE_PRINT_LHEX
(
flags
);
DRIVER_STATE_PRINT_INT
(
tx_blocks_freed
);
DRIVER_STATE_PRINT_INT
(
tx_security_last_seq_lsb
);
DRIVER_STATE_PRINT_INT
(
rx_counter
);
DRIVER_STATE_PRINT_INT
(
session_counter
);
DRIVER_STATE_PRINT_INT
(
state
);
DRIVER_STATE_PRINT_INT
(
bss_type
);
DRIVER_STATE_PRINT_INT
(
channel
);
DRIVER_STATE_PRINT_HEX
(
rate_set
);
DRIVER_STATE_PRINT_HEX
(
basic_rate_set
);
DRIVER_STATE_PRINT_HEX
(
basic_rate
);
DRIVER_STATE_PRINT_INT
(
band
);
DRIVER_STATE_PRINT_INT
(
beacon_int
);
DRIVER_STATE_PRINT_INT
(
psm_entry_retry
);
DRIVER_STATE_PRINT_INT
(
ps_poll_failures
);
DRIVER_STATE_PRINT_INT
(
power_level
);
DRIVER_STATE_PRINT_INT
(
rssi_thold
);
DRIVER_STATE_PRINT_INT
(
last_rssi_event
);
DRIVER_STATE_PRINT_INT
(
sg_enabled
);
DRIVER_STATE_PRINT_INT
(
enable_11a
);
DRIVER_STATE_PRINT_INT
(
noise
);
DRIVER_STATE_PRINT_LHEX
(
ap_hlid_map
[
0
]);
DRIVER_STATE_PRINT_INT
(
last_tx_hlid
);
DRIVER_STATE_PRINT_INT
(
ba_support
);
DRIVER_STATE_PRINT_HEX
(
ba_rx_bitmap
);
DRIVER_STATE_PRINT_HEX
(
ap_fw_ps_map
);
DRIVER_STATE_PRINT_LHEX
(
ap_ps_map
);
DRIVER_STATE_PRINT_HEX
(
quirks
);
...
...
@@ -399,6 +385,115 @@ static const struct file_operations driver_state_ops = {
.
llseek
=
default_llseek
,
};
static
ssize_t
vifs_state_read
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
wl1271
*
wl
=
file
->
private_data
;
struct
wl12xx_vif
*
wlvif
;
int
ret
,
res
=
0
;
const
int
buf_size
=
4096
;
char
*
buf
;
char
tmp_buf
[
64
];
buf
=
kzalloc
(
buf_size
,
GFP_KERNEL
);
if
(
!
buf
)
return
-
ENOMEM
;
mutex_lock
(
&
wl
->
mutex
);
#define VIF_STATE_PRINT(x, fmt) \
(res += scnprintf(buf + res, buf_size - res, \
#x " = " fmt "\n", wlvif->x))
#define VIF_STATE_PRINT_LONG(x) VIF_STATE_PRINT(x, "%ld")
#define VIF_STATE_PRINT_INT(x) VIF_STATE_PRINT(x, "%d")
#define VIF_STATE_PRINT_STR(x) VIF_STATE_PRINT(x, "%s")
#define VIF_STATE_PRINT_LHEX(x) VIF_STATE_PRINT(x, "0x%lx")
#define VIF_STATE_PRINT_LLHEX(x) VIF_STATE_PRINT(x, "0x%llx")
#define VIF_STATE_PRINT_HEX(x) VIF_STATE_PRINT(x, "0x%x")
#define VIF_STATE_PRINT_NSTR(x, len) \
do { \
memset(tmp_buf, 0, sizeof(tmp_buf)); \
memcpy(tmp_buf, wlvif->x, \
min_t(u8, len, sizeof(tmp_buf) - 1)); \
res += scnprintf(buf + res, buf_size - res, \
#x " = %s\n", tmp_buf); \
} while (0)
wl12xx_for_each_wlvif
(
wl
,
wlvif
)
{
VIF_STATE_PRINT_INT
(
role_id
);
VIF_STATE_PRINT_INT
(
bss_type
);
VIF_STATE_PRINT_LHEX
(
flags
);
VIF_STATE_PRINT_INT
(
p2p
);
VIF_STATE_PRINT_INT
(
dev_role_id
);
VIF_STATE_PRINT_INT
(
dev_hlid
);
if
(
wlvif
->
bss_type
==
BSS_TYPE_STA_BSS
||
wlvif
->
bss_type
==
BSS_TYPE_IBSS
)
{
VIF_STATE_PRINT_INT
(
sta
.
hlid
);
VIF_STATE_PRINT_INT
(
sta
.
ba_rx_bitmap
);
VIF_STATE_PRINT_INT
(
sta
.
basic_rate_idx
);
VIF_STATE_PRINT_INT
(
sta
.
ap_rate_idx
);
VIF_STATE_PRINT_INT
(
sta
.
p2p_rate_idx
);
}
else
{
VIF_STATE_PRINT_INT
(
ap
.
global_hlid
);
VIF_STATE_PRINT_INT
(
ap
.
bcast_hlid
);
VIF_STATE_PRINT_LHEX
(
ap
.
sta_hlid_map
[
0
]);
VIF_STATE_PRINT_INT
(
ap
.
mgmt_rate_idx
);
VIF_STATE_PRINT_INT
(
ap
.
bcast_rate_idx
);
VIF_STATE_PRINT_INT
(
ap
.
ucast_rate_idx
[
0
]);
VIF_STATE_PRINT_INT
(
ap
.
ucast_rate_idx
[
1
]);
VIF_STATE_PRINT_INT
(
ap
.
ucast_rate_idx
[
2
]);
VIF_STATE_PRINT_INT
(
ap
.
ucast_rate_idx
[
3
]);
}
VIF_STATE_PRINT_INT
(
last_tx_hlid
);
VIF_STATE_PRINT_LHEX
(
links_map
[
0
]);
VIF_STATE_PRINT_NSTR
(
ssid
,
wlvif
->
ssid_len
);
VIF_STATE_PRINT_INT
(
band
);
VIF_STATE_PRINT_INT
(
channel
);
VIF_STATE_PRINT_HEX
(
bitrate_masks
[
0
]);
VIF_STATE_PRINT_HEX
(
bitrate_masks
[
1
]);
VIF_STATE_PRINT_HEX
(
basic_rate_set
);
VIF_STATE_PRINT_HEX
(
basic_rate
);
VIF_STATE_PRINT_HEX
(
rate_set
);
VIF_STATE_PRINT_INT
(
beacon_int
);
VIF_STATE_PRINT_INT
(
default_key
);
VIF_STATE_PRINT_INT
(
aid
);
VIF_STATE_PRINT_INT
(
session_counter
);
VIF_STATE_PRINT_INT
(
ps_poll_failures
);
VIF_STATE_PRINT_INT
(
psm_entry_retry
);
VIF_STATE_PRINT_INT
(
power_level
);
VIF_STATE_PRINT_INT
(
rssi_thold
);
VIF_STATE_PRINT_INT
(
last_rssi_event
);
VIF_STATE_PRINT_INT
(
ba_support
);
VIF_STATE_PRINT_INT
(
ba_allowed
);
VIF_STATE_PRINT_LLHEX
(
tx_security_seq
);
VIF_STATE_PRINT_INT
(
tx_security_last_seq_lsb
);
}
#undef VIF_STATE_PRINT_INT
#undef VIF_STATE_PRINT_LONG
#undef VIF_STATE_PRINT_HEX
#undef VIF_STATE_PRINT_LHEX
#undef VIF_STATE_PRINT_LLHEX
#undef VIF_STATE_PRINT_STR
#undef VIF_STATE_PRINT_NSTR
#undef VIF_STATE_PRINT
mutex_unlock
(
&
wl
->
mutex
);
ret
=
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
buf
,
res
);
kfree
(
buf
);
return
ret
;
}
static
const
struct
file_operations
vifs_state_ops
=
{
.
read
=
vifs_state_read
,
.
open
=
wl1271_open_file_generic
,
.
llseek
=
default_llseek
,
};
static
ssize_t
dtim_interval_read
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
...
...
@@ -520,6 +615,7 @@ static ssize_t rx_streaming_interval_write(struct file *file,
size_t
count
,
loff_t
*
ppos
)
{
struct
wl1271
*
wl
=
file
->
private_data
;
struct
wl12xx_vif
*
wlvif
;
unsigned
long
value
;
int
ret
;
...
...
@@ -543,7 +639,9 @@ static ssize_t rx_streaming_interval_write(struct file *file,
if
(
ret
<
0
)
goto
out
;
wl1271_recalc_rx_streaming
(
wl
);
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
wl1271_recalc_rx_streaming
(
wl
,
wlvif
);
}
wl1271_ps_elp_sleep
(
wl
);
out:
...
...
@@ -572,6 +670,7 @@ static ssize_t rx_streaming_always_write(struct file *file,
size_t
count
,
loff_t
*
ppos
)
{
struct
wl1271
*
wl
=
file
->
private_data
;
struct
wl12xx_vif
*
wlvif
;
unsigned
long
value
;
int
ret
;
...
...
@@ -595,7 +694,9 @@ static ssize_t rx_streaming_always_write(struct file *file,
if
(
ret
<
0
)
goto
out
;
wl1271_recalc_rx_streaming
(
wl
);
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
wl1271_recalc_rx_streaming
(
wl
,
wlvif
);
}
wl1271_ps_elp_sleep
(
wl
);
out:
...
...
@@ -624,6 +725,7 @@ static ssize_t beacon_filtering_write(struct file *file,
size_t
count
,
loff_t
*
ppos
)
{
struct
wl1271
*
wl
=
file
->
private_data
;
struct
wl12xx_vif
*
wlvif
;
char
buf
[
10
];
size_t
len
;
unsigned
long
value
;
...
...
@@ -646,7 +748,9 @@ static ssize_t beacon_filtering_write(struct file *file,
if
(
ret
<
0
)
goto
out
;
ret
=
wl1271_acx_beacon_filter_opt
(
wl
,
!!
value
);
wl12xx_for_each_wlvif
(
wl
,
wlvif
)
{
ret
=
wl1271_acx_beacon_filter_opt
(
wl
,
wlvif
,
!!
value
);
}
wl1271_ps_elp_sleep
(
wl
);
out:
...
...
@@ -770,6 +874,7 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,
DEBUGFS_ADD
(
gpio_power
,
rootdir
);
DEBUGFS_ADD
(
start_recovery
,
rootdir
);
DEBUGFS_ADD
(
driver_state
,
rootdir
);
DEBUGFS_ADD
(
vifs_state
,
rootdir
);
DEBUGFS_ADD
(
dtim_interval
,
rootdir
);
DEBUGFS_ADD
(
beacon_interval
,
rootdir
);
DEBUGFS_ADD
(
beacon_filtering
,
rootdir
);
...
...
drivers/net/wireless/wl12xx/event.c
View file @
f589cf4f
...
...
@@ -22,6 +22,7 @@
*/
#include "wl12xx.h"
#include "debug.h"
#include "reg.h"
#include "io.h"
#include "event.h"
...
...
@@ -31,12 +32,16 @@
void
wl1271_pspoll_work
(
struct
work_struct
*
work
)
{
struct
ieee80211_vif
*
vif
;
struct
wl12xx_vif
*
wlvif
;
struct
delayed_work
*
dwork
;
struct
wl1271
*
wl
;
int
ret
;
dwork
=
container_of
(
work
,
struct
delayed_work
,
work
);
wl
=
container_of
(
dwork
,
struct
wl1271
,
pspoll_work
);
wlvif
=
container_of
(
dwork
,
struct
wl12xx_vif
,
pspoll_work
);
vif
=
container_of
((
void
*
)
wlvif
,
struct
ieee80211_vif
,
drv_priv
);
wl
=
wlvif
->
wl
;
wl1271_debug
(
DEBUG_EVENT
,
"pspoll work"
);
...
...
@@ -45,10 +50,10 @@ void wl1271_pspoll_work(struct work_struct *work)
if
(
unlikely
(
wl
->
state
==
WL1271_STATE_OFF
))
goto
out
;
if
(
!
test_and_clear_bit
(
WL
1271_FLAG_PSPOLL_FAILURE
,
&
wl
->
flags
))
if
(
!
test_and_clear_bit
(
WL
VIF_FLAG_PSPOLL_FAILURE
,
&
wlvif
->
flags
))
goto
out
;
if
(
!
test_bit
(
WL
1271_FLAG_STA_ASSOCIATED
,
&
wl
->
flags
))
if
(
!
test_bit
(
WL
VIF_FLAG_STA_ASSOCIATED
,
&
wlvif
->
flags
))
goto
out
;
/*
...
...
@@ -60,31 +65,33 @@ void wl1271_pspoll_work(struct work_struct *work)
if
(
ret
<
0
)
goto
out
;
wl1271_ps_set_mode
(
wl
,
STATION_POWER_SAVE_MODE
,
wl
->
basic_rate
,
true
);
wl1271_ps_set_mode
(
wl
,
wlvif
,
STATION_POWER_SAVE_MODE
,
wlvif
->
basic_rate
,
true
);
wl1271_ps_elp_sleep
(
wl
);
out:
mutex_unlock
(
&
wl
->
mutex
);
};
static
void
wl1271_event_pspoll_delivery_fail
(
struct
wl1271
*
wl
)
static
void
wl1271_event_pspoll_delivery_fail
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
int
delay
=
wl
->
conf
.
conn
.
ps_poll_recovery_period
;
int
ret
;
wl
->
ps_poll_failures
++
;
if
(
wl
->
ps_poll_failures
==
1
)
wl
vif
->
ps_poll_failures
++
;
if
(
wl
vif
->
ps_poll_failures
==
1
)
wl1271_info
(
"AP with dysfunctional ps-poll, "
"trying to work around it."
);
/* force active mode receive data from the AP */
if
(
test_bit
(
WL
1271_FLAG_PSM
,
&
wl
->
flags
))
{
ret
=
wl1271_ps_set_mode
(
wl
,
STATION_ACTIVE_MODE
,
wl
->
basic_rate
,
true
);
if
(
test_bit
(
WL
VIF_FLAG_PSM
,
&
wlvif
->
flags
))
{
ret
=
wl1271_ps_set_mode
(
wl
,
wlvif
,
STATION_ACTIVE_MODE
,
wl
vif
->
basic_rate
,
true
);
if
(
ret
<
0
)
return
;
set_bit
(
WL
1271_FLAG_PSPOLL_FAILURE
,
&
wl
->
flags
);
ieee80211_queue_delayed_work
(
wl
->
hw
,
&
wl
->
pspoll_work
,
set_bit
(
WL
VIF_FLAG_PSPOLL_FAILURE
,
&
wlvif
->
flags
);
ieee80211_queue_delayed_work
(
wl
->
hw
,
&
wl
vif
->
pspoll_work
,
msecs_to_jiffies
(
delay
));
}
...
...
@@ -97,6 +104,7 @@ static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl)
}
static
int
wl1271_event_ps_report
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
event_mailbox
*
mbox
,
bool
*
beacon_loss
)
{
...
...
@@ -109,41 +117,37 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
case
EVENT_ENTER_POWER_SAVE_FAIL
:
wl1271_debug
(
DEBUG_PSM
,
"PSM entry failed"
);
if
(
!
test_bit
(
WL
1271_FLAG_PSM
,
&
wl
->
flags
))
{
if
(
!
test_bit
(
WL
VIF_FLAG_PSM
,
&
wlvif
->
flags
))
{
/* remain in active mode */
wl
->
psm_entry_retry
=
0
;
wl
vif
->
psm_entry_retry
=
0
;
break
;
}
if
(
wl
->
psm_entry_retry
<
total_retries
)
{
wl
->
psm_entry_retry
++
;
ret
=
wl1271_ps_set_mode
(
wl
,
STATION_POWER_SAVE_MODE
,
wl
->
basic_rate
,
true
);
if
(
wlvif
->
psm_entry_retry
<
total_retries
)
{
wlvif
->
psm_entry_retry
++
;
ret
=
wl1271_ps_set_mode
(
wl
,
wlvif
,
STATION_POWER_SAVE_MODE
,
wlvif
->
basic_rate
,
true
);
}
else
{
wl1271_info
(
"No ack to nullfunc from AP."
);
wl
->
psm_entry_retry
=
0
;
wl
vif
->
psm_entry_retry
=
0
;
*
beacon_loss
=
true
;
}
break
;
case
EVENT_ENTER_POWER_SAVE_SUCCESS
:
wl
->
psm_entry_retry
=
0
;
/* enable beacon filtering */
ret
=
wl1271_acx_beacon_filter_opt
(
wl
,
true
);
if
(
ret
<
0
)
break
;
wlvif
->
psm_entry_retry
=
0
;
/*
* BET has only a minor effect in 5GHz and masks
* channel switch IEs, so we only enable BET on 2.4GHz
*/
if
(
wl
->
band
==
IEEE80211_BAND_2GHZ
)
if
(
wl
vif
->
band
==
IEEE80211_BAND_2GHZ
)
/* enable beacon early termination */
ret
=
wl1271_acx_bet_enable
(
wl
,
true
);
ret
=
wl1271_acx_bet_enable
(
wl
,
wlvif
,
true
);
if
(
wl
->
ps_compl
)
{
complete
(
wl
->
ps_compl
);
wl
->
ps_compl
=
NULL
;
if
(
wl
vif
->
ps_compl
)
{
complete
(
wl
vif
->
ps_compl
);
wl
vif
->
ps_compl
=
NULL
;
}
break
;
default:
...
...
@@ -154,39 +158,44 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
}
static
void
wl1271_event_rssi_trigger
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
event_mailbox
*
mbox
)
{
struct
ieee80211_vif
*
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
enum
nl80211_cqm_rssi_threshold_event
event
;
s8
metric
=
mbox
->
rssi_snr_trigger_metric
[
0
];
wl1271_debug
(
DEBUG_EVENT
,
"RSSI trigger metric: %d"
,
metric
);
if
(
metric
<=
wl
->
rssi_thold
)
if
(
metric
<=
wl
vif
->
rssi_thold
)
event
=
NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW
;
else
event
=
NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH
;
if
(
event
!=
wl
->
last_rssi_event
)
ieee80211_cqm_rssi_notify
(
wl
->
vif
,
event
,
GFP_KERNEL
);
wl
->
last_rssi_event
=
event
;
if
(
event
!=
wl
vif
->
last_rssi_event
)
ieee80211_cqm_rssi_notify
(
vif
,
event
,
GFP_KERNEL
);
wl
vif
->
last_rssi_event
=
event
;
}
static
void
wl1271_stop_ba_event
(
struct
wl1271
*
wl
)
static
void
wl1271_stop_ba_event
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
if
(
wl
->
bss_type
!=
BSS_TYPE_AP_BSS
)
{
if
(
!
wl
->
ba_rx_bitmap
)
struct
ieee80211_vif
*
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
if
(
wlvif
->
bss_type
!=
BSS_TYPE_AP_BSS
)
{
if
(
!
wlvif
->
sta
.
ba_rx_bitmap
)
return
;
ieee80211_stop_rx_ba_session
(
wl
->
vif
,
wl
->
ba_rx_bitmap
,
wl
->
bssid
);
ieee80211_stop_rx_ba_session
(
vif
,
wlvif
->
sta
.
ba_rx_bitmap
,
vif
->
bss_conf
.
bssid
);
}
else
{
int
i
;
u8
hlid
;
struct
wl1271_link
*
lnk
;
for
(
i
=
WL1271_AP_STA_HLID_START
;
i
<
AP_MAX_LINKS
;
i
++
)
{
lnk
=
&
wl
->
links
[
i
];
if
(
!
wl1271_is_active_sta
(
wl
,
i
)
||
!
lnk
->
ba_bitmap
)
for_each_set_bit
(
hlid
,
wlvif
->
ap
.
sta_hlid_map
,
WL12XX_MAX_LINKS
)
{
lnk
=
&
wl
->
links
[
hlid
];
if
(
!
lnk
->
ba_bitmap
)
continue
;
ieee80211_stop_rx_ba_session
(
wl
->
vif
,
ieee80211_stop_rx_ba_session
(
vif
,
lnk
->
ba_bitmap
,
lnk
->
addr
);
}
...
...
@@ -196,14 +205,23 @@ static void wl1271_stop_ba_event(struct wl1271 *wl)
static
void
wl12xx_event_soft_gemini_sense
(
struct
wl1271
*
wl
,
u8
enable
)
{
struct
ieee80211_vif
*
vif
;
struct
wl12xx_vif
*
wlvif
;
if
(
enable
)
{
/* disable dynamic PS when requested by the firmware */
ieee80211_disable_dyn_ps
(
wl
->
vif
);
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
ieee80211_disable_dyn_ps
(
vif
);
}
set_bit
(
WL1271_FLAG_SOFT_GEMINI
,
&
wl
->
flags
);
}
else
{
ieee80211_enable_dyn_ps
(
wl
->
vif
);
clear_bit
(
WL1271_FLAG_SOFT_GEMINI
,
&
wl
->
flags
);
wl1271_recalc_rx_streaming
(
wl
);
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
ieee80211_enable_dyn_ps
(
vif
);
wl1271_recalc_rx_streaming
(
wl
,
wlvif
);
}
}
}
...
...
@@ -217,10 +235,11 @@ static void wl1271_event_mbox_dump(struct event_mailbox *mbox)
static
int
wl1271_event_process
(
struct
wl1271
*
wl
,
struct
event_mailbox
*
mbox
)
{
struct
ieee80211_vif
*
vif
;
struct
wl12xx_vif
*
wlvif
;
int
ret
;
u32
vector
;
bool
beacon_loss
=
false
;
bool
is_ap
=
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
);
bool
disconnect_sta
=
false
;
unsigned
long
sta_bitmap
=
0
;
...
...
@@ -234,7 +253,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
wl1271_debug
(
DEBUG_EVENT
,
"status: 0x%x"
,
mbox
->
scheduled_scan_status
);
wl1271_scan_stm
(
wl
);
wl1271_scan_stm
(
wl
,
wl
->
scan_vif
);
}
if
(
vector
&
PERIODIC_SCAN_REPORT_EVENT_ID
)
{
...
...
@@ -253,8 +272,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
}
}
if
(
vector
&
SOFT_GEMINI_SENSE_EVENT_ID
&&
wl
->
bss_type
==
BSS_TYPE_STA_BSS
)
if
(
vector
&
SOFT_GEMINI_SENSE_EVENT_ID
)
wl12xx_event_soft_gemini_sense
(
wl
,
mbox
->
soft_gemini_sense_info
);
...
...
@@ -267,40 +285,54 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
* BSS_LOSE_EVENT, beacon loss has to be reported to the stack.
*
*/
if
((
vector
&
BSS_LOSE_EVENT_ID
)
&&
!
is_ap
)
{
if
(
vector
&
BSS_LOSE_EVENT_ID
)
{
/* TODO: check for multi-role */
wl1271_info
(
"Beacon loss detected."
);
/* indicate to the stack, that beacons have been lost */
beacon_loss
=
true
;
}
if
(
(
vector
&
PS_REPORT_EVENT_ID
)
&&
!
is_ap
)
{
if
(
vector
&
PS_REPORT_EVENT_ID
)
{
wl1271_debug
(
DEBUG_EVENT
,
"PS_REPORT_EVENT"
);
ret
=
wl1271_event_ps_report
(
wl
,
mbox
,
&
beacon_loss
);
if
(
ret
<
0
)
return
ret
;
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
ret
=
wl1271_event_ps_report
(
wl
,
wlvif
,
mbox
,
&
beacon_loss
);
if
(
ret
<
0
)
return
ret
;
}
}
if
((
vector
&
PSPOLL_DELIVERY_FAILURE_EVENT_ID
)
&&
!
is_ap
)
wl1271_event_pspoll_delivery_fail
(
wl
);
if
(
vector
&
PSPOLL_DELIVERY_FAILURE_EVENT_ID
)
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
wl1271_event_pspoll_delivery_fail
(
wl
,
wlvif
);
}
if
(
vector
&
RSSI_SNR_TRIGGER_0_EVENT_ID
)
{
/* TODO: check actual multi-role support */
wl1271_debug
(
DEBUG_EVENT
,
"RSSI_SNR_TRIGGER_0_EVENT"
);
if
(
wl
->
vif
)
wl1271_event_rssi_trigger
(
wl
,
mbox
);
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
wl1271_event_rssi_trigger
(
wl
,
wlvif
,
mbox
);
}
}
if
((
vector
&
BA_SESSION_RX_CONSTRAINT_EVENT_ID
))
{
if
(
vector
&
BA_SESSION_RX_CONSTRAINT_EVENT_ID
)
{
u8
role_id
=
mbox
->
role_id
;
wl1271_debug
(
DEBUG_EVENT
,
"BA_SESSION_RX_CONSTRAINT_EVENT_ID. "
"ba_allowed = 0x%x"
,
mbox
->
rx_ba_allowed
);
"ba_allowed = 0x%x, role_id=%d"
,
mbox
->
rx_ba_allowed
,
role_id
);
wl
->
ba_allowed
=
!!
mbox
->
rx_ba_allowed
;
wl12xx_for_each_wlvif
(
wl
,
wlvif
)
{
if
(
role_id
!=
0xff
&&
role_id
!=
wlvif
->
role_id
)
continue
;
if
(
wl
->
vif
&&
!
wl
->
ba_allowed
)
wl1271_stop_ba_event
(
wl
);
wlvif
->
ba_allowed
=
!!
mbox
->
rx_ba_allowed
;
if
(
!
wlvif
->
ba_allowed
)
wl1271_stop_ba_event
(
wl
,
wlvif
);
}
}
if
(
(
vector
&
CHANNEL_SWITCH_COMPLETE_EVENT_ID
)
&&
!
is_ap
)
{
if
(
vector
&
CHANNEL_SWITCH_COMPLETE_EVENT_ID
)
{
wl1271_debug
(
DEBUG_EVENT
,
"CHANNEL_SWITCH_COMPLETE_EVENT_ID. "
"status = 0x%x"
,
mbox
->
channel_switch_status
);
...
...
@@ -309,50 +341,65 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
* 1) channel switch complete with status=0
* 2) channel switch failed status=1
*/
if
(
test_and_clear_bit
(
WL1271_FLAG_CS_PROGRESS
,
&
wl
->
flags
)
&&
(
wl
->
vif
))
ieee80211_chswitch_done
(
wl
->
vif
,
mbox
->
channel_switch_status
?
false
:
true
);
/* TODO: configure only the relevant vif */
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
struct
ieee80211_vif
*
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
bool
success
;
if
(
!
test_and_clear_bit
(
WLVIF_FLAG_CS_PROGRESS
,
&
wl
->
flags
))
continue
;
success
=
mbox
->
channel_switch_status
?
false
:
true
;
ieee80211_chswitch_done
(
vif
,
success
);
}
}
if
((
vector
&
DUMMY_PACKET_EVENT_ID
))
{
wl1271_debug
(
DEBUG_EVENT
,
"DUMMY_PACKET_ID_EVENT_ID"
);
if
(
wl
->
vif
)
wl1271_tx_dummy_packet
(
wl
);
wl1271_tx_dummy_packet
(
wl
);
}
/*
* "TX retries exceeded" has a different meaning according to mode.
* In AP mode the offending station is disconnected.
*/
if
(
(
vector
&
MAX_TX_RETRY_EVENT_ID
)
&&
is_ap
)
{
if
(
vector
&
MAX_TX_RETRY_EVENT_ID
)
{
wl1271_debug
(
DEBUG_EVENT
,
"MAX_TX_RETRY_EVENT_ID"
);
sta_bitmap
|=
le16_to_cpu
(
mbox
->
sta_tx_retry_exceeded
);
disconnect_sta
=
true
;
}
if
(
(
vector
&
INACTIVE_STA_EVENT_ID
)
&&
is_ap
)
{
if
(
vector
&
INACTIVE_STA_EVENT_ID
)
{
wl1271_debug
(
DEBUG_EVENT
,
"INACTIVE_STA_EVENT_ID"
);
sta_bitmap
|=
le16_to_cpu
(
mbox
->
sta_aging_status
);
disconnect_sta
=
true
;
}
if
(
is_ap
&&
disconnect_sta
)
{
if
(
disconnect_sta
)
{
u32
num_packets
=
wl
->
conf
.
tx
.
max_tx_retries
;
struct
ieee80211_sta
*
sta
;
const
u8
*
addr
;
int
h
;
for
(
h
=
find_first_bit
(
&
sta_bitmap
,
AP_MAX_LINKS
);
h
<
AP_MAX_LINKS
;
h
=
find_next_bit
(
&
sta_bitmap
,
AP_MAX_LINKS
,
h
+
1
))
{
if
(
!
wl1271_is_active_sta
(
wl
,
h
))
for_each_set_bit
(
h
,
&
sta_bitmap
,
WL12XX_MAX_LINKS
)
{
bool
found
=
false
;
/* find the ap vif connected to this sta */
wl12xx_for_each_wlvif_ap
(
wl
,
wlvif
)
{
if
(
!
test_bit
(
h
,
wlvif
->
ap
.
sta_hlid_map
))
continue
;
found
=
true
;
break
;
}
if
(
!
found
)
continue
;
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
addr
=
wl
->
links
[
h
].
addr
;
rcu_read_lock
();
sta
=
ieee80211_find_sta
(
wl
->
vif
,
addr
);
sta
=
ieee80211_find_sta
(
vif
,
addr
);
if
(
sta
)
{
wl1271_debug
(
DEBUG_EVENT
,
"remove sta %d"
,
h
);
ieee80211_report_low_ack
(
sta
,
num_packets
);
...
...
@@ -361,8 +408,11 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
}
}
if
(
wl
->
vif
&&
beacon_loss
)
ieee80211_connection_loss
(
wl
->
vif
);
if
(
beacon_loss
)
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
ieee80211_connection_loss
(
vif
);
}
return
0
;
}
...
...
drivers/net/wireless/wl12xx/event.h
View file @
f589cf4f
...
...
@@ -132,7 +132,4 @@ void wl1271_event_mbox_config(struct wl1271 *wl);
int
wl1271_event_handle
(
struct
wl1271
*
wl
,
u8
mbox
);
void
wl1271_pspoll_work
(
struct
work_struct
*
work
);
/* Functions from main.c */
bool
wl1271_is_active_sta
(
struct
wl1271
*
wl
,
u8
hlid
);
#endif
drivers/net/wireless/wl12xx/init.c
View file @
f589cf4f
...
...
@@ -25,6 +25,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include "debug.h"
#include "init.h"
#include "wl12xx_80211.h"
#include "acx.h"
...
...
@@ -33,7 +34,7 @@
#include "tx.h"
#include "io.h"
int
wl1271_
sta_
init_templates_config
(
struct
wl1271
*
wl
)
int
wl1271_init_templates_config
(
struct
wl1271
*
wl
)
{
int
ret
,
i
;
...
...
@@ -64,7 +65,7 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl)
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_QOS_NULL_DATA
,
NULL
,
sizeof
(
struct
wl12xx_qos_null_data_template
),
(
struct
ieee80211_qos_hdr
),
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -88,10 +89,33 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl)
if
(
ret
<
0
)
return
ret
;
/*
* Put very large empty placeholders for all templates. These
* reserve memory for later.
*/
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_AP_PROBE_RESPONSE
,
NULL
,
WL1271_CMD_TEMPL_MAX_SIZE
,
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_AP_BEACON
,
NULL
,
WL1271_CMD_TEMPL_MAX_SIZE
,
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_DEAUTH_AP
,
NULL
,
sizeof
(
struct
wl12xx_disconn_template
),
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
return
ret
;
for
(
i
=
0
;
i
<
CMD_TEMPL_KLV_IDX_MAX
;
i
++
)
{
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_KLV
,
NULL
,
WL1271_CMD_TEMPL_DFLT_SIZE
,
i
,
WL1271_RATE_AUTOMATIC
);
sizeof
(
struct
ieee80211_qos_hdr
)
,
i
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
return
ret
;
}
...
...
@@ -99,7 +123,8 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl)
return
0
;
}
static
int
wl1271_ap_init_deauth_template
(
struct
wl1271
*
wl
)
static
int
wl1271_ap_init_deauth_template
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
wl12xx_disconn_template
*
tmpl
;
int
ret
;
...
...
@@ -114,7 +139,7 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl)
tmpl
->
header
.
frame_ctl
=
cpu_to_le16
(
IEEE80211_FTYPE_MGMT
|
IEEE80211_STYPE_DEAUTH
);
rate
=
wl1271_tx_min_rate_get
(
wl
,
wl
->
basic_rate_set
);
rate
=
wl1271_tx_min_rate_get
(
wl
,
wl
vif
->
basic_rate_set
);
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_DEAUTH_AP
,
tmpl
,
sizeof
(
*
tmpl
),
0
,
rate
);
...
...
@@ -123,8 +148,10 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl)
return
ret
;
}
static
int
wl1271_ap_init_null_template
(
struct
wl1271
*
wl
)
static
int
wl1271_ap_init_null_template
(
struct
wl1271
*
wl
,
struct
ieee80211_vif
*
vif
)
{
struct
wl12xx_vif
*
wlvif
=
wl12xx_vif_to_data
(
vif
);
struct
ieee80211_hdr_3addr
*
nullfunc
;
int
ret
;
u32
rate
;
...
...
@@ -141,10 +168,10 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl)
/* nullfunc->addr1 is filled by FW */
memcpy
(
nullfunc
->
addr2
,
wl
->
mac_
addr
,
ETH_ALEN
);
memcpy
(
nullfunc
->
addr3
,
wl
->
mac_
addr
,
ETH_ALEN
);
memcpy
(
nullfunc
->
addr2
,
vif
->
addr
,
ETH_ALEN
);
memcpy
(
nullfunc
->
addr3
,
vif
->
addr
,
ETH_ALEN
);
rate
=
wl1271_tx_min_rate_get
(
wl
,
wl
->
basic_rate_set
);
rate
=
wl1271_tx_min_rate_get
(
wl
,
wl
vif
->
basic_rate_set
);
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_NULL_DATA
,
nullfunc
,
sizeof
(
*
nullfunc
),
0
,
rate
);
...
...
@@ -153,8 +180,10 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl)
return
ret
;
}
static
int
wl1271_ap_init_qos_null_template
(
struct
wl1271
*
wl
)
static
int
wl1271_ap_init_qos_null_template
(
struct
wl1271
*
wl
,
struct
ieee80211_vif
*
vif
)
{
struct
wl12xx_vif
*
wlvif
=
wl12xx_vif_to_data
(
vif
);
struct
ieee80211_qos_hdr
*
qosnull
;
int
ret
;
u32
rate
;
...
...
@@ -171,10 +200,10 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl)
/* qosnull->addr1 is filled by FW */
memcpy
(
qosnull
->
addr2
,
wl
->
mac_
addr
,
ETH_ALEN
);
memcpy
(
qosnull
->
addr3
,
wl
->
mac_
addr
,
ETH_ALEN
);
memcpy
(
qosnull
->
addr2
,
vif
->
addr
,
ETH_ALEN
);
memcpy
(
qosnull
->
addr3
,
vif
->
addr
,
ETH_ALEN
);
rate
=
wl1271_tx_min_rate_get
(
wl
,
wl
->
basic_rate_set
);
rate
=
wl1271_tx_min_rate_get
(
wl
,
wl
vif
->
basic_rate_set
);
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_QOS_NULL_DATA
,
qosnull
,
sizeof
(
*
qosnull
),
0
,
rate
);
...
...
@@ -183,93 +212,59 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl)
return
ret
;
}
static
int
wl12
71_ap_init_templates
_config
(
struct
wl1271
*
wl
)
static
int
wl12
xx_init_rx
_config
(
struct
wl1271
*
wl
)
{
int
ret
;
/*
* Put very large empty placeholders for all templates. These
* reserve memory for later.
*/
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_AP_PROBE_RESPONSE
,
NULL
,
WL1271_CMD_TEMPL_MAX_SIZE
,
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_AP_BEACON
,
NULL
,
WL1271_CMD_TEMPL_MAX_SIZE
,
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_DEAUTH_AP
,
NULL
,
sizeof
(
struct
wl12xx_disconn_template
),
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_NULL_DATA
,
NULL
,
sizeof
(
struct
wl12xx_null_data_template
),
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_QOS_NULL_DATA
,
NULL
,
sizeof
(
struct
wl12xx_qos_null_data_template
),
0
,
WL1271_RATE_AUTOMATIC
);
ret
=
wl1271_acx_rx_msdu_life_time
(
wl
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
static
int
wl12xx_init_rx
_config
(
struct
wl1271
*
wl
)
int
wl1271_init_phy
_config
(
struct
wl1271
*
wl
)
{
int
ret
;
ret
=
wl1271_acx_
rx_msdu_life_time
(
wl
);
ret
=
wl1271_acx_
pd_threshold
(
wl
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
int
wl1271_init_phy_config
(
struct
wl1271
*
wl
)
static
int
wl12xx_init_phy_vif_config
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
int
ret
;
ret
=
wl1271_acx_pd_threshold
(
wl
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_acx_slot
(
wl
,
DEFAULT_SLOT_TIME
);
ret
=
wl1271_acx_slot
(
wl
,
wlvif
,
DEFAULT_SLOT_TIME
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_acx_service_period_timeout
(
wl
);
ret
=
wl1271_acx_service_period_timeout
(
wl
,
wlvif
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_acx_rts_threshold
(
wl
,
wl
->
hw
->
wiphy
->
rts_threshold
);
ret
=
wl1271_acx_rts_threshold
(
wl
,
wl
vif
,
wl
->
hw
->
wiphy
->
rts_threshold
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
static
int
wl1271_init_beacon_filter
(
struct
wl1271
*
wl
)
static
int
wl1271_init_sta_beacon_filter
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
int
ret
;
/* disable beacon filtering at this stage */
ret
=
wl1271_acx_beacon_filter_opt
(
wl
,
false
);
ret
=
wl1271_acx_beacon_filter_table
(
wl
,
wlvif
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_acx_beacon_filter_table
(
wl
);
/* enable beacon filtering */
ret
=
wl1271_acx_beacon_filter_opt
(
wl
,
wlvif
,
true
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -302,11 +297,12 @@ int wl1271_init_energy_detection(struct wl1271 *wl)
return
0
;
}
static
int
wl1271_init_beacon_broadcast
(
struct
wl1271
*
wl
)
static
int
wl1271_init_beacon_broadcast
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
int
ret
;
ret
=
wl1271_acx_bcn_dtim_options
(
wl
);
ret
=
wl1271_acx_bcn_dtim_options
(
wl
,
wlvif
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -327,7 +323,8 @@ static int wl12xx_init_fwlog(struct wl1271 *wl)
return
0
;
}
static
int
wl1271_sta_hw_init
(
struct
wl1271
*
wl
)
/* generic sta initialization (non vif-specific) */
static
int
wl1271_sta_hw_init
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
int
ret
;
...
...
@@ -338,25 +335,7 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
}
/* PS config */
ret
=
wl1271_acx_config_ps
(
wl
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_sta_init_templates_config
(
wl
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_acx_group_address_tbl
(
wl
,
true
,
NULL
,
0
);
if
(
ret
<
0
)
return
ret
;
/* Initialize connection monitoring thresholds */
ret
=
wl1271_acx_conn_monit_params
(
wl
,
false
);
if
(
ret
<
0
)
return
ret
;
/* Beacon filtering */
ret
=
wl1271_init_beacon_filter
(
wl
);
ret
=
wl12xx_acx_config_ps
(
wl
,
wlvif
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -365,103 +344,61 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
if
(
ret
<
0
)
return
ret
;
/* Beacons and broadcast settings */
ret
=
wl1271_init_beacon_broadcast
(
wl
);
if
(
ret
<
0
)
return
ret
;
/* Configure for ELP power saving */
ret
=
wl1271_acx_sleep_auth
(
wl
,
WL1271_PSM_ELP
);
if
(
ret
<
0
)
return
ret
;
/* Configure rssi/snr averaging weights */
ret
=
wl1271_acx_rssi_snr_avg_weights
(
wl
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_acx_sta_rate_policies
(
wl
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl12xx_acx_mem_cfg
(
wl
);
if
(
ret
<
0
)
return
ret
;
/* Configure the FW logger */
ret
=
wl12xx_init_fwlog
(
wl
);
ret
=
wl1271_acx_sta_rate_policies
(
wl
,
wlvif
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
static
int
wl1271_sta_hw_init_post_mem
(
struct
wl1271
*
wl
)
static
int
wl1271_sta_hw_init_post_mem
(
struct
wl1271
*
wl
,
struct
ieee80211_vif
*
vif
)
{
struct
wl12xx_vif
*
wlvif
=
wl12xx_vif_to_data
(
vif
);
int
ret
,
i
;
/* disable all keep-alive templates */
for
(
i
=
0
;
i
<
CMD_TEMPL_KLV_IDX_MAX
;
i
++
)
{
ret
=
wl1271_acx_keep_alive_config
(
wl
,
i
,
ret
=
wl1271_acx_keep_alive_config
(
wl
,
wlvif
,
i
,
ACX_KEEP_ALIVE_TPL_INVALID
);
if
(
ret
<
0
)
return
ret
;
}
/* disable the keep-alive feature */
ret
=
wl1271_acx_keep_alive_mode
(
wl
,
false
);
ret
=
wl1271_acx_keep_alive_mode
(
wl
,
wlvif
,
false
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
static
int
wl1271_ap_hw_init
(
struct
wl1271
*
wl
)
/* generic ap initialization (non vif-specific) */
static
int
wl1271_ap_hw_init
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
int
ret
;
ret
=
wl1271_ap_init_templates_config
(
wl
);
if
(
ret
<
0
)
return
ret
;
/* Configure for power always on */
ret
=
wl1271_acx_sleep_auth
(
wl
,
WL1271_PSM_CAM
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_init_ap_rates
(
wl
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_acx_ap_max_tx_retry
(
wl
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl12xx_acx_mem_cfg
(
wl
);
if
(
ret
<
0
)
return
ret
;
/* initialize Tx power */
ret
=
wl1271_acx_tx_power
(
wl
,
wl
->
power_level
);
ret
=
wl1271_init_ap_rates
(
wl
,
wlvif
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
int
wl1271_ap_init_templates
(
struct
wl1271
*
wl
)
int
wl1271_ap_init_templates
(
struct
wl1271
*
wl
,
struct
ieee80211_vif
*
vif
)
{
struct
wl12xx_vif
*
wlvif
=
wl12xx_vif_to_data
(
vif
);
int
ret
;
ret
=
wl1271_ap_init_deauth_template
(
wl
);
ret
=
wl1271_ap_init_deauth_template
(
wl
,
wlvif
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_ap_init_null_template
(
wl
);
ret
=
wl1271_ap_init_null_template
(
wl
,
vif
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_ap_init_qos_null_template
(
wl
);
ret
=
wl1271_ap_init_qos_null_template
(
wl
,
vif
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -469,43 +406,45 @@ int wl1271_ap_init_templates(struct wl1271 *wl)
* when operating as AP we want to receive external beacons for
* configuring ERP protection.
*/
ret
=
wl1271_acx_beacon_filter_opt
(
wl
,
false
);
ret
=
wl1271_acx_beacon_filter_opt
(
wl
,
wlvif
,
false
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
static
int
wl1271_ap_hw_init_post_mem
(
struct
wl1271
*
wl
)
static
int
wl1271_ap_hw_init_post_mem
(
struct
wl1271
*
wl
,
struct
ieee80211_vif
*
vif
)
{
return
wl1271_ap_init_templates
(
wl
);
return
wl1271_ap_init_templates
(
wl
,
vif
);
}
int
wl1271_init_ap_rates
(
struct
wl1271
*
wl
)
int
wl1271_init_ap_rates
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
int
i
,
ret
;
struct
conf_tx_rate_class
rc
;
u32
supported_rates
;
wl1271_debug
(
DEBUG_AP
,
"AP basic rate set: 0x%x"
,
wl
->
basic_rate_set
);
wl1271_debug
(
DEBUG_AP
,
"AP basic rate set: 0x%x"
,
wlvif
->
basic_rate_set
);
if
(
wl
->
basic_rate_set
==
0
)
if
(
wl
vif
->
basic_rate_set
==
0
)
return
-
EINVAL
;
rc
.
enabled_rates
=
wl
->
basic_rate_set
;
rc
.
enabled_rates
=
wl
vif
->
basic_rate_set
;
rc
.
long_retry_limit
=
10
;
rc
.
short_retry_limit
=
10
;
rc
.
aflags
=
0
;
ret
=
wl1271_acx_ap_rate_policy
(
wl
,
&
rc
,
ACX_TX_AP_MODE_MGMT_RATE
);
ret
=
wl1271_acx_ap_rate_policy
(
wl
,
&
rc
,
wlvif
->
ap
.
mgmt_rate_idx
);
if
(
ret
<
0
)
return
ret
;
/* use the min basic rate for AP broadcast/multicast */
rc
.
enabled_rates
=
wl1271_tx_min_rate_get
(
wl
,
wl
->
basic_rate_set
);
rc
.
enabled_rates
=
wl1271_tx_min_rate_get
(
wl
,
wl
vif
->
basic_rate_set
);
rc
.
short_retry_limit
=
10
;
rc
.
long_retry_limit
=
10
;
rc
.
aflags
=
0
;
ret
=
wl1271_acx_ap_rate_policy
(
wl
,
&
rc
,
ACX_TX_AP_MODE_BCST_RATE
);
ret
=
wl1271_acx_ap_rate_policy
(
wl
,
&
rc
,
wlvif
->
ap
.
bcast_rate_idx
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -513,7 +452,7 @@ int wl1271_init_ap_rates(struct wl1271 *wl)
* If the basic rates contain OFDM rates, use OFDM only
* rates for unicast TX as well. Else use all supported rates.
*/
if
((
wl
->
basic_rate_set
&
CONF_TX_OFDM_RATES
))
if
((
wl
vif
->
basic_rate_set
&
CONF_TX_OFDM_RATES
))
supported_rates
=
CONF_TX_OFDM_RATES
;
else
supported_rates
=
CONF_TX_AP_ENABLED_RATES
;
...
...
@@ -527,7 +466,8 @@ int wl1271_init_ap_rates(struct wl1271 *wl)
rc
.
short_retry_limit
=
10
;
rc
.
long_retry_limit
=
10
;
rc
.
aflags
=
0
;
ret
=
wl1271_acx_ap_rate_policy
(
wl
,
&
rc
,
i
);
ret
=
wl1271_acx_ap_rate_policy
(
wl
,
&
rc
,
wlvif
->
ap
.
ucast_rate_idx
[
i
]);
if
(
ret
<
0
)
return
ret
;
}
...
...
@@ -535,24 +475,23 @@ int wl1271_init_ap_rates(struct wl1271 *wl)
return
0
;
}
static
int
wl1271_set_ba_policies
(
struct
wl1271
*
wl
)
static
int
wl1271_set_ba_policies
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
/* Reset the BA RX indicators */
wl
->
ba_rx_bitmap
=
0
;
wl
->
ba_allowed
=
true
;
wlvif
->
ba_allowed
=
true
;
wl
->
ba_rx_session_count
=
0
;
/* BA is supported in STA/AP modes */
if
(
wl
->
bss_type
!=
BSS_TYPE_AP_BSS
&&
wl
->
bss_type
!=
BSS_TYPE_STA_BSS
)
{
wl
->
ba_support
=
false
;
if
(
wl
vif
->
bss_type
!=
BSS_TYPE_AP_BSS
&&
wl
vif
->
bss_type
!=
BSS_TYPE_STA_BSS
)
{
wl
vif
->
ba_support
=
false
;
return
0
;
}
wl
->
ba_support
=
true
;
wl
vif
->
ba_support
=
true
;
/* 802.11n initiator BA session setting */
return
wl12xx_acx_set_ba_initiator_policy
(
wl
);
return
wl12xx_acx_set_ba_initiator_policy
(
wl
,
wlvif
);
}
int
wl1271_chip_specific_init
(
struct
wl1271
*
wl
)
...
...
@@ -562,7 +501,7 @@ int wl1271_chip_specific_init(struct wl1271 *wl)
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
{
u32
host_cfg_bitmap
=
HOST_IF_CFG_RX_FIFO_ENABLE
;
if
(
wl
->
quirks
&
WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT
)
if
(
!
(
wl
->
quirks
&
WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT
)
)
/* Enable SDIO padding */
host_cfg_bitmap
|=
HOST_IF_CFG_TX_PAD_TO_SDIO_BLK
;
...
...
@@ -575,13 +514,150 @@ int wl1271_chip_specific_init(struct wl1271 *wl)
return
ret
;
}
/* vif-specifc initialization */
static
int
wl12xx_init_sta_role
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
int
ret
;
int
wl1271_hw_init
(
struct
wl1271
*
wl
)
ret
=
wl1271_acx_group_address_tbl
(
wl
,
wlvif
,
true
,
NULL
,
0
);
if
(
ret
<
0
)
return
ret
;
/* Initialize connection monitoring thresholds */
ret
=
wl1271_acx_conn_monit_params
(
wl
,
wlvif
,
false
);
if
(
ret
<
0
)
return
ret
;
/* Beacon filtering */
ret
=
wl1271_init_sta_beacon_filter
(
wl
,
wlvif
);
if
(
ret
<
0
)
return
ret
;
/* Beacons and broadcast settings */
ret
=
wl1271_init_beacon_broadcast
(
wl
,
wlvif
);
if
(
ret
<
0
)
return
ret
;
/* Configure rssi/snr averaging weights */
ret
=
wl1271_acx_rssi_snr_avg_weights
(
wl
,
wlvif
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
/* vif-specific intialization */
static
int
wl12xx_init_ap_role
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
int
ret
;
ret
=
wl1271_acx_ap_max_tx_retry
(
wl
,
wlvif
);
if
(
ret
<
0
)
return
ret
;
/* initialize Tx power */
ret
=
wl1271_acx_tx_power
(
wl
,
wlvif
,
wlvif
->
power_level
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
int
wl1271_init_vif_specific
(
struct
wl1271
*
wl
,
struct
ieee80211_vif
*
vif
)
{
struct
wl12xx_vif
*
wlvif
=
wl12xx_vif_to_data
(
vif
);
struct
conf_tx_ac_category
*
conf_ac
;
struct
conf_tx_tid
*
conf_tid
;
bool
is_ap
=
(
wlvif
->
bss_type
==
BSS_TYPE_AP_BSS
);
int
ret
,
i
;
bool
is_ap
=
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
);
/*
* consider all existing roles before configuring psm.
* TODO: reconfigure on interface removal.
*/
if
(
!
wl
->
ap_count
)
{
if
(
is_ap
)
{
/* Configure for power always on */
ret
=
wl1271_acx_sleep_auth
(
wl
,
WL1271_PSM_CAM
);
if
(
ret
<
0
)
return
ret
;
}
else
if
(
!
wl
->
sta_count
)
{
/* Configure for ELP power saving */
ret
=
wl1271_acx_sleep_auth
(
wl
,
WL1271_PSM_ELP
);
if
(
ret
<
0
)
return
ret
;
}
}
/* Mode specific init */
if
(
is_ap
)
{
ret
=
wl1271_ap_hw_init
(
wl
,
wlvif
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl12xx_init_ap_role
(
wl
,
wlvif
);
if
(
ret
<
0
)
return
ret
;
}
else
{
ret
=
wl1271_sta_hw_init
(
wl
,
wlvif
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl12xx_init_sta_role
(
wl
,
wlvif
);
if
(
ret
<
0
)
return
ret
;
}
wl12xx_init_phy_vif_config
(
wl
,
wlvif
);
/* Default TID/AC configuration */
BUG_ON
(
wl
->
conf
.
tx
.
tid_conf_count
!=
wl
->
conf
.
tx
.
ac_conf_count
);
for
(
i
=
0
;
i
<
wl
->
conf
.
tx
.
tid_conf_count
;
i
++
)
{
conf_ac
=
&
wl
->
conf
.
tx
.
ac_conf
[
i
];
ret
=
wl1271_acx_ac_cfg
(
wl
,
wlvif
,
conf_ac
->
ac
,
conf_ac
->
cw_min
,
conf_ac
->
cw_max
,
conf_ac
->
aifsn
,
conf_ac
->
tx_op_limit
);
if
(
ret
<
0
)
return
ret
;
conf_tid
=
&
wl
->
conf
.
tx
.
tid_conf
[
i
];
ret
=
wl1271_acx_tid_cfg
(
wl
,
wlvif
,
conf_tid
->
queue_id
,
conf_tid
->
channel_type
,
conf_tid
->
tsid
,
conf_tid
->
ps_scheme
,
conf_tid
->
ack_policy
,
conf_tid
->
apsd_conf
[
0
],
conf_tid
->
apsd_conf
[
1
]);
if
(
ret
<
0
)
return
ret
;
}
/* Configure HW encryption */
ret
=
wl1271_acx_feature_cfg
(
wl
,
wlvif
);
if
(
ret
<
0
)
return
ret
;
/* Mode specific init - post mem init */
if
(
is_ap
)
ret
=
wl1271_ap_hw_init_post_mem
(
wl
,
vif
);
else
ret
=
wl1271_sta_hw_init_post_mem
(
wl
,
vif
);
if
(
ret
<
0
)
return
ret
;
/* Configure initiator BA sessions policies */
ret
=
wl1271_set_ba_policies
(
wl
,
wlvif
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
int
wl1271_hw_init
(
struct
wl1271
*
wl
)
{
int
ret
;
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
ret
=
wl128x_cmd_general_parms
(
wl
);
...
...
@@ -602,12 +678,17 @@ int wl1271_hw_init(struct wl1271 *wl)
if
(
ret
<
0
)
return
ret
;
/* Mode specific init */
if
(
is_ap
)
ret
=
wl1271_ap_hw_init
(
wl
);
else
ret
=
wl1271_sta_hw_init
(
wl
);
/* Init templates */
ret
=
wl1271_init_templates_config
(
wl
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl12xx_acx_mem_cfg
(
wl
);
if
(
ret
<
0
)
return
ret
;
/* Configure the FW logger */
ret
=
wl12xx_init_fwlog
(
wl
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -655,61 +736,20 @@ int wl1271_hw_init(struct wl1271 *wl)
if
(
ret
<
0
)
goto
out_free_memmap
;
/* Default TID/AC configuration */
BUG_ON
(
wl
->
conf
.
tx
.
tid_conf_count
!=
wl
->
conf
.
tx
.
ac_conf_count
);
for
(
i
=
0
;
i
<
wl
->
conf
.
tx
.
tid_conf_count
;
i
++
)
{
conf_ac
=
&
wl
->
conf
.
tx
.
ac_conf
[
i
];
ret
=
wl1271_acx_ac_cfg
(
wl
,
conf_ac
->
ac
,
conf_ac
->
cw_min
,
conf_ac
->
cw_max
,
conf_ac
->
aifsn
,
conf_ac
->
tx_op_limit
);
if
(
ret
<
0
)
goto
out_free_memmap
;
conf_tid
=
&
wl
->
conf
.
tx
.
tid_conf
[
i
];
ret
=
wl1271_acx_tid_cfg
(
wl
,
conf_tid
->
queue_id
,
conf_tid
->
channel_type
,
conf_tid
->
tsid
,
conf_tid
->
ps_scheme
,
conf_tid
->
ack_policy
,
conf_tid
->
apsd_conf
[
0
],
conf_tid
->
apsd_conf
[
1
]);
if
(
ret
<
0
)
goto
out_free_memmap
;
}
/* Enable data path */
ret
=
wl1271_cmd_data_path
(
wl
,
1
);
if
(
ret
<
0
)
goto
out_free_memmap
;
/* Configure HW encryption */
ret
=
wl1271_acx_feature_cfg
(
wl
);
if
(
ret
<
0
)
goto
out_free_memmap
;
/* configure PM */
ret
=
wl1271_acx_pm_config
(
wl
);
if
(
ret
<
0
)
goto
out_free_memmap
;
/* Mode specific init - post mem init */
if
(
is_ap
)
ret
=
wl1271_ap_hw_init_post_mem
(
wl
);
else
ret
=
wl1271_sta_hw_init_post_mem
(
wl
);
if
(
ret
<
0
)
goto
out_free_memmap
;
ret
=
wl12xx_acx_set_rate_mgmt_params
(
wl
);
if
(
ret
<
0
)
goto
out_free_memmap
;
/* Configure initiator BA sessions policies */
ret
=
wl1271_set_ba_policies
(
wl
);
if
(
ret
<
0
)
goto
out_free_memmap
;
/* configure hangover */
ret
=
wl12xx_acx_config_hangover
(
wl
);
if
(
ret
<
0
)
...
...
drivers/net/wireless/wl12xx/init.h
View file @
f589cf4f
...
...
@@ -27,13 +27,14 @@
#include "wl12xx.h"
int
wl1271_hw_init_power_auth
(
struct
wl1271
*
wl
);
int
wl1271_
sta_
init_templates_config
(
struct
wl1271
*
wl
);
int
wl1271_init_templates_config
(
struct
wl1271
*
wl
);
int
wl1271_init_phy_config
(
struct
wl1271
*
wl
);
int
wl1271_init_pta
(
struct
wl1271
*
wl
);
int
wl1271_init_energy_detection
(
struct
wl1271
*
wl
);
int
wl1271_chip_specific_init
(
struct
wl1271
*
wl
);
int
wl1271_hw_init
(
struct
wl1271
*
wl
);
int
wl1271_init_ap_rates
(
struct
wl1271
*
wl
);
int
wl1271_ap_init_templates
(
struct
wl1271
*
wl
);
int
wl1271_init_vif_specific
(
struct
wl1271
*
wl
,
struct
ieee80211_vif
*
vif
);
int
wl1271_init_ap_rates
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl1271_ap_init_templates
(
struct
wl1271
*
wl
,
struct
ieee80211_vif
*
vif
);
#endif
drivers/net/wireless/wl12xx/io.c
View file @
f589cf4f
...
...
@@ -24,8 +24,10 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/interrupt.h>
#include "wl12xx.h"
#include "debug.h"
#include "wl12xx_80211.h"
#include "io.h"
#include "tx.h"
...
...
@@ -46,7 +48,7 @@
bool
wl1271_set_block_size
(
struct
wl1271
*
wl
)
{
if
(
wl
->
if_ops
->
set_block_size
)
{
wl
->
if_ops
->
set_block_size
(
wl
,
WL12XX_BUS_BLOCK_SIZE
);
wl
->
if_ops
->
set_block_size
(
wl
->
dev
,
WL12XX_BUS_BLOCK_SIZE
);
return
true
;
}
...
...
@@ -55,12 +57,12 @@ bool wl1271_set_block_size(struct wl1271 *wl)
void
wl1271_disable_interrupts
(
struct
wl1271
*
wl
)
{
wl
->
if_ops
->
disable_irq
(
wl
);
disable_irq
(
wl
->
irq
);
}
void
wl1271_enable_interrupts
(
struct
wl1271
*
wl
)
{
wl
->
if_ops
->
enable_irq
(
wl
);
enable_irq
(
wl
->
irq
);
}
/* Set the SPI partitions to access the chip addresses
...
...
@@ -128,13 +130,13 @@ EXPORT_SYMBOL_GPL(wl1271_set_partition);
void
wl1271_io_reset
(
struct
wl1271
*
wl
)
{
if
(
wl
->
if_ops
->
reset
)
wl
->
if_ops
->
reset
(
wl
);
wl
->
if_ops
->
reset
(
wl
->
dev
);
}
void
wl1271_io_init
(
struct
wl1271
*
wl
)
{
if
(
wl
->
if_ops
->
init
)
wl
->
if_ops
->
init
(
wl
);
wl
->
if_ops
->
init
(
wl
->
dev
);
}
void
wl1271_top_reg_write
(
struct
wl1271
*
wl
,
int
addr
,
u16
val
)
...
...
drivers/net/wireless/wl12xx/io.h
View file @
f589cf4f
...
...
@@ -51,23 +51,17 @@ void wl1271_enable_interrupts(struct wl1271 *wl);
void
wl1271_io_reset
(
struct
wl1271
*
wl
);
void
wl1271_io_init
(
struct
wl1271
*
wl
);
static
inline
struct
device
*
wl1271_wl_to_dev
(
struct
wl1271
*
wl
)
{
return
wl
->
if_ops
->
dev
(
wl
);
}
/* Raw target IO, address is not translated */
static
inline
void
wl1271_raw_write
(
struct
wl1271
*
wl
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
wl
->
if_ops
->
write
(
wl
,
addr
,
buf
,
len
,
fixed
);
wl
->
if_ops
->
write
(
wl
->
dev
,
addr
,
buf
,
len
,
fixed
);
}
static
inline
void
wl1271_raw_read
(
struct
wl1271
*
wl
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
wl
->
if_ops
->
read
(
wl
,
addr
,
buf
,
len
,
fixed
);
wl
->
if_ops
->
read
(
wl
->
dev
,
addr
,
buf
,
len
,
fixed
);
}
static
inline
u32
wl1271_raw_read32
(
struct
wl1271
*
wl
,
int
addr
)
...
...
@@ -155,13 +149,13 @@ static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val)
static
inline
void
wl1271_power_off
(
struct
wl1271
*
wl
)
{
wl
->
if_ops
->
power
(
wl
,
false
);
wl
->
if_ops
->
power
(
wl
->
dev
,
false
);
clear_bit
(
WL1271_FLAG_GPIO_POWER
,
&
wl
->
flags
);
}
static
inline
int
wl1271_power_on
(
struct
wl1271
*
wl
)
{
int
ret
=
wl
->
if_ops
->
power
(
wl
,
true
);
int
ret
=
wl
->
if_ops
->
power
(
wl
->
dev
,
true
);
if
(
ret
==
0
)
set_bit
(
WL1271_FLAG_GPIO_POWER
,
&
wl
->
flags
);
...
...
@@ -176,15 +170,10 @@ u16 wl1271_top_reg_read(struct wl1271 *wl, int addr);
int
wl1271_set_partition
(
struct
wl1271
*
wl
,
struct
wl1271_partition_set
*
p
);
bool
wl1271_set_block_size
(
struct
wl1271
*
wl
);
/* Functions from wl1271_main.c */
int
wl1271_register_hw
(
struct
wl1271
*
wl
);
void
wl1271_unregister_hw
(
struct
wl1271
*
wl
);
int
wl1271_init_ieee80211
(
struct
wl1271
*
wl
);
struct
ieee80211_hw
*
wl1271_alloc_hw
(
void
);
int
wl1271_free_hw
(
struct
wl1271
*
wl
);
irqreturn_t
wl1271_irq
(
int
irq
,
void
*
data
);
bool
wl1271_set_block_size
(
struct
wl1271
*
wl
);
int
wl1271_tx_dummy_packet
(
struct
wl1271
*
wl
);
#endif
drivers/net/wireless/wl12xx/main.c
View file @
f589cf4f
This source diff could not be displayed because it is too large. You can
view the blob
instead.
drivers/net/wireless/wl12xx/ps.c
View file @
f589cf4f
...
...
@@ -25,6 +25,7 @@
#include "ps.h"
#include "io.h"
#include "tx.h"
#include "debug.h"
#define WL1271_WAKEUP_TIMEOUT 500
...
...
@@ -32,6 +33,7 @@ void wl1271_elp_work(struct work_struct *work)
{
struct
delayed_work
*
dwork
;
struct
wl1271
*
wl
;
struct
wl12xx_vif
*
wlvif
;
dwork
=
container_of
(
work
,
struct
delayed_work
,
work
);
wl
=
container_of
(
dwork
,
struct
wl1271
,
elp_work
);
...
...
@@ -47,11 +49,15 @@ void wl1271_elp_work(struct work_struct *work)
if
(
unlikely
(
!
test_bit
(
WL1271_FLAG_ELP_REQUESTED
,
&
wl
->
flags
)))
goto
out
;
if
(
test_bit
(
WL1271_FLAG_IN_ELP
,
&
wl
->
flags
)
||
(
!
test_bit
(
WL1271_FLAG_PSM
,
&
wl
->
flags
)
&&
!
test_bit
(
WL1271_FLAG_IDLE
,
&
wl
->
flags
)))
if
(
test_bit
(
WL1271_FLAG_IN_ELP
,
&
wl
->
flags
))
goto
out
;
wl12xx_for_each_wlvif
(
wl
,
wlvif
)
{
if
(
!
test_bit
(
WLVIF_FLAG_PSM
,
&
wlvif
->
flags
)
&&
!
test_bit
(
WL1271_FLAG_IDLE
,
&
wl
->
flags
))
goto
out
;
}
wl1271_debug
(
DEBUG_PSM
,
"chip to elp"
);
wl1271_raw_write32
(
wl
,
HW_ACCESS_ELP_CTRL_REG_ADDR
,
ELPCTRL_SLEEP
);
set_bit
(
WL1271_FLAG_IN_ELP
,
&
wl
->
flags
);
...
...
@@ -65,13 +71,17 @@ void wl1271_elp_work(struct work_struct *work)
/* Routines to toggle sleep mode while in ELP */
void
wl1271_ps_elp_sleep
(
struct
wl1271
*
wl
)
{
struct
wl12xx_vif
*
wlvif
;
/* we shouldn't get consecutive sleep requests */
if
(
WARN_ON
(
test_and_set_bit
(
WL1271_FLAG_ELP_REQUESTED
,
&
wl
->
flags
)))
return
;
if
(
!
test_bit
(
WL1271_FLAG_PSM
,
&
wl
->
flags
)
&&
!
test_bit
(
WL1271_FLAG_IDLE
,
&
wl
->
flags
))
return
;
wl12xx_for_each_wlvif
(
wl
,
wlvif
)
{
if
(
!
test_bit
(
WLVIF_FLAG_PSM
,
&
wlvif
->
flags
)
&&
!
test_bit
(
WL1271_FLAG_IDLE
,
&
wl
->
flags
))
return
;
}
ieee80211_queue_delayed_work
(
wl
->
hw
,
&
wl
->
elp_work
,
msecs_to_jiffies
(
ELP_ENTRY_DELAY
));
...
...
@@ -143,8 +153,8 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)
return
0
;
}
int
wl1271_ps_set_mode
(
struct
wl1271
*
wl
,
enum
wl1271_cmd_ps_mode
mode
,
u32
rates
,
bool
send
)
int
wl1271_ps_set_mode
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
enum
wl1271_cmd_ps_mode
mode
,
u32
rates
,
bool
send
)
{
int
ret
;
...
...
@@ -152,39 +162,34 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
case
STATION_POWER_SAVE_MODE
:
wl1271_debug
(
DEBUG_PSM
,
"entering psm"
);
ret
=
wl1271_acx_wake_up_conditions
(
wl
);
ret
=
wl1271_acx_wake_up_conditions
(
wl
,
wlvif
);
if
(
ret
<
0
)
{
wl1271_error
(
"couldn't set wake up conditions"
);
return
ret
;
}
ret
=
wl1271_cmd_ps_mode
(
wl
,
STATION_POWER_SAVE_MODE
);
ret
=
wl1271_cmd_ps_mode
(
wl
,
wlvif
,
STATION_POWER_SAVE_MODE
);
if
(
ret
<
0
)
return
ret
;
set_bit
(
WL
1271_FLAG_PSM
,
&
wl
->
flags
);
set_bit
(
WL
VIF_FLAG_PSM
,
&
wlvif
->
flags
);
break
;
case
STATION_ACTIVE_MODE
:
default:
wl1271_debug
(
DEBUG_PSM
,
"leaving psm"
);
/* disable beacon early termination */
if
(
wl
->
band
==
IEEE80211_BAND_2GHZ
)
{
ret
=
wl1271_acx_bet_enable
(
wl
,
false
);
if
(
wl
vif
->
band
==
IEEE80211_BAND_2GHZ
)
{
ret
=
wl1271_acx_bet_enable
(
wl
,
wlvif
,
false
);
if
(
ret
<
0
)
return
ret
;
}
/* disable beacon filtering */
ret
=
wl1271_acx_beacon_filter_opt
(
wl
,
false
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_cmd_ps_mode
(
wl
,
STATION_ACTIVE_MODE
);
ret
=
wl1271_cmd_ps_mode
(
wl
,
wlvif
,
STATION_ACTIVE_MODE
);
if
(
ret
<
0
)
return
ret
;
clear_bit
(
WL
1271_FLAG_PSM
,
&
wl
->
flags
);
clear_bit
(
WL
VIF_FLAG_PSM
,
&
wlvif
->
flags
);
break
;
}
...
...
@@ -223,9 +228,11 @@ static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid)
wl1271_handle_tx_low_watermark
(
wl
);
}
void
wl1271_ps_link_start
(
struct
wl1271
*
wl
,
u8
hlid
,
bool
clean_queues
)
void
wl12xx_ps_link_start
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
hlid
,
bool
clean_queues
)
{
struct
ieee80211_sta
*
sta
;
struct
ieee80211_vif
*
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
if
(
test_bit
(
hlid
,
&
wl
->
ap_ps_map
))
return
;
...
...
@@ -235,7 +242,7 @@ void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues)
clean_queues
);
rcu_read_lock
();
sta
=
ieee80211_find_sta
(
wl
->
vif
,
wl
->
links
[
hlid
].
addr
);
sta
=
ieee80211_find_sta
(
vif
,
wl
->
links
[
hlid
].
addr
);
if
(
!
sta
)
{
wl1271_error
(
"could not find sta %pM for starting ps"
,
wl
->
links
[
hlid
].
addr
);
...
...
@@ -253,9 +260,10 @@ void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues)
__set_bit
(
hlid
,
&
wl
->
ap_ps_map
);
}
void
wl12
71_ps_link_end
(
struct
wl1271
*
wl
,
u8
hlid
)
void
wl12
xx_ps_link_end
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
hlid
)
{
struct
ieee80211_sta
*
sta
;
struct
ieee80211_vif
*
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
if
(
!
test_bit
(
hlid
,
&
wl
->
ap_ps_map
))
return
;
...
...
@@ -265,7 +273,7 @@ void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid)
__clear_bit
(
hlid
,
&
wl
->
ap_ps_map
);
rcu_read_lock
();
sta
=
ieee80211_find_sta
(
wl
->
vif
,
wl
->
links
[
hlid
].
addr
);
sta
=
ieee80211_find_sta
(
vif
,
wl
->
links
[
hlid
].
addr
);
if
(
!
sta
)
{
wl1271_error
(
"could not find sta %pM for ending ps"
,
wl
->
links
[
hlid
].
addr
);
...
...
drivers/net/wireless/wl12xx/ps.h
View file @
f589cf4f
...
...
@@ -27,13 +27,14 @@
#include "wl12xx.h"
#include "acx.h"
int
wl1271_ps_set_mode
(
struct
wl1271
*
wl
,
enum
wl1271_cmd_ps_mode
mode
,
u32
rates
,
bool
send
);
int
wl1271_ps_set_mode
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
enum
wl1271_cmd_ps_mode
mode
,
u32
rates
,
bool
send
);
void
wl1271_ps_elp_sleep
(
struct
wl1271
*
wl
);
int
wl1271_ps_elp_wakeup
(
struct
wl1271
*
wl
);
void
wl1271_elp_work
(
struct
work_struct
*
work
);
void
wl1271_ps_link_start
(
struct
wl1271
*
wl
,
u8
hlid
,
bool
clean_queues
);
void
wl1271_ps_link_end
(
struct
wl1271
*
wl
,
u8
hlid
);
void
wl12xx_ps_link_start
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
hlid
,
bool
clean_queues
);
void
wl12xx_ps_link_end
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
hlid
);
#define WL1271_PS_COMPLETE_TIMEOUT 500
...
...
drivers/net/wireless/wl12xx/reg.h
View file @
f589cf4f
...
...
@@ -408,7 +408,7 @@
/* Firmware image load chunk size */
#define CHUNK_SIZE
512
#define CHUNK_SIZE
16384
/* Firmware image header size */
#define FW_HDR_SIZE 8
...
...
drivers/net/wireless/wl12xx/rx.c
View file @
f589cf4f
...
...
@@ -25,9 +25,11 @@
#include <linux/sched.h>
#include "wl12xx.h"
#include "debug.h"
#include "acx.h"
#include "reg.h"
#include "rx.h"
#include "tx.h"
#include "io.h"
static
u8
wl12xx_rx_get_mem_block
(
struct
wl12xx_fw_status
*
status
,
...
...
@@ -96,7 +98,7 @@ static void wl1271_rx_status(struct wl1271 *wl,
}
static
int
wl1271_rx_handle_data
(
struct
wl1271
*
wl
,
u8
*
data
,
u32
length
,
bool
unaligned
)
bool
unaligned
,
u8
*
hlid
)
{
struct
wl1271_rx_descriptor
*
desc
;
struct
sk_buff
*
skb
;
...
...
@@ -159,6 +161,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
* payload aligned to 4 bytes.
*/
memcpy
(
buf
,
data
+
sizeof
(
*
desc
),
length
-
sizeof
(
*
desc
));
*
hlid
=
desc
->
hlid
;
hdr
=
(
struct
ieee80211_hdr
*
)
skb
->
data
;
if
(
ieee80211_is_beacon
(
hdr
->
frame_control
))
...
...
@@ -169,10 +172,10 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
wl1271_rx_status
(
wl
,
desc
,
IEEE80211_SKB_RXCB
(
skb
),
beacon
);
seq_num
=
(
le16_to_cpu
(
hdr
->
seq_ctrl
)
&
IEEE80211_SCTL_SEQ
)
>>
4
;
wl1271_debug
(
DEBUG_RX
,
"rx skb 0x%p: %d B %s seq %d"
,
skb
,
wl1271_debug
(
DEBUG_RX
,
"rx skb 0x%p: %d B %s seq %d
hlid %d
"
,
skb
,
skb
->
len
-
desc
->
pad_len
,
beacon
?
"beacon"
:
""
,
seq_num
);
seq_num
,
*
hlid
);
skb_trim
(
skb
,
skb
->
len
-
desc
->
pad_len
);
...
...
@@ -185,6 +188,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
void
wl12xx_rx
(
struct
wl1271
*
wl
,
struct
wl12xx_fw_status
*
status
)
{
struct
wl1271_acx_mem_map
*
wl_mem_map
=
wl
->
target_mem_map
;
unsigned
long
active_hlids
[
BITS_TO_LONGS
(
WL12XX_MAX_LINKS
)]
=
{
0
};
u32
buf_size
;
u32
fw_rx_counter
=
status
->
fw_rx_counter
&
NUM_RX_PKT_DESC_MOD_MASK
;
u32
drv_rx_counter
=
wl
->
rx_counter
&
NUM_RX_PKT_DESC_MOD_MASK
;
...
...
@@ -192,8 +196,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
u32
mem_block
;
u32
pkt_length
;
u32
pkt_offset
;
bool
is_ap
=
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
);
bool
had_data
=
false
;
u8
hlid
;
bool
unaligned
=
false
;
while
(
drv_rx_counter
!=
fw_rx_counter
)
{
...
...
@@ -253,8 +256,11 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
*/
if
(
wl1271_rx_handle_data
(
wl
,
wl
->
aggr_buf
+
pkt_offset
,
pkt_length
,
unaligned
)
==
1
)
had_data
=
true
;
pkt_length
,
unaligned
,
&
hlid
)
==
1
)
{
WARN_ON
(
hlid
>=
WL12XX_MAX_LINKS
);
__set_bit
(
hlid
,
active_hlids
);
}
wl
->
rx_counter
++
;
drv_rx_counter
++
;
...
...
@@ -270,17 +276,5 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
if
(
wl
->
quirks
&
WL12XX_QUIRK_END_OF_TRANSACTION
)
wl1271_write32
(
wl
,
RX_DRIVER_COUNTER_ADDRESS
,
wl
->
rx_counter
);
if
(
!
is_ap
&&
wl
->
conf
.
rx_streaming
.
interval
&&
had_data
&&
(
wl
->
conf
.
rx_streaming
.
always
||
test_bit
(
WL1271_FLAG_SOFT_GEMINI
,
&
wl
->
flags
)))
{
u32
timeout
=
wl
->
conf
.
rx_streaming
.
duration
;
/* restart rx streaming */
if
(
!
test_bit
(
WL1271_FLAG_RX_STREAMING_STARTED
,
&
wl
->
flags
))
ieee80211_queue_work
(
wl
->
hw
,
&
wl
->
rx_streaming_enable_work
);
mod_timer
(
&
wl
->
rx_streaming_timer
,
jiffies
+
msecs_to_jiffies
(
timeout
));
}
wl12xx_rearm_rx_streaming
(
wl
,
active_hlids
);
}
drivers/net/wireless/wl12xx/scan.c
View file @
f589cf4f
...
...
@@ -24,6 +24,7 @@
#include <linux/ieee80211.h>
#include "wl12xx.h"
#include "debug.h"
#include "cmd.h"
#include "scan.h"
#include "acx.h"
...
...
@@ -34,6 +35,8 @@ void wl1271_scan_complete_work(struct work_struct *work)
{
struct
delayed_work
*
dwork
;
struct
wl1271
*
wl
;
struct
ieee80211_vif
*
vif
;
struct
wl12xx_vif
*
wlvif
;
int
ret
;
bool
is_sta
,
is_ibss
;
...
...
@@ -50,28 +53,31 @@ void wl1271_scan_complete_work(struct work_struct *work)
if
(
wl
->
scan
.
state
==
WL1271_SCAN_STATE_IDLE
)
goto
out
;
vif
=
wl
->
scan_vif
;
wlvif
=
wl12xx_vif_to_data
(
vif
);
wl
->
scan
.
state
=
WL1271_SCAN_STATE_IDLE
;
memset
(
wl
->
scan
.
scanned_ch
,
0
,
sizeof
(
wl
->
scan
.
scanned_ch
));
wl
->
scan
.
req
=
NULL
;
wl
->
scan_vif
=
NULL
;
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out
;
if
(
test_bit
(
WL
1271_FLAG_STA_ASSOCIATED
,
&
wl
->
flags
))
{
if
(
test_bit
(
WL
VIF_FLAG_STA_ASSOCIATED
,
&
wlvif
->
flags
))
{
/* restore hardware connection monitoring template */
wl1271_cmd_build_ap_probe_req
(
wl
,
wl
->
probereq
);
wl1271_cmd_build_ap_probe_req
(
wl
,
wl
vif
,
wlvif
->
probereq
);
}
/* return to ROC if needed */
is_sta
=
(
wl
->
bss_type
==
BSS_TYPE_STA_BSS
);
is_ibss
=
(
wl
->
bss_type
==
BSS_TYPE_IBSS
);
if
(((
is_sta
&&
!
test_bit
(
WL
1271_FLAG_STA_ASSOCIATED
,
&
wl
->
flags
))
||
(
is_ibss
&&
!
test_bit
(
WL
1271_FLAG_IBSS_JOINED
,
&
wl
->
flags
)))
&&
!
test_bit
(
wl
->
dev_role_id
,
wl
->
roc_map
))
{
is_sta
=
(
wl
vif
->
bss_type
==
BSS_TYPE_STA_BSS
);
is_ibss
=
(
wl
vif
->
bss_type
==
BSS_TYPE_IBSS
);
if
(((
is_sta
&&
!
test_bit
(
WL
VIF_FLAG_STA_ASSOCIATED
,
&
wlvif
->
flags
))
||
(
is_ibss
&&
!
test_bit
(
WL
VIF_FLAG_IBSS_JOINED
,
&
wlvif
->
flags
)))
&&
!
test_bit
(
wl
vif
->
dev_role_id
,
wl
->
roc_map
))
{
/* restore remain on channel */
wl12xx_cmd_role_start_dev
(
wl
);
wl12xx_roc
(
wl
,
wl
->
dev_role_id
);
wl12xx_start_dev
(
wl
,
wlvif
);
}
wl1271_ps_elp_sleep
(
wl
);
...
...
@@ -155,9 +161,11 @@ static int wl1271_get_scan_channels(struct wl1271 *wl,
#define WL1271_NOTHING_TO_SCAN 1
static
int
wl1271_scan_send
(
struct
wl1271
*
wl
,
enum
ieee80211_band
band
,
bool
passive
,
u32
basic_rate
)
static
int
wl1271_scan_send
(
struct
wl1271
*
wl
,
struct
ieee80211_vif
*
vif
,
enum
ieee80211_band
band
,
bool
passive
,
u32
basic_rate
)
{
struct
wl12xx_vif
*
wlvif
=
wl12xx_vif_to_data
(
vif
);
struct
wl1271_cmd_scan
*
cmd
;
struct
wl1271_cmd_trigger_scan_to
*
trigger
;
int
ret
;
...
...
@@ -177,11 +185,11 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
if
(
passive
)
scan_options
|=
WL1271_SCAN_OPT_PASSIVE
;
if
(
WARN_ON
(
wl
->
role_id
==
WL12XX_INVALID_ROLE_ID
))
{
if
(
WARN_ON
(
wl
vif
->
role_id
==
WL12XX_INVALID_ROLE_ID
))
{
ret
=
-
EINVAL
;
goto
out
;
}
cmd
->
params
.
role_id
=
wl
->
role_id
;
cmd
->
params
.
role_id
=
wl
vif
->
role_id
;
cmd
->
params
.
scan_options
=
cpu_to_le16
(
scan_options
);
cmd
->
params
.
n_ch
=
wl1271_get_scan_channels
(
wl
,
wl
->
scan
.
req
,
...
...
@@ -194,7 +202,6 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
cmd
->
params
.
tx_rate
=
cpu_to_le32
(
basic_rate
);
cmd
->
params
.
n_probe_reqs
=
wl
->
conf
.
scan
.
num_probe_reqs
;
cmd
->
params
.
tx_rate
=
cpu_to_le32
(
basic_rate
);
cmd
->
params
.
tid_trigger
=
0
;
cmd
->
params
.
scan_tag
=
WL1271_SCAN_DEFAULT_TAG
;
...
...
@@ -208,11 +215,11 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
memcpy
(
cmd
->
params
.
ssid
,
wl
->
scan
.
ssid
,
wl
->
scan
.
ssid_len
);
}
memcpy
(
cmd
->
addr
,
wl
->
mac_
addr
,
ETH_ALEN
);
memcpy
(
cmd
->
addr
,
vif
->
addr
,
ETH_ALEN
);
ret
=
wl1271_cmd_build_probe_req
(
wl
,
wl
->
scan
.
ssid
,
wl
->
scan
.
ssid_len
,
wl
->
scan
.
req
->
ie
,
wl
->
scan
.
req
->
ie_len
,
band
);
ret
=
wl1271_cmd_build_probe_req
(
wl
,
wl
vif
,
wl
->
scan
.
ssid
,
wl
->
scan
.
ssid_len
,
wl
->
scan
.
req
->
ie
,
wl
->
scan
.
req
->
ie_len
,
band
);
if
(
ret
<
0
)
{
wl1271_error
(
"PROBE request template failed"
);
goto
out
;
...
...
@@ -241,11 +248,12 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
return
ret
;
}
void
wl1271_scan_stm
(
struct
wl1271
*
wl
)
void
wl1271_scan_stm
(
struct
wl1271
*
wl
,
struct
ieee80211_vif
*
vif
)
{
struct
wl12xx_vif
*
wlvif
=
wl12xx_vif_to_data
(
vif
);
int
ret
=
0
;
enum
ieee80211_band
band
;
u32
rate
;
u32
rate
,
mask
;
switch
(
wl
->
scan
.
state
)
{
case
WL1271_SCAN_STATE_IDLE
:
...
...
@@ -253,47 +261,59 @@ void wl1271_scan_stm(struct wl1271 *wl)
case
WL1271_SCAN_STATE_2GHZ_ACTIVE
:
band
=
IEEE80211_BAND_2GHZ
;
rate
=
wl1271_tx_min_rate_get
(
wl
,
wl
->
bitrate_masks
[
band
]);
ret
=
wl1271_scan_send
(
wl
,
band
,
false
,
rate
);
mask
=
wlvif
->
bitrate_masks
[
band
];
if
(
wl
->
scan
.
req
->
no_cck
)
{
mask
&=
~
CONF_TX_CCK_RATES
;
if
(
!
mask
)
mask
=
CONF_TX_RATE_MASK_BASIC_P2P
;
}
rate
=
wl1271_tx_min_rate_get
(
wl
,
mask
);
ret
=
wl1271_scan_send
(
wl
,
vif
,
band
,
false
,
rate
);
if
(
ret
==
WL1271_NOTHING_TO_SCAN
)
{
wl
->
scan
.
state
=
WL1271_SCAN_STATE_2GHZ_PASSIVE
;
wl1271_scan_stm
(
wl
);
wl1271_scan_stm
(
wl
,
vif
);
}
break
;
case
WL1271_SCAN_STATE_2GHZ_PASSIVE
:
band
=
IEEE80211_BAND_2GHZ
;
rate
=
wl1271_tx_min_rate_get
(
wl
,
wl
->
bitrate_masks
[
band
]);
ret
=
wl1271_scan_send
(
wl
,
band
,
true
,
rate
);
mask
=
wlvif
->
bitrate_masks
[
band
];
if
(
wl
->
scan
.
req
->
no_cck
)
{
mask
&=
~
CONF_TX_CCK_RATES
;
if
(
!
mask
)
mask
=
CONF_TX_RATE_MASK_BASIC_P2P
;
}
rate
=
wl1271_tx_min_rate_get
(
wl
,
mask
);
ret
=
wl1271_scan_send
(
wl
,
vif
,
band
,
true
,
rate
);
if
(
ret
==
WL1271_NOTHING_TO_SCAN
)
{
if
(
wl
->
enable_11a
)
wl
->
scan
.
state
=
WL1271_SCAN_STATE_5GHZ_ACTIVE
;
else
wl
->
scan
.
state
=
WL1271_SCAN_STATE_DONE
;
wl1271_scan_stm
(
wl
);
wl1271_scan_stm
(
wl
,
vif
);
}
break
;
case
WL1271_SCAN_STATE_5GHZ_ACTIVE
:
band
=
IEEE80211_BAND_5GHZ
;
rate
=
wl1271_tx_min_rate_get
(
wl
,
wl
->
bitrate_masks
[
band
]);
ret
=
wl1271_scan_send
(
wl
,
band
,
false
,
rate
);
rate
=
wl1271_tx_min_rate_get
(
wl
,
wl
vif
->
bitrate_masks
[
band
]);
ret
=
wl1271_scan_send
(
wl
,
vif
,
band
,
false
,
rate
);
if
(
ret
==
WL1271_NOTHING_TO_SCAN
)
{
wl
->
scan
.
state
=
WL1271_SCAN_STATE_5GHZ_PASSIVE
;
wl1271_scan_stm
(
wl
);
wl1271_scan_stm
(
wl
,
vif
);
}
break
;
case
WL1271_SCAN_STATE_5GHZ_PASSIVE
:
band
=
IEEE80211_BAND_5GHZ
;
rate
=
wl1271_tx_min_rate_get
(
wl
,
wl
->
bitrate_masks
[
band
]);
ret
=
wl1271_scan_send
(
wl
,
band
,
true
,
rate
);
rate
=
wl1271_tx_min_rate_get
(
wl
,
wl
vif
->
bitrate_masks
[
band
]);
ret
=
wl1271_scan_send
(
wl
,
vif
,
band
,
true
,
rate
);
if
(
ret
==
WL1271_NOTHING_TO_SCAN
)
{
wl
->
scan
.
state
=
WL1271_SCAN_STATE_DONE
;
wl1271_scan_stm
(
wl
);
wl1271_scan_stm
(
wl
,
vif
);
}
break
;
...
...
@@ -317,7 +337,8 @@ void wl1271_scan_stm(struct wl1271 *wl)
}
}
int
wl1271_scan
(
struct
wl1271
*
wl
,
const
u8
*
ssid
,
size_t
ssid_len
,
int
wl1271_scan
(
struct
wl1271
*
wl
,
struct
ieee80211_vif
*
vif
,
const
u8
*
ssid
,
size_t
ssid_len
,
struct
cfg80211_scan_request
*
req
)
{
/*
...
...
@@ -338,6 +359,7 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
wl
->
scan
.
ssid_len
=
0
;
}
wl
->
scan_vif
=
vif
;
wl
->
scan
.
req
=
req
;
memset
(
wl
->
scan
.
scanned_ch
,
0
,
sizeof
(
wl
->
scan
.
scanned_ch
));
...
...
@@ -346,7 +368,7 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
ieee80211_queue_delayed_work
(
wl
->
hw
,
&
wl
->
scan_complete_work
,
msecs_to_jiffies
(
WL1271_SCAN_TIMEOUT
));
wl1271_scan_stm
(
wl
);
wl1271_scan_stm
(
wl
,
vif
);
return
0
;
}
...
...
@@ -550,6 +572,9 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
* so they're used in probe requests.
*/
for
(
i
=
0
;
i
<
req
->
n_ssids
;
i
++
)
{
if
(
!
req
->
ssids
[
i
].
ssid_len
)
continue
;
for
(
j
=
0
;
j
<
cmd
->
n_ssids
;
j
++
)
if
(
!
memcmp
(
req
->
ssids
[
i
].
ssid
,
cmd
->
ssids
[
j
].
ssid
,
...
...
@@ -585,6 +610,7 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
}
int
wl1271_scan_sched_scan_config
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
cfg80211_sched_scan_request
*
req
,
struct
ieee80211_sched_scan_ies
*
ies
)
{
...
...
@@ -631,7 +657,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
}
if
(
!
force_passive
&&
cfg
->
active
[
0
])
{
ret
=
wl1271_cmd_build_probe_req
(
wl
,
req
->
ssids
[
0
].
ssid
,
ret
=
wl1271_cmd_build_probe_req
(
wl
,
wlvif
,
req
->
ssids
[
0
].
ssid
,
req
->
ssids
[
0
].
ssid_len
,
ies
->
ie
[
IEEE80211_BAND_2GHZ
],
ies
->
len
[
IEEE80211_BAND_2GHZ
],
...
...
@@ -643,7 +669,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
}
if
(
!
force_passive
&&
cfg
->
active
[
1
])
{
ret
=
wl1271_cmd_build_probe_req
(
wl
,
req
->
ssids
[
0
].
ssid
,
ret
=
wl1271_cmd_build_probe_req
(
wl
,
wlvif
,
req
->
ssids
[
0
].
ssid
,
req
->
ssids
[
0
].
ssid_len
,
ies
->
ie
[
IEEE80211_BAND_5GHZ
],
ies
->
len
[
IEEE80211_BAND_5GHZ
],
...
...
@@ -667,14 +693,14 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
return
ret
;
}
int
wl1271_scan_sched_scan_start
(
struct
wl1271
*
wl
)
int
wl1271_scan_sched_scan_start
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
wl1271_cmd_sched_scan_start
*
start
;
int
ret
=
0
;
wl1271_debug
(
DEBUG_CMD
,
"cmd periodic scan start"
);
if
(
wl
->
bss_type
!=
BSS_TYPE_STA_BSS
)
if
(
wl
vif
->
bss_type
!=
BSS_TYPE_STA_BSS
)
return
-
EOPNOTSUPP
;
if
(
!
test_bit
(
WL1271_FLAG_IDLE
,
&
wl
->
flags
))
...
...
drivers/net/wireless/wl12xx/scan.h
View file @
f589cf4f
...
...
@@ -26,18 +26,20 @@
#include "wl12xx.h"
int
wl1271_scan
(
struct
wl1271
*
wl
,
const
u8
*
ssid
,
size_t
ssid_len
,
int
wl1271_scan
(
struct
wl1271
*
wl
,
struct
ieee80211_vif
*
vif
,
const
u8
*
ssid
,
size_t
ssid_len
,
struct
cfg80211_scan_request
*
req
);
int
wl1271_scan_stop
(
struct
wl1271
*
wl
);
int
wl1271_scan_build_probe_req
(
struct
wl1271
*
wl
,
const
u8
*
ssid
,
size_t
ssid_len
,
const
u8
*
ie
,
size_t
ie_len
,
u8
band
);
void
wl1271_scan_stm
(
struct
wl1271
*
wl
);
void
wl1271_scan_stm
(
struct
wl1271
*
wl
,
struct
ieee80211_vif
*
vif
);
void
wl1271_scan_complete_work
(
struct
work_struct
*
work
);
int
wl1271_scan_sched_scan_config
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
cfg80211_sched_scan_request
*
req
,
struct
ieee80211_sched_scan_ies
*
ies
);
int
wl1271_scan_sched_scan_start
(
struct
wl1271
*
wl
);
int
wl1271_scan_sched_scan_start
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
void
wl1271_scan_sched_scan_stop
(
struct
wl1271
*
wl
);
void
wl1271_scan_sched_scan_results
(
struct
wl1271
*
wl
);
...
...
drivers/net/wireless/wl12xx/sdio.c
View file @
f589cf4f
...
...
@@ -24,6 +24,7 @@
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/platform_device.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/card.h>
...
...
@@ -44,107 +45,67 @@
#define SDIO_DEVICE_ID_TI_WL1271 0x4076
#endif
struct
wl12xx_sdio_glue
{
struct
device
*
dev
;
struct
platform_device
*
core
;
};
static
const
struct
sdio_device_id
wl1271_devices
[]
__devinitconst
=
{
{
SDIO_DEVICE
(
SDIO_VENDOR_ID_TI
,
SDIO_DEVICE_ID_TI_WL1271
)
},
{}
};
MODULE_DEVICE_TABLE
(
sdio
,
wl1271_devices
);
static
void
wl1271_sdio_set_block_size
(
struct
wl1271
*
wl
,
unsigned
int
blksz
)
{
sdio_claim_host
(
wl
->
if_priv
);
sdio_set_block_size
(
wl
->
if_priv
,
blksz
);
sdio_release_host
(
wl
->
if_priv
);
}
static
inline
struct
sdio_func
*
wl_to_func
(
struct
wl1271
*
wl
)
{
return
wl
->
if_priv
;
}
static
struct
device
*
wl1271_sdio_wl_to_dev
(
struct
wl1271
*
wl
)
{
return
&
(
wl_to_func
(
wl
)
->
dev
);
}
static
irqreturn_t
wl1271_hardirq
(
int
irq
,
void
*
cookie
)
static
void
wl1271_sdio_set_block_size
(
struct
device
*
child
,
unsigned
int
blksz
)
{
struct
wl12
71
*
wl
=
cookie
;
unsigned
long
flags
;
struct
wl12
xx_sdio_glue
*
glue
=
dev_get_drvdata
(
child
->
parent
)
;
struct
sdio_func
*
func
=
dev_to_sdio_func
(
glue
->
dev
)
;
wl1271_debug
(
DEBUG_IRQ
,
"IRQ"
);
/* complete the ELP completion */
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
set_bit
(
WL1271_FLAG_IRQ_RUNNING
,
&
wl
->
flags
);
if
(
wl
->
elp_compl
)
{
complete
(
wl
->
elp_compl
);
wl
->
elp_compl
=
NULL
;
}
if
(
test_bit
(
WL1271_FLAG_SUSPENDED
,
&
wl
->
flags
))
{
/* don't enqueue a work right now. mark it as pending */
set_bit
(
WL1271_FLAG_PENDING_WORK
,
&
wl
->
flags
);
wl1271_debug
(
DEBUG_IRQ
,
"should not enqueue work"
);
disable_irq_nosync
(
wl
->
irq
);
pm_wakeup_event
(
wl1271_sdio_wl_to_dev
(
wl
),
0
);
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
return
IRQ_HANDLED
;
}
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
return
IRQ_WAKE_THREAD
;
}
static
void
wl1271_sdio_disable_interrupts
(
struct
wl1271
*
wl
)
{
disable_irq
(
wl
->
irq
);
}
static
void
wl1271_sdio_enable_interrupts
(
struct
wl1271
*
wl
)
{
enable_irq
(
wl
->
irq
);
sdio_claim_host
(
func
);
sdio_set_block_size
(
func
,
blksz
);
sdio_release_host
(
func
);
}
static
void
wl12
71_sdio_raw_read
(
struct
wl1271
*
wl
,
int
addr
,
void
*
buf
,
static
void
wl12
xx_sdio_raw_read
(
struct
device
*
child
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
int
ret
;
struct
sdio_func
*
func
=
wl_to_func
(
wl
);
struct
wl12xx_sdio_glue
*
glue
=
dev_get_drvdata
(
child
->
parent
);
struct
sdio_func
*
func
=
dev_to_sdio_func
(
glue
->
dev
);
if
(
unlikely
(
addr
==
HW_ACCESS_ELP_CTRL_REG_ADDR
))
{
((
u8
*
)
buf
)[
0
]
=
sdio_f0_readb
(
func
,
addr
,
&
ret
);
wl1271_debug
(
DEBUG_SDIO
,
"sdio read 52 addr 0x%x, byte 0x%02x
"
,
addr
,
((
u8
*
)
buf
)[
0
]);
dev_dbg
(
child
->
parent
,
"sdio read 52 addr 0x%x, byte 0x%02x
\n
"
,
addr
,
((
u8
*
)
buf
)[
0
]);
}
else
{
if
(
fixed
)
ret
=
sdio_readsb
(
func
,
buf
,
addr
,
len
);
else
ret
=
sdio_memcpy_fromio
(
func
,
buf
,
addr
,
len
);
wl1271_debug
(
DEBUG_SDIO
,
"sdio read 53 addr 0x%x, %zu bytes"
,
addr
,
len
);
wl1271_dump_ascii
(
DEBUG_SDIO
,
"data: "
,
buf
,
len
);
dev_dbg
(
child
->
parent
,
"sdio read 53 addr 0x%x, %zu bytes
\n
"
,
addr
,
len
);
}
if
(
ret
)
wl1271_error
(
"sdio read failed (%d)
"
,
ret
);
dev_err
(
child
->
parent
,
"sdio read failed (%d)
\n
"
,
ret
);
}
static
void
wl12
71_sdio_raw_write
(
struct
wl1271
*
wl
,
int
addr
,
void
*
buf
,
static
void
wl12
xx_sdio_raw_write
(
struct
device
*
child
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
int
ret
;
struct
sdio_func
*
func
=
wl_to_func
(
wl
);
struct
wl12xx_sdio_glue
*
glue
=
dev_get_drvdata
(
child
->
parent
);
struct
sdio_func
*
func
=
dev_to_sdio_func
(
glue
->
dev
);
if
(
unlikely
(
addr
==
HW_ACCESS_ELP_CTRL_REG_ADDR
))
{
sdio_f0_writeb
(
func
,
((
u8
*
)
buf
)[
0
],
addr
,
&
ret
);
wl1271_debug
(
DEBUG_SDIO
,
"sdio write 52 addr 0x%x, byte 0x%02x
"
,
addr
,
((
u8
*
)
buf
)[
0
]);
dev_dbg
(
child
->
parent
,
"sdio write 52 addr 0x%x, byte 0x%02x
\n
"
,
addr
,
((
u8
*
)
buf
)[
0
]);
}
else
{
wl1271_debug
(
DEBUG_SDIO
,
"sdio write 53 addr 0x%x, %zu bytes"
,
addr
,
len
);
wl1271_dump_ascii
(
DEBUG_SDIO
,
"data: "
,
buf
,
len
);
dev_dbg
(
child
->
parent
,
"sdio write 53 addr 0x%x, %zu bytes
\n
"
,
addr
,
len
);
if
(
fixed
)
ret
=
sdio_writesb
(
func
,
addr
,
buf
,
len
);
...
...
@@ -153,13 +114,13 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf,
}
if
(
ret
)
wl1271_error
(
"sdio write failed (%d)
"
,
ret
);
dev_err
(
child
->
parent
,
"sdio write failed (%d)
\n
"
,
ret
);
}
static
int
wl12
71_sdio_power_on
(
struct
wl1271
*
wl
)
static
int
wl12
xx_sdio_power_on
(
struct
wl12xx_sdio_glue
*
glue
)
{
struct
sdio_func
*
func
=
wl_to_func
(
wl
);
int
ret
;
struct
sdio_func
*
func
=
dev_to_sdio_func
(
glue
->
dev
);
/* If enabled, tell runtime PM not to power off the card */
if
(
pm_runtime_enabled
(
&
func
->
dev
))
{
...
...
@@ -180,10 +141,10 @@ static int wl1271_sdio_power_on(struct wl1271 *wl)
return
ret
;
}
static
int
wl12
71_sdio_power_off
(
struct
wl1271
*
wl
)
static
int
wl12
xx_sdio_power_off
(
struct
wl12xx_sdio_glue
*
glue
)
{
struct
sdio_func
*
func
=
wl_to_func
(
wl
);
int
ret
;
struct
sdio_func
*
func
=
dev_to_sdio_func
(
glue
->
dev
);
sdio_disable_func
(
func
);
sdio_release_host
(
func
);
...
...
@@ -200,46 +161,43 @@ static int wl1271_sdio_power_off(struct wl1271 *wl)
return
ret
;
}
static
int
wl12
71_sdio_set_power
(
struct
wl1271
*
wl
,
bool
enable
)
static
int
wl12
xx_sdio_set_power
(
struct
device
*
child
,
bool
enable
)
{
struct
wl12xx_sdio_glue
*
glue
=
dev_get_drvdata
(
child
->
parent
);
if
(
enable
)
return
wl12
71_sdio_power_on
(
wl
);
return
wl12
xx_sdio_power_on
(
glue
);
else
return
wl12
71_sdio_power_off
(
wl
);
return
wl12
xx_sdio_power_off
(
glue
);
}
static
struct
wl1271_if_operations
sdio_ops
=
{
.
read
=
wl1271_sdio_raw_read
,
.
write
=
wl1271_sdio_raw_write
,
.
power
=
wl1271_sdio_set_power
,
.
dev
=
wl1271_sdio_wl_to_dev
,
.
enable_irq
=
wl1271_sdio_enable_interrupts
,
.
disable_irq
=
wl1271_sdio_disable_interrupts
,
.
read
=
wl12xx_sdio_raw_read
,
.
write
=
wl12xx_sdio_raw_write
,
.
power
=
wl12xx_sdio_set_power
,
.
set_block_size
=
wl1271_sdio_set_block_size
,
};
static
int
__devinit
wl1271_probe
(
struct
sdio_func
*
func
,
const
struct
sdio_device_id
*
id
)
{
struct
ieee80211_hw
*
hw
;
const
struct
wl12xx_platform_data
*
wlan_data
;
struct
wl1271
*
wl
;
unsigned
long
irqflags
;
struct
wl12xx_platform_data
*
wlan_data
;
struct
wl12xx_sdio_glue
*
glue
;
struct
resource
res
[
1
];
mmc_pm_flag_t
mmcflags
;
int
ret
;
int
ret
=
-
ENOMEM
;
/* We are only able to handle the wlan function */
if
(
func
->
num
!=
0x02
)
return
-
ENODEV
;
hw
=
wl1271_alloc_hw
(
);
if
(
IS_ERR
(
hw
))
return
PTR_ERR
(
hw
);
wl
=
hw
->
priv
;
glue
=
kzalloc
(
sizeof
(
*
glue
),
GFP_KERNEL
);
if
(
!
glue
)
{
dev_err
(
&
func
->
dev
,
"can't allocate glue
\n
"
);
goto
out
;
}
wl
->
if_priv
=
func
;
wl
->
if_ops
=
&
sdio_ops
;
glue
->
dev
=
&
func
->
dev
;
/* Grab access to FN0 for ELP reg. */
func
->
card
->
quirks
|=
MMC_QUIRK_LENIENT_FN0
;
...
...
@@ -250,80 +208,79 @@ static int __devinit wl1271_probe(struct sdio_func *func,
wlan_data
=
wl12xx_get_platform_data
();
if
(
IS_ERR
(
wlan_data
))
{
ret
=
PTR_ERR
(
wlan_data
);
wl1271_error
(
"missing wlan platform data: %d
"
,
ret
);
goto
out_free
;
dev_err
(
glue
->
dev
,
"missing wlan platform data: %d
\n
"
,
ret
);
goto
out_free
_glue
;
}
wl
->
irq
=
wlan_data
->
irq
;
wl
->
ref_clock
=
wlan_data
->
board_ref_clock
;
wl
->
tcxo_clock
=
wlan_data
->
board_tcxo_clock
;
wl
->
platform_quirks
=
wlan_data
->
platform_quirks
;
/* if sdio can keep power while host is suspended, enable wow */
mmcflags
=
sdio_get_host_pm_caps
(
func
);
dev_dbg
(
glue
->
dev
,
"sdio PM caps = 0x%x
\n
"
,
mmcflags
);
if
(
wl
->
platform_quirks
&
WL12XX_PLATFORM_QUIRK_EDGE_IRQ
)
irqflags
=
IRQF_TRIGGER_RISING
;
else
irqflags
=
IRQF_TRIGGER_HIGH
|
IRQF_ONESHOT
;
ret
=
request_threaded_irq
(
wl
->
irq
,
wl1271_hardirq
,
wl1271_irq
,
irqflags
,
DRIVER_NAME
,
wl
);
if
(
ret
<
0
)
{
wl1271_error
(
"request_irq() failed: %d"
,
ret
);
goto
out_free
;
}
if
(
mmcflags
&
MMC_PM_KEEP_POWER
)
wlan_data
->
pwr_in_suspend
=
true
;
wlan_data
->
ops
=
&
sdio_ops
;
ret
=
enable_irq_wake
(
wl
->
irq
);
if
(
!
ret
)
{
wl
->
irq_wake_enabled
=
true
;
device_init_wakeup
(
wl1271_sdio_wl_to_dev
(
wl
),
1
);
sdio_set_drvdata
(
func
,
glue
);
/* if sdio can keep power while host is suspended, enable wow */
mmcflags
=
sdio_get_host_pm_caps
(
func
);
wl1271_debug
(
DEBUG_SDIO
,
"sdio PM caps = 0x%x"
,
mmcflags
);
/* Tell PM core that we don't need the card to be powered now */
pm_runtime_put_noidle
(
&
func
->
dev
);
if
(
mmcflags
&
MMC_PM_KEEP_POWER
)
hw
->
wiphy
->
wowlan
.
flags
=
WIPHY_WOWLAN_ANY
;
glue
->
core
=
platform_device_alloc
(
"wl12xx"
,
-
1
);
if
(
!
glue
->
core
)
{
dev_err
(
glue
->
dev
,
"can't allocate platform_device"
);
ret
=
-
ENOMEM
;
goto
out_free_glue
;
}
disable_irq
(
wl
->
irq
);
ret
=
wl1271_init_ieee80211
(
wl
);
if
(
ret
)
goto
out_irq
;
glue
->
core
->
dev
.
parent
=
&
func
->
dev
;
ret
=
wl1271_register_hw
(
wl
);
if
(
ret
)
goto
out_irq
;
memset
(
res
,
0x00
,
sizeof
(
res
));
sdio_set_drvdata
(
func
,
wl
);
res
[
0
].
start
=
wlan_data
->
irq
;
res
[
0
].
flags
=
IORESOURCE_IRQ
;
res
[
0
].
name
=
"irq"
;
/* Tell PM core that we don't need the card to be powered now */
pm_runtime_put_noidle
(
&
func
->
dev
);
ret
=
platform_device_add_resources
(
glue
->
core
,
res
,
ARRAY_SIZE
(
res
));
if
(
ret
)
{
dev_err
(
glue
->
dev
,
"can't add resources
\n
"
);
goto
out_dev_put
;
}
ret
=
platform_device_add_data
(
glue
->
core
,
wlan_data
,
sizeof
(
*
wlan_data
));
if
(
ret
)
{
dev_err
(
glue
->
dev
,
"can't add platform data
\n
"
);
goto
out_dev_put
;
}
ret
=
platform_device_add
(
glue
->
core
);
if
(
ret
)
{
dev_err
(
glue
->
dev
,
"can't add platform device
\n
"
);
goto
out_dev_put
;
}
return
0
;
out_irq
:
free_irq
(
wl
->
irq
,
wl
);
out_dev_put
:
platform_device_put
(
glue
->
core
);
out_fre
e:
wl1271_free_hw
(
wl
);
out_free_glu
e:
kfree
(
glue
);
out:
return
ret
;
}
static
void
__devexit
wl1271_remove
(
struct
sdio_func
*
func
)
{
struct
wl12
71
*
wl
=
sdio_get_drvdata
(
func
);
struct
wl12
xx_sdio_glue
*
glue
=
sdio_get_drvdata
(
func
);
/* Undo decrement done above in wl1271_probe */
pm_runtime_get_noresume
(
&
func
->
dev
);
wl1271_unregister_hw
(
wl
);
if
(
wl
->
irq_wake_enabled
)
{
device_init_wakeup
(
wl1271_sdio_wl_to_dev
(
wl
),
0
);
disable_irq_wake
(
wl
->
irq
);
}
free_irq
(
wl
->
irq
,
wl
);
wl1271_free_hw
(
wl
);
platform_device_del
(
glue
->
core
);
platform_device_put
(
glue
->
core
);
kfree
(
glue
);
}
#ifdef CONFIG_PM
...
...
@@ -332,20 +289,21 @@ static int wl1271_suspend(struct device *dev)
/* Tell MMC/SDIO core it's OK to power down the card
* (if it isn't already), but not to remove it completely */
struct
sdio_func
*
func
=
dev_to_sdio_func
(
dev
);
struct
wl1271
*
wl
=
sdio_get_drvdata
(
func
);
struct
wl12xx_sdio_glue
*
glue
=
sdio_get_drvdata
(
func
);
struct
wl1271
*
wl
=
platform_get_drvdata
(
glue
->
core
);
mmc_pm_flag_t
sdio_flags
;
int
ret
=
0
;
wl1271_debug
(
DEBUG_MAC80211
,
"wl1271 suspend. wow_enabled: %d
"
,
wl
->
wow_enabled
);
dev_dbg
(
dev
,
"wl1271 suspend. wow_enabled: %d
\n
"
,
wl
->
wow_enabled
);
/* check whether sdio should keep power */
if
(
wl
->
wow_enabled
)
{
sdio_flags
=
sdio_get_host_pm_caps
(
func
);
if
(
!
(
sdio_flags
&
MMC_PM_KEEP_POWER
))
{
wl1271_error
(
"can't keep power while host "
"is suspended"
);
dev_err
(
dev
,
"can't keep power while host "
"is suspended
\n
"
);
ret
=
-
EINVAL
;
goto
out
;
}
...
...
@@ -353,7 +311,7 @@ static int wl1271_suspend(struct device *dev)
/* keep power while host suspended */
ret
=
sdio_set_host_pm_flags
(
func
,
MMC_PM_KEEP_POWER
);
if
(
ret
)
{
wl1271_error
(
"error while trying to keep power
"
);
dev_err
(
dev
,
"error while trying to keep power
\n
"
);
goto
out
;
}
...
...
@@ -367,9 +325,10 @@ static int wl1271_suspend(struct device *dev)
static
int
wl1271_resume
(
struct
device
*
dev
)
{
struct
sdio_func
*
func
=
dev_to_sdio_func
(
dev
);
struct
wl1271
*
wl
=
sdio_get_drvdata
(
func
);
struct
wl12xx_sdio_glue
*
glue
=
sdio_get_drvdata
(
func
);
struct
wl1271
*
wl
=
platform_get_drvdata
(
glue
->
core
);
wl1271_debug
(
DEBUG_MAC80211
,
"wl1271 resume
"
);
dev_dbg
(
dev
,
"wl1271 resume
\n
"
);
if
(
wl
->
wow_enabled
)
{
/* claim back host */
sdio_claim_host
(
func
);
...
...
drivers/net/wireless/wl12xx/sdio_test.c
deleted
100644 → 0
View file @
0052d812
/*
* SDIO testing driver for wl12xx
*
* Copyright (C) 2010 Nokia Corporation
*
* Contact: Roger Quadros <roger.quadros@nokia.com>
*
* wl12xx read/write routines taken from the main module
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/crc7.h>
#include <linux/vmalloc.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
#include <linux/gpio.h>
#include <linux/wl12xx.h>
#include <linux/kthread.h>
#include <linux/firmware.h>
#include <linux/pm_runtime.h>
#include "wl12xx.h"
#include "io.h"
#include "boot.h"
#ifndef SDIO_VENDOR_ID_TI
#define SDIO_VENDOR_ID_TI 0x0097
#endif
#ifndef SDIO_DEVICE_ID_TI_WL1271
#define SDIO_DEVICE_ID_TI_WL1271 0x4076
#endif
static
bool
rx
,
tx
;
module_param
(
rx
,
bool
,
S_IRUGO
|
S_IWUSR
);
MODULE_PARM_DESC
(
rx
,
"Perform rx test. Default (0). "
"This test continuously reads data from the SDIO device.
\n
"
);
module_param
(
tx
,
bool
,
S_IRUGO
|
S_IWUSR
);
MODULE_PARM_DESC
(
tx
,
"Perform tx test. Default (0). "
"This test continuously writes data to the SDIO device.
\n
"
);
struct
wl1271_test
{
struct
wl1271
wl
;
struct
task_struct
*
test_task
;
};
static
const
struct
sdio_device_id
wl1271_devices
[]
=
{
{
SDIO_DEVICE
(
SDIO_VENDOR_ID_TI
,
SDIO_DEVICE_ID_TI_WL1271
)
},
{}
};
static
inline
struct
sdio_func
*
wl_to_func
(
struct
wl1271
*
wl
)
{
return
wl
->
if_priv
;
}
static
struct
device
*
wl1271_sdio_wl_to_dev
(
struct
wl1271
*
wl
)
{
return
&
(
wl_to_func
(
wl
)
->
dev
);
}
static
void
wl1271_sdio_raw_read
(
struct
wl1271
*
wl
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
int
ret
=
0
;
struct
sdio_func
*
func
=
wl_to_func
(
wl
);
if
(
unlikely
(
addr
==
HW_ACCESS_ELP_CTRL_REG_ADDR
))
{
((
u8
*
)
buf
)[
0
]
=
sdio_f0_readb
(
func
,
addr
,
&
ret
);
wl1271_debug
(
DEBUG_SDIO
,
"sdio read 52 addr 0x%x, byte 0x%02x"
,
addr
,
((
u8
*
)
buf
)[
0
]);
}
else
{
if
(
fixed
)
ret
=
sdio_readsb
(
func
,
buf
,
addr
,
len
);
else
ret
=
sdio_memcpy_fromio
(
func
,
buf
,
addr
,
len
);
wl1271_debug
(
DEBUG_SDIO
,
"sdio read 53 addr 0x%x, %zu bytes"
,
addr
,
len
);
wl1271_dump_ascii
(
DEBUG_SDIO
,
"data: "
,
buf
,
len
);
}
if
(
ret
)
wl1271_error
(
"sdio read failed (%d)"
,
ret
);
}
static
void
wl1271_sdio_raw_write
(
struct
wl1271
*
wl
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
int
ret
=
0
;
struct
sdio_func
*
func
=
wl_to_func
(
wl
);
if
(
unlikely
(
addr
==
HW_ACCESS_ELP_CTRL_REG_ADDR
))
{
sdio_f0_writeb
(
func
,
((
u8
*
)
buf
)[
0
],
addr
,
&
ret
);
wl1271_debug
(
DEBUG_SDIO
,
"sdio write 52 addr 0x%x, byte 0x%02x"
,
addr
,
((
u8
*
)
buf
)[
0
]);
}
else
{
wl1271_debug
(
DEBUG_SDIO
,
"sdio write 53 addr 0x%x, %zu bytes"
,
addr
,
len
);
wl1271_dump_ascii
(
DEBUG_SDIO
,
"data: "
,
buf
,
len
);
if
(
fixed
)
ret
=
sdio_writesb
(
func
,
addr
,
buf
,
len
);
else
ret
=
sdio_memcpy_toio
(
func
,
addr
,
buf
,
len
);
}
if
(
ret
)
wl1271_error
(
"sdio write failed (%d)"
,
ret
);
}
static
int
wl1271_sdio_set_power
(
struct
wl1271
*
wl
,
bool
enable
)
{
struct
sdio_func
*
func
=
wl_to_func
(
wl
);
int
ret
;
/* Let the SDIO stack handle wlan_enable control, so we
* keep host claimed while wlan is in use to keep wl1271
* alive.
*/
if
(
enable
)
{
/* Power up the card */
ret
=
pm_runtime_get_sync
(
&
func
->
dev
);
if
(
ret
<
0
)
goto
out
;
/* Runtime PM might be disabled, power up the card manually */
ret
=
mmc_power_restore_host
(
func
->
card
->
host
);
if
(
ret
<
0
)
goto
out
;
sdio_claim_host
(
func
);
sdio_enable_func
(
func
);
}
else
{
sdio_disable_func
(
func
);
sdio_release_host
(
func
);
/* Runtime PM might be disabled, power off the card manually */
ret
=
mmc_power_save_host
(
func
->
card
->
host
);
if
(
ret
<
0
)
goto
out
;
/* Power down the card */
ret
=
pm_runtime_put_sync
(
&
func
->
dev
);
}
out:
return
ret
;
}
static
void
wl1271_sdio_disable_interrupts
(
struct
wl1271
*
wl
)
{
}
static
void
wl1271_sdio_enable_interrupts
(
struct
wl1271
*
wl
)
{
}
static
struct
wl1271_if_operations
sdio_ops
=
{
.
read
=
wl1271_sdio_raw_read
,
.
write
=
wl1271_sdio_raw_write
,
.
power
=
wl1271_sdio_set_power
,
.
dev
=
wl1271_sdio_wl_to_dev
,
.
enable_irq
=
wl1271_sdio_enable_interrupts
,
.
disable_irq
=
wl1271_sdio_disable_interrupts
,
};
static
void
wl1271_fw_wakeup
(
struct
wl1271
*
wl
)
{
u32
elp_reg
;
elp_reg
=
ELPCTRL_WAKE_UP
;
wl1271_raw_write32
(
wl
,
HW_ACCESS_ELP_CTRL_REG_ADDR
,
elp_reg
);
}
static
int
wl1271_fetch_firmware
(
struct
wl1271
*
wl
)
{
const
struct
firmware
*
fw
;
int
ret
;
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
ret
=
request_firmware
(
&
fw
,
WL128X_FW_NAME
,
wl1271_wl_to_dev
(
wl
));
else
ret
=
request_firmware
(
&
fw
,
WL127X_FW_NAME
,
wl1271_wl_to_dev
(
wl
));
if
(
ret
<
0
)
{
wl1271_error
(
"could not get firmware: %d"
,
ret
);
return
ret
;
}
if
(
fw
->
size
%
4
)
{
wl1271_error
(
"firmware size is not multiple of 32 bits: %zu"
,
fw
->
size
);
ret
=
-
EILSEQ
;
goto
out
;
}
wl
->
fw_len
=
fw
->
size
;
wl
->
fw
=
vmalloc
(
wl
->
fw_len
);
if
(
!
wl
->
fw
)
{
wl1271_error
(
"could not allocate memory for the firmware"
);
ret
=
-
ENOMEM
;
goto
out
;
}
memcpy
(
wl
->
fw
,
fw
->
data
,
wl
->
fw_len
);
ret
=
0
;
out:
release_firmware
(
fw
);
return
ret
;
}
static
int
wl1271_fetch_nvs
(
struct
wl1271
*
wl
)
{
const
struct
firmware
*
fw
;
int
ret
;
ret
=
request_firmware
(
&
fw
,
WL12XX_NVS_NAME
,
wl1271_wl_to_dev
(
wl
));
if
(
ret
<
0
)
{
wl1271_error
(
"could not get nvs file: %d"
,
ret
);
return
ret
;
}
wl
->
nvs
=
kmemdup
(
fw
->
data
,
fw
->
size
,
GFP_KERNEL
);
if
(
!
wl
->
nvs
)
{
wl1271_error
(
"could not allocate memory for the nvs file"
);
ret
=
-
ENOMEM
;
goto
out
;
}
wl
->
nvs_len
=
fw
->
size
;
out:
release_firmware
(
fw
);
return
ret
;
}
static
int
wl1271_chip_wakeup
(
struct
wl1271
*
wl
)
{
struct
wl1271_partition_set
partition
;
int
ret
;
msleep
(
WL1271_PRE_POWER_ON_SLEEP
);
ret
=
wl1271_power_on
(
wl
);
if
(
ret
)
return
ret
;
msleep
(
WL1271_POWER_ON_SLEEP
);
/* We don't need a real memory partition here, because we only want
* to use the registers at this point. */
memset
(
&
partition
,
0
,
sizeof
(
partition
));
partition
.
reg
.
start
=
REGISTERS_BASE
;
partition
.
reg
.
size
=
REGISTERS_DOWN_SIZE
;
wl1271_set_partition
(
wl
,
&
partition
);
/* ELP module wake up */
wl1271_fw_wakeup
(
wl
);
/* whal_FwCtrl_BootSm() */
/* 0. read chip id from CHIP_ID */
wl
->
chip
.
id
=
wl1271_read32
(
wl
,
CHIP_ID_B
);
/* 1. check if chip id is valid */
switch
(
wl
->
chip
.
id
)
{
case
CHIP_ID_1271_PG10
:
wl1271_warning
(
"chip id 0x%x (1271 PG10) support is obsolete"
,
wl
->
chip
.
id
);
break
;
case
CHIP_ID_1271_PG20
:
wl1271_notice
(
"chip id 0x%x (1271 PG20)"
,
wl
->
chip
.
id
);
break
;
case
CHIP_ID_1283_PG20
:
wl1271_notice
(
"chip id 0x%x (1283 PG20)"
,
wl
->
chip
.
id
);
break
;
case
CHIP_ID_1283_PG10
:
default:
wl1271_warning
(
"unsupported chip id: 0x%x"
,
wl
->
chip
.
id
);
return
-
ENODEV
;
}
return
ret
;
}
static
struct
wl1271_partition_set
part_down
=
{
.
mem
=
{
.
start
=
0x00000000
,
.
size
=
0x000177c0
},
.
reg
=
{
.
start
=
REGISTERS_BASE
,
.
size
=
0x00008800
},
.
mem2
=
{
.
start
=
0x00000000
,
.
size
=
0x00000000
},
.
mem3
=
{
.
start
=
0x00000000
,
.
size
=
0x00000000
},
};
static
int
tester
(
void
*
data
)
{
struct
wl1271
*
wl
=
data
;
struct
sdio_func
*
func
=
wl_to_func
(
wl
);
struct
device
*
pdev
=
&
func
->
dev
;
int
ret
=
0
;
bool
rx_started
=
0
;
bool
tx_started
=
0
;
uint8_t
*
tx_buf
,
*
rx_buf
;
int
test_size
=
PAGE_SIZE
;
u32
addr
=
0
;
struct
wl1271_partition_set
partition
;
/* We assume chip is powered up and firmware fetched */
memcpy
(
&
partition
,
&
part_down
,
sizeof
(
partition
));
partition
.
mem
.
start
=
addr
;
wl1271_set_partition
(
wl
,
&
partition
);
tx_buf
=
kmalloc
(
test_size
,
GFP_KERNEL
);
rx_buf
=
kmalloc
(
test_size
,
GFP_KERNEL
);
if
(
!
tx_buf
||
!
rx_buf
)
{
dev_err
(
pdev
,
"Could not allocate memory. Test will not run.
\n
"
);
ret
=
-
ENOMEM
;
goto
free
;
}
memset
(
tx_buf
,
0x5a
,
test_size
);
/* write something in data area so we can read it back */
wl1271_write
(
wl
,
addr
,
tx_buf
,
test_size
,
false
);
while
(
!
kthread_should_stop
())
{
if
(
rx
&&
!
rx_started
)
{
dev_info
(
pdev
,
"starting rx test
\n
"
);
rx_started
=
1
;
}
else
if
(
!
rx
&&
rx_started
)
{
dev_info
(
pdev
,
"stopping rx test
\n
"
);
rx_started
=
0
;
}
if
(
tx
&&
!
tx_started
)
{
dev_info
(
pdev
,
"starting tx test
\n
"
);
tx_started
=
1
;
}
else
if
(
!
tx
&&
tx_started
)
{
dev_info
(
pdev
,
"stopping tx test
\n
"
);
tx_started
=
0
;
}
if
(
rx_started
)
wl1271_read
(
wl
,
addr
,
rx_buf
,
test_size
,
false
);
if
(
tx_started
)
wl1271_write
(
wl
,
addr
,
tx_buf
,
test_size
,
false
);
if
(
!
rx_started
&&
!
tx_started
)
msleep
(
100
);
}
free:
kfree
(
tx_buf
);
kfree
(
rx_buf
);
return
ret
;
}
static
int
__devinit
wl1271_probe
(
struct
sdio_func
*
func
,
const
struct
sdio_device_id
*
id
)
{
const
struct
wl12xx_platform_data
*
wlan_data
;
struct
wl1271
*
wl
;
struct
wl1271_test
*
wl_test
;
int
ret
=
0
;
/* wl1271 has 2 sdio functions we handle just the wlan part */
if
(
func
->
num
!=
0x02
)
return
-
ENODEV
;
wl_test
=
kzalloc
(
sizeof
(
struct
wl1271_test
),
GFP_KERNEL
);
if
(
!
wl_test
)
{
dev_err
(
&
func
->
dev
,
"Could not allocate memory
\n
"
);
return
-
ENOMEM
;
}
wl
=
&
wl_test
->
wl
;
wl
->
if_priv
=
func
;
wl
->
if_ops
=
&
sdio_ops
;
/* Grab access to FN0 for ELP reg. */
func
->
card
->
quirks
|=
MMC_QUIRK_LENIENT_FN0
;
/* Use block mode for transferring over one block size of data */
func
->
card
->
quirks
|=
MMC_QUIRK_BLKSZ_FOR_BYTE_MODE
;
wlan_data
=
wl12xx_get_platform_data
();
if
(
IS_ERR
(
wlan_data
))
{
ret
=
PTR_ERR
(
wlan_data
);
dev_err
(
&
func
->
dev
,
"missing wlan platform data: %d
\n
"
,
ret
);
goto
out_free
;
}
wl
->
irq
=
wlan_data
->
irq
;
wl
->
ref_clock
=
wlan_data
->
board_ref_clock
;
wl
->
tcxo_clock
=
wlan_data
->
board_tcxo_clock
;
sdio_set_drvdata
(
func
,
wl_test
);
/* power up the device */
ret
=
wl1271_chip_wakeup
(
wl
);
if
(
ret
)
{
dev_err
(
&
func
->
dev
,
"could not wake up chip
\n
"
);
goto
out_free
;
}
if
(
wl
->
fw
==
NULL
)
{
ret
=
wl1271_fetch_firmware
(
wl
);
if
(
ret
<
0
)
{
dev_err
(
&
func
->
dev
,
"firmware fetch error
\n
"
);
goto
out_off
;
}
}
/* fetch NVS */
if
(
wl
->
nvs
==
NULL
)
{
ret
=
wl1271_fetch_nvs
(
wl
);
if
(
ret
<
0
)
{
dev_err
(
&
func
->
dev
,
"NVS fetch error
\n
"
);
goto
out_off
;
}
}
ret
=
wl1271_load_firmware
(
wl
);
if
(
ret
<
0
)
{
dev_err
(
&
func
->
dev
,
"firmware load error: %d
\n
"
,
ret
);
goto
out_free
;
}
dev_info
(
&
func
->
dev
,
"initialized
\n
"
);
/* I/O testing will be done in the tester thread */
wl_test
->
test_task
=
kthread_run
(
tester
,
wl
,
"sdio_tester"
);
if
(
IS_ERR
(
wl_test
->
test_task
))
{
dev_err
(
&
func
->
dev
,
"unable to create kernel thread
\n
"
);
ret
=
PTR_ERR
(
wl_test
->
test_task
);
goto
out_free
;
}
return
0
;
out_off:
/* power off the chip */
wl1271_power_off
(
wl
);
out_free:
kfree
(
wl_test
);
return
ret
;
}
static
void
__devexit
wl1271_remove
(
struct
sdio_func
*
func
)
{
struct
wl1271_test
*
wl_test
=
sdio_get_drvdata
(
func
);
/* stop the I/O test thread */
kthread_stop
(
wl_test
->
test_task
);
/* power off the chip */
wl1271_power_off
(
&
wl_test
->
wl
);
vfree
(
wl_test
->
wl
.
fw
);
wl_test
->
wl
.
fw
=
NULL
;
kfree
(
wl_test
->
wl
.
nvs
);
wl_test
->
wl
.
nvs
=
NULL
;
kfree
(
wl_test
);
}
static
struct
sdio_driver
wl1271_sdio_driver
=
{
.
name
=
"wl12xx_sdio_test"
,
.
id_table
=
wl1271_devices
,
.
probe
=
wl1271_probe
,
.
remove
=
__devexit_p
(
wl1271_remove
),
};
static
int
__init
wl1271_init
(
void
)
{
int
ret
;
ret
=
sdio_register_driver
(
&
wl1271_sdio_driver
);
if
(
ret
<
0
)
pr_err
(
"failed to register sdio driver: %d
\n
"
,
ret
);
return
ret
;
}
module_init
(
wl1271_init
);
static
void
__exit
wl1271_exit
(
void
)
{
sdio_unregister_driver
(
&
wl1271_sdio_driver
);
}
module_exit
(
wl1271_exit
);
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Roger Quadros <roger.quadros@nokia.com>"
);
drivers/net/wireless/wl12xx/spi.c
View file @
f589cf4f
...
...
@@ -27,6 +27,7 @@
#include <linux/crc7.h>
#include <linux/spi/spi.h>
#include <linux/wl12xx.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include "wl12xx.h"
...
...
@@ -69,35 +70,22 @@
#define WSPI_MAX_NUM_OF_CHUNKS (WL1271_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE)
static
inline
struct
spi_device
*
wl_to_spi
(
struct
wl1271
*
wl
)
{
return
wl
->
if_priv
;
}
static
struct
device
*
wl1271_spi_wl_to_dev
(
struct
wl1271
*
wl
)
{
return
&
(
wl_to_spi
(
wl
)
->
dev
);
}
static
void
wl1271_spi_disable_interrupts
(
struct
wl1271
*
wl
)
{
disable_irq
(
wl
->
irq
);
}
static
void
wl1271_spi_enable_interrupts
(
struct
wl1271
*
wl
)
{
enable_irq
(
wl
->
irq
);
}
struct
wl12xx_spi_glue
{
struct
device
*
dev
;
struct
platform_device
*
core
;
};
static
void
wl12
71_spi_reset
(
struct
wl1271
*
wl
)
static
void
wl12
xx_spi_reset
(
struct
device
*
child
)
{
struct
wl12xx_spi_glue
*
glue
=
dev_get_drvdata
(
child
->
parent
);
u8
*
cmd
;
struct
spi_transfer
t
;
struct
spi_message
m
;
cmd
=
kzalloc
(
WSPI_INIT_CMD_LEN
,
GFP_KERNEL
);
if
(
!
cmd
)
{
wl1271_error
(
"could not allocate cmd for spi reset"
);
dev_err
(
child
->
parent
,
"could not allocate cmd for spi reset
\n
"
);
return
;
}
...
...
@@ -110,21 +98,22 @@ static void wl1271_spi_reset(struct wl1271 *wl)
t
.
len
=
WSPI_INIT_CMD_LEN
;
spi_message_add_tail
(
&
t
,
&
m
);
spi_sync
(
wl_to_spi
(
wl
),
&
m
);
spi_sync
(
to_spi_device
(
glue
->
dev
),
&
m
);
wl1271_dump
(
DEBUG_SPI
,
"spi reset -> "
,
cmd
,
WSPI_INIT_CMD_LEN
);
kfree
(
cmd
);
}
static
void
wl12
71_spi_init
(
struct
wl1271
*
wl
)
static
void
wl12
xx_spi_init
(
struct
device
*
child
)
{
struct
wl12xx_spi_glue
*
glue
=
dev_get_drvdata
(
child
->
parent
);
u8
crc
[
WSPI_INIT_CMD_CRC_LEN
],
*
cmd
;
struct
spi_transfer
t
;
struct
spi_message
m
;
cmd
=
kzalloc
(
WSPI_INIT_CMD_LEN
,
GFP_KERNEL
);
if
(
!
cmd
)
{
wl1271_error
(
"could not allocate cmd for spi init"
);
dev_err
(
child
->
parent
,
"could not allocate cmd for spi init
\n
"
);
return
;
}
...
...
@@ -165,15 +154,16 @@ static void wl1271_spi_init(struct wl1271 *wl)
t
.
len
=
WSPI_INIT_CMD_LEN
;
spi_message_add_tail
(
&
t
,
&
m
);
spi_sync
(
wl_to_spi
(
wl
),
&
m
);
wl1271_dump
(
DEBUG_SPI
,
"spi init -> "
,
cmd
,
WSPI_INIT_CMD_LEN
);
spi_sync
(
to_spi_device
(
glue
->
dev
),
&
m
);
kfree
(
cmd
);
}
#define WL1271_BUSY_WORD_TIMEOUT 1000
static
int
wl12
71_spi_read_busy
(
struct
wl1271
*
wl
)
static
int
wl12
xx_spi_read_busy
(
struct
device
*
child
)
{
struct
wl12xx_spi_glue
*
glue
=
dev_get_drvdata
(
child
->
parent
);
struct
wl1271
*
wl
=
dev_get_drvdata
(
child
);
struct
spi_transfer
t
[
1
];
struct
spi_message
m
;
u32
*
busy_buf
;
...
...
@@ -194,20 +184,22 @@ static int wl1271_spi_read_busy(struct wl1271 *wl)
t
[
0
].
len
=
sizeof
(
u32
);
t
[
0
].
cs_change
=
true
;
spi_message_add_tail
(
&
t
[
0
],
&
m
);
spi_sync
(
wl_to_spi
(
wl
),
&
m
);
spi_sync
(
to_spi_device
(
glue
->
dev
),
&
m
);
if
(
*
busy_buf
&
0x1
)
return
0
;
}
/* The SPI bus is unresponsive, the read failed. */
wl1271_error
(
"SPI read busy-word timeout!
\n
"
);
dev_err
(
child
->
parent
,
"SPI read busy-word timeout!
\n
"
);
return
-
ETIMEDOUT
;
}
static
void
wl12
71_spi_raw_read
(
struct
wl1271
*
wl
,
int
addr
,
void
*
buf
,
static
void
wl12
xx_spi_raw_read
(
struct
device
*
child
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
struct
wl12xx_spi_glue
*
glue
=
dev_get_drvdata
(
child
->
parent
);
struct
wl1271
*
wl
=
dev_get_drvdata
(
child
);
struct
spi_transfer
t
[
2
];
struct
spi_message
m
;
u32
*
busy_buf
;
...
...
@@ -243,10 +235,10 @@ static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf,
t
[
1
].
cs_change
=
true
;
spi_message_add_tail
(
&
t
[
1
],
&
m
);
spi_sync
(
wl_to_spi
(
wl
),
&
m
);
spi_sync
(
to_spi_device
(
glue
->
dev
),
&
m
);
if
(
!
(
busy_buf
[
WL1271_BUSY_WORD_CNT
-
1
]
&
0x1
)
&&
wl12
71_spi_read_busy
(
wl
))
{
wl12
xx_spi_read_busy
(
child
))
{
memset
(
buf
,
0
,
chunk_len
);
return
;
}
...
...
@@ -259,10 +251,7 @@ static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf,
t
[
0
].
cs_change
=
true
;
spi_message_add_tail
(
&
t
[
0
],
&
m
);
spi_sync
(
wl_to_spi
(
wl
),
&
m
);
wl1271_dump
(
DEBUG_SPI
,
"spi_read cmd -> "
,
cmd
,
sizeof
(
*
cmd
));
wl1271_dump
(
DEBUG_SPI
,
"spi_read buf <- "
,
buf
,
chunk_len
);
spi_sync
(
to_spi_device
(
glue
->
dev
),
&
m
);
if
(
!
fixed
)
addr
+=
chunk_len
;
...
...
@@ -271,9 +260,10 @@ static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf,
}
}
static
void
wl12
71_spi_raw_write
(
struct
wl1271
*
wl
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
static
void
wl12
xx_spi_raw_write
(
struct
device
*
child
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
struct
wl12xx_spi_glue
*
glue
=
dev_get_drvdata
(
child
->
parent
);
struct
spi_transfer
t
[
2
*
WSPI_MAX_NUM_OF_CHUNKS
];
struct
spi_message
m
;
u32
commands
[
WSPI_MAX_NUM_OF_CHUNKS
];
...
...
@@ -308,9 +298,6 @@ static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf,
t
[
i
].
len
=
chunk_len
;
spi_message_add_tail
(
&
t
[
i
++
],
&
m
);
wl1271_dump
(
DEBUG_SPI
,
"spi_write cmd -> "
,
cmd
,
sizeof
(
*
cmd
));
wl1271_dump
(
DEBUG_SPI
,
"spi_write buf -> "
,
buf
,
chunk_len
);
if
(
!
fixed
)
addr
+=
chunk_len
;
buf
+=
chunk_len
;
...
...
@@ -318,72 +305,41 @@ static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf,
cmd
++
;
}
spi_sync
(
wl_to_spi
(
wl
),
&
m
);
}
static
irqreturn_t
wl1271_hardirq
(
int
irq
,
void
*
cookie
)
{
struct
wl1271
*
wl
=
cookie
;
unsigned
long
flags
;
wl1271_debug
(
DEBUG_IRQ
,
"IRQ"
);
/* complete the ELP completion */
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
set_bit
(
WL1271_FLAG_IRQ_RUNNING
,
&
wl
->
flags
);
if
(
wl
->
elp_compl
)
{
complete
(
wl
->
elp_compl
);
wl
->
elp_compl
=
NULL
;
}
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
return
IRQ_WAKE_THREAD
;
}
static
int
wl1271_spi_set_power
(
struct
wl1271
*
wl
,
bool
enable
)
{
if
(
wl
->
set_power
)
wl
->
set_power
(
enable
);
return
0
;
spi_sync
(
to_spi_device
(
glue
->
dev
),
&
m
);
}
static
struct
wl1271_if_operations
spi_ops
=
{
.
read
=
wl1271_spi_raw_read
,
.
write
=
wl1271_spi_raw_write
,
.
reset
=
wl1271_spi_reset
,
.
init
=
wl1271_spi_init
,
.
power
=
wl1271_spi_set_power
,
.
dev
=
wl1271_spi_wl_to_dev
,
.
enable_irq
=
wl1271_spi_enable_interrupts
,
.
disable_irq
=
wl1271_spi_disable_interrupts
,
.
read
=
wl12xx_spi_raw_read
,
.
write
=
wl12xx_spi_raw_write
,
.
reset
=
wl12xx_spi_reset
,
.
init
=
wl12xx_spi_init
,
.
set_block_size
=
NULL
,
};
static
int
__devinit
wl1271_probe
(
struct
spi_device
*
spi
)
{
struct
wl12xx_spi_glue
*
glue
;
struct
wl12xx_platform_data
*
pdata
;
struct
ieee80211_hw
*
hw
;
struct
wl1271
*
wl
;
unsigned
long
irqflags
;
int
ret
;
struct
resource
res
[
1
];
int
ret
=
-
ENOMEM
;
pdata
=
spi
->
dev
.
platform_data
;
if
(
!
pdata
)
{
wl1271_error
(
"no platform data
"
);
dev_err
(
&
spi
->
dev
,
"no platform data
\n
"
);
return
-
ENODEV
;
}
hw
=
wl1271_alloc_hw
();
if
(
IS_ERR
(
hw
))
return
PTR_ERR
(
hw
);
pdata
->
ops
=
&
spi_ops
;
wl
=
hw
->
priv
;
glue
=
kzalloc
(
sizeof
(
*
glue
),
GFP_KERNEL
);
if
(
!
glue
)
{
dev_err
(
&
spi
->
dev
,
"can't allocate glue
\n
"
);
goto
out
;
}
dev_set_drvdata
(
&
spi
->
dev
,
wl
);
wl
->
if_priv
=
spi
;
glue
->
dev
=
&
spi
->
dev
;
wl
->
if_ops
=
&
spi_ops
;
spi_set_drvdata
(
spi
,
glue
)
;
/* This is the only SPI value that we need to set here, the rest
* comes from the board-peripherals file */
...
...
@@ -391,69 +347,61 @@ static int __devinit wl1271_probe(struct spi_device *spi)
ret
=
spi_setup
(
spi
);
if
(
ret
<
0
)
{
wl1271_error
(
"spi_setup failed
"
);
goto
out_free
;
dev_err
(
glue
->
dev
,
"spi_setup failed
\n
"
);
goto
out_free
_glue
;
}
wl
->
set_power
=
pdata
->
set_power
;
if
(
!
wl
->
set_power
)
{
wl1271_error
(
"set power function missing in platform data
"
);
ret
=
-
ENO
DEV
;
goto
out_free
;
glue
->
core
=
platform_device_alloc
(
"wl12xx"
,
-
1
)
;
if
(
!
glue
->
core
)
{
dev_err
(
glue
->
dev
,
"can't allocate platform_device
\n
"
);
ret
=
-
ENO
MEM
;
goto
out_free
_glue
;
}
wl
->
ref_clock
=
pdata
->
board_ref_clock
;
wl
->
tcxo_clock
=
pdata
->
board_tcxo_clock
;
wl
->
platform_quirks
=
pdata
->
platform_quirks
;
glue
->
core
->
dev
.
parent
=
&
spi
->
dev
;
if
(
wl
->
platform_quirks
&
WL12XX_PLATFORM_QUIRK_EDGE_IRQ
)
irqflags
=
IRQF_TRIGGER_RISING
;
else
irqflags
=
IRQF_TRIGGER_HIGH
|
IRQF_ONESHOT
;
memset
(
res
,
0x00
,
sizeof
(
res
));
wl
->
irq
=
spi
->
irq
;
if
(
wl
->
irq
<
0
)
{
wl1271_error
(
"irq missing in platform data"
);
ret
=
-
ENODEV
;
goto
out_free
;
}
res
[
0
].
start
=
spi
->
irq
;
res
[
0
].
flags
=
IORESOURCE_IRQ
;
res
[
0
].
name
=
"irq"
;
ret
=
request_threaded_irq
(
wl
->
irq
,
wl1271_hardirq
,
wl1271_irq
,
irqflags
,
DRIVER_NAME
,
wl
);
if
(
ret
<
0
)
{
wl1271_error
(
"request_irq() failed: %d"
,
ret
);
goto
out_free
;
ret
=
platform_device_add_resources
(
glue
->
core
,
res
,
ARRAY_SIZE
(
res
));
if
(
ret
)
{
dev_err
(
glue
->
dev
,
"can't add resources
\n
"
);
goto
out_dev_put
;
}
disable_irq
(
wl
->
irq
);
ret
=
wl1271_init_ieee80211
(
wl
);
if
(
ret
)
goto
out_irq
;
ret
=
platform_device_add_data
(
glue
->
core
,
pdata
,
sizeof
(
*
pdata
)
);
if
(
ret
)
{
dev_err
(
glue
->
dev
,
"can't add platform data
\n
"
);
goto
out_dev_put
;
}
ret
=
wl1271_register_hw
(
wl
);
if
(
ret
)
goto
out_irq
;
ret
=
platform_device_add
(
glue
->
core
);
if
(
ret
)
{
dev_err
(
glue
->
dev
,
"can't register platform device
\n
"
);
goto
out_dev_put
;
}
return
0
;
out_irq:
free_irq
(
wl
->
irq
,
wl
);
out_free:
wl1271_free_hw
(
wl
);
out_dev_put:
platform_device_put
(
glue
->
core
);
out_free_glue:
kfree
(
glue
);
out:
return
ret
;
}
static
int
__devexit
wl1271_remove
(
struct
spi_device
*
spi
)
{
struct
wl12
71
*
wl
=
dev_get_drvdata
(
&
spi
->
dev
);
struct
wl12
xx_spi_glue
*
glue
=
spi_get_drvdata
(
spi
);
wl1271_unregister_hw
(
wl
);
free_irq
(
wl
->
irq
,
wl
);
wl1271_free_hw
(
wl
);
platform_device_del
(
glue
->
core
);
platform_device_put
(
glue
->
core
);
kfree
(
glue
);
return
0
;
}
...
...
drivers/net/wireless/wl12xx/testmode.c
View file @
f589cf4f
...
...
@@ -26,8 +26,10 @@
#include <net/genetlink.h>
#include "wl12xx.h"
#include "debug.h"
#include "acx.h"
#include "reg.h"
#include "ps.h"
#define WL1271_TM_MAX_DATA_LENGTH 1024
...
...
@@ -87,31 +89,47 @@ static int wl1271_tm_cmd_test(struct wl1271 *wl, struct nlattr *tb[])
return
-
EMSGSIZE
;
mutex_lock
(
&
wl
->
mutex
);
ret
=
wl1271_cmd_test
(
wl
,
buf
,
buf_len
,
answer
);
mutex_unlock
(
&
wl
->
mutex
);
if
(
wl
->
state
==
WL1271_STATE_OFF
)
{
ret
=
-
EINVAL
;
goto
out
;
}
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out
;
ret
=
wl1271_cmd_test
(
wl
,
buf
,
buf_len
,
answer
);
if
(
ret
<
0
)
{
wl1271_warning
(
"testmode cmd test failed: %d"
,
ret
);
return
ret
;
goto
out_sleep
;
}
if
(
answer
)
{
len
=
nla_total_size
(
buf_len
);
skb
=
cfg80211_testmode_alloc_reply_skb
(
wl
->
hw
->
wiphy
,
len
);
if
(
!
skb
)
return
-
ENOMEM
;
if
(
!
skb
)
{
ret
=
-
ENOMEM
;
goto
out_sleep
;
}
NLA_PUT
(
skb
,
WL1271_TM_ATTR_DATA
,
buf_len
,
buf
);
ret
=
cfg80211_testmode_reply
(
skb
);
if
(
ret
<
0
)
return
ret
;
goto
out_sleep
;
}
return
0
;
out_sleep:
wl1271_ps_elp_sleep
(
wl
);
out:
mutex_unlock
(
&
wl
->
mutex
);
return
ret
;
nla_put_failure:
kfree_skb
(
skb
);
return
-
EMSGSIZE
;
ret
=
-
EMSGSIZE
;
goto
out_sleep
;
}
static
int
wl1271_tm_cmd_interrogate
(
struct
wl1271
*
wl
,
struct
nlattr
*
tb
[])
...
...
@@ -128,33 +146,53 @@ static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[])
ie_id
=
nla_get_u8
(
tb
[
WL1271_TM_ATTR_IE_ID
]);
mutex_lock
(
&
wl
->
mutex
);
if
(
wl
->
state
==
WL1271_STATE_OFF
)
{
ret
=
-
EINVAL
;
goto
out
;
}
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out
;
cmd
=
kzalloc
(
sizeof
(
*
cmd
),
GFP_KERNEL
);
if
(
!
cmd
)
return
-
ENOMEM
;
if
(
!
cmd
)
{
ret
=
-
ENOMEM
;
goto
out_sleep
;
}
mutex_lock
(
&
wl
->
mutex
);
ret
=
wl1271_cmd_interrogate
(
wl
,
ie_id
,
cmd
,
sizeof
(
*
cmd
));
mutex_unlock
(
&
wl
->
mutex
);
if
(
ret
<
0
)
{
wl1271_warning
(
"testmode cmd interrogate failed: %d"
,
ret
);
kfree
(
cmd
);
return
ret
;
goto
out_free
;
}
skb
=
cfg80211_testmode_alloc_reply_skb
(
wl
->
hw
->
wiphy
,
sizeof
(
*
cmd
));
if
(
!
skb
)
{
kfree
(
cmd
)
;
return
-
ENOMEM
;
ret
=
-
ENOMEM
;
goto
out_free
;
}
NLA_PUT
(
skb
,
WL1271_TM_ATTR_DATA
,
sizeof
(
*
cmd
),
cmd
);
ret
=
cfg80211_testmode_reply
(
skb
);
if
(
ret
<
0
)
goto
out_free
;
out_free:
kfree
(
cmd
);
out_sleep:
wl1271_ps_elp_sleep
(
wl
);
out:
mutex_unlock
(
&
wl
->
mutex
);
return
0
;
return
ret
;
nla_put_failure:
kfree_skb
(
skb
);
return
-
EMSGSIZE
;
ret
=
-
EMSGSIZE
;
goto
out_free
;
}
static
int
wl1271_tm_cmd_configure
(
struct
wl1271
*
wl
,
struct
nlattr
*
tb
[])
...
...
drivers/net/wireless/wl12xx/tx.c
View file @
f589cf4f
...
...
@@ -26,22 +26,24 @@
#include <linux/etherdevice.h>
#include "wl12xx.h"
#include "debug.h"
#include "io.h"
#include "reg.h"
#include "ps.h"
#include "tx.h"
#include "event.h"
static
int
wl1271_set_default_wep_key
(
struct
wl1271
*
wl
,
u8
id
)
static
int
wl1271_set_default_wep_key
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
id
)
{
int
ret
;
bool
is_ap
=
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
);
bool
is_ap
=
(
wl
vif
->
bss_type
==
BSS_TYPE_AP_BSS
);
if
(
is_ap
)
ret
=
wl12xx_cmd_set_default_wep_key
(
wl
,
id
,
wl
->
ap_
bcast_hlid
);
wl
vif
->
ap
.
bcast_hlid
);
else
ret
=
wl12xx_cmd_set_default_wep_key
(
wl
,
id
,
wl
->
sta_
hlid
);
ret
=
wl12xx_cmd_set_default_wep_key
(
wl
,
id
,
wl
vif
->
sta
.
hlid
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -76,7 +78,8 @@ static void wl1271_free_tx_id(struct wl1271 *wl, int id)
}
static
int
wl1271_tx_update_filters
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
)
struct
wl12xx_vif
*
wlvif
,
struct
sk_buff
*
skb
)
{
struct
ieee80211_hdr
*
hdr
;
int
ret
;
...
...
@@ -92,15 +95,11 @@ static int wl1271_tx_update_filters(struct wl1271 *wl,
if
(
!
ieee80211_is_auth
(
hdr
->
frame_control
))
return
0
;
if
(
wl
->
dev_hlid
!=
WL12XX_INVALID_LINK_ID
)
if
(
wl
vif
->
dev_hlid
!=
WL12XX_INVALID_LINK_ID
)
goto
out
;
wl1271_debug
(
DEBUG_CMD
,
"starting device role for roaming"
);
ret
=
wl12xx_cmd_role_start_dev
(
wl
);
if
(
ret
<
0
)
goto
out
;
ret
=
wl12xx_roc
(
wl
,
wl
->
dev_role_id
);
ret
=
wl12xx_start_dev
(
wl
,
wlvif
);
if
(
ret
<
0
)
goto
out
;
out:
...
...
@@ -123,18 +122,16 @@ static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
wl1271_acx_set_inconnection_sta
(
wl
,
hdr
->
addr1
);
}
static
void
wl1271_tx_regulate_link
(
struct
wl1271
*
wl
,
u8
hlid
)
static
void
wl1271_tx_regulate_link
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
hlid
)
{
bool
fw_ps
,
single_sta
;
u8
tx_pkts
;
/* only regulate station links */
if
(
hlid
<
WL1271_AP_STA_HLID_START
)
if
(
WARN_ON
(
!
test_bit
(
hlid
,
wlvif
->
links_map
)))
return
;
if
(
WARN_ON
(
!
wl1271_is_active_sta
(
wl
,
hlid
)))
return
;
fw_ps
=
test_bit
(
hlid
,
(
unsigned
long
*
)
&
wl
->
ap_fw_ps_map
);
tx_pkts
=
wl
->
links
[
hlid
].
allocated_pkts
;
single_sta
=
(
wl
->
active_sta_count
==
1
);
...
...
@@ -146,7 +143,7 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid)
* case FW-memory congestion is not a problem.
*/
if
(
!
single_sta
&&
fw_ps
&&
tx_pkts
>=
WL1271_PS_STA_MAX_PACKETS
)
wl12
71_ps_link_start
(
wl
,
hlid
,
true
);
wl12
xx_ps_link_start
(
wl
,
wlvif
,
hlid
,
true
);
}
bool
wl12xx_is_dummy_packet
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
)
...
...
@@ -154,7 +151,8 @@ bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb)
return
wl
->
dummy_packet
==
skb
;
}
u8
wl12xx_tx_get_hlid_ap
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
)
u8
wl12xx_tx_get_hlid_ap
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
sk_buff
*
skb
)
{
struct
ieee80211_tx_info
*
control
=
IEEE80211_SKB_CB
(
skb
);
...
...
@@ -167,49 +165,51 @@ u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb)
}
else
{
struct
ieee80211_hdr
*
hdr
;
if
(
!
test_bit
(
WL
1271_FLAG_AP_STARTED
,
&
wl
->
flags
))
if
(
!
test_bit
(
WL
VIF_FLAG_AP_STARTED
,
&
wlvif
->
flags
))
return
wl
->
system_hlid
;
hdr
=
(
struct
ieee80211_hdr
*
)
skb
->
data
;
if
(
ieee80211_is_mgmt
(
hdr
->
frame_control
))
return
wl
->
ap_
global_hlid
;
return
wl
vif
->
ap
.
global_hlid
;
else
return
wl
->
ap_
bcast_hlid
;
return
wl
vif
->
ap
.
bcast_hlid
;
}
}
static
u8
wl1271_tx_get_hlid
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
)
u8
wl12xx_tx_get_hlid
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
sk_buff
*
skb
)
{
struct
ieee80211_hdr
*
hdr
=
(
struct
ieee80211_hdr
*
)
skb
->
data
;
if
(
wl12xx_is_dummy_packet
(
wl
,
skb
))
if
(
!
wlvif
||
wl12xx_is_dummy_packet
(
wl
,
skb
))
return
wl
->
system_hlid
;
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
return
wl12xx_tx_get_hlid_ap
(
wl
,
skb
);
if
(
wl
vif
->
bss_type
==
BSS_TYPE_AP_BSS
)
return
wl12xx_tx_get_hlid_ap
(
wl
,
wlvif
,
skb
);
wl1271_tx_update_filters
(
wl
,
skb
);
wl1271_tx_update_filters
(
wl
,
wlvif
,
skb
);
if
((
test_bit
(
WL
1271_FLAG_STA_ASSOCIATED
,
&
wl
->
flags
)
||
test_bit
(
WL
1271_FLAG_IBSS_JOINED
,
&
wl
->
flags
))
&&
if
((
test_bit
(
WL
VIF_FLAG_STA_ASSOCIATED
,
&
wlvif
->
flags
)
||
test_bit
(
WL
VIF_FLAG_IBSS_JOINED
,
&
wlvif
->
flags
))
&&
!
ieee80211_is_auth
(
hdr
->
frame_control
)
&&
!
ieee80211_is_assoc_req
(
hdr
->
frame_control
))
return
wl
->
sta_
hlid
;
return
wl
vif
->
sta
.
hlid
;
else
return
wl
->
dev_hlid
;
return
wl
vif
->
dev_hlid
;
}
static
unsigned
int
wl12xx_calc_packet_alignment
(
struct
wl1271
*
wl
,
unsigned
int
packet_length
)
{
if
(
wl
->
quirks
&
WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT
)
return
ALIGN
(
packet_length
,
WL12XX_BUS_BLOCK_SIZE
);
else
if
(
wl
->
quirks
&
WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT
)
return
ALIGN
(
packet_length
,
WL1271_TX_ALIGN_TO
);
else
return
ALIGN
(
packet_length
,
WL12XX_BUS_BLOCK_SIZE
);
}
static
int
wl1271_tx_allocate
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
,
u32
extra
,
u32
buf_offset
,
u8
hlid
)
static
int
wl1271_tx_allocate
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
sk_buff
*
skb
,
u32
extra
,
u32
buf_offset
,
u8
hlid
)
{
struct
wl1271_tx_hw_descr
*
desc
;
u32
total_len
=
skb
->
len
+
sizeof
(
struct
wl1271_tx_hw_descr
)
+
extra
;
...
...
@@ -217,6 +217,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
u32
total_blocks
;
int
id
,
ret
=
-
EBUSY
,
ac
;
u32
spare_blocks
=
wl
->
tx_spare_blocks
;
bool
is_dummy
=
false
;
if
(
buf_offset
+
total_len
>
WL1271_AGGR_BUFFER_SIZE
)
return
-
EAGAIN
;
...
...
@@ -231,8 +232,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
len
=
wl12xx_calc_packet_alignment
(
wl
,
total_len
);
/* in case of a dummy packet, use default amount of spare mem blocks */
if
(
unlikely
(
wl12xx_is_dummy_packet
(
wl
,
skb
)))
if
(
unlikely
(
wl12xx_is_dummy_packet
(
wl
,
skb
)))
{
is_dummy
=
true
;
spare_blocks
=
TX_HW_BLOCK_SPARE_DEFAULT
;
}
total_blocks
=
(
len
+
TX_HW_BLOCK_SIZE
-
1
)
/
TX_HW_BLOCK_SIZE
+
spare_blocks
;
...
...
@@ -257,8 +260,9 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
ac
=
wl1271_tx_get_queue
(
skb_get_queue_mapping
(
skb
));
wl
->
tx_allocated_pkts
[
ac
]
++
;
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
&&
hlid
>=
WL1271_AP_STA_HLID_START
)
if
(
!
is_dummy
&&
wlvif
&&
wlvif
->
bss_type
==
BSS_TYPE_AP_BSS
&&
test_bit
(
hlid
,
wlvif
->
ap
.
sta_hlid_map
))
wl
->
links
[
hlid
].
allocated_pkts
++
;
ret
=
0
;
...
...
@@ -273,15 +277,16 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
return
ret
;
}
static
void
wl1271_tx_fill_hdr
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
,
u32
extra
,
struct
ieee80211_tx_info
*
control
,
u8
hlid
)
static
void
wl1271_tx_fill_hdr
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
sk_buff
*
skb
,
u32
extra
,
struct
ieee80211_tx_info
*
control
,
u8
hlid
)
{
struct
timespec
ts
;
struct
wl1271_tx_hw_descr
*
desc
;
int
aligned_len
,
ac
,
rate_idx
;
s64
hosttime
;
u16
tx_attr
;
bool
is_dummy
;
desc
=
(
struct
wl1271_tx_hw_descr
*
)
skb
->
data
;
...
...
@@ -298,7 +303,8 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
hosttime
=
(
timespec_to_ns
(
&
ts
)
>>
10
);
desc
->
start_time
=
cpu_to_le32
(
hosttime
-
wl
->
time_offset
);
if
(
wl
->
bss_type
!=
BSS_TYPE_AP_BSS
)
is_dummy
=
wl12xx_is_dummy_packet
(
wl
,
skb
);
if
(
is_dummy
||
!
wlvif
||
wlvif
->
bss_type
!=
BSS_TYPE_AP_BSS
)
desc
->
life_time
=
cpu_to_le16
(
TX_HW_MGMT_PKT_LIFETIME_TU
);
else
desc
->
life_time
=
cpu_to_le16
(
TX_HW_AP_MODE_PKT_LIFETIME_TU
);
...
...
@@ -307,39 +313,42 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
ac
=
wl1271_tx_get_queue
(
skb_get_queue_mapping
(
skb
));
desc
->
tid
=
skb
->
priority
;
if
(
wl12xx_is_dummy_packet
(
wl
,
skb
)
)
{
if
(
is_dummy
)
{
/*
* FW expects the dummy packet to have an invalid session id -
* any session id that is different than the one set in the join
*/
tx_attr
=
(
(
~
wl
->
session_counter
)
<<
tx_attr
=
(
SESSION_COUNTER_INVALID
<<
TX_HW_ATTR_OFST_SESSION_COUNTER
)
&
TX_HW_ATTR_SESSION_COUNTER
;
tx_attr
|=
TX_HW_ATTR_TX_DUMMY_REQ
;
}
else
{
}
else
if
(
wlvif
)
{
/* configure the tx attributes */
tx_attr
=
wl
->
session_counter
<<
TX_HW_ATTR_OFST_SESSION_COUNTER
;
tx_attr
=
wlvif
->
session_counter
<<
TX_HW_ATTR_OFST_SESSION_COUNTER
;
}
desc
->
hlid
=
hlid
;
if
(
wl
->
bss_type
!=
BSS_TYPE_AP_BSS
)
{
if
(
is_dummy
||
!
wlvif
)
rate_idx
=
0
;
else
if
(
wlvif
->
bss_type
!=
BSS_TYPE_AP_BSS
)
{
/* if the packets are destined for AP (have a STA entry)
send them with AP rate policies, otherwise use default
basic rates */
if
(
control
->
control
.
sta
)
rate_idx
=
ACX_TX_AP_FULL_RATE
;
if
(
control
->
flags
&
IEEE80211_TX_CTL_NO_CCK_RATE
)
rate_idx
=
wlvif
->
sta
.
p2p_rate_idx
;
else
if
(
control
->
control
.
sta
)
rate_idx
=
wlvif
->
sta
.
ap_rate_idx
;
else
rate_idx
=
ACX_TX_BASIC_RATE
;
rate_idx
=
wlvif
->
sta
.
basic_rate_idx
;
}
else
{
if
(
hlid
==
wl
->
ap_
global_hlid
)
rate_idx
=
ACX_TX_AP_MODE_MGMT_RATE
;
else
if
(
hlid
==
wl
->
ap_
bcast_hlid
)
rate_idx
=
ACX_TX_AP_MODE_BCST_RATE
;
if
(
hlid
==
wl
vif
->
ap
.
global_hlid
)
rate_idx
=
wlvif
->
ap
.
mgmt_rate_idx
;
else
if
(
hlid
==
wl
vif
->
ap
.
bcast_hlid
)
rate_idx
=
wlvif
->
ap
.
bcast_rate_idx
;
else
rate_idx
=
ac
;
rate_idx
=
wlvif
->
ap
.
ucast_rate_idx
[
ac
]
;
}
tx_attr
|=
rate_idx
<<
TX_HW_ATTR_OFST_RATE_POLICY
;
...
...
@@ -379,20 +388,24 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
}
/* caller must hold wl->mutex */
static
int
wl1271_prepare_tx_frame
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
,
u32
buf_offset
)
static
int
wl1271_prepare_tx_frame
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
sk_buff
*
skb
,
u32
buf_offset
)
{
struct
ieee80211_tx_info
*
info
;
u32
extra
=
0
;
int
ret
=
0
;
u32
total_len
;
u8
hlid
;
bool
is_dummy
;
if
(
!
skb
)
return
-
EINVAL
;
info
=
IEEE80211_SKB_CB
(
skb
);
/* TODO: handle dummy packets on multi-vifs */
is_dummy
=
wl12xx_is_dummy_packet
(
wl
,
skb
);
if
(
info
->
control
.
hw_key
&&
info
->
control
.
hw_key
->
cipher
==
WLAN_CIPHER_SUITE_TKIP
)
extra
=
WL1271_TKIP_IV_SPACE
;
...
...
@@ -405,29 +418,28 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
is_wep
=
(
cipher
==
WLAN_CIPHER_SUITE_WEP40
)
||
(
cipher
==
WLAN_CIPHER_SUITE_WEP104
);
if
(
unlikely
(
is_wep
&&
wl
->
default_key
!=
idx
))
{
ret
=
wl1271_set_default_wep_key
(
wl
,
idx
);
if
(
unlikely
(
is_wep
&&
wl
vif
->
default_key
!=
idx
))
{
ret
=
wl1271_set_default_wep_key
(
wl
,
wlvif
,
idx
);
if
(
ret
<
0
)
return
ret
;
wl
->
default_key
=
idx
;
wl
vif
->
default_key
=
idx
;
}
}
hlid
=
wl1271_tx_get_hlid
(
wl
,
skb
);
hlid
=
wl12xx_tx_get_hlid
(
wl
,
wlvif
,
skb
);
if
(
hlid
==
WL12XX_INVALID_LINK_ID
)
{
wl1271_error
(
"invalid hlid. dropping skb 0x%p"
,
skb
);
return
-
EINVAL
;
}
ret
=
wl1271_tx_allocate
(
wl
,
skb
,
extra
,
buf_offset
,
hlid
);
ret
=
wl1271_tx_allocate
(
wl
,
wlvif
,
skb
,
extra
,
buf_offset
,
hlid
);
if
(
ret
<
0
)
return
ret
;
wl1271_tx_fill_hdr
(
wl
,
skb
,
extra
,
info
,
hlid
);
wl1271_tx_fill_hdr
(
wl
,
wlvif
,
skb
,
extra
,
info
,
hlid
);
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
{
if
(
!
is_dummy
&&
wlvif
&&
wlvif
->
bss_type
==
BSS_TYPE_AP_BSS
)
{
wl1271_tx_ap_update_inconnection_sta
(
wl
,
skb
);
wl1271_tx_regulate_link
(
wl
,
hlid
);
wl1271_tx_regulate_link
(
wl
,
wlvif
,
hlid
);
}
/*
...
...
@@ -444,7 +456,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
memset
(
wl
->
aggr_buf
+
buf_offset
+
skb
->
len
,
0
,
total_len
-
skb
->
len
);
/* Revert side effects in the dummy packet skb, so it can be reused */
if
(
wl12xx_is_dummy_packet
(
wl
,
skb
)
)
if
(
is_dummy
)
skb_pull
(
skb
,
sizeof
(
struct
wl1271_tx_hw_descr
));
return
total_len
;
...
...
@@ -522,19 +534,18 @@ static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl,
return
&
queues
[
q
];
}
static
struct
sk_buff
*
wl1271_sta_skb_dequeue
(
struct
wl1271
*
wl
)
static
struct
sk_buff
*
wl12xx_lnk_skb_dequeue
(
struct
wl1271
*
wl
,
struct
wl1271_link
*
lnk
)
{
struct
sk_buff
*
skb
=
NULL
;
struct
sk_buff
*
skb
;
unsigned
long
flags
;
struct
sk_buff_head
*
queue
;
queue
=
wl1271_select_queue
(
wl
,
wl
->
tx_queue
);
queue
=
wl1271_select_queue
(
wl
,
lnk
->
tx_queue
);
if
(
!
queue
)
goto
out
;
return
NULL
;
skb
=
skb_dequeue
(
queue
);
out:
if
(
skb
)
{
int
q
=
wl1271_tx_get_queue
(
skb_get_queue_mapping
(
skb
));
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
...
...
@@ -545,43 +556,33 @@ static struct sk_buff *wl1271_sta_skb_dequeue(struct wl1271 *wl)
return
skb
;
}
static
struct
sk_buff
*
wl1271_ap_skb_dequeue
(
struct
wl1271
*
wl
)
static
struct
sk_buff
*
wl12xx_vif_skb_dequeue
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
sk_buff
*
skb
=
NULL
;
unsigned
long
flags
;
int
i
,
h
,
start_hlid
;
struct
sk_buff_head
*
queue
;
/* start from the link after the last one */
start_hlid
=
(
wl
->
last_tx_hlid
+
1
)
%
AP
_MAX_LINKS
;
start_hlid
=
(
wl
vif
->
last_tx_hlid
+
1
)
%
WL12XX
_MAX_LINKS
;
/* dequeue according to AC, round robin on each link */
for
(
i
=
0
;
i
<
AP
_MAX_LINKS
;
i
++
)
{
h
=
(
start_hlid
+
i
)
%
AP
_MAX_LINKS
;
for
(
i
=
0
;
i
<
WL12XX
_MAX_LINKS
;
i
++
)
{
h
=
(
start_hlid
+
i
)
%
WL12XX
_MAX_LINKS
;
/* only consider connected stations */
if
(
h
>=
WL1271_AP_STA_HLID_START
&&
!
test_bit
(
h
-
WL1271_AP_STA_HLID_START
,
wl
->
ap_hlid_map
))
if
(
!
test_bit
(
h
,
wlvif
->
links_map
))
continue
;
queue
=
wl1271_select_queue
(
wl
,
wl
->
links
[
h
].
tx_queue
);
if
(
!
queue
)
skb
=
wl12xx_lnk_skb_dequeue
(
wl
,
&
wl
->
links
[
h
]
);
if
(
!
skb
)
continue
;
skb
=
skb_dequeue
(
queue
);
if
(
skb
)
break
;
wlvif
->
last_tx_hlid
=
h
;
break
;
}
if
(
skb
)
{
int
q
=
wl1271_tx_get_queue
(
skb_get_queue_mapping
(
skb
));
wl
->
last_tx_hlid
=
h
;
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
wl
->
tx_queue_count
[
q
]
--
;
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
}
else
{
wl
->
last_tx_hlid
=
0
;
}
if
(
!
skb
)
wlvif
->
last_tx_hlid
=
0
;
return
skb
;
}
...
...
@@ -589,12 +590,32 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl)
static
struct
sk_buff
*
wl1271_skb_dequeue
(
struct
wl1271
*
wl
)
{
unsigned
long
flags
;
struct
wl12xx_vif
*
wlvif
=
wl
->
last_wlvif
;
struct
sk_buff
*
skb
=
NULL
;
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
skb
=
wl1271_ap_skb_dequeue
(
wl
);
else
skb
=
wl1271_sta_skb_dequeue
(
wl
);
if
(
wlvif
)
{
wl12xx_for_each_wlvif_continue
(
wl
,
wlvif
)
{
skb
=
wl12xx_vif_skb_dequeue
(
wl
,
wlvif
);
if
(
skb
)
{
wl
->
last_wlvif
=
wlvif
;
break
;
}
}
}
/* do another pass */
if
(
!
skb
)
{
wl12xx_for_each_wlvif
(
wl
,
wlvif
)
{
skb
=
wl12xx_vif_skb_dequeue
(
wl
,
wlvif
);
if
(
skb
)
{
wl
->
last_wlvif
=
wlvif
;
break
;
}
}
}
if
(
!
skb
)
skb
=
wl12xx_lnk_skb_dequeue
(
wl
,
&
wl
->
links
[
wl
->
system_hlid
]);
if
(
!
skb
&&
test_and_clear_bit
(
WL1271_FLAG_DUMMY_PACKET_PENDING
,
&
wl
->
flags
))
{
...
...
@@ -610,21 +631,21 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl)
return
skb
;
}
static
void
wl1271_skb_queue_head
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
)
static
void
wl1271_skb_queue_head
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
sk_buff
*
skb
)
{
unsigned
long
flags
;
int
q
=
wl1271_tx_get_queue
(
skb_get_queue_mapping
(
skb
));
if
(
wl12xx_is_dummy_packet
(
wl
,
skb
))
{
set_bit
(
WL1271_FLAG_DUMMY_PACKET_PENDING
,
&
wl
->
flags
);
}
else
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
{
u8
hlid
=
wl12
71_tx_get_hlid
(
wl
,
skb
);
}
else
{
u8
hlid
=
wl12
xx_tx_get_hlid
(
wl
,
wlvif
,
skb
);
skb_queue_head
(
&
wl
->
links
[
hlid
].
tx_queue
[
q
],
skb
);
/* make sure we dequeue the same packet next time */
wl
->
last_tx_hlid
=
(
hlid
+
AP_MAX_LINKS
-
1
)
%
AP_MAX_LINKS
;
}
else
{
skb_queue_head
(
&
wl
->
tx_queue
[
q
],
skb
);
wlvif
->
last_tx_hlid
=
(
hlid
+
WL12XX_MAX_LINKS
-
1
)
%
WL12XX_MAX_LINKS
;
}
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
...
...
@@ -639,29 +660,71 @@ static bool wl1271_tx_is_data_present(struct sk_buff *skb)
return
ieee80211_is_data_present
(
hdr
->
frame_control
);
}
void
wl12xx_rearm_rx_streaming
(
struct
wl1271
*
wl
,
unsigned
long
*
active_hlids
)
{
struct
wl12xx_vif
*
wlvif
;
u32
timeout
;
u8
hlid
;
if
(
!
wl
->
conf
.
rx_streaming
.
interval
)
return
;
if
(
!
wl
->
conf
.
rx_streaming
.
always
&&
!
test_bit
(
WL1271_FLAG_SOFT_GEMINI
,
&
wl
->
flags
))
return
;
timeout
=
wl
->
conf
.
rx_streaming
.
duration
;
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
bool
found
=
false
;
for_each_set_bit
(
hlid
,
active_hlids
,
WL12XX_MAX_LINKS
)
{
if
(
test_bit
(
hlid
,
wlvif
->
links_map
))
{
found
=
true
;
break
;
}
}
if
(
!
found
)
continue
;
/* enable rx streaming */
if
(
!
test_bit
(
WLVIF_FLAG_RX_STREAMING_STARTED
,
&
wlvif
->
flags
))
ieee80211_queue_work
(
wl
->
hw
,
&
wlvif
->
rx_streaming_enable_work
);
mod_timer
(
&
wlvif
->
rx_streaming_timer
,
jiffies
+
msecs_to_jiffies
(
timeout
));
}
}
void
wl1271_tx_work_locked
(
struct
wl1271
*
wl
)
{
struct
wl12xx_vif
*
wlvif
;
struct
sk_buff
*
skb
;
struct
wl1271_tx_hw_descr
*
desc
;
u32
buf_offset
=
0
;
bool
sent_packets
=
false
;
bool
had_data
=
false
;
bool
is_ap
=
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
);
unsigned
long
active_hlids
[
BITS_TO_LONGS
(
WL12XX_MAX_LINKS
)]
=
{
0
};
int
ret
;
if
(
unlikely
(
wl
->
state
==
WL1271_STATE_OFF
))
return
;
while
((
skb
=
wl1271_skb_dequeue
(
wl
)))
{
if
(
wl1271_tx_is_data_present
(
skb
))
had_data
=
tru
e
;
struct
ieee80211_tx_info
*
info
=
IEEE80211_SKB_CB
(
skb
);
bool
has_data
=
fals
e
;
ret
=
wl1271_prepare_tx_frame
(
wl
,
skb
,
buf_offset
);
wlvif
=
NULL
;
if
(
!
wl12xx_is_dummy_packet
(
wl
,
skb
)
&&
info
->
control
.
vif
)
wlvif
=
wl12xx_vif_to_data
(
info
->
control
.
vif
);
has_data
=
wlvif
&&
wl1271_tx_is_data_present
(
skb
);
ret
=
wl1271_prepare_tx_frame
(
wl
,
wlvif
,
skb
,
buf_offset
);
if
(
ret
==
-
EAGAIN
)
{
/*
* Aggregation buffer is full.
* Flush buffer and try again.
*/
wl1271_skb_queue_head
(
wl
,
skb
);
wl1271_skb_queue_head
(
wl
,
wlvif
,
skb
);
wl1271_write
(
wl
,
WL1271_SLV_MEM_DATA
,
wl
->
aggr_buf
,
buf_offset
,
true
);
sent_packets
=
true
;
...
...
@@ -672,7 +735,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
* Firmware buffer is full.
* Queue back last skb, and stop aggregating.
*/
wl1271_skb_queue_head
(
wl
,
skb
);
wl1271_skb_queue_head
(
wl
,
wlvif
,
skb
);
/* No work left, avoid scheduling redundant tx work */
set_bit
(
WL1271_FLAG_FW_TX_BUSY
,
&
wl
->
flags
);
goto
out_ack
;
...
...
@@ -682,6 +745,10 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
}
buf_offset
+=
ret
;
wl
->
tx_packets_count
++
;
if
(
has_data
)
{
desc
=
(
struct
wl1271_tx_hw_descr
*
)
skb
->
data
;
__set_bit
(
desc
->
hlid
,
active_hlids
);
}
}
out_ack:
...
...
@@ -701,19 +768,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
wl1271_handle_tx_low_watermark
(
wl
);
}
if
(
!
is_ap
&&
wl
->
conf
.
rx_streaming
.
interval
&&
had_data
&&
(
wl
->
conf
.
rx_streaming
.
always
||
test_bit
(
WL1271_FLAG_SOFT_GEMINI
,
&
wl
->
flags
)))
{
u32
timeout
=
wl
->
conf
.
rx_streaming
.
duration
;
/* enable rx streaming */
if
(
!
test_bit
(
WL1271_FLAG_RX_STREAMING_STARTED
,
&
wl
->
flags
))
ieee80211_queue_work
(
wl
->
hw
,
&
wl
->
rx_streaming_enable_work
);
mod_timer
(
&
wl
->
rx_streaming_timer
,
jiffies
+
msecs_to_jiffies
(
timeout
));
}
wl12xx_rearm_rx_streaming
(
wl
,
active_hlids
);
}
void
wl1271_tx_work
(
struct
work_struct
*
work
)
...
...
@@ -737,6 +792,8 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
struct
wl1271_tx_hw_res_descr
*
result
)
{
struct
ieee80211_tx_info
*
info
;
struct
ieee80211_vif
*
vif
;
struct
wl12xx_vif
*
wlvif
;
struct
sk_buff
*
skb
;
int
id
=
result
->
id
;
int
rate
=
-
1
;
...
...
@@ -756,11 +813,16 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
return
;
}
/* info->control is valid as long as we don't update info->status */
vif
=
info
->
control
.
vif
;
wlvif
=
wl12xx_vif_to_data
(
vif
);
/* update the TX status info */
if
(
result
->
status
==
TX_SUCCESS
)
{
if
(
!
(
info
->
flags
&
IEEE80211_TX_CTL_NO_ACK
))
info
->
flags
|=
IEEE80211_TX_STAT_ACK
;
rate
=
wl1271_rate_to_idx
(
result
->
rate_class_index
,
wl
->
band
);
rate
=
wl1271_rate_to_idx
(
result
->
rate_class_index
,
wlvif
->
band
);
retries
=
result
->
ack_failures
;
}
else
if
(
result
->
status
==
TX_RETRY_EXCEEDED
)
{
wl
->
stats
.
excessive_retries
++
;
...
...
@@ -783,14 +845,14 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
info
->
control
.
hw_key
->
cipher
==
WLAN_CIPHER_SUITE_CCMP
||
info
->
control
.
hw_key
->
cipher
==
WL1271_CIPHER_SUITE_GEM
))
{
u8
fw_lsb
=
result
->
tx_security_sequence_number_lsb
;
u8
cur_lsb
=
wl
->
tx_security_last_seq_lsb
;
u8
cur_lsb
=
wl
vif
->
tx_security_last_seq_lsb
;
/*
* update security sequence number, taking care of potential
* wrap-around
*/
wl
->
tx_security_seq
+=
(
fw_lsb
-
cur_lsb
+
256
)
%
256
;
wl
->
tx_security_last_seq_lsb
=
fw_lsb
;
wl
vif
->
tx_security_seq
+=
(
fw_lsb
-
cur_lsb
)
&
0xff
;
wl
vif
->
tx_security_last_seq_lsb
=
fw_lsb
;
}
/* remove private header from packet */
...
...
@@ -886,39 +948,30 @@ void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid)
}
/* caller must hold wl->mutex and TX must be stopped */
void
wl12
71_tx_reset
(
struct
wl1271
*
wl
,
bool
reset_tx_queues
)
void
wl12
xx_tx_reset_wlvif
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
int
i
;
struct
sk_buff
*
skb
;
struct
ieee80211_tx_info
*
info
;
/* TX failure */
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
{
for
(
i
=
0
;
i
<
AP_MAX_LINKS
;
i
++
)
{
wl1271_free_sta
(
wl
,
i
);
wl1271_tx_reset_link_queues
(
wl
,
i
);
wl
->
links
[
i
].
allocated_pkts
=
0
;
wl
->
links
[
i
].
prev_freed_pkts
=
0
;
}
wl
->
last_tx_hlid
=
0
;
}
else
{
for
(
i
=
0
;
i
<
NUM_TX_QUEUES
;
i
++
)
{
while
((
skb
=
skb_dequeue
(
&
wl
->
tx_queue
[
i
])))
{
wl1271_debug
(
DEBUG_TX
,
"freeing skb 0x%p"
,
skb
);
if
(
!
wl12xx_is_dummy_packet
(
wl
,
skb
))
{
info
=
IEEE80211_SKB_CB
(
skb
);
info
->
status
.
rates
[
0
].
idx
=
-
1
;
info
->
status
.
rates
[
0
].
count
=
0
;
ieee80211_tx_status_ni
(
wl
->
hw
,
skb
);
}
}
}
for_each_set_bit
(
i
,
wlvif
->
links_map
,
WL12XX_MAX_LINKS
)
{
if
(
wlvif
->
bss_type
==
BSS_TYPE_AP_BSS
)
wl1271_free_sta
(
wl
,
wlvif
,
i
);
else
wlvif
->
sta
.
ba_rx_bitmap
=
0
;
wl
->
ba_rx_bitmap
=
0
;
wl1271_tx_reset_link_queues
(
wl
,
i
);
wl
->
links
[
i
].
allocated_pkts
=
0
;
wl
->
links
[
i
].
prev_freed_pkts
=
0
;
}
wlvif
->
last_tx_hlid
=
0
;
}
/* caller must hold wl->mutex and TX must be stopped */
void
wl12xx_tx_reset
(
struct
wl1271
*
wl
,
bool
reset_tx_queues
)
{
int
i
;
struct
sk_buff
*
skb
;
struct
ieee80211_tx_info
*
info
;
for
(
i
=
0
;
i
<
NUM_TX_QUEUES
;
i
++
)
wl
->
tx_queue_count
[
i
]
=
0
;
...
...
drivers/net/wireless/wl12xx/tx.h
View file @
f589cf4f
...
...
@@ -206,18 +206,23 @@ static inline int wl1271_tx_total_queue_count(struct wl1271 *wl)
void
wl1271_tx_work
(
struct
work_struct
*
work
);
void
wl1271_tx_work_locked
(
struct
wl1271
*
wl
);
void
wl1271_tx_complete
(
struct
wl1271
*
wl
);
void
wl1271_tx_reset
(
struct
wl1271
*
wl
,
bool
reset_tx_queues
);
void
wl12xx_tx_reset_wlvif
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
void
wl12xx_tx_reset
(
struct
wl1271
*
wl
,
bool
reset_tx_queues
);
void
wl1271_tx_flush
(
struct
wl1271
*
wl
);
u8
wl1271_rate_to_idx
(
int
rate
,
enum
ieee80211_band
band
);
u32
wl1271_tx_enabled_rates_get
(
struct
wl1271
*
wl
,
u32
rate_set
,
enum
ieee80211_band
rate_band
);
u32
wl1271_tx_min_rate_get
(
struct
wl1271
*
wl
,
u32
rate_set
);
u8
wl12xx_tx_get_hlid_ap
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
);
u8
wl12xx_tx_get_hlid_ap
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
sk_buff
*
skb
);
u8
wl12xx_tx_get_hlid
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
sk_buff
*
skb
);
void
wl1271_tx_reset_link_queues
(
struct
wl1271
*
wl
,
u8
hlid
);
void
wl1271_handle_tx_low_watermark
(
struct
wl1271
*
wl
);
bool
wl12xx_is_dummy_packet
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
);
void
wl12xx_rearm_rx_streaming
(
struct
wl1271
*
wl
,
unsigned
long
*
active_hlids
);
/* from main.c */
void
wl1271_free_sta
(
struct
wl1271
*
wl
,
u8
hlid
);
void
wl1271_free_sta
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
hlid
);
#endif
drivers/net/wireless/wl12xx/wl12xx.h
View file @
f589cf4f
...
...
@@ -35,9 +35,6 @@
#include "conf.h"
#include "ini.h"
#define DRIVER_NAME "wl1271"
#define DRIVER_PREFIX DRIVER_NAME ": "
/*
* FW versions support BA 11n
* versions marks x.x.x.50-60.x
...
...
@@ -45,73 +42,6 @@
#define WL12XX_BA_SUPPORT_FW_COST_VER2_START 50
#define WL12XX_BA_SUPPORT_FW_COST_VER2_END 60
enum
{
DEBUG_NONE
=
0
,
DEBUG_IRQ
=
BIT
(
0
),
DEBUG_SPI
=
BIT
(
1
),
DEBUG_BOOT
=
BIT
(
2
),
DEBUG_MAILBOX
=
BIT
(
3
),
DEBUG_TESTMODE
=
BIT
(
4
),
DEBUG_EVENT
=
BIT
(
5
),
DEBUG_TX
=
BIT
(
6
),
DEBUG_RX
=
BIT
(
7
),
DEBUG_SCAN
=
BIT
(
8
),
DEBUG_CRYPT
=
BIT
(
9
),
DEBUG_PSM
=
BIT
(
10
),
DEBUG_MAC80211
=
BIT
(
11
),
DEBUG_CMD
=
BIT
(
12
),
DEBUG_ACX
=
BIT
(
13
),
DEBUG_SDIO
=
BIT
(
14
),
DEBUG_FILTERS
=
BIT
(
15
),
DEBUG_ADHOC
=
BIT
(
16
),
DEBUG_AP
=
BIT
(
17
),
DEBUG_MASTER
=
(
DEBUG_ADHOC
|
DEBUG_AP
),
DEBUG_ALL
=
~
0
,
};
extern
u32
wl12xx_debug_level
;
#define DEBUG_DUMP_LIMIT 1024
#define wl1271_error(fmt, arg...) \
pr_err(DRIVER_PREFIX "ERROR " fmt "\n", ##arg)
#define wl1271_warning(fmt, arg...) \
pr_warning(DRIVER_PREFIX "WARNING " fmt "\n", ##arg)
#define wl1271_notice(fmt, arg...) \
pr_info(DRIVER_PREFIX fmt "\n", ##arg)
#define wl1271_info(fmt, arg...) \
pr_info(DRIVER_PREFIX fmt "\n", ##arg)
#define wl1271_debug(level, fmt, arg...) \
do { \
if (level & wl12xx_debug_level) \
pr_debug(DRIVER_PREFIX fmt "\n", ##arg); \
} while (0)
/* TODO: use pr_debug_hex_dump when it will be available */
#define wl1271_dump(level, prefix, buf, len) \
do { \
if (level & wl12xx_debug_level) \
print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \
DUMP_PREFIX_OFFSET, 16, 1, \
buf, \
min_t(size_t, len, DEBUG_DUMP_LIMIT), \
0); \
} while (0)
#define wl1271_dump_ascii(level, prefix, buf, len) \
do { \
if (level & wl12xx_debug_level) \
print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \
DUMP_PREFIX_OFFSET, 16, 1, \
buf, \
min_t(size_t, len, DEBUG_DUMP_LIMIT), \
true); \
} while (0)
#define WL127X_FW_NAME "ti-connectivity/wl127x-fw-3.bin"
#define WL128X_FW_NAME "ti-connectivity/wl128x-fw-3.bin"
...
...
@@ -142,15 +72,11 @@ extern u32 wl12xx_debug_level;
#define WL12XX_INVALID_ROLE_ID 0xff
#define WL12XX_INVALID_LINK_ID 0xff
#define WL12XX_MAX_RATE_POLICIES 16
/* Defined by FW as 0. Will not be freed or allocated. */
#define WL12XX_SYSTEM_HLID 0
/*
* TODO: we currently don't support multirole. remove
* this constant from the code when we do.
*/
#define WL1271_AP_STA_HLID_START 3
/*
* When in AP-mode, we allow (at least) this number of packets
* to be transmitted to FW for a STA in PS-mode. Only when packets are
...
...
@@ -236,13 +162,6 @@ struct wl1271_stats {
#define AP_MAX_STATIONS 8
/* Broadcast and Global links + system link + links to stations */
/*
* TODO: when WL1271_AP_STA_HLID_START is no longer constant, change all
* the places that use this.
*/
#define AP_MAX_LINKS (AP_MAX_STATIONS + WL1271_AP_STA_HLID_START)
/* FW status registers */
struct
wl12xx_fw_status
{
__le32
intr
;
...
...
@@ -299,17 +218,14 @@ struct wl1271_scan {
};
struct
wl1271_if_operations
{
void
(
*
read
)(
struct
wl1271
*
wl
,
int
addr
,
void
*
buf
,
size_t
len
,
void
(
*
read
)(
struct
device
*
child
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
);
void
(
*
write
)(
struct
wl1271
*
wl
,
int
addr
,
void
*
buf
,
size_t
len
,
void
(
*
write
)(
struct
device
*
child
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
);
void
(
*
reset
)(
struct
wl1271
*
wl
);
void
(
*
init
)(
struct
wl1271
*
wl
);
int
(
*
power
)(
struct
wl1271
*
wl
,
bool
enable
);
struct
device
*
(
*
dev
)(
struct
wl1271
*
wl
);
void
(
*
enable_irq
)(
struct
wl1271
*
wl
);
void
(
*
disable_irq
)(
struct
wl1271
*
wl
);
void
(
*
set_block_size
)
(
struct
wl1271
*
wl
,
unsigned
int
blksz
);
void
(
*
reset
)(
struct
device
*
child
);
void
(
*
init
)(
struct
device
*
child
);
int
(
*
power
)(
struct
device
*
child
,
bool
enable
);
void
(
*
set_block_size
)
(
struct
device
*
child
,
unsigned
int
blksz
);
};
#define MAX_NUM_KEYS 14
...
...
@@ -326,29 +242,33 @@ struct wl1271_ap_key {
};
enum
wl12xx_flags
{
WL1271_FLAG_STA_ASSOCIATED
,
WL1271_FLAG_IBSS_JOINED
,
WL1271_FLAG_GPIO_POWER
,
WL1271_FLAG_TX_QUEUE_STOPPED
,
WL1271_FLAG_TX_PENDING
,
WL1271_FLAG_IN_ELP
,
WL1271_FLAG_ELP_REQUESTED
,
WL1271_FLAG_PSM
,
WL1271_FLAG_PSM_REQUESTED
,
WL1271_FLAG_IRQ_RUNNING
,
WL1271_FLAG_IDLE
,
WL1271_FLAG_PSPOLL_FAILURE
,
WL1271_FLAG_STA_STATE_SENT
,
WL1271_FLAG_FW_TX_BUSY
,
WL1271_FLAG_AP_STARTED
,
WL1271_FLAG_IF_INITIALIZED
,
WL1271_FLAG_DUMMY_PACKET_PENDING
,
WL1271_FLAG_SUSPENDED
,
WL1271_FLAG_PENDING_WORK
,
WL1271_FLAG_SOFT_GEMINI
,
WL1271_FLAG_RX_STREAMING_STARTED
,
WL1271_FLAG_RECOVERY_IN_PROGRESS
,
WL1271_FLAG_CS_PROGRESS
,
};
enum
wl12xx_vif_flags
{
WLVIF_FLAG_INITIALIZED
,
WLVIF_FLAG_STA_ASSOCIATED
,
WLVIF_FLAG_IBSS_JOINED
,
WLVIF_FLAG_AP_STARTED
,
WLVIF_FLAG_PSM
,
WLVIF_FLAG_PSM_REQUESTED
,
WLVIF_FLAG_STA_STATE_SENT
,
WLVIF_FLAG_RX_STREAMING_STARTED
,
WLVIF_FLAG_PSPOLL_FAILURE
,
WLVIF_FLAG_CS_PROGRESS
,
WLVIF_FLAG_AP_PROBE_RESP_SET
,
};
struct
wl1271_link
{
...
...
@@ -366,10 +286,11 @@ struct wl1271_link {
};
struct
wl1271
{
struct
platform_device
*
plat_dev
;
struct
ieee80211_hw
*
hw
;
bool
mac80211_registered
;
struct
device
*
dev
;
void
*
if_priv
;
struct
wl1271_if_operations
*
if_ops
;
...
...
@@ -399,25 +320,20 @@ struct wl1271 {
s8
hw_pg_ver
;
u8
bssid
[
ETH_ALEN
];
u8
mac_addr
[
ETH_ALEN
];
u8
bss_type
;
u8
set_bss_type
;
u8
p2p
;
/* we are using p2p role */
u8
ssid
[
IEEE80211_MAX_SSID_LEN
+
1
];
u8
ssid_len
;
int
channel
;
u8
role_id
;
u8
dev_role_id
;
u8
system_hlid
;
u8
sta_hlid
;
u8
dev_hlid
;
u8
ap_global_hlid
;
u8
ap_bcast_hlid
;
unsigned
long
links_map
[
BITS_TO_LONGS
(
WL12XX_MAX_LINKS
)];
unsigned
long
roles_map
[
BITS_TO_LONGS
(
WL12XX_MAX_ROLES
)];
unsigned
long
roc_map
[
BITS_TO_LONGS
(
WL12XX_MAX_ROLES
)];
unsigned
long
rate_policies_map
[
BITS_TO_LONGS
(
WL12XX_MAX_RATE_POLICIES
)];
struct
list_head
wlvif_list
;
u8
sta_count
;
u8
ap_count
;
struct
wl1271_acx_mem_map
*
target_mem_map
;
...
...
@@ -440,11 +356,7 @@ struct wl1271 {
/* Time-offset between host and chipset clocks */
s64
time_offset
;
/* Session counter for the chipset */
int
session_counter
;
/* Frames scheduled for transmission, not handled yet */
struct
sk_buff_head
tx_queue
[
NUM_TX_QUEUES
];
int
tx_queue_count
[
NUM_TX_QUEUES
];
long
stopped_queues_map
;
...
...
@@ -462,17 +374,6 @@ struct wl1271 {
struct
sk_buff
*
tx_frames
[
ACX_TX_DESCRIPTORS
];
int
tx_frames_cnt
;
/*
* Security sequence number
* bits 0-15: lower 16 bits part of sequence number
* bits 16-47: higher 32 bits part of sequence number
* bits 48-63: not in use
*/
u64
tx_security_seq
;
/* 8 bits of the last sequence number in use */
u8
tx_security_last_seq_lsb
;
/* FW Rx counter */
u32
rx_counter
;
...
...
@@ -507,59 +408,21 @@ struct wl1271 {
u32
mbox_ptr
[
2
];
/* Are we currently scanning */
struct
ieee80211_vif
*
scan_vif
;
struct
wl1271_scan
scan
;
struct
delayed_work
scan_complete_work
;
bool
sched_scanning
;
/* probe-req template for the current AP */
struct
sk_buff
*
probereq
;
/* Our association ID */
u16
aid
;
/*
* currently configured rate set:
* bits 0-15 - 802.11abg rates
* bits 16-23 - 802.11n MCS index mask
* support only 1 stream, thus only 8 bits for the MCS rates (0-7).
*/
u32
basic_rate_set
;
u32
basic_rate
;
u32
rate_set
;
u32
bitrate_masks
[
IEEE80211_NUM_BANDS
];
/* The current band */
enum
ieee80211_band
band
;
/* Beaconing interval (needed for ad-hoc) */
u32
beacon_int
;
/* Default key (for WEP) */
u32
default_key
;
/* Rx Streaming */
struct
work_struct
rx_streaming_enable_work
;
struct
work_struct
rx_streaming_disable_work
;
struct
timer_list
rx_streaming_timer
;
struct
completion
*
elp_compl
;
struct
completion
*
ps_compl
;
struct
delayed_work
elp_work
;
struct
delayed_work
pspoll_work
;
/* counter for ps-poll delivery failures */
int
ps_poll_failures
;
/* retry counter for PSM entries */
u8
psm_entry_retry
;
/* in dBm */
int
power_level
;
int
rssi_thold
;
int
last_rssi_event
;
struct
wl1271_stats
stats
;
__le32
buffer_32
;
...
...
@@ -583,20 +446,9 @@ struct wl1271 {
/* Most recently reported noise in dBm */
s8
noise
;
/* map for HLIDs of associated stations - when operating in AP mode */
unsigned
long
ap_hlid_map
[
BITS_TO_LONGS
(
AP_MAX_STATIONS
)];
/* recoreded keys for AP-mode - set here before AP startup */
struct
wl1271_ap_key
*
recorded_ap_keys
[
MAX_NUM_KEYS
];
/* bands supported by this instance of wl12xx */
struct
ieee80211_supported_band
bands
[
IEEE80211_NUM_BANDS
];
/* RX BA constraint value */
bool
ba_support
;
u8
ba_rx_bitmap
;
bool
ba_allowed
;
int
tcxo_clock
;
/*
...
...
@@ -610,10 +462,7 @@ struct wl1271 {
* AP-mode - links indexed by HLID. The global and broadcast links
* are always active.
*/
struct
wl1271_link
links
[
AP_MAX_LINKS
];
/* the hlid of the link where the last transmitted skb came from */
int
last_tx_hlid
;
struct
wl1271_link
links
[
WL12XX_MAX_LINKS
];
/* AP-mode - a bitmap of links currently in PS mode according to FW */
u32
ap_fw_ps_map
;
...
...
@@ -632,21 +481,173 @@ struct wl1271 {
/* AP-mode - number of currently connected stations */
int
active_sta_count
;
/* last wlvif we transmitted from */
struct
wl12xx_vif
*
last_wlvif
;
};
struct
wl1271_station
{
u8
hlid
;
};
struct
wl12xx_vif
{
struct
wl1271
*
wl
;
struct
list_head
list
;
unsigned
long
flags
;
u8
bss_type
;
u8
p2p
;
/* we are using p2p role */
u8
role_id
;
/* sta/ibss specific */
u8
dev_role_id
;
u8
dev_hlid
;
union
{
struct
{
u8
hlid
;
u8
ba_rx_bitmap
;
u8
basic_rate_idx
;
u8
ap_rate_idx
;
u8
p2p_rate_idx
;
}
sta
;
struct
{
u8
global_hlid
;
u8
bcast_hlid
;
/* HLIDs bitmap of associated stations */
unsigned
long
sta_hlid_map
[
BITS_TO_LONGS
(
WL12XX_MAX_LINKS
)];
/* recoreded keys - set here before AP startup */
struct
wl1271_ap_key
*
recorded_keys
[
MAX_NUM_KEYS
];
u8
mgmt_rate_idx
;
u8
bcast_rate_idx
;
u8
ucast_rate_idx
[
CONF_TX_MAX_AC_COUNT
];
}
ap
;
};
/* the hlid of the last transmitted skb */
int
last_tx_hlid
;
unsigned
long
links_map
[
BITS_TO_LONGS
(
WL12XX_MAX_LINKS
)];
u8
ssid
[
IEEE80211_MAX_SSID_LEN
+
1
];
u8
ssid_len
;
/* The current band */
enum
ieee80211_band
band
;
int
channel
;
u32
bitrate_masks
[
IEEE80211_NUM_BANDS
];
u32
basic_rate_set
;
/*
* currently configured rate set:
* bits 0-15 - 802.11abg rates
* bits 16-23 - 802.11n MCS index mask
* support only 1 stream, thus only 8 bits for the MCS rates (0-7).
*/
u32
basic_rate
;
u32
rate_set
;
/* probe-req template for the current AP */
struct
sk_buff
*
probereq
;
/* Beaconing interval (needed for ad-hoc) */
u32
beacon_int
;
/* Default key (for WEP) */
u32
default_key
;
/* Our association ID */
u16
aid
;
/* Session counter for the chipset */
int
session_counter
;
struct
completion
*
ps_compl
;
struct
delayed_work
pspoll_work
;
/* counter for ps-poll delivery failures */
int
ps_poll_failures
;
/* retry counter for PSM entries */
u8
psm_entry_retry
;
/* in dBm */
int
power_level
;
int
rssi_thold
;
int
last_rssi_event
;
/* RX BA constraint value */
bool
ba_support
;
bool
ba_allowed
;
/* Rx Streaming */
struct
work_struct
rx_streaming_enable_work
;
struct
work_struct
rx_streaming_disable_work
;
struct
timer_list
rx_streaming_timer
;
/*
* This struct must be last!
* data that has to be saved acrossed reconfigs (e.g. recovery)
* should be declared in this struct.
*/
struct
{
u8
persistent
[
0
];
/*
* Security sequence number
* bits 0-15: lower 16 bits part of sequence number
* bits 16-47: higher 32 bits part of sequence number
* bits 48-63: not in use
*/
u64
tx_security_seq
;
/* 8 bits of the last sequence number in use */
u8
tx_security_last_seq_lsb
;
};
};
static
inline
struct
wl12xx_vif
*
wl12xx_vif_to_data
(
struct
ieee80211_vif
*
vif
)
{
return
(
struct
wl12xx_vif
*
)
vif
->
drv_priv
;
}
static
inline
struct
ieee80211_vif
*
wl12xx_wlvif_to_vif
(
struct
wl12xx_vif
*
wlvif
)
{
return
container_of
((
void
*
)
wlvif
,
struct
ieee80211_vif
,
drv_priv
);
}
#define wl12xx_for_each_wlvif(wl, wlvif) \
list_for_each_entry(wlvif, &wl->wlvif_list, list)
#define wl12xx_for_each_wlvif_continue(wl, wlvif) \
list_for_each_entry_continue(wlvif, &wl->wlvif_list, list)
#define wl12xx_for_each_wlvif_bss_type(wl, wlvif, _bss_type) \
wl12xx_for_each_wlvif(wl, wlvif) \
if (wlvif->bss_type == _bss_type)
#define wl12xx_for_each_wlvif_sta(wl, wlvif) \
wl12xx_for_each_wlvif_bss_type(wl, wlvif, BSS_TYPE_STA_BSS)
#define wl12xx_for_each_wlvif_ap(wl, wlvif) \
wl12xx_for_each_wlvif_bss_type(wl, wlvif, BSS_TYPE_AP_BSS)
int
wl1271_plt_start
(
struct
wl1271
*
wl
);
int
wl1271_plt_stop
(
struct
wl1271
*
wl
);
int
wl1271_recalc_rx_streaming
(
struct
wl1271
*
wl
);
int
wl1271_recalc_rx_streaming
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
void
wl12xx_queue_recovery_work
(
struct
wl1271
*
wl
);
size_t
wl12xx_copy_fwlog
(
struct
wl1271
*
wl
,
u8
*
memblock
,
size_t
maxlen
);
#define JOIN_TIMEOUT 5000
/* 5000 milliseconds to join */
#define SESSION_COUNTER_MAX 7
/* maximum value for the session counter */
#define SESSION_COUNTER_MAX 6
/* maximum value for the session counter */
#define SESSION_COUNTER_INVALID 7
/* used with dummy_packet */
#define WL1271_DEFAULT_POWER_LEVEL 0
...
...
@@ -669,8 +670,8 @@ size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen);
/* Each RX/TX transaction requires an end-of-transaction transfer */
#define WL12XX_QUIRK_END_OF_TRANSACTION BIT(0)
/*
WL128X requires aggregated packets to be aligned to the SDIO block size
*/
#define WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT BIT(2)
/*
wl127x and SPI don't support SDIO block size alignment
*/
#define WL12XX_QUIRK_
NO_
BLOCKSIZE_ALIGNMENT BIT(2)
/* Older firmwares did not implement the FW logger over bus feature */
#define WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED BIT(4)
...
...
drivers/net/wireless/wl12xx/wl12xx_80211.h
View file @
f589cf4f
...
...
@@ -116,11 +116,6 @@ struct wl12xx_ps_poll_template {
u8
ta
[
ETH_ALEN
];
}
__packed
;
struct
wl12xx_qos_null_data_template
{
struct
ieee80211_header
header
;
__le16
qos_ctl
;
}
__packed
;
struct
wl12xx_arp_rsp_template
{
struct
ieee80211_hdr_3addr
hdr
;
...
...
drivers/net/wireless/wl12xx/wl12xx_platform_data.c
View file @
f589cf4f
...
...
@@ -2,7 +2,7 @@
#include <linux/err.h>
#include <linux/wl12xx.h>
static
const
struct
wl12xx_platform_data
*
platform_data
;
static
struct
wl12xx_platform_data
*
platform_data
;
int
__init
wl12xx_set_platform_data
(
const
struct
wl12xx_platform_data
*
data
)
{
...
...
@@ -18,7 +18,7 @@ int __init wl12xx_set_platform_data(const struct wl12xx_platform_data *data)
return
0
;
}
const
struct
wl12xx_platform_data
*
wl12xx_get_platform_data
(
void
)
struct
wl12xx_platform_data
*
wl12xx_get_platform_data
(
void
)
{
if
(
!
platform_data
)
return
ERR_PTR
(
-
ENODEV
);
...
...
include/linux/wl12xx.h
View file @
f589cf4f
...
...
@@ -54,6 +54,9 @@ struct wl12xx_platform_data {
int
board_ref_clock
;
int
board_tcxo_clock
;
unsigned
long
platform_quirks
;
bool
pwr_in_suspend
;
struct
wl1271_if_operations
*
ops
;
};
/* Platform does not support level trigger interrupts */
...
...
@@ -73,6 +76,6 @@ int wl12xx_set_platform_data(const struct wl12xx_platform_data *data)
#endif
const
struct
wl12xx_platform_data
*
wl12xx_get_platform_data
(
void
);
struct
wl12xx_platform_data
*
wl12xx_get_platform_data
(
void
);
#endif
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