Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
aaabee8b
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
aaabee8b
编写于
12月 04, 2012
作者:
L
Luciano Coelho
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'wl12xx-next' into for-linville
Conflicts: drivers/net/wireless/ti/wlcore/main.c
上级
795e9364
2f244561
变更
41
展开全部
隐藏空白更改
内联
并排
Showing
41 changed file
with
3495 addition
and
1703 deletion
+3495
-1703
drivers/net/wireless/ti/wl1251/Kconfig
drivers/net/wireless/ti/wl1251/Kconfig
+1
-1
drivers/net/wireless/ti/wl12xx/Makefile
drivers/net/wireless/ti/wl12xx/Makefile
+1
-1
drivers/net/wireless/ti/wl12xx/cmd.c
drivers/net/wireless/ti/wl12xx/cmd.c
+37
-0
drivers/net/wireless/ti/wl12xx/cmd.h
drivers/net/wireless/ti/wl12xx/cmd.h
+20
-0
drivers/net/wireless/ti/wl12xx/event.c
drivers/net/wireless/ti/wl12xx/event.c
+112
-0
drivers/net/wireless/ti/wl12xx/event.h
drivers/net/wireless/ti/wl12xx/event.h
+111
-0
drivers/net/wireless/ti/wl12xx/main.c
drivers/net/wireless/ti/wl12xx/main.c
+76
-46
drivers/net/wireless/ti/wl12xx/scan.c
drivers/net/wireless/ti/wl12xx/scan.c
+501
-0
drivers/net/wireless/ti/wl12xx/scan.h
drivers/net/wireless/ti/wl12xx/scan.h
+140
-0
drivers/net/wireless/ti/wl12xx/wl12xx.h
drivers/net/wireless/ti/wl12xx/wl12xx.h
+28
-10
drivers/net/wireless/ti/wl18xx/Makefile
drivers/net/wireless/ti/wl18xx/Makefile
+1
-1
drivers/net/wireless/ti/wl18xx/acx.c
drivers/net/wireless/ti/wl18xx/acx.c
+32
-1
drivers/net/wireless/ti/wl18xx/acx.h
drivers/net/wireless/ti/wl18xx/acx.h
+21
-1
drivers/net/wireless/ti/wl18xx/cmd.c
drivers/net/wireless/ti/wl18xx/cmd.c
+80
-0
drivers/net/wireless/ti/wl18xx/cmd.h
drivers/net/wireless/ti/wl18xx/cmd.h
+52
-0
drivers/net/wireless/ti/wl18xx/event.c
drivers/net/wireless/ti/wl18xx/event.c
+103
-0
drivers/net/wireless/ti/wl18xx/event.h
drivers/net/wireless/ti/wl18xx/event.h
+76
-0
drivers/net/wireless/ti/wl18xx/main.c
drivers/net/wireless/ti/wl18xx/main.c
+85
-9
drivers/net/wireless/ti/wl18xx/scan.c
drivers/net/wireless/ti/wl18xx/scan.c
+322
-0
drivers/net/wireless/ti/wl18xx/scan.h
drivers/net/wireless/ti/wl18xx/scan.h
+115
-0
drivers/net/wireless/ti/wl18xx/wl18xx.h
drivers/net/wireless/ti/wl18xx/wl18xx.h
+4
-4
drivers/net/wireless/ti/wlcore/acx.h
drivers/net/wireless/ti/wlcore/acx.h
+0
-1
drivers/net/wireless/ti/wlcore/boot.c
drivers/net/wireless/ti/wlcore/boot.c
+35
-42
drivers/net/wireless/ti/wlcore/cmd.c
drivers/net/wireless/ti/wlcore/cmd.c
+201
-121
drivers/net/wireless/ti/wlcore/cmd.h
drivers/net/wireless/ti/wlcore/cmd.h
+48
-26
drivers/net/wireless/ti/wlcore/conf.h
drivers/net/wireless/ti/wlcore/conf.h
+16
-15
drivers/net/wireless/ti/wlcore/debugfs.c
drivers/net/wireless/ti/wlcore/debugfs.c
+2
-3
drivers/net/wireless/ti/wlcore/event.c
drivers/net/wireless/ti/wlcore/event.c
+155
-174
drivers/net/wireless/ti/wlcore/event.h
drivers/net/wireless/ti/wlcore/event.h
+25
-76
drivers/net/wireless/ti/wlcore/hw_ops.h
drivers/net/wireless/ti/wlcore/hw_ops.h
+8
-0
drivers/net/wireless/ti/wlcore/init.c
drivers/net/wireless/ti/wlcore/init.c
+11
-5
drivers/net/wireless/ti/wlcore/main.c
drivers/net/wireless/ti/wlcore/main.c
+788
-481
drivers/net/wireless/ti/wlcore/ps.c
drivers/net/wireless/ti/wlcore/ps.c
+0
-3
drivers/net/wireless/ti/wlcore/rx.c
drivers/net/wireless/ti/wlcore/rx.c
+4
-0
drivers/net/wireless/ti/wlcore/scan.c
drivers/net/wireless/ti/wlcore/scan.c
+153
-530
drivers/net/wireless/ti/wlcore/scan.h
drivers/net/wireless/ti/wlcore/scan.h
+37
-105
drivers/net/wireless/ti/wlcore/sdio.c
drivers/net/wireless/ti/wlcore/sdio.c
+1
-2
drivers/net/wireless/ti/wlcore/spi.c
drivers/net/wireless/ti/wlcore/spi.c
+2
-3
drivers/net/wireless/ti/wlcore/tx.c
drivers/net/wireless/ti/wlcore/tx.c
+9
-8
drivers/net/wireless/ti/wlcore/wlcore.h
drivers/net/wireless/ti/wlcore/wlcore.h
+71
-20
drivers/net/wireless/ti/wlcore/wlcore_i.h
drivers/net/wireless/ti/wlcore/wlcore_i.h
+11
-14
未找到文件。
drivers/net/wireless/ti/wl1251/Kconfig
浏览文件 @
aaabee8b
menuconfig WL1251
tristate "TI wl1251 driver support"
depends on MAC80211 &&
EXPERIMENTAL &&
GENERIC_HARDIRQS
depends on MAC80211 && GENERIC_HARDIRQS
select FW_LOADER
select CRC7
---help---
...
...
drivers/net/wireless/ti/wl12xx/Makefile
浏览文件 @
aaabee8b
wl12xx-objs
=
main.o cmd.o acx.o debugfs.o
wl12xx-objs
=
main.o cmd.o acx.o debugfs.o
scan.o event.o
obj-$(CONFIG_WL12XX)
+=
wl12xx.o
drivers/net/wireless/ti/wl12xx/cmd.c
浏览文件 @
aaabee8b
...
...
@@ -284,3 +284,40 @@ int wl128x_cmd_radio_parms(struct wl1271 *wl)
kfree
(
radio_parms
);
return
ret
;
}
int
wl12xx_cmd_channel_switch
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
ieee80211_channel_switch
*
ch_switch
)
{
struct
wl12xx_cmd_channel_switch
*
cmd
;
int
ret
;
wl1271_debug
(
DEBUG_ACX
,
"cmd channel switch"
);
cmd
=
kzalloc
(
sizeof
(
*
cmd
),
GFP_KERNEL
);
if
(
!
cmd
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
cmd
->
role_id
=
wlvif
->
role_id
;
cmd
->
channel
=
ch_switch
->
channel
->
hw_value
;
cmd
->
switch_time
=
ch_switch
->
count
;
cmd
->
stop_tx
=
ch_switch
->
block_tx
;
/* FIXME: control from mac80211 in the future */
/* Enable TX on the target channel */
cmd
->
post_switch_tx_disable
=
0
;
ret
=
wl1271_cmd_send
(
wl
,
CMD_CHANNEL_SWITCH
,
cmd
,
sizeof
(
*
cmd
),
0
);
if
(
ret
<
0
)
{
wl1271_error
(
"failed to send channel switch command"
);
goto
out_free
;
}
out_free:
kfree
(
cmd
);
out:
return
ret
;
}
drivers/net/wireless/ti/wl12xx/cmd.h
浏览文件 @
aaabee8b
...
...
@@ -103,10 +103,30 @@ struct wl1271_ext_radio_parms_cmd {
u8
padding
[
3
];
}
__packed
;
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
;
/* 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
;
int
wl1271_cmd_general_parms
(
struct
wl1271
*
wl
);
int
wl128x_cmd_general_parms
(
struct
wl1271
*
wl
);
int
wl1271_cmd_radio_parms
(
struct
wl1271
*
wl
);
int
wl128x_cmd_radio_parms
(
struct
wl1271
*
wl
);
int
wl1271_cmd_ext_radio_parms
(
struct
wl1271
*
wl
);
int
wl12xx_cmd_channel_switch
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
ieee80211_channel_switch
*
ch_switch
);
#endif
/* __WL12XX_CMD_H__ */
drivers/net/wireless/ti/wl12xx/event.c
0 → 100644
浏览文件 @
aaabee8b
/*
* This file is part of wl12xx
*
* Copyright (C) 2012 Texas Instruments. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include "event.h"
#include "scan.h"
#include "../wlcore/cmd.h"
#include "../wlcore/debug.h"
int
wl12xx_wait_for_event
(
struct
wl1271
*
wl
,
enum
wlcore_wait_event
event
,
bool
*
timeout
)
{
u32
local_event
;
switch
(
event
)
{
case
WLCORE_EVENT_ROLE_STOP_COMPLETE
:
local_event
=
ROLE_STOP_COMPLETE_EVENT_ID
;
break
;
case
WLCORE_EVENT_PEER_REMOVE_COMPLETE
:
local_event
=
PEER_REMOVE_COMPLETE_EVENT_ID
;
break
;
default:
/* event not implemented */
return
0
;
}
return
wlcore_cmd_wait_for_event_or_timeout
(
wl
,
local_event
,
timeout
);
}
int
wl12xx_process_mailbox_events
(
struct
wl1271
*
wl
)
{
struct
wl12xx_event_mailbox
*
mbox
=
wl
->
mbox
;
u32
vector
;
vector
=
le32_to_cpu
(
mbox
->
events_vector
);
vector
&=
~
(
le32_to_cpu
(
mbox
->
events_mask
));
wl1271_debug
(
DEBUG_EVENT
,
"MBOX vector: 0x%x"
,
vector
);
if
(
vector
&
SCAN_COMPLETE_EVENT_ID
)
{
wl1271_debug
(
DEBUG_EVENT
,
"status: 0x%x"
,
mbox
->
scheduled_scan_status
);
if
(
wl
->
scan_wlvif
)
wl12xx_scan_completed
(
wl
,
wl
->
scan_wlvif
);
}
if
(
vector
&
PERIODIC_SCAN_REPORT_EVENT_ID
)
wlcore_event_sched_scan_report
(
wl
,
mbox
->
scheduled_scan_status
);
if
(
vector
&
PERIODIC_SCAN_COMPLETE_EVENT_ID
)
wlcore_event_sched_scan_completed
(
wl
,
mbox
->
scheduled_scan_status
);
if
(
vector
&
SOFT_GEMINI_SENSE_EVENT_ID
)
wlcore_event_soft_gemini_sense
(
wl
,
mbox
->
soft_gemini_sense_info
);
if
(
vector
&
BSS_LOSE_EVENT_ID
)
wlcore_event_beacon_loss
(
wl
,
0xff
);
if
(
vector
&
RSSI_SNR_TRIGGER_0_EVENT_ID
)
wlcore_event_rssi_trigger
(
wl
,
mbox
->
rssi_snr_trigger_metric
);
if
(
vector
&
BA_SESSION_RX_CONSTRAINT_EVENT_ID
)
wlcore_event_ba_rx_constraint
(
wl
,
BIT
(
mbox
->
role_id
),
mbox
->
rx_ba_allowed
);
if
(
vector
&
CHANNEL_SWITCH_COMPLETE_EVENT_ID
)
wlcore_event_channel_switch
(
wl
,
0xff
,
mbox
->
channel_switch_status
);
if
(
vector
&
DUMMY_PACKET_EVENT_ID
)
wlcore_event_dummy_packet
(
wl
);
/*
* "TX retries exceeded" has a different meaning according to mode.
* In AP mode the offending station is disconnected.
*/
if
(
vector
&
MAX_TX_RETRY_EVENT_ID
)
wlcore_event_max_tx_failure
(
wl
,
le16_to_cpu
(
mbox
->
sta_tx_retry_exceeded
));
if
(
vector
&
INACTIVE_STA_EVENT_ID
)
wlcore_event_inactive_sta
(
wl
,
le16_to_cpu
(
mbox
->
sta_aging_status
));
if
(
vector
&
REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID
)
wlcore_event_roc_complete
(
wl
);
return
0
;
}
drivers/net/wireless/ti/wl12xx/event.h
0 → 100644
浏览文件 @
aaabee8b
/*
* This file is part of wl12xx
*
* Copyright (C) 2012 Texas Instruments. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __WL12XX_EVENT_H__
#define __WL12XX_EVENT_H__
#include "../wlcore/wlcore.h"
enum
{
MEASUREMENT_START_EVENT_ID
=
BIT
(
8
),
MEASUREMENT_COMPLETE_EVENT_ID
=
BIT
(
9
),
SCAN_COMPLETE_EVENT_ID
=
BIT
(
10
),
WFD_DISCOVERY_COMPLETE_EVENT_ID
=
BIT
(
11
),
AP_DISCOVERY_COMPLETE_EVENT_ID
=
BIT
(
12
),
RESERVED1
=
BIT
(
13
),
PSPOLL_DELIVERY_FAILURE_EVENT_ID
=
BIT
(
14
),
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
),
MAX_TX_RETRY_EVENT_ID
=
BIT
(
20
),
DUMMY_PACKET_EVENT_ID
=
BIT
(
21
),
SOFT_GEMINI_SENSE_EVENT_ID
=
BIT
(
22
),
CHANGE_AUTO_MODE_TIMEOUT_EVENT_ID
=
BIT
(
23
),
SOFT_GEMINI_AVALANCHE_EVENT_ID
=
BIT
(
24
),
PLT_RX_CALIBRATION_COMPLETE_EVENT_ID
=
BIT
(
25
),
INACTIVE_STA_EVENT_ID
=
BIT
(
26
),
PEER_REMOVE_COMPLETE_EVENT_ID
=
BIT
(
27
),
PERIODIC_SCAN_COMPLETE_EVENT_ID
=
BIT
(
28
),
PERIODIC_SCAN_REPORT_EVENT_ID
=
BIT
(
29
),
BA_SESSION_RX_CONSTRAINT_EVENT_ID
=
BIT
(
30
),
REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID
=
BIT
(
31
),
};
struct
wl12xx_event_mailbox
{
__le32
events_vector
;
__le32
events_mask
;
__le32
reserved_1
;
__le32
reserved_2
;
u8
number_of_scan_results
;
u8
scan_tag
;
u8
completed_scan_status
;
u8
reserved_3
;
u8
soft_gemini_sense_info
;
u8
soft_gemini_protective_info
;
s8
rssi_snr_trigger_metric
[
NUM_OF_RSSI_SNR_TRIGGERS
];
u8
change_auto_mode_timeout
;
u8
scheduled_scan_status
;
u8
reserved4
;
/* tuned channel (roc) */
u8
roc_channel
;
__le16
hlid_removed_bitmap
;
/* bitmap of aged stations (by HLID) */
__le16
sta_aging_status
;
/* bitmap of stations (by HLID) which exceeded max tx retries */
__le16
sta_tx_retry_exceeded
;
/* discovery completed results */
u8
discovery_tag
;
u8
number_of_preq_results
;
u8
number_of_prsp_results
;
u8
reserved_5
;
/* rx ba constraint */
u8
role_id
;
/* 0xFF means any role. */
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
reserved_8
[
9
];
}
__packed
;
int
wl12xx_wait_for_event
(
struct
wl1271
*
wl
,
enum
wlcore_wait_event
event
,
bool
*
timeout
);
int
wl12xx_process_mailbox_events
(
struct
wl1271
*
wl
);
#endif
drivers/net/wireless/ti/wl12xx/main.c
浏览文件 @
aaabee8b
...
...
@@ -38,6 +38,8 @@
#include "reg.h"
#include "cmd.h"
#include "acx.h"
#include "scan.h"
#include "event.h"
#include "debugfs.h"
static
char
*
fref_param
;
...
...
@@ -265,8 +267,8 @@ static struct wlcore_conf wl12xx_conf = {
.
scan
=
{
.
min_dwell_time_active
=
7500
,
.
max_dwell_time_active
=
30000
,
.
min_dwell_time_passive
=
100000
,
.
max_dwell_time_passive
=
10
0000
,
.
dwell_time_passive
=
100000
,
.
dwell_time_dfs
=
15
0000
,
.
num_probe_reqs
=
2
,
.
split_scan_timeout
=
50000
,
},
...
...
@@ -368,6 +370,10 @@ static struct wlcore_conf wl12xx_conf = {
.
increase_time
=
1
,
.
window_size
=
16
,
},
.
recovery
=
{
.
bug_on_recovery
=
0
,
.
no_recovery
=
0
,
},
};
static
struct
wl12xx_priv_conf
wl12xx_default_priv_conf
=
{
...
...
@@ -601,7 +607,7 @@ static int wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
{
int
ret
;
if
(
wl
->
chip
.
id
!=
CHIP_ID_128
3
_PG20
)
{
if
(
wl
->
chip
.
id
!=
CHIP_ID_128
X
_PG20
)
{
struct
wl1271_acx_mem_map
*
wl_mem_map
=
wl
->
target_mem_map
;
struct
wl127x_rx_mem_pool_addr
rx_mem_addr
;
...
...
@@ -631,13 +637,14 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
int
ret
=
0
;
switch
(
wl
->
chip
.
id
)
{
case
CHIP_ID_127
1
_PG10
:
case
CHIP_ID_127
X
_PG10
:
wl1271_warning
(
"chip id 0x%x (1271 PG10) support is obsolete"
,
wl
->
chip
.
id
);
wl
->
quirks
|=
WLCORE_QUIRK_LEGACY_NVS
|
WLCORE_QUIRK_DUAL_PROBE_TMPL
|
WLCORE_QUIRK_TKIP_HEADER_SPACE
;
WLCORE_QUIRK_TKIP_HEADER_SPACE
|
WLCORE_QUIRK_START_STA_FAILS
;
wl
->
sr_fw_name
=
WL127X_FW_NAME_SINGLE
;
wl
->
mr_fw_name
=
WL127X_FW_NAME_MULTI
;
memcpy
(
&
wl
->
conf
.
mem
,
&
wl12xx_default_priv_conf
.
mem_wl127x
,
...
...
@@ -646,18 +653,21 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
/* read data preparation is only needed by wl127x */
wl
->
ops
->
prepare_read
=
wl127x_prepare_read
;
wlcore_set_min_fw_ver
(
wl
,
WL127X_CHIP_VER
,
WL127X_IFTYPE_VER
,
WL127X_MAJOR_VER
,
WL127X_SUBTYPE_VER
,
WL127X_MINOR_VER
);
wlcore_set_min_fw_ver
(
wl
,
WL127X_CHIP_VER
,
WL127X_IFTYPE_SR_VER
,
WL127X_MAJOR_SR_VER
,
WL127X_SUBTYPE_SR_VER
,
WL127X_MINOR_SR_VER
,
WL127X_IFTYPE_MR_VER
,
WL127X_MAJOR_MR_VER
,
WL127X_SUBTYPE_MR_VER
,
WL127X_MINOR_MR_VER
);
break
;
case
CHIP_ID_127
1
_PG20
:
case
CHIP_ID_127
X
_PG20
:
wl1271_debug
(
DEBUG_BOOT
,
"chip id 0x%x (1271 PG20)"
,
wl
->
chip
.
id
);
wl
->
quirks
|=
WLCORE_QUIRK_LEGACY_NVS
|
WLCORE_QUIRK_DUAL_PROBE_TMPL
|
WLCORE_QUIRK_TKIP_HEADER_SPACE
;
WLCORE_QUIRK_TKIP_HEADER_SPACE
|
WLCORE_QUIRK_START_STA_FAILS
;
wl
->
plt_fw_name
=
WL127X_PLT_FW_NAME
;
wl
->
sr_fw_name
=
WL127X_FW_NAME_SINGLE
;
wl
->
mr_fw_name
=
WL127X_FW_NAME_MULTI
;
...
...
@@ -667,12 +677,14 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
/* read data preparation is only needed by wl127x */
wl
->
ops
->
prepare_read
=
wl127x_prepare_read
;
wlcore_set_min_fw_ver
(
wl
,
WL127X_CHIP_VER
,
WL127X_IFTYPE_VER
,
WL127X_MAJOR_VER
,
WL127X_SUBTYPE_VER
,
WL127X_MINOR_VER
);
wlcore_set_min_fw_ver
(
wl
,
WL127X_CHIP_VER
,
WL127X_IFTYPE_SR_VER
,
WL127X_MAJOR_SR_VER
,
WL127X_SUBTYPE_SR_VER
,
WL127X_MINOR_SR_VER
,
WL127X_IFTYPE_MR_VER
,
WL127X_MAJOR_MR_VER
,
WL127X_SUBTYPE_MR_VER
,
WL127X_MINOR_MR_VER
);
break
;
case
CHIP_ID_128
3
_PG20
:
case
CHIP_ID_128
X
_PG20
:
wl1271_debug
(
DEBUG_BOOT
,
"chip id 0x%x (1283 PG20)"
,
wl
->
chip
.
id
);
wl
->
plt_fw_name
=
WL128X_PLT_FW_NAME
;
...
...
@@ -682,19 +694,28 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
/* wl128x requires TX blocksize alignment */
wl
->
quirks
|=
WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN
|
WLCORE_QUIRK_DUAL_PROBE_TMPL
|
WLCORE_QUIRK_TKIP_HEADER_SPACE
;
wlcore_set_min_fw_ver
(
wl
,
WL128X_CHIP_VER
,
WL128X_IFTYPE_VER
,
WL128X_MAJOR_VER
,
WL128X_SUBTYPE_VER
,
WL128X_MINOR_VER
);
WLCORE_QUIRK_TKIP_HEADER_SPACE
|
WLCORE_QUIRK_START_STA_FAILS
;
wlcore_set_min_fw_ver
(
wl
,
WL128X_CHIP_VER
,
WL128X_IFTYPE_SR_VER
,
WL128X_MAJOR_SR_VER
,
WL128X_SUBTYPE_SR_VER
,
WL128X_MINOR_SR_VER
,
WL128X_IFTYPE_MR_VER
,
WL128X_MAJOR_MR_VER
,
WL128X_SUBTYPE_MR_VER
,
WL128X_MINOR_MR_VER
);
break
;
case
CHIP_ID_128
3
_PG10
:
case
CHIP_ID_128
X
_PG10
:
default:
wl1271_warning
(
"unsupported chip id: 0x%x"
,
wl
->
chip
.
id
);
ret
=
-
ENODEV
;
goto
out
;
}
/* common settings */
wl
->
scan_templ_id_2_4
=
CMD_TEMPL_APP_PROBE_REQ_2_4_LEGACY
;
wl
->
scan_templ_id_5
=
CMD_TEMPL_APP_PROBE_REQ_5_LEGACY
;
wl
->
sched_scan_templ_id_2_4
=
CMD_TEMPL_CFG_PROBE_REQ_2_4
;
wl
->
sched_scan_templ_id_5
=
CMD_TEMPL_CFG_PROBE_REQ_5
;
wl
->
max_channels_5
=
WL12XX_MAX_CHANNELS_5GHZ
;
out:
return
ret
;
}
...
...
@@ -1067,7 +1088,7 @@ static int wl12xx_pre_boot(struct wl1271 *wl)
u32
clk
;
int
selected_clock
=
-
1
;
if
(
wl
->
chip
.
id
==
CHIP_ID_128
3
_PG20
)
{
if
(
wl
->
chip
.
id
==
CHIP_ID_128
X
_PG20
)
{
ret
=
wl128x_boot_clk
(
wl
,
&
selected_clock
);
if
(
ret
<
0
)
goto
out
;
...
...
@@ -1098,7 +1119,7 @@ static int wl12xx_pre_boot(struct wl1271 *wl)
wl1271_debug
(
DEBUG_BOOT
,
"clk2 0x%x"
,
clk
);
if
(
wl
->
chip
.
id
==
CHIP_ID_128
3
_PG20
)
if
(
wl
->
chip
.
id
==
CHIP_ID_128
X
_PG20
)
clk
|=
((
selected_clock
&
0x3
)
<<
1
)
<<
4
;
else
clk
|=
(
priv
->
ref_clock
<<
1
)
<<
4
;
...
...
@@ -1152,7 +1173,7 @@ static int wl12xx_pre_upload(struct wl1271 *wl)
/* WL1271: The reference driver skips steps 7 to 10 (jumps directly
* to upload_fw) */
if
(
wl
->
chip
.
id
==
CHIP_ID_128
3
_PG20
)
{
if
(
wl
->
chip
.
id
==
CHIP_ID_128
X
_PG20
)
{
ret
=
wl12xx_top_reg_write
(
wl
,
SDIO_IO_DS
,
HCI_IO_DS_6MA
);
if
(
ret
<
0
)
goto
out
;
...
...
@@ -1219,6 +1240,23 @@ static int wl12xx_boot(struct wl1271 *wl)
if
(
ret
<
0
)
goto
out
;
wl
->
event_mask
=
BSS_LOSE_EVENT_ID
|
REGAINED_BSS_EVENT_ID
|
SCAN_COMPLETE_EVENT_ID
|
ROLE_STOP_COMPLETE_EVENT_ID
|
RSSI_SNR_TRIGGER_0_EVENT_ID
|
PSPOLL_DELIVERY_FAILURE_EVENT_ID
|
SOFT_GEMINI_SENSE_EVENT_ID
|
PERIODIC_SCAN_REPORT_EVENT_ID
|
PERIODIC_SCAN_COMPLETE_EVENT_ID
|
DUMMY_PACKET_EVENT_ID
|
PEER_REMOVE_COMPLETE_EVENT_ID
|
BA_SESSION_RX_CONSTRAINT_EVENT_ID
|
REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID
|
INACTIVE_STA_EVENT_ID
|
MAX_TX_RETRY_EVENT_ID
|
CHANNEL_SWITCH_COMPLETE_EVENT_ID
;
ret
=
wlcore_boot_run_firmware
(
wl
);
if
(
ret
<
0
)
goto
out
;
...
...
@@ -1261,7 +1299,7 @@ static void
wl12xx_set_tx_desc_blocks
(
struct
wl1271
*
wl
,
struct
wl1271_tx_hw_descr
*
desc
,
u32
blks
,
u32
spare_blks
)
{
if
(
wl
->
chip
.
id
==
CHIP_ID_128
3
_PG20
)
{
if
(
wl
->
chip
.
id
==
CHIP_ID_128
X
_PG20
)
{
desc
->
wl128x_mem
.
total_mem_blocks
=
blks
;
}
else
{
desc
->
wl127x_mem
.
extra_blocks
=
spare_blks
;
...
...
@@ -1275,7 +1313,7 @@ wl12xx_set_tx_desc_data_len(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
{
u32
aligned_len
=
wlcore_calc_packet_alignment
(
wl
,
skb
->
len
);
if
(
wl
->
chip
.
id
==
CHIP_ID_128
3
_PG20
)
{
if
(
wl
->
chip
.
id
==
CHIP_ID_128
X
_PG20
)
{
desc
->
wl128x_mem
.
extra_bytes
=
aligned_len
-
skb
->
len
;
desc
->
length
=
cpu_to_le16
(
aligned_len
>>
2
);
...
...
@@ -1339,7 +1377,7 @@ static int wl12xx_hw_init(struct wl1271 *wl)
{
int
ret
;
if
(
wl
->
chip
.
id
==
CHIP_ID_128
3
_PG20
)
{
if
(
wl
->
chip
.
id
==
CHIP_ID_128
X
_PG20
)
{
u32
host_cfg_bitmap
=
HOST_IF_CFG_RX_FIFO_ENABLE
;
ret
=
wl128x_cmd_general_parms
(
wl
);
...
...
@@ -1394,22 +1432,6 @@ static u32 wl12xx_sta_get_ap_rate_mask(struct wl1271 *wl,
return
wlvif
->
rate_set
;
}
static
int
wl12xx_identify_fw
(
struct
wl1271
*
wl
)
{
unsigned
int
*
fw_ver
=
wl
->
chip
.
fw_ver
;
/* Only new station firmwares support routing fw logs to the host */
if
((
fw_ver
[
FW_VER_IF_TYPE
]
==
FW_VER_IF_TYPE_STA
)
&&
(
fw_ver
[
FW_VER_MINOR
]
<
FW_VER_MINOR_FWLOG_STA_MIN
))
wl
->
quirks
|=
WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED
;
/* This feature is not yet supported for AP mode */
if
(
fw_ver
[
FW_VER_IF_TYPE
]
==
FW_VER_IF_TYPE_AP
)
wl
->
quirks
|=
WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED
;
return
0
;
}
static
void
wl12xx_conf_init
(
struct
wl1271
*
wl
)
{
struct
wl12xx_priv
*
priv
=
wl
->
priv
;
...
...
@@ -1426,7 +1448,7 @@ static bool wl12xx_mac_in_fuse(struct wl1271 *wl)
bool
supported
=
false
;
u8
major
,
minor
;
if
(
wl
->
chip
.
id
==
CHIP_ID_128
3
_PG20
)
{
if
(
wl
->
chip
.
id
==
CHIP_ID_128
X
_PG20
)
{
major
=
WL128X_PG_GET_MAJOR
(
wl
->
hw_pg_ver
);
minor
=
WL128X_PG_GET_MINOR
(
wl
->
hw_pg_ver
);
...
...
@@ -1482,7 +1504,7 @@ static int wl12xx_get_pg_ver(struct wl1271 *wl, s8 *ver)
u16
die_info
;
int
ret
;
if
(
wl
->
chip
.
id
==
CHIP_ID_128
3
_PG20
)
if
(
wl
->
chip
.
id
==
CHIP_ID_128
X
_PG20
)
ret
=
wl12xx_top_reg_read
(
wl
,
WL128X_REG_FUSE_DATA_2_1
,
&
die_info
);
else
...
...
@@ -1594,11 +1616,12 @@ static int wl12xx_setup(struct wl1271 *wl);
static
struct
wlcore_ops
wl12xx_ops
=
{
.
setup
=
wl12xx_setup
,
.
identify_chip
=
wl12xx_identify_chip
,
.
identify_fw
=
wl12xx_identify_fw
,
.
boot
=
wl12xx_boot
,
.
plt_init
=
wl12xx_plt_init
,
.
trigger_cmd
=
wl12xx_trigger_cmd
,
.
ack_event
=
wl12xx_ack_event
,
.
wait_for_event
=
wl12xx_wait_for_event
,
.
process_mailbox_events
=
wl12xx_process_mailbox_events
,
.
calc_tx_blocks
=
wl12xx_calc_tx_blocks
,
.
set_tx_desc_blocks
=
wl12xx_set_tx_desc_blocks
,
.
set_tx_desc_data_len
=
wl12xx_set_tx_desc_data_len
,
...
...
@@ -1615,8 +1638,13 @@ static struct wlcore_ops wl12xx_ops = {
.
set_rx_csum
=
NULL
,
.
ap_get_mimo_wide_rate_mask
=
NULL
,
.
debugfs_init
=
wl12xx_debugfs_add_files
,
.
scan_start
=
wl12xx_scan_start
,
.
scan_stop
=
wl12xx_scan_stop
,
.
sched_scan_start
=
wl12xx_sched_scan_start
,
.
sched_scan_stop
=
wl12xx_scan_sched_scan_stop
,
.
get_spare_blocks
=
wl12xx_get_spare_blocks
,
.
set_key
=
wl12xx_set_key
,
.
channel_switch
=
wl12xx_cmd_channel_switch
,
.
pre_pkt_send
=
NULL
,
};
...
...
@@ -1641,6 +1669,7 @@ static int wl12xx_setup(struct wl1271 *wl)
wl
->
rtable
=
wl12xx_rtable
;
wl
->
num_tx_desc
=
WL12XX_NUM_TX_DESCRIPTORS
;
wl
->
num_rx_desc
=
WL12XX_NUM_RX_DESCRIPTORS
;
wl
->
num_channels
=
1
;
wl
->
num_mac_addr
=
WL12XX_NUM_MAC_ADDRESSES
;
wl
->
band_rate_to_idx
=
wl12xx_band_rate_to_idx
;
wl
->
hw_tx_rate_tbl_size
=
WL12XX_CONF_HW_RXTX_RATE_MAX
;
...
...
@@ -1703,7 +1732,8 @@ static int __devinit wl12xx_probe(struct platform_device *pdev)
int
ret
;
hw
=
wlcore_alloc_hw
(
sizeof
(
struct
wl12xx_priv
),
WL12XX_AGGR_BUFFER_SIZE
);
WL12XX_AGGR_BUFFER_SIZE
,
sizeof
(
struct
wl12xx_event_mailbox
));
if
(
IS_ERR
(
hw
))
{
wl1271_error
(
"can't allocate hw"
);
ret
=
PTR_ERR
(
hw
);
...
...
drivers/net/wireless/ti/wl12xx/scan.c
0 → 100644
浏览文件 @
aaabee8b
/*
* This file is part of wl12xx
*
* Copyright (C) 2012 Texas Instruments. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include <linux/ieee80211.h>
#include "scan.h"
#include "../wlcore/debug.h"
#include "../wlcore/tx.h"
static
int
wl1271_get_scan_channels
(
struct
wl1271
*
wl
,
struct
cfg80211_scan_request
*
req
,
struct
basic_scan_channel_params
*
channels
,
enum
ieee80211_band
band
,
bool
passive
)
{
struct
conf_scan_settings
*
c
=
&
wl
->
conf
.
scan
;
int
i
,
j
;
u32
flags
;
for
(
i
=
0
,
j
=
0
;
i
<
req
->
n_channels
&&
j
<
WL1271_SCAN_MAX_CHANNELS
;
i
++
)
{
flags
=
req
->
channels
[
i
]
->
flags
;
if
(
!
test_bit
(
i
,
wl
->
scan
.
scanned_ch
)
&&
!
(
flags
&
IEEE80211_CHAN_DISABLED
)
&&
(
req
->
channels
[
i
]
->
band
==
band
)
&&
/*
* In passive scans, we scan all remaining
* channels, even if not marked as such.
* In active scans, we only scan channels not
* marked as passive.
*/
(
passive
||
!
(
flags
&
IEEE80211_CHAN_PASSIVE_SCAN
)))
{
wl1271_debug
(
DEBUG_SCAN
,
"band %d, center_freq %d "
,
req
->
channels
[
i
]
->
band
,
req
->
channels
[
i
]
->
center_freq
);
wl1271_debug
(
DEBUG_SCAN
,
"hw_value %d, flags %X"
,
req
->
channels
[
i
]
->
hw_value
,
req
->
channels
[
i
]
->
flags
);
wl1271_debug
(
DEBUG_SCAN
,
"max_antenna_gain %d, max_power %d"
,
req
->
channels
[
i
]
->
max_antenna_gain
,
req
->
channels
[
i
]
->
max_power
);
wl1271_debug
(
DEBUG_SCAN
,
"beacon_found %d"
,
req
->
channels
[
i
]
->
beacon_found
);
if
(
!
passive
)
{
channels
[
j
].
min_duration
=
cpu_to_le32
(
c
->
min_dwell_time_active
);
channels
[
j
].
max_duration
=
cpu_to_le32
(
c
->
max_dwell_time_active
);
}
else
{
channels
[
j
].
min_duration
=
cpu_to_le32
(
c
->
dwell_time_passive
);
channels
[
j
].
max_duration
=
cpu_to_le32
(
c
->
dwell_time_passive
);
}
channels
[
j
].
early_termination
=
0
;
channels
[
j
].
tx_power_att
=
req
->
channels
[
i
]
->
max_power
;
channels
[
j
].
channel
=
req
->
channels
[
i
]
->
hw_value
;
memset
(
&
channels
[
j
].
bssid_lsb
,
0xff
,
4
);
memset
(
&
channels
[
j
].
bssid_msb
,
0xff
,
2
);
/* Mark the channels we already used */
set_bit
(
i
,
wl
->
scan
.
scanned_ch
);
j
++
;
}
}
return
j
;
}
#define WL1271_NOTHING_TO_SCAN 1
static
int
wl1271_scan_send
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
enum
ieee80211_band
band
,
bool
passive
,
u32
basic_rate
)
{
struct
ieee80211_vif
*
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
struct
wl1271_cmd_scan
*
cmd
;
struct
wl1271_cmd_trigger_scan_to
*
trigger
;
int
ret
;
u16
scan_options
=
0
;
/* skip active scans if we don't have SSIDs */
if
(
!
passive
&&
wl
->
scan
.
req
->
n_ssids
==
0
)
return
WL1271_NOTHING_TO_SCAN
;
cmd
=
kzalloc
(
sizeof
(
*
cmd
),
GFP_KERNEL
);
trigger
=
kzalloc
(
sizeof
(
*
trigger
),
GFP_KERNEL
);
if
(
!
cmd
||
!
trigger
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
if
(
wl
->
conf
.
scan
.
split_scan_timeout
)
scan_options
|=
WL1271_SCAN_OPT_SPLIT_SCAN
;
if
(
passive
)
scan_options
|=
WL1271_SCAN_OPT_PASSIVE
;
cmd
->
params
.
role_id
=
wlvif
->
role_id
;
if
(
WARN_ON
(
cmd
->
params
.
role_id
==
WL12XX_INVALID_ROLE_ID
))
{
ret
=
-
EINVAL
;
goto
out
;
}
cmd
->
params
.
scan_options
=
cpu_to_le16
(
scan_options
);
cmd
->
params
.
n_ch
=
wl1271_get_scan_channels
(
wl
,
wl
->
scan
.
req
,
cmd
->
channels
,
band
,
passive
);
if
(
cmd
->
params
.
n_ch
==
0
)
{
ret
=
WL1271_NOTHING_TO_SCAN
;
goto
out
;
}
cmd
->
params
.
tx_rate
=
cpu_to_le32
(
basic_rate
);
cmd
->
params
.
n_probe_reqs
=
wl
->
conf
.
scan
.
num_probe_reqs
;
cmd
->
params
.
tid_trigger
=
CONF_TX_AC_ANY_TID
;
cmd
->
params
.
scan_tag
=
WL1271_SCAN_DEFAULT_TAG
;
if
(
band
==
IEEE80211_BAND_2GHZ
)
cmd
->
params
.
band
=
WL1271_SCAN_BAND_2_4_GHZ
;
else
cmd
->
params
.
band
=
WL1271_SCAN_BAND_5_GHZ
;
if
(
wl
->
scan
.
ssid_len
&&
wl
->
scan
.
ssid
)
{
cmd
->
params
.
ssid_len
=
wl
->
scan
.
ssid_len
;
memcpy
(
cmd
->
params
.
ssid
,
wl
->
scan
.
ssid
,
wl
->
scan
.
ssid_len
);
}
memcpy
(
cmd
->
addr
,
vif
->
addr
,
ETH_ALEN
);
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
,
false
);
if
(
ret
<
0
)
{
wl1271_error
(
"PROBE request template failed"
);
goto
out
;
}
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
)
{
wl1271_error
(
"trigger scan to failed for hw scan"
);
goto
out
;
}
wl1271_dump
(
DEBUG_SCAN
,
"SCAN: "
,
cmd
,
sizeof
(
*
cmd
));
ret
=
wl1271_cmd_send
(
wl
,
CMD_SCAN
,
cmd
,
sizeof
(
*
cmd
),
0
);
if
(
ret
<
0
)
{
wl1271_error
(
"SCAN failed"
);
goto
out
;
}
out:
kfree
(
cmd
);
kfree
(
trigger
);
return
ret
;
}
int
wl12xx_scan_stop
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
wl1271_cmd_header
*
cmd
=
NULL
;
int
ret
=
0
;
if
(
WARN_ON
(
wl
->
scan
.
state
==
WL1271_SCAN_STATE_IDLE
))
return
-
EINVAL
;
wl1271_debug
(
DEBUG_CMD
,
"cmd scan stop"
);
cmd
=
kzalloc
(
sizeof
(
*
cmd
),
GFP_KERNEL
);
if
(
!
cmd
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
ret
=
wl1271_cmd_send
(
wl
,
CMD_STOP_SCAN
,
cmd
,
sizeof
(
*
cmd
),
0
);
if
(
ret
<
0
)
{
wl1271_error
(
"cmd stop_scan failed"
);
goto
out
;
}
out:
kfree
(
cmd
);
return
ret
;
}
void
wl1271_scan_stm
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
int
ret
=
0
;
enum
ieee80211_band
band
;
u32
rate
,
mask
;
switch
(
wl
->
scan
.
state
)
{
case
WL1271_SCAN_STATE_IDLE
:
break
;
case
WL1271_SCAN_STATE_2GHZ_ACTIVE
:
band
=
IEEE80211_BAND_2GHZ
;
mask
=
wlvif
->
bitrate_masks
[
band
];
if
(
wl
->
scan
.
req
->
no_cck
)
{
mask
&=
~
CONF_TX_CCK_RATES
;
if
(
!
mask
)
mask
=
CONF_TX_RATE_MASK_BASIC_P2P
;
}
rate
=
wl1271_tx_min_rate_get
(
wl
,
mask
);
ret
=
wl1271_scan_send
(
wl
,
wlvif
,
band
,
false
,
rate
);
if
(
ret
==
WL1271_NOTHING_TO_SCAN
)
{
wl
->
scan
.
state
=
WL1271_SCAN_STATE_2GHZ_PASSIVE
;
wl1271_scan_stm
(
wl
,
wlvif
);
}
break
;
case
WL1271_SCAN_STATE_2GHZ_PASSIVE
:
band
=
IEEE80211_BAND_2GHZ
;
mask
=
wlvif
->
bitrate_masks
[
band
];
if
(
wl
->
scan
.
req
->
no_cck
)
{
mask
&=
~
CONF_TX_CCK_RATES
;
if
(
!
mask
)
mask
=
CONF_TX_RATE_MASK_BASIC_P2P
;
}
rate
=
wl1271_tx_min_rate_get
(
wl
,
mask
);
ret
=
wl1271_scan_send
(
wl
,
wlvif
,
band
,
true
,
rate
);
if
(
ret
==
WL1271_NOTHING_TO_SCAN
)
{
if
(
wl
->
enable_11a
)
wl
->
scan
.
state
=
WL1271_SCAN_STATE_5GHZ_ACTIVE
;
else
wl
->
scan
.
state
=
WL1271_SCAN_STATE_DONE
;
wl1271_scan_stm
(
wl
,
wlvif
);
}
break
;
case
WL1271_SCAN_STATE_5GHZ_ACTIVE
:
band
=
IEEE80211_BAND_5GHZ
;
rate
=
wl1271_tx_min_rate_get
(
wl
,
wlvif
->
bitrate_masks
[
band
]);
ret
=
wl1271_scan_send
(
wl
,
wlvif
,
band
,
false
,
rate
);
if
(
ret
==
WL1271_NOTHING_TO_SCAN
)
{
wl
->
scan
.
state
=
WL1271_SCAN_STATE_5GHZ_PASSIVE
;
wl1271_scan_stm
(
wl
,
wlvif
);
}
break
;
case
WL1271_SCAN_STATE_5GHZ_PASSIVE
:
band
=
IEEE80211_BAND_5GHZ
;
rate
=
wl1271_tx_min_rate_get
(
wl
,
wlvif
->
bitrate_masks
[
band
]);
ret
=
wl1271_scan_send
(
wl
,
wlvif
,
band
,
true
,
rate
);
if
(
ret
==
WL1271_NOTHING_TO_SCAN
)
{
wl
->
scan
.
state
=
WL1271_SCAN_STATE_DONE
;
wl1271_scan_stm
(
wl
,
wlvif
);
}
break
;
case
WL1271_SCAN_STATE_DONE
:
wl
->
scan
.
failed
=
false
;
cancel_delayed_work
(
&
wl
->
scan_complete_work
);
ieee80211_queue_delayed_work
(
wl
->
hw
,
&
wl
->
scan_complete_work
,
msecs_to_jiffies
(
0
));
break
;
default:
wl1271_error
(
"invalid scan state"
);
break
;
}
if
(
ret
<
0
)
{
cancel_delayed_work
(
&
wl
->
scan_complete_work
);
ieee80211_queue_delayed_work
(
wl
->
hw
,
&
wl
->
scan_complete_work
,
msecs_to_jiffies
(
0
));
}
}
static
void
wl12xx_adjust_channels
(
struct
wl1271_cmd_sched_scan_config
*
cmd
,
struct
wlcore_scan_channels
*
cmd_channels
)
{
memcpy
(
cmd
->
passive
,
cmd_channels
->
passive
,
sizeof
(
cmd
->
passive
));
memcpy
(
cmd
->
active
,
cmd_channels
->
active
,
sizeof
(
cmd
->
active
));
cmd
->
dfs
=
cmd_channels
->
dfs
;
cmd
->
n_pactive_ch
=
cmd_channels
->
passive_active
;
memcpy
(
cmd
->
channels_2
,
cmd_channels
->
channels_2
,
sizeof
(
cmd
->
channels_2
));
memcpy
(
cmd
->
channels_5
,
cmd_channels
->
channels_5
,
sizeof
(
cmd
->
channels_2
));
/* channels_4 are not supported, so no need to copy them */
}
int
wl1271_scan_sched_scan_config
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
cfg80211_sched_scan_request
*
req
,
struct
ieee80211_sched_scan_ies
*
ies
)
{
struct
wl1271_cmd_sched_scan_config
*
cfg
=
NULL
;
struct
wlcore_scan_channels
*
cfg_channels
=
NULL
;
struct
conf_sched_scan_settings
*
c
=
&
wl
->
conf
.
sched_scan
;
int
i
,
ret
;
bool
force_passive
=
!
req
->
n_ssids
;
wl1271_debug
(
DEBUG_CMD
,
"cmd sched_scan scan config"
);
cfg
=
kzalloc
(
sizeof
(
*
cfg
),
GFP_KERNEL
);
if
(
!
cfg
)
return
-
ENOMEM
;
cfg
->
role_id
=
wlvif
->
role_id
;
cfg
->
rssi_threshold
=
c
->
rssi_threshold
;
cfg
->
snr_threshold
=
c
->
snr_threshold
;
cfg
->
n_probe_reqs
=
c
->
num_probe_reqs
;
/* cycles set to 0 it means infinite (until manually stopped) */
cfg
->
cycles
=
0
;
/* report APs when at least 1 is found */
cfg
->
report_after
=
1
;
/* don't stop scanning automatically when something is found */
cfg
->
terminate
=
0
;
cfg
->
tag
=
WL1271_SCAN_DEFAULT_TAG
;
/* don't filter on BSS type */
cfg
->
bss_type
=
SCAN_BSS_TYPE_ANY
;
/* currently NL80211 supports only a single interval */
for
(
i
=
0
;
i
<
SCAN_MAX_CYCLE_INTERVALS
;
i
++
)
cfg
->
intervals
[
i
]
=
cpu_to_le32
(
req
->
interval
);
cfg
->
ssid_len
=
0
;
ret
=
wlcore_scan_sched_scan_ssid_list
(
wl
,
wlvif
,
req
);
if
(
ret
<
0
)
goto
out
;
cfg
->
filter_type
=
ret
;
wl1271_debug
(
DEBUG_SCAN
,
"filter_type = %d"
,
cfg
->
filter_type
);
cfg_channels
=
kzalloc
(
sizeof
(
*
cfg_channels
),
GFP_KERNEL
);
if
(
!
cfg_channels
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
if
(
!
wlcore_set_scan_chan_params
(
wl
,
cfg_channels
,
req
->
channels
,
req
->
n_channels
,
req
->
n_ssids
,
SCAN_TYPE_PERIODIC
))
{
wl1271_error
(
"scan channel list is empty"
);
ret
=
-
EINVAL
;
goto
out
;
}
wl12xx_adjust_channels
(
cfg
,
cfg_channels
);
if
(
!
force_passive
&&
cfg
->
active
[
0
])
{
u8
band
=
IEEE80211_BAND_2GHZ
;
ret
=
wl12xx_cmd_build_probe_req
(
wl
,
wlvif
,
wlvif
->
role_id
,
band
,
req
->
ssids
[
0
].
ssid
,
req
->
ssids
[
0
].
ssid_len
,
ies
->
ie
[
band
],
ies
->
len
[
band
],
true
);
if
(
ret
<
0
)
{
wl1271_error
(
"2.4GHz PROBE request template failed"
);
goto
out
;
}
}
if
(
!
force_passive
&&
cfg
->
active
[
1
])
{
u8
band
=
IEEE80211_BAND_5GHZ
;
ret
=
wl12xx_cmd_build_probe_req
(
wl
,
wlvif
,
wlvif
->
role_id
,
band
,
req
->
ssids
[
0
].
ssid
,
req
->
ssids
[
0
].
ssid_len
,
ies
->
ie
[
band
],
ies
->
len
[
band
],
true
);
if
(
ret
<
0
)
{
wl1271_error
(
"5GHz PROBE request template failed"
);
goto
out
;
}
}
wl1271_dump
(
DEBUG_SCAN
,
"SCAN_CFG: "
,
cfg
,
sizeof
(
*
cfg
));
ret
=
wl1271_cmd_send
(
wl
,
CMD_CONNECTION_SCAN_CFG
,
cfg
,
sizeof
(
*
cfg
),
0
);
if
(
ret
<
0
)
{
wl1271_error
(
"SCAN configuration failed"
);
goto
out
;
}
out:
kfree
(
cfg_channels
);
kfree
(
cfg
);
return
ret
;
}
int
wl1271_scan_sched_scan_start
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
wl1271_cmd_sched_scan_start
*
start
;
int
ret
=
0
;
wl1271_debug
(
DEBUG_CMD
,
"cmd periodic scan start"
);
if
(
wlvif
->
bss_type
!=
BSS_TYPE_STA_BSS
)
return
-
EOPNOTSUPP
;
if
((
wl
->
quirks
&
WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN
)
&&
test_bit
(
WLVIF_FLAG_IN_USE
,
&
wlvif
->
flags
))
return
-
EBUSY
;
start
=
kzalloc
(
sizeof
(
*
start
),
GFP_KERNEL
);
if
(
!
start
)
return
-
ENOMEM
;
start
->
role_id
=
wlvif
->
role_id
;
start
->
tag
=
WL1271_SCAN_DEFAULT_TAG
;
ret
=
wl1271_cmd_send
(
wl
,
CMD_START_PERIODIC_SCAN
,
start
,
sizeof
(
*
start
),
0
);
if
(
ret
<
0
)
{
wl1271_error
(
"failed to send scan start command"
);
goto
out_free
;
}
out_free:
kfree
(
start
);
return
ret
;
}
int
wl12xx_sched_scan_start
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
cfg80211_sched_scan_request
*
req
,
struct
ieee80211_sched_scan_ies
*
ies
)
{
int
ret
;
ret
=
wl1271_scan_sched_scan_config
(
wl
,
wlvif
,
req
,
ies
);
if
(
ret
<
0
)
return
ret
;
return
wl1271_scan_sched_scan_start
(
wl
,
wlvif
);
}
void
wl12xx_scan_sched_scan_stop
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
wl1271_cmd_sched_scan_stop
*
stop
;
int
ret
=
0
;
wl1271_debug
(
DEBUG_CMD
,
"cmd periodic scan stop"
);
/* FIXME: what to do if alloc'ing to stop fails? */
stop
=
kzalloc
(
sizeof
(
*
stop
),
GFP_KERNEL
);
if
(
!
stop
)
{
wl1271_error
(
"failed to alloc memory to send sched scan stop"
);
return
;
}
stop
->
role_id
=
wlvif
->
role_id
;
stop
->
tag
=
WL1271_SCAN_DEFAULT_TAG
;
ret
=
wl1271_cmd_send
(
wl
,
CMD_STOP_PERIODIC_SCAN
,
stop
,
sizeof
(
*
stop
),
0
);
if
(
ret
<
0
)
{
wl1271_error
(
"failed to send sched scan stop command"
);
goto
out_free
;
}
out_free:
kfree
(
stop
);
}
int
wl12xx_scan_start
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
cfg80211_scan_request
*
req
)
{
wl1271_scan_stm
(
wl
,
wlvif
);
return
0
;
}
void
wl12xx_scan_completed
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
wl1271_scan_stm
(
wl
,
wlvif
);
}
drivers/net/wireless/ti/wl12xx/scan.h
0 → 100644
浏览文件 @
aaabee8b
/*
* This file is part of wl12xx
*
* Copyright (C) 2012 Texas Instruments. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __WL12XX_SCAN_H__
#define __WL12XX_SCAN_H__
#include "../wlcore/wlcore.h"
#include "../wlcore/cmd.h"
#include "../wlcore/scan.h"
#define WL12XX_MAX_CHANNELS_5GHZ 23
struct
basic_scan_params
{
/* Scan option flags (WL1271_SCAN_OPT_*) */
__le16
scan_options
;
u8
role_id
;
/* Number of scan channels in the list (maximum 30) */
u8
n_ch
;
/* This field indicates the number of probe requests to send
per channel for an active scan */
u8
n_probe_reqs
;
u8
tid_trigger
;
u8
ssid_len
;
u8
use_ssid_list
;
/* Rate bit field for sending the probes */
__le32
tx_rate
;
u8
ssid
[
IEEE80211_MAX_SSID_LEN
];
/* Band to scan */
u8
band
;
u8
scan_tag
;
u8
padding2
[
2
];
}
__packed
;
struct
basic_scan_channel_params
{
/* Duration in TU to wait for frames on a channel for active scan */
__le32
min_duration
;
__le32
max_duration
;
__le32
bssid_lsb
;
__le16
bssid_msb
;
u8
early_termination
;
u8
tx_power_att
;
u8
channel
;
/* FW internal use only! */
u8
dfs_candidate
;
u8
activity_detected
;
u8
pad
;
}
__packed
;
struct
wl1271_cmd_scan
{
struct
wl1271_cmd_header
header
;
struct
basic_scan_params
params
;
struct
basic_scan_channel_params
channels
[
WL1271_SCAN_MAX_CHANNELS
];
/* src mac address */
u8
addr
[
ETH_ALEN
];
u8
padding
[
2
];
}
__packed
;
struct
wl1271_cmd_sched_scan_config
{
struct
wl1271_cmd_header
header
;
__le32
intervals
[
SCAN_MAX_CYCLE_INTERVALS
];
s8
rssi_threshold
;
/* for filtering (in dBm) */
s8
snr_threshold
;
/* for filtering (in dB) */
u8
cycles
;
/* maximum number of scan cycles */
u8
report_after
;
/* report when this number of results are received */
u8
terminate
;
/* stop scanning after reporting */
u8
tag
;
u8
bss_type
;
/* for filtering */
u8
filter_type
;
u8
ssid_len
;
/* For SCAN_SSID_FILTER_SPECIFIC */
u8
ssid
[
IEEE80211_MAX_SSID_LEN
];
u8
n_probe_reqs
;
/* Number of probes requests per channel */
u8
passive
[
SCAN_MAX_BANDS
];
u8
active
[
SCAN_MAX_BANDS
];
u8
dfs
;
u8
n_pactive_ch
;
/* number of pactive (passive until fw detects energy)
channels in BG band */
u8
role_id
;
u8
padding
[
1
];
struct
conn_scan_ch_params
channels_2
[
MAX_CHANNELS_2GHZ
];
struct
conn_scan_ch_params
channels_5
[
WL12XX_MAX_CHANNELS_5GHZ
];
struct
conn_scan_ch_params
channels_4
[
MAX_CHANNELS_4GHZ
];
}
__packed
;
struct
wl1271_cmd_sched_scan_start
{
struct
wl1271_cmd_header
header
;
u8
tag
;
u8
role_id
;
u8
padding
[
2
];
}
__packed
;
struct
wl1271_cmd_sched_scan_stop
{
struct
wl1271_cmd_header
header
;
u8
tag
;
u8
role_id
;
u8
padding
[
2
];
}
__packed
;
int
wl12xx_scan_start
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
cfg80211_scan_request
*
req
);
int
wl12xx_scan_stop
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
void
wl12xx_scan_completed
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl12xx_sched_scan_start
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
cfg80211_sched_scan_request
*
req
,
struct
ieee80211_sched_scan_ies
*
ies
);
void
wl12xx_scan_sched_scan_stop
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
#endif
drivers/net/wireless/ti/wl12xx/wl12xx.h
浏览文件 @
aaabee8b
...
...
@@ -24,19 +24,37 @@
#include "conf.h"
/* minimum FW required for driver for wl127x */
/* WiLink 6/7 chip IDs */
#define CHIP_ID_127X_PG10 (0x04030101)
#define CHIP_ID_127X_PG20 (0x04030111)
#define CHIP_ID_128X_PG10 (0x05030101)
#define CHIP_ID_128X_PG20 (0x05030111)
/* FW chip version for wl127x */
#define WL127X_CHIP_VER 6
#define WL127X_IFTYPE_VER 3
#define WL127X_MAJOR_VER 10
#define WL127X_SUBTYPE_VER 2
#define WL127X_MINOR_VER 115
/* minimum single-role FW version for wl127x */
#define WL127X_IFTYPE_SR_VER 3
#define WL127X_MAJOR_SR_VER 10
#define WL127X_SUBTYPE_SR_VER WLCORE_FW_VER_IGNORE
#define WL127X_MINOR_SR_VER 115
/* minimum multi-role FW version for wl127x */
#define WL127X_IFTYPE_MR_VER 5
#define WL127X_MAJOR_MR_VER 7
#define WL127X_SUBTYPE_MR_VER WLCORE_FW_VER_IGNORE
#define WL127X_MINOR_MR_VER 115
/*
minimum FW required for driver
for wl128x */
/*
FW chip version
for wl128x */
#define WL128X_CHIP_VER 7
#define WL128X_IFTYPE_VER 3
#define WL128X_MAJOR_VER 10
#define WL128X_SUBTYPE_VER 2
#define WL128X_MINOR_VER 115
/* minimum single-role FW version for wl128x */
#define WL128X_IFTYPE_SR_VER 3
#define WL128X_MAJOR_SR_VER 10
#define WL128X_SUBTYPE_SR_VER WLCORE_FW_VER_IGNORE
#define WL128X_MINOR_SR_VER 115
/* minimum multi-role FW version for wl128x */
#define WL128X_IFTYPE_MR_VER 5
#define WL128X_MAJOR_MR_VER 7
#define WL128X_SUBTYPE_MR_VER WLCORE_FW_VER_IGNORE
#define WL128X_MINOR_MR_VER 42
#define WL12XX_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
...
...
drivers/net/wireless/ti/wl18xx/Makefile
浏览文件 @
aaabee8b
wl18xx-objs
=
main.o acx.o tx.o io.o debugfs.o
wl18xx-objs
=
main.o acx.o tx.o io.o debugfs.o
scan.o cmd.o event.o
obj-$(CONFIG_WL18XX)
+=
wl18xx.o
drivers/net/wireless/ti/wl18xx/acx.c
浏览文件 @
aaabee8b
...
...
@@ -75,7 +75,7 @@ int wl18xx_acx_set_checksum_state(struct wl1271 *wl)
acx
->
checksum_state
=
CHECKSUM_OFFLOAD_ENABLED
;
ret
=
wl1271_cmd_configure
(
wl
,
ACX_C
HECK
SUM_CONFIG
,
acx
,
sizeof
(
*
acx
));
ret
=
wl1271_cmd_configure
(
wl
,
ACX_CSUM_CONFIG
,
acx
,
sizeof
(
*
acx
));
if
(
ret
<
0
)
{
wl1271_warning
(
"failed to set Tx checksum state: %d"
,
ret
);
goto
out
;
...
...
@@ -109,3 +109,34 @@ int wl18xx_acx_clear_statistics(struct wl1271 *wl)
kfree
(
acx
);
return
ret
;
}
int
wl18xx_acx_peer_ht_operation_mode
(
struct
wl1271
*
wl
,
u8
hlid
,
bool
wide
)
{
struct
wlcore_peer_ht_operation_mode
*
acx
;
int
ret
;
wl1271_debug
(
DEBUG_ACX
,
"acx peer ht operation mode hlid %d bw %d"
,
hlid
,
wide
);
acx
=
kzalloc
(
sizeof
(
*
acx
),
GFP_KERNEL
);
if
(
!
acx
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
acx
->
hlid
=
hlid
;
acx
->
bandwidth
=
wide
?
WLCORE_BANDWIDTH_40MHZ
:
WLCORE_BANDWIDTH_20MHZ
;
ret
=
wl1271_cmd_configure
(
wl
,
ACX_PEER_HT_OPERATION_MODE_CFG
,
acx
,
sizeof
(
*
acx
));
if
(
ret
<
0
)
{
wl1271_warning
(
"acx peer ht operation mode failed: %d"
,
ret
);
goto
out
;
}
out:
kfree
(
acx
);
return
ret
;
}
drivers/net/wireless/ti/wl18xx/acx.h
浏览文件 @
aaabee8b
...
...
@@ -26,7 +26,13 @@
#include "../wlcore/acx.h"
enum
{
ACX_CLEAR_STATISTICS
=
0x0047
,
ACX_NS_IPV6_FILTER
=
0x0050
,
ACX_PEER_HT_OPERATION_MODE_CFG
=
0x0051
,
ACX_CSUM_CONFIG
=
0x0052
,
ACX_SIM_CONFIG
=
0x0053
,
ACX_CLEAR_STATISTICS
=
0x0054
,
ACX_AUTO_RX_STREAMING
=
0x0055
,
ACX_PEER_CAP
=
0x0056
};
/* numbers of bits the length field takes (add 1 for the actual number) */
...
...
@@ -278,10 +284,24 @@ struct wl18xx_acx_clear_statistics {
struct
acx_header
header
;
};
enum
wlcore_bandwidth
{
WLCORE_BANDWIDTH_20MHZ
,
WLCORE_BANDWIDTH_40MHZ
,
};
struct
wlcore_peer_ht_operation_mode
{
struct
acx_header
header
;
u8
hlid
;
u8
bandwidth
;
/* enum wlcore_bandwidth */
u8
padding
[
2
];
};
int
wl18xx_acx_host_if_cfg_bitmap
(
struct
wl1271
*
wl
,
u32
host_cfg_bitmap
,
u32
sdio_blk_size
,
u32
extra_mem_blks
,
u32
len_field_size
);
int
wl18xx_acx_set_checksum_state
(
struct
wl1271
*
wl
);
int
wl18xx_acx_clear_statistics
(
struct
wl1271
*
wl
);
int
wl18xx_acx_peer_ht_operation_mode
(
struct
wl1271
*
wl
,
u8
hlid
,
bool
wide
);
#endif
/* __WL18XX_ACX_H__ */
drivers/net/wireless/ti/wl18xx/cmd.c
0 → 100644
浏览文件 @
aaabee8b
/*
* This file is part of wl18xx
*
* Copyright (C) 2011 Texas Instruments Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include "../wlcore/cmd.h"
#include "../wlcore/debug.h"
#include "../wlcore/hw_ops.h"
#include "cmd.h"
int
wl18xx_cmd_channel_switch
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
ieee80211_channel_switch
*
ch_switch
)
{
struct
wl18xx_cmd_channel_switch
*
cmd
;
u32
supported_rates
;
int
ret
;
wl1271_debug
(
DEBUG_ACX
,
"cmd channel switch"
);
cmd
=
kzalloc
(
sizeof
(
*
cmd
),
GFP_KERNEL
);
if
(
!
cmd
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
cmd
->
role_id
=
wlvif
->
role_id
;
cmd
->
channel
=
ch_switch
->
channel
->
hw_value
;
cmd
->
switch_time
=
ch_switch
->
count
;
cmd
->
stop_tx
=
ch_switch
->
block_tx
;
switch
(
ch_switch
->
channel
->
band
)
{
case
IEEE80211_BAND_2GHZ
:
cmd
->
band
=
WLCORE_BAND_2_4GHZ
;
break
;
case
IEEE80211_BAND_5GHZ
:
cmd
->
band
=
WLCORE_BAND_5GHZ
;
break
;
default:
wl1271_error
(
"invalid channel switch band: %d"
,
ch_switch
->
channel
->
band
);
ret
=
-
EINVAL
;
goto
out_free
;
}
supported_rates
=
CONF_TX_ENABLED_RATES
|
CONF_TX_MCS_RATES
|
wlcore_hw_sta_get_ap_rate_mask
(
wl
,
wlvif
);
if
(
wlvif
->
p2p
)
supported_rates
&=
~
CONF_TX_CCK_RATES
;
cmd
->
local_supported_rates
=
cpu_to_le32
(
supported_rates
);
cmd
->
channel_type
=
wlvif
->
channel_type
;
ret
=
wl1271_cmd_send
(
wl
,
CMD_CHANNEL_SWITCH
,
cmd
,
sizeof
(
*
cmd
),
0
);
if
(
ret
<
0
)
{
wl1271_error
(
"failed to send channel switch command"
);
goto
out_free
;
}
out_free:
kfree
(
cmd
);
out:
return
ret
;
}
drivers/net/wireless/ti/wl18xx/cmd.h
0 → 100644
浏览文件 @
aaabee8b
/*
* This file is part of wl18xx
*
* Copyright (C) 2011 Texas Instruments. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __WL18XX_CMD_H__
#define __WL18XX_CMD_H__
#include "../wlcore/wlcore.h"
#include "../wlcore/acx.h"
struct
wl18xx_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
;
/* Stop the role TX, should expect it after radar detection */
u8
stop_tx
;
__le32
local_supported_rates
;
u8
channel_type
;
u8
band
;
u8
padding
[
2
];
}
__packed
;
int
wl18xx_cmd_channel_switch
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
ieee80211_channel_switch
*
ch_switch
);
#endif
drivers/net/wireless/ti/wl18xx/event.c
0 → 100644
浏览文件 @
aaabee8b
/*
* This file is part of wl12xx
*
* Copyright (C) 2012 Texas Instruments. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include "event.h"
#include "scan.h"
#include "../wlcore/cmd.h"
#include "../wlcore/debug.h"
int
wl18xx_wait_for_event
(
struct
wl1271
*
wl
,
enum
wlcore_wait_event
event
,
bool
*
timeout
)
{
u32
local_event
;
switch
(
event
)
{
case
WLCORE_EVENT_PEER_REMOVE_COMPLETE
:
local_event
=
PEER_REMOVE_COMPLETE_EVENT_ID
;
break
;
case
WLCORE_EVENT_DFS_CONFIG_COMPLETE
:
local_event
=
DFS_CHANNELS_CONFIG_COMPLETE_EVENT
;
break
;
default:
/* event not implemented */
return
0
;
}
return
wlcore_cmd_wait_for_event_or_timeout
(
wl
,
local_event
,
timeout
);
}
int
wl18xx_process_mailbox_events
(
struct
wl1271
*
wl
)
{
struct
wl18xx_event_mailbox
*
mbox
=
wl
->
mbox
;
u32
vector
;
vector
=
le32_to_cpu
(
mbox
->
events_vector
);
wl1271_debug
(
DEBUG_EVENT
,
"MBOX vector: 0x%x"
,
vector
);
if
(
vector
&
SCAN_COMPLETE_EVENT_ID
)
{
wl1271_debug
(
DEBUG_EVENT
,
"scan results: %d"
,
mbox
->
number_of_scan_results
);
if
(
wl
->
scan_wlvif
)
wl18xx_scan_completed
(
wl
,
wl
->
scan_wlvif
);
}
if
(
vector
&
PERIODIC_SCAN_COMPLETE_EVENT_ID
)
wlcore_event_sched_scan_completed
(
wl
,
1
);
if
(
vector
&
RSSI_SNR_TRIGGER_0_EVENT_ID
)
wlcore_event_rssi_trigger
(
wl
,
mbox
->
rssi_snr_trigger_metric
);
if
(
vector
&
BA_SESSION_RX_CONSTRAINT_EVENT_ID
)
wlcore_event_ba_rx_constraint
(
wl
,
le16_to_cpu
(
mbox
->
rx_ba_role_id_bitmap
),
le16_to_cpu
(
mbox
->
rx_ba_allowed_bitmap
));
if
(
vector
&
BSS_LOSS_EVENT_ID
)
wlcore_event_beacon_loss
(
wl
,
le16_to_cpu
(
mbox
->
bss_loss_bitmap
));
if
(
vector
&
CHANNEL_SWITCH_COMPLETE_EVENT_ID
)
wlcore_event_channel_switch
(
wl
,
le16_to_cpu
(
mbox
->
channel_switch_role_id_bitmap
),
true
);
if
(
vector
&
DUMMY_PACKET_EVENT_ID
)
wlcore_event_dummy_packet
(
wl
);
/*
* "TX retries exceeded" has a different meaning according to mode.
* In AP mode the offending station is disconnected.
*/
if
(
vector
&
MAX_TX_FAILURE_EVENT_ID
)
wlcore_event_max_tx_failure
(
wl
,
le32_to_cpu
(
mbox
->
tx_retry_exceeded_bitmap
));
if
(
vector
&
INACTIVE_STA_EVENT_ID
)
wlcore_event_inactive_sta
(
wl
,
le32_to_cpu
(
mbox
->
inactive_sta_bitmap
));
if
(
vector
&
REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID
)
wlcore_event_roc_complete
(
wl
);
return
0
;
}
drivers/net/wireless/ti/wl18xx/event.h
0 → 100644
浏览文件 @
aaabee8b
/*
* This file is part of wl18xx
*
* Copyright (C) 2012 Texas Instruments. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __WL18XX_EVENT_H__
#define __WL18XX_EVENT_H__
#include "../wlcore/wlcore.h"
enum
{
SCAN_COMPLETE_EVENT_ID
=
BIT
(
8
),
RADAR_DETECTED_EVENT_ID
=
BIT
(
9
),
CHANNEL_SWITCH_COMPLETE_EVENT_ID
=
BIT
(
10
),
BSS_LOSS_EVENT_ID
=
BIT
(
11
),
MAX_TX_FAILURE_EVENT_ID
=
BIT
(
12
),
DUMMY_PACKET_EVENT_ID
=
BIT
(
13
),
INACTIVE_STA_EVENT_ID
=
BIT
(
14
),
PEER_REMOVE_COMPLETE_EVENT_ID
=
BIT
(
15
),
PERIODIC_SCAN_COMPLETE_EVENT_ID
=
BIT
(
16
),
BA_SESSION_RX_CONSTRAINT_EVENT_ID
=
BIT
(
17
),
REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID
=
BIT
(
18
),
DFS_CHANNELS_CONFIG_COMPLETE_EVENT
=
BIT
(
19
),
};
struct
wl18xx_event_mailbox
{
__le32
events_vector
;
u8
number_of_scan_results
;
u8
number_of_sched_scan_results
;
__le16
channel_switch_role_id_bitmap
;
s8
rssi_snr_trigger_metric
[
NUM_OF_RSSI_SNR_TRIGGERS
];
/* bitmap of removed links */
__le32
hlid_removed_bitmap
;
/* rx ba constraint */
__le16
rx_ba_role_id_bitmap
;
/* 0xfff means any role. */
__le16
rx_ba_allowed_bitmap
;
/* bitmap of roc completed (by role id) */
__le16
roc_completed_bitmap
;
/* bitmap of stations (by role id) with bss loss */
__le16
bss_loss_bitmap
;
/* bitmap of stations (by HLID) which exceeded max tx retries */
__le32
tx_retry_exceeded_bitmap
;
/* bitmap of inactive stations (by HLID) */
__le32
inactive_sta_bitmap
;
}
__packed
;
int
wl18xx_wait_for_event
(
struct
wl1271
*
wl
,
enum
wlcore_wait_event
event
,
bool
*
timeout
);
int
wl18xx_process_mailbox_events
(
struct
wl1271
*
wl
);
#endif
drivers/net/wireless/ti/wl18xx/main.c
浏览文件 @
aaabee8b
...
...
@@ -34,10 +34,13 @@
#include "reg.h"
#include "conf.h"
#include "cmd.h"
#include "acx.h"
#include "tx.h"
#include "wl18xx.h"
#include "io.h"
#include "scan.h"
#include "event.h"
#include "debugfs.h"
#define WL18XX_RX_CHECKSUM_MASK 0x40
...
...
@@ -391,8 +394,8 @@ static struct wlcore_conf wl18xx_conf = {
.
scan
=
{
.
min_dwell_time_active
=
7500
,
.
max_dwell_time_active
=
30000
,
.
min_dwell_time_passive
=
100000
,
.
max_dwell_time_passive
=
10
0000
,
.
dwell_time_passive
=
100000
,
.
dwell_time_dfs
=
15
0000
,
.
num_probe_reqs
=
2
,
.
split_scan_timeout
=
50000
,
},
...
...
@@ -489,6 +492,10 @@ static struct wlcore_conf wl18xx_conf = {
.
increase_time
=
1
,
.
window_size
=
16
,
},
.
recovery
=
{
.
bug_on_recovery
=
0
,
.
no_recovery
=
0
,
},
};
static
struct
wl18xx_priv_conf
wl18xx_default_priv_conf
=
{
...
...
@@ -595,7 +602,7 @@ static const struct wl18xx_clk_cfg wl18xx_clk_table[NUM_CLOCK_CONFIGS] = {
};
/* TODO: maybe move to a new header file? */
#define WL18XX_FW_NAME "ti-connectivity/wl18xx-fw.bin"
#define WL18XX_FW_NAME "ti-connectivity/wl18xx-fw
-2
.bin"
static
int
wl18xx_identify_chip
(
struct
wl1271
*
wl
)
{
...
...
@@ -612,11 +619,15 @@ static int wl18xx_identify_chip(struct wl1271 *wl)
WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN
|
WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN
|
WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN
|
WLCORE_QUIRK_TX_PAD_LAST_FRAME
;
wlcore_set_min_fw_ver
(
wl
,
WL18XX_CHIP_VER
,
WL18XX_IFTYPE_VER
,
WL18XX_MAJOR_VER
,
WL18XX_SUBTYPE_VER
,
WL18XX_MINOR_VER
);
WLCORE_QUIRK_TX_PAD_LAST_FRAME
|
WLCORE_QUIRK_REGDOMAIN_CONF
|
WLCORE_QUIRK_DUAL_PROBE_TMPL
;
wlcore_set_min_fw_ver
(
wl
,
WL18XX_CHIP_VER
,
WL18XX_IFTYPE_VER
,
WL18XX_MAJOR_VER
,
WL18XX_SUBTYPE_VER
,
WL18XX_MINOR_VER
,
/* there's no separate multi-role FW */
0
,
0
,
0
,
0
);
break
;
case
CHIP_ID_185x_PG10
:
wl1271_warning
(
"chip id 0x%x (185x PG10) is deprecated"
,
...
...
@@ -630,6 +641,11 @@ static int wl18xx_identify_chip(struct wl1271 *wl)
goto
out
;
}
wl
->
scan_templ_id_2_4
=
CMD_TEMPL_CFG_PROBE_REQ_2_4
;
wl
->
scan_templ_id_5
=
CMD_TEMPL_CFG_PROBE_REQ_5
;
wl
->
sched_scan_templ_id_2_4
=
CMD_TEMPL_PROBE_REQ_2_4_PERIODIC
;
wl
->
sched_scan_templ_id_5
=
CMD_TEMPL_PROBE_REQ_5_PERIODIC
;
wl
->
max_channels_5
=
WL18XX_MAX_CHANNELS_5GHZ
;
out:
return
ret
;
}
...
...
@@ -843,6 +859,19 @@ static int wl18xx_boot(struct wl1271 *wl)
if
(
ret
<
0
)
goto
out
;
wl
->
event_mask
=
BSS_LOSS_EVENT_ID
|
SCAN_COMPLETE_EVENT_ID
|
RSSI_SNR_TRIGGER_0_EVENT_ID
|
PERIODIC_SCAN_COMPLETE_EVENT_ID
|
DUMMY_PACKET_EVENT_ID
|
PEER_REMOVE_COMPLETE_EVENT_ID
|
BA_SESSION_RX_CONSTRAINT_EVENT_ID
|
REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID
|
INACTIVE_STA_EVENT_ID
|
MAX_TX_FAILURE_EVENT_ID
|
CHANNEL_SWITCH_COMPLETE_EVENT_ID
|
DFS_CHANNELS_CONFIG_COMPLETE_EVENT
;
ret
=
wlcore_boot_run_firmware
(
wl
);
if
(
ret
<
0
)
goto
out
;
...
...
@@ -1296,6 +1325,43 @@ static u32 wl18xx_pre_pkt_send(struct wl1271 *wl,
return
buf_offset
;
}
static
void
wl18xx_sta_rc_update
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
ieee80211_sta
*
sta
,
u32
changed
)
{
bool
wide
=
sta
->
ht_cap
.
cap
&
IEEE80211_HT_CAP_SUP_WIDTH_20_40
;
wl1271_debug
(
DEBUG_MAC80211
,
"mac80211 sta_rc_update wide %d"
,
wide
);
if
(
!
(
changed
&
IEEE80211_RC_BW_CHANGED
))
return
;
mutex_lock
(
&
wl
->
mutex
);
/* sanity */
if
(
WARN_ON
(
wlvif
->
bss_type
!=
BSS_TYPE_STA_BSS
))
goto
out
;
/* ignore the change before association */
if
(
!
test_bit
(
WLVIF_FLAG_STA_ASSOCIATED
,
&
wlvif
->
flags
))
goto
out
;
/*
* If we started out as wide, we can change the operation mode. If we
* thought this was a 20mhz AP, we have to reconnect
*/
if
(
wlvif
->
sta
.
role_chan_type
==
NL80211_CHAN_HT40MINUS
||
wlvif
->
sta
.
role_chan_type
==
NL80211_CHAN_HT40PLUS
)
wl18xx_acx_peer_ht_operation_mode
(
wl
,
wlvif
->
sta
.
hlid
,
wide
);
else
ieee80211_connection_loss
(
wl12xx_wlvif_to_vif
(
wlvif
));
out:
mutex_unlock
(
&
wl
->
mutex
);
}
static
int
wl18xx_setup
(
struct
wl1271
*
wl
);
static
struct
wlcore_ops
wl18xx_ops
=
{
...
...
@@ -1305,6 +1371,8 @@ static struct wlcore_ops wl18xx_ops = {
.
plt_init
=
wl18xx_plt_init
,
.
trigger_cmd
=
wl18xx_trigger_cmd
,
.
ack_event
=
wl18xx_ack_event
,
.
wait_for_event
=
wl18xx_wait_for_event
,
.
process_mailbox_events
=
wl18xx_process_mailbox_events
,
.
calc_tx_blocks
=
wl18xx_calc_tx_blocks
,
.
set_tx_desc_blocks
=
wl18xx_set_tx_desc_blocks
,
.
set_tx_desc_data_len
=
wl18xx_set_tx_desc_data_len
,
...
...
@@ -1320,10 +1388,16 @@ static struct wlcore_ops wl18xx_ops = {
.
ap_get_mimo_wide_rate_mask
=
wl18xx_ap_get_mimo_wide_rate_mask
,
.
get_mac
=
wl18xx_get_mac
,
.
debugfs_init
=
wl18xx_debugfs_add_files
,
.
scan_start
=
wl18xx_scan_start
,
.
scan_stop
=
wl18xx_scan_stop
,
.
sched_scan_start
=
wl18xx_sched_scan_start
,
.
sched_scan_stop
=
wl18xx_scan_sched_scan_stop
,
.
handle_static_data
=
wl18xx_handle_static_data
,
.
get_spare_blocks
=
wl18xx_get_spare_blocks
,
.
set_key
=
wl18xx_set_key
,
.
channel_switch
=
wl18xx_cmd_channel_switch
,
.
pre_pkt_send
=
wl18xx_pre_pkt_send
,
.
sta_rc_update
=
wl18xx_sta_rc_update
,
};
/* HT cap appropriate for wide channels in 2Ghz */
...
...
@@ -1388,6 +1462,7 @@ static int wl18xx_setup(struct wl1271 *wl)
wl
->
rtable
=
wl18xx_rtable
;
wl
->
num_tx_desc
=
WL18XX_NUM_TX_DESCRIPTORS
;
wl
->
num_rx_desc
=
WL18XX_NUM_TX_DESCRIPTORS
;
wl
->
num_channels
=
2
;
wl
->
num_mac_addr
=
WL18XX_NUM_MAC_ADDRESSES
;
wl
->
band_rate_to_idx
=
wl18xx_band_rate_to_idx
;
wl
->
hw_tx_rate_tbl_size
=
WL18XX_CONF_HW_RXTX_RATE_MAX
;
...
...
@@ -1506,7 +1581,8 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
int
ret
;
hw
=
wlcore_alloc_hw
(
sizeof
(
struct
wl18xx_priv
),
WL18XX_AGGR_BUFFER_SIZE
);
WL18XX_AGGR_BUFFER_SIZE
,
sizeof
(
struct
wl18xx_event_mailbox
));
if
(
IS_ERR
(
hw
))
{
wl1271_error
(
"can't allocate hw"
);
ret
=
PTR_ERR
(
hw
);
...
...
drivers/net/wireless/ti/wl18xx/scan.c
0 → 100644
浏览文件 @
aaabee8b
/*
* This file is part of wl18xx
*
* Copyright (C) 2012 Texas Instruments. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include <linux/ieee80211.h>
#include "scan.h"
#include "../wlcore/debug.h"
static
void
wl18xx_adjust_channels
(
struct
wl18xx_cmd_scan_params
*
cmd
,
struct
wlcore_scan_channels
*
cmd_channels
)
{
memcpy
(
cmd
->
passive
,
cmd_channels
->
passive
,
sizeof
(
cmd
->
passive
));
memcpy
(
cmd
->
active
,
cmd_channels
->
active
,
sizeof
(
cmd
->
active
));
cmd
->
dfs
=
cmd_channels
->
dfs
;
cmd
->
passive_active
=
cmd_channels
->
passive_active
;
memcpy
(
cmd
->
channels_2
,
cmd_channels
->
channels_2
,
sizeof
(
cmd
->
channels_2
));
memcpy
(
cmd
->
channels_5
,
cmd_channels
->
channels_5
,
sizeof
(
cmd
->
channels_2
));
/* channels_4 are not supported, so no need to copy them */
}
static
int
wl18xx_scan_send
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
cfg80211_scan_request
*
req
)
{
struct
wl18xx_cmd_scan_params
*
cmd
;
struct
wlcore_scan_channels
*
cmd_channels
=
NULL
;
int
ret
;
cmd
=
kzalloc
(
sizeof
(
*
cmd
),
GFP_KERNEL
);
if
(
!
cmd
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
cmd
->
role_id
=
wlvif
->
role_id
;
if
(
WARN_ON
(
cmd
->
role_id
==
WL12XX_INVALID_ROLE_ID
))
{
ret
=
-
EINVAL
;
goto
out
;
}
cmd
->
scan_type
=
SCAN_TYPE_SEARCH
;
cmd
->
rssi_threshold
=
-
127
;
cmd
->
snr_threshold
=
0
;
cmd
->
bss_type
=
SCAN_BSS_TYPE_ANY
;
cmd
->
ssid_from_list
=
0
;
cmd
->
filter
=
0
;
cmd
->
add_broadcast
=
0
;
cmd
->
urgency
=
0
;
cmd
->
protect
=
0
;
cmd
->
n_probe_reqs
=
wl
->
conf
.
scan
.
num_probe_reqs
;
cmd
->
terminate_after
=
0
;
/* configure channels */
WARN_ON
(
req
->
n_ssids
>
1
);
cmd_channels
=
kzalloc
(
sizeof
(
*
cmd_channels
),
GFP_KERNEL
);
if
(
!
cmd_channels
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
wlcore_set_scan_chan_params
(
wl
,
cmd_channels
,
req
->
channels
,
req
->
n_channels
,
req
->
n_ssids
,
SCAN_TYPE_SEARCH
);
wl18xx_adjust_channels
(
cmd
,
cmd_channels
);
/*
* all the cycles params (except total cycles) should
* remain 0 for normal scan
*/
cmd
->
total_cycles
=
1
;
if
(
req
->
no_cck
)
cmd
->
rate
=
WL18XX_SCAN_RATE_6
;
cmd
->
tag
=
WL1271_SCAN_DEFAULT_TAG
;
if
(
req
->
n_ssids
)
{
cmd
->
ssid_len
=
req
->
ssids
[
0
].
ssid_len
;
memcpy
(
cmd
->
ssid
,
req
->
ssids
[
0
].
ssid
,
cmd
->
ssid_len
);
}
/* TODO: per-band ies? */
if
(
cmd
->
active
[
0
])
{
u8
band
=
IEEE80211_BAND_2GHZ
;
ret
=
wl12xx_cmd_build_probe_req
(
wl
,
wlvif
,
cmd
->
role_id
,
band
,
req
->
ssids
[
0
].
ssid
,
req
->
ssids
[
0
].
ssid_len
,
req
->
ie
,
req
->
ie_len
,
false
);
if
(
ret
<
0
)
{
wl1271_error
(
"2.4GHz PROBE request template failed"
);
goto
out
;
}
}
if
(
cmd
->
active
[
1
])
{
u8
band
=
IEEE80211_BAND_5GHZ
;
ret
=
wl12xx_cmd_build_probe_req
(
wl
,
wlvif
,
cmd
->
role_id
,
band
,
req
->
ssids
[
0
].
ssid
,
req
->
ssids
[
0
].
ssid_len
,
req
->
ie
,
req
->
ie_len
,
false
);
if
(
ret
<
0
)
{
wl1271_error
(
"5GHz PROBE request template failed"
);
goto
out
;
}
}
wl1271_dump
(
DEBUG_SCAN
,
"SCAN: "
,
cmd
,
sizeof
(
*
cmd
));
ret
=
wl1271_cmd_send
(
wl
,
CMD_SCAN
,
cmd
,
sizeof
(
*
cmd
),
0
);
if
(
ret
<
0
)
{
wl1271_error
(
"SCAN failed"
);
goto
out
;
}
out:
kfree
(
cmd_channels
);
kfree
(
cmd
);
return
ret
;
}
void
wl18xx_scan_completed
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
wl
->
scan
.
failed
=
false
;
cancel_delayed_work
(
&
wl
->
scan_complete_work
);
ieee80211_queue_delayed_work
(
wl
->
hw
,
&
wl
->
scan_complete_work
,
msecs_to_jiffies
(
0
));
}
static
int
wl18xx_scan_sched_scan_config
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
cfg80211_sched_scan_request
*
req
,
struct
ieee80211_sched_scan_ies
*
ies
)
{
struct
wl18xx_cmd_scan_params
*
cmd
;
struct
wlcore_scan_channels
*
cmd_channels
=
NULL
;
struct
conf_sched_scan_settings
*
c
=
&
wl
->
conf
.
sched_scan
;
int
ret
;
int
filter_type
;
wl1271_debug
(
DEBUG_CMD
,
"cmd sched_scan scan config"
);
filter_type
=
wlcore_scan_sched_scan_ssid_list
(
wl
,
wlvif
,
req
);
if
(
filter_type
<
0
)
return
filter_type
;
cmd
=
kzalloc
(
sizeof
(
*
cmd
),
GFP_KERNEL
);
if
(
!
cmd
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
cmd
->
role_id
=
wlvif
->
role_id
;
if
(
WARN_ON
(
cmd
->
role_id
==
WL12XX_INVALID_ROLE_ID
))
{
ret
=
-
EINVAL
;
goto
out
;
}
cmd
->
scan_type
=
SCAN_TYPE_PERIODIC
;
cmd
->
rssi_threshold
=
c
->
rssi_threshold
;
cmd
->
snr_threshold
=
c
->
snr_threshold
;
/* don't filter on BSS type */
cmd
->
bss_type
=
SCAN_BSS_TYPE_ANY
;
cmd
->
ssid_from_list
=
1
;
if
(
filter_type
==
SCAN_SSID_FILTER_LIST
)
cmd
->
filter
=
1
;
cmd
->
add_broadcast
=
0
;
cmd
->
urgency
=
0
;
cmd
->
protect
=
0
;
cmd
->
n_probe_reqs
=
c
->
num_probe_reqs
;
/* don't stop scanning automatically when something is found */
cmd
->
terminate_after
=
0
;
cmd_channels
=
kzalloc
(
sizeof
(
*
cmd_channels
),
GFP_KERNEL
);
if
(
!
cmd_channels
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
/* configure channels */
wlcore_set_scan_chan_params
(
wl
,
cmd_channels
,
req
->
channels
,
req
->
n_channels
,
req
->
n_ssids
,
SCAN_TYPE_PERIODIC
);
wl18xx_adjust_channels
(
cmd
,
cmd_channels
);
cmd
->
short_cycles_sec
=
0
;
cmd
->
long_cycles_sec
=
cpu_to_le16
(
req
->
interval
);
cmd
->
short_cycles_count
=
0
;
cmd
->
total_cycles
=
0
;
cmd
->
tag
=
WL1271_SCAN_DEFAULT_TAG
;
if
(
cmd
->
active
[
0
])
{
u8
band
=
IEEE80211_BAND_2GHZ
;
ret
=
wl12xx_cmd_build_probe_req
(
wl
,
wlvif
,
cmd
->
role_id
,
band
,
req
->
ssids
[
0
].
ssid
,
req
->
ssids
[
0
].
ssid_len
,
ies
->
ie
[
band
],
ies
->
len
[
band
],
true
);
if
(
ret
<
0
)
{
wl1271_error
(
"2.4GHz PROBE request template failed"
);
goto
out
;
}
}
if
(
cmd
->
active
[
1
])
{
u8
band
=
IEEE80211_BAND_5GHZ
;
ret
=
wl12xx_cmd_build_probe_req
(
wl
,
wlvif
,
cmd
->
role_id
,
band
,
req
->
ssids
[
0
].
ssid
,
req
->
ssids
[
0
].
ssid_len
,
ies
->
ie
[
band
],
ies
->
len
[
band
],
true
);
if
(
ret
<
0
)
{
wl1271_error
(
"5GHz PROBE request template failed"
);
goto
out
;
}
}
wl1271_dump
(
DEBUG_SCAN
,
"SCAN: "
,
cmd
,
sizeof
(
*
cmd
));
ret
=
wl1271_cmd_send
(
wl
,
CMD_SCAN
,
cmd
,
sizeof
(
*
cmd
),
0
);
if
(
ret
<
0
)
{
wl1271_error
(
"SCAN failed"
);
goto
out
;
}
out:
kfree
(
cmd_channels
);
kfree
(
cmd
);
return
ret
;
}
int
wl18xx_sched_scan_start
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
cfg80211_sched_scan_request
*
req
,
struct
ieee80211_sched_scan_ies
*
ies
)
{
return
wl18xx_scan_sched_scan_config
(
wl
,
wlvif
,
req
,
ies
);
}
static
int
__wl18xx_scan_stop
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
scan_type
)
{
struct
wl18xx_cmd_scan_stop
*
stop
;
int
ret
;
wl1271_debug
(
DEBUG_CMD
,
"cmd periodic scan stop"
);
stop
=
kzalloc
(
sizeof
(
*
stop
),
GFP_KERNEL
);
if
(
!
stop
)
{
wl1271_error
(
"failed to alloc memory to send sched scan stop"
);
return
-
ENOMEM
;
}
stop
->
role_id
=
wlvif
->
role_id
;
stop
->
scan_type
=
scan_type
;
ret
=
wl1271_cmd_send
(
wl
,
CMD_STOP_SCAN
,
stop
,
sizeof
(
*
stop
),
0
);
if
(
ret
<
0
)
{
wl1271_error
(
"failed to send sched scan stop command"
);
goto
out_free
;
}
out_free:
kfree
(
stop
);
return
ret
;
}
void
wl18xx_scan_sched_scan_stop
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
__wl18xx_scan_stop
(
wl
,
wlvif
,
SCAN_TYPE_PERIODIC
);
}
int
wl18xx_scan_start
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
cfg80211_scan_request
*
req
)
{
return
wl18xx_scan_send
(
wl
,
wlvif
,
req
);
}
int
wl18xx_scan_stop
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
return
__wl18xx_scan_stop
(
wl
,
wlvif
,
SCAN_TYPE_SEARCH
);
}
drivers/net/wireless/ti/wl18xx/scan.h
0 → 100644
浏览文件 @
aaabee8b
/*
* This file is part of wl18xx
*
* Copyright (C) 2012 Texas Instruments. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __WL18XX_SCAN_H__
#define __WL18XX_SCAN_H__
#include "../wlcore/wlcore.h"
#include "../wlcore/cmd.h"
#include "../wlcore/scan.h"
struct
tracking_ch_params
{
struct
conn_scan_ch_params
channel
;
__le32
bssid_lsb
;
__le16
bssid_msb
;
u8
padding
[
2
];
}
__packed
;
/* probe request rate */
enum
{
WL18XX_SCAN_RATE_1
=
0
,
WL18XX_SCAN_RATE_5_5
=
1
,
WL18XX_SCAN_RATE_6
=
2
,
};
#define WL18XX_MAX_CHANNELS_5GHZ 32
struct
wl18xx_cmd_scan_params
{
struct
wl1271_cmd_header
header
;
u8
role_id
;
u8
scan_type
;
s8
rssi_threshold
;
/* for filtering (in dBm) */
s8
snr_threshold
;
/* for filtering (in dB) */
u8
bss_type
;
/* for filtering */
u8
ssid_from_list
;
/* use ssid from configured ssid list */
u8
filter
;
/* forward only results with matching ssids */
/*
* add broadcast ssid in addition to the configured ssids.
* the driver should add dummy entry for it (?).
*/
u8
add_broadcast
;
u8
urgency
;
u8
protect
;
/* ??? */
u8
n_probe_reqs
;
/* Number of probes requests per channel */
u8
terminate_after
;
/* early terminate scan operation */
u8
passive
[
SCAN_MAX_BANDS
];
/* number of passive scan channels */
u8
active
[
SCAN_MAX_BANDS
];
/* number of active scan channels */
u8
dfs
;
/* number of dfs channels in 5ghz */
u8
passive_active
;
/* number of passive before active channels 2.4ghz */
__le16
short_cycles_sec
;
__le16
long_cycles_sec
;
u8
short_cycles_count
;
u8
total_cycles
;
/* 0 - infinite */
u8
rate
;
u8
padding
[
1
];
union
{
struct
{
struct
conn_scan_ch_params
channels_2
[
MAX_CHANNELS_2GHZ
];
struct
conn_scan_ch_params
channels_5
[
WL18XX_MAX_CHANNELS_5GHZ
];
struct
conn_scan_ch_params
channels_4
[
MAX_CHANNELS_4GHZ
];
};
struct
tracking_ch_params
channels_tracking
[
WL1271_SCAN_MAX_CHANNELS
];
}
;
u8
ssid
[
IEEE80211_MAX_SSID_LEN
];
u8
ssid_len
;
/* For SCAN_SSID_FILTER_SPECIFIC */
u8
tag
;
u8
padding1
[
2
];
}
__packed
;
struct
wl18xx_cmd_scan_stop
{
struct
wl1271_cmd_header
header
;
u8
role_id
;
u8
scan_type
;
u8
padding
[
2
];
}
__packed
;
int
wl18xx_scan_start
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
cfg80211_scan_request
*
req
);
int
wl18xx_scan_stop
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
void
wl18xx_scan_completed
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl18xx_sched_scan_start
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
cfg80211_sched_scan_request
*
req
,
struct
ieee80211_sched_scan_ies
*
ies
);
void
wl18xx_scan_sched_scan_stop
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
#endif
drivers/net/wireless/ti/wl18xx/wl18xx.h
浏览文件 @
aaabee8b
...
...
@@ -26,10 +26,10 @@
/* minimum FW required for driver */
#define WL18XX_CHIP_VER 8
#define WL18XX_IFTYPE_VER
2
#define WL18XX_MAJOR_VER
0
#define WL18XX_SUBTYPE_VER
0
#define WL18XX_MINOR_VER
100
#define WL18XX_IFTYPE_VER
5
#define WL18XX_MAJOR_VER
WLCORE_FW_VER_IGNORE
#define WL18XX_SUBTYPE_VER
WLCORE_FW_VER_IGNORE
#define WL18XX_MINOR_VER
28
#define WL18XX_CMD_MAX_SIZE 740
...
...
drivers/net/wireless/ti/wlcore/acx.h
浏览文件 @
aaabee8b
...
...
@@ -1025,7 +1025,6 @@ enum {
ACX_CONFIG_HANGOVER
=
0x0042
,
ACX_FEATURE_CFG
=
0x0043
,
ACX_PROTECTION_CFG
=
0x0044
,
ACX_CHECKSUM_CONFIG
=
0x0045
,
};
...
...
drivers/net/wireless/ti/wlcore/boot.c
浏览文件 @
aaabee8b
...
...
@@ -84,47 +84,57 @@ static int wlcore_boot_parse_fw_ver(struct wl1271 *wl,
static
int
wlcore_validate_fw_ver
(
struct
wl1271
*
wl
)
{
unsigned
int
*
fw_ver
=
wl
->
chip
.
fw_ver
;
unsigned
int
*
min_ver
=
wl
->
min_fw_ver
;
unsigned
int
*
min_ver
=
(
wl
->
fw_type
==
WL12XX_FW_TYPE_NORMAL
)
?
wl
->
min_sr_fw_ver
:
wl
->
min_mr_fw_ver
;
char
min_fw_str
[
32
]
=
""
;
int
i
;
/* the chip must be exactly equal */
if
(
min_ver
[
FW_VER_CHIP
]
!=
fw_ver
[
FW_VER_CHIP
])
if
((
min_ver
[
FW_VER_CHIP
]
!=
WLCORE_FW_VER_IGNORE
)
&&
(
min_ver
[
FW_VER_CHIP
]
!=
fw_ver
[
FW_VER_CHIP
]))
goto
fail
;
/* always check the next digit if all previous ones are equal */
if
(
min_ver
[
FW_VER_IF_TYPE
]
<
fw_ver
[
FW_VER_IF_TYPE
])
goto
out
;
else
if
(
min_ver
[
FW_VER_IF_TYPE
]
>
fw_ver
[
FW_VER_IF_TYPE
])
/* the firmware type must be equal */
if
((
min_ver
[
FW_VER_IF_TYPE
]
!=
WLCORE_FW_VER_IGNORE
)
&&
(
min_ver
[
FW_VER_IF_TYPE
]
!=
fw_ver
[
FW_VER_IF_TYPE
]))
goto
fail
;
if
(
min_ver
[
FW_VER_MAJOR
]
<
fw_ver
[
FW_VER_MAJOR
])
goto
out
;
else
if
(
min_ver
[
FW_VER_MAJOR
]
>
fw_ver
[
FW_VER_MAJOR
]
)
/* the project number must be equal */
if
((
min_ver
[
FW_VER_SUBTYPE
]
!=
WLCORE_FW_VER_IGNORE
)
&&
(
min_ver
[
FW_VER_SUBTYPE
]
!=
fw_ver
[
FW_VER_SUBTYPE
])
)
goto
fail
;
if
(
min_ver
[
FW_VER_SUBTYPE
]
<
fw_ver
[
FW_VER_SUBTYPE
])
goto
out
;
else
if
(
min_ver
[
FW_VER_SUBTYPE
]
>
fw_ver
[
FW_VER_SUBTYPE
]
)
/* the API version must be greater or equal */
if
((
min_ver
[
FW_VER_MAJOR
]
!=
WLCORE_FW_VER_IGNORE
)
&&
(
min_ver
[
FW_VER_MAJOR
]
>
fw_ver
[
FW_VER_MAJOR
])
)
goto
fail
;
if
(
min_ver
[
FW_VER_MINOR
]
<
fw_ver
[
FW_VER_MINOR
])
goto
out
;
else
if
(
min_ver
[
FW_VER_MINOR
]
>
fw_ver
[
FW_VER_MINOR
])
/* if the API version is equal... */
if
(((
min_ver
[
FW_VER_MAJOR
]
==
WLCORE_FW_VER_IGNORE
)
||
(
min_ver
[
FW_VER_MAJOR
]
==
fw_ver
[
FW_VER_MAJOR
]))
&&
/* ...the minor must be greater or equal */
((
min_ver
[
FW_VER_MINOR
]
!=
WLCORE_FW_VER_IGNORE
)
&&
(
min_ver
[
FW_VER_MINOR
]
>
fw_ver
[
FW_VER_MINOR
])))
goto
fail
;
out:
return
0
;
fail:
wl1271_error
(
"Your WiFi FW version (%u.%u.%u.%u.%u) is outdated.
\n
"
"Please use at least FW %u.%u.%u.%u.%u.
\n
"
"You can get more information at:
\n
"
"http://wireless.kernel.org/en/users/Drivers/wl12xx"
,
for
(
i
=
0
;
i
<
NUM_FW_VER
;
i
++
)
if
(
min_ver
[
i
]
==
WLCORE_FW_VER_IGNORE
)
snprintf
(
min_fw_str
,
sizeof
(
min_fw_str
),
"%s*."
,
min_fw_str
);
else
snprintf
(
min_fw_str
,
sizeof
(
min_fw_str
),
"%s%u."
,
min_fw_str
,
min_ver
[
i
]);
wl1271_error
(
"Your WiFi FW version (%u.%u.%u.%u.%u) is invalid.
\n
"
"Please use at least FW %s
\n
"
"You can get the latest firmwares at:
\n
"
"git://github.com/TI-OpenLink/firmwares.git"
,
fw_ver
[
FW_VER_CHIP
],
fw_ver
[
FW_VER_IF_TYPE
],
fw_ver
[
FW_VER_MAJOR
],
fw_ver
[
FW_VER_SUBTYPE
],
fw_ver
[
FW_VER_MINOR
],
min_ver
[
FW_VER_CHIP
],
min_ver
[
FW_VER_IF_TYPE
],
min_ver
[
FW_VER_MAJOR
],
min_ver
[
FW_VER_SUBTYPE
],
min_ver
[
FW_VER_MINOR
]);
fw_ver
[
FW_VER_MINOR
],
min_fw_str
);
return
-
EINVAL
;
}
...
...
@@ -491,7 +501,7 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
if
(
ret
<
0
)
return
ret
;
wl
->
mbox_ptr
[
1
]
=
wl
->
mbox_ptr
[
0
]
+
sizeof
(
struct
event_mailbox
)
;
wl
->
mbox_ptr
[
1
]
=
wl
->
mbox_ptr
[
0
]
+
wl
->
mbox_size
;
wl1271_debug
(
DEBUG_MAILBOX
,
"MBOX ptrs: 0x%x 0x%x"
,
wl
->
mbox_ptr
[
0
],
wl
->
mbox_ptr
[
1
]);
...
...
@@ -508,23 +518,6 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
*/
/* unmask required mbox events */
wl
->
event_mask
=
BSS_LOSE_EVENT_ID
|
REGAINED_BSS_EVENT_ID
|
SCAN_COMPLETE_EVENT_ID
|
ROLE_STOP_COMPLETE_EVENT_ID
|
RSSI_SNR_TRIGGER_0_EVENT_ID
|
PSPOLL_DELIVERY_FAILURE_EVENT_ID
|
SOFT_GEMINI_SENSE_EVENT_ID
|
PERIODIC_SCAN_REPORT_EVENT_ID
|
PERIODIC_SCAN_COMPLETE_EVENT_ID
|
DUMMY_PACKET_EVENT_ID
|
PEER_REMOVE_COMPLETE_EVENT_ID
|
BA_SESSION_RX_CONSTRAINT_EVENT_ID
|
REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID
|
INACTIVE_STA_EVENT_ID
|
MAX_TX_RETRY_EVENT_ID
|
CHANNEL_SWITCH_COMPLETE_EVENT_ID
;
ret
=
wl1271_event_unmask
(
wl
);
if
(
ret
<
0
)
{
wl1271_error
(
"EVENT mask setting failed"
);
...
...
drivers/net/wireless/ti/wlcore/cmd.c
浏览文件 @
aaabee8b
...
...
@@ -131,13 +131,14 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
wl12xx_queue_recovery_work
(
wl
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
wl1271_cmd_send
);
/*
* Poll the mailbox event field until any of the bits in the mask is set or a
* timeout occurs (WL1271_EVENT_TIMEOUT in msecs)
*/
static
int
wl1271
_cmd_wait_for_event_or_timeout
(
struct
wl1271
*
wl
,
u32
mask
,
bool
*
timeout
)
int
wlcore
_cmd_wait_for_event_or_timeout
(
struct
wl1271
*
wl
,
u32
mask
,
bool
*
timeout
)
{
u32
*
events_vector
;
u32
event
;
...
...
@@ -187,20 +188,7 @@ static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl,
kfree
(
events_vector
);
return
ret
;
}
static
int
wl1271_cmd_wait_for_event
(
struct
wl1271
*
wl
,
u32
mask
)
{
int
ret
;
bool
timeout
=
false
;
ret
=
wl1271_cmd_wait_for_event_or_timeout
(
wl
,
mask
,
&
timeout
);
if
(
ret
!=
0
||
timeout
)
{
wl12xx_queue_recovery_work
(
wl
);
return
ret
;
}
return
0
;
}
EXPORT_SYMBOL_GPL
(
wlcore_cmd_wait_for_event_or_timeout
);
int
wl12xx_cmd_role_enable
(
struct
wl1271
*
wl
,
u8
*
addr
,
u8
role_type
,
u8
*
role_id
)
...
...
@@ -278,6 +266,16 @@ int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id)
return
ret
;
}
static
int
wlcore_get_new_session_id
(
struct
wl1271
*
wl
,
u8
hlid
)
{
if
(
wl
->
session_ids
[
hlid
]
>=
SESSION_COUNTER_MAX
)
wl
->
session_ids
[
hlid
]
=
0
;
wl
->
session_ids
[
hlid
]
++
;
return
wl
->
session_ids
[
hlid
];
}
int
wl12xx_allocate_link
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
*
hlid
)
{
unsigned
long
flags
;
...
...
@@ -285,6 +283,8 @@ int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
if
(
link
>=
WL12XX_MAX_LINKS
)
return
-
EBUSY
;
wl
->
session_ids
[
link
]
=
wlcore_get_new_session_id
(
wl
,
link
);
/* these bits are used by op_tx */
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
__set_bit
(
link
,
wl
->
links_map
);
...
...
@@ -316,17 +316,6 @@ void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
*
hlid
=
WL12XX_INVALID_LINK_ID
;
}
static
int
wl12xx_get_new_session_id
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
if
(
wlvif
->
session_counter
>=
SESSION_COUNTER_MAX
)
wlvif
->
session_counter
=
0
;
wlvif
->
session_counter
++
;
return
wlvif
->
session_counter
;
}
static
u8
wlcore_get_native_channel_type
(
u8
nl_channel_type
)
{
switch
(
nl_channel_type
)
{
...
...
@@ -345,7 +334,9 @@ static u8 wlcore_get_native_channel_type(u8 nl_channel_type)
}
static
int
wl12xx_cmd_role_start_dev
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
struct
wl12xx_vif
*
wlvif
,
enum
ieee80211_band
band
,
int
channel
)
{
struct
wl12xx_cmd_role_start
*
cmd
;
int
ret
;
...
...
@@ -359,9 +350,9 @@ static int wl12xx_cmd_role_start_dev(struct wl1271 *wl,
wl1271_debug
(
DEBUG_CMD
,
"cmd role start dev %d"
,
wlvif
->
dev_role_id
);
cmd
->
role_id
=
wlvif
->
dev_role_id
;
if
(
wlvif
->
band
==
IEEE80211_BAND_5GHZ
)
if
(
band
==
IEEE80211_BAND_5GHZ
)
cmd
->
band
=
WLCORE_BAND_5GHZ
;
cmd
->
channel
=
wlvif
->
channel
;
cmd
->
channel
=
channel
;
if
(
wlvif
->
dev_hlid
==
WL12XX_INVALID_LINK_ID
)
{
ret
=
wl12xx_allocate_link
(
wl
,
wlvif
,
&
wlvif
->
dev_hlid
);
...
...
@@ -369,7 +360,7 @@ static int wl12xx_cmd_role_start_dev(struct wl1271 *wl,
goto
out_free
;
}
cmd
->
device
.
hlid
=
wlvif
->
dev_hlid
;
cmd
->
device
.
session
=
wl
12xx_get_new_session_id
(
wl
,
wlvif
)
;
cmd
->
device
.
session
=
wl
->
session_ids
[
wlvif
->
dev_hlid
]
;
wl1271_debug
(
DEBUG_CMD
,
"role start: roleid=%d, hlid=%d, session=%d"
,
cmd
->
role_id
,
cmd
->
device
.
hlid
,
cmd
->
device
.
session
);
...
...
@@ -420,12 +411,6 @@ static int wl12xx_cmd_role_stop_dev(struct wl1271 *wl,
goto
out_free
;
}
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
;
}
wl12xx_free_link
(
wl
,
wlvif
,
&
wlvif
->
dev_hlid
);
out_free:
...
...
@@ -439,6 +424,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
struct
ieee80211_vif
*
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
struct
wl12xx_cmd_role_start
*
cmd
;
u32
supported_rates
;
int
ret
;
cmd
=
kzalloc
(
sizeof
(
*
cmd
),
GFP_KERNEL
);
...
...
@@ -459,7 +445,14 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif)
cmd
->
sta
.
ssid_len
=
wlvif
->
ssid_len
;
memcpy
(
cmd
->
sta
.
ssid
,
wlvif
->
ssid
,
wlvif
->
ssid_len
);
memcpy
(
cmd
->
sta
.
bssid
,
vif
->
bss_conf
.
bssid
,
ETH_ALEN
);
cmd
->
sta
.
local_rates
=
cpu_to_le32
(
wlvif
->
rate_set
);
supported_rates
=
CONF_TX_ENABLED_RATES
|
CONF_TX_MCS_RATES
|
wlcore_hw_sta_get_ap_rate_mask
(
wl
,
wlvif
);
if
(
wlvif
->
p2p
)
supported_rates
&=
~
CONF_TX_CCK_RATES
;
cmd
->
sta
.
local_rates
=
cpu_to_le32
(
supported_rates
);
cmd
->
channel_type
=
wlcore_get_native_channel_type
(
wlvif
->
channel_type
);
if
(
wlvif
->
sta
.
hlid
==
WL12XX_INVALID_LINK_ID
)
{
...
...
@@ -468,8 +461,13 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif)
goto
out_free
;
}
cmd
->
sta
.
hlid
=
wlvif
->
sta
.
hlid
;
cmd
->
sta
.
session
=
wl12xx_get_new_session_id
(
wl
,
wlvif
);
cmd
->
sta
.
remote_rates
=
cpu_to_le32
(
wlvif
->
rate_set
);
cmd
->
sta
.
session
=
wl
->
session_ids
[
wlvif
->
sta
.
hlid
];
/*
* We don't have the correct remote rates in this stage, and there
* is no way to update them later, so use our supported rates instead.
* The fw will take the configured rate policies into account anyway.
*/
cmd
->
sta
.
remote_rates
=
cpu_to_le32
(
supported_rates
);
wl1271_debug
(
DEBUG_CMD
,
"role start: roleid=%d, hlid=%d, session=%d "
"basic_rate_set: 0x%x, remote_rates: 0x%x"
,
...
...
@@ -482,6 +480,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif)
goto
err_hlid
;
}
wlvif
->
sta
.
role_chan_type
=
wlvif
->
channel_type
;
goto
out_free
;
err_hlid:
...
...
@@ -500,7 +499,6 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
struct
wl12xx_cmd_role_stop
*
cmd
;
int
ret
;
bool
timeout
=
false
;
if
(
WARN_ON
(
wlvif
->
sta
.
hlid
==
WL12XX_INVALID_LINK_ID
))
return
-
EINVAL
;
...
...
@@ -523,17 +521,6 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif)
goto
out_free
;
}
/*
* Sometimes the firmware doesn't send this event, so we just
* time out without failing. Queue recovery for other
* failures.
*/
ret
=
wl1271_cmd_wait_for_event_or_timeout
(
wl
,
ROLE_STOP_COMPLETE_EVENT_ID
,
&
timeout
);
if
(
ret
)
wl12xx_queue_recovery_work
(
wl
);
wl12xx_free_link
(
wl
,
wlvif
,
&
wlvif
->
sta
.
hlid
);
out_free:
...
...
@@ -579,12 +566,15 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif)
cmd
->
ap
.
bss_index
=
WL1271_AP_BSS_INDEX
;
cmd
->
ap
.
global_hlid
=
wlvif
->
ap
.
global_hlid
;
cmd
->
ap
.
broadcast_hlid
=
wlvif
->
ap
.
bcast_hlid
;
cmd
->
ap
.
global_session_id
=
wl
->
session_ids
[
wlvif
->
ap
.
global_hlid
];
cmd
->
ap
.
bcast_session_id
=
wl
->
session_ids
[
wlvif
->
ap
.
bcast_hlid
];
cmd
->
ap
.
basic_rate_set
=
cpu_to_le32
(
wlvif
->
basic_rate_set
);
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
->
ap
.
wmm
=
wlvif
->
wmm_enabled
;
cmd
->
channel
=
wlvif
->
channel
;
cmd
->
channel_type
=
wlcore_get_native_channel_type
(
wlvif
->
channel_type
);
...
...
@@ -599,8 +589,10 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif)
memcpy
(
cmd
->
ap
.
ssid
,
bss_conf
->
ssid
,
bss_conf
->
ssid_len
);
}
supported_rates
=
CONF_TX_
AP_
ENABLED_RATES
|
CONF_TX_MCS_RATES
|
supported_rates
=
CONF_TX_ENABLED_RATES
|
CONF_TX_MCS_RATES
|
wlcore_hw_ap_get_mimo_wide_rate_mask
(
wl
,
wlvif
);
if
(
wlvif
->
p2p
)
supported_rates
&=
~
CONF_TX_CCK_RATES
;
wl1271_debug
(
DEBUG_CMD
,
"cmd role start ap with supported_rates 0x%08x"
,
supported_rates
);
...
...
@@ -1034,8 +1026,8 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct
sk_buff
*
skb
;
int
ret
;
u32
rate
;
u16
template_id_2_4
=
CMD_TEMPL_CFG_PROBE_REQ
_2_4
;
u16
template_id_5
=
CMD_TEMPL_CFG_PROBE_REQ
_5
;
u16
template_id_2_4
=
wl
->
scan_templ_id
_2_4
;
u16
template_id_5
=
wl
->
scan_templ_id
_5
;
skb
=
ieee80211_probereq_get
(
wl
->
hw
,
vif
,
ssid
,
ssid_len
,
ie
,
ie_len
);
...
...
@@ -1046,10 +1038,10 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
wl1271_dump
(
DEBUG_SCAN
,
"PROBE REQ: "
,
skb
->
data
,
skb
->
len
);
if
(
!
sched_scan
&&
if
(
sched_scan
&&
(
wl
->
quirks
&
WLCORE_QUIRK_DUAL_PROBE_TMPL
))
{
template_id_2_4
=
CMD_TEMPL_APP_PROBE_REQ
_2_4
;
template_id_5
=
CMD_TEMPL_APP_PROBE_REQ
_5
;
template_id_2_4
=
wl
->
sched_scan_templ_id
_2_4
;
template_id_5
=
wl
->
sched_scan_templ_id
_5
;
}
rate
=
wl1271_tx_min_rate_get
(
wl
,
wlvif
->
bitrate_masks
[
band
]);
...
...
@@ -1066,6 +1058,7 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
dev_kfree_skb
(
skb
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
wl12xx_cmd_build_probe_req
);
struct
sk_buff
*
wl1271_cmd_build_ap_probe_req
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
...
...
@@ -1377,7 +1370,8 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif,
return
ret
;
}
int
wl12xx_cmd_set_peer_state
(
struct
wl1271
*
wl
,
u8
hlid
)
int
wl12xx_cmd_set_peer_state
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
hlid
)
{
struct
wl12xx_cmd_set_peer_state
*
cmd
;
int
ret
=
0
;
...
...
@@ -1393,6 +1387,10 @@ int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid)
cmd
->
hlid
=
hlid
;
cmd
->
state
=
WL1271_CMD_STA_STATE_CONNECTED
;
/* wmm param is valid only for station role */
if
(
wlvif
->
bss_type
==
BSS_TYPE_STA_BSS
)
cmd
->
wmm
=
wlvif
->
wmm_enabled
;
ret
=
wl1271_cmd_send
(
wl
,
CMD_SET_PEER_STATE
,
cmd
,
sizeof
(
*
cmd
),
0
);
if
(
ret
<
0
)
{
wl1271_error
(
"failed to send set peer state command"
);
...
...
@@ -1427,6 +1425,7 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif,
cmd
->
hlid
=
hlid
;
cmd
->
sp_len
=
sta
->
max_sp
;
cmd
->
wmm
=
sta
->
wme
?
1
:
0
;
cmd
->
session_id
=
wl
->
session_ids
[
hlid
];
for
(
i
=
0
;
i
<
NUM_ACCESS_CATEGORIES_COPY
;
i
++
)
if
(
sta
->
wme
&&
(
sta
->
uapsd_queues
&
BIT
(
i
)))
...
...
@@ -1488,9 +1487,10 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid)
goto
out_free
;
}
ret
=
wl1271_cmd_wait_for_event_or_timeout
(
wl
,
PEER_REMOVE_COMPLETE_EVENT_ID
,
&
timeout
);
ret
=
wl
->
ops
->
wait_for_event
(
wl
,
WLCORE_EVENT_PEER_REMOVE_COMPLETE
,
&
timeout
);
/*
* We are ok with a timeout here. The event is sometimes not sent
* due to a firmware bug. In case of another error (like SDIO timeout)
...
...
@@ -1506,6 +1506,131 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid)
return
ret
;
}
static
int
wlcore_get_reg_conf_ch_idx
(
enum
ieee80211_band
band
,
u16
ch
)
{
int
idx
=
-
1
;
switch
(
band
)
{
case
IEEE80211_BAND_5GHZ
:
if
(
ch
>=
8
&&
ch
<=
16
)
idx
=
((
ch
-
8
)
/
4
+
18
);
else
if
(
ch
>=
34
&&
ch
<=
64
)
idx
=
((
ch
-
34
)
/
2
+
3
+
18
);
else
if
(
ch
>=
100
&&
ch
<=
140
)
idx
=
((
ch
-
100
)
/
4
+
15
+
18
);
else
if
(
ch
>=
149
&&
ch
<=
165
)
idx
=
((
ch
-
149
)
/
4
+
26
+
18
);
else
idx
=
-
1
;
break
;
case
IEEE80211_BAND_2GHZ
:
if
(
ch
>=
1
&&
ch
<=
14
)
idx
=
ch
-
1
;
else
idx
=
-
1
;
break
;
default:
wl1271_error
(
"get reg conf ch idx - unknown band: %d"
,
(
int
)
band
);
}
return
idx
;
}
void
wlcore_set_pending_regdomain_ch
(
struct
wl1271
*
wl
,
u16
channel
,
enum
ieee80211_band
band
)
{
int
ch_bit_idx
=
0
;
if
(
!
(
wl
->
quirks
&
WLCORE_QUIRK_REGDOMAIN_CONF
))
return
;
ch_bit_idx
=
wlcore_get_reg_conf_ch_idx
(
band
,
channel
);
if
(
ch_bit_idx
>
0
&&
ch_bit_idx
<=
WL1271_MAX_CHANNELS
)
set_bit
(
ch_bit_idx
,
(
long
*
)
wl
->
reg_ch_conf_pending
);
}
int
wlcore_cmd_regdomain_config_locked
(
struct
wl1271
*
wl
)
{
struct
wl12xx_cmd_regdomain_dfs_config
*
cmd
=
NULL
;
int
ret
=
0
,
i
,
b
,
ch_bit_idx
;
struct
ieee80211_channel
*
channel
;
u32
tmp_ch_bitmap
[
2
];
u16
ch
;
struct
wiphy
*
wiphy
=
wl
->
hw
->
wiphy
;
struct
ieee80211_supported_band
*
band
;
bool
timeout
=
false
;
if
(
!
(
wl
->
quirks
&
WLCORE_QUIRK_REGDOMAIN_CONF
))
return
0
;
wl1271_debug
(
DEBUG_CMD
,
"cmd reg domain config"
);
memset
(
tmp_ch_bitmap
,
0
,
sizeof
(
tmp_ch_bitmap
));
for
(
b
=
IEEE80211_BAND_2GHZ
;
b
<=
IEEE80211_BAND_5GHZ
;
b
++
)
{
band
=
wiphy
->
bands
[
b
];
for
(
i
=
0
;
i
<
band
->
n_channels
;
i
++
)
{
channel
=
&
band
->
channels
[
i
];
ch
=
channel
->
hw_value
;
if
(
channel
->
flags
&
(
IEEE80211_CHAN_DISABLED
|
IEEE80211_CHAN_RADAR
|
IEEE80211_CHAN_PASSIVE_SCAN
))
continue
;
ch_bit_idx
=
wlcore_get_reg_conf_ch_idx
(
b
,
ch
);
if
(
ch_bit_idx
<
0
)
continue
;
set_bit
(
ch_bit_idx
,
(
long
*
)
tmp_ch_bitmap
);
}
}
tmp_ch_bitmap
[
0
]
|=
wl
->
reg_ch_conf_pending
[
0
];
tmp_ch_bitmap
[
1
]
|=
wl
->
reg_ch_conf_pending
[
1
];
if
(
!
memcmp
(
tmp_ch_bitmap
,
wl
->
reg_ch_conf_last
,
sizeof
(
tmp_ch_bitmap
)))
goto
out
;
cmd
=
kzalloc
(
sizeof
(
*
cmd
),
GFP_KERNEL
);
if
(
!
cmd
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
cmd
->
ch_bit_map1
=
cpu_to_le32
(
tmp_ch_bitmap
[
0
]);
cmd
->
ch_bit_map2
=
cpu_to_le32
(
tmp_ch_bitmap
[
1
]);
wl1271_debug
(
DEBUG_CMD
,
"cmd reg domain bitmap1: 0x%08x, bitmap2: 0x%08x"
,
cmd
->
ch_bit_map1
,
cmd
->
ch_bit_map2
);
ret
=
wl1271_cmd_send
(
wl
,
CMD_DFS_CHANNEL_CONFIG
,
cmd
,
sizeof
(
*
cmd
),
0
);
if
(
ret
<
0
)
{
wl1271_error
(
"failed to send reg domain dfs config"
);
goto
out
;
}
ret
=
wl
->
ops
->
wait_for_event
(
wl
,
WLCORE_EVENT_DFS_CONFIG_COMPLETE
,
&
timeout
);
if
(
ret
<
0
||
timeout
)
{
wl1271_error
(
"reg domain conf %serror"
,
timeout
?
"completion "
:
""
);
ret
=
timeout
?
-
ETIMEDOUT
:
ret
;
goto
out
;
}
memcpy
(
wl
->
reg_ch_conf_last
,
tmp_ch_bitmap
,
sizeof
(
tmp_ch_bitmap
));
memset
(
wl
->
reg_ch_conf_pending
,
0
,
sizeof
(
wl
->
reg_ch_conf_pending
));
out:
kfree
(
cmd
);
return
ret
;
}
int
wl12xx_cmd_config_fwlog
(
struct
wl1271
*
wl
)
{
struct
wl12xx_cmd_config_fwlog
*
cmd
;
...
...
@@ -1591,12 +1716,12 @@ int wl12xx_cmd_stop_fwlog(struct wl1271 *wl)
}
static
int
wl12xx_cmd_roc
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
role_id
)
u8
role_id
,
enum
ieee80211_band
band
,
u8
channel
)
{
struct
wl12xx_cmd_roc
*
cmd
;
int
ret
=
0
;
wl1271_debug
(
DEBUG_CMD
,
"cmd roc %d (%d)"
,
wlvif
->
channel
,
role_id
);
wl1271_debug
(
DEBUG_CMD
,
"cmd roc %d (%d)"
,
channel
,
role_id
);
if
(
WARN_ON
(
role_id
==
WL12XX_INVALID_ROLE_ID
))
return
-
EINVAL
;
...
...
@@ -1608,8 +1733,8 @@ static int wl12xx_cmd_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif,
}
cmd
->
role_id
=
role_id
;
cmd
->
channel
=
wlvif
->
channel
;
switch
(
wlvif
->
band
)
{
cmd
->
channel
=
channel
;
switch
(
band
)
{
case
IEEE80211_BAND_2GHZ
:
cmd
->
band
=
WLCORE_BAND_2_4GHZ
;
break
;
...
...
@@ -1664,30 +1789,18 @@ static int wl12xx_cmd_croc(struct wl1271 *wl, u8 role_id)
return
ret
;
}
int
wl12xx_roc
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
role_id
)
int
wl12xx_roc
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
role_id
,
enum
ieee80211_band
band
,
u8
channel
)
{
int
ret
=
0
;
bool
is_first_roc
;
if
(
WARN_ON
(
test_bit
(
role_id
,
wl
->
roc_map
)))
return
0
;
is_first_roc
=
(
find_first_bit
(
wl
->
roc_map
,
WL12XX_MAX_ROLES
)
>=
WL12XX_MAX_ROLES
);
ret
=
wl12xx_cmd_roc
(
wl
,
wlvif
,
role_id
);
ret
=
wl12xx_cmd_roc
(
wl
,
wlvif
,
role_id
,
band
,
channel
);
if
(
ret
<
0
)
goto
out
;
if
(
is_first_roc
)
{
ret
=
wl1271_cmd_wait_for_event
(
wl
,
REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID
);
if
(
ret
<
0
)
{
wl1271_error
(
"cmd roc event completion error"
);
goto
out
;
}
}
__set_bit
(
role_id
,
wl
->
roc_map
);
out:
return
ret
;
...
...
@@ -1717,43 +1830,7 @@ int wl12xx_croc(struct wl1271 *wl, u8 role_id)
return
ret
;
}
int
wl12xx_cmd_channel_switch
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
ieee80211_channel_switch
*
ch_switch
)
{
struct
wl12xx_cmd_channel_switch
*
cmd
;
int
ret
;
wl1271_debug
(
DEBUG_ACX
,
"cmd channel switch"
);
cmd
=
kzalloc
(
sizeof
(
*
cmd
),
GFP_KERNEL
);
if
(
!
cmd
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
cmd
->
role_id
=
wlvif
->
role_id
;
cmd
->
channel
=
ch_switch
->
channel
->
hw_value
;
cmd
->
switch_time
=
ch_switch
->
count
;
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
)
{
wl1271_error
(
"failed to send channel switch command"
);
goto
out_free
;
}
out_free:
kfree
(
cmd
);
out:
return
ret
;
}
int
wl12xx_cmd_stop_channel_switch
(
struct
wl1271
*
wl
)
int
wl12xx_cmd_stop_channel_switch
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
struct
wl12xx_cmd_stop_channel_switch
*
cmd
;
int
ret
;
...
...
@@ -1766,6 +1843,8 @@ int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl)
goto
out
;
}
cmd
->
role_id
=
wlvif
->
role_id
;
ret
=
wl1271_cmd_send
(
wl
,
CMD_STOP_CHANNEL_SWICTH
,
cmd
,
sizeof
(
*
cmd
),
0
);
if
(
ret
<
0
)
{
wl1271_error
(
"failed to stop channel switch command"
);
...
...
@@ -1780,7 +1859,8 @@ int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl)
}
/* start dev role and roc on its channel */
int
wl12xx_start_dev
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
int
wl12xx_start_dev
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
enum
ieee80211_band
band
,
int
channel
)
{
int
ret
;
...
...
@@ -1795,11 +1875,11 @@ int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif)
if
(
ret
<
0
)
goto
out
;
ret
=
wl12xx_cmd_role_start_dev
(
wl
,
wlvif
);
ret
=
wl12xx_cmd_role_start_dev
(
wl
,
wlvif
,
band
,
channel
);
if
(
ret
<
0
)
goto
out_disable
;
ret
=
wl12xx_roc
(
wl
,
wlvif
,
wlvif
->
dev_role_id
);
ret
=
wl12xx_roc
(
wl
,
wlvif
,
wlvif
->
dev_role_id
,
band
,
channel
);
if
(
ret
<
0
)
goto
out_stop
;
...
...
drivers/net/wireless/ti/wlcore/cmd.h
浏览文件 @
aaabee8b
...
...
@@ -39,7 +39,8 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int
wl12xx_cmd_role_start_ap
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl12xx_cmd_role_stop_ap
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl12xx_cmd_role_start_ibss
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl12xx_start_dev
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl12xx_start_dev
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
enum
ieee80211_band
band
,
int
channel
);
int
wl12xx_stop_dev
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl1271_cmd_test
(
struct
wl1271
*
wl
,
void
*
buf
,
size_t
buf_len
,
u8
answer
);
int
wl1271_cmd_interrogate
(
struct
wl1271
*
wl
,
u16
id
,
void
*
buf
,
size_t
len
);
...
...
@@ -75,22 +76,30 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u16
action
,
u8
id
,
u8
key_type
,
u8
key_size
,
const
u8
*
key
,
u8
hlid
,
u32
tx_seq_32
,
u16
tx_seq_16
);
int
wl12xx_cmd_set_peer_state
(
struct
wl1271
*
wl
,
u8
hlid
);
int
wl12xx_roc
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
role_id
);
int
wl12xx_cmd_set_peer_state
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
hlid
);
int
wl12xx_roc
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
role_id
,
enum
ieee80211_band
band
,
u8
channel
);
int
wl12xx_croc
(
struct
wl1271
*
wl
,
u8
role_id
);
int
wl12xx_cmd_add_peer
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
ieee80211_sta
*
sta
,
u8
hlid
);
int
wl12xx_cmd_remove_peer
(
struct
wl1271
*
wl
,
u8
hlid
);
void
wlcore_set_pending_regdomain_ch
(
struct
wl1271
*
wl
,
u16
channel
,
enum
ieee80211_band
band
);
int
wlcore_cmd_regdomain_config_locked
(
struct
wl1271
*
wl
);
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_cmd_stop_channel_switch
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl12xx_allocate_link
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
*
hlid
);
void
wl12xx_free_link
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
*
hlid
);
int
wlcore_cmd_wait_for_event_or_timeout
(
struct
wl1271
*
wl
,
u32
mask
,
bool
*
timeout
);
enum
wl1271_commands
{
CMD_INTERROGATE
=
1
,
/* use this to read information elements */
...
...
@@ -149,8 +158,11 @@ enum wl1271_commands {
CMD_WFD_START_DISCOVERY
=
45
,
CMD_WFD_STOP_DISCOVERY
=
46
,
CMD_WFD_ATTRIBUTE_CONFIG
=
47
,
CMD_NOP
=
48
,
CMD_LAST_COMMAND
,
CMD_GENERIC_CFG
=
48
,
CMD_NOP
=
49
,
/* start of 18xx specific commands */
CMD_DFS_CHANNEL_CONFIG
=
60
,
MAX_COMMAND_ID
=
0xFFFF
,
};
...
...
@@ -167,8 +179,8 @@ enum cmd_templ {
CMD_TEMPL_PS_POLL
,
CMD_TEMPL_KLV
,
CMD_TEMPL_DISCONNECT
,
CMD_TEMPL_APP_PROBE_REQ_2_4
,
CMD_TEMPL_APP_PROBE_REQ_5
,
CMD_TEMPL_APP_PROBE_REQ_2_4
_LEGACY
,
CMD_TEMPL_APP_PROBE_REQ_5
_LEGACY
,
CMD_TEMPL_BAR
,
/* for firmware internal use only */
CMD_TEMPL_CTS
,
/*
* For CTS-to-self (FastCTS) mechanism
...
...
@@ -179,6 +191,8 @@ enum cmd_templ {
CMD_TEMPL_DEAUTH_AP
,
CMD_TEMPL_TEMPORARY
,
CMD_TEMPL_LINK_MEASUREMENT_REPORT
,
CMD_TEMPL_PROBE_REQ_2_4_PERIODIC
,
CMD_TEMPL_PROBE_REQ_5_PERIODIC
,
CMD_TEMPL_MAX
=
0xff
};
...
...
@@ -345,7 +359,15 @@ struct wl12xx_cmd_role_start {
u8
reset_tsf
;
u8
padding_1
[
4
];
/*
* ap supports wmm (note that there is additional
* per-sta wmm configuration)
*/
u8
wmm
;
u8
bcast_session_id
;
u8
global_session_id
;
u8
padding_1
[
1
];
}
__packed
ap
;
};
}
__packed
;
...
...
@@ -515,7 +537,14 @@ struct wl12xx_cmd_set_peer_state {
u8
hlid
;
u8
state
;
u8
padding
[
2
];
/*
* wmm is relevant for sta role only.
* ap role configures the per-sta wmm params in
* the add_peer command.
*/
u8
wmm
;
u8
padding
[
1
];
}
__packed
;
struct
wl12xx_cmd_roc
{
...
...
@@ -558,7 +587,7 @@ struct wl12xx_cmd_add_peer {
u8
bss_index
;
u8
sp_len
;
u8
wmm
;
u8
padding1
;
u8
session_id
;
}
__packed
;
struct
wl12xx_cmd_remove_peer
{
...
...
@@ -597,6 +626,13 @@ enum wl12xx_fwlogger_output {
WL12XX_FWLOG_OUTPUT_HOST
,
};
struct
wl12xx_cmd_regdomain_dfs_config
{
struct
wl1271_cmd_header
header
;
__le32
ch_bit_map1
;
__le32
ch_bit_map2
;
}
__packed
;
struct
wl12xx_cmd_config_fwlog
{
struct
wl1271_cmd_header
header
;
...
...
@@ -626,27 +662,13 @@ struct wl12xx_cmd_stop_fwlog {
struct
wl1271_cmd_header
header
;
}
__packed
;
struct
wl12xx_cmd_channel_switch
{
struct
wl12xx_cmd_
stop_
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
;
/* 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
{
struct
wl1271_cmd_header
header
;
}
__packed
;
/* Used to check radio status after calibration */
#define MAX_TLV_LENGTH 500
#define TEST_CMD_P2G_CAL 2
/* TX BiP */
...
...
drivers/net/wireless/ti/wlcore/conf.h
浏览文件 @
aaabee8b
...
...
@@ -415,11 +415,11 @@ struct conf_rx_settings {
#define CONF_TX_RATE_MASK_BASIC_P2P CONF_HW_BIT_RATE_6MBPS
/*
* Rates supported for data packets when operating as AP. Note the absence
* Rates supported for data packets when operating as
STA/
AP. Note the absence
* of the 22Mbps rate. There is a FW limitation on 12 rates so we must drop
* one. The rate dropped is not mandatory under any operating mode.
*/
#define CONF_TX_
AP_ENABLED_RATES (CONF_HW_BIT_RATE_1MBPS |
\
#define CONF_TX_
ENABLED_RATES (CONF_HW_BIT_RATE_1MBPS |
\
CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | \
CONF_HW_BIT_RATE_6MBPS | CONF_HW_BIT_RATE_9MBPS | \
CONF_HW_BIT_RATE_11MBPS | CONF_HW_BIT_RATE_12MBPS | \
...
...
@@ -1059,19 +1059,11 @@ struct conf_scan_settings {
*/
u32
max_dwell_time_active
;
/*
* The minimum time to wait on each channel for passive scans
*
* Range: u32 tu/1000
*/
u32
min_dwell_time_passive
;
/* time to wait on the channel for passive scans (in TU/1000) */
u32
dwell_time_passive
;
/*
* The maximum time to wait on each channel for passive scans
*
* Range: u32 tu/1000
*/
u32
max_dwell_time_passive
;
/* time to wait on the channel for DFS scans (in TU/1000) */
u32
dwell_time_dfs
;
/*
* Number of probe requests to transmit on each active scan channel
...
...
@@ -1276,12 +1268,20 @@ struct conf_hangover_settings {
u8
window_size
;
}
__packed
;
struct
conf_recovery_settings
{
/* BUG() on fw recovery */
u8
bug_on_recovery
;
/* Prevent HW recovery. FW will remain stuck. */
u8
no_recovery
;
}
__packed
;
/*
* The conf version consists of 4 bytes. The two MSB are the wlcore
* version, the two LSB are the lower driver's private conf
* version.
*/
#define WLCORE_CONF_VERSION (0x000
2
<< 16)
#define WLCORE_CONF_VERSION (0x000
4
<< 16)
#define WLCORE_CONF_MASK 0xffff0000
#define WLCORE_CONF_SIZE (sizeof(struct wlcore_conf_header) + \
sizeof(struct wlcore_conf))
...
...
@@ -1309,6 +1309,7 @@ struct wlcore_conf {
struct
conf_fwlog
fwlog
;
struct
conf_rate_policy_settings
rate
;
struct
conf_hangover_settings
hangover
;
struct
conf_recovery_settings
recovery
;
}
__packed
;
struct
wlcore_conf_file
{
...
...
drivers/net/wireless/ti/wlcore/debugfs.c
浏览文件 @
aaabee8b
...
...
@@ -490,7 +490,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
DRIVER_STATE_PRINT_HEX
(
chip
.
id
);
DRIVER_STATE_PRINT_STR
(
chip
.
fw_ver_str
);
DRIVER_STATE_PRINT_STR
(
chip
.
phy_fw_ver_str
);
DRIVER_STATE_PRINT_INT
(
sched_scanning
);
DRIVER_STATE_PRINT_INT
(
recovery_count
);
#undef DRIVER_STATE_PRINT_INT
#undef DRIVER_STATE_PRINT_LONG
...
...
@@ -589,7 +589,6 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf,
VIF_STATE_PRINT_INT
(
beacon_int
);
VIF_STATE_PRINT_INT
(
default_key
);
VIF_STATE_PRINT_INT
(
aid
);
VIF_STATE_PRINT_INT
(
session_counter
);
VIF_STATE_PRINT_INT
(
psm_entry_retry
);
VIF_STATE_PRINT_INT
(
power_level
);
VIF_STATE_PRINT_INT
(
rssi_thold
);
...
...
@@ -993,7 +992,7 @@ static ssize_t sleep_auth_write(struct file *file,
return
-
EINVAL
;
}
if
(
value
<
0
||
value
>
WL1271_PSM_MAX
)
{
if
(
value
>
WL1271_PSM_MAX
)
{
wl1271_warning
(
"sleep_auth must be between 0 and %d"
,
WL1271_PSM_MAX
);
return
-
ERANGE
;
...
...
drivers/net/wireless/ti/wlcore/event.c
浏览文件 @
aaabee8b
...
...
@@ -29,25 +29,29 @@
#include "scan.h"
#include "wl12xx_80211.h"
static
void
wl1271_event_rssi_trigger
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
event_mailbox
*
mbox
)
void
wlcore_event_rssi_trigger
(
struct
wl1271
*
wl
,
s8
*
metric_arr
)
{
struct
ieee80211_vif
*
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
struct
wl12xx_vif
*
wlvif
;
struct
ieee80211_vif
*
vif
;
enum
nl80211_cqm_rssi_threshold_event
event
;
s8
metric
=
m
box
->
rssi_snr_trigger_metric
[
0
];
s8
metric
=
m
etric_arr
[
0
];
wl1271_debug
(
DEBUG_EVENT
,
"RSSI trigger metric: %d"
,
metric
);
if
(
metric
<=
wlvif
->
rssi_thold
)
event
=
NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW
;
else
event
=
NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH
;
if
(
event
!=
wlvif
->
last_rssi_event
)
ieee80211_cqm_rssi_notify
(
vif
,
event
,
GFP_KERNEL
);
wlvif
->
last_rssi_event
=
event
;
/* TODO: check actual multi-role support */
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
if
(
metric
<=
wlvif
->
rssi_thold
)
event
=
NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW
;
else
event
=
NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH
;
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
if
(
event
!=
wlvif
->
last_rssi_event
)
ieee80211_cqm_rssi_notify
(
vif
,
event
,
GFP_KERNEL
);
wlvif
->
last_rssi_event
=
event
;
}
}
EXPORT_SYMBOL_GPL
(
wlcore_event_rssi_trigger
);
static
void
wl1271_stop_ba_event
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
...
...
@@ -74,8 +78,7 @@ 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
)
void
wlcore_event_soft_gemini_sense
(
struct
wl1271
*
wl
,
u8
enable
)
{
struct
wl12xx_vif
*
wlvif
;
...
...
@@ -87,201 +90,179 @@ static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl,
wl1271_recalc_rx_streaming
(
wl
,
wlvif
);
}
}
}
EXPORT_SYMBOL_GPL
(
wlcore_event_soft_gemini_sense
);
static
void
wl1271_event_mbox_dump
(
struct
event_mailbox
*
mbox
)
void
wlcore_event_sched_scan_report
(
struct
wl1271
*
wl
,
u8
status
)
{
wl1271_debug
(
DEBUG_EVENT
,
"MBOX DUMP:"
);
wl1271_debug
(
DEBUG_EVENT
,
"
\t
vector: 0x%x"
,
mbox
->
events_vector
);
wl1271_debug
(
DEBUG_EVENT
,
"
\t
mask: 0x%x"
,
mbox
->
events_mask
);
wl1271_debug
(
DEBUG_EVENT
,
"PERIODIC_SCAN_REPORT_EVENT (status 0x%0x)"
,
status
);
wl1271_scan_sched_scan_results
(
wl
);
}
EXPORT_SYMBOL_GPL
(
wlcore_event_sched_scan_report
);
static
int
wl1271_event_process
(
struct
wl1271
*
wl
)
void
wlcore_event_sched_scan_completed
(
struct
wl1271
*
wl
,
u8
status
)
{
struct
event_mailbox
*
mbox
=
wl
->
mbox
;
struct
ieee80211_vif
*
vif
;
struct
wl12xx_vif
*
wlvif
;
u32
vector
;
bool
disconnect_sta
=
false
;
unsigned
long
sta_bitmap
=
0
;
int
ret
;
wl1271_debug
(
DEBUG_EVENT
,
"PERIODIC_SCAN_COMPLETE_EVENT (status 0x%0x)"
,
status
);
wl1271_event_mbox_dump
(
mbox
);
if
(
wl
->
sched_vif
)
{
ieee80211_sched_scan_stopped
(
wl
->
hw
);
wl
->
sched_vif
=
NULL
;
}
}
EXPORT_SYMBOL_GPL
(
wlcore_event_sched_scan_completed
);
vector
=
le32_to_cpu
(
mbox
->
events_vector
);
vector
&=
~
(
le32_to_cpu
(
mbox
->
events_mask
));
wl1271_debug
(
DEBUG_EVENT
,
"vector: 0x%x"
,
vector
);
void
wlcore_event_ba_rx_constraint
(
struct
wl1271
*
wl
,
unsigned
long
roles_bitmap
,
unsigned
long
allowed_bitmap
)
{
struct
wl12xx_vif
*
wlvif
;
if
(
vector
&
SCAN_COMPLETE_EVENT_ID
)
{
wl1271_debug
(
DEBUG_EVENT
,
"status: 0x%x"
,
mbox
->
scheduled_scan_status
);
wl1271_debug
(
DEBUG_EVENT
,
"%s: roles=0x%lx allowed=0x%lx"
,
__func__
,
roles_bitmap
,
allowed_bitmap
);
wl1271_scan_stm
(
wl
,
wl
->
scan_vif
);
}
wl12xx_for_each_wlvif
(
wl
,
wlvif
)
{
if
(
wlvif
->
role_id
==
WL12XX_INVALID_ROLE_ID
||
!
test_bit
(
wlvif
->
role_id
,
&
roles_bitmap
))
continue
;
if
(
vector
&
PERIODIC_SCAN_REPORT_EVENT_ID
)
{
wl1271_debug
(
DEBUG_EVENT
,
"PERIODIC_SCAN_REPORT_EVENT "
"(status 0x%0x)"
,
mbox
->
scheduled_scan_status
);
wl1271_scan_sched_scan_results
(
wl
);
wlvif
->
ba_allowed
=
!!
test_bit
(
wlvif
->
role_id
,
&
allowed_bitmap
);
if
(
!
wlvif
->
ba_allowed
)
wl1271_stop_ba_event
(
wl
,
wlvif
);
}
}
EXPORT_SYMBOL_GPL
(
wlcore_event_ba_rx_constraint
);
if
(
vector
&
PERIODIC_SCAN_COMPLETE_EVENT_ID
)
{
wl1271_debug
(
DEBUG_EVENT
,
"PERIODIC_SCAN_COMPLETE_EVENT "
"(status 0x%0x)"
,
mbox
->
scheduled_scan_status
);
if
(
wl
->
sched_scanning
)
{
ieee80211_sched_scan_stopped
(
wl
->
hw
);
wl
->
sched_scanning
=
false
;
}
}
void
wlcore_event_channel_switch
(
struct
wl1271
*
wl
,
unsigned
long
roles_bitmap
,
bool
success
)
{
struct
wl12xx_vif
*
wlvif
;
struct
ieee80211_vif
*
vif
;
if
(
vector
&
SOFT_GEMINI_SENSE_EVENT_ID
)
wl12xx_event_soft_gemini_sense
(
wl
,
mbox
->
soft_gemini_sense_info
);
wl1271_debug
(
DEBUG_EVENT
,
"%s: roles=0x%lx success=%d"
,
__func__
,
roles_bitmap
,
success
);
/*
* We are HW_MONITOR device. On beacon loss - queue
* connection loss work. Cancel it on REGAINED event.
*/
if
(
vector
&
BSS_LOSE_EVENT_ID
)
{
/* TODO: check for multi-role */
int
delay
=
wl
->
conf
.
conn
.
synch_fail_thold
*
wl
->
conf
.
conn
.
bss_lose_timeout
;
wl1271_info
(
"Beacon loss detected."
);
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
if
(
wlvif
->
role_id
==
WL12XX_INVALID_ROLE_ID
||
!
test_bit
(
wlvif
->
role_id
,
&
roles_bitmap
))
continue
;
/*
* if the work is already queued, it should take place. We
* don't want to delay the connection loss indication
* any more.
*/
ieee80211_queue_delayed_work
(
wl
->
hw
,
&
wl
->
connection_loss_work
,
msecs_to_jiffies
(
delay
));
if
(
!
test_and_clear_bit
(
WLVIF_FLAG_CS_PROGRESS
,
&
wlvif
->
flags
))
continue
;
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
ieee80211_cqm_rssi_notify
(
vif
,
NL80211_CQM_RSSI_BEACON_LOSS_EVENT
,
GFP_KERNEL
);
}
ieee80211_chswitch_done
(
vif
,
success
);
cancel_delayed_work
(
&
wlvif
->
channel_switch_work
);
}
}
EXPORT_SYMBOL_GPL
(
wlcore_event_channel_switch
);
if
(
vector
&
REGAINED_BSS_EVENT_ID
)
{
/* TODO: check for multi-role */
wl1271_info
(
"Beacon regained."
);
cancel_delayed_work
(
&
wl
->
connection_loss_work
);
/* sanity check - we can't lose and gain the beacon together */
WARN
(
vector
&
BSS_LOSE_EVENT_ID
,
"Concurrent beacon loss and gain from FW"
);
}
void
wlcore_event_dummy_packet
(
struct
wl1271
*
wl
)
{
wl1271_debug
(
DEBUG_EVENT
,
"DUMMY_PACKET_ID_EVENT_ID"
);
wl1271_tx_dummy_packet
(
wl
);
}
EXPORT_SYMBOL_GPL
(
wlcore_event_dummy_packet
);
if
(
vector
&
RSSI_SNR_TRIGGER_0_EVENT_ID
)
{
/* TODO: check actual multi-role support */
wl1271_debug
(
DEBUG_EVENT
,
"RSSI_SNR_TRIGGER_0_EVENT"
);
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
wl1271_event_rssi_trigger
(
wl
,
wlvif
,
mbox
);
static
void
wlcore_disconnect_sta
(
struct
wl1271
*
wl
,
unsigned
long
sta_bitmap
)
{
u32
num_packets
=
wl
->
conf
.
tx
.
max_tx_retries
;
struct
wl12xx_vif
*
wlvif
;
struct
ieee80211_vif
*
vif
;
struct
ieee80211_sta
*
sta
;
const
u8
*
addr
;
int
h
;
for_each_set_bit
(
h
,
&
sta_bitmap
,
WL12XX_MAX_LINKS
)
{
bool
found
=
false
;
/* find the ap vif connected to this sta */
wl12xx_for_each_wlvif_ap
(
wl
,
wlvif
)
{
if
(
!
test_bit
(
h
,
wlvif
->
ap
.
sta_hlid_map
))
continue
;
found
=
true
;
break
;
}
}
if
(
!
found
)
continue
;
if
(
vector
&
BA_SESSION_RX_CONSTRAINT_EVENT_ID
)
{
u8
role_id
=
mbox
->
role_id
;
wl1271_debug
(
DEBUG_EVENT
,
"BA_SESSION_RX_CONSTRAINT_EVENT_ID. "
"ba_allowed = 0x%x, role_id=%d"
,
mbox
->
rx_ba_allowed
,
role_id
);
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
addr
=
wl
->
links
[
h
].
addr
;
wl12xx_for_each_wlvif
(
wl
,
wlvif
)
{
if
(
role_id
!=
0xff
&&
role_id
!=
wlvif
->
role_id
)
continue
;
wlvif
->
ba_allowed
=
!!
mbox
->
rx_ba_allowed
;
if
(
!
wlvif
->
ba_allowed
)
wl1271_stop_ba_event
(
wl
,
wlvif
);
rcu_read_lock
();
sta
=
ieee80211_find_sta
(
vif
,
addr
);
if
(
sta
)
{
wl1271_debug
(
DEBUG_EVENT
,
"remove sta %d"
,
h
);
ieee80211_report_low_ack
(
sta
,
num_packets
);
}
rcu_read_unlock
();
}
}
if
(
vector
&
CHANNEL_SWITCH_COMPLETE_EVENT_ID
)
{
wl1271_debug
(
DEBUG_EVENT
,
"CHANNEL_SWITCH_COMPLETE_EVENT_ID. "
"status = 0x%x"
,
mbox
->
channel_switch_status
);
/*
* That event uses for two cases:
* 1) channel switch complete with status=0
* 2) channel switch failed status=1
*/
/* TODO: configure only the relevant vif */
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
bool
success
;
if
(
!
test_and_clear_bit
(
WLVIF_FLAG_CS_PROGRESS
,
&
wlvif
->
flags
))
continue
;
success
=
mbox
->
channel_switch_status
?
false
:
true
;
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
void
wlcore_event_max_tx_failure
(
struct
wl1271
*
wl
,
unsigned
long
sta_bitmap
)
{
wl1271_debug
(
DEBUG_EVENT
,
"MAX_TX_FAILURE_EVENT_ID"
);
wlcore_disconnect_sta
(
wl
,
sta_bitmap
);
}
EXPORT_SYMBOL_GPL
(
wlcore_event_max_tx_failure
);
ieee80211_chswitch_done
(
vif
,
success
);
}
}
void
wlcore_event_inactive_sta
(
struct
wl1271
*
wl
,
unsigned
long
sta_bitmap
)
{
wl1271_debug
(
DEBUG_EVENT
,
"INACTIVE_STA_EVENT_ID"
);
wlcore_disconnect_sta
(
wl
,
sta_bitmap
);
}
EXPORT_SYMBOL_GPL
(
wlcore_event_inactive_sta
);
if
((
vector
&
DUMMY_PACKET_EVENT_ID
))
{
wl1271_debug
(
DEBUG_EVENT
,
"DUMMY_PACKET_ID_EVENT_ID"
);
ret
=
wl1271_tx_dummy_packet
(
wl
);
if
(
ret
<
0
)
return
ret
;
}
void
wlcore_event_roc_complete
(
struct
wl1271
*
wl
)
{
wl1271_debug
(
DEBUG_EVENT
,
"REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID"
);
if
(
wl
->
roc_vif
)
ieee80211_ready_on_channel
(
wl
->
hw
);
}
EXPORT_SYMBOL_GPL
(
wlcore_event_roc_complete
);
void
wlcore_event_beacon_loss
(
struct
wl1271
*
wl
,
unsigned
long
roles_bitmap
)
{
/*
*
"TX retries exceeded" has a different meaning according to mode.
*
In AP mode the offending station is disconnected
.
*
We are HW_MONITOR device. On beacon loss - queue
*
connection loss work. Cancel it on REGAINED event
.
*/
if
(
vector
&
MAX_TX_RETRY_EVENT_ID
)
{
wl1271_debug
(
DEBUG_EVENT
,
"MAX_TX_RETRY_EVENT_ID"
);
sta_bitmap
|=
le16_to_cpu
(
mbox
->
sta_tx_retry_exceeded
);
disconnect_sta
=
true
;
}
struct
wl12xx_vif
*
wlvif
;
struct
ieee80211_vif
*
vif
;
int
delay
=
wl
->
conf
.
conn
.
synch_fail_thold
*
wl
->
conf
.
conn
.
bss_lose_timeout
;
if
(
vector
&
INACTIVE_STA_EVENT_ID
)
{
wl1271_debug
(
DEBUG_EVENT
,
"INACTIVE_STA_EVENT_ID"
);
sta_bitmap
|=
le16_to_cpu
(
mbox
->
sta_aging_status
);
disconnect_sta
=
true
;
}
wl1271_info
(
"Beacon loss detected. roles:0x%lx"
,
roles_bitmap
);
if
(
disconnect_sta
)
{
u32
num_packets
=
wl
->
conf
.
tx
.
max_tx_retries
;
struct
ieee80211_sta
*
sta
;
const
u8
*
addr
;
int
h
;
for_each_set_bit
(
h
,
&
sta_bitmap
,
WL12XX_MAX_LINKS
)
{
bool
found
=
false
;
/* find the ap vif connected to this sta */
wl12xx_for_each_wlvif_ap
(
wl
,
wlvif
)
{
if
(
!
test_bit
(
h
,
wlvif
->
ap
.
sta_hlid_map
))
continue
;
found
=
true
;
break
;
}
if
(
!
found
)
continue
;
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
if
(
wlvif
->
role_id
==
WL12XX_INVALID_ROLE_ID
||
!
test_bit
(
wlvif
->
role_id
,
&
roles_bitmap
))
continue
;
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
addr
=
wl
->
links
[
h
].
addr
;
/*
* if the work is already queued, it should take place.
* We don't want to delay the connection loss
* indication any more.
*/
ieee80211_queue_delayed_work
(
wl
->
hw
,
&
wlvif
->
connection_loss_work
,
msecs_to_jiffies
(
delay
));
rcu_read_lock
();
sta
=
ieee80211_find_sta
(
vif
,
addr
);
if
(
sta
)
{
wl1271_debug
(
DEBUG_EVENT
,
"remove sta %d"
,
h
);
ieee80211_report_low_ack
(
sta
,
num_packets
);
}
rcu_read_unlock
();
}
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
ieee80211_cqm_rssi_notify
(
vif
,
NL80211_CQM_RSSI_BEACON_LOSS_EVENT
,
GFP_KERNEL
);
}
return
0
;
}
EXPORT_SYMBOL_GPL
(
wlcore_event_beacon_loss
);
int
wl1271_event_unmask
(
struct
wl1271
*
wl
)
{
...
...
@@ -305,12 +286,12 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
/* first we read the mbox descriptor */
ret
=
wlcore_read
(
wl
,
wl
->
mbox_ptr
[
mbox_num
],
wl
->
mbox
,
sizeof
(
*
wl
->
mbox
)
,
false
);
wl
->
mbox_size
,
false
);
if
(
ret
<
0
)
return
ret
;
/* process the descriptor */
ret
=
wl
1271_event_proces
s
(
wl
);
ret
=
wl
->
ops
->
process_mailbox_event
s
(
wl
);
if
(
ret
<
0
)
return
ret
;
...
...
drivers/net/wireless/ti/wlcore/event.h
浏览文件 @
aaabee8b
...
...
@@ -46,33 +46,17 @@ enum {
RSSI_SNR_TRIGGER_5_EVENT_ID
=
BIT
(
5
),
RSSI_SNR_TRIGGER_6_EVENT_ID
=
BIT
(
6
),
RSSI_SNR_TRIGGER_7_EVENT_ID
=
BIT
(
7
),
MEASUREMENT_START_EVENT_ID
=
BIT
(
8
),
MEASUREMENT_COMPLETE_EVENT_ID
=
BIT
(
9
),
SCAN_COMPLETE_EVENT_ID
=
BIT
(
10
),
WFD_DISCOVERY_COMPLETE_EVENT_ID
=
BIT
(
11
),
AP_DISCOVERY_COMPLETE_EVENT_ID
=
BIT
(
12
),
RESERVED1
=
BIT
(
13
),
PSPOLL_DELIVERY_FAILURE_EVENT_ID
=
BIT
(
14
),
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
),
MAX_TX_RETRY_EVENT_ID
=
BIT
(
20
),
DUMMY_PACKET_EVENT_ID
=
BIT
(
21
),
SOFT_GEMINI_SENSE_EVENT_ID
=
BIT
(
22
),
CHANGE_AUTO_MODE_TIMEOUT_EVENT_ID
=
BIT
(
23
),
SOFT_GEMINI_AVALANCHE_EVENT_ID
=
BIT
(
24
),
PLT_RX_CALIBRATION_COMPLETE_EVENT_ID
=
BIT
(
25
),
INACTIVE_STA_EVENT_ID
=
BIT
(
26
),
PEER_REMOVE_COMPLETE_EVENT_ID
=
BIT
(
27
),
PERIODIC_SCAN_COMPLETE_EVENT_ID
=
BIT
(
28
),
PERIODIC_SCAN_REPORT_EVENT_ID
=
BIT
(
29
),
BA_SESSION_RX_CONSTRAINT_EVENT_ID
=
BIT
(
30
),
REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID
=
BIT
(
31
),
EVENT_MBOX_ALL_EVENT_ID
=
0x7fffffff
,
};
/* events the driver might want to wait for */
enum
wlcore_wait_event
{
WLCORE_EVENT_ROLE_STOP_COMPLETE
,
WLCORE_EVENT_PEER_REMOVE_COMPLETE
,
WLCORE_EVENT_DFS_CONFIG_COMPLETE
};
enum
{
EVENT_ENTER_POWER_SAVE_FAIL
=
0
,
EVENT_ENTER_POWER_SAVE_SUCCESS
,
...
...
@@ -80,61 +64,26 @@ enum {
#define NUM_OF_RSSI_SNR_TRIGGERS 8
struct
event_mailbox
{
__le32
events_vector
;
__le32
events_mask
;
__le32
reserved_1
;
__le32
reserved_2
;
u8
number_of_scan_results
;
u8
scan_tag
;
u8
completed_scan_status
;
u8
reserved_3
;
u8
soft_gemini_sense_info
;
u8
soft_gemini_protective_info
;
s8
rssi_snr_trigger_metric
[
NUM_OF_RSSI_SNR_TRIGGERS
];
u8
change_auto_mode_timeout
;
u8
scheduled_scan_status
;
u8
reserved4
;
/* tuned channel (roc) */
u8
roc_channel
;
__le16
hlid_removed_bitmap
;
/* bitmap of aged stations (by HLID) */
__le16
sta_aging_status
;
/* bitmap of stations (by HLID) which exceeded max tx retries */
__le16
sta_tx_retry_exceeded
;
/* discovery completed results */
u8
discovery_tag
;
u8
number_of_preq_results
;
u8
number_of_prsp_results
;
u8
reserved_5
;
/* rx ba constraint */
u8
role_id
;
/* 0xFF means any role. */
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
reserved_8
[
9
];
}
__packed
;
struct
wl1271
;
int
wl1271_event_unmask
(
struct
wl1271
*
wl
);
int
wl1271_event_handle
(
struct
wl1271
*
wl
,
u8
mbox
);
void
wlcore_event_soft_gemini_sense
(
struct
wl1271
*
wl
,
u8
enable
);
void
wlcore_event_sched_scan_report
(
struct
wl1271
*
wl
,
u8
status
);
void
wlcore_event_sched_scan_completed
(
struct
wl1271
*
wl
,
u8
status
);
void
wlcore_event_ba_rx_constraint
(
struct
wl1271
*
wl
,
unsigned
long
roles_bitmap
,
unsigned
long
allowed_bitmap
);
void
wlcore_event_channel_switch
(
struct
wl1271
*
wl
,
unsigned
long
roles_bitmap
,
bool
success
);
void
wlcore_event_beacon_loss
(
struct
wl1271
*
wl
,
unsigned
long
roles_bitmap
);
void
wlcore_event_dummy_packet
(
struct
wl1271
*
wl
);
void
wlcore_event_max_tx_failure
(
struct
wl1271
*
wl
,
unsigned
long
sta_bitmap
);
void
wlcore_event_inactive_sta
(
struct
wl1271
*
wl
,
unsigned
long
sta_bitmap
);
void
wlcore_event_roc_complete
(
struct
wl1271
*
wl
);
void
wlcore_event_rssi_trigger
(
struct
wl1271
*
wl
,
s8
*
metric_arr
);
#endif
drivers/net/wireless/ti/wlcore/hw_ops.h
浏览文件 @
aaabee8b
...
...
@@ -201,4 +201,12 @@ wlcore_hw_pre_pkt_send(struct wl1271 *wl, u32 buf_offset, u32 last_len)
return
buf_offset
;
}
static
inline
void
wlcore_hw_sta_rc_update
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
ieee80211_sta
*
sta
,
u32
changed
)
{
if
(
wl
->
ops
->
sta_rc_update
)
wl
->
ops
->
sta_rc_update
(
wl
,
wlvif
,
sta
,
changed
);
}
#endif
drivers/net/wireless/ti/wlcore/init.c
浏览文件 @
aaabee8b
...
...
@@ -41,14 +41,14 @@ int wl1271_init_templates_config(struct wl1271 *wl)
/* send empty templates for fw memory reservation */
ret
=
wl1271_cmd_template_set
(
wl
,
WL12XX_INVALID_ROLE_ID
,
CMD_TEMPL_CFG_PROBE_REQ
_2_4
,
NULL
,
wl
->
scan_templ_id
_2_4
,
NULL
,
WL1271_CMD_TEMPL_MAX_SIZE
,
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_cmd_template_set
(
wl
,
WL12XX_INVALID_ROLE_ID
,
CMD_TEMPL_CFG_PROBE_REQ
_5
,
wl
->
scan_templ_id
_5
,
NULL
,
WL1271_CMD_TEMPL_MAX_SIZE
,
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
...
...
@@ -56,14 +56,16 @@ int wl1271_init_templates_config(struct wl1271 *wl)
if
(
wl
->
quirks
&
WLCORE_QUIRK_DUAL_PROBE_TMPL
)
{
ret
=
wl1271_cmd_template_set
(
wl
,
WL12XX_INVALID_ROLE_ID
,
CMD_TEMPL_APP_PROBE_REQ_2_4
,
NULL
,
wl
->
sched_scan_templ_id_2_4
,
NULL
,
WL1271_CMD_TEMPL_MAX_SIZE
,
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_cmd_template_set
(
wl
,
WL12XX_INVALID_ROLE_ID
,
CMD_TEMPL_APP_PROBE_REQ_5
,
NULL
,
wl
->
sched_scan_templ_id_5
,
NULL
,
WL1271_CMD_TEMPL_MAX_SIZE
,
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
...
...
@@ -463,7 +465,7 @@ int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif)
if
((
wlvif
->
basic_rate_set
&
CONF_TX_OFDM_RATES
))
supported_rates
=
CONF_TX_OFDM_RATES
;
else
supported_rates
=
CONF_TX_
AP_
ENABLED_RATES
;
supported_rates
=
CONF_TX_ENABLED_RATES
;
/* unconditionally enable HT rates */
supported_rates
|=
CONF_TX_MCS_RATES
;
...
...
@@ -679,6 +681,10 @@ int wl1271_hw_init(struct wl1271 *wl)
if
(
ret
<
0
)
return
ret
;
ret
=
wlcore_cmd_regdomain_config_locked
(
wl
);
if
(
ret
<
0
)
return
ret
;
/* Bluetooth WLAN coexistence */
ret
=
wl1271_init_pta
(
wl
);
if
(
ret
<
0
)
...
...
drivers/net/wireless/ti/wlcore/main.c
浏览文件 @
aaabee8b
此差异已折叠。
点击以展开。
drivers/net/wireless/ti/wlcore/ps.c
浏览文件 @
aaabee8b
...
...
@@ -151,9 +151,6 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)
wl12xx_queue_recovery_work
(
wl
);
ret
=
-
ETIMEDOUT
;
goto
err
;
}
else
if
(
ret
<
0
)
{
wl1271_error
(
"ELP wakeup completion error."
);
goto
err
;
}
}
...
...
drivers/net/wireless/ti/wlcore/rx.c
浏览文件 @
aaabee8b
...
...
@@ -97,6 +97,10 @@ static void wl1271_rx_status(struct wl1271 *wl,
wl1271_warning
(
"Michael MIC error"
);
}
}
if
(
beacon
)
wlcore_set_pending_regdomain_ch
(
wl
,
(
u16
)
desc
->
channel
,
status
->
band
);
}
static
int
wl1271_rx_handle_data
(
struct
wl1271
*
wl
,
u8
*
data
,
u32
length
,
...
...
drivers/net/wireless/ti/wlcore/scan.c
浏览文件 @
aaabee8b
此差异已折叠。
点击以展开。
drivers/net/wireless/ti/wlcore/scan.h
浏览文件 @
aaabee8b
...
...
@@ -26,21 +26,19 @@
#include "wlcore.h"
int
wl
1271
_scan
(
struct
wl1271
*
wl
,
struct
ieee80211_vif
*
vif
,
int
wl
core
_scan
(
struct
wl1271
*
wl
,
struct
ieee80211_vif
*
vif
,
const
u8
*
ssid
,
size_t
ssid_len
,
struct
cfg80211_scan_request
*
req
);
int
wl1271_scan_stop
(
struct
wl1271
*
wl
);
int
wl1271_scan_build_probe_req
(
struct
wl1271
*
wl
,
const
u8
*
ssid
,
size_t
ssid_len
,
const
u8
*
ie
,
size_t
ie_len
,
u8
band
);
void
wl1271_scan_stm
(
struct
wl1271
*
wl
,
struct
ieee80211_vif
*
vif
);
void
wl1271_scan_stm
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wl
vif
);
void
wl1271_scan_complete_work
(
struct
work_struct
*
work
);
int
wl1271_scan_sched_scan_config
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
cfg80211_sched_scan_request
*
req
,
struct
ieee80211_sched_scan_ies
*
ies
);
int
wl1271_scan_sched_scan_start
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
void
wl1271_scan_sched_scan_stop
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
void
wl1271_scan_sched_scan_results
(
struct
wl1271
*
wl
);
#define WL1271_SCAN_MAX_CHANNELS 24
...
...
@@ -66,56 +64,6 @@ enum {
WL1271_SCAN_STATE_DONE
};
struct
basic_scan_params
{
/* Scan option flags (WL1271_SCAN_OPT_*) */
__le16
scan_options
;
u8
role_id
;
/* Number of scan channels in the list (maximum 30) */
u8
n_ch
;
/* This field indicates the number of probe requests to send
per channel for an active scan */
u8
n_probe_reqs
;
u8
tid_trigger
;
u8
ssid_len
;
u8
use_ssid_list
;
/* Rate bit field for sending the probes */
__le32
tx_rate
;
u8
ssid
[
IEEE80211_MAX_SSID_LEN
];
/* Band to scan */
u8
band
;
u8
scan_tag
;
u8
padding2
[
2
];
}
__packed
;
struct
basic_scan_channel_params
{
/* Duration in TU to wait for frames on a channel for active scan */
__le32
min_duration
;
__le32
max_duration
;
__le32
bssid_lsb
;
__le16
bssid_msb
;
u8
early_termination
;
u8
tx_power_att
;
u8
channel
;
/* FW internal use only! */
u8
dfs_candidate
;
u8
activity_detected
;
u8
pad
;
}
__packed
;
struct
wl1271_cmd_scan
{
struct
wl1271_cmd_header
header
;
struct
basic_scan_params
params
;
struct
basic_scan_channel_params
channels
[
WL1271_SCAN_MAX_CHANNELS
];
/* src mac address */
u8
addr
[
ETH_ALEN
];
u8
padding
[
2
];
}
__packed
;
struct
wl1271_cmd_trigger_scan_to
{
struct
wl1271_cmd_header
header
;
...
...
@@ -123,9 +71,17 @@ struct wl1271_cmd_trigger_scan_to {
}
__packed
;
#define MAX_CHANNELS_2GHZ 14
#define MAX_CHANNELS_5GHZ 23
#define MAX_CHANNELS_4GHZ 4
/*
* This max value here is used only for the struct definition of
* wlcore_scan_channels. This struct is used by both 12xx
* and 18xx (which have different max 5ghz channels value).
* In order to make sure this is large enough, just use the
* max possible 5ghz channels.
*/
#define MAX_CHANNELS_5GHZ 42
#define SCAN_MAX_CYCLE_INTERVALS 16
#define SCAN_MAX_BANDS 3
...
...
@@ -160,43 +116,6 @@ struct conn_scan_ch_params {
u8
padding
[
3
];
}
__packed
;
struct
wl1271_cmd_sched_scan_config
{
struct
wl1271_cmd_header
header
;
__le32
intervals
[
SCAN_MAX_CYCLE_INTERVALS
];
s8
rssi_threshold
;
/* for filtering (in dBm) */
s8
snr_threshold
;
/* for filtering (in dB) */
u8
cycles
;
/* maximum number of scan cycles */
u8
report_after
;
/* report when this number of results are received */
u8
terminate
;
/* stop scanning after reporting */
u8
tag
;
u8
bss_type
;
/* for filtering */
u8
filter_type
;
u8
ssid_len
;
/* For SCAN_SSID_FILTER_SPECIFIC */
u8
ssid
[
IEEE80211_MAX_SSID_LEN
];
u8
n_probe_reqs
;
/* Number of probes requests per channel */
u8
passive
[
SCAN_MAX_BANDS
];
u8
active
[
SCAN_MAX_BANDS
];
u8
dfs
;
u8
n_pactive_ch
;
/* number of pactive (passive until fw detects energy)
channels in BG band */
u8
role_id
;
u8
padding
[
1
];
struct
conn_scan_ch_params
channels_2
[
MAX_CHANNELS_2GHZ
];
struct
conn_scan_ch_params
channels_5
[
MAX_CHANNELS_5GHZ
];
struct
conn_scan_ch_params
channels_4
[
MAX_CHANNELS_4GHZ
];
}
__packed
;
#define SCHED_SCAN_MAX_SSIDS 16
enum
{
...
...
@@ -220,21 +139,34 @@ struct wl1271_cmd_sched_scan_ssid_list {
u8
padding
[
2
];
}
__packed
;
struct
wl1271_cmd_sched_scan_start
{
struct
wl1271_cmd_header
header
;
struct
wlcore_scan_channels
{
u8
passive
[
SCAN_MAX_BANDS
];
/* number of passive scan channels */
u8
active
[
SCAN_MAX_BANDS
];
/* number of active scan channels */
u8
dfs
;
/* number of dfs channels in 5ghz */
u8
passive_active
;
/* number of passive before active channels 2.4ghz */
u8
tag
;
u8
role_id
;
u8
padding
[
2
];
}
__packed
;
struct
wl1271_cmd_sched_scan_stop
{
struct
wl1271_cmd_header
header
;
struct
conn_scan_ch_params
channels_2
[
MAX_CHANNELS_2GHZ
];
struct
conn_scan_ch_params
channels_5
[
MAX_CHANNELS_5GHZ
];
struct
conn_scan_ch_params
channels_4
[
MAX_CHANNELS_4GHZ
];
};
u8
tag
;
u8
role_id
;
u8
padding
[
2
];
}
__packed
;
enum
{
SCAN_TYPE_SEARCH
=
0
,
SCAN_TYPE_PERIODIC
=
1
,
SCAN_TYPE_TRACKING
=
2
,
};
bool
wlcore_set_scan_chan_params
(
struct
wl1271
*
wl
,
struct
wlcore_scan_channels
*
cfg
,
struct
ieee80211_channel
*
channels
[],
u32
n_channels
,
u32
n_ssids
,
int
scan_type
);
int
wlcore_scan_sched_scan_ssid_list
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
cfg80211_sched_scan_request
*
req
);
#endif
/* __WL1271_SCAN_H__ */
drivers/net/wireless/ti/wlcore/sdio.c
浏览文件 @
aaabee8b
...
...
@@ -326,8 +326,7 @@ static void __devexit wl1271_remove(struct sdio_func *func)
/* Undo decrement done above in wl1271_probe */
pm_runtime_get_noresume
(
&
func
->
dev
);
platform_device_del
(
glue
->
core
);
platform_device_put
(
glue
->
core
);
platform_device_unregister
(
glue
->
core
);
kfree
(
glue
);
}
...
...
drivers/net/wireless/ti/wlcore/spi.c
浏览文件 @
aaabee8b
...
...
@@ -270,7 +270,7 @@ static int __must_check wl12xx_spi_raw_write(struct device *child, int addr,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
struct
wl12xx_spi_glue
*
glue
=
dev_get_drvdata
(
child
->
parent
);
struct
spi_transfer
t
[
2
*
WSPI_MAX_NUM_OF_CHUNKS
];
struct
spi_transfer
t
[
2
*
(
WSPI_MAX_NUM_OF_CHUNKS
+
1
)
];
struct
spi_message
m
;
u32
commands
[
WSPI_MAX_NUM_OF_CHUNKS
];
u32
*
cmd
;
...
...
@@ -407,8 +407,7 @@ static int __devexit wl1271_remove(struct spi_device *spi)
{
struct
wl12xx_spi_glue
*
glue
=
spi_get_drvdata
(
spi
);
platform_device_del
(
glue
->
core
);
platform_device_put
(
glue
->
core
);
platform_device_unregister
(
glue
->
core
);
kfree
(
glue
);
return
0
;
...
...
drivers/net/wireless/ti/wlcore/tx.c
浏览文件 @
aaabee8b
...
...
@@ -155,7 +155,7 @@ static u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u8
wl12xx_tx_get_hlid
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
sk_buff
*
skb
,
struct
ieee80211_sta
*
sta
)
{
struct
ieee80211_
hdr
*
hdr
=
(
struct
ieee80211_hdr
*
)
skb
->
data
;
struct
ieee80211_
tx_info
*
control
;
if
(
!
wlvif
||
wl12xx_is_dummy_packet
(
wl
,
skb
))
return
wl
->
system_hlid
;
...
...
@@ -163,13 +163,13 @@ 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
,
sta
);
if
((
test_bit
(
WLVIF_FLAG_STA_ASSOCIATED
,
&
wlvif
->
flags
)
||
test_bit
(
WLVIF_FLAG_IBSS_JOINED
,
&
wlvif
->
flags
))
&&
!
ieee80211_is_auth
(
hdr
->
frame_control
)
&&
!
ieee80211_is_assoc_req
(
hdr
->
frame_control
))
return
wlvif
->
sta
.
hlid
;
else
control
=
IEEE80211_SKB_CB
(
skb
);
if
(
control
->
flags
&
IEEE80211_TX_CTL_TX_OFFCHAN
)
{
wl1271_debug
(
DEBUG_TX
,
"tx offchannel"
);
return
wlvif
->
dev_hlid
;
}
return
wlvif
->
sta
.
hlid
;
}
unsigned
int
wlcore_calc_packet_alignment
(
struct
wl1271
*
wl
,
...
...
@@ -294,7 +294,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif,
tx_attr
|=
TX_HW_ATTR_TX_DUMMY_REQ
;
}
else
if
(
wlvif
)
{
/* configure the tx attributes */
tx_attr
=
wl
vif
->
session_counter
<<
tx_attr
=
wl
->
session_ids
[
hlid
]
<<
TX_HW_ATTR_OFST_SESSION_COUNTER
;
}
...
...
@@ -1135,6 +1135,7 @@ u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set)
return
BIT
(
__ffs
(
rate_set
));
}
EXPORT_SYMBOL_GPL
(
wl1271_tx_min_rate_get
);
void
wlcore_stop_queue_locked
(
struct
wl1271
*
wl
,
u8
queue
,
enum
wlcore_queue_stop_reason
reason
)
...
...
drivers/net/wireless/ti/wlcore/wlcore.h
浏览文件 @
aaabee8b
此差异已折叠。
点击以展开。
drivers/net/wireless/ti/wlcore/wlcore_i.h
浏览文件 @
aaabee8b
...
...
@@ -109,17 +109,6 @@ enum {
NUM_FW_VER
};
#define FW_VER_CHIP_WL127X 6
#define FW_VER_CHIP_WL128X 7
#define FW_VER_IF_TYPE_STA 1
#define FW_VER_IF_TYPE_AP 2
#define FW_VER_MINOR_1_SPARE_STA_MIN 58
#define FW_VER_MINOR_1_SPARE_AP_MIN 47
#define FW_VER_MINOR_FWLOG_STA_MIN 70
struct
wl1271_chip
{
u32
id
;
char
fw_ver_str
[
ETHTOOL_BUSINFO_LEN
];
...
...
@@ -315,6 +304,7 @@ struct wl12xx_rx_filter {
struct
wl1271_station
{
u8
hlid
;
bool
in_connection
;
};
struct
wl12xx_vif
{
...
...
@@ -341,6 +331,8 @@ struct wl12xx_vif {
u8
klv_template_id
;
bool
qos
;
/* channel type we started the STA role with */
enum
nl80211_channel_type
role_chan_type
;
}
sta
;
struct
{
u8
global_hlid
;
...
...
@@ -396,9 +388,6 @@ struct wl12xx_vif {
/* Our association ID */
u16
aid
;
/* Session counter for the chipset */
int
session_counter
;
/* retry counter for PSM entries */
u8
psm_entry_retry
;
...
...
@@ -416,11 +405,19 @@ struct wl12xx_vif {
bool
ba_support
;
bool
ba_allowed
;
bool
wmm_enabled
;
/* Rx Streaming */
struct
work_struct
rx_streaming_enable_work
;
struct
work_struct
rx_streaming_disable_work
;
struct
timer_list
rx_streaming_timer
;
struct
delayed_work
channel_switch_work
;
struct
delayed_work
connection_loss_work
;
/* number of in connection stations */
int
inconn_count
;
/*
* This struct must be last!
* data that has to be saved acrossed reconfigs (e.g. recovery)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录