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
nexedi
linux
Commits
8715d941
Commit
8715d941
authored
Feb 22, 2012
by
John W. Linville
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-linville' of
git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx
parents
ca994a36
51c4ed95
Changes
33
Show whitespace changes
Inline
Side-by-side
Showing
33 changed files
with
1386 additions
and
798 deletions
+1386
-798
drivers/net/wireless/wl1251/Makefile
drivers/net/wireless/wl1251/Makefile
+2
-0
drivers/net/wireless/wl1251/boot.c
drivers/net/wireless/wl1251/boot.c
+0
-2
drivers/net/wireless/wl1251/io.h
drivers/net/wireless/wl1251/io.h
+4
-5
drivers/net/wireless/wl1251/wl1251.h
drivers/net/wireless/wl1251/wl1251.h
+1
-1
drivers/net/wireless/wl12xx/Makefile
drivers/net/wireless/wl12xx/Makefile
+2
-0
drivers/net/wireless/wl12xx/acx.c
drivers/net/wireless/wl12xx/acx.c
+11
-6
drivers/net/wireless/wl12xx/acx.h
drivers/net/wireless/wl12xx/acx.h
+77
-72
drivers/net/wireless/wl12xx/boot.c
drivers/net/wireless/wl12xx/boot.c
+15
-90
drivers/net/wireless/wl12xx/boot.h
drivers/net/wireless/wl12xx/boot.h
+0
-10
drivers/net/wireless/wl12xx/cmd.c
drivers/net/wireless/wl12xx/cmd.c
+105
-38
drivers/net/wireless/wl12xx/cmd.h
drivers/net/wireless/wl12xx/cmd.h
+82
-66
drivers/net/wireless/wl12xx/conf.h
drivers/net/wireless/wl12xx/conf.h
+43
-8
drivers/net/wireless/wl12xx/debug.h
drivers/net/wireless/wl12xx/debug.h
+1
-0
drivers/net/wireless/wl12xx/debugfs.c
drivers/net/wireless/wl12xx/debugfs.c
+239
-2
drivers/net/wireless/wl12xx/event.c
drivers/net/wireless/wl12xx/event.c
+2
-152
drivers/net/wireless/wl12xx/event.h
drivers/net/wireless/wl12xx/event.h
+12
-8
drivers/net/wireless/wl12xx/init.c
drivers/net/wireless/wl12xx/init.c
+36
-19
drivers/net/wireless/wl12xx/io.c
drivers/net/wireless/wl12xx/io.c
+59
-0
drivers/net/wireless/wl12xx/io.h
drivers/net/wireless/wl12xx/io.h
+2
-0
drivers/net/wireless/wl12xx/main.c
drivers/net/wireless/wl12xx/main.c
+466
-208
drivers/net/wireless/wl12xx/ps.c
drivers/net/wireless/wl12xx/ps.c
+24
-10
drivers/net/wireless/wl12xx/ps.h
drivers/net/wireless/wl12xx/ps.h
+1
-1
drivers/net/wireless/wl12xx/reg.h
drivers/net/wireless/wl12xx/reg.h
+27
-0
drivers/net/wireless/wl12xx/rx.c
drivers/net/wireless/wl12xx/rx.c
+1
-1
drivers/net/wireless/wl12xx/scan.c
drivers/net/wireless/wl12xx/scan.c
+30
-26
drivers/net/wireless/wl12xx/scan.h
drivers/net/wireless/wl12xx/scan.h
+1
-1
drivers/net/wireless/wl12xx/sdio.c
drivers/net/wireless/wl12xx/sdio.c
+16
-13
drivers/net/wireless/wl12xx/spi.c
drivers/net/wireless/wl12xx/spi.c
+6
-2
drivers/net/wireless/wl12xx/testmode.c
drivers/net/wireless/wl12xx/testmode.c
+50
-0
drivers/net/wireless/wl12xx/tx.c
drivers/net/wireless/wl12xx/tx.c
+34
-41
drivers/net/wireless/wl12xx/tx.h
drivers/net/wireless/wl12xx/tx.h
+4
-1
drivers/net/wireless/wl12xx/wl12xx.h
drivers/net/wireless/wl12xx/wl12xx.h
+32
-14
drivers/net/wireless/wl12xx/wl12xx_80211.h
drivers/net/wireless/wl12xx/wl12xx_80211.h
+1
-1
No files found.
drivers/net/wireless/wl1251/Makefile
View file @
8715d941
...
...
@@ -6,3 +6,5 @@ wl1251_sdio-objs += sdio.o
obj-$(CONFIG_WL1251)
+=
wl1251.o
obj-$(CONFIG_WL1251_SPI)
+=
wl1251_spi.o
obj-$(CONFIG_WL1251_SDIO)
+=
wl1251_sdio.o
ccflags-y
+=
-D__CHECK_ENDIAN__
drivers/net/wireless/wl1251/boot.c
View file @
8715d941
...
...
@@ -464,8 +464,6 @@ static int wl1251_boot_upload_nvs(struct wl1251 *wl)
val
=
(
nvs_ptr
[
0
]
|
(
nvs_ptr
[
1
]
<<
8
)
|
(
nvs_ptr
[
2
]
<<
16
)
|
(
nvs_ptr
[
3
]
<<
24
));
val
=
cpu_to_le32
(
val
);
wl1251_debug
(
DEBUG_BOOT
,
"nvs write table 0x%x: 0x%x"
,
nvs_start
,
val
);
...
...
drivers/net/wireless/wl1251/io.h
View file @
8715d941
...
...
@@ -36,16 +36,15 @@
static
inline
u32
wl1251_read32
(
struct
wl1251
*
wl
,
int
addr
)
{
u32
response
;
wl
->
if_ops
->
read
(
wl
,
addr
,
&
response
,
sizeof
(
u32
));
wl
->
if_ops
->
read
(
wl
,
addr
,
&
wl
->
buffer_32
,
sizeof
(
wl
->
buffer_32
));
return
response
;
return
le32_to_cpu
(
wl
->
buffer_32
)
;
}
static
inline
void
wl1251_write32
(
struct
wl1251
*
wl
,
int
addr
,
u32
val
)
{
wl
->
if_ops
->
write
(
wl
,
addr
,
&
val
,
sizeof
(
u32
));
wl
->
buffer_32
=
cpu_to_le32
(
val
);
wl
->
if_ops
->
write
(
wl
,
addr
,
&
wl
->
buffer_32
,
sizeof
(
wl
->
buffer_32
));
}
static
inline
u32
wl1251_read_elp
(
struct
wl1251
*
wl
,
int
addr
)
...
...
drivers/net/wireless/wl1251/wl1251.h
View file @
8715d941
...
...
@@ -380,7 +380,7 @@ struct wl1251 {
struct
wl1251_stats
stats
;
struct
wl1251_debugfs
debugfs
;
u
32
buffer_32
;
__le
32
buffer_32
;
u32
buffer_cmd
;
u8
buffer_busyword
[
WL1251_BUSY_WORD_LEN
];
struct
wl1251_rx_descriptor
*
rx_descriptor
;
...
...
drivers/net/wireless/wl12xx/Makefile
View file @
8715d941
...
...
@@ -11,3 +11,5 @@ obj-$(CONFIG_WL12XX_SDIO) += wl12xx_sdio.o
# small builtin driver bit
obj-$(CONFIG_WL12XX_PLATFORM_DATA)
+=
wl12xx_platform_data.o
ccflags-y
+=
-D__CHECK_ENDIAN__
drivers/net/wireless/wl12xx/acx.c
View file @
8715d941
...
...
@@ -34,12 +34,14 @@
#include "reg.h"
#include "ps.h"
int
wl1271_acx_wake_up_conditions
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
int
wl1271_acx_wake_up_conditions
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
wake_up_event
,
u8
listen_interval
)
{
struct
acx_wake_up_condition
*
wake_up
;
int
ret
;
wl1271_debug
(
DEBUG_ACX
,
"acx wake up conditions"
);
wl1271_debug
(
DEBUG_ACX
,
"acx wake up conditions (wake_up_event %d listen_interval %d)"
,
wake_up_event
,
listen_interval
);
wake_up
=
kzalloc
(
sizeof
(
*
wake_up
),
GFP_KERNEL
);
if
(
!
wake_up
)
{
...
...
@@ -48,8 +50,8 @@ int wl1271_acx_wake_up_conditions(struct wl1271 *wl, struct wl12xx_vif *wlvif)
}
wake_up
->
role_id
=
wlvif
->
role_id
;
wake_up
->
wake_up_event
=
w
l
->
conf
.
conn
.
w
ake_up_event
;
wake_up
->
listen_interval
=
wl
->
conf
.
conn
.
listen_interval
;
wake_up
->
wake_up_event
=
wake_up_event
;
wake_up
->
listen_interval
=
listen_interval
;
ret
=
wl1271_cmd_configure
(
wl
,
ACX_WAKE_UP_CONDITIONS
,
wake_up
,
sizeof
(
*
wake_up
));
...
...
@@ -1459,9 +1461,10 @@ int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
return
ret
;
}
int
wl1271_acx_tsf_info
(
struct
wl1271
*
wl
,
u64
*
mactime
)
int
wl12xx_acx_tsf_info
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u64
*
mactime
)
{
struct
wl12
71
_acx_fw_tsf_information
*
tsf_info
;
struct
wl12
xx
_acx_fw_tsf_information
*
tsf_info
;
int
ret
;
tsf_info
=
kzalloc
(
sizeof
(
*
tsf_info
),
GFP_KERNEL
);
...
...
@@ -1470,6 +1473,8 @@ int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime)
goto
out
;
}
tsf_info
->
role_id
=
wlvif
->
role_id
;
ret
=
wl1271_cmd_interrogate
(
wl
,
ACX_TSF_INFO
,
tsf_info
,
sizeof
(
*
tsf_info
));
if
(
ret
<
0
)
{
...
...
drivers/net/wireless/wl12xx/acx.h
View file @
8715d941
...
...
@@ -995,15 +995,17 @@ struct wl1271_acx_ba_receiver_setup {
u8
padding
[
2
];
}
__packed
;
struct
wl12
71
_acx_fw_tsf_information
{
struct
wl12
xx
_acx_fw_tsf_information
{
struct
acx_header
header
;
u8
role_id
;
u8
padding1
[
3
];
__le32
current_tsf_high
;
__le32
current_tsf_low
;
__le32
last_bttt_high
;
__le32
last_tbtt_low
;
u8
last_dtim_count
;
u8
padding
[
3
];
u8
padding
2
[
3
];
}
__packed
;
struct
wl1271_acx_ps_rx_streaming
{
...
...
@@ -1151,79 +1153,81 @@ struct wl12xx_acx_config_hangover {
}
__packed
;
enum
{
ACX_WAKE_UP_CONDITIONS
=
0x0002
,
ACX_MEM_CFG
=
0x0003
,
ACX_SLOT
=
0x0004
,
ACX_AC_CFG
=
0x0007
,
ACX_MEM_MAP
=
0x0008
,
ACX_AID
=
0x000A
,
ACX_MEDIUM_USAGE
=
0x000F
,
ACX_TX_QUEUE_CFG
=
0x0011
,
/* FIXME: only used by wl1251 */
ACX_STATISTICS
=
0x0013
,
/* Debug API */
ACX_PWR_CONSUMPTION_STATISTICS
=
0x0014
,
ACX_FEATURE_CFG
=
0x0015
,
ACX_TID_CFG
=
0x001A
,
ACX_PS_RX_STREAMING
=
0x001B
,
ACX_BEACON_FILTER_OPT
=
0x001F
,
ACX_NOISE_HIST
=
0x0021
,
ACX_HDK_VERSION
=
0x0022
,
/* ??? */
ACX_PD_THRESHOLD
=
0x0023
,
ACX_TX_CONFIG_OPT
=
0x0024
,
ACX_CCA_THRESHOLD
=
0x0025
,
ACX_EVENT_MBOX_MASK
=
0x0026
,
ACX_CONN_MONIT_PARAMS
=
0x002D
,
ACX_BCN_DTIM_OPTIONS
=
0x0031
,
ACX_SG_ENABLE
=
0x0032
,
ACX_SG_CFG
=
0x0033
,
ACX_FM_COEX_CFG
=
0x0034
,
ACX_BEACON_FILTER_TABLE
=
0x0038
,
ACX_ARP_IP_FILTER
=
0x0039
,
ACX_ROAMING_STATISTICS_TBL
=
0x003B
,
ACX_RATE_POLICY
=
0x003D
,
ACX_CTS_PROTECTION
=
0x003E
,
ACX_SLEEP_AUTH
=
0x003F
,
ACX_PREAMBLE_TYPE
=
0x0040
,
ACX_ERROR_CNT
=
0x0041
,
ACX_IBSS_FILTER
=
0x0044
,
ACX_SERVICE_PERIOD_TIMEOUT
=
0x0045
,
ACX_TSF_INFO
=
0x0046
,
ACX_CONFIG_PS_WMM
=
0x0049
,
ACX_ENABLE_RX_DATA_FILTER
=
0x004A
,
ACX_SET_RX_DATA_FILTER
=
0x004B
,
ACX_GET_DATA_FILTER_STATISTICS
=
0x004C
,
ACX_RX_CONFIG_OPT
=
0x004E
,
ACX_FRAG_CFG
=
0x004F
,
ACX_BET_ENABLE
=
0x0050
,
ACX_RSSI_SNR_TRIGGER
=
0x0051
,
ACX_RSSI_SNR_WEIGHTS
=
0x0052
,
ACX_KEEP_ALIVE_MODE
=
0x0053
,
ACX_SET_KEEP_ALIVE_CONFIG
=
0x0054
,
ACX_BA_SESSION_INIT_POLICY
=
0x0055
,
ACX_BA_SESSION_RX_SETUP
=
0x0056
,
ACX_PEER_HT_CAP
=
0x0057
,
ACX_HT_BSS_OPERATION
=
0x0058
,
ACX_COEX_ACTIVITY
=
0x0059
,
ACX_BURST_MODE
=
0x005C
,
ACX_SET_RATE_MGMT_PARAMS
=
0x005D
,
ACX_SET_RATE_ADAPT_PARAMS
=
0x0060
,
ACX_SET_DCO_ITRIM_PARAMS
=
0x0061
,
ACX_GEN_FW_CMD
=
0x0070
,
ACX_HOST_IF_CFG_BITMAP
=
0x0071
,
ACX_MAX_TX_FAILURE
=
0x0072
,
ACX_UPDATE_INCONNECTION_STA_LIST
=
0x0073
,
DOT11_RX_MSDU_LIFE_TIME
=
0x1004
,
DOT11_CUR_TX_PWR
=
0x100D
,
DOT11_RX_DOT11_MODE
=
0x1012
,
DOT11_RTS_THRESHOLD
=
0x1013
,
DOT11_GROUP_ADDRESS_TBL
=
0x1014
,
ACX_PM_CONFIG
=
0x1016
,
ACX_CONFIG_PS
=
0x1017
,
ACX_CONFIG_HANGOVER
=
0x1018
,
ACX_WAKE_UP_CONDITIONS
=
0x0000
,
ACX_MEM_CFG
=
0x0001
,
ACX_SLOT
=
0x0002
,
ACX_AC_CFG
=
0x0003
,
ACX_MEM_MAP
=
0x0004
,
ACX_AID
=
0x0005
,
ACX_MEDIUM_USAGE
=
0x0006
,
ACX_STATISTICS
=
0x0007
,
ACX_PWR_CONSUMPTION_STATISTICS
=
0x0008
,
ACX_TID_CFG
=
0x0009
,
ACX_PS_RX_STREAMING
=
0x000A
,
ACX_BEACON_FILTER_OPT
=
0x000B
,
ACX_NOISE_HIST
=
0x000C
,
ACX_HDK_VERSION
=
0x000D
,
ACX_PD_THRESHOLD
=
0x000E
,
ACX_TX_CONFIG_OPT
=
0x000F
,
ACX_CCA_THRESHOLD
=
0x0010
,
ACX_EVENT_MBOX_MASK
=
0x0011
,
ACX_CONN_MONIT_PARAMS
=
0x0012
,
ACX_DISABLE_BROADCASTS
=
0x0013
,
ACX_BCN_DTIM_OPTIONS
=
0x0014
,
ACX_SG_ENABLE
=
0x0015
,
ACX_SG_CFG
=
0x0016
,
ACX_FM_COEX_CFG
=
0x0017
,
ACX_BEACON_FILTER_TABLE
=
0x0018
,
ACX_ARP_IP_FILTER
=
0x0019
,
ACX_ROAMING_STATISTICS_TBL
=
0x001A
,
ACX_RATE_POLICY
=
0x001B
,
ACX_CTS_PROTECTION
=
0x001C
,
ACX_SLEEP_AUTH
=
0x001D
,
ACX_PREAMBLE_TYPE
=
0x001E
,
ACX_ERROR_CNT
=
0x001F
,
ACX_IBSS_FILTER
=
0x0020
,
ACX_SERVICE_PERIOD_TIMEOUT
=
0x0021
,
ACX_TSF_INFO
=
0x0022
,
ACX_CONFIG_PS_WMM
=
0x0023
,
ACX_ENABLE_RX_DATA_FILTER
=
0x0024
,
ACX_SET_RX_DATA_FILTER
=
0x0025
,
ACX_GET_DATA_FILTER_STATISTICS
=
0x0026
,
ACX_RX_CONFIG_OPT
=
0x0027
,
ACX_FRAG_CFG
=
0x0028
,
ACX_BET_ENABLE
=
0x0029
,
ACX_RSSI_SNR_TRIGGER
=
0x002A
,
ACX_RSSI_SNR_WEIGHTS
=
0x002B
,
ACX_KEEP_ALIVE_MODE
=
0x002C
,
ACX_SET_KEEP_ALIVE_CONFIG
=
0x002D
,
ACX_BA_SESSION_INIT_POLICY
=
0x002E
,
ACX_BA_SESSION_RX_SETUP
=
0x002F
,
ACX_PEER_HT_CAP
=
0x0030
,
ACX_HT_BSS_OPERATION
=
0x0031
,
ACX_COEX_ACTIVITY
=
0x0032
,
ACX_BURST_MODE
=
0x0033
,
ACX_SET_RATE_MGMT_PARAMS
=
0x0034
,
ACX_GET_RATE_MGMT_PARAMS
=
0x0035
,
ACX_SET_RATE_ADAPT_PARAMS
=
0x0036
,
ACX_SET_DCO_ITRIM_PARAMS
=
0x0037
,
ACX_GEN_FW_CMD
=
0x0038
,
ACX_HOST_IF_CFG_BITMAP
=
0x0039
,
ACX_MAX_TX_FAILURE
=
0x003A
,
ACX_UPDATE_INCONNECTION_STA_LIST
=
0x003B
,
DOT11_RX_MSDU_LIFE_TIME
=
0x003C
,
DOT11_CUR_TX_PWR
=
0x003D
,
DOT11_RTS_THRESHOLD
=
0x003E
,
DOT11_GROUP_ADDRESS_TBL
=
0x003F
,
ACX_PM_CONFIG
=
0x0040
,
ACX_CONFIG_PS
=
0x0041
,
ACX_CONFIG_HANGOVER
=
0x0042
,
ACX_FEATURE_CFG
=
0x0043
,
ACX_PROTECTION_CFG
=
0x0044
,
};
int
wl1271_acx_wake_up_conditions
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
struct
wl12xx_vif
*
wlvif
,
u8
wake_up_event
,
u8
listen_interval
);
int
wl1271_acx_sleep_auth
(
struct
wl1271
*
wl
,
u8
sleep_auth
);
int
wl1271_acx_tx_power
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
int
power
);
...
...
@@ -1296,7 +1300,8 @@ 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
wl12xx_acx_tsf_info
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u64
*
mactime
);
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
);
...
...
drivers/net/wireless/wl12xx/boot.c
View file @
8715d941
...
...
@@ -33,65 +33,6 @@
#include "event.h"
#include "rx.h"
static
struct
wl1271_partition_set
part_table
[
PART_TABLE_LEN
]
=
{
[
PART_DOWN
]
=
{
.
mem
=
{
.
start
=
0x00000000
,
.
size
=
0x000177c0
},
.
reg
=
{
.
start
=
REGISTERS_BASE
,
.
size
=
0x00008800
},
.
mem2
=
{
.
start
=
0x00000000
,
.
size
=
0x00000000
},
.
mem3
=
{
.
start
=
0x00000000
,
.
size
=
0x00000000
},
},
[
PART_WORK
]
=
{
.
mem
=
{
.
start
=
0x00040000
,
.
size
=
0x00014fc0
},
.
reg
=
{
.
start
=
REGISTERS_BASE
,
.
size
=
0x0000a000
},
.
mem2
=
{
.
start
=
0x003004f8
,
.
size
=
0x00000004
},
.
mem3
=
{
.
start
=
0x00040404
,
.
size
=
0x00000000
},
},
[
PART_DRPW
]
=
{
.
mem
=
{
.
start
=
0x00040000
,
.
size
=
0x00014fc0
},
.
reg
=
{
.
start
=
DRPW_BASE
,
.
size
=
0x00006000
},
.
mem2
=
{
.
start
=
0x00000000
,
.
size
=
0x00000000
},
.
mem3
=
{
.
start
=
0x00000000
,
.
size
=
0x00000000
}
}
};
static
void
wl1271_boot_set_ecpu_ctrl
(
struct
wl1271
*
wl
,
u32
flag
)
{
u32
cpu_ctrl
;
...
...
@@ -181,13 +122,13 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
return
-
ENOMEM
;
}
memcpy
(
&
partition
,
&
part_table
[
PART_DOWN
],
sizeof
(
partition
));
memcpy
(
&
partition
,
&
wl12xx_
part_table
[
PART_DOWN
],
sizeof
(
partition
));
partition
.
mem
.
start
=
dest
;
wl1271_set_partition
(
wl
,
&
partition
);
/* 10.1 set partition limit and chunk num */
chunk_num
=
0
;
partition_limit
=
part_table
[
PART_DOWN
].
mem
.
size
;
partition_limit
=
wl12xx_
part_table
[
PART_DOWN
].
mem
.
size
;
while
(
chunk_num
<
fw_data_len
/
CHUNK_SIZE
)
{
/* 10.2 update partition, if needed */
...
...
@@ -195,7 +136,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
if
(
addr
>
partition_limit
)
{
addr
=
dest
+
chunk_num
*
CHUNK_SIZE
;
partition_limit
=
chunk_num
*
CHUNK_SIZE
+
part_table
[
PART_DOWN
].
mem
.
size
;
wl12xx_
part_table
[
PART_DOWN
].
mem
.
size
;
partition
.
mem
.
start
=
addr
;
wl1271_set_partition
(
wl
,
&
partition
);
}
...
...
@@ -317,12 +258,12 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
}
/* update current MAC address to NVS */
nvs_ptr
[
11
]
=
wl
->
mac_
addr
[
0
];
nvs_ptr
[
10
]
=
wl
->
mac_
addr
[
1
];
nvs_ptr
[
6
]
=
wl
->
mac_
addr
[
2
];
nvs_ptr
[
5
]
=
wl
->
mac_
addr
[
3
];
nvs_ptr
[
4
]
=
wl
->
mac_
addr
[
4
];
nvs_ptr
[
3
]
=
wl
->
mac_
addr
[
5
];
nvs_ptr
[
11
]
=
wl
->
addresses
[
0
].
addr
[
0
];
nvs_ptr
[
10
]
=
wl
->
addresses
[
0
].
addr
[
1
];
nvs_ptr
[
6
]
=
wl
->
addresses
[
0
].
addr
[
2
];
nvs_ptr
[
5
]
=
wl
->
addresses
[
0
].
addr
[
3
];
nvs_ptr
[
4
]
=
wl
->
addresses
[
0
].
addr
[
4
];
nvs_ptr
[
3
]
=
wl
->
addresses
[
0
].
addr
[
5
];
/*
* Layout before the actual NVS tables:
...
...
@@ -383,7 +324,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
nvs_len
-=
nvs_ptr
-
(
u8
*
)
wl
->
nvs
;
/* Now we must set the partition correctly */
wl1271_set_partition
(
wl
,
&
part_table
[
PART_WORK
]);
wl1271_set_partition
(
wl
,
&
wl12xx_
part_table
[
PART_WORK
]);
/* Copy the NVS tables to a new block to ensure alignment */
nvs_aligned
=
kmemdup
(
nvs_ptr
,
nvs_len
,
GFP_KERNEL
);
...
...
@@ -492,7 +433,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
wl
->
event_box_addr
=
wl1271_read32
(
wl
,
REG_EVENT_MAILBOX_PTR
);
/* set the working partition to its "running" mode offset */
wl1271_set_partition
(
wl
,
&
part_table
[
PART_WORK
]);
wl1271_set_partition
(
wl
,
&
wl12xx_
part_table
[
PART_WORK
]);
wl1271_debug
(
DEBUG_MAILBOX
,
"cmd_box_addr 0x%x event_box_addr 0x%x"
,
wl
->
cmd_box_addr
,
wl
->
event_box_addr
);
...
...
@@ -507,8 +448,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
/* unmask required mbox events */
wl
->
event_mask
=
BSS_LOSE_EVENT_ID
|
SCAN_COMPLETE_EVENT_ID
|
PS_REPORT_EVENT_ID
|
DISCONNECT_EVENT_COMPLETE_ID
|
ROLE_STOP_COMPLETE_EVENT_ID
|
RSSI_SNR_TRIGGER_0_EVENT_ID
|
PSPOLL_DELIVERY_FAILURE_EVENT_ID
|
SOFT_GEMINI_SENSE_EVENT_ID
|
...
...
@@ -547,19 +487,6 @@ static int wl1271_boot_write_irq_polarity(struct wl1271 *wl)
return
0
;
}
static
void
wl1271_boot_hw_version
(
struct
wl1271
*
wl
)
{
u32
fuse
;
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
fuse
=
wl1271_top_reg_read
(
wl
,
WL128X_REG_FUSE_DATA_2_1
);
else
fuse
=
wl1271_top_reg_read
(
wl
,
WL127X_REG_FUSE_DATA_2_1
);
fuse
=
(
fuse
&
PG_VER_MASK
)
>>
PG_VER_OFFSET
;
wl
->
hw_pg_ver
=
(
s8
)
fuse
;
}
static
int
wl128x_switch_tcxo_to_fref
(
struct
wl1271
*
wl
)
{
u16
spare_reg
;
...
...
@@ -698,7 +625,7 @@ static int wl127x_boot_clk(struct wl1271 *wl)
u32
pause
;
u32
clk
;
if
(
((
wl
->
hw_pg_ver
&
PG_MAJOR_VER_MASK
)
>>
PG_MAJOR_VER_OFFSET
)
<
3
)
if
(
WL127X_PG_GET_MAJOR
(
wl
->
hw_pg_ver
)
<
3
)
wl
->
quirks
|=
WL12XX_QUIRK_END_OF_TRANSACTION
;
if
(
wl
->
ref_clock
==
CONF_REF_CLK_19_2_E
||
...
...
@@ -753,8 +680,6 @@ int wl1271_load_firmware(struct wl1271 *wl)
u32
tmp
,
clk
;
int
selected_clock
=
-
1
;
wl1271_boot_hw_version
(
wl
);
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
{
ret
=
wl128x_boot_clk
(
wl
,
&
selected_clock
);
if
(
ret
<
0
)
...
...
@@ -769,7 +694,7 @@ int wl1271_load_firmware(struct wl1271 *wl)
wl1271_write32
(
wl
,
WELP_ARM_COMMAND
,
WELP_ARM_COMMAND_VAL
);
udelay
(
500
);
wl1271_set_partition
(
wl
,
&
part_table
[
PART_DRPW
]);
wl1271_set_partition
(
wl
,
&
wl12xx_
part_table
[
PART_DRPW
]);
/* Read-modify-write DRPW_SCRATCH_START register (see next state)
to be used by DRPw FW. The RTRIM value will be added by the FW
...
...
@@ -788,7 +713,7 @@ int wl1271_load_firmware(struct wl1271 *wl)
wl1271_write32
(
wl
,
DRPW_SCRATCH_START
,
clk
);
wl1271_set_partition
(
wl
,
&
part_table
[
PART_WORK
]);
wl1271_set_partition
(
wl
,
&
wl12xx_
part_table
[
PART_WORK
]);
/* Disable interrupts */
wl1271_write32
(
wl
,
ACX_REG_INTERRUPT_MASK
,
WL1271_ACX_INTR_ALL
);
...
...
drivers/net/wireless/wl12xx/boot.h
View file @
8715d941
...
...
@@ -55,16 +55,6 @@ struct wl1271_static_data {
#define OCP_REG_CLK_POLARITY 0x0cb2
#define OCP_REG_CLK_PULL 0x0cb4
#define WL127X_REG_FUSE_DATA_2_1 0x050a
#define WL128X_REG_FUSE_DATA_2_1 0x2152
#define PG_VER_MASK 0x3c
#define PG_VER_OFFSET 2
#define PG_MAJOR_VER_MASK 0x3
#define PG_MAJOR_VER_OFFSET 0x0
#define PG_MINOR_VER_MASK 0xc
#define PG_MINOR_VER_OFFSET 0x2
#define CMD_MBOX_ADDRESS 0x407B4
#define POLARITY_LOW BIT(1)
...
...
drivers/net/wireless/wl12xx/cmd.c
View file @
8715d941
...
...
@@ -566,7 +566,7 @@ static int wl12xx_cmd_role_stop_dev(struct wl1271 *wl,
goto
out_free
;
}
ret
=
wl1271_cmd_wait_for_event
(
wl
,
DISCONNECT_EVENT_COMPLETE
_ID
);
ret
=
wl1271_cmd_wait_for_event
(
wl
,
ROLE_STOP_COMPLETE_EVENT
_ID
);
if
(
ret
<
0
)
{
wl1271_error
(
"cmd role stop dev event completion error"
);
goto
out_free
;
...
...
@@ -715,6 +715,8 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif)
cmd
->
ap
.
beacon_interval
=
cpu_to_le16
(
wlvif
->
beacon_int
);
cmd
->
ap
.
dtim_interval
=
bss_conf
->
dtim_period
;
cmd
->
ap
.
beacon_expiry
=
WL1271_AP_DEF_BEACON_EXP
;
/* FIXME: Change when adding DFS */
cmd
->
ap
.
reset_tsf
=
1
;
/* By default reset AP TSF */
cmd
->
channel
=
wlvif
->
channel
;
if
(
!
bss_conf
->
hidden_ssid
)
{
...
...
@@ -994,7 +996,7 @@ int wl1271_cmd_data_path(struct wl1271 *wl, bool enable)
}
int
wl1271_cmd_ps_mode
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
ps_mode
)
u8
ps_mode
,
u16
auto_ps_timeout
)
{
struct
wl1271_cmd_ps_params
*
ps_params
=
NULL
;
int
ret
=
0
;
...
...
@@ -1009,6 +1011,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
ps_params
->
role_id
=
wlvif
->
role_id
;
ps_params
->
ps_mode
=
ps_mode
;
ps_params
->
auto_ps_timeout
=
auto_ps_timeout
;
ret
=
wl1271_cmd_send
(
wl
,
CMD_SET_PS_MODE
,
ps_params
,
sizeof
(
*
ps_params
),
0
);
...
...
@@ -1022,13 +1025,15 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
return
ret
;
}
int
wl1271_cmd_template_set
(
struct
wl1271
*
wl
,
u16
template_id
,
void
*
buf
,
size_t
buf_len
,
int
index
,
u32
rates
)
int
wl1271_cmd_template_set
(
struct
wl1271
*
wl
,
u8
role_id
,
u16
template_id
,
void
*
buf
,
size_t
buf_len
,
int
index
,
u32
rates
)
{
struct
wl1271_cmd_template_set
*
cmd
;
int
ret
=
0
;
wl1271_debug
(
DEBUG_CMD
,
"cmd template_set %d"
,
template_id
);
wl1271_debug
(
DEBUG_CMD
,
"cmd template_set %d (role %d)"
,
template_id
,
role_id
);
WARN_ON
(
buf_len
>
WL1271_CMD_TEMPL_MAX_SIZE
);
buf_len
=
min_t
(
size_t
,
buf_len
,
WL1271_CMD_TEMPL_MAX_SIZE
);
...
...
@@ -1039,6 +1044,8 @@ int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
goto
out
;
}
/* during initialization wlvif is NULL */
cmd
->
role_id
=
role_id
;
cmd
->
len
=
cpu_to_le16
(
buf_len
);
cmd
->
template_type
=
template_id
;
cmd
->
enabled_rates
=
cpu_to_le32
(
rates
);
...
...
@@ -1082,7 +1089,8 @@ int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif)
ptr
=
skb
->
data
;
}
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_NULL_DATA
,
ptr
,
size
,
0
,
ret
=
wl1271_cmd_template_set
(
wl
,
wlvif
->
role_id
,
CMD_TEMPL_NULL_DATA
,
ptr
,
size
,
0
,
wlvif
->
basic_rate
);
out:
...
...
@@ -1105,7 +1113,7 @@ int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl,
if
(
!
skb
)
goto
out
;
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_KLV
,
ret
=
wl1271_cmd_template_set
(
wl
,
wlvif
->
role_id
,
CMD_TEMPL_KLV
,
skb
->
data
,
skb
->
len
,
CMD_TEMPL_KLV_IDX_NULL_DATA
,
wlvif
->
basic_rate
);
...
...
@@ -1130,7 +1138,8 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif,
if
(
!
skb
)
goto
out
;
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_PS_POLL
,
skb
->
data
,
ret
=
wl1271_cmd_template_set
(
wl
,
wlvif
->
role_id
,
CMD_TEMPL_PS_POLL
,
skb
->
data
,
skb
->
len
,
0
,
wlvif
->
basic_rate_set
);
out:
...
...
@@ -1138,9 +1147,10 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif,
return
ret
;
}
int
wl1271_cmd_build_probe_req
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
int
wl12xx_cmd_build_probe_req
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
role_id
,
u8
band
,
const
u8
*
ssid
,
size_t
ssid_len
,
const
u8
*
ie
,
size_t
ie_len
,
u8
band
)
const
u8
*
ie
,
size_t
ie_len
)
{
struct
ieee80211_vif
*
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
struct
sk_buff
*
skb
;
...
...
@@ -1158,10 +1168,12 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
rate
=
wl1271_tx_min_rate_get
(
wl
,
wlvif
->
bitrate_masks
[
band
]);
if
(
band
==
IEEE80211_BAND_2GHZ
)
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_CFG_PROBE_REQ_2_4
,
ret
=
wl1271_cmd_template_set
(
wl
,
role_id
,
CMD_TEMPL_CFG_PROBE_REQ_2_4
,
skb
->
data
,
skb
->
len
,
0
,
rate
);
else
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_CFG_PROBE_REQ_5
,
ret
=
wl1271_cmd_template_set
(
wl
,
role_id
,
CMD_TEMPL_CFG_PROBE_REQ_5
,
skb
->
data
,
skb
->
len
,
0
,
rate
);
out:
...
...
@@ -1186,10 +1198,12 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
rate
=
wl1271_tx_min_rate_get
(
wl
,
wlvif
->
bitrate_masks
[
wlvif
->
band
]);
if
(
wlvif
->
band
==
IEEE80211_BAND_2GHZ
)
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_CFG_PROBE_REQ_2_4
,
ret
=
wl1271_cmd_template_set
(
wl
,
wlvif
->
role_id
,
CMD_TEMPL_CFG_PROBE_REQ_2_4
,
skb
->
data
,
skb
->
len
,
0
,
rate
);
else
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_CFG_PROBE_REQ_5
,
ret
=
wl1271_cmd_template_set
(
wl
,
wlvif
->
role_id
,
CMD_TEMPL_CFG_PROBE_REQ_5
,
skb
->
data
,
skb
->
len
,
0
,
rate
);
if
(
ret
<
0
)
...
...
@@ -1199,32 +1213,34 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
return
skb
;
}
int
wl1271_cmd_build_arp_rsp
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
__be32
ip_addr
)
int
wl1271_cmd_build_arp_rsp
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
int
ret
;
int
ret
,
extra
;
u16
fc
;
struct
ieee80211_vif
*
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
struct
wl12xx_arp_rsp_template
tmpl
;
struct
sk_buff
*
skb
;
struct
wl12xx_arp_rsp_template
*
tmpl
;
struct
ieee80211_hdr_3addr
*
hdr
;
struct
arphdr
*
arp_hdr
;
memset
(
&
tmpl
,
0
,
sizeof
(
tmpl
));
skb
=
dev_alloc_skb
(
sizeof
(
*
hdr
)
+
sizeof
(
__le16
)
+
sizeof
(
*
tmpl
)
+
WL1271_EXTRA_SPACE_MAX
);
if
(
!
skb
)
{
wl1271_error
(
"failed to allocate buffer for arp rsp template"
);
return
-
ENOMEM
;
}
/* mac80211 header */
hdr
=
&
tmpl
.
hdr
;
hdr
->
frame_control
=
cpu_to_le16
(
IEEE80211_FTYPE_DATA
|
IEEE80211_STYPE_DATA
|
IEEE80211_FCTL_TODS
);
memcpy
(
hdr
->
addr1
,
vif
->
bss_conf
.
bssid
,
ETH_ALEN
);
memcpy
(
hdr
->
addr2
,
vif
->
addr
,
ETH_ALEN
);
memset
(
hdr
->
addr3
,
0xff
,
ETH_ALEN
);
skb_reserve
(
skb
,
sizeof
(
*
hdr
)
+
WL1271_EXTRA_SPACE_MAX
);
tmpl
=
(
struct
wl12xx_arp_rsp_template
*
)
skb_put
(
skb
,
sizeof
(
*
tmpl
));
memset
(
tmpl
,
0
,
sizeof
(
tmpl
));
/* llc layer */
memcpy
(
tmpl
.
llc_hdr
,
rfc1042_header
,
sizeof
(
rfc1042_header
));
tmpl
.
llc_type
=
cpu_to_be16
(
ETH_P_ARP
);
memcpy
(
tmpl
->
llc_hdr
,
rfc1042_header
,
sizeof
(
rfc1042_header
));
tmpl
->
llc_type
=
cpu_to_be16
(
ETH_P_ARP
);
/* arp header */
arp_hdr
=
&
tmpl
.
arp_hdr
;
arp_hdr
=
&
tmpl
->
arp_hdr
;
arp_hdr
->
ar_hrd
=
cpu_to_be16
(
ARPHRD_ETHER
);
arp_hdr
->
ar_pro
=
cpu_to_be16
(
ETH_P_IP
);
arp_hdr
->
ar_hln
=
ETH_ALEN
;
...
...
@@ -1232,13 +1248,59 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif,
arp_hdr
->
ar_op
=
cpu_to_be16
(
ARPOP_REPLY
);
/* arp payload */
memcpy
(
tmpl
.
sender_hw
,
vif
->
addr
,
ETH_ALEN
);
tmpl
.
sender_ip
=
ip_addr
;
memcpy
(
tmpl
->
sender_hw
,
vif
->
addr
,
ETH_ALEN
);
tmpl
->
sender_ip
=
wlvif
->
ip_addr
;
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_ARP_RSP
,
&
tmpl
,
sizeof
(
tmpl
),
0
,
wlvif
->
basic_rate
);
/* encryption space */
switch
(
wlvif
->
encryption_type
)
{
case
KEY_TKIP
:
extra
=
WL1271_EXTRA_SPACE_TKIP
;
break
;
case
KEY_AES
:
extra
=
WL1271_EXTRA_SPACE_AES
;
break
;
case
KEY_NONE
:
case
KEY_WEP
:
case
KEY_GEM
:
extra
=
0
;
break
;
default:
wl1271_warning
(
"Unknown encryption type: %d"
,
wlvif
->
encryption_type
);
ret
=
-
EINVAL
;
goto
out
;
}
if
(
extra
)
{
u8
*
space
=
skb_push
(
skb
,
extra
);
memset
(
space
,
0
,
extra
);
}
/* QoS header - BE */
if
(
wlvif
->
sta
.
qos
)
memset
(
skb_push
(
skb
,
sizeof
(
__le16
)),
0
,
sizeof
(
__le16
));
/* mac80211 header */
hdr
=
(
struct
ieee80211_hdr_3addr
*
)
skb_push
(
skb
,
sizeof
(
*
hdr
));
memset
(
hdr
,
0
,
sizeof
(
hdr
));
fc
=
IEEE80211_FTYPE_DATA
|
IEEE80211_FCTL_TODS
;
if
(
wlvif
->
sta
.
qos
)
fc
|=
IEEE80211_STYPE_QOS_DATA
;
else
fc
|=
IEEE80211_STYPE_DATA
;
if
(
wlvif
->
encryption_type
!=
KEY_NONE
)
fc
|=
IEEE80211_FCTL_PROTECTED
;
hdr
->
frame_control
=
cpu_to_le16
(
fc
);
memcpy
(
hdr
->
addr1
,
vif
->
bss_conf
.
bssid
,
ETH_ALEN
);
memcpy
(
hdr
->
addr2
,
vif
->
addr
,
ETH_ALEN
);
memset
(
hdr
->
addr3
,
0xff
,
ETH_ALEN
);
ret
=
wl1271_cmd_template_set
(
wl
,
wlvif
->
role_id
,
CMD_TEMPL_ARP_RSP
,
skb
->
data
,
skb
->
len
,
0
,
wlvif
->
basic_rate
);
out:
dev_kfree_skb
(
skb
);
return
ret
;
}
...
...
@@ -1260,7 +1322,8 @@ int wl1271_build_qos_null_data(struct wl1271 *wl, struct ieee80211_vif *vif)
/* FIXME: not sure what priority to use here */
template
.
qos_ctrl
=
cpu_to_le16
(
0
);
return
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_QOS_NULL_DATA
,
&
template
,
return
wl1271_cmd_template_set
(
wl
,
wlvif
->
role_id
,
CMD_TEMPL_QOS_NULL_DATA
,
&
template
,
sizeof
(
template
),
0
,
wlvif
->
basic_rate
);
}
...
...
@@ -1744,6 +1807,7 @@ int wl12xx_croc(struct wl1271 *wl, u8 role_id)
}
int
wl12xx_cmd_channel_switch
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
ieee80211_channel_switch
*
ch_switch
)
{
struct
wl12xx_cmd_channel_switch
*
cmd
;
...
...
@@ -1757,10 +1821,13 @@ int wl12xx_cmd_channel_switch(struct wl1271 *wl,
goto
out
;
}
cmd
->
role_id
=
wlvif
->
role_id
;
cmd
->
channel
=
ch_switch
->
channel
->
hw_value
;
cmd
->
switch_time
=
ch_switch
->
count
;
cmd
->
tx_suspend
=
ch_switch
->
block_tx
;
cmd
->
flush
=
0
;
/* this value is ignored by the FW */
cmd
->
stop_tx
=
ch_switch
->
block_tx
;
/* FIXME: control from mac80211 in the future */
cmd
->
post_switch_tx_disable
=
0
;
/* Enable TX on the target channel */
ret
=
wl1271_cmd_send
(
wl
,
CMD_CHANNEL_SWITCH
,
cmd
,
sizeof
(
*
cmd
),
0
);
if
(
ret
<
0
)
{
...
...
drivers/net/wireless/wl12xx/cmd.h
View file @
8715d941
...
...
@@ -51,22 +51,23 @@ 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
,
struct
wl12xx_vif
*
wlvif
,
u8
ps_mode
);
u8
ps_mode
,
u16
auto_ps_timeout
);
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_template_set
(
struct
wl1271
*
wl
,
u8
role_id
,
u16
template_id
,
void
*
buf
,
size_t
buf_len
,
int
index
,
u32
rates
);
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
,
int
wl12xx_cmd_build_probe_req
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
role_id
,
u8
band
,
const
u8
*
ssid
,
size_t
ssid_len
,
const
u8
*
ie
,
size_t
ie_len
,
u8
band
);
const
u8
*
ie
,
size_t
ie_len
);
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
,
struct
wl12xx_vif
*
wlvif
,
__be32
ip_addr
);
int
wl1271_cmd_build_arp_rsp
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
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
);
...
...
@@ -89,6 +90,7 @@ int wl12xx_cmd_config_fwlog(struct wl1271 *wl);
int
wl12xx_cmd_start_fwlog
(
struct
wl1271
*
wl
);
int
wl12xx_cmd_stop_fwlog
(
struct
wl1271
*
wl
);
int
wl12xx_cmd_channel_switch
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
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
,
...
...
@@ -96,62 +98,65 @@ int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif,
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
*/
CMD_CONFIGURE
=
2
,
/*use this to write information elements
*/
CMD_INTERROGATE
=
1
,
/* use this to read information elements
*/
CMD_CONFIGURE
=
2
,
/* use this to write information elements
*/
CMD_ENABLE_RX
=
3
,
CMD_ENABLE_TX
=
4
,
CMD_DISABLE_RX
=
5
,
CMD_DISABLE_TX
=
6
,
CMD_SCAN
=
8
,
CMD_STOP_SCAN
=
9
,
CMD_SET_KEYS
=
12
,
CMD_READ_MEMORY
=
13
,
CMD_WRITE_MEMORY
=
14
,
CMD_SET_TEMPLATE
=
19
,
CMD_TEST
=
2
3
,
CMD_NOISE_HIST
=
28
,
CMD_QUIET_ELEMENT_SET_STATE
=
29
,
CMD_SET_BCN_MODE
=
33
,
CMD_MEASUREMENT
=
34
,
CMD_
STOP_MEASUREMENT
=
35
,
CMD_S
ET_PS_MODE
=
37
,
CMD_
CHANNEL_SWITCH
=
38
,
CMD_
STOP_CHANNEL_SWICTH
=
39
,
CMD_
AP_DISCOVERY
=
40
,
CMD_
STOP_AP_DISCOVERY
=
41
,
CMD_
HEALTH_CHECK
=
45
,
CMD_
DEBUG
=
46
,
CMD_
TRIGGER_SCAN_TO
=
47
,
CMD_
CONNECTION_SCAN_CFG
=
48
,
CMD_CONNECTION_SCAN_
SSID_CFG
=
49
,
CMD_
START_PERIODIC_SCAN
=
50
,
CMD_ST
OP_PERIODIC_SCAN
=
51
,
CMD_S
ET_PEER_STATE
=
52
,
CMD_
REMAIN_ON_CHANNEL
=
53
,
CMD_
CANCEL_REMAIN_ON_CHANNEL
=
54
,
CMD_CONFIG_FWLOGGER
=
55
,
CMD_START_FWLOGGER
=
56
,
CMD_STOP_FWLOGGER
=
57
,
/* A
P
commands */
CMD_ADD_PEER
=
62
,
CMD_REMOVE_PEER
=
63
,
CMD_SCAN
=
7
,
CMD_STOP_SCAN
=
8
,
CMD_SET_KEYS
=
9
,
CMD_READ_MEMORY
=
10
,
CMD_WRITE_MEMORY
=
11
,
CMD_SET_TEMPLATE
=
12
,
CMD_TEST
=
1
3
,
CMD_NOISE_HIST
=
14
,
CMD_QUIET_ELEMENT_SET_STATE
=
15
,
CMD_SET_BCN_MODE
=
16
,
CMD_
MEASUREMENT
=
17
,
CMD_S
TOP_MEASUREMENT
=
18
,
CMD_
SET_PS_MODE
=
19
,
CMD_
CHANNEL_SWITCH
=
20
,
CMD_
STOP_CHANNEL_SWICTH
=
21
,
CMD_
AP_DISCOVERY
=
22
,
CMD_
STOP_AP_DISCOVERY
=
23
,
CMD_
HEALTH_CHECK
=
24
,
CMD_
DEBUG
=
25
,
CMD_
TRIGGER_SCAN_TO
=
26
,
CMD_CONNECTION_SCAN_
CFG
=
27
,
CMD_
CONNECTION_SCAN_SSID_CFG
=
28
,
CMD_ST
ART_PERIODIC_SCAN
=
29
,
CMD_S
TOP_PERIODIC_SCAN
=
30
,
CMD_
SET_PEER_STATE
=
31
,
CMD_
REMAIN_ON_CHANNEL
=
32
,
CMD_CANCEL_REMAIN_ON_CHANNEL
=
33
,
CMD_CONFIG_FWLOGGER
=
34
,
CMD_START_FWLOGGER
=
35
,
CMD_STOP_FWLOGGER
=
36
,
/* A
ccess point
commands */
CMD_ADD_PEER
=
37
,
CMD_REMOVE_PEER
=
38
,
/* Role API */
CMD_ROLE_ENABLE
=
70
,
CMD_ROLE_DISABLE
=
71
,
CMD_ROLE_START
=
72
,
CMD_ROLE_STOP
=
73
,
CMD_ROLE_ENABLE
=
39
,
CMD_ROLE_DISABLE
=
40
,
CMD_ROLE_START
=
41
,
CMD_ROLE_STOP
=
42
,
/* WIFI Direct */
CMD_WFD_START_DISCOVERY
=
80
,
CMD_WFD_STOP_DISCOVERY
=
81
,
CMD_WFD_ATTRIBUTE_CONFIG
=
82
,
/* DFS */
CMD_START_RADAR_DETECTION
=
43
,
CMD_STOP_RADAR_DETECTION
=
44
,
CMD_NOP
=
100
,
/* WIFI Direct */
CMD_WFD_START_DISCOVERY
=
45
,
CMD_WFD_STOP_DISCOVERY
=
46
,
CMD_WFD_ATTRIBUTE_CONFIG
=
47
,
CMD_NOP
=
48
,
CMD_LAST_COMMAND
,
NUM_COMMANDS
,
MAX_COMMAND_ID
=
0xFFFF
,
};
...
...
@@ -191,7 +196,7 @@ enum cmd_templ {
/* unit ms */
#define WL1271_COMMAND_TIMEOUT 2000
#define WL1271_CMD_TEMPL_DFLT_SIZE 252
#define WL1271_CMD_TEMPL_MAX_SIZE 5
48
#define WL1271_CMD_TEMPL_MAX_SIZE 5
12
#define WL1271_EVENT_TIMEOUT 750
struct
wl1271_cmd_header
{
...
...
@@ -339,7 +344,9 @@ struct wl12xx_cmd_role_start {
u8
ssid_len
;
u8
ssid
[
IEEE80211_MAX_SSID_LEN
];
u8
padding_1
[
5
];
u8
reset_tsf
;
u8
padding_1
[
4
];
}
__packed
ap
;
};
}
__packed
;
...
...
@@ -364,14 +371,18 @@ struct cmd_enabledisable_path {
struct
wl1271_cmd_template_set
{
struct
wl1271_cmd_header
header
;
__le16
len
;
u8
role_id
;
u8
template_type
;
__le16
len
;
u8
index
;
/* relevant only for KLV_TEMPLATE type */
u8
padding
[
3
];
__le32
enabled_rates
;
u8
short_retry_limit
;
u8
long_retry_limit
;
u8
aflags
;
u8
reserved
;
u8
template_data
[
WL1271_CMD_TEMPL_MAX_SIZE
];
}
__packed
;
...
...
@@ -388,6 +399,7 @@ struct wl1271_tim {
}
__packed
;
enum
wl1271_cmd_ps_mode
{
STATION_AUTO_PS_MODE
,
/* Dynamic Power Save */
STATION_ACTIVE_MODE
,
STATION_POWER_SAVE_MODE
};
...
...
@@ -397,7 +409,7 @@ struct wl1271_cmd_ps_params {
u8
role_id
;
u8
ps_mode
;
/* STATION_* */
u
8
padding
[
2
]
;
u
16
auto_ps_timeout
;
}
__packed
;
/* HW encryption keys */
...
...
@@ -695,14 +707,18 @@ struct wl12xx_cmd_stop_fwlog {
struct
wl12xx_cmd_channel_switch
{
struct
wl1271_cmd_header
header
;
u8
role_id
;
/* The new serving channel */
u8
channel
;
/* Relative time of the serving channel switch in TBTT units */
u8
switch_time
;
/* 1: Suspend TX till switch time; 0: Do not suspend TX */
u8
tx_suspend
;
/* 1: Flush TX at switch time; 0: Do not flush */
u8
flush
;
/* Stop the role TX, should expect it after radar detection */
u8
stop_tx
;
/* The target channel tx status 1-stopped 0-open*/
u8
post_switch_tx_disable
;
u8
padding
[
3
];
}
__packed
;
struct
wl12xx_cmd_stop_channel_switch
{
...
...
drivers/net/wireless/wl12xx/conf.h
View file @
8715d941
...
...
@@ -66,7 +66,8 @@ enum {
};
enum
{
CONF_HW_RXTX_RATE_MCS7
=
0
,
CONF_HW_RXTX_RATE_MCS7_SGI
=
0
,
CONF_HW_RXTX_RATE_MCS7
,
CONF_HW_RXTX_RATE_MCS6
,
CONF_HW_RXTX_RATE_MCS5
,
CONF_HW_RXTX_RATE_MCS4
,
...
...
@@ -91,6 +92,10 @@ enum {
CONF_HW_RXTX_RATE_UNSUPPORTED
=
0xff
};
/* Rates between and including these are MCS rates */
#define CONF_HW_RXTX_RATE_MCS_MIN CONF_HW_RXTX_RATE_MCS7_SGI
#define CONF_HW_RXTX_RATE_MCS_MAX CONF_HW_RXTX_RATE_MCS0
enum
{
CONF_SG_DISABLE
=
0
,
CONF_SG_PROTECTIVE
,
...
...
@@ -312,6 +317,10 @@ enum {
CONF_AP_BT_ACL_VAL_BT_SERVE_TIME
,
CONF_AP_BT_ACL_VAL_WL_SERVE_TIME
,
/* CTS Diluting params */
CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH
,
CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER
,
CONF_SG_TEMP_PARAM_1
,
CONF_SG_TEMP_PARAM_2
,
CONF_SG_TEMP_PARAM_3
,
...
...
@@ -809,6 +818,19 @@ struct conf_conn_settings {
*/
u8
listen_interval
;
/*
* Firmware wakeup conditions during suspend
* Range: CONF_WAKE_UP_EVENT_*
*/
u8
suspend_wake_up_event
;
/*
* Listen interval during suspend.
* Currently will be in DTIMs (1-10)
*
*/
u8
suspend_listen_interval
;
/*
* Enable or disable the beacon filtering.
*
...
...
@@ -867,13 +889,6 @@ struct conf_conn_settings {
*/
u8
ps_poll_threshold
;
/*
* PS Poll failure recovery ACTIVE period length
*
* Range: u32 (ms)
*/
u32
ps_poll_recovery_period
;
/*
* Configuration of signal average weights.
*/
...
...
@@ -921,6 +936,18 @@ struct conf_conn_settings {
*/
u8
psm_entry_nullfunc_retries
;
/*
* Specifies the dynamic PS timeout in ms that will be used
* by the FW when in AUTO_PS mode
*/
u16
dynamic_ps_timeout
;
/*
* Specifies whether dynamic PS should be disabled and PSM forced.
* This is required for certain WiFi certification tests.
*/
u8
forced_ps
;
/*
*
* Specifies the interval of the connection keep-alive null-func
...
...
@@ -1055,6 +1082,14 @@ struct conf_scan_settings {
*/
u16
num_probe_reqs
;
/*
* Scan trigger (split scan) timeout. The FW will split the scan
* operation into slices of the given time and allow the FW to schedule
* other tasks in between.
*
* Range: u32 Microsecs
*/
u32
split_scan_timeout
;
};
struct
conf_sched_scan_settings
{
...
...
drivers/net/wireless/wl12xx/debug.h
View file @
8715d941
...
...
@@ -51,6 +51,7 @@ enum {
DEBUG_FILTERS
=
BIT
(
15
),
DEBUG_ADHOC
=
BIT
(
16
),
DEBUG_AP
=
BIT
(
17
),
DEBUG_PROBE
=
BIT
(
18
),
DEBUG_MASTER
=
(
DEBUG_ADHOC
|
DEBUG_AP
),
DEBUG_ALL
=
~
0
,
};
...
...
drivers/net/wireless/wl12xx/debugfs.c
View file @
8715d941
...
...
@@ -113,7 +113,7 @@ static void wl1271_debugfs_update_stats(struct wl1271 *wl)
if
(
ret
<
0
)
goto
out
;
if
(
wl
->
state
==
WL1271_STATE_ON
&&
if
(
wl
->
state
==
WL1271_STATE_ON
&&
!
wl
->
plt
&&
time_after
(
jiffies
,
wl
->
stats
.
fw_stats_update
+
msecs_to_jiffies
(
WL1271_DEBUGFS_STATS_LIFETIME
)))
{
wl1271_acx_statistics
(
wl
,
wl
->
stats
.
fw_stats
);
...
...
@@ -312,6 +312,181 @@ static const struct file_operations start_recovery_ops = {
.
llseek
=
default_llseek
,
};
static
ssize_t
dynamic_ps_timeout_read
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
wl1271
*
wl
=
file
->
private_data
;
return
wl1271_format_buffer
(
user_buf
,
count
,
ppos
,
"%d
\n
"
,
wl
->
conf
.
conn
.
dynamic_ps_timeout
);
}
static
ssize_t
dynamic_ps_timeout_write
(
struct
file
*
file
,
const
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
wl1271
*
wl
=
file
->
private_data
;
struct
wl12xx_vif
*
wlvif
;
unsigned
long
value
;
int
ret
;
ret
=
kstrtoul_from_user
(
user_buf
,
count
,
10
,
&
value
);
if
(
ret
<
0
)
{
wl1271_warning
(
"illegal value in dynamic_ps"
);
return
-
EINVAL
;
}
if
(
value
<
1
||
value
>
65535
)
{
wl1271_warning
(
"dyanmic_ps_timeout is not in valid range"
);
return
-
ERANGE
;
}
mutex_lock
(
&
wl
->
mutex
);
wl
->
conf
.
conn
.
dynamic_ps_timeout
=
value
;
if
(
wl
->
state
==
WL1271_STATE_OFF
)
goto
out
;
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out
;
/* In case we're already in PSM, trigger it again to set new timeout
* immediately without waiting for re-association
*/
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
if
(
test_bit
(
WLVIF_FLAG_IN_PS
,
&
wlvif
->
flags
))
wl1271_ps_set_mode
(
wl
,
wlvif
,
STATION_AUTO_PS_MODE
);
}
wl1271_ps_elp_sleep
(
wl
);
out:
mutex_unlock
(
&
wl
->
mutex
);
return
count
;
}
static
const
struct
file_operations
dynamic_ps_timeout_ops
=
{
.
read
=
dynamic_ps_timeout_read
,
.
write
=
dynamic_ps_timeout_write
,
.
open
=
wl1271_open_file_generic
,
.
llseek
=
default_llseek
,
};
static
ssize_t
forced_ps_read
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
wl1271
*
wl
=
file
->
private_data
;
return
wl1271_format_buffer
(
user_buf
,
count
,
ppos
,
"%d
\n
"
,
wl
->
conf
.
conn
.
forced_ps
);
}
static
ssize_t
forced_ps_write
(
struct
file
*
file
,
const
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
wl1271
*
wl
=
file
->
private_data
;
struct
wl12xx_vif
*
wlvif
;
unsigned
long
value
;
int
ret
,
ps_mode
;
ret
=
kstrtoul_from_user
(
user_buf
,
count
,
10
,
&
value
);
if
(
ret
<
0
)
{
wl1271_warning
(
"illegal value in forced_ps"
);
return
-
EINVAL
;
}
if
(
value
!=
1
&&
value
!=
0
)
{
wl1271_warning
(
"forced_ps should be either 0 or 1"
);
return
-
ERANGE
;
}
mutex_lock
(
&
wl
->
mutex
);
if
(
wl
->
conf
.
conn
.
forced_ps
==
value
)
goto
out
;
wl
->
conf
.
conn
.
forced_ps
=
value
;
if
(
wl
->
state
==
WL1271_STATE_OFF
)
goto
out
;
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out
;
/* In case we're already in PSM, trigger it again to switch mode
* immediately without waiting for re-association
*/
ps_mode
=
value
?
STATION_POWER_SAVE_MODE
:
STATION_AUTO_PS_MODE
;
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
if
(
test_bit
(
WLVIF_FLAG_IN_PS
,
&
wlvif
->
flags
))
wl1271_ps_set_mode
(
wl
,
wlvif
,
ps_mode
);
}
wl1271_ps_elp_sleep
(
wl
);
out:
mutex_unlock
(
&
wl
->
mutex
);
return
count
;
}
static
const
struct
file_operations
forced_ps_ops
=
{
.
read
=
forced_ps_read
,
.
write
=
forced_ps_write
,
.
open
=
wl1271_open_file_generic
,
.
llseek
=
default_llseek
,
};
static
ssize_t
split_scan_timeout_read
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
wl1271
*
wl
=
file
->
private_data
;
return
wl1271_format_buffer
(
user_buf
,
count
,
ppos
,
"%d
\n
"
,
wl
->
conf
.
scan
.
split_scan_timeout
/
1000
);
}
static
ssize_t
split_scan_timeout_write
(
struct
file
*
file
,
const
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
wl1271
*
wl
=
file
->
private_data
;
unsigned
long
value
;
int
ret
;
ret
=
kstrtoul_from_user
(
user_buf
,
count
,
10
,
&
value
);
if
(
ret
<
0
)
{
wl1271_warning
(
"illegal value in split_scan_timeout"
);
return
-
EINVAL
;
}
if
(
value
==
0
)
wl1271_info
(
"split scan will be disabled"
);
mutex_lock
(
&
wl
->
mutex
);
wl
->
conf
.
scan
.
split_scan_timeout
=
value
*
1000
;
mutex_unlock
(
&
wl
->
mutex
);
return
count
;
}
static
const
struct
file_operations
split_scan_timeout_ops
=
{
.
read
=
split_scan_timeout_read
,
.
write
=
split_scan_timeout_write
,
.
open
=
wl1271_open_file_generic
,
.
llseek
=
default_llseek
,
};
static
ssize_t
driver_state_read
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
...
...
@@ -446,6 +621,7 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf,
VIF_STATE_PRINT_INT
(
sta
.
basic_rate_idx
);
VIF_STATE_PRINT_INT
(
sta
.
ap_rate_idx
);
VIF_STATE_PRINT_INT
(
sta
.
p2p_rate_idx
);
VIF_STATE_PRINT_INT
(
sta
.
qos
);
}
else
{
VIF_STATE_PRINT_INT
(
ap
.
global_hlid
);
VIF_STATE_PRINT_INT
(
ap
.
bcast_hlid
);
...
...
@@ -471,7 +647,6 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf,
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
);
...
...
@@ -562,6 +737,64 @@ static const struct file_operations dtim_interval_ops = {
.
llseek
=
default_llseek
,
};
static
ssize_t
suspend_dtim_interval_read
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
wl1271
*
wl
=
file
->
private_data
;
u8
value
;
if
(
wl
->
conf
.
conn
.
suspend_wake_up_event
==
CONF_WAKE_UP_EVENT_DTIM
||
wl
->
conf
.
conn
.
suspend_wake_up_event
==
CONF_WAKE_UP_EVENT_N_DTIM
)
value
=
wl
->
conf
.
conn
.
suspend_listen_interval
;
else
value
=
0
;
return
wl1271_format_buffer
(
user_buf
,
count
,
ppos
,
"%d
\n
"
,
value
);
}
static
ssize_t
suspend_dtim_interval_write
(
struct
file
*
file
,
const
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
wl1271
*
wl
=
file
->
private_data
;
unsigned
long
value
;
int
ret
;
ret
=
kstrtoul_from_user
(
user_buf
,
count
,
10
,
&
value
);
if
(
ret
<
0
)
{
wl1271_warning
(
"illegal value for suspend_dtim_interval"
);
return
-
EINVAL
;
}
if
(
value
<
1
||
value
>
10
)
{
wl1271_warning
(
"suspend_dtim value is not in valid range"
);
return
-
ERANGE
;
}
mutex_lock
(
&
wl
->
mutex
);
wl
->
conf
.
conn
.
suspend_listen_interval
=
value
;
/* for some reason there are different event types for 1 and >1 */
if
(
value
==
1
)
wl
->
conf
.
conn
.
suspend_wake_up_event
=
CONF_WAKE_UP_EVENT_DTIM
;
else
wl
->
conf
.
conn
.
suspend_wake_up_event
=
CONF_WAKE_UP_EVENT_N_DTIM
;
mutex_unlock
(
&
wl
->
mutex
);
return
count
;
}
static
const
struct
file_operations
suspend_dtim_interval_ops
=
{
.
read
=
suspend_dtim_interval_read
,
.
write
=
suspend_dtim_interval_write
,
.
open
=
wl1271_open_file_generic
,
.
llseek
=
default_llseek
,
};
static
ssize_t
beacon_interval_read
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
...
...
@@ -886,8 +1119,12 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,
DEBUGFS_ADD
(
driver_state
,
rootdir
);
DEBUGFS_ADD
(
vifs_state
,
rootdir
);
DEBUGFS_ADD
(
dtim_interval
,
rootdir
);
DEBUGFS_ADD
(
suspend_dtim_interval
,
rootdir
);
DEBUGFS_ADD
(
beacon_interval
,
rootdir
);
DEBUGFS_ADD
(
beacon_filtering
,
rootdir
);
DEBUGFS_ADD
(
dynamic_ps_timeout
,
rootdir
);
DEBUGFS_ADD
(
forced_ps
,
rootdir
);
DEBUGFS_ADD
(
split_scan_timeout
,
rootdir
);
streaming
=
debugfs_create_dir
(
"rx_streaming"
,
rootdir
);
if
(
!
streaming
||
IS_ERR
(
streaming
))
...
...
drivers/net/wireless/wl12xx/event.c
View file @
8715d941
...
...
@@ -30,133 +30,6 @@
#include "scan.h"
#include "wl12xx_80211.h"
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
);
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"
);
mutex_lock
(
&
wl
->
mutex
);
if
(
unlikely
(
wl
->
state
==
WL1271_STATE_OFF
))
goto
out
;
if
(
!
test_and_clear_bit
(
WLVIF_FLAG_PSPOLL_FAILURE
,
&
wlvif
->
flags
))
goto
out
;
if
(
!
test_bit
(
WLVIF_FLAG_STA_ASSOCIATED
,
&
wlvif
->
flags
))
goto
out
;
/*
* if we end up here, then we were in powersave when the pspoll
* delivery failure occurred, and no-one changed state since, so
* we should go back to powersave.
*/
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out
;
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
,
struct
wl12xx_vif
*
wlvif
)
{
int
delay
=
wl
->
conf
.
conn
.
ps_poll_recovery_period
;
int
ret
;
wlvif
->
ps_poll_failures
++
;
if
(
wlvif
->
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
(
WLVIF_FLAG_PSM
,
&
wlvif
->
flags
))
{
ret
=
wl1271_ps_set_mode
(
wl
,
wlvif
,
STATION_ACTIVE_MODE
,
wlvif
->
basic_rate
,
true
);
if
(
ret
<
0
)
return
;
set_bit
(
WLVIF_FLAG_PSPOLL_FAILURE
,
&
wlvif
->
flags
);
ieee80211_queue_delayed_work
(
wl
->
hw
,
&
wlvif
->
pspoll_work
,
msecs_to_jiffies
(
delay
));
}
/*
* If already in active mode, lets we should be getting data from
* the AP right away. If we enter PSM too fast after this, and data
* remains on the AP, we will get another event like this, and we'll
* go into active once more.
*/
}
static
int
wl1271_event_ps_report
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
event_mailbox
*
mbox
,
bool
*
beacon_loss
)
{
int
ret
=
0
;
u32
total_retries
=
wl
->
conf
.
conn
.
psm_entry_retries
;
wl1271_debug
(
DEBUG_EVENT
,
"ps_status: 0x%x"
,
mbox
->
ps_status
);
switch
(
mbox
->
ps_status
)
{
case
EVENT_ENTER_POWER_SAVE_FAIL
:
wl1271_debug
(
DEBUG_PSM
,
"PSM entry failed"
);
if
(
!
test_bit
(
WLVIF_FLAG_PSM
,
&
wlvif
->
flags
))
{
/* remain in active mode */
wlvif
->
psm_entry_retry
=
0
;
break
;
}
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."
);
wlvif
->
psm_entry_retry
=
0
;
*
beacon_loss
=
true
;
}
break
;
case
EVENT_ENTER_POWER_SAVE_SUCCESS
:
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
(
wlvif
->
band
==
IEEE80211_BAND_2GHZ
)
/* enable beacon early termination */
ret
=
wl1271_acx_bet_enable
(
wl
,
wlvif
,
true
);
if
(
wlvif
->
ps_compl
)
{
complete
(
wlvif
->
ps_compl
);
wlvif
->
ps_compl
=
NULL
;
}
break
;
default:
break
;
}
return
ret
;
}
static
void
wl1271_event_rssi_trigger
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
event_mailbox
*
mbox
)
...
...
@@ -205,21 +78,13 @@ static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif)
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 */
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
{
clear_bit
(
WL1271_FLAG_SOFT_GEMINI
,
&
wl
->
flags
);
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
ieee80211_enable_dyn_ps
(
vif
);
wl1271_recalc_rx_streaming
(
wl
,
wlvif
);
}
}
...
...
@@ -237,7 +102,6 @@ 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
disconnect_sta
=
false
;
...
...
@@ -293,21 +157,6 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
beacon_loss
=
true
;
}
if
(
vector
&
PS_REPORT_EVENT_ID
)
{
wl1271_debug
(
DEBUG_EVENT
,
"PS_REPORT_EVENT"
);
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
)
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"
);
...
...
@@ -344,7 +193,6 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
/* 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
,
...
...
@@ -352,6 +200,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
continue
;
success
=
mbox
->
channel_switch_status
?
false
:
true
;
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
ieee80211_chswitch_done
(
vif
,
success
);
}
}
...
...
drivers/net/wireless/wl12xx/event.h
View file @
8715d941
...
...
@@ -51,10 +51,10 @@ enum {
SCAN_COMPLETE_EVENT_ID
=
BIT
(
10
),
WFD_DISCOVERY_COMPLETE_EVENT_ID
=
BIT
(
11
),
AP_DISCOVERY_COMPLETE_EVENT_ID
=
BIT
(
12
),
PS_REPORT_EVENT_ID
=
BIT
(
13
),
RESERVED1
=
BIT
(
13
),
PSPOLL_DELIVERY_FAILURE_EVENT_ID
=
BIT
(
14
),
DISCONNECT_EVENT_COMPLETE
_ID
=
BIT
(
15
),
/* BIT(16) is reserved */
ROLE_STOP_COMPLETE_EVENT
_ID
=
BIT
(
15
),
RADAR_DETECTED_EVENT_ID
=
BIT
(
16
),
CHANNEL_SWITCH_COMPLETE_EVENT_ID
=
BIT
(
17
),
BSS_LOSE_EVENT_ID
=
BIT
(
18
),
REGAINED_BSS_EVENT_ID
=
BIT
(
19
),
...
...
@@ -94,9 +94,9 @@ struct event_mailbox {
u8
soft_gemini_sense_info
;
u8
soft_gemini_protective_info
;
s8
rssi_snr_trigger_metric
[
NUM_OF_RSSI_SNR_TRIGGERS
];
u8
chan
nel_switch_status
;
u8
chan
ge_auto_mode_timeout
;
u8
scheduled_scan_status
;
u8
ps_status
;
u8
reserved4
;
/* tuned channel (roc) */
u8
roc_channel
;
...
...
@@ -119,17 +119,21 @@ struct event_mailbox {
u8
rx_ba_allowed
;
u8
reserved_6
[
2
];
/* Channel switch results */
u8
channel_switch_role_id
;
u8
channel_switch_status
;
u8
reserved_7
[
2
];
u8
ps_poll_delivery_failure_role_ids
;
u8
stopped_role_ids
;
u8
started_role_ids
;
u8
change_auto_mode_timeout
;
u8
reserved_
7
[
12
];
u8
reserved_
8
[
9
];
}
__packed
;
int
wl1271_event_unmask
(
struct
wl1271
*
wl
);
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
);
#endif
drivers/net/wireless/wl12xx/init.c
View file @
8715d941
...
...
@@ -37,54 +37,64 @@
int
wl1271_init_templates_config
(
struct
wl1271
*
wl
)
{
int
ret
,
i
;
size_t
max_size
;
/* send empty templates for fw memory reservation */
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_CFG_PROBE_REQ_2_4
,
NULL
,
WL1271_CMD_TEMPL_DFLT_SIZE
,
ret
=
wl1271_cmd_template_set
(
wl
,
WL12XX_INVALID_ROLE_ID
,
CMD_TEMPL_CFG_PROBE_REQ_2_4
,
NULL
,
WL1271_CMD_TEMPL_MAX_SIZE
,
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_CFG_PROBE_REQ_5
,
NULL
,
WL1271_CMD_TEMPL_DFLT_SIZE
,
0
,
ret
=
wl1271_cmd_template_set
(
wl
,
WL12XX_INVALID_ROLE_ID
,
CMD_TEMPL_CFG_PROBE_REQ_5
,
NULL
,
WL1271_CMD_TEMPL_MAX_SIZE
,
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_NULL_DATA
,
NULL
,
ret
=
wl1271_cmd_template_set
(
wl
,
WL12XX_INVALID_ROLE_ID
,
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_PS_POLL
,
NULL
,
ret
=
wl1271_cmd_template_set
(
wl
,
WL12XX_INVALID_ROLE_ID
,
CMD_TEMPL_PS_POLL
,
NULL
,
sizeof
(
struct
wl12xx_ps_poll_template
),
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_QOS_NULL_DATA
,
NULL
,
ret
=
wl1271_cmd_template_set
(
wl
,
WL12XX_INVALID_ROLE_ID
,
CMD_TEMPL_QOS_NULL_DATA
,
NULL
,
sizeof
(
struct
ieee80211_qos_hdr
),
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_PROBE_RESPONSE
,
NULL
,
ret
=
wl1271_cmd_template_set
(
wl
,
WL12XX_INVALID_ROLE_ID
,
CMD_TEMPL_PROBE_RESPONSE
,
NULL
,
WL1271_CMD_TEMPL_DFLT_SIZE
,
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_BEACON
,
NULL
,
ret
=
wl1271_cmd_template_set
(
wl
,
WL12XX_INVALID_ROLE_ID
,
CMD_TEMPL_BEACON
,
NULL
,
WL1271_CMD_TEMPL_DFLT_SIZE
,
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_ARP_RSP
,
NULL
,
sizeof
(
struct
wl12xx_arp_rsp_template
),
max_size
=
sizeof
(
struct
wl12xx_arp_rsp_template
)
+
WL1271_EXTRA_SPACE_MAX
;
ret
=
wl1271_cmd_template_set
(
wl
,
WL12XX_INVALID_ROLE_ID
,
CMD_TEMPL_ARP_RSP
,
NULL
,
max_size
,
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -93,19 +103,22 @@ int wl1271_init_templates_config(struct wl1271 *wl)
* 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
,
ret
=
wl1271_cmd_template_set
(
wl
,
WL12XX_INVALID_ROLE_ID
,
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
,
ret
=
wl1271_cmd_template_set
(
wl
,
WL12XX_INVALID_ROLE_ID
,
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
,
ret
=
wl1271_cmd_template_set
(
wl
,
WL12XX_INVALID_ROLE_ID
,
CMD_TEMPL_DEAUTH_AP
,
NULL
,
sizeof
(
struct
wl12xx_disconn_template
),
0
,
WL1271_RATE_AUTOMATIC
);
...
...
@@ -113,7 +126,8 @@ int wl1271_init_templates_config(struct wl1271 *wl)
return
ret
;
for
(
i
=
0
;
i
<
CMD_TEMPL_KLV_IDX_MAX
;
i
++
)
{
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_KLV
,
NULL
,
ret
=
wl1271_cmd_template_set
(
wl
,
WL12XX_INVALID_ROLE_ID
,
CMD_TEMPL_KLV
,
NULL
,
sizeof
(
struct
ieee80211_qos_hdr
),
i
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
...
...
@@ -140,7 +154,8 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl,
IEEE80211_STYPE_DEAUTH
);
rate
=
wl1271_tx_min_rate_get
(
wl
,
wlvif
->
basic_rate_set
);
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_DEAUTH_AP
,
ret
=
wl1271_cmd_template_set
(
wl
,
wlvif
->
role_id
,
CMD_TEMPL_DEAUTH_AP
,
tmpl
,
sizeof
(
*
tmpl
),
0
,
rate
);
out:
...
...
@@ -172,7 +187,8 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl,
memcpy
(
nullfunc
->
addr3
,
vif
->
addr
,
ETH_ALEN
);
rate
=
wl1271_tx_min_rate_get
(
wl
,
wlvif
->
basic_rate_set
);
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_NULL_DATA
,
nullfunc
,
ret
=
wl1271_cmd_template_set
(
wl
,
wlvif
->
role_id
,
CMD_TEMPL_NULL_DATA
,
nullfunc
,
sizeof
(
*
nullfunc
),
0
,
rate
);
out:
...
...
@@ -204,7 +220,8 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl,
memcpy
(
qosnull
->
addr3
,
vif
->
addr
,
ETH_ALEN
);
rate
=
wl1271_tx_min_rate_get
(
wl
,
wlvif
->
basic_rate_set
);
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_QOS_NULL_DATA
,
qosnull
,
ret
=
wl1271_cmd_template_set
(
wl
,
wlvif
->
role_id
,
CMD_TEMPL_QOS_NULL_DATA
,
qosnull
,
sizeof
(
*
qosnull
),
0
,
rate
);
out:
...
...
drivers/net/wireless/wl12xx/io.c
View file @
8715d941
...
...
@@ -45,6 +45,65 @@
#define OCP_STATUS_REQ_FAILED 0x20000
#define OCP_STATUS_RESP_ERROR 0x30000
struct
wl1271_partition_set
wl12xx_part_table
[
PART_TABLE_LEN
]
=
{
[
PART_DOWN
]
=
{
.
mem
=
{
.
start
=
0x00000000
,
.
size
=
0x000177c0
},
.
reg
=
{
.
start
=
REGISTERS_BASE
,
.
size
=
0x00008800
},
.
mem2
=
{
.
start
=
0x00000000
,
.
size
=
0x00000000
},
.
mem3
=
{
.
start
=
0x00000000
,
.
size
=
0x00000000
},
},
[
PART_WORK
]
=
{
.
mem
=
{
.
start
=
0x00040000
,
.
size
=
0x00014fc0
},
.
reg
=
{
.
start
=
REGISTERS_BASE
,
.
size
=
0x0000a000
},
.
mem2
=
{
.
start
=
0x003004f8
,
.
size
=
0x00000004
},
.
mem3
=
{
.
start
=
0x00040404
,
.
size
=
0x00000000
},
},
[
PART_DRPW
]
=
{
.
mem
=
{
.
start
=
0x00040000
,
.
size
=
0x00014fc0
},
.
reg
=
{
.
start
=
DRPW_BASE
,
.
size
=
0x00006000
},
.
mem2
=
{
.
start
=
0x00000000
,
.
size
=
0x00000000
},
.
mem3
=
{
.
start
=
0x00000000
,
.
size
=
0x00000000
}
}
};
bool
wl1271_set_block_size
(
struct
wl1271
*
wl
)
{
if
(
wl
->
if_ops
->
set_block_size
)
{
...
...
drivers/net/wireless/wl12xx/io.h
View file @
8715d941
...
...
@@ -43,6 +43,8 @@
#define HW_ACCESS_PRAM_MAX_RANGE 0x3c000
extern
struct
wl1271_partition_set
wl12xx_part_table
[
PART_TABLE_LEN
];
struct
wl1271
;
void
wl1271_disable_interrupts
(
struct
wl1271
*
wl
);
...
...
drivers/net/wireless/wl12xx/main.c
View file @
8715d941
/*
* This file is part of wl1271
*
...
...
@@ -115,6 +116,9 @@ static struct conf_drv_settings default_conf = {
[
CONF_AP_CONNECTION_PROTECTION_TIME
]
=
0
,
[
CONF_AP_BT_ACL_VAL_BT_SERVE_TIME
]
=
25
,
[
CONF_AP_BT_ACL_VAL_WL_SERVE_TIME
]
=
25
,
/* CTS Diluting params */
[
CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH
]
=
0
,
[
CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER
]
=
0
,
},
.
state
=
CONF_SG_PROTECTIVE
,
},
...
...
@@ -217,6 +221,8 @@ static struct conf_drv_settings default_conf = {
.
conn
=
{
.
wake_up_event
=
CONF_WAKE_UP_EVENT_DTIM
,
.
listen_interval
=
1
,
.
suspend_wake_up_event
=
CONF_WAKE_UP_EVENT_N_DTIM
,
.
suspend_listen_interval
=
3
,
.
bcn_filt_mode
=
CONF_BCN_FILT_MODE_ENABLED
,
.
bcn_filt_ie_count
=
2
,
.
bcn_filt_ie
=
{
...
...
@@ -235,12 +241,13 @@ static struct conf_drv_settings default_conf = {
.
broadcast_timeout
=
20000
,
.
rx_broadcast_in_ps
=
1
,
.
ps_poll_threshold
=
10
,
.
ps_poll_recovery_period
=
700
,
.
bet_enable
=
CONF_BET_MODE_ENABLE
,
.
bet_max_consecutive
=
50
,
.
psm_entry_retries
=
8
,
.
psm_exit_retries
=
16
,
.
psm_entry_nullfunc_retries
=
3
,
.
dynamic_ps_timeout
=
100
,
.
forced_ps
=
false
,
.
keep_alive_interval
=
55000
,
.
max_listen_interval
=
20
,
},
...
...
@@ -265,6 +272,7 @@ static struct conf_drv_settings default_conf = {
.
min_dwell_time_passive
=
100000
,
.
max_dwell_time_passive
=
100000
,
.
num_probe_reqs
=
2
,
.
split_scan_timeout
=
50000
,
},
.
sched_scan
=
{
/* sched_scan requires dwell times in TU instead of TU/1000 */
...
...
@@ -672,8 +680,6 @@ static int wl1271_plt_init(struct wl1271 *wl)
if
(
ret
<
0
)
return
ret
;
}
if
(
ret
<
0
)
return
ret
;
/* Chip-specific initializations */
ret
=
wl1271_chip_specific_init
(
wl
);
...
...
@@ -985,16 +991,70 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
return
IRQ_HANDLED
;
}
static
int
wl1271_fetch_firmware
(
struct
wl1271
*
wl
)
struct
vif_counter_data
{
u8
counter
;
struct
ieee80211_vif
*
cur_vif
;
bool
cur_vif_running
;
};
static
void
wl12xx_vif_count_iter
(
void
*
data
,
u8
*
mac
,
struct
ieee80211_vif
*
vif
)
{
struct
vif_counter_data
*
counter
=
data
;
counter
->
counter
++
;
if
(
counter
->
cur_vif
==
vif
)
counter
->
cur_vif_running
=
true
;
}
/* caller must not hold wl->mutex, as it might deadlock */
static
void
wl12xx_get_vif_count
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
cur_vif
,
struct
vif_counter_data
*
data
)
{
memset
(
data
,
0
,
sizeof
(
*
data
));
data
->
cur_vif
=
cur_vif
;
ieee80211_iterate_active_interfaces
(
hw
,
wl12xx_vif_count_iter
,
data
);
}
static
int
wl12xx_fetch_firmware
(
struct
wl1271
*
wl
,
bool
plt
)
{
const
struct
firmware
*
fw
;
const
char
*
fw_name
;
enum
wl12xx_fw_type
fw_type
;
int
ret
;
if
(
plt
)
{
fw_type
=
WL12XX_FW_TYPE_PLT
;
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
fw_name
=
WL128X_PLT_FW_NAME
;
else
fw_name
=
WL127X_PLT_FW_NAME
;
}
else
{
/*
* we can't call wl12xx_get_vif_count() here because
* wl->mutex is taken, so use the cached last_vif_count value
*/
if
(
wl
->
last_vif_count
>
1
)
{
fw_type
=
WL12XX_FW_TYPE_MULTI
;
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
fw_name
=
WL128X_FW_NAME
;
fw_name
=
WL128X_FW_NAME_MULTI
;
else
fw_name
=
WL127X_FW_NAME
;
fw_name
=
WL127X_FW_NAME_MULTI
;
}
else
{
fw_type
=
WL12XX_FW_TYPE_NORMAL
;
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
fw_name
=
WL128X_FW_NAME_SINGLE
;
else
fw_name
=
WL127X_FW_NAME_SINGLE
;
}
}
if
(
wl
->
fw_type
==
fw_type
)
return
0
;
wl1271_debug
(
DEBUG_BOOT
,
"booting firmware %s"
,
fw_name
);
...
...
@@ -1013,6 +1073,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
}
vfree
(
wl
->
fw
);
wl
->
fw_type
=
WL12XX_FW_TYPE_NONE
;
wl
->
fw_len
=
fw
->
size
;
wl
->
fw
=
vmalloc
(
wl
->
fw_len
);
...
...
@@ -1024,7 +1085,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
memcpy
(
wl
->
fw
,
fw
->
data
,
wl
->
fw_len
);
ret
=
0
;
wl
->
fw_type
=
fw_type
;
out:
release_firmware
(
fw
);
...
...
@@ -1152,7 +1213,7 @@ static void wl1271_recovery_work(struct work_struct *work)
mutex_lock
(
&
wl
->
mutex
);
if
(
wl
->
state
!=
WL1271_STATE_ON
)
if
(
wl
->
state
!=
WL1271_STATE_ON
||
wl
->
plt
)
goto
out_unlock
;
/* Avoid a recursive recovery */
...
...
@@ -1232,10 +1293,9 @@ static int wl1271_setup(struct wl1271 *wl)
return
0
;
}
static
int
wl12
71_chip_wakeup
(
struct
wl1271
*
wl
)
static
int
wl12
xx_set_power_on
(
struct
wl1271
*
wl
)
{
struct
wl1271_partition_set
partition
;
int
ret
=
0
;
int
ret
;
msleep
(
WL1271_PRE_POWER_ON_SLEEP
);
ret
=
wl1271_power_on
(
wl
);
...
...
@@ -1245,20 +1305,22 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
wl1271_io_reset
(
wl
);
wl1271_io_init
(
wl
);
/* 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
);
wl1271_set_partition
(
wl
,
&
wl12xx_part_table
[
PART_DOWN
]);
/* ELP module wake up */
wl1271_fw_wakeup
(
wl
);
/* whal_FwCtrl_BootSm() */
out:
return
ret
;
}
/* 0. read chip id from CHIP_ID */
wl
->
chip
.
id
=
wl1271_read32
(
wl
,
CHIP_ID_B
);
static
int
wl12xx_chip_wakeup
(
struct
wl1271
*
wl
,
bool
plt
)
{
int
ret
=
0
;
ret
=
wl12xx_set_power_on
(
wl
);
if
(
ret
<
0
)
goto
out
;
/*
* For wl127x based devices we could use the default block
...
...
@@ -1307,11 +1369,9 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
goto
out
;
}
if
(
wl
->
fw
==
NULL
)
{
ret
=
wl1271_fetch_firmware
(
wl
);
ret
=
wl12xx_fetch_firmware
(
wl
,
plt
);
if
(
ret
<
0
)
goto
out
;
}
/* No NVS from netlink, try to get it from the filesystem */
if
(
wl
->
nvs
==
NULL
)
{
...
...
@@ -1343,7 +1403,7 @@ int wl1271_plt_start(struct wl1271 *wl)
while
(
retries
)
{
retries
--
;
ret
=
wl12
71_chip_wakeup
(
wl
);
ret
=
wl12
xx_chip_wakeup
(
wl
,
true
);
if
(
ret
<
0
)
goto
power_off
;
...
...
@@ -1355,7 +1415,8 @@ int wl1271_plt_start(struct wl1271 *wl)
if
(
ret
<
0
)
goto
irq_disable
;
wl
->
state
=
WL1271_STATE_PLT
;
wl
->
plt
=
true
;
wl
->
state
=
WL1271_STATE_ON
;
wl1271_notice
(
"firmware booted in PLT mode (%s)"
,
wl
->
chip
.
fw_ver_str
);
...
...
@@ -1391,41 +1452,51 @@ int wl1271_plt_start(struct wl1271 *wl)
return
ret
;
}
static
int
__
wl1271_plt_stop
(
struct
wl1271
*
wl
)
int
wl1271_plt_stop
(
struct
wl1271
*
wl
)
{
int
ret
=
0
;
wl1271_notice
(
"power down"
);
if
(
wl
->
state
!=
WL1271_STATE_PLT
)
{
/*
* Interrupts must be disabled before setting the state to OFF.
* Otherwise, the interrupt handler might be called and exit without
* reading the interrupt status.
*/
wl1271_disable_interrupts
(
wl
);
mutex_lock
(
&
wl
->
mutex
);
if
(
!
wl
->
plt
)
{
mutex_unlock
(
&
wl
->
mutex
);
/*
* This will not necessarily enable interrupts as interrupts
* may have been disabled when op_stop was called. It will,
* however, balance the above call to disable_interrupts().
*/
wl1271_enable_interrupts
(
wl
);
wl1271_error
(
"cannot power down because not in PLT "
"state: %d"
,
wl
->
state
);
ret
=
-
EBUSY
;
goto
out
;
}
wl1271_power_off
(
wl
);
wl
->
state
=
WL1271_STATE_OFF
;
wl
->
rx_counter
=
0
;
mutex_unlock
(
&
wl
->
mutex
);
wl1271_disable_interrupts
(
wl
);
wl1271_flush_deferred_work
(
wl
);
cancel_work_sync
(
&
wl
->
netstack_work
);
cancel_work_sync
(
&
wl
->
recovery_work
);
mutex_lock
(
&
wl
->
mutex
);
out:
return
ret
;
}
int
wl1271_plt_stop
(
struct
wl1271
*
wl
)
{
int
ret
;
cancel_delayed_work_sync
(
&
wl
->
elp_work
);
mutex_lock
(
&
wl
->
mutex
);
ret
=
__wl1271_plt_stop
(
wl
);
wl1271_power_off
(
wl
);
wl
->
flags
=
0
;
wl
->
state
=
WL1271_STATE_OFF
;
wl
->
plt
=
false
;
wl
->
rx_counter
=
0
;
mutex_unlock
(
&
wl
->
mutex
);
out:
return
ret
;
}
...
...
@@ -1574,38 +1645,16 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl,
if
(
ret
<
0
)
goto
out_unlock
;
/* enter psm if needed*/
if
(
!
test_bit
(
WLVIF_FLAG_PSM
,
&
wlvif
->
flags
))
{
DECLARE_COMPLETION_ONSTACK
(
comp
l
);
ret
=
wl1271_acx_wake_up_conditions
(
wl
,
wlvif
,
wl
->
conf
.
conn
.
suspend_wake_up_event
,
wl
->
conf
.
conn
.
suspend_listen_interva
l
);
wlvif
->
ps_compl
=
&
compl
;
ret
=
wl1271_ps_set_mode
(
wl
,
wlvif
,
STATION_POWER_SAVE_MODE
,
wlvif
->
basic_rate
,
true
);
if
(
ret
<
0
)
goto
out_sleep
;
wl1271_error
(
"suspend: set wake up conditions failed: %d"
,
ret
)
;
/* we must unlock here so we will be able to get events */
wl1271_ps_elp_sleep
(
wl
);
mutex_unlock
(
&
wl
->
mutex
);
ret
=
wait_for_completion_timeout
(
&
compl
,
msecs_to_jiffies
(
WL1271_PS_COMPLETE_TIMEOUT
));
mutex_lock
(
&
wl
->
mutex
);
if
(
ret
<=
0
)
{
wl1271_warning
(
"couldn't enter ps mode!"
);
ret
=
-
EBUSY
;
goto
out_cleanup
;
}
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out_cleanup
;
}
out_sleep:
wl1271_ps_elp_sleep
(
wl
);
out_cleanup:
wlvif
->
ps_compl
=
NULL
;
out_unlock:
mutex_unlock
(
&
wl
->
mutex
);
return
ret
;
...
...
@@ -1648,11 +1697,11 @@ static int wl1271_configure_suspend(struct wl1271 *wl,
static
void
wl1271_configure_resume
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
int
ret
;
bool
is_sta
=
wlvif
->
bss_type
==
BSS_TYPE_STA_BSS
;
int
ret
=
0
;
bool
is_ap
=
wlvif
->
bss_type
==
BSS_TYPE_AP_BSS
;
bool
is_sta
=
wlvif
->
bss_type
==
BSS_TYPE_STA_BSS
;
if
(
!
is_sta
&&
!
is_ap
)
if
(
(
!
is_ap
)
&&
(
!
is_sta
)
)
return
;
mutex_lock
(
&
wl
->
mutex
);
...
...
@@ -1661,12 +1710,16 @@ static void wl1271_configure_resume(struct wl1271 *wl,
goto
out
;
if
(
is_sta
)
{
/* exit psm if it wasn't configured */
if
(
!
test_bit
(
WLVIF_FLAG_PSM_REQUESTED
,
&
wlvif
->
flags
))
wl1271_ps_set_mode
(
wl
,
wlvif
,
STATION_ACTIVE_MODE
,
wlvif
->
basic_rate
,
true
);
ret
=
wl1271_acx_wake_up_conditions
(
wl
,
wlvif
,
wl
->
conf
.
conn
.
wake_up_event
,
wl
->
conf
.
conn
.
listen_interval
);
if
(
ret
<
0
)
wl1271_error
(
"resume: wake up conditions failed: %d"
,
ret
);
}
else
if
(
is_ap
)
{
wl1271_acx_beacon_filter_opt
(
wl
,
wlvif
,
false
);
ret
=
wl1271_acx_beacon_filter_opt
(
wl
,
wlvif
,
false
);
}
wl1271_ps_elp_sleep
(
wl
);
...
...
@@ -1709,9 +1762,6 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
wl1271_enable_interrupts
(
wl
);
flush_work
(
&
wl
->
tx_work
);
wl12xx_for_each_wlvif
(
wl
,
wlvif
)
{
flush_delayed_work
(
&
wlvif
->
pspoll_work
);
}
flush_delayed_work
(
&
wl
->
elp_work
);
return
0
;
...
...
@@ -1778,11 +1828,25 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
wl1271_debug
(
DEBUG_MAC80211
,
"mac80211 stop"
);
/*
* Interrupts must be disabled before setting the state to OFF.
* Otherwise, the interrupt handler might be called and exit without
* reading the interrupt status.
*/
wl1271_disable_interrupts
(
wl
);
mutex_lock
(
&
wl
->
mutex
);
if
(
wl
->
state
==
WL1271_STATE_OFF
)
{
mutex_unlock
(
&
wl
->
mutex
);
/*
* This will not necessarily enable interrupts as interrupts
* may have been disabled when op_stop was called. It will,
* however, balance the above call to disable_interrupts().
*/
wl1271_enable_interrupts
(
wl
);
return
;
}
/*
* this must be before the cancel_work calls below, so that the work
* functions don't perform further work.
...
...
@@ -1794,7 +1858,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
list_del
(
&
wl
->
list
);
mutex_unlock
(
&
wl_list_mutex
);
wl1271_disable_interrupts
(
wl
);
wl1271_flush_deferred_work
(
wl
);
cancel_delayed_work_sync
(
&
wl
->
scan_complete_work
);
cancel_work_sync
(
&
wl
->
netstack_work
);
...
...
@@ -1969,7 +2032,6 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
wl1271_rx_streaming_enable_work
);
INIT_WORK
(
&
wlvif
->
rx_streaming_disable_work
,
wl1271_rx_streaming_disable_work
);
INIT_DELAYED_WORK
(
&
wlvif
->
pspoll_work
,
wl1271_pspoll_work
);
INIT_LIST_HEAD
(
&
wlvif
->
list
);
setup_timer
(
&
wlvif
->
rx_streaming_timer
,
wl1271_rx_streaming_timer
,
...
...
@@ -1986,7 +2048,7 @@ static bool wl12xx_init_fw(struct wl1271 *wl)
while
(
retries
)
{
retries
--
;
ret
=
wl12
71_chip_wakeup
(
wl
);
ret
=
wl12
xx_chip_wakeup
(
wl
,
false
);
if
(
ret
<
0
)
goto
power_off
;
...
...
@@ -2051,11 +2113,60 @@ static bool wl12xx_dev_role_started(struct wl12xx_vif *wlvif)
return
wlvif
->
dev_hlid
!=
WL12XX_INVALID_LINK_ID
;
}
/*
* Check whether a fw switch (i.e. moving from one loaded
* fw to another) is needed. This function is also responsible
* for updating wl->last_vif_count, so it must be called before
* loading a non-plt fw (so the correct fw (single-role/multi-role)
* will be used).
*/
static
bool
wl12xx_need_fw_change
(
struct
wl1271
*
wl
,
struct
vif_counter_data
vif_counter_data
,
bool
add
)
{
enum
wl12xx_fw_type
current_fw
=
wl
->
fw_type
;
u8
vif_count
=
vif_counter_data
.
counter
;
if
(
test_bit
(
WL1271_FLAG_VIF_CHANGE_IN_PROGRESS
,
&
wl
->
flags
))
return
false
;
/* increase the vif count if this is a new vif */
if
(
add
&&
!
vif_counter_data
.
cur_vif_running
)
vif_count
++
;
wl
->
last_vif_count
=
vif_count
;
/* no need for fw change if the device is OFF */
if
(
wl
->
state
==
WL1271_STATE_OFF
)
return
false
;
if
(
vif_count
>
1
&&
current_fw
==
WL12XX_FW_TYPE_NORMAL
)
return
true
;
if
(
vif_count
<=
1
&&
current_fw
==
WL12XX_FW_TYPE_MULTI
)
return
true
;
return
false
;
}
/*
* Enter "forced psm". Make sure the sta is in psm against the ap,
* to make the fw switch a bit more disconnection-persistent.
*/
static
void
wl12xx_force_active_psm
(
struct
wl1271
*
wl
)
{
struct
wl12xx_vif
*
wlvif
;
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
wl1271_ps_set_mode
(
wl
,
wlvif
,
STATION_POWER_SAVE_MODE
);
}
}
static
int
wl1271_op_add_interface
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
)
{
struct
wl1271
*
wl
=
hw
->
priv
;
struct
wl12xx_vif
*
wlvif
=
wl12xx_vif_to_data
(
vif
);
struct
vif_counter_data
vif_count
;
int
ret
=
0
;
u8
role_type
;
bool
booted
=
false
;
...
...
@@ -2066,18 +2177,13 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
wl1271_debug
(
DEBUG_MAC80211
,
"mac80211 add interface type %d mac %pM"
,
ieee80211_vif_type_p2p
(
vif
),
vif
->
addr
);
wl12xx_get_vif_count
(
hw
,
vif
,
&
vif_count
);
mutex_lock
(
&
wl
->
mutex
);
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out_unlock
;
if
(
wl
->
vif
)
{
wl1271_debug
(
DEBUG_MAC80211
,
"multiple vifs are not supported yet"
);
ret
=
-
EBUSY
;
goto
out
;
}
/*
* in some very corner case HW recovery scenarios its possible to
* get here before __wl1271_op_remove_interface is complete, so
...
...
@@ -2089,6 +2195,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
goto
out
;
}
ret
=
wl12xx_init_vif_data
(
wl
,
vif
);
if
(
ret
<
0
)
goto
out
;
...
...
@@ -2100,6 +2207,13 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
goto
out
;
}
if
(
wl12xx_need_fw_change
(
wl
,
vif_count
,
true
))
{
wl12xx_force_active_psm
(
wl
);
mutex_unlock
(
&
wl
->
mutex
);
wl1271_recovery_work
(
&
wl
->
recovery_work
);
return
0
;
}
/*
* TODO: after the nvs issue will be solved, move this block
* to start(), and make sure here the driver is ON.
...
...
@@ -2109,7 +2223,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
* we still need this in order to configure the fw
* while uploading the nvs
*/
memcpy
(
wl
->
mac_
addr
,
vif
->
addr
,
ETH_ALEN
);
memcpy
(
wl
->
addresses
[
0
].
addr
,
vif
->
addr
,
ETH_ALEN
);
booted
=
wl12xx_init_fw
(
wl
);
if
(
!
booted
)
{
...
...
@@ -2142,7 +2256,6 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
if
(
ret
<
0
)
goto
out
;
wl
->
vif
=
vif
;
list_add
(
&
wlvif
->
list
,
&
wl
->
wlvif_list
);
set_bit
(
WLVIF_FLAG_INITIALIZED
,
&
wlvif
->
flags
);
...
...
@@ -2175,18 +2288,12 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
if
(
!
test_and_clear_bit
(
WLVIF_FLAG_INITIALIZED
,
&
wlvif
->
flags
))
return
;
wl
->
vif
=
NULL
;
/* because of hardware recovery, we may get here twice */
if
(
wl
->
state
!=
WL1271_STATE_ON
)
return
;
wl1271_info
(
"down"
);
/* enable dyn ps just in case (if left on due to fw crash etc) */
if
(
wlvif
->
bss_type
==
BSS_TYPE_STA_BSS
)
ieee80211_enable_dyn_ps
(
vif
);
if
(
wl
->
scan
.
state
!=
WL1271_SCAN_STATE_IDLE
&&
wl
->
scan_vif
==
vif
)
{
wl
->
scan
.
state
=
WL1271_SCAN_STATE_IDLE
;
...
...
@@ -2253,10 +2360,10 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
wl
->
sta_count
--
;
mutex_unlock
(
&
wl
->
mutex
);
del_timer_sync
(
&
wlvif
->
rx_streaming_timer
);
cancel_work_sync
(
&
wlvif
->
rx_streaming_enable_work
);
cancel_work_sync
(
&
wlvif
->
rx_streaming_disable_work
);
cancel_delayed_work_sync
(
&
wlvif
->
pspoll_work
);
mutex_lock
(
&
wl
->
mutex
);
}
...
...
@@ -2267,7 +2374,10 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
struct
wl1271
*
wl
=
hw
->
priv
;
struct
wl12xx_vif
*
wlvif
=
wl12xx_vif_to_data
(
vif
);
struct
wl12xx_vif
*
iter
;
struct
vif_counter_data
vif_count
;
bool
cancel_recovery
=
true
;
wl12xx_get_vif_count
(
hw
,
vif
,
&
vif_count
);
mutex_lock
(
&
wl
->
mutex
);
if
(
wl
->
state
==
WL1271_STATE_OFF
||
...
...
@@ -2286,8 +2396,14 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
break
;
}
WARN_ON
(
iter
!=
wlvif
);
if
(
wl12xx_need_fw_change
(
wl
,
vif_count
,
false
))
{
wl12xx_force_active_psm
(
wl
);
wl12xx_queue_recovery_work
(
wl
);
cancel_recovery
=
false
;
}
out:
mutex_unlock
(
&
wl
->
mutex
);
if
(
cancel_recovery
)
cancel_work_sync
(
&
wl
->
recovery_work
);
}
...
...
@@ -2295,11 +2411,18 @@ static int wl12xx_op_change_interface(struct ieee80211_hw *hw,
struct
ieee80211_vif
*
vif
,
enum
nl80211_iftype
new_type
,
bool
p2p
)
{
struct
wl1271
*
wl
=
hw
->
priv
;
int
ret
;
set_bit
(
WL1271_FLAG_VIF_CHANGE_IN_PROGRESS
,
&
wl
->
flags
);
wl1271_op_remove_interface
(
hw
,
vif
);
vif
->
type
=
ieee80211_iftype_p2p
(
new_type
,
p2p
);
vif
->
p2p
=
p2p
;
return
wl1271_op_add_interface
(
hw
,
vif
);
ret
=
wl1271_op_add_interface
(
hw
,
vif
);
clear_bit
(
WL1271_FLAG_VIF_CHANGE_IN_PROGRESS
,
&
wl
->
flags
);
return
ret
;
}
static
int
wl1271_join
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
...
...
@@ -2320,6 +2443,9 @@ static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif,
if
(
test_bit
(
WLVIF_FLAG_STA_ASSOCIATED
,
&
wlvif
->
flags
))
wl1271_info
(
"JOIN while associated."
);
/* clear encryption type */
wlvif
->
encryption_type
=
KEY_NONE
;
if
(
set_assoc
)
set_bit
(
WLVIF_FLAG_STA_ASSOCIATED
,
&
wlvif
->
flags
);
...
...
@@ -2503,38 +2629,41 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif,
}
}
/*
* if mac80211 changes the PSM mode, make sure the mode is not
* incorrectly changed after the pspoll failure active window.
*/
if
(
changed
&
IEEE80211_CONF_CHANGE_PS
)
clear_bit
(
WLVIF_FLAG_PSPOLL_FAILURE
,
&
wlvif
->
flags
);
if
((
changed
&
IEEE80211_CONF_CHANGE_PS
)
&&
!
is_ap
)
{
if
(
conf
->
flags
&
IEEE80211_CONF_PS
&&
!
test_bit
(
WLVIF_FLAG_PSM_REQUESTED
,
&
wlvif
->
flags
))
{
set_bit
(
WLVIF_FLAG_PSM_REQUESTED
,
&
wlvif
->
flags
);
if
((
conf
->
flags
&
IEEE80211_CONF_PS
)
&&
test_bit
(
WLVIF_FLAG_STA_ASSOCIATED
,
&
wlvif
->
flags
)
&&
!
test_bit
(
WLVIF_FLAG_IN_PS
,
&
wlvif
->
flags
))
{
/*
* We enter PSM only if we're already associated.
* If we're not, we'll enter it when joining an SSID,
* through the bss_info_changed() hook.
*/
if
(
test_bit
(
WLVIF_FLAG_STA_ASSOCIATED
,
&
wlvif
->
flags
))
{
wl1271_debug
(
DEBUG_PSM
,
"psm enabled"
);
ret
=
wl1271_ps_set_mode
(
wl
,
wlvif
,
STATION_POWER_SAVE_MODE
,
wlvif
->
basic_rate
,
true
);
int
ps_mode
;
char
*
ps_mode_str
;
if
(
wl
->
conf
.
conn
.
forced_ps
)
{
ps_mode
=
STATION_POWER_SAVE_MODE
;
ps_mode_str
=
"forced"
;
}
else
{
ps_mode
=
STATION_AUTO_PS_MODE
;
ps_mode_str
=
"auto"
;
}
wl1271_debug
(
DEBUG_PSM
,
"%s ps enabled"
,
ps_mode_str
);
ret
=
wl1271_ps_set_mode
(
wl
,
wlvif
,
ps_mode
);
if
(
ret
<
0
)
wl1271_warning
(
"enter %s ps failed %d"
,
ps_mode_str
,
ret
);
}
else
if
(
!
(
conf
->
flags
&
IEEE80211_CONF_PS
)
&&
test_bit
(
WLVIF_FLAG_PSM_REQUESTED
,
&
wlvif
->
flags
))
{
wl1271_debug
(
DEBUG_PSM
,
"psm disabled"
);
test_bit
(
WLVIF_FLAG_IN_PS
,
&
wlvif
->
flags
))
{
clear_bit
(
WLVIF_FLAG_PSM_REQUESTED
,
&
wlvif
->
flags
);
wl1271_debug
(
DEBUG_PSM
,
"auto ps disabled"
);
if
(
test_bit
(
WLVIF_FLAG_PSM
,
&
wlvif
->
flags
))
ret
=
wl1271_ps_set_mode
(
wl
,
wlvif
,
STATION_ACTIVE_MODE
,
wlvif
->
basic_rate
,
true
);
STATION_ACTIVE_MODE
);
if
(
ret
<
0
)
wl1271_warning
(
"exit auto ps failed %d"
,
ret
);
}
}
if
(
conf
->
power_level
!=
wlvif
->
power_level
)
{
...
...
@@ -2974,6 +3103,21 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
wl1271_error
(
"Could not add or replace key"
);
goto
out_sleep
;
}
/*
* reconfiguring arp response if the unicast (or common)
* encryption key type was changed
*/
if
(
wlvif
->
bss_type
==
BSS_TYPE_STA_BSS
&&
(
sta
||
key_type
==
KEY_WEP
)
&&
wlvif
->
encryption_type
!=
key_type
)
{
wlvif
->
encryption_type
=
key_type
;
ret
=
wl1271_cmd_build_arp_rsp
(
wl
,
wlvif
);
if
(
ret
<
0
)
{
wl1271_warning
(
"build arp rsp failed: %d"
,
ret
);
goto
out_sleep
;
}
}
break
;
case
DISABLE_KEY
:
...
...
@@ -3043,10 +3187,6 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
goto
out_sleep
;
}
/* cancel ROC before scanning */
if
(
wl12xx_dev_role_started
(
wlvif
))
wl12xx_stop_dev
(
wl
,
wlvif
);
ret
=
wl1271_scan
(
hw
->
priv
,
vif
,
ssid
,
len
,
req
);
out_sleep:
wl1271_ps_elp_sleep
(
wl
);
...
...
@@ -3108,6 +3248,11 @@ static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw,
mutex_lock
(
&
wl
->
mutex
);
if
(
wl
->
state
==
WL1271_STATE_OFF
)
{
ret
=
-
EAGAIN
;
goto
out
;
}
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out
;
...
...
@@ -3139,6 +3284,9 @@ static void wl1271_op_sched_scan_stop(struct ieee80211_hw *hw,
mutex_lock
(
&
wl
->
mutex
);
if
(
wl
->
state
==
WL1271_STATE_OFF
)
goto
out
;
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out
;
...
...
@@ -3266,6 +3414,7 @@ static void wl12xx_remove_vendor_ie(struct sk_buff *skb,
static
int
wl1271_ap_set_probe_resp_tmpl
(
struct
wl1271
*
wl
,
u32
rates
,
struct
ieee80211_vif
*
vif
)
{
struct
wl12xx_vif
*
wlvif
=
wl12xx_vif_to_data
(
vif
);
struct
sk_buff
*
skb
;
int
ret
;
...
...
@@ -3273,7 +3422,7 @@ static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, u32 rates,
if
(
!
skb
)
return
-
EOPNOTSUPP
;
ret
=
wl1271_cmd_template_set
(
wl
,
ret
=
wl1271_cmd_template_set
(
wl
,
wlvif
->
role_id
,
CMD_TEMPL_AP_PROBE_RESPONSE
,
skb
->
data
,
skb
->
len
,
0
,
...
...
@@ -3297,7 +3446,7 @@ static int wl1271_ap_set_probe_resp_tmpl_legacy(struct wl1271 *wl,
/* no need to change probe response if the SSID is set correctly */
if
(
wlvif
->
ssid_len
>
0
)
return
wl1271_cmd_template_set
(
wl
,
return
wl1271_cmd_template_set
(
wl
,
wlvif
->
role_id
,
CMD_TEMPL_AP_PROBE_RESPONSE
,
probe_rsp_data
,
probe_rsp_len
,
0
,
...
...
@@ -3334,7 +3483,7 @@ static int wl1271_ap_set_probe_resp_tmpl_legacy(struct wl1271 *wl,
ptr
,
probe_rsp_len
-
(
ptr
-
probe_rsp_data
));
templ_len
+=
probe_rsp_len
-
(
ptr
-
probe_rsp_data
);
return
wl1271_cmd_template_set
(
wl
,
return
wl1271_cmd_template_set
(
wl
,
wlvif
->
role_id
,
CMD_TEMPL_AP_PROBE_RESPONSE
,
probe_rsp_templ
,
templ_len
,
0
,
...
...
@@ -3431,7 +3580,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
min_rate
=
wl1271_tx_min_rate_get
(
wl
,
wlvif
->
basic_rate_set
);
tmpl_id
=
is_ap
?
CMD_TEMPL_AP_BEACON
:
CMD_TEMPL_BEACON
;
ret
=
wl1271_cmd_template_set
(
wl
,
tmpl_id
,
ret
=
wl1271_cmd_template_set
(
wl
,
wlvif
->
role_id
,
tmpl_id
,
beacon
->
data
,
beacon
->
len
,
0
,
min_rate
);
...
...
@@ -3470,7 +3619,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
beacon
->
len
,
min_rate
);
else
ret
=
wl1271_cmd_template_set
(
wl
,
ret
=
wl1271_cmd_template_set
(
wl
,
wlvif
->
role_id
,
CMD_TEMPL_PROBE_RESPONSE
,
beacon
->
data
,
beacon
->
len
,
0
,
...
...
@@ -3634,7 +3783,8 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
wlvif
->
rssi_thold
=
bss_conf
->
cqm_rssi_thold
;
}
if
(
changed
&
BSS_CHANGED_BSSID
)
if
(
changed
&
BSS_CHANGED_BSSID
&&
(
is_ibss
||
bss_conf
->
assoc
))
if
(
!
is_zero_ether_addr
(
bss_conf
->
bssid
))
{
ret
=
wl12xx_cmd_build_null_data
(
wl
,
wlvif
);
if
(
ret
<
0
)
...
...
@@ -3673,8 +3823,6 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
wlvif
->
aid
=
bss_conf
->
aid
;
set_assoc
=
true
;
wlvif
->
ps_poll_failures
=
0
;
/*
* use basic rates from AP, and determine lowest rate
* to use with control frames.
...
...
@@ -3734,9 +3882,6 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
dev_kfree_skb
(
wlvif
->
probereq
);
wlvif
->
probereq
=
NULL
;
/* re-enable dynamic ps - just in case */
ieee80211_enable_dyn_ps
(
vif
);
/* revert back to minimum rates for the current band */
wl1271_set_band_rate
(
wl
,
wlvif
);
wlvif
->
basic_rate
=
...
...
@@ -3810,34 +3955,6 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
if
(
ret
<
0
)
goto
out
;
if
(
changed
&
BSS_CHANGED_ARP_FILTER
)
{
__be32
addr
=
bss_conf
->
arp_addr_list
[
0
];
WARN_ON
(
wlvif
->
bss_type
!=
BSS_TYPE_STA_BSS
);
if
(
bss_conf
->
arp_addr_cnt
==
1
&&
bss_conf
->
arp_filter_enabled
)
{
/*
* The template should have been configured only upon
* association. however, it seems that the correct ip
* isn't being set (when sending), so we have to
* reconfigure the template upon every ip change.
*/
ret
=
wl1271_cmd_build_arp_rsp
(
wl
,
wlvif
,
addr
);
if
(
ret
<
0
)
{
wl1271_warning
(
"build arp rsp failed: %d"
,
ret
);
goto
out
;
}
ret
=
wl1271_acx_arp_ip_filter
(
wl
,
wlvif
,
ACX_ARP_FILTER_ARP_FILTERING
,
addr
);
}
else
ret
=
wl1271_acx_arp_ip_filter
(
wl
,
wlvif
,
0
,
addr
);
if
(
ret
<
0
)
goto
out
;
}
if
(
do_join
)
{
ret
=
wl1271_join
(
wl
,
wlvif
,
set_assoc
);
if
(
ret
<
0
)
{
...
...
@@ -3863,19 +3980,6 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
if
(
ret
<
0
)
goto
out
;
}
/* If we want to go in PSM but we're not there yet */
if
(
test_bit
(
WLVIF_FLAG_PSM_REQUESTED
,
&
wlvif
->
flags
)
&&
!
test_bit
(
WLVIF_FLAG_PSM
,
&
wlvif
->
flags
))
{
enum
wl1271_cmd_ps_mode
mode
;
mode
=
STATION_POWER_SAVE_MODE
;
ret
=
wl1271_ps_set_mode
(
wl
,
wlvif
,
mode
,
wlvif
->
basic_rate
,
true
);
if
(
ret
<
0
)
goto
out
;
}
}
/* Handle new association with HT. Do this after join. */
...
...
@@ -3917,6 +4021,41 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
}
}
/* Handle arp filtering. Done after join. */
if
((
changed
&
BSS_CHANGED_ARP_FILTER
)
||
(
!
is_ibss
&&
(
changed
&
BSS_CHANGED_QOS
)))
{
__be32
addr
=
bss_conf
->
arp_addr_list
[
0
];
wlvif
->
sta
.
qos
=
bss_conf
->
qos
;
WARN_ON
(
wlvif
->
bss_type
!=
BSS_TYPE_STA_BSS
);
if
(
bss_conf
->
arp_addr_cnt
==
1
&&
bss_conf
->
arp_filter_enabled
)
{
wlvif
->
ip_addr
=
addr
;
/*
* The template should have been configured only upon
* association. however, it seems that the correct ip
* isn't being set (when sending), so we have to
* reconfigure the template upon every ip change.
*/
ret
=
wl1271_cmd_build_arp_rsp
(
wl
,
wlvif
);
if
(
ret
<
0
)
{
wl1271_warning
(
"build arp rsp failed: %d"
,
ret
);
goto
out
;
}
ret
=
wl1271_acx_arp_ip_filter
(
wl
,
wlvif
,
(
ACX_ARP_FILTER_ARP_FILTERING
|
ACX_ARP_FILTER_AUTO_ARP
),
addr
);
}
else
{
wlvif
->
ip_addr
=
0
;
ret
=
wl1271_acx_arp_ip_filter
(
wl
,
wlvif
,
0
,
addr
);
}
if
(
ret
<
0
)
goto
out
;
}
out:
return
;
}
...
...
@@ -4012,6 +4151,7 @@ static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw,
{
struct
wl1271
*
wl
=
hw
->
priv
;
struct
wl12xx_vif
*
wlvif
=
wl12xx_vif_to_data
(
vif
);
u64
mactime
=
ULLONG_MAX
;
int
ret
;
...
...
@@ -4026,7 +4166,7 @@ static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw,
if
(
ret
<
0
)
goto
out
;
ret
=
wl12
71_acx_tsf_info
(
wl
,
&
mactime
);
ret
=
wl12
xx_acx_tsf_info
(
wl
,
wlvif
,
&
mactime
);
if
(
ret
<
0
)
goto
out_sleep
;
...
...
@@ -4373,7 +4513,7 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
/* TODO: change mac80211 to pass vif as param */
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
ret
=
wl12xx_cmd_channel_switch
(
wl
,
ch_switch
);
ret
=
wl12xx_cmd_channel_switch
(
wl
,
wlvif
,
ch_switch
);
if
(
!
ret
)
set_bit
(
WLVIF_FLAG_CS_PROGRESS
,
&
wlvif
->
flags
);
...
...
@@ -4467,6 +4607,7 @@ static struct ieee80211_channel wl1271_channels[] = {
/* mapping to indexes for wl1271_rates */
static
const
u8
wl1271_rate_to_idx_2ghz
[]
=
{
/* MCS rates are used only with 11n */
7
,
/* CONF_HW_RXTX_RATE_MCS7_SGI */
7
,
/* CONF_HW_RXTX_RATE_MCS7 */
6
,
/* CONF_HW_RXTX_RATE_MCS6 */
5
,
/* CONF_HW_RXTX_RATE_MCS5 */
...
...
@@ -4588,6 +4729,7 @@ static struct ieee80211_channel wl1271_channels_5ghz[] = {
/* mapping to indexes for wl1271_rates_5ghz */
static
const
u8
wl1271_rate_to_idx_5ghz
[]
=
{
/* MCS rates are used only with 11n */
7
,
/* CONF_HW_RXTX_RATE_MCS7_SGI */
7
,
/* CONF_HW_RXTX_RATE_MCS7 */
6
,
/* CONF_HW_RXTX_RATE_MCS6 */
5
,
/* CONF_HW_RXTX_RATE_MCS5 */
...
...
@@ -4828,13 +4970,120 @@ static struct bin_attribute fwlog_attr = {
.
read
=
wl1271_sysfs_read_fwlog
,
};
static
bool
wl12xx_mac_in_fuse
(
struct
wl1271
*
wl
)
{
bool
supported
=
false
;
u8
major
,
minor
;
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
{
major
=
WL128X_PG_GET_MAJOR
(
wl
->
hw_pg_ver
);
minor
=
WL128X_PG_GET_MINOR
(
wl
->
hw_pg_ver
);
/* in wl128x we have the MAC address if the PG is >= (2, 1) */
if
(
major
>
2
||
(
major
==
2
&&
minor
>=
1
))
supported
=
true
;
}
else
{
major
=
WL127X_PG_GET_MAJOR
(
wl
->
hw_pg_ver
);
minor
=
WL127X_PG_GET_MINOR
(
wl
->
hw_pg_ver
);
/* in wl127x we have the MAC address if the PG is >= (3, 1) */
if
(
major
==
3
&&
minor
>=
1
)
supported
=
true
;
}
wl1271_debug
(
DEBUG_PROBE
,
"PG Ver major = %d minor = %d, MAC %s present"
,
major
,
minor
,
supported
?
"is"
:
"is not"
);
return
supported
;
}
static
void
wl12xx_derive_mac_addresses
(
struct
wl1271
*
wl
,
u32
oui
,
u32
nic
,
int
n
)
{
int
i
;
wl1271_debug
(
DEBUG_PROBE
,
"base address: oui %06x nic %06x, n %d"
,
oui
,
nic
,
n
);
if
(
nic
+
n
-
1
>
0xffffff
)
wl1271_warning
(
"NIC part of the MAC address wraps around!"
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
wl
->
addresses
[
i
].
addr
[
0
]
=
(
u8
)(
oui
>>
16
);
wl
->
addresses
[
i
].
addr
[
1
]
=
(
u8
)(
oui
>>
8
);
wl
->
addresses
[
i
].
addr
[
2
]
=
(
u8
)
oui
;
wl
->
addresses
[
i
].
addr
[
3
]
=
(
u8
)(
nic
>>
16
);
wl
->
addresses
[
i
].
addr
[
4
]
=
(
u8
)(
nic
>>
8
);
wl
->
addresses
[
i
].
addr
[
5
]
=
(
u8
)
nic
;
nic
++
;
}
wl
->
hw
->
wiphy
->
n_addresses
=
n
;
wl
->
hw
->
wiphy
->
addresses
=
wl
->
addresses
;
}
static
void
wl12xx_get_fuse_mac
(
struct
wl1271
*
wl
)
{
u32
mac1
,
mac2
;
wl1271_set_partition
(
wl
,
&
wl12xx_part_table
[
PART_DRPW
]);
mac1
=
wl1271_read32
(
wl
,
WL12XX_REG_FUSE_BD_ADDR_1
);
mac2
=
wl1271_read32
(
wl
,
WL12XX_REG_FUSE_BD_ADDR_2
);
/* these are the two parts of the BD_ADDR */
wl
->
fuse_oui_addr
=
((
mac2
&
0xffff
)
<<
8
)
+
((
mac1
&
0xff000000
)
>>
24
);
wl
->
fuse_nic_addr
=
mac1
&
0xffffff
;
wl1271_set_partition
(
wl
,
&
wl12xx_part_table
[
PART_DOWN
]);
}
static
int
wl12xx_get_hw_info
(
struct
wl1271
*
wl
)
{
int
ret
;
u32
die_info
;
ret
=
wl12xx_set_power_on
(
wl
);
if
(
ret
<
0
)
goto
out
;
wl
->
chip
.
id
=
wl1271_read32
(
wl
,
CHIP_ID_B
);
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
die_info
=
wl1271_top_reg_read
(
wl
,
WL128X_REG_FUSE_DATA_2_1
);
else
die_info
=
wl1271_top_reg_read
(
wl
,
WL127X_REG_FUSE_DATA_2_1
);
wl
->
hw_pg_ver
=
(
s8
)
(
die_info
&
PG_VER_MASK
)
>>
PG_VER_OFFSET
;
if
(
!
wl12xx_mac_in_fuse
(
wl
))
{
wl
->
fuse_oui_addr
=
0
;
wl
->
fuse_nic_addr
=
0
;
}
else
{
wl12xx_get_fuse_mac
(
wl
);
}
wl1271_power_off
(
wl
);
out:
return
ret
;
}
static
int
wl1271_register_hw
(
struct
wl1271
*
wl
)
{
int
ret
;
u32
oui_addr
=
0
,
nic_addr
=
0
;
if
(
wl
->
mac80211_registered
)
return
0
;
ret
=
wl12xx_get_hw_info
(
wl
);
if
(
ret
<
0
)
{
wl1271_error
(
"couldn't get hw info"
);
goto
out
;
}
ret
=
wl1271_fetch_nvs
(
wl
);
if
(
ret
==
0
)
{
/* NOTE: The wl->nvs->nvs element must be first, in
...
...
@@ -4843,20 +5092,25 @@ static int wl1271_register_hw(struct wl1271 *wl)
*/
u8
*
nvs_ptr
=
(
u8
*
)
wl
->
nvs
;
wl
->
mac_addr
[
0
]
=
nvs_ptr
[
11
];
wl
->
mac_addr
[
1
]
=
nvs_ptr
[
10
];
wl
->
mac_addr
[
2
]
=
nvs_ptr
[
6
];
wl
->
mac_addr
[
3
]
=
nvs_ptr
[
5
];
wl
->
mac_addr
[
4
]
=
nvs_ptr
[
4
];
wl
->
mac_addr
[
5
]
=
nvs_ptr
[
3
];
oui_addr
=
(
nvs_ptr
[
11
]
<<
16
)
+
(
nvs_ptr
[
10
]
<<
8
)
+
nvs_ptr
[
6
];
nic_addr
=
(
nvs_ptr
[
5
]
<<
16
)
+
(
nvs_ptr
[
4
]
<<
8
)
+
nvs_ptr
[
3
];
}
SET_IEEE80211_PERM_ADDR
(
wl
->
hw
,
wl
->
mac_addr
);
/* if the MAC address is zeroed in the NVS derive from fuse */
if
(
oui_addr
==
0
&&
nic_addr
==
0
)
{
oui_addr
=
wl
->
fuse_oui_addr
;
/* fuse has the BD_ADDR, the WLAN addresses are the next two */
nic_addr
=
wl
->
fuse_nic_addr
+
1
;
}
wl12xx_derive_mac_addresses
(
wl
,
oui_addr
,
nic_addr
,
2
);
ret
=
ieee80211_register_hw
(
wl
->
hw
);
if
(
ret
<
0
)
{
wl1271_error
(
"unable to register mac80211 hw: %d"
,
ret
);
return
re
t
;
goto
ou
t
;
}
wl
->
mac80211_registered
=
true
;
...
...
@@ -4867,13 +5121,14 @@ static int wl1271_register_hw(struct wl1271 *wl)
wl1271_notice
(
"loaded"
);
return
0
;
out:
return
ret
;
}
static
void
wl1271_unregister_hw
(
struct
wl1271
*
wl
)
{
if
(
wl
->
state
==
WL1271_STATE_PLT
)
__
wl1271_plt_stop
(
wl
);
if
(
wl
->
plt
)
wl1271_plt_stop
(
wl
);
unregister_netdevice_notifier
(
&
wl1271_dev_notifier
);
ieee80211_unregister_hw
(
wl
->
hw
);
...
...
@@ -4892,7 +5147,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
};
/* The tx descriptor buffer and the TKIP space. */
wl
->
hw
->
extra_tx_headroom
=
WL1271_
TKIP_IV_SPACE
+
wl
->
hw
->
extra_tx_headroom
=
WL1271_
EXTRA_SPACE_TKIP
+
sizeof
(
struct
wl1271_tx_hw_descr
);
/* unit us */
...
...
@@ -4902,6 +5157,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
wl
->
hw
->
flags
=
IEEE80211_HW_SIGNAL_DBM
|
IEEE80211_HW_SUPPORTS_PS
|
IEEE80211_HW_SUPPORTS_DYNAMIC_PS
|
IEEE80211_HW_SUPPORTS_UAPSD
|
IEEE80211_HW_HAS_RATE_CONTROL
|
IEEE80211_HW_CONNECTION_MONITOR
|
...
...
@@ -4909,7 +5165,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
IEEE80211_HW_SPECTRUM_MGMT
|
IEEE80211_HW_AP_LINK_PS
|
IEEE80211_HW_AMPDU_AGGREGATION
|
IEEE80211_HW_TX_AMPDU_SETUP_IN_HW
;
IEEE80211_HW_TX_AMPDU_SETUP_IN_HW
|
IEEE80211_HW_SCAN_WHILE_IDLE
;
wl
->
hw
->
wiphy
->
cipher_suites
=
cipher_suites
;
wl
->
hw
->
wiphy
->
n_cipher_suites
=
ARRAY_SIZE
(
cipher_suites
);
...
...
@@ -4925,10 +5182,10 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
* should be the maximum length possible for a template, without
* the IEEE80211 header of the template
*/
wl
->
hw
->
wiphy
->
max_scan_ie_len
=
WL1271_CMD_TEMPL_
DFLT
_SIZE
-
wl
->
hw
->
wiphy
->
max_scan_ie_len
=
WL1271_CMD_TEMPL_
MAX
_SIZE
-
sizeof
(
struct
ieee80211_header
);
wl
->
hw
->
wiphy
->
max_sched_scan_ie_len
=
WL1271_CMD_TEMPL_
DFLT
_SIZE
-
wl
->
hw
->
wiphy
->
max_sched_scan_ie_len
=
WL1271_CMD_TEMPL_
MAX
_SIZE
-
sizeof
(
struct
ieee80211_header
);
wl
->
hw
->
wiphy
->
flags
|=
WIPHY_FLAG_AP_UAPSD
;
...
...
@@ -5022,7 +5279,6 @@ static struct ieee80211_hw *wl1271_alloc_hw(void)
wl
->
rx_counter
=
0
;
wl
->
power_level
=
WL1271_DEFAULT_POWER_LEVEL
;
wl
->
band
=
IEEE80211_BAND_2GHZ
;
wl
->
vif
=
NULL
;
wl
->
flags
=
0
;
wl
->
sg_enabled
=
true
;
wl
->
hw_pg_ver
=
-
1
;
...
...
@@ -5047,6 +5303,7 @@ static struct ieee80211_hw *wl1271_alloc_hw(void)
spin_lock_init
(
&
wl
->
wl_lock
);
wl
->
state
=
WL1271_STATE_OFF
;
wl
->
fw_type
=
WL12XX_FW_TYPE_NONE
;
mutex_init
(
&
wl
->
mutex
);
/* Apply default driver configuration. */
...
...
@@ -5114,6 +5371,7 @@ static int wl1271_free_hw(struct wl1271 *wl)
vfree
(
wl
->
fw
);
wl
->
fw
=
NULL
;
wl
->
fw_type
=
WL12XX_FW_TYPE_NONE
;
kfree
(
wl
->
nvs
);
wl
->
nvs
=
NULL
;
...
...
@@ -5300,7 +5558,7 @@ module_param_named(debug_level, wl12xx_debug_level, uint, S_IRUSR | S_IWUSR);
MODULE_PARM_DESC
(
debug_level
,
"wl12xx debugging level"
);
module_param_named
(
fwlog
,
fwlog_param
,
charp
,
0
);
MODULE_PARM_DESC
(
keymap
,
MODULE_PARM_DESC
(
fwlog
,
"FW logger options: continuous, ondemand, dbgpins or disable"
);
module_param
(
bug_on_recovery
,
bool
,
S_IRUSR
|
S_IWUSR
);
...
...
drivers/net/wireless/wl12xx/ps.c
View file @
8715d941
...
...
@@ -56,7 +56,7 @@ void wl1271_elp_work(struct work_struct *work)
if
(
wlvif
->
bss_type
==
BSS_TYPE_AP_BSS
)
goto
out
;
if
(
!
test_bit
(
WLVIF_FLAG_
PSM
,
&
wlvif
->
flags
)
&&
if
(
!
test_bit
(
WLVIF_FLAG_
IN_PS
,
&
wlvif
->
flags
)
&&
test_bit
(
WLVIF_FLAG_IN_USE
,
&
wlvif
->
flags
))
goto
out
;
}
...
...
@@ -84,7 +84,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
if
(
wlvif
->
bss_type
==
BSS_TYPE_AP_BSS
)
return
;
if
(
!
test_bit
(
WLVIF_FLAG_
PSM
,
&
wlvif
->
flags
)
&&
if
(
!
test_bit
(
WLVIF_FLAG_
IN_PS
,
&
wlvif
->
flags
)
&&
test_bit
(
WLVIF_FLAG_IN_USE
,
&
wlvif
->
flags
))
return
;
}
...
...
@@ -160,28 +160,39 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)
}
int
wl1271_ps_set_mode
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
enum
wl1271_cmd_ps_mode
mode
,
u32
rates
,
bool
send
)
enum
wl1271_cmd_ps_mode
mode
)
{
int
ret
;
u16
timeout
=
wl
->
conf
.
conn
.
dynamic_ps_timeout
;
switch
(
mode
)
{
case
STATION_AUTO_PS_MODE
:
case
STATION_POWER_SAVE_MODE
:
wl1271_debug
(
DEBUG_PSM
,
"entering psm"
);
wl1271_debug
(
DEBUG_PSM
,
"entering psm (mode=%d,timeout=%u)"
,
mode
,
timeout
);
ret
=
wl1271_acx_wake_up_conditions
(
wl
,
wlvif
);
ret
=
wl1271_acx_wake_up_conditions
(
wl
,
wlvif
,
wl
->
conf
.
conn
.
wake_up_event
,
wl
->
conf
.
conn
.
listen_interval
);
if
(
ret
<
0
)
{
wl1271_error
(
"couldn't set wake up conditions"
);
return
ret
;
}
ret
=
wl1271_cmd_ps_mode
(
wl
,
wlvif
,
STATION_POWER_SAVE_MODE
);
ret
=
wl1271_cmd_ps_mode
(
wl
,
wlvif
,
mode
,
timeout
);
if
(
ret
<
0
)
return
ret
;
set_bit
(
WLVIF_FLAG_PSM
,
&
wlvif
->
flags
);
set_bit
(
WLVIF_FLAG_IN_PS
,
&
wlvif
->
flags
);
/* enable beacon early termination. Not relevant for 5GHz */
if
(
wlvif
->
band
==
IEEE80211_BAND_2GHZ
)
{
ret
=
wl1271_acx_bet_enable
(
wl
,
wlvif
,
true
);
if
(
ret
<
0
)
return
ret
;
}
break
;
case
STATION_ACTIVE_MODE
:
default:
wl1271_debug
(
DEBUG_PSM
,
"leaving psm"
);
/* disable beacon early termination */
...
...
@@ -191,12 +202,15 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
return
ret
;
}
ret
=
wl1271_cmd_ps_mode
(
wl
,
wlvif
,
STATION_ACTIVE_MODE
);
ret
=
wl1271_cmd_ps_mode
(
wl
,
wlvif
,
mode
,
0
);
if
(
ret
<
0
)
return
ret
;
clear_bit
(
WLVIF_FLAG_
PSM
,
&
wlvif
->
flags
);
clear_bit
(
WLVIF_FLAG_
IN_PS
,
&
wlvif
->
flags
);
break
;
default:
wl1271_warning
(
"trying to set ps to unsupported mode %d"
,
mode
);
ret
=
-
EINVAL
;
}
return
ret
;
...
...
drivers/net/wireless/wl12xx/ps.h
View file @
8715d941
...
...
@@ -28,7 +28,7 @@
#include "acx.h"
int
wl1271_ps_set_mode
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
enum
wl1271_cmd_ps_mode
mode
,
u32
rates
,
bool
send
);
enum
wl1271_cmd_ps_mode
mode
);
void
wl1271_ps_elp_sleep
(
struct
wl1271
*
wl
);
int
wl1271_ps_elp_wakeup
(
struct
wl1271
*
wl
);
void
wl1271_elp_work
(
struct
work_struct
*
work
);
...
...
drivers/net/wireless/wl12xx/reg.h
View file @
8715d941
...
...
@@ -525,4 +525,31 @@ b12-b0 - Supported Rate indicator bits as defined below.
*/
#define INTR_TRIG_TX_PROC1 BIT(18)
#define WL127X_REG_FUSE_DATA_2_1 0x050a
#define WL128X_REG_FUSE_DATA_2_1 0x2152
#define PG_VER_MASK 0x3c
#define PG_VER_OFFSET 2
#define WL127X_PG_MAJOR_VER_MASK 0x3
#define WL127X_PG_MAJOR_VER_OFFSET 0x0
#define WL127X_PG_MINOR_VER_MASK 0xc
#define WL127X_PG_MINOR_VER_OFFSET 0x2
#define WL128X_PG_MAJOR_VER_MASK 0xc
#define WL128X_PG_MAJOR_VER_OFFSET 0x2
#define WL128X_PG_MINOR_VER_MASK 0x3
#define WL128X_PG_MINOR_VER_OFFSET 0x0
#define WL127X_PG_GET_MAJOR(pg_ver) ((pg_ver & WL127X_PG_MAJOR_VER_MASK) >> \
WL127X_PG_MAJOR_VER_OFFSET)
#define WL127X_PG_GET_MINOR(pg_ver) ((pg_ver & WL127X_PG_MINOR_VER_MASK) >> \
WL127X_PG_MINOR_VER_OFFSET)
#define WL128X_PG_GET_MAJOR(pg_ver) ((pg_ver & WL128X_PG_MAJOR_VER_MASK) >> \
WL128X_PG_MAJOR_VER_OFFSET)
#define WL128X_PG_GET_MINOR(pg_ver) ((pg_ver & WL128X_PG_MINOR_VER_MASK) >> \
WL128X_PG_MINOR_VER_OFFSET)
#define WL12XX_REG_FUSE_BD_ADDR_1 0x00310eb4
#define WL12XX_REG_FUSE_BD_ADDR_2 0x00310eb8
#endif
drivers/net/wireless/wl12xx/rx.c
View file @
8715d941
...
...
@@ -113,7 +113,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
* In PLT mode we seem to get frames and mac80211 warns about them,
* workaround this by not retrieving them at all.
*/
if
(
unlikely
(
wl
->
state
==
WL1271_STATE_PLT
))
if
(
unlikely
(
wl
->
plt
))
return
-
EINVAL
;
/* the data read starts with the descriptor */
...
...
drivers/net/wireless/wl12xx/scan.c
View file @
8715d941
...
...
@@ -38,7 +38,6 @@ void wl1271_scan_complete_work(struct work_struct *work)
struct
ieee80211_vif
*
vif
;
struct
wl12xx_vif
*
wlvif
;
int
ret
;
bool
is_sta
,
is_ibss
;
dwork
=
container_of
(
work
,
struct
delayed_work
,
work
);
wl
=
container_of
(
dwork
,
struct
wl1271
,
scan_complete_work
);
...
...
@@ -70,15 +69,6 @@ void wl1271_scan_complete_work(struct work_struct *work)
wl1271_cmd_build_ap_probe_req
(
wl
,
wlvif
,
wlvif
->
probereq
);
}
/* return to ROC if needed */
is_sta
=
(
wlvif
->
bss_type
==
BSS_TYPE_STA_BSS
);
is_ibss
=
(
wlvif
->
bss_type
==
BSS_TYPE_IBSS
);
if
(((
is_sta
&&
!
test_bit
(
WLVIF_FLAG_STA_ASSOCIATED
,
&
wlvif
->
flags
))
||
(
is_ibss
&&
!
test_bit
(
WLVIF_FLAG_IBSS_JOINED
,
&
wlvif
->
flags
)))
&&
!
test_bit
(
wlvif
->
dev_role_id
,
wl
->
roc_map
))
{
/* restore remain on channel */
wl12xx_start_dev
(
wl
,
wlvif
);
}
wl1271_ps_elp_sleep
(
wl
);
if
(
wl
->
scan
.
failed
)
{
...
...
@@ -182,14 +172,23 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif,
goto
out
;
}
if
(
wl
->
conf
.
scan
.
split_scan_timeout
)
scan_options
|=
WL1271_SCAN_OPT_SPLIT_SCAN
;
if
(
passive
)
scan_options
|=
WL1271_SCAN_OPT_PASSIVE
;
if
(
WARN_ON
(
wlvif
->
role_id
==
WL12XX_INVALID_ROLE_ID
))
{
if
(
wlvif
->
bss_type
==
BSS_TYPE_AP_BSS
||
test_bit
(
WLVIF_FLAG_STA_ASSOCIATED
,
&
wlvif
->
flags
))
cmd
->
params
.
role_id
=
wlvif
->
role_id
;
else
cmd
->
params
.
role_id
=
wlvif
->
dev_role_id
;
if
(
WARN_ON
(
cmd
->
params
.
role_id
==
WL12XX_INVALID_ROLE_ID
))
{
ret
=
-
EINVAL
;
goto
out
;
}
cmd
->
params
.
role_id
=
wlvif
->
role_id
;
cmd
->
params
.
scan_options
=
cpu_to_le16
(
scan_options
);
cmd
->
params
.
n_ch
=
wl1271_get_scan_channels
(
wl
,
wl
->
scan
.
req
,
...
...
@@ -202,7 +201,7 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif,
cmd
->
params
.
tx_rate
=
cpu_to_le32
(
basic_rate
);
cmd
->
params
.
n_probe_reqs
=
wl
->
conf
.
scan
.
num_probe_reqs
;
cmd
->
params
.
tid_trigger
=
0
;
cmd
->
params
.
tid_trigger
=
CONF_TX_AC_ANY_TID
;
cmd
->
params
.
scan_tag
=
WL1271_SCAN_DEFAULT_TAG
;
if
(
band
==
IEEE80211_BAND_2GHZ
)
...
...
@@ -217,16 +216,17 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif,
memcpy
(
cmd
->
addr
,
vif
->
addr
,
ETH_ALEN
);
ret
=
wl1271_cmd_build_probe_req
(
wl
,
wlvif
,
wl
->
scan
.
ssid
,
wl
->
scan
.
ssid_len
,
wl
->
scan
.
req
->
ie
,
wl
->
scan
.
req
->
ie_len
,
band
);
ret
=
wl12xx_cmd_build_probe_req
(
wl
,
wlvif
,
cmd
->
params
.
role_id
,
band
,
wl
->
scan
.
ssid
,
wl
->
scan
.
ssid_len
,
wl
->
scan
.
req
->
ie
,
wl
->
scan
.
req
->
ie_len
);
if
(
ret
<
0
)
{
wl1271_error
(
"PROBE request template failed"
);
goto
out
;
}
/* disable the timeout */
trigger
->
timeout
=
0
;
trigger
->
timeout
=
cpu_to_le32
(
wl
->
conf
.
scan
.
split_scan_timeout
);
ret
=
wl1271_cmd_send
(
wl
,
CMD_TRIGGER_SCAN_TO
,
trigger
,
sizeof
(
*
trigger
),
0
);
if
(
ret
<
0
)
{
...
...
@@ -658,11 +658,13 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
}
if
(
!
force_passive
&&
cfg
->
active
[
0
])
{
ret
=
wl1271_cmd_build_probe_req
(
wl
,
wlvif
,
req
->
ssids
[
0
].
ssid
,
u8
band
=
IEEE80211_BAND_2GHZ
;
ret
=
wl12xx_cmd_build_probe_req
(
wl
,
wlvif
,
wlvif
->
dev_role_id
,
band
,
req
->
ssids
[
0
].
ssid
,
req
->
ssids
[
0
].
ssid_len
,
ies
->
ie
[
IEEE80211_BAND_2GHZ
],
ies
->
len
[
IEEE80211_BAND_2GHZ
],
IEEE80211_BAND_2GHZ
);
ies
->
ie
[
band
],
ies
->
len
[
band
]);
if
(
ret
<
0
)
{
wl1271_error
(
"2.4GHz PROBE request template failed"
);
goto
out
;
...
...
@@ -670,11 +672,13 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
}
if
(
!
force_passive
&&
cfg
->
active
[
1
])
{
ret
=
wl1271_cmd_build_probe_req
(
wl
,
wlvif
,
req
->
ssids
[
0
].
ssid
,
u8
band
=
IEEE80211_BAND_5GHZ
;
ret
=
wl12xx_cmd_build_probe_req
(
wl
,
wlvif
,
wlvif
->
dev_role_id
,
band
,
req
->
ssids
[
0
].
ssid
,
req
->
ssids
[
0
].
ssid_len
,
ies
->
ie
[
IEEE80211_BAND_5GHZ
],
ies
->
len
[
IEEE80211_BAND_5GHZ
],
IEEE80211_BAND_5GHZ
);
ies
->
ie
[
band
],
ies
->
len
[
band
]);
if
(
ret
<
0
)
{
wl1271_error
(
"5GHz PROBE request template failed"
);
goto
out
;
...
...
drivers/net/wireless/wl12xx/scan.h
View file @
8715d941
...
...
@@ -48,7 +48,7 @@ void wl1271_scan_sched_scan_results(struct wl1271 *wl);
#define WL1271_SCAN_CURRENT_TX_PWR 0
#define WL1271_SCAN_OPT_ACTIVE 0
#define WL1271_SCAN_OPT_PASSIVE 1
#define WL1271_SCAN_OPT_
TRIGGERED_SCAN
2
#define WL1271_SCAN_OPT_
SPLIT_SCAN
2
#define WL1271_SCAN_OPT_PRIORITY_HIGH 4
/* scan even if we fail to enter psm */
#define WL1271_SCAN_OPT_FORCE 8
...
...
drivers/net/wireless/wl12xx/sdio.c
View file @
8715d941
...
...
@@ -74,6 +74,8 @@ static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf,
struct
wl12xx_sdio_glue
*
glue
=
dev_get_drvdata
(
child
->
parent
);
struct
sdio_func
*
func
=
dev_to_sdio_func
(
glue
->
dev
);
sdio_claim_host
(
func
);
if
(
unlikely
(
addr
==
HW_ACCESS_ELP_CTRL_REG_ADDR
))
{
((
u8
*
)
buf
)[
0
]
=
sdio_f0_readb
(
func
,
addr
,
&
ret
);
dev_dbg
(
child
->
parent
,
"sdio read 52 addr 0x%x, byte 0x%02x
\n
"
,
...
...
@@ -88,6 +90,8 @@ static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf,
addr
,
len
);
}
sdio_release_host
(
func
);
if
(
ret
)
dev_err
(
child
->
parent
,
"sdio read failed (%d)
\n
"
,
ret
);
}
...
...
@@ -99,6 +103,8 @@ static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf,
struct
wl12xx_sdio_glue
*
glue
=
dev_get_drvdata
(
child
->
parent
);
struct
sdio_func
*
func
=
dev_to_sdio_func
(
glue
->
dev
);
sdio_claim_host
(
func
);
if
(
unlikely
(
addr
==
HW_ACCESS_ELP_CTRL_REG_ADDR
))
{
sdio_f0_writeb
(
func
,
((
u8
*
)
buf
)[
0
],
addr
,
&
ret
);
dev_dbg
(
child
->
parent
,
"sdio write 52 addr 0x%x, byte 0x%02x
\n
"
,
...
...
@@ -113,6 +119,8 @@ static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf,
ret
=
sdio_memcpy_toio
(
func
,
addr
,
buf
,
len
);
}
sdio_release_host
(
func
);
if
(
ret
)
dev_err
(
child
->
parent
,
"sdio write failed (%d)
\n
"
,
ret
);
}
...
...
@@ -136,6 +144,7 @@ static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue)
sdio_claim_host
(
func
);
sdio_enable_func
(
func
);
sdio_release_host
(
func
);
out:
return
ret
;
...
...
@@ -146,6 +155,7 @@ static int wl12xx_sdio_power_off(struct wl12xx_sdio_glue *glue)
int
ret
;
struct
sdio_func
*
func
=
dev_to_sdio_func
(
glue
->
dev
);
sdio_claim_host
(
func
);
sdio_disable_func
(
func
);
sdio_release_host
(
func
);
...
...
@@ -314,9 +324,6 @@ static int wl1271_suspend(struct device *dev)
dev_err
(
dev
,
"error while trying to keep power
\n
"
);
goto
out
;
}
/* release host */
sdio_release_host
(
func
);
}
out:
return
ret
;
...
...
@@ -324,15 +331,7 @@ static int wl1271_suspend(struct device *dev)
static
int
wl1271_resume
(
struct
device
*
dev
)
{
struct
sdio_func
*
func
=
dev_to_sdio_func
(
dev
);
struct
wl12xx_sdio_glue
*
glue
=
sdio_get_drvdata
(
func
);
struct
wl1271
*
wl
=
platform_get_drvdata
(
glue
->
core
);
dev_dbg
(
dev
,
"wl1271 resume
\n
"
);
if
(
wl
->
wow_enabled
)
{
/* claim back host */
sdio_claim_host
(
func
);
}
return
0
;
}
...
...
@@ -371,5 +370,9 @@ module_exit(wl1271_exit);
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Luciano Coelho <coelho@ti.com>"
);
MODULE_AUTHOR
(
"Juuso Oikarinen <juuso.oikarinen@nokia.com>"
);
MODULE_FIRMWARE
(
WL127X_FW_NAME
);
MODULE_FIRMWARE
(
WL128X_FW_NAME
);
MODULE_FIRMWARE
(
WL127X_FW_NAME_SINGLE
);
MODULE_FIRMWARE
(
WL127X_FW_NAME_MULTI
);
MODULE_FIRMWARE
(
WL127X_PLT_FW_NAME
);
MODULE_FIRMWARE
(
WL128X_FW_NAME_SINGLE
);
MODULE_FIRMWARE
(
WL128X_FW_NAME_MULTI
);
MODULE_FIRMWARE
(
WL128X_PLT_FW_NAME
);
drivers/net/wireless/wl12xx/spi.c
View file @
8715d941
...
...
@@ -433,6 +433,10 @@ module_exit(wl1271_exit);
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Luciano Coelho <coelho@ti.com>"
);
MODULE_AUTHOR
(
"Juuso Oikarinen <juuso.oikarinen@nokia.com>"
);
MODULE_FIRMWARE
(
WL127X_FW_NAME
);
MODULE_FIRMWARE
(
WL128X_FW_NAME
);
MODULE_FIRMWARE
(
WL127X_FW_NAME_SINGLE
);
MODULE_FIRMWARE
(
WL127X_FW_NAME_MULTI
);
MODULE_FIRMWARE
(
WL127X_PLT_FW_NAME
);
MODULE_FIRMWARE
(
WL128X_FW_NAME_SINGLE
);
MODULE_FIRMWARE
(
WL128X_FW_NAME_MULTI
);
MODULE_FIRMWARE
(
WL128X_PLT_FW_NAME
);
MODULE_ALIAS
(
"spi:wl1271"
);
drivers/net/wireless/wl12xx/testmode.c
View file @
8715d941
...
...
@@ -30,6 +30,7 @@
#include "acx.h"
#include "reg.h"
#include "ps.h"
#include "io.h"
#define WL1271_TM_MAX_DATA_LENGTH 1024
...
...
@@ -41,6 +42,7 @@ enum wl1271_tm_commands {
WL1271_TM_CMD_NVS_PUSH
,
/* Not in use. Keep to not break ABI */
WL1271_TM_CMD_SET_PLT_MODE
,
WL1271_TM_CMD_RECOVER
,
WL1271_TM_CMD_GET_MAC
,
__WL1271_TM_CMD_AFTER_LAST
};
...
...
@@ -264,6 +266,52 @@ static int wl1271_tm_cmd_recover(struct wl1271 *wl, struct nlattr *tb[])
return
0
;
}
static
int
wl12xx_tm_cmd_get_mac
(
struct
wl1271
*
wl
,
struct
nlattr
*
tb
[])
{
struct
sk_buff
*
skb
;
u8
mac_addr
[
ETH_ALEN
];
int
ret
=
0
;
mutex_lock
(
&
wl
->
mutex
);
if
(
!
wl
->
plt
)
{
ret
=
-
EINVAL
;
goto
out
;
}
if
(
wl
->
fuse_oui_addr
==
0
&&
wl
->
fuse_nic_addr
==
0
)
{
ret
=
-
EOPNOTSUPP
;
goto
out
;
}
mac_addr
[
0
]
=
(
u8
)(
wl
->
fuse_oui_addr
>>
16
);
mac_addr
[
1
]
=
(
u8
)(
wl
->
fuse_oui_addr
>>
8
);
mac_addr
[
2
]
=
(
u8
)
wl
->
fuse_oui_addr
;
mac_addr
[
3
]
=
(
u8
)(
wl
->
fuse_nic_addr
>>
16
);
mac_addr
[
4
]
=
(
u8
)(
wl
->
fuse_nic_addr
>>
8
);
mac_addr
[
5
]
=
(
u8
)
wl
->
fuse_nic_addr
;
skb
=
cfg80211_testmode_alloc_reply_skb
(
wl
->
hw
->
wiphy
,
ETH_ALEN
);
if
(
!
skb
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
NLA_PUT
(
skb
,
WL1271_TM_ATTR_DATA
,
ETH_ALEN
,
mac_addr
);
ret
=
cfg80211_testmode_reply
(
skb
);
if
(
ret
<
0
)
goto
out
;
out:
mutex_unlock
(
&
wl
->
mutex
);
return
ret
;
nla_put_failure:
kfree_skb
(
skb
);
ret
=
-
EMSGSIZE
;
goto
out
;
}
int
wl1271_tm_cmd
(
struct
ieee80211_hw
*
hw
,
void
*
data
,
int
len
)
{
struct
wl1271
*
wl
=
hw
->
priv
;
...
...
@@ -288,6 +336,8 @@ int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len)
return
wl1271_tm_cmd_set_plt_mode
(
wl
,
tb
);
case
WL1271_TM_CMD_RECOVER
:
return
wl1271_tm_cmd_recover
(
wl
,
tb
);
case
WL1271_TM_CMD_GET_MAC
:
return
wl12xx_tm_cmd_get_mac
(
wl
,
tb
);
default:
return
-
EOPNOTSUPP
;
}
...
...
drivers/net/wireless/wl12xx/tx.c
View file @
8715d941
...
...
@@ -77,35 +77,6 @@ static void wl1271_free_tx_id(struct wl1271 *wl, int id)
}
}
static
int
wl1271_tx_update_filters
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
sk_buff
*
skb
)
{
struct
ieee80211_hdr
*
hdr
;
int
ret
;
hdr
=
(
struct
ieee80211_hdr
*
)
skb
->
data
;
/*
* stop bssid-based filtering before transmitting authentication
* requests. this way the hw will never drop authentication
* responses coming from BSSIDs it isn't familiar with (e.g. on
* roaming)
*/
if
(
!
ieee80211_is_auth
(
hdr
->
frame_control
))
return
0
;
if
(
wlvif
->
dev_hlid
!=
WL12XX_INVALID_LINK_ID
)
goto
out
;
wl1271_debug
(
DEBUG_CMD
,
"starting device role for roaming"
);
ret
=
wl12xx_start_dev
(
wl
,
wlvif
);
if
(
ret
<
0
)
goto
out
;
out:
return
0
;
}
static
void
wl1271_tx_ap_update_inconnection_sta
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
)
{
...
...
@@ -187,8 +158,6 @@ u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif,
if
(
wlvif
->
bss_type
==
BSS_TYPE_AP_BSS
)
return
wl12xx_tx_get_hlid_ap
(
wl
,
wlvif
,
skb
);
wl1271_tx_update_filters
(
wl
,
wlvif
,
skb
);
if
((
test_bit
(
WLVIF_FLAG_STA_ASSOCIATED
,
&
wlvif
->
flags
)
||
test_bit
(
WLVIF_FLAG_IBSS_JOINED
,
&
wlvif
->
flags
))
&&
!
ieee80211_is_auth
(
hdr
->
frame_control
)
&&
...
...
@@ -286,16 +255,20 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif,
int
aligned_len
,
ac
,
rate_idx
;
s64
hosttime
;
u16
tx_attr
=
0
;
__le16
frame_control
;
struct
ieee80211_hdr
*
hdr
;
u8
*
frame_start
;
bool
is_dummy
;
desc
=
(
struct
wl1271_tx_hw_descr
*
)
skb
->
data
;
frame_start
=
(
u8
*
)(
desc
+
1
);
hdr
=
(
struct
ieee80211_hdr
*
)(
frame_start
+
extra
);
frame_control
=
hdr
->
frame_control
;
/* relocate space for security header */
if
(
extra
)
{
void
*
framestart
=
skb
->
data
+
sizeof
(
*
desc
);
u16
fc
=
*
(
u16
*
)(
framestart
+
extra
);
int
hdrlen
=
ieee80211_hdrlen
(
cpu_to_le16
(
fc
));
memmove
(
framestart
,
framestart
+
extra
,
hdrlen
);
int
hdrlen
=
ieee80211_hdrlen
(
frame_control
);
memmove
(
frame_start
,
hdr
,
hdrlen
);
}
/* configure packet life time */
...
...
@@ -384,6 +357,11 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif,
desc
->
wl127x_mem
.
total_mem_blocks
);
}
/* for WEP shared auth - no fw encryption is needed */
if
(
ieee80211_is_auth
(
frame_control
)
&&
ieee80211_has_protected
(
frame_control
))
tx_attr
|=
TX_HW_ATTR_HOST_ENCRYPT
;
desc
->
tx_attr
=
cpu_to_le16
(
tx_attr
);
}
...
...
@@ -408,7 +386,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif,
if
(
info
->
control
.
hw_key
&&
info
->
control
.
hw_key
->
cipher
==
WLAN_CIPHER_SUITE_TKIP
)
extra
=
WL1271_
TKIP_IV_SPACE
;
extra
=
WL1271_
EXTRA_SPACE_TKIP
;
if
(
info
->
control
.
hw_key
)
{
bool
is_wep
;
...
...
@@ -795,6 +773,18 @@ void wl1271_tx_work(struct work_struct *work)
mutex_unlock
(
&
wl
->
mutex
);
}
static
u8
wl1271_tx_get_rate_flags
(
u8
rate_class_index
)
{
u8
flags
=
0
;
if
(
rate_class_index
>=
CONF_HW_RXTX_RATE_MCS_MIN
&&
rate_class_index
<=
CONF_HW_RXTX_RATE_MCS_MAX
)
flags
|=
IEEE80211_TX_RC_MCS
;
if
(
rate_class_index
==
CONF_HW_RXTX_RATE_MCS7_SGI
)
flags
|=
IEEE80211_TX_RC_SHORT_GI
;
return
flags
;
}
static
void
wl1271_tx_complete_packet
(
struct
wl1271
*
wl
,
struct
wl1271_tx_hw_res_descr
*
result
)
{
...
...
@@ -804,6 +794,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
struct
sk_buff
*
skb
;
int
id
=
result
->
id
;
int
rate
=
-
1
;
u8
rate_flags
=
0
;
u8
retries
=
0
;
/* check for id legality */
...
...
@@ -830,6 +821,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
info
->
flags
|=
IEEE80211_TX_STAT_ACK
;
rate
=
wl1271_rate_to_idx
(
result
->
rate_class_index
,
wlvif
->
band
);
rate_flags
=
wl1271_tx_get_rate_flags
(
result
->
rate_class_index
);
retries
=
result
->
ack_failures
;
}
else
if
(
result
->
status
==
TX_RETRY_EXCEEDED
)
{
wl
->
stats
.
excessive_retries
++
;
...
...
@@ -838,7 +830,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
info
->
status
.
rates
[
0
].
idx
=
rate
;
info
->
status
.
rates
[
0
].
count
=
retries
;
info
->
status
.
rates
[
0
].
flags
=
0
;
info
->
status
.
rates
[
0
].
flags
=
rate_flags
;
info
->
status
.
ack_signal
=
-
1
;
wl
->
stats
.
retry_count
+=
result
->
ack_failures
;
...
...
@@ -869,8 +861,9 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
if
(
info
->
control
.
hw_key
&&
info
->
control
.
hw_key
->
cipher
==
WLAN_CIPHER_SUITE_TKIP
)
{
int
hdrlen
=
ieee80211_get_hdrlen_from_skb
(
skb
);
memmove
(
skb
->
data
+
WL1271_TKIP_IV_SPACE
,
skb
->
data
,
hdrlen
);
skb_pull
(
skb
,
WL1271_TKIP_IV_SPACE
);
memmove
(
skb
->
data
+
WL1271_EXTRA_SPACE_TKIP
,
skb
->
data
,
hdrlen
);
skb_pull
(
skb
,
WL1271_EXTRA_SPACE_TKIP
);
}
wl1271_debug
(
DEBUG_TX
,
"tx status id %u skb 0x%p failures %u rate 0x%x"
...
...
@@ -1012,9 +1005,9 @@ void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
info
->
control
.
hw_key
->
cipher
==
WLAN_CIPHER_SUITE_TKIP
)
{
int
hdrlen
=
ieee80211_get_hdrlen_from_skb
(
skb
);
memmove
(
skb
->
data
+
WL1271_
TKIP_IV_SPACE
,
memmove
(
skb
->
data
+
WL1271_
EXTRA_SPACE_TKIP
,
skb
->
data
,
hdrlen
);
skb_pull
(
skb
,
WL1271_
TKIP_IV_SPACE
);
skb_pull
(
skb
,
WL1271_
EXTRA_SPACE_TKIP
);
}
info
->
status
.
rates
[
0
].
idx
=
-
1
;
...
...
drivers/net/wireless/wl12xx/tx.h
View file @
8715d941
...
...
@@ -39,6 +39,7 @@
#define TX_HW_ATTR_LAST_WORD_PAD (BIT(10) | BIT(11))
#define TX_HW_ATTR_TX_CMPLT_REQ BIT(12)
#define TX_HW_ATTR_TX_DUMMY_REQ BIT(13)
#define TX_HW_ATTR_HOST_ENCRYPT BIT(14)
#define TX_HW_ATTR_OFST_SAVE_RETRIES 0
#define TX_HW_ATTR_OFST_HEADER_PAD 1
...
...
@@ -51,7 +52,9 @@
#define TX_HW_RESULT_QUEUE_LEN_MASK 0xf
#define WL1271_TX_ALIGN_TO 4
#define WL1271_TKIP_IV_SPACE 4
#define WL1271_EXTRA_SPACE_TKIP 4
#define WL1271_EXTRA_SPACE_AES 8
#define WL1271_EXTRA_SPACE_MAX 8
/* Used for management frames and dummy packets */
#define WL1271_TID_MGMT 7
...
...
drivers/net/wireless/wl12xx/wl12xx.h
View file @
8715d941
...
...
@@ -35,8 +35,14 @@
#include "conf.h"
#include "ini.h"
#define WL127X_FW_NAME "ti-connectivity/wl127x-fw-3.bin"
#define WL128X_FW_NAME "ti-connectivity/wl128x-fw-3.bin"
#define WL127X_FW_NAME_MULTI "ti-connectivity/wl127x-fw-4-mr.bin"
#define WL127X_FW_NAME_SINGLE "ti-connectivity/wl127x-fw-4-sr.bin"
#define WL128X_FW_NAME_MULTI "ti-connectivity/wl128x-fw-4-mr.bin"
#define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin"
#define WL127X_PLT_FW_NAME "ti-connectivity/wl127x-fw-4-plt.bin"
#define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin"
/*
* wl127x and wl128x are using the same NVS file name. However, the
...
...
@@ -90,7 +96,13 @@
enum
wl1271_state
{
WL1271_STATE_OFF
,
WL1271_STATE_ON
,
WL1271_STATE_PLT
,
};
enum
wl12xx_fw_type
{
WL12XX_FW_TYPE_NONE
,
WL12XX_FW_TYPE_NORMAL
,
WL12XX_FW_TYPE_MULTI
,
WL12XX_FW_TYPE_PLT
,
};
enum
wl1271_partition_type
{
...
...
@@ -247,6 +259,7 @@ enum wl12xx_flags {
WL1271_FLAG_PENDING_WORK
,
WL1271_FLAG_SOFT_GEMINI
,
WL1271_FLAG_RECOVERY_IN_PROGRESS
,
WL1271_FLAG_VIF_CHANGE_IN_PROGRESS
,
};
enum
wl12xx_vif_flags
{
...
...
@@ -254,8 +267,7 @@ enum wl12xx_vif_flags {
WLVIF_FLAG_STA_ASSOCIATED
,
WLVIF_FLAG_IBSS_JOINED
,
WLVIF_FLAG_AP_STARTED
,
WLVIF_FLAG_PSM
,
WLVIF_FLAG_PSM_REQUESTED
,
WLVIF_FLAG_IN_PS
,
WLVIF_FLAG_STA_STATE_SENT
,
WLVIF_FLAG_RX_STREAMING_STARTED
,
WLVIF_FLAG_PSPOLL_FAILURE
,
...
...
@@ -295,6 +307,9 @@ struct wl1271 {
spinlock_t
wl_lock
;
enum
wl1271_state
state
;
enum
wl12xx_fw_type
fw_type
;
bool
plt
;
u8
last_vif_count
;
struct
mutex
mutex
;
unsigned
long
flags
;
...
...
@@ -313,7 +328,12 @@ struct wl1271 {
s8
hw_pg_ver
;
u8
mac_addr
[
ETH_ALEN
];
/* address read from the fuse ROM */
u32
fuse_oui_addr
;
u32
fuse_nic_addr
;
/* we have up to 2 MAC addresses */
struct
mac_address
addresses
[
2
];
int
channel
;
u8
system_hlid
;
...
...
@@ -425,8 +445,6 @@ struct wl1271 {
struct
wl12xx_fw_status
*
fw_status
;
struct
wl1271_tx_hw_res_if
*
tx_res_if
;
struct
ieee80211_vif
*
vif
;
/* Current chipset configuration */
struct
conf_drv_settings
conf
;
...
...
@@ -503,6 +521,8 @@ struct wl12xx_vif {
u8
basic_rate_idx
;
u8
ap_rate_idx
;
u8
p2p_rate_idx
;
bool
qos
;
}
sta
;
struct
{
u8
global_hlid
;
...
...
@@ -560,12 +580,6 @@ struct wl12xx_vif {
/* 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
;
...
...
@@ -575,6 +589,10 @@ struct wl12xx_vif {
int
rssi_thold
;
int
last_rssi_event
;
/* save the current encryption type for auto-arp config */
u8
encryption_type
;
__be32
ip_addr
;
/* RX BA constraint value */
bool
ba_support
;
bool
ba_allowed
;
...
...
drivers/net/wireless/wl12xx/wl12xx_80211.h
View file @
8715d941
...
...
@@ -117,7 +117,7 @@ struct wl12xx_ps_poll_template {
}
__packed
;
struct
wl12xx_arp_rsp_template
{
struct
ieee80211_hdr_3addr
hdr
;
/* not including ieee80211 header */
u8
llc_hdr
[
sizeof
(
rfc1042_header
)];
__be16
llc_type
;
...
...
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