Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
56e1bd77
K
Kernel
项目概览
openeuler
/
Kernel
接近 2 年 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
56e1bd77
编写于
1月 29, 2013
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'for-linville' of
git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx
Conflicts: drivers/net/wireless/ti/wlcore/main.c
上级
9ebea382
5b37649b
变更
47
展开全部
隐藏空白更改
内联
并排
Showing
47 changed file
with
4632 addition
and
2032 deletion
+4632
-2032
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
+116
-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
+140
-52
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
+30
-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
+86
-1
drivers/net/wireless/ti/wl18xx/acx.h
drivers/net/wireless/ti/wl18xx/acx.h
+54
-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/conf.h
drivers/net/wireless/ti/wl18xx/conf.h
+15
-6
drivers/net/wireless/ti/wl18xx/event.c
drivers/net/wireless/ti/wl18xx/event.c
+111
-0
drivers/net/wireless/ti/wl18xx/event.h
drivers/net/wireless/ti/wl18xx/event.h
+77
-0
drivers/net/wireless/ti/wl18xx/main.c
drivers/net/wireless/ti/wl18xx/main.c
+219
-48
drivers/net/wireless/ti/wl18xx/scan.c
drivers/net/wireless/ti/wl18xx/scan.c
+326
-0
drivers/net/wireless/ti/wl18xx/scan.h
drivers/net/wireless/ti/wl18xx/scan.h
+127
-0
drivers/net/wireless/ti/wl18xx/tx.c
drivers/net/wireless/ti/wl18xx/tx.c
+49
-5
drivers/net/wireless/ti/wl18xx/wl18xx.h
drivers/net/wireless/ti/wl18xx/wl18xx.h
+43
-7
drivers/net/wireless/ti/wlcore/acx.c
drivers/net/wireless/ti/wlcore/acx.c
+13
-2
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
+281
-138
drivers/net/wireless/ti/wlcore/cmd.h
drivers/net/wireless/ti/wlcore/cmd.h
+54
-27
drivers/net/wireless/ti/wlcore/conf.h
drivers/net/wireless/ti/wlcore/conf.h
+87
-23
drivers/net/wireless/ti/wlcore/debugfs.c
drivers/net/wireless/ti/wlcore/debugfs.c
+6
-4
drivers/net/wireless/ti/wlcore/event.c
drivers/net/wireless/ti/wlcore/event.c
+149
-177
drivers/net/wireless/ti/wlcore/event.h
drivers/net/wireless/ti/wlcore/event.h
+23
-76
drivers/net/wireless/ti/wlcore/hw_ops.h
drivers/net/wireless/ti/wlcore/hw_ops.h
+41
-0
drivers/net/wireless/ti/wlcore/init.c
drivers/net/wireless/ti/wlcore/init.c
+11
-8
drivers/net/wireless/ti/wlcore/io.h
drivers/net/wireless/ti/wlcore/io.h
+6
-6
drivers/net/wireless/ti/wlcore/main.c
drivers/net/wireless/ti/wlcore/main.c
+1010
-579
drivers/net/wireless/ti/wlcore/ps.c
drivers/net/wireless/ti/wlcore/ps.c
+6
-5
drivers/net/wireless/ti/wlcore/rx.c
drivers/net/wireless/ti/wlcore/rx.c
+18
-15
drivers/net/wireless/ti/wlcore/rx.h
drivers/net/wireless/ti/wlcore/rx.h
+1
-2
drivers/net/wireless/ti/wlcore/scan.c
drivers/net/wireless/ti/wlcore/scan.c
+172
-524
drivers/net/wireless/ti/wlcore/scan.h
drivers/net/wireless/ti/wlcore/scan.h
+38
-106
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
+193
-105
drivers/net/wireless/ti/wlcore/tx.h
drivers/net/wireless/ti/wlcore/tx.h
+22
-13
drivers/net/wireless/ti/wlcore/wlcore.h
drivers/net/wireless/ti/wlcore/wlcore.h
+93
-25
drivers/net/wireless/ti/wlcore/wlcore_i.h
drivers/net/wireless/ti/wlcore/wlcore_i.h
+33
-16
未找到文件。
drivers/net/wireless/ti/wl1251/Kconfig
浏览文件 @
56e1bd77
menuconfig WL1251
menuconfig WL1251
tristate "TI wl1251 driver support"
tristate "TI wl1251 driver support"
depends on MAC80211 &&
EXPERIMENTAL &&
GENERIC_HARDIRQS
depends on MAC80211 && GENERIC_HARDIRQS
select FW_LOADER
select FW_LOADER
select CRC7
select CRC7
---help---
---help---
...
...
drivers/net/wireless/ti/wl12xx/Makefile
浏览文件 @
56e1bd77
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
obj-$(CONFIG_WL12XX)
+=
wl12xx.o
drivers/net/wireless/ti/wl12xx/cmd.c
浏览文件 @
56e1bd77
...
@@ -284,3 +284,40 @@ int wl128x_cmd_radio_parms(struct wl1271 *wl)
...
@@ -284,3 +284,40 @@ int wl128x_cmd_radio_parms(struct wl1271 *wl)
kfree
(
radio_parms
);
kfree
(
radio_parms
);
return
ret
;
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
浏览文件 @
56e1bd77
...
@@ -103,10 +103,30 @@ struct wl1271_ext_radio_parms_cmd {
...
@@ -103,10 +103,30 @@ struct wl1271_ext_radio_parms_cmd {
u8
padding
[
3
];
u8
padding
[
3
];
}
__packed
;
}
__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
wl1271_cmd_general_parms
(
struct
wl1271
*
wl
);
int
wl128x_cmd_general_parms
(
struct
wl1271
*
wl
);
int
wl128x_cmd_general_parms
(
struct
wl1271
*
wl
);
int
wl1271_cmd_radio_parms
(
struct
wl1271
*
wl
);
int
wl1271_cmd_radio_parms
(
struct
wl1271
*
wl
);
int
wl128x_cmd_radio_parms
(
struct
wl1271
*
wl
);
int
wl128x_cmd_radio_parms
(
struct
wl1271
*
wl
);
int
wl1271_cmd_ext_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__ */
#endif
/* __WL12XX_CMD_H__ */
drivers/net/wireless/ti/wl12xx/event.c
0 → 100644
浏览文件 @
56e1bd77
/*
* 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
)
{
wl1271_debug
(
DEBUG_EVENT
,
"PERIODIC_SCAN_REPORT_EVENT (status 0x%0x)"
,
mbox
->
scheduled_scan_status
);
wlcore_scan_sched_scan_results
(
wl
);
}
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
浏览文件 @
56e1bd77
/*
* 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
浏览文件 @
56e1bd77
...
@@ -38,6 +38,8 @@
...
@@ -38,6 +38,8 @@
#include "reg.h"
#include "reg.h"
#include "cmd.h"
#include "cmd.h"
#include "acx.h"
#include "acx.h"
#include "scan.h"
#include "event.h"
#include "debugfs.h"
#include "debugfs.h"
static
char
*
fref_param
;
static
char
*
fref_param
;
...
@@ -208,6 +210,8 @@ static struct wlcore_conf wl12xx_conf = {
...
@@ -208,6 +210,8 @@ static struct wlcore_conf wl12xx_conf = {
.
tmpl_short_retry_limit
=
10
,
.
tmpl_short_retry_limit
=
10
,
.
tmpl_long_retry_limit
=
10
,
.
tmpl_long_retry_limit
=
10
,
.
tx_watchdog_timeout
=
5000
,
.
tx_watchdog_timeout
=
5000
,
.
slow_link_thold
=
3
,
.
fast_link_thold
=
10
,
},
},
.
conn
=
{
.
conn
=
{
.
wake_up_event
=
CONF_WAKE_UP_EVENT_DTIM
,
.
wake_up_event
=
CONF_WAKE_UP_EVENT_DTIM
,
...
@@ -265,8 +269,10 @@ static struct wlcore_conf wl12xx_conf = {
...
@@ -265,8 +269,10 @@ static struct wlcore_conf wl12xx_conf = {
.
scan
=
{
.
scan
=
{
.
min_dwell_time_active
=
7500
,
.
min_dwell_time_active
=
7500
,
.
max_dwell_time_active
=
30000
,
.
max_dwell_time_active
=
30000
,
.
min_dwell_time_passive
=
100000
,
.
min_dwell_time_active_long
=
25000
,
.
max_dwell_time_passive
=
100000
,
.
max_dwell_time_active_long
=
50000
,
.
dwell_time_passive
=
100000
,
.
dwell_time_dfs
=
150000
,
.
num_probe_reqs
=
2
,
.
num_probe_reqs
=
2
,
.
split_scan_timeout
=
50000
,
.
split_scan_timeout
=
50000
,
},
},
...
@@ -368,6 +374,10 @@ static struct wlcore_conf wl12xx_conf = {
...
@@ -368,6 +374,10 @@ static struct wlcore_conf wl12xx_conf = {
.
increase_time
=
1
,
.
increase_time
=
1
,
.
window_size
=
16
,
.
window_size
=
16
,
},
},
.
recovery
=
{
.
bug_on_recovery
=
0
,
.
no_recovery
=
0
,
},
};
};
static
struct
wl12xx_priv_conf
wl12xx_default_priv_conf
=
{
static
struct
wl12xx_priv_conf
wl12xx_default_priv_conf
=
{
...
@@ -601,9 +611,9 @@ static int wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
...
@@ -601,9 +611,9 @@ static int wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
{
{
int
ret
;
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
wl1271_acx_mem_map
*
wl_mem_map
=
wl
->
target_mem_map
;
struct
wl12
7x_rx_mem_pool_addr
rx_mem_addr
;
struct
wl12
xx_priv
*
priv
=
wl
->
priv
;
/*
/*
* Choose the block we want to read
* Choose the block we want to read
...
@@ -612,13 +622,13 @@ static int wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
...
@@ -612,13 +622,13 @@ static int wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
*/
*/
u32
mem_block
=
rx_desc
&
RX_MEM_BLOCK_MASK
;
u32
mem_block
=
rx_desc
&
RX_MEM_BLOCK_MASK
;
rx_mem_addr
.
addr
=
(
mem_block
<<
8
)
+
priv
->
rx_mem_addr
->
addr
=
(
mem_block
<<
8
)
+
le32_to_cpu
(
wl_mem_map
->
packet_memory_pool_start
);
le32_to_cpu
(
wl_mem_map
->
packet_memory_pool_start
);
rx_mem_addr
.
addr_extra
=
rx_mem_addr
.
addr
+
4
;
priv
->
rx_mem_addr
->
addr_extra
=
priv
->
rx_mem_addr
->
addr
+
4
;
ret
=
wlcore_write
(
wl
,
WL1271_SLV_REG_DATA
,
&
rx_mem_addr
,
ret
=
wlcore_write
(
wl
,
WL1271_SLV_REG_DATA
,
priv
->
rx_mem_addr
,
sizeof
(
rx_mem_addr
),
false
);
sizeof
(
*
priv
->
rx_mem_addr
),
false
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
}
}
...
@@ -631,13 +641,15 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
...
@@ -631,13 +641,15 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
int
ret
=
0
;
int
ret
=
0
;
switch
(
wl
->
chip
.
id
)
{
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"
,
wl1271_warning
(
"chip id 0x%x (1271 PG10) support is obsolete"
,
wl
->
chip
.
id
);
wl
->
chip
.
id
);
wl
->
quirks
|=
WLCORE_QUIRK_LEGACY_NVS
|
wl
->
quirks
|=
WLCORE_QUIRK_LEGACY_NVS
|
WLCORE_QUIRK_DUAL_PROBE_TMPL
|
WLCORE_QUIRK_DUAL_PROBE_TMPL
|
WLCORE_QUIRK_TKIP_HEADER_SPACE
;
WLCORE_QUIRK_TKIP_HEADER_SPACE
|
WLCORE_QUIRK_START_STA_FAILS
|
WLCORE_QUIRK_AP_ZERO_SESSION_ID
;
wl
->
sr_fw_name
=
WL127X_FW_NAME_SINGLE
;
wl
->
sr_fw_name
=
WL127X_FW_NAME_SINGLE
;
wl
->
mr_fw_name
=
WL127X_FW_NAME_MULTI
;
wl
->
mr_fw_name
=
WL127X_FW_NAME_MULTI
;
memcpy
(
&
wl
->
conf
.
mem
,
&
wl12xx_default_priv_conf
.
mem_wl127x
,
memcpy
(
&
wl
->
conf
.
mem
,
&
wl12xx_default_priv_conf
.
mem_wl127x
,
...
@@ -646,18 +658,22 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
...
@@ -646,18 +658,22 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
/* read data preparation is only needed by wl127x */
/* read data preparation is only needed by wl127x */
wl
->
ops
->
prepare_read
=
wl127x_prepare_read
;
wl
->
ops
->
prepare_read
=
wl127x_prepare_read
;
wlcore_set_min_fw_ver
(
wl
,
WL127X_CHIP_VER
,
WL127X_IFTYPE_VER
,
wlcore_set_min_fw_ver
(
wl
,
WL127X_CHIP_VER
,
WL127X_MAJOR_VER
,
WL127X_SUBTYPE_VER
,
WL127X_IFTYPE_SR_VER
,
WL127X_MAJOR_SR_VER
,
WL127X_MINOR_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
;
break
;
case
CHIP_ID_127
1
_PG20
:
case
CHIP_ID_127
X
_PG20
:
wl1271_debug
(
DEBUG_BOOT
,
"chip id 0x%x (1271 PG20)"
,
wl1271_debug
(
DEBUG_BOOT
,
"chip id 0x%x (1271 PG20)"
,
wl
->
chip
.
id
);
wl
->
chip
.
id
);
wl
->
quirks
|=
WLCORE_QUIRK_LEGACY_NVS
|
wl
->
quirks
|=
WLCORE_QUIRK_LEGACY_NVS
|
WLCORE_QUIRK_DUAL_PROBE_TMPL
|
WLCORE_QUIRK_DUAL_PROBE_TMPL
|
WLCORE_QUIRK_TKIP_HEADER_SPACE
;
WLCORE_QUIRK_TKIP_HEADER_SPACE
|
WLCORE_QUIRK_START_STA_FAILS
|
WLCORE_QUIRK_AP_ZERO_SESSION_ID
;
wl
->
plt_fw_name
=
WL127X_PLT_FW_NAME
;
wl
->
plt_fw_name
=
WL127X_PLT_FW_NAME
;
wl
->
sr_fw_name
=
WL127X_FW_NAME_SINGLE
;
wl
->
sr_fw_name
=
WL127X_FW_NAME_SINGLE
;
wl
->
mr_fw_name
=
WL127X_FW_NAME_MULTI
;
wl
->
mr_fw_name
=
WL127X_FW_NAME_MULTI
;
...
@@ -667,12 +683,14 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
...
@@ -667,12 +683,14 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
/* read data preparation is only needed by wl127x */
/* read data preparation is only needed by wl127x */
wl
->
ops
->
prepare_read
=
wl127x_prepare_read
;
wl
->
ops
->
prepare_read
=
wl127x_prepare_read
;
wlcore_set_min_fw_ver
(
wl
,
WL127X_CHIP_VER
,
WL127X_IFTYPE_VER
,
wlcore_set_min_fw_ver
(
wl
,
WL127X_CHIP_VER
,
WL127X_MAJOR_VER
,
WL127X_SUBTYPE_VER
,
WL127X_IFTYPE_SR_VER
,
WL127X_MAJOR_SR_VER
,
WL127X_MINOR_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
;
break
;
case
CHIP_ID_128
3
_PG20
:
case
CHIP_ID_128
X
_PG20
:
wl1271_debug
(
DEBUG_BOOT
,
"chip id 0x%x (1283 PG20)"
,
wl1271_debug
(
DEBUG_BOOT
,
"chip id 0x%x (1283 PG20)"
,
wl
->
chip
.
id
);
wl
->
chip
.
id
);
wl
->
plt_fw_name
=
WL128X_PLT_FW_NAME
;
wl
->
plt_fw_name
=
WL128X_PLT_FW_NAME
;
...
@@ -682,19 +700,29 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
...
@@ -682,19 +700,29 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
/* wl128x requires TX blocksize alignment */
/* wl128x requires TX blocksize alignment */
wl
->
quirks
|=
WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN
|
wl
->
quirks
|=
WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN
|
WLCORE_QUIRK_DUAL_PROBE_TMPL
|
WLCORE_QUIRK_DUAL_PROBE_TMPL
|
WLCORE_QUIRK_TKIP_HEADER_SPACE
;
WLCORE_QUIRK_TKIP_HEADER_SPACE
|
WLCORE_QUIRK_START_STA_FAILS
|
wlcore_set_min_fw_ver
(
wl
,
WL128X_CHIP_VER
,
WL128X_IFTYPE_VER
,
WLCORE_QUIRK_AP_ZERO_SESSION_ID
;
WL128X_MAJOR_VER
,
WL128X_SUBTYPE_VER
,
WL128X_MINOR_VER
);
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
;
break
;
case
CHIP_ID_128
3
_PG10
:
case
CHIP_ID_128
X
_PG10
:
default:
default:
wl1271_warning
(
"unsupported chip id: 0x%x"
,
wl
->
chip
.
id
);
wl1271_warning
(
"unsupported chip id: 0x%x"
,
wl
->
chip
.
id
);
ret
=
-
ENODEV
;
ret
=
-
ENODEV
;
goto
out
;
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:
out:
return
ret
;
return
ret
;
}
}
...
@@ -1067,7 +1095,7 @@ static int wl12xx_pre_boot(struct wl1271 *wl)
...
@@ -1067,7 +1095,7 @@ static int wl12xx_pre_boot(struct wl1271 *wl)
u32
clk
;
u32
clk
;
int
selected_clock
=
-
1
;
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
);
ret
=
wl128x_boot_clk
(
wl
,
&
selected_clock
);
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
out
;
goto
out
;
...
@@ -1098,7 +1126,7 @@ static int wl12xx_pre_boot(struct wl1271 *wl)
...
@@ -1098,7 +1126,7 @@ static int wl12xx_pre_boot(struct wl1271 *wl)
wl1271_debug
(
DEBUG_BOOT
,
"clk2 0x%x"
,
clk
);
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
;
clk
|=
((
selected_clock
&
0x3
)
<<
1
)
<<
4
;
else
else
clk
|=
(
priv
->
ref_clock
<<
1
)
<<
4
;
clk
|=
(
priv
->
ref_clock
<<
1
)
<<
4
;
...
@@ -1152,7 +1180,7 @@ static int wl12xx_pre_upload(struct wl1271 *wl)
...
@@ -1152,7 +1180,7 @@ static int wl12xx_pre_upload(struct wl1271 *wl)
/* WL1271: The reference driver skips steps 7 to 10 (jumps directly
/* WL1271: The reference driver skips steps 7 to 10 (jumps directly
* to upload_fw) */
* 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
);
ret
=
wl12xx_top_reg_write
(
wl
,
SDIO_IO_DS
,
HCI_IO_DS_6MA
);
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
out
;
goto
out
;
...
@@ -1219,6 +1247,23 @@ static int wl12xx_boot(struct wl1271 *wl)
...
@@ -1219,6 +1247,23 @@ static int wl12xx_boot(struct wl1271 *wl)
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
out
;
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
);
ret
=
wlcore_boot_run_firmware
(
wl
);
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
out
;
goto
out
;
...
@@ -1261,7 +1306,7 @@ static void
...
@@ -1261,7 +1306,7 @@ static void
wl12xx_set_tx_desc_blocks
(
struct
wl1271
*
wl
,
struct
wl1271_tx_hw_descr
*
desc
,
wl12xx_set_tx_desc_blocks
(
struct
wl1271
*
wl
,
struct
wl1271_tx_hw_descr
*
desc
,
u32
blks
,
u32
spare_blks
)
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
;
desc
->
wl128x_mem
.
total_mem_blocks
=
blks
;
}
else
{
}
else
{
desc
->
wl127x_mem
.
extra_blocks
=
spare_blks
;
desc
->
wl127x_mem
.
extra_blocks
=
spare_blks
;
...
@@ -1275,7 +1320,7 @@ wl12xx_set_tx_desc_data_len(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
...
@@ -1275,7 +1320,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
);
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
->
wl128x_mem
.
extra_bytes
=
aligned_len
-
skb
->
len
;
desc
->
length
=
cpu_to_le16
(
aligned_len
>>
2
);
desc
->
length
=
cpu_to_le16
(
aligned_len
>>
2
);
...
@@ -1339,7 +1384,7 @@ static int wl12xx_hw_init(struct wl1271 *wl)
...
@@ -1339,7 +1384,7 @@ static int wl12xx_hw_init(struct wl1271 *wl)
{
{
int
ret
;
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
;
u32
host_cfg_bitmap
=
HOST_IF_CFG_RX_FIFO_ENABLE
;
ret
=
wl128x_cmd_general_parms
(
wl
);
ret
=
wl128x_cmd_general_parms
(
wl
);
...
@@ -1394,22 +1439,6 @@ static u32 wl12xx_sta_get_ap_rate_mask(struct wl1271 *wl,
...
@@ -1394,22 +1439,6 @@ static u32 wl12xx_sta_get_ap_rate_mask(struct wl1271 *wl,
return
wlvif
->
rate_set
;
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
)
static
void
wl12xx_conf_init
(
struct
wl1271
*
wl
)
{
{
struct
wl12xx_priv
*
priv
=
wl
->
priv
;
struct
wl12xx_priv
*
priv
=
wl
->
priv
;
...
@@ -1426,7 +1455,7 @@ static bool wl12xx_mac_in_fuse(struct wl1271 *wl)
...
@@ -1426,7 +1455,7 @@ static bool wl12xx_mac_in_fuse(struct wl1271 *wl)
bool
supported
=
false
;
bool
supported
=
false
;
u8
major
,
minor
;
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
);
major
=
WL128X_PG_GET_MAJOR
(
wl
->
hw_pg_ver
);
minor
=
WL128X_PG_GET_MINOR
(
wl
->
hw_pg_ver
);
minor
=
WL128X_PG_GET_MINOR
(
wl
->
hw_pg_ver
);
...
@@ -1482,7 +1511,7 @@ static int wl12xx_get_pg_ver(struct wl1271 *wl, s8 *ver)
...
@@ -1482,7 +1511,7 @@ static int wl12xx_get_pg_ver(struct wl1271 *wl, s8 *ver)
u16
die_info
;
u16
die_info
;
int
ret
;
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
,
ret
=
wl12xx_top_reg_read
(
wl
,
WL128X_REG_FUSE_DATA_2_1
,
&
die_info
);
&
die_info
);
else
else
...
@@ -1589,16 +1618,46 @@ static int wl12xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
...
@@ -1589,16 +1618,46 @@ static int wl12xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
return
wlcore_set_key
(
wl
,
cmd
,
vif
,
sta
,
key_conf
);
return
wlcore_set_key
(
wl
,
cmd
,
vif
,
sta
,
key_conf
);
}
}
static
int
wl12xx_set_peer_cap
(
struct
wl1271
*
wl
,
struct
ieee80211_sta_ht_cap
*
ht_cap
,
bool
allow_ht_operation
,
u32
rate_set
,
u8
hlid
)
{
return
wl1271_acx_set_ht_capabilities
(
wl
,
ht_cap
,
allow_ht_operation
,
hlid
);
}
static
bool
wl12xx_lnk_high_prio
(
struct
wl1271
*
wl
,
u8
hlid
,
struct
wl1271_link
*
lnk
)
{
u8
thold
;
if
(
test_bit
(
hlid
,
(
unsigned
long
*
)
&
wl
->
fw_fast_lnk_map
))
thold
=
wl
->
conf
.
tx
.
fast_link_thold
;
else
thold
=
wl
->
conf
.
tx
.
slow_link_thold
;
return
lnk
->
allocated_pkts
<
thold
;
}
static
bool
wl12xx_lnk_low_prio
(
struct
wl1271
*
wl
,
u8
hlid
,
struct
wl1271_link
*
lnk
)
{
/* any link is good for low priority */
return
true
;
}
static
int
wl12xx_setup
(
struct
wl1271
*
wl
);
static
int
wl12xx_setup
(
struct
wl1271
*
wl
);
static
struct
wlcore_ops
wl12xx_ops
=
{
static
struct
wlcore_ops
wl12xx_ops
=
{
.
setup
=
wl12xx_setup
,
.
setup
=
wl12xx_setup
,
.
identify_chip
=
wl12xx_identify_chip
,
.
identify_chip
=
wl12xx_identify_chip
,
.
identify_fw
=
wl12xx_identify_fw
,
.
boot
=
wl12xx_boot
,
.
boot
=
wl12xx_boot
,
.
plt_init
=
wl12xx_plt_init
,
.
plt_init
=
wl12xx_plt_init
,
.
trigger_cmd
=
wl12xx_trigger_cmd
,
.
trigger_cmd
=
wl12xx_trigger_cmd
,
.
ack_event
=
wl12xx_ack_event
,
.
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
,
.
calc_tx_blocks
=
wl12xx_calc_tx_blocks
,
.
set_tx_desc_blocks
=
wl12xx_set_tx_desc_blocks
,
.
set_tx_desc_blocks
=
wl12xx_set_tx_desc_blocks
,
.
set_tx_desc_data_len
=
wl12xx_set_tx_desc_data_len
,
.
set_tx_desc_data_len
=
wl12xx_set_tx_desc_data_len
,
...
@@ -1615,9 +1674,17 @@ static struct wlcore_ops wl12xx_ops = {
...
@@ -1615,9 +1674,17 @@ static struct wlcore_ops wl12xx_ops = {
.
set_rx_csum
=
NULL
,
.
set_rx_csum
=
NULL
,
.
ap_get_mimo_wide_rate_mask
=
NULL
,
.
ap_get_mimo_wide_rate_mask
=
NULL
,
.
debugfs_init
=
wl12xx_debugfs_add_files
,
.
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
,
.
get_spare_blocks
=
wl12xx_get_spare_blocks
,
.
set_key
=
wl12xx_set_key
,
.
set_key
=
wl12xx_set_key
,
.
channel_switch
=
wl12xx_cmd_channel_switch
,
.
pre_pkt_send
=
NULL
,
.
pre_pkt_send
=
NULL
,
.
set_peer_cap
=
wl12xx_set_peer_cap
,
.
lnk_high_prio
=
wl12xx_lnk_high_prio
,
.
lnk_low_prio
=
wl12xx_lnk_low_prio
,
};
};
static
struct
ieee80211_sta_ht_cap
wl12xx_ht_cap
=
{
static
struct
ieee80211_sta_ht_cap
wl12xx_ht_cap
=
{
...
@@ -1641,6 +1708,7 @@ static int wl12xx_setup(struct wl1271 *wl)
...
@@ -1641,6 +1708,7 @@ static int wl12xx_setup(struct wl1271 *wl)
wl
->
rtable
=
wl12xx_rtable
;
wl
->
rtable
=
wl12xx_rtable
;
wl
->
num_tx_desc
=
WL12XX_NUM_TX_DESCRIPTORS
;
wl
->
num_tx_desc
=
WL12XX_NUM_TX_DESCRIPTORS
;
wl
->
num_rx_desc
=
WL12XX_NUM_RX_DESCRIPTORS
;
wl
->
num_rx_desc
=
WL12XX_NUM_RX_DESCRIPTORS
;
wl
->
num_channels
=
1
;
wl
->
num_mac_addr
=
WL12XX_NUM_MAC_ADDRESSES
;
wl
->
num_mac_addr
=
WL12XX_NUM_MAC_ADDRESSES
;
wl
->
band_rate_to_idx
=
wl12xx_band_rate_to_idx
;
wl
->
band_rate_to_idx
=
wl12xx_band_rate_to_idx
;
wl
->
hw_tx_rate_tbl_size
=
WL12XX_CONF_HW_RXTX_RATE_MAX
;
wl
->
hw_tx_rate_tbl_size
=
WL12XX_CONF_HW_RXTX_RATE_MAX
;
...
@@ -1693,6 +1761,10 @@ static int wl12xx_setup(struct wl1271 *wl)
...
@@ -1693,6 +1761,10 @@ static int wl12xx_setup(struct wl1271 *wl)
wl1271_error
(
"Invalid tcxo parameter %s"
,
tcxo_param
);
wl1271_error
(
"Invalid tcxo parameter %s"
,
tcxo_param
);
}
}
priv
->
rx_mem_addr
=
kmalloc
(
sizeof
(
*
priv
->
rx_mem_addr
),
GFP_KERNEL
);
if
(
!
priv
->
rx_mem_addr
)
return
-
ENOMEM
;
return
0
;
return
0
;
}
}
...
@@ -1703,7 +1775,8 @@ static int wl12xx_probe(struct platform_device *pdev)
...
@@ -1703,7 +1775,8 @@ static int wl12xx_probe(struct platform_device *pdev)
int
ret
;
int
ret
;
hw
=
wlcore_alloc_hw
(
sizeof
(
struct
wl12xx_priv
),
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
))
{
if
(
IS_ERR
(
hw
))
{
wl1271_error
(
"can't allocate hw"
);
wl1271_error
(
"can't allocate hw"
);
ret
=
PTR_ERR
(
hw
);
ret
=
PTR_ERR
(
hw
);
...
@@ -1725,6 +1798,21 @@ static int wl12xx_probe(struct platform_device *pdev)
...
@@ -1725,6 +1798,21 @@ static int wl12xx_probe(struct platform_device *pdev)
return
ret
;
return
ret
;
}
}
static
int
wl12xx_remove
(
struct
platform_device
*
pdev
)
{
struct
wl1271
*
wl
=
platform_get_drvdata
(
pdev
);
struct
wl12xx_priv
*
priv
;
if
(
!
wl
)
goto
out
;
priv
=
wl
->
priv
;
kfree
(
priv
->
rx_mem_addr
);
out:
return
wlcore_remove
(
pdev
);
}
static
const
struct
platform_device_id
wl12xx_id_table
[]
=
{
static
const
struct
platform_device_id
wl12xx_id_table
[]
=
{
{
"wl12xx"
,
0
},
{
"wl12xx"
,
0
},
{
}
/* Terminating Entry */
{
}
/* Terminating Entry */
...
@@ -1733,7 +1821,7 @@ MODULE_DEVICE_TABLE(platform, wl12xx_id_table);
...
@@ -1733,7 +1821,7 @@ MODULE_DEVICE_TABLE(platform, wl12xx_id_table);
static
struct
platform_driver
wl12xx_driver
=
{
static
struct
platform_driver
wl12xx_driver
=
{
.
probe
=
wl12xx_probe
,
.
probe
=
wl12xx_probe
,
.
remove
=
wl
core
_remove
,
.
remove
=
wl
12xx
_remove
,
.
id_table
=
wl12xx_id_table
,
.
id_table
=
wl12xx_id_table
,
.
driver
=
{
.
driver
=
{
.
name
=
"wl12xx_driver"
,
.
name
=
"wl12xx_driver"
,
...
...
drivers/net/wireless/ti/wl12xx/scan.c
0 → 100644
浏览文件 @
56e1bd77
/*
* 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
浏览文件 @
56e1bd77
/*
* 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
浏览文件 @
56e1bd77
...
@@ -24,19 +24,37 @@
...
@@ -24,19 +24,37 @@
#include "conf.h"
#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_CHIP_VER 6
#define WL127X_IFTYPE_VER 3
/* minimum single-role FW version for wl127x */
#define WL127X_MAJOR_VER 10
#define WL127X_IFTYPE_SR_VER 3
#define WL127X_SUBTYPE_VER 2
#define WL127X_MAJOR_SR_VER 10
#define WL127X_MINOR_VER 115
#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_CHIP_VER 7
#define WL128X_IFTYPE_VER 3
/* minimum single-role FW version for wl128x */
#define WL128X_MAJOR_VER 10
#define WL128X_IFTYPE_SR_VER 3
#define WL128X_SUBTYPE_VER 2
#define WL128X_MAJOR_SR_VER 10
#define WL128X_MINOR_VER 115
#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)
#define WL12XX_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
...
@@ -55,6 +73,8 @@ struct wl12xx_priv {
...
@@ -55,6 +73,8 @@ struct wl12xx_priv {
int
ref_clock
;
int
ref_clock
;
int
tcxo_clock
;
int
tcxo_clock
;
struct
wl127x_rx_mem_pool_addr
*
rx_mem_addr
;
};
};
#endif
/* __WL12XX_PRIV_H__ */
#endif
/* __WL12XX_PRIV_H__ */
drivers/net/wireless/ti/wl18xx/Makefile
浏览文件 @
56e1bd77
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
obj-$(CONFIG_WL18XX)
+=
wl18xx.o
drivers/net/wireless/ti/wl18xx/acx.c
浏览文件 @
56e1bd77
...
@@ -75,7 +75,7 @@ int wl18xx_acx_set_checksum_state(struct wl1271 *wl)
...
@@ -75,7 +75,7 @@ int wl18xx_acx_set_checksum_state(struct wl1271 *wl)
acx
->
checksum_state
=
CHECKSUM_OFFLOAD_ENABLED
;
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
)
{
if
(
ret
<
0
)
{
wl1271_warning
(
"failed to set Tx checksum state: %d"
,
ret
);
wl1271_warning
(
"failed to set Tx checksum state: %d"
,
ret
);
goto
out
;
goto
out
;
...
@@ -109,3 +109,88 @@ int wl18xx_acx_clear_statistics(struct wl1271 *wl)
...
@@ -109,3 +109,88 @@ int wl18xx_acx_clear_statistics(struct wl1271 *wl)
kfree
(
acx
);
kfree
(
acx
);
return
ret
;
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
;
}
/*
* this command is basically the same as wl1271_acx_ht_capabilities,
* with the addition of supported rates. they should be unified in
* the next fw api change
*/
int
wl18xx_acx_set_peer_cap
(
struct
wl1271
*
wl
,
struct
ieee80211_sta_ht_cap
*
ht_cap
,
bool
allow_ht_operation
,
u32
rate_set
,
u8
hlid
)
{
struct
wlcore_acx_peer_cap
*
acx
;
int
ret
=
0
;
u32
ht_capabilites
=
0
;
wl1271_debug
(
DEBUG_ACX
,
"acx set cap ht_supp: %d ht_cap: %d rates: 0x%x"
,
ht_cap
->
ht_supported
,
ht_cap
->
cap
,
rate_set
);
acx
=
kzalloc
(
sizeof
(
*
acx
),
GFP_KERNEL
);
if
(
!
acx
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
if
(
allow_ht_operation
&&
ht_cap
->
ht_supported
)
{
/* no need to translate capabilities - use the spec values */
ht_capabilites
=
ht_cap
->
cap
;
/*
* this bit is not employed by the spec but only by FW to
* indicate peer HT support
*/
ht_capabilites
|=
WL12XX_HT_CAP_HT_OPERATION
;
/* get data from A-MPDU parameters field */
acx
->
ampdu_max_length
=
ht_cap
->
ampdu_factor
;
acx
->
ampdu_min_spacing
=
ht_cap
->
ampdu_density
;
}
acx
->
hlid
=
hlid
;
acx
->
ht_capabilites
=
cpu_to_le32
(
ht_capabilites
);
acx
->
supported_rates
=
cpu_to_le32
(
rate_set
);
ret
=
wl1271_cmd_configure
(
wl
,
ACX_PEER_CAP
,
acx
,
sizeof
(
*
acx
));
if
(
ret
<
0
)
{
wl1271_warning
(
"acx ht capabilities setting failed: %d"
,
ret
);
goto
out
;
}
out:
kfree
(
acx
);
return
ret
;
}
drivers/net/wireless/ti/wl18xx/acx.h
浏览文件 @
56e1bd77
...
@@ -26,7 +26,13 @@
...
@@ -26,7 +26,13 @@
#include "../wlcore/acx.h"
#include "../wlcore/acx.h"
enum
{
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) */
/* numbers of bits the length field takes (add 1 for the actual number) */
...
@@ -278,10 +284,57 @@ struct wl18xx_acx_clear_statistics {
...
@@ -278,10 +284,57 @@ struct wl18xx_acx_clear_statistics {
struct
acx_header
header
;
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
];
};
/*
* ACX_PEER_CAP
* this struct is very similar to wl1271_acx_ht_capabilities, with the
* addition of supported rates
*/
struct
wlcore_acx_peer_cap
{
struct
acx_header
header
;
/* bitmask of capability bits supported by the peer */
__le32
ht_capabilites
;
/* rates supported by the remote peer */
__le32
supported_rates
;
/* Indicates to which link these capabilities apply. */
u8
hlid
;
/*
* This the maximum A-MPDU length supported by the AP. The FW may not
* exceed this length when sending A-MPDUs
*/
u8
ampdu_max_length
;
/* This is the minimal spacing required when sending A-MPDUs to the AP*/
u8
ampdu_min_spacing
;
u8
padding
;
}
__packed
;
int
wl18xx_acx_host_if_cfg_bitmap
(
struct
wl1271
*
wl
,
u32
host_cfg_bitmap
,
int
wl18xx_acx_host_if_cfg_bitmap
(
struct
wl1271
*
wl
,
u32
host_cfg_bitmap
,
u32
sdio_blk_size
,
u32
extra_mem_blks
,
u32
sdio_blk_size
,
u32
extra_mem_blks
,
u32
len_field_size
);
u32
len_field_size
);
int
wl18xx_acx_set_checksum_state
(
struct
wl1271
*
wl
);
int
wl18xx_acx_set_checksum_state
(
struct
wl1271
*
wl
);
int
wl18xx_acx_clear_statistics
(
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
);
int
wl18xx_acx_set_peer_cap
(
struct
wl1271
*
wl
,
struct
ieee80211_sta_ht_cap
*
ht_cap
,
bool
allow_ht_operation
,
u32
rate_set
,
u8
hlid
);
#endif
/* __WL18XX_ACX_H__ */
#endif
/* __WL18XX_ACX_H__ */
drivers/net/wireless/ti/wl18xx/cmd.c
0 → 100644
浏览文件 @
56e1bd77
/*
* 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
浏览文件 @
56e1bd77
/*
* 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/conf.h
浏览文件 @
56e1bd77
...
@@ -23,20 +23,21 @@
...
@@ -23,20 +23,21 @@
#define __WL18XX_CONF_H__
#define __WL18XX_CONF_H__
#define WL18XX_CONF_MAGIC 0x10e100ca
#define WL18XX_CONF_MAGIC 0x10e100ca
#define WL18XX_CONF_VERSION (WLCORE_CONF_VERSION | 0x000
3
)
#define WL18XX_CONF_VERSION (WLCORE_CONF_VERSION | 0x000
5
)
#define WL18XX_CONF_MASK 0x0000ffff
#define WL18XX_CONF_MASK 0x0000ffff
#define WL18XX_CONF_SIZE (WLCORE_CONF_SIZE + \
#define WL18XX_CONF_SIZE (WLCORE_CONF_SIZE + \
sizeof(struct wl18xx_priv_conf))
sizeof(struct wl18xx_priv_conf))
#define NUM_OF_CHANNELS_11_ABG 150
#define NUM_OF_CHANNELS_11_ABG 150
#define NUM_OF_CHANNELS_11_P 7
#define NUM_OF_CHANNELS_11_P 7
#define WL18XX_NUM_OF_SUB_BANDS 9
#define SRF_TABLE_LEN 16
#define SRF_TABLE_LEN 16
#define PIN_MUXING_SIZE 2
#define PIN_MUXING_SIZE 2
#define WL18XX_TRACE_LOSS_GAPS_TX 10
#define WL18XX_TRACE_LOSS_GAPS_RX 18
struct
wl18xx_mac_and_phy_params
{
struct
wl18xx_mac_and_phy_params
{
u8
phy_standalone
;
u8
phy_standalone
;
u8
rdl
;
u8
spare0
;
u8
enable_clpc
;
u8
enable_clpc
;
u8
enable_tx_low_pwr_on_siso_rdl
;
u8
enable_tx_low_pwr_on_siso_rdl
;
u8
auto_detect
;
u8
auto_detect
;
...
@@ -69,18 +70,26 @@ struct wl18xx_mac_and_phy_params {
...
@@ -69,18 +70,26 @@ struct wl18xx_mac_and_phy_params {
u8
pwr_limit_reference_11_abg
;
u8
pwr_limit_reference_11_abg
;
u8
per_chan_pwr_limit_arr_11p
[
NUM_OF_CHANNELS_11_P
];
u8
per_chan_pwr_limit_arr_11p
[
NUM_OF_CHANNELS_11_P
];
u8
pwr_limit_reference_11p
;
u8
pwr_limit_reference_11p
;
u8
per_sub_band_tx_trace_loss
[
WL18XX_NUM_OF_SUB_BANDS
];
u8
spare1
[
9
];
u8
per_sub_band_rx_trace_loss
[
WL18XX_NUM_OF_SUB_BANDS
];
u8
spare2
[
9
];
u8
primary_clock_setting_time
;
u8
primary_clock_setting_time
;
u8
clock_valid_on_wake_up
;
u8
clock_valid_on_wake_up
;
u8
secondary_clock_setting_time
;
u8
secondary_clock_setting_time
;
u8
board_type
;
u8
board_type
;
/* enable point saturation */
/* enable point saturation */
u8
psat
;
u8
psat
;
/* low/medium/high Tx power in dBm */
/* low/medium/high Tx power in dBm
for STA-HP BG
*/
s8
low_power_val
;
s8
low_power_val
;
s8
med_power_val
;
s8
med_power_val
;
s8
high_power_val
;
s8
high_power_val
;
s8
per_sub_band_tx_trace_loss
[
WL18XX_TRACE_LOSS_GAPS_TX
];
s8
per_sub_band_rx_trace_loss
[
WL18XX_TRACE_LOSS_GAPS_RX
];
u8
tx_rf_margin
;
/* low/medium/high Tx power in dBm for other role */
s8
low_power_val_2nd
;
s8
med_power_val_2nd
;
s8
high_power_val_2nd
;
u8
padding
[
1
];
u8
padding
[
1
];
}
__packed
;
}
__packed
;
...
...
drivers/net/wireless/ti/wl18xx/event.c
0 → 100644
浏览文件 @
56e1bd77
/*
* 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_REPORT_EVENT_ID
)
{
wl1271_debug
(
DEBUG_EVENT
,
"PERIODIC_SCAN_REPORT_EVENT (results %d)"
,
mbox
->
number_of_sched_scan_results
);
wlcore_scan_sched_scan_results
(
wl
);
}
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
浏览文件 @
56e1bd77
/*
* 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
),
PERIODIC_SCAN_REPORT_EVENT_ID
=
BIT
(
20
),
};
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
浏览文件 @
56e1bd77
...
@@ -34,10 +34,13 @@
...
@@ -34,10 +34,13 @@
#include "reg.h"
#include "reg.h"
#include "conf.h"
#include "conf.h"
#include "cmd.h"
#include "acx.h"
#include "acx.h"
#include "tx.h"
#include "tx.h"
#include "wl18xx.h"
#include "wl18xx.h"
#include "io.h"
#include "io.h"
#include "scan.h"
#include "event.h"
#include "debugfs.h"
#include "debugfs.h"
#define WL18XX_RX_CHECKSUM_MASK 0x40
#define WL18XX_RX_CHECKSUM_MASK 0x40
...
@@ -334,6 +337,8 @@ static struct wlcore_conf wl18xx_conf = {
...
@@ -334,6 +337,8 @@ static struct wlcore_conf wl18xx_conf = {
.
tmpl_short_retry_limit
=
10
,
.
tmpl_short_retry_limit
=
10
,
.
tmpl_long_retry_limit
=
10
,
.
tmpl_long_retry_limit
=
10
,
.
tx_watchdog_timeout
=
5000
,
.
tx_watchdog_timeout
=
5000
,
.
slow_link_thold
=
3
,
.
fast_link_thold
=
30
,
},
},
.
conn
=
{
.
conn
=
{
.
wake_up_event
=
CONF_WAKE_UP_EVENT_DTIM
,
.
wake_up_event
=
CONF_WAKE_UP_EVENT_DTIM
,
...
@@ -391,8 +396,10 @@ static struct wlcore_conf wl18xx_conf = {
...
@@ -391,8 +396,10 @@ static struct wlcore_conf wl18xx_conf = {
.
scan
=
{
.
scan
=
{
.
min_dwell_time_active
=
7500
,
.
min_dwell_time_active
=
7500
,
.
max_dwell_time_active
=
30000
,
.
max_dwell_time_active
=
30000
,
.
min_dwell_time_passive
=
100000
,
.
min_dwell_time_active_long
=
25000
,
.
max_dwell_time_passive
=
100000
,
.
max_dwell_time_active_long
=
50000
,
.
dwell_time_passive
=
100000
,
.
dwell_time_dfs
=
150000
,
.
num_probe_reqs
=
2
,
.
num_probe_reqs
=
2
,
.
split_scan_timeout
=
50000
,
.
split_scan_timeout
=
50000
,
},
},
...
@@ -489,6 +496,10 @@ static struct wlcore_conf wl18xx_conf = {
...
@@ -489,6 +496,10 @@ static struct wlcore_conf wl18xx_conf = {
.
increase_time
=
1
,
.
increase_time
=
1
,
.
window_size
=
16
,
.
window_size
=
16
,
},
},
.
recovery
=
{
.
bug_on_recovery
=
0
,
.
no_recovery
=
0
,
},
};
};
static
struct
wl18xx_priv_conf
wl18xx_default_priv_conf
=
{
static
struct
wl18xx_priv_conf
wl18xx_default_priv_conf
=
{
...
@@ -501,7 +512,6 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = {
...
@@ -501,7 +512,6 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = {
.
clock_valid_on_wake_up
=
0x00
,
.
clock_valid_on_wake_up
=
0x00
,
.
secondary_clock_setting_time
=
0x05
,
.
secondary_clock_setting_time
=
0x05
,
.
board_type
=
BOARD_TYPE_HDK_18XX
,
.
board_type
=
BOARD_TYPE_HDK_18XX
,
.
rdl
=
0x01
,
.
auto_detect
=
0x00
,
.
auto_detect
=
0x00
,
.
dedicated_fem
=
FEM_NONE
,
.
dedicated_fem
=
FEM_NONE
,
.
low_band_component
=
COMPONENT_3_WAY_SWITCH
,
.
low_band_component
=
COMPONENT_3_WAY_SWITCH
,
...
@@ -517,14 +527,39 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = {
...
@@ -517,14 +527,39 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = {
.
enable_clpc
=
0x00
,
.
enable_clpc
=
0x00
,
.
enable_tx_low_pwr_on_siso_rdl
=
0x00
,
.
enable_tx_low_pwr_on_siso_rdl
=
0x00
,
.
rx_profile
=
0x00
,
.
rx_profile
=
0x00
,
.
pwr_limit_reference_11_abg
=
0xc8
,
.
pwr_limit_reference_11_abg
=
0x64
,
.
per_chan_pwr_limit_arr_11abg
=
{
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
},
.
pwr_limit_reference_11p
=
0x64
,
.
per_chan_pwr_limit_arr_11p
=
{
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
},
.
psat
=
0
,
.
psat
=
0
,
.
low_power_val
=
0x00
,
.
low_power_val
=
0x08
,
.
med_power_val
=
0x0a
,
.
med_power_val
=
0x12
,
.
high_power_val
=
0x1e
,
.
high_power_val
=
0x18
,
.
low_power_val_2nd
=
0x05
,
.
med_power_val_2nd
=
0x0a
,
.
high_power_val_2nd
=
0x14
,
.
external_pa_dc2dc
=
0
,
.
external_pa_dc2dc
=
0
,
.
number_of_assembled_ant2_4
=
1
,
.
number_of_assembled_ant2_4
=
2
,
.
number_of_assembled_ant5
=
1
,
.
number_of_assembled_ant5
=
1
,
.
tx_rf_margin
=
1
,
},
},
};
};
...
@@ -595,7 +630,7 @@ static const struct wl18xx_clk_cfg wl18xx_clk_table[NUM_CLOCK_CONFIGS] = {
...
@@ -595,7 +630,7 @@ static const struct wl18xx_clk_cfg wl18xx_clk_table[NUM_CLOCK_CONFIGS] = {
};
};
/* TODO: maybe move to a new header file? */
/* 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
)
static
int
wl18xx_identify_chip
(
struct
wl1271
*
wl
)
{
{
...
@@ -608,15 +643,18 @@ static int wl18xx_identify_chip(struct wl1271 *wl)
...
@@ -608,15 +643,18 @@ static int wl18xx_identify_chip(struct wl1271 *wl)
wl
->
sr_fw_name
=
WL18XX_FW_NAME
;
wl
->
sr_fw_name
=
WL18XX_FW_NAME
;
/* wl18xx uses the same firmware for PLT */
/* wl18xx uses the same firmware for PLT */
wl
->
plt_fw_name
=
WL18XX_FW_NAME
;
wl
->
plt_fw_name
=
WL18XX_FW_NAME
;
wl
->
quirks
|=
WLCORE_QUIRK_NO_ELP
|
wl
->
quirks
|=
WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN
|
WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN
|
WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN
|
WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN
|
WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN
|
WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN
|
WLCORE_QUIRK_TX_PAD_LAST_FRAME
;
WLCORE_QUIRK_TX_PAD_LAST_FRAME
|
WLCORE_QUIRK_REGDOMAIN_CONF
|
wlcore_set_min_fw_ver
(
wl
,
WL18XX_CHIP_VER
,
WL18XX_IFTYPE_VER
,
WLCORE_QUIRK_DUAL_PROBE_TMPL
;
WL18XX_MAJOR_VER
,
WL18XX_SUBTYPE_VER
,
WL18XX_MINOR_VER
);
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
;
break
;
case
CHIP_ID_185x_PG10
:
case
CHIP_ID_185x_PG10
:
wl1271_warning
(
"chip id 0x%x (185x PG10) is deprecated"
,
wl1271_warning
(
"chip id 0x%x (185x PG10) is deprecated"
,
...
@@ -630,6 +668,11 @@ static int wl18xx_identify_chip(struct wl1271 *wl)
...
@@ -630,6 +668,11 @@ static int wl18xx_identify_chip(struct wl1271 *wl)
goto
out
;
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:
out:
return
ret
;
return
ret
;
}
}
...
@@ -843,6 +886,20 @@ static int wl18xx_boot(struct wl1271 *wl)
...
@@ -843,6 +886,20 @@ static int wl18xx_boot(struct wl1271 *wl)
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
out
;
goto
out
;
wl
->
event_mask
=
BSS_LOSS_EVENT_ID
|
SCAN_COMPLETE_EVENT_ID
|
RSSI_SNR_TRIGGER_0_EVENT_ID
|
PERIODIC_SCAN_COMPLETE_EVENT_ID
|
PERIODIC_SCAN_REPORT_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
);
ret
=
wlcore_boot_run_firmware
(
wl
);
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
out
;
goto
out
;
...
@@ -964,7 +1021,7 @@ static int wl18xx_hw_init(struct wl1271 *wl)
...
@@ -964,7 +1021,7 @@ static int wl18xx_hw_init(struct wl1271 *wl)
/* (re)init private structures. Relevant on recovery as well. */
/* (re)init private structures. Relevant on recovery as well. */
priv
->
last_fw_rls_idx
=
0
;
priv
->
last_fw_rls_idx
=
0
;
priv
->
extra_spare_
vif
_count
=
0
;
priv
->
extra_spare_
key
_count
=
0
;
/* set the default amount of spare blocks in the bitmap */
/* set the default amount of spare blocks in the bitmap */
ret
=
wl18xx_set_host_cfg_bitmap
(
wl
,
WL18XX_TX_HW_BLOCK_SPARE
);
ret
=
wl18xx_set_host_cfg_bitmap
(
wl
,
WL18XX_TX_HW_BLOCK_SPARE
);
...
@@ -1022,7 +1079,12 @@ static bool wl18xx_is_mimo_supported(struct wl1271 *wl)
...
@@ -1022,7 +1079,12 @@ static bool wl18xx_is_mimo_supported(struct wl1271 *wl)
{
{
struct
wl18xx_priv
*
priv
=
wl
->
priv
;
struct
wl18xx_priv
*
priv
=
wl
->
priv
;
return
priv
->
conf
.
phy
.
number_of_assembled_ant2_4
>=
2
;
/* only support MIMO with multiple antennas, and when SISO
* is not forced through config
*/
return
(
priv
->
conf
.
phy
.
number_of_assembled_ant2_4
>=
2
)
&&
(
priv
->
conf
.
ht
.
mode
!=
HT_MODE_WIDE
)
&&
(
priv
->
conf
.
ht
.
mode
!=
HT_MODE_SISO20
);
}
}
/*
/*
...
@@ -1223,8 +1285,8 @@ static int wl18xx_get_spare_blocks(struct wl1271 *wl, bool is_gem)
...
@@ -1223,8 +1285,8 @@ static int wl18xx_get_spare_blocks(struct wl1271 *wl, bool is_gem)
{
{
struct
wl18xx_priv
*
priv
=
wl
->
priv
;
struct
wl18xx_priv
*
priv
=
wl
->
priv
;
/* If we have
VIF
s requiring extra spare, indulge them */
/* If we have
key
s requiring extra spare, indulge them */
if
(
priv
->
extra_spare_
vif
_count
)
if
(
priv
->
extra_spare_
key
_count
)
return
WL18XX_TX_HW_EXTRA_BLOCK_SPARE
;
return
WL18XX_TX_HW_EXTRA_BLOCK_SPARE
;
return
WL18XX_TX_HW_BLOCK_SPARE
;
return
WL18XX_TX_HW_BLOCK_SPARE
;
...
@@ -1236,42 +1298,48 @@ static int wl18xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
...
@@ -1236,42 +1298,48 @@ static int wl18xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
struct
ieee80211_key_conf
*
key_conf
)
struct
ieee80211_key_conf
*
key_conf
)
{
{
struct
wl18xx_priv
*
priv
=
wl
->
priv
;
struct
wl18xx_priv
*
priv
=
wl
->
priv
;
bool
change_spare
=
false
;
bool
change_spare
=
false
,
special_enc
;
int
ret
;
int
ret
;
wl1271_debug
(
DEBUG_CRYPT
,
"extra spare keys before: %d"
,
priv
->
extra_spare_key_count
);
special_enc
=
key_conf
->
cipher
==
WL1271_CIPHER_SUITE_GEM
||
key_conf
->
cipher
==
WLAN_CIPHER_SUITE_TKIP
;
ret
=
wlcore_set_key
(
wl
,
cmd
,
vif
,
sta
,
key_conf
);
if
(
ret
<
0
)
goto
out
;
/*
/*
* when adding the first or removing the last GEM/TKIP
interface
,
* when adding the first or removing the last GEM/TKIP
key
,
* we have to adjust the number of spare blocks.
* we have to adjust the number of spare blocks.
*/
*/
change_spare
=
(
key_conf
->
cipher
==
WL1271_CIPHER_SUITE_GEM
||
if
(
special_enc
)
{
key_conf
->
cipher
==
WLAN_CIPHER_SUITE_TKIP
)
&&
if
(
cmd
==
SET_KEY
)
{
((
priv
->
extra_spare_vif_count
==
0
&&
cmd
==
SET_KEY
)
||
/* first key */
(
priv
->
extra_spare_vif_count
==
1
&&
cmd
==
DISABLE_KEY
));
change_spare
=
(
priv
->
extra_spare_key_count
==
0
);
priv
->
extra_spare_key_count
++
;
}
else
if
(
cmd
==
DISABLE_KEY
)
{
/* last key */
change_spare
=
(
priv
->
extra_spare_key_count
==
1
);
priv
->
extra_spare_key_count
--
;
}
}
/* no need to change spare - just regular set_key */
wl1271_debug
(
DEBUG_CRYPT
,
"extra spare keys after: %d"
,
if
(
!
change_spare
)
priv
->
extra_spare_key_count
);
return
wlcore_set_key
(
wl
,
cmd
,
vif
,
sta
,
key_conf
);
ret
=
wlcore_set_key
(
wl
,
cmd
,
vif
,
sta
,
key_conf
);
if
(
!
change_spare
)
if
(
ret
<
0
)
goto
out
;
goto
out
;
/* key is now set, change the spare blocks */
/* key is now set, change the spare blocks */
if
(
cmd
==
SET_KEY
)
{
if
(
priv
->
extra_spare_key_count
)
ret
=
wl18xx_set_host_cfg_bitmap
(
wl
,
ret
=
wl18xx_set_host_cfg_bitmap
(
wl
,
WL18XX_TX_HW_EXTRA_BLOCK_SPARE
);
WL18XX_TX_HW_EXTRA_BLOCK_SPARE
);
if
(
ret
<
0
)
else
goto
out
;
priv
->
extra_spare_vif_count
++
;
}
else
{
ret
=
wl18xx_set_host_cfg_bitmap
(
wl
,
ret
=
wl18xx_set_host_cfg_bitmap
(
wl
,
WL18XX_TX_HW_BLOCK_SPARE
);
WL18XX_TX_HW_BLOCK_SPARE
);
if
(
ret
<
0
)
goto
out
;
priv
->
extra_spare_vif_count
--
;
}
out:
out:
return
ret
;
return
ret
;
...
@@ -1296,6 +1364,92 @@ static u32 wl18xx_pre_pkt_send(struct wl1271 *wl,
...
@@ -1296,6 +1364,92 @@ static u32 wl18xx_pre_pkt_send(struct wl1271 *wl,
return
buf_offset
;
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_set_peer_cap
(
struct
wl1271
*
wl
,
struct
ieee80211_sta_ht_cap
*
ht_cap
,
bool
allow_ht_operation
,
u32
rate_set
,
u8
hlid
)
{
return
wl18xx_acx_set_peer_cap
(
wl
,
ht_cap
,
allow_ht_operation
,
rate_set
,
hlid
);
}
static
bool
wl18xx_lnk_high_prio
(
struct
wl1271
*
wl
,
u8
hlid
,
struct
wl1271_link
*
lnk
)
{
u8
thold
;
struct
wl18xx_fw_status_priv
*
status_priv
=
(
struct
wl18xx_fw_status_priv
*
)
wl
->
fw_status_2
->
priv
;
u32
suspend_bitmap
=
le32_to_cpu
(
status_priv
->
link_suspend_bitmap
);
/* suspended links are never high priority */
if
(
test_bit
(
hlid
,
(
unsigned
long
*
)
&
suspend_bitmap
))
return
false
;
/* the priority thresholds are taken from FW */
if
(
test_bit
(
hlid
,
(
unsigned
long
*
)
&
wl
->
fw_fast_lnk_map
)
&&
!
test_bit
(
hlid
,
(
unsigned
long
*
)
&
wl
->
ap_fw_ps_map
))
thold
=
status_priv
->
tx_fast_link_prio_threshold
;
else
thold
=
status_priv
->
tx_slow_link_prio_threshold
;
return
lnk
->
allocated_pkts
<
thold
;
}
static
bool
wl18xx_lnk_low_prio
(
struct
wl1271
*
wl
,
u8
hlid
,
struct
wl1271_link
*
lnk
)
{
u8
thold
;
struct
wl18xx_fw_status_priv
*
status_priv
=
(
struct
wl18xx_fw_status_priv
*
)
wl
->
fw_status_2
->
priv
;
u32
suspend_bitmap
=
le32_to_cpu
(
status_priv
->
link_suspend_bitmap
);
if
(
test_bit
(
hlid
,
(
unsigned
long
*
)
&
suspend_bitmap
))
thold
=
status_priv
->
tx_suspend_threshold
;
else
if
(
test_bit
(
hlid
,
(
unsigned
long
*
)
&
wl
->
fw_fast_lnk_map
)
&&
!
test_bit
(
hlid
,
(
unsigned
long
*
)
&
wl
->
ap_fw_ps_map
))
thold
=
status_priv
->
tx_fast_stop_threshold
;
else
thold
=
status_priv
->
tx_slow_stop_threshold
;
return
lnk
->
allocated_pkts
<
thold
;
}
static
int
wl18xx_setup
(
struct
wl1271
*
wl
);
static
int
wl18xx_setup
(
struct
wl1271
*
wl
);
static
struct
wlcore_ops
wl18xx_ops
=
{
static
struct
wlcore_ops
wl18xx_ops
=
{
...
@@ -1305,6 +1459,8 @@ static struct wlcore_ops wl18xx_ops = {
...
@@ -1305,6 +1459,8 @@ static struct wlcore_ops wl18xx_ops = {
.
plt_init
=
wl18xx_plt_init
,
.
plt_init
=
wl18xx_plt_init
,
.
trigger_cmd
=
wl18xx_trigger_cmd
,
.
trigger_cmd
=
wl18xx_trigger_cmd
,
.
ack_event
=
wl18xx_ack_event
,
.
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
,
.
calc_tx_blocks
=
wl18xx_calc_tx_blocks
,
.
set_tx_desc_blocks
=
wl18xx_set_tx_desc_blocks
,
.
set_tx_desc_blocks
=
wl18xx_set_tx_desc_blocks
,
.
set_tx_desc_data_len
=
wl18xx_set_tx_desc_data_len
,
.
set_tx_desc_data_len
=
wl18xx_set_tx_desc_data_len
,
...
@@ -1320,16 +1476,26 @@ static struct wlcore_ops wl18xx_ops = {
...
@@ -1320,16 +1476,26 @@ static struct wlcore_ops wl18xx_ops = {
.
ap_get_mimo_wide_rate_mask
=
wl18xx_ap_get_mimo_wide_rate_mask
,
.
ap_get_mimo_wide_rate_mask
=
wl18xx_ap_get_mimo_wide_rate_mask
,
.
get_mac
=
wl18xx_get_mac
,
.
get_mac
=
wl18xx_get_mac
,
.
debugfs_init
=
wl18xx_debugfs_add_files
,
.
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
,
.
handle_static_data
=
wl18xx_handle_static_data
,
.
get_spare_blocks
=
wl18xx_get_spare_blocks
,
.
get_spare_blocks
=
wl18xx_get_spare_blocks
,
.
set_key
=
wl18xx_set_key
,
.
set_key
=
wl18xx_set_key
,
.
channel_switch
=
wl18xx_cmd_channel_switch
,
.
pre_pkt_send
=
wl18xx_pre_pkt_send
,
.
pre_pkt_send
=
wl18xx_pre_pkt_send
,
.
sta_rc_update
=
wl18xx_sta_rc_update
,
.
set_peer_cap
=
wl18xx_set_peer_cap
,
.
lnk_high_prio
=
wl18xx_lnk_high_prio
,
.
lnk_low_prio
=
wl18xx_lnk_low_prio
,
};
};
/* HT cap appropriate for wide channels in 2Ghz */
/* HT cap appropriate for wide channels in 2Ghz */
static
struct
ieee80211_sta_ht_cap
wl18xx_siso40_ht_cap_2ghz
=
{
static
struct
ieee80211_sta_ht_cap
wl18xx_siso40_ht_cap_2ghz
=
{
.
cap
=
IEEE80211_HT_CAP_SGI_20
|
IEEE80211_HT_CAP_SGI_40
|
.
cap
=
IEEE80211_HT_CAP_SGI_20
|
IEEE80211_HT_CAP_SGI_40
|
IEEE80211_HT_CAP_SUP_WIDTH_20_40
|
IEEE80211_HT_CAP_DSSSCCK40
,
IEEE80211_HT_CAP_SUP_WIDTH_20_40
|
IEEE80211_HT_CAP_DSSSCCK40
|
IEEE80211_HT_CAP_GRN_FLD
,
.
ht_supported
=
true
,
.
ht_supported
=
true
,
.
ampdu_factor
=
IEEE80211_HT_MAX_AMPDU_16K
,
.
ampdu_factor
=
IEEE80211_HT_MAX_AMPDU_16K
,
.
ampdu_density
=
IEEE80211_HT_MPDU_DENSITY_16
,
.
ampdu_density
=
IEEE80211_HT_MPDU_DENSITY_16
,
...
@@ -1343,7 +1509,8 @@ static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_2ghz = {
...
@@ -1343,7 +1509,8 @@ static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_2ghz = {
/* HT cap appropriate for wide channels in 5Ghz */
/* HT cap appropriate for wide channels in 5Ghz */
static
struct
ieee80211_sta_ht_cap
wl18xx_siso40_ht_cap_5ghz
=
{
static
struct
ieee80211_sta_ht_cap
wl18xx_siso40_ht_cap_5ghz
=
{
.
cap
=
IEEE80211_HT_CAP_SGI_20
|
IEEE80211_HT_CAP_SGI_40
|
.
cap
=
IEEE80211_HT_CAP_SGI_20
|
IEEE80211_HT_CAP_SGI_40
|
IEEE80211_HT_CAP_SUP_WIDTH_20_40
,
IEEE80211_HT_CAP_SUP_WIDTH_20_40
|
IEEE80211_HT_CAP_GRN_FLD
,
.
ht_supported
=
true
,
.
ht_supported
=
true
,
.
ampdu_factor
=
IEEE80211_HT_MAX_AMPDU_16K
,
.
ampdu_factor
=
IEEE80211_HT_MAX_AMPDU_16K
,
.
ampdu_density
=
IEEE80211_HT_MPDU_DENSITY_16
,
.
ampdu_density
=
IEEE80211_HT_MPDU_DENSITY_16
,
...
@@ -1356,7 +1523,8 @@ static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_5ghz = {
...
@@ -1356,7 +1523,8 @@ static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_5ghz = {
/* HT cap appropriate for SISO 20 */
/* HT cap appropriate for SISO 20 */
static
struct
ieee80211_sta_ht_cap
wl18xx_siso20_ht_cap
=
{
static
struct
ieee80211_sta_ht_cap
wl18xx_siso20_ht_cap
=
{
.
cap
=
IEEE80211_HT_CAP_SGI_20
,
.
cap
=
IEEE80211_HT_CAP_SGI_20
|
IEEE80211_HT_CAP_GRN_FLD
,
.
ht_supported
=
true
,
.
ht_supported
=
true
,
.
ampdu_factor
=
IEEE80211_HT_MAX_AMPDU_16K
,
.
ampdu_factor
=
IEEE80211_HT_MAX_AMPDU_16K
,
.
ampdu_density
=
IEEE80211_HT_MPDU_DENSITY_16
,
.
ampdu_density
=
IEEE80211_HT_MPDU_DENSITY_16
,
...
@@ -1369,7 +1537,8 @@ static struct ieee80211_sta_ht_cap wl18xx_siso20_ht_cap = {
...
@@ -1369,7 +1537,8 @@ static struct ieee80211_sta_ht_cap wl18xx_siso20_ht_cap = {
/* HT cap appropriate for MIMO rates in 20mhz channel */
/* HT cap appropriate for MIMO rates in 20mhz channel */
static
struct
ieee80211_sta_ht_cap
wl18xx_mimo_ht_cap_2ghz
=
{
static
struct
ieee80211_sta_ht_cap
wl18xx_mimo_ht_cap_2ghz
=
{
.
cap
=
IEEE80211_HT_CAP_SGI_20
,
.
cap
=
IEEE80211_HT_CAP_SGI_20
|
IEEE80211_HT_CAP_GRN_FLD
,
.
ht_supported
=
true
,
.
ht_supported
=
true
,
.
ampdu_factor
=
IEEE80211_HT_MAX_AMPDU_16K
,
.
ampdu_factor
=
IEEE80211_HT_MAX_AMPDU_16K
,
.
ampdu_density
=
IEEE80211_HT_MPDU_DENSITY_16
,
.
ampdu_density
=
IEEE80211_HT_MPDU_DENSITY_16
,
...
@@ -1387,7 +1556,8 @@ static int wl18xx_setup(struct wl1271 *wl)
...
@@ -1387,7 +1556,8 @@ static int wl18xx_setup(struct wl1271 *wl)
wl
->
rtable
=
wl18xx_rtable
;
wl
->
rtable
=
wl18xx_rtable
;
wl
->
num_tx_desc
=
WL18XX_NUM_TX_DESCRIPTORS
;
wl
->
num_tx_desc
=
WL18XX_NUM_TX_DESCRIPTORS
;
wl
->
num_rx_desc
=
WL18XX_NUM_TX_DESCRIPTORS
;
wl
->
num_rx_desc
=
WL18XX_NUM_RX_DESCRIPTORS
;
wl
->
num_channels
=
2
;
wl
->
num_mac_addr
=
WL18XX_NUM_MAC_ADDRESSES
;
wl
->
num_mac_addr
=
WL18XX_NUM_MAC_ADDRESSES
;
wl
->
band_rate_to_idx
=
wl18xx_band_rate_to_idx
;
wl
->
band_rate_to_idx
=
wl18xx_band_rate_to_idx
;
wl
->
hw_tx_rate_tbl_size
=
WL18XX_CONF_HW_RXTX_RATE_MAX
;
wl
->
hw_tx_rate_tbl_size
=
WL18XX_CONF_HW_RXTX_RATE_MAX
;
...
@@ -1506,7 +1676,8 @@ static int wl18xx_probe(struct platform_device *pdev)
...
@@ -1506,7 +1676,8 @@ static int wl18xx_probe(struct platform_device *pdev)
int
ret
;
int
ret
;
hw
=
wlcore_alloc_hw
(
sizeof
(
struct
wl18xx_priv
),
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
))
{
if
(
IS_ERR
(
hw
))
{
wl1271_error
(
"can't allocate hw"
);
wl1271_error
(
"can't allocate hw"
);
ret
=
PTR_ERR
(
hw
);
ret
=
PTR_ERR
(
hw
);
...
...
drivers/net/wireless/ti/wl18xx/scan.c
0 → 100644
浏览文件 @
56e1bd77
/*
* 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
?
req
->
ssids
[
0
].
ssid
:
NULL
,
req
->
ssids
?
req
->
ssids
[
0
].
ssid_len
:
0
,
req
->
ie
,
req
->
ie_len
,
false
);
if
(
ret
<
0
)
{
wl1271_error
(
"2.4GHz PROBE request template failed"
);
goto
out
;
}
}
if
(
cmd
->
active
[
1
]
||
cmd
->
dfs
)
{
u8
band
=
IEEE80211_BAND_5GHZ
;
ret
=
wl12xx_cmd_build_probe_req
(
wl
,
wlvif
,
cmd
->
role_id
,
band
,
req
->
ssids
?
req
->
ssids
[
0
].
ssid
:
NULL
,
req
->
ssids
?
req
->
ssids
[
0
].
ssid_len
:
0
,
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
;
/* create a PERIODIC_SCAN_REPORT_EVENT whenever we've got a match */
cmd
->
report_threshold
=
1
;
cmd
->
terminate_on_report
=
0
;
if
(
cmd
->
active
[
0
])
{
u8
band
=
IEEE80211_BAND_2GHZ
;
ret
=
wl12xx_cmd_build_probe_req
(
wl
,
wlvif
,
cmd
->
role_id
,
band
,
req
->
ssids
?
req
->
ssids
[
0
].
ssid
:
NULL
,
req
->
ssids
?
req
->
ssids
[
0
].
ssid_len
:
0
,
ies
->
ie
[
band
],
ies
->
len
[
band
],
true
);
if
(
ret
<
0
)
{
wl1271_error
(
"2.4GHz PROBE request template failed"
);
goto
out
;
}
}
if
(
cmd
->
active
[
1
]
||
cmd
->
dfs
)
{
u8
band
=
IEEE80211_BAND_5GHZ
;
ret
=
wl12xx_cmd_build_probe_req
(
wl
,
wlvif
,
cmd
->
role_id
,
band
,
req
->
ssids
?
req
->
ssids
[
0
].
ssid
:
NULL
,
req
->
ssids
?
req
->
ssids
[
0
].
ssid_len
:
0
,
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
浏览文件 @
56e1bd77
/*
* 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
padding
[
2
];
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
rate
;
/* send SCAN_REPORT_EVENT in periodic scans after each cycle
* if number of results >= report_threshold. Must be 0 for
* non periodic scans
*/
u8
report_threshold
;
/* Should periodic scan stop after a report event was created.
* Must be 0 for non periodic scans.
*/
u8
terminate_on_report
;
u8
padding1
[
3
];
}
__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/tx.c
浏览文件 @
56e1bd77
...
@@ -28,6 +28,49 @@
...
@@ -28,6 +28,49 @@
#include "wl18xx.h"
#include "wl18xx.h"
#include "tx.h"
#include "tx.h"
static
void
wl18xx_get_last_tx_rate
(
struct
wl1271
*
wl
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_tx_rate
*
rate
)
{
u8
fw_rate
=
wl
->
fw_status_2
->
counters
.
tx_last_rate
;
if
(
fw_rate
>
CONF_HW_RATE_INDEX_MAX
)
{
wl1271_error
(
"last Tx rate invalid: %d"
,
fw_rate
);
rate
->
idx
=
0
;
rate
->
flags
=
0
;
return
;
}
if
(
fw_rate
<=
CONF_HW_RATE_INDEX_54MBPS
)
{
rate
->
idx
=
fw_rate
;
rate
->
flags
=
0
;
}
else
{
rate
->
flags
=
IEEE80211_TX_RC_MCS
;
rate
->
idx
=
fw_rate
-
CONF_HW_RATE_INDEX_MCS0
;
/* SGI modifier is counted as a separate rate */
if
(
fw_rate
>=
CONF_HW_RATE_INDEX_MCS7_SGI
)
(
rate
->
idx
)
--
;
if
(
fw_rate
==
CONF_HW_RATE_INDEX_MCS15_SGI
)
(
rate
->
idx
)
--
;
/* this also covers the 40Mhz SGI case (= MCS15) */
if
(
fw_rate
==
CONF_HW_RATE_INDEX_MCS7_SGI
||
fw_rate
==
CONF_HW_RATE_INDEX_MCS15_SGI
)
rate
->
flags
|=
IEEE80211_TX_RC_SHORT_GI
;
if
(
fw_rate
>
CONF_HW_RATE_INDEX_MCS7_SGI
&&
vif
)
{
struct
wl12xx_vif
*
wlvif
=
wl12xx_vif_to_data
(
vif
);
if
(
wlvif
->
channel_type
==
NL80211_CHAN_HT40MINUS
||
wlvif
->
channel_type
==
NL80211_CHAN_HT40PLUS
)
{
/* adjustment needed for range 0-7 */
rate
->
idx
-=
8
;
rate
->
flags
|=
IEEE80211_TX_RC_40_MHZ_WIDTH
;
}
}
}
}
static
void
wl18xx_tx_complete_packet
(
struct
wl1271
*
wl
,
u8
tx_stat_byte
)
static
void
wl18xx_tx_complete_packet
(
struct
wl1271
*
wl
,
u8
tx_stat_byte
)
{
{
struct
ieee80211_tx_info
*
info
;
struct
ieee80211_tx_info
*
info
;
...
@@ -44,7 +87,6 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte)
...
@@ -44,7 +87,6 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte)
/* a zero bit indicates Tx success */
/* a zero bit indicates Tx success */
tx_success
=
!
(
tx_stat_byte
&
BIT
(
WL18XX_TX_STATUS_STAT_BIT_IDX
));
tx_success
=
!
(
tx_stat_byte
&
BIT
(
WL18XX_TX_STATUS_STAT_BIT_IDX
));
skb
=
wl
->
tx_frames
[
id
];
skb
=
wl
->
tx_frames
[
id
];
info
=
IEEE80211_SKB_CB
(
skb
);
info
=
IEEE80211_SKB_CB
(
skb
);
...
@@ -56,11 +98,13 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte)
...
@@ -56,11 +98,13 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte)
/* update the TX status info */
/* update the TX status info */
if
(
tx_success
&&
!
(
info
->
flags
&
IEEE80211_TX_CTL_NO_ACK
))
if
(
tx_success
&&
!
(
info
->
flags
&
IEEE80211_TX_CTL_NO_ACK
))
info
->
flags
|=
IEEE80211_TX_STAT_ACK
;
info
->
flags
|=
IEEE80211_TX_STAT_ACK
;
/*
* first pass info->control.vif while it's valid, and then fill out
* the info->status structures
*/
wl18xx_get_last_tx_rate
(
wl
,
info
->
control
.
vif
,
&
info
->
status
.
rates
[
0
]);
/* no real data about Tx completion */
info
->
status
.
rates
[
0
].
count
=
1
;
/* no data about retries */
info
->
status
.
rates
[
0
].
idx
=
-
1
;
info
->
status
.
rates
[
0
].
count
=
0
;
info
->
status
.
rates
[
0
].
flags
=
0
;
info
->
status
.
ack_signal
=
-
1
;
info
->
status
.
ack_signal
=
-
1
;
if
(
!
tx_success
)
if
(
!
tx_success
)
...
...
drivers/net/wireless/ti/wl18xx/wl18xx.h
浏览文件 @
56e1bd77
...
@@ -26,10 +26,10 @@
...
@@ -26,10 +26,10 @@
/* minimum FW required for driver */
/* minimum FW required for driver */
#define WL18XX_CHIP_VER 8
#define WL18XX_CHIP_VER 8
#define WL18XX_IFTYPE_VER
2
#define WL18XX_IFTYPE_VER
5
#define WL18XX_MAJOR_VER
0
#define WL18XX_MAJOR_VER
WLCORE_FW_VER_IGNORE
#define WL18XX_SUBTYPE_VER
0
#define WL18XX_SUBTYPE_VER
WLCORE_FW_VER_IGNORE
#define WL18XX_MINOR_VER
100
#define WL18XX_MINOR_VER
28
#define WL18XX_CMD_MAX_SIZE 740
#define WL18XX_CMD_MAX_SIZE 740
...
@@ -49,8 +49,8 @@ struct wl18xx_priv {
...
@@ -49,8 +49,8 @@ struct wl18xx_priv {
/* Index of last released Tx desc in FW */
/* Index of last released Tx desc in FW */
u8
last_fw_rls_idx
;
u8
last_fw_rls_idx
;
/* number of
VIF
s requiring extra spare mem-blocks */
/* number of
key
s requiring extra spare mem-blocks */
int
extra_spare_
vif
_count
;
int
extra_spare_
key
_count
;
};
};
#define WL18XX_FW_MAX_TX_STATUS_DESC 33
#define WL18XX_FW_MAX_TX_STATUS_DESC 33
...
@@ -68,7 +68,43 @@ struct wl18xx_fw_status_priv {
...
@@ -68,7 +68,43 @@ struct wl18xx_fw_status_priv {
*/
*/
u8
released_tx_desc
[
WL18XX_FW_MAX_TX_STATUS_DESC
];
u8
released_tx_desc
[
WL18XX_FW_MAX_TX_STATUS_DESC
];
u8
padding
[
2
];
/* A bitmap representing the currently suspended links. The suspend
* is short lived, for multi-channel Tx requirements.
*/
__le32
link_suspend_bitmap
;
/* packet threshold for an "almost empty" AC,
* for Tx schedulng purposes
*/
u8
tx_ac_threshold
;
/* number of packets to queue up for a link in PS */
u8
tx_ps_threshold
;
/* number of packet to queue up for a suspended link */
u8
tx_suspend_threshold
;
/* Should have less than this number of packets in queue of a slow
* link to qualify as high priority link
*/
u8
tx_slow_link_prio_threshold
;
/* Should have less than this number of packets in queue of a fast
* link to qualify as high priority link
*/
u8
tx_fast_link_prio_threshold
;
/* Should have less than this number of packets in queue of a slow
* link before we stop queuing up packets for it.
*/
u8
tx_slow_stop_threshold
;
/* Should have less than this number of packets in queue of a fast
* link before we stop queuing up packets for it.
*/
u8
tx_fast_stop_threshold
;
u8
padding
[
3
];
};
};
#define WL18XX_PHY_VERSION_MAX_LEN 20
#define WL18XX_PHY_VERSION_MAX_LEN 20
...
...
drivers/net/wireless/ti/wlcore/acx.c
浏览文件 @
56e1bd77
...
@@ -1340,6 +1340,8 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
...
@@ -1340,6 +1340,8 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
kfree
(
acx
);
kfree
(
acx
);
return
ret
;
return
ret
;
}
}
EXPORT_SYMBOL_GPL
(
wl1271_acx_set_ht_capabilities
);
int
wl1271_acx_set_ht_information
(
struct
wl1271
*
wl
,
int
wl1271_acx_set_ht_information
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
wl12xx_vif
*
wlvif
,
...
@@ -1433,13 +1435,22 @@ int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
...
@@ -1433,13 +1435,22 @@ int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
acx
->
win_size
=
wl
->
conf
.
ht
.
rx_ba_win_size
;
acx
->
win_size
=
wl
->
conf
.
ht
.
rx_ba_win_size
;
acx
->
ssn
=
ssn
;
acx
->
ssn
=
ssn
;
ret
=
wl1271_cmd_configure
(
wl
,
ACX_BA_SESSION_RX_SETUP
,
acx
,
ret
=
wlcore_cmd_configure_failsafe
(
wl
,
ACX_BA_SESSION_RX_SETUP
,
acx
,
sizeof
(
*
acx
));
sizeof
(
*
acx
),
BIT
(
CMD_STATUS_NO_RX_BA_SESSION
));
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
wl1271_warning
(
"acx ba receiver session failed: %d"
,
ret
);
wl1271_warning
(
"acx ba receiver session failed: %d"
,
ret
);
goto
out
;
goto
out
;
}
}
/* sometimes we can't start the session */
if
(
ret
==
CMD_STATUS_NO_RX_BA_SESSION
)
{
wl1271_warning
(
"no fw rx ba on tid %d"
,
tid_index
);
ret
=
-
EBUSY
;
goto
out
;
}
ret
=
0
;
out:
out:
kfree
(
acx
);
kfree
(
acx
);
return
ret
;
return
ret
;
...
...
drivers/net/wireless/ti/wlcore/acx.h
浏览文件 @
56e1bd77
...
@@ -1025,7 +1025,6 @@ enum {
...
@@ -1025,7 +1025,6 @@ enum {
ACX_CONFIG_HANGOVER
=
0x0042
,
ACX_CONFIG_HANGOVER
=
0x0042
,
ACX_FEATURE_CFG
=
0x0043
,
ACX_FEATURE_CFG
=
0x0043
,
ACX_PROTECTION_CFG
=
0x0044
,
ACX_PROTECTION_CFG
=
0x0044
,
ACX_CHECKSUM_CONFIG
=
0x0045
,
};
};
...
...
drivers/net/wireless/ti/wlcore/boot.c
浏览文件 @
56e1bd77
...
@@ -84,47 +84,57 @@ static int wlcore_boot_parse_fw_ver(struct wl1271 *wl,
...
@@ -84,47 +84,57 @@ static int wlcore_boot_parse_fw_ver(struct wl1271 *wl,
static
int
wlcore_validate_fw_ver
(
struct
wl1271
*
wl
)
static
int
wlcore_validate_fw_ver
(
struct
wl1271
*
wl
)
{
{
unsigned
int
*
fw_ver
=
wl
->
chip
.
fw_ver
;
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 */
/* 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
;
goto
fail
;
/* always check the next digit if all previous ones are equal */
/* the firmware type must be equal */
if
((
min_ver
[
FW_VER_IF_TYPE
]
!=
WLCORE_FW_VER_IGNORE
)
&&
if
(
min_ver
[
FW_VER_IF_TYPE
]
<
fw_ver
[
FW_VER_IF_TYPE
])
(
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
])
goto
fail
;
goto
fail
;
if
(
min_ver
[
FW_VER_MAJOR
]
<
fw_ver
[
FW_VER_MAJOR
])
/* the project number must be equal */
goto
out
;
if
((
min_ver
[
FW_VER_SUBTYPE
]
!=
WLCORE_FW_VER_IGNORE
)
&&
else
if
(
min_ver
[
FW_VER_MAJOR
]
>
fw_ver
[
FW_VER_MAJOR
]
)
(
min_ver
[
FW_VER_SUBTYPE
]
!=
fw_ver
[
FW_VER_SUBTYPE
])
)
goto
fail
;
goto
fail
;
if
(
min_ver
[
FW_VER_SUBTYPE
]
<
fw_ver
[
FW_VER_SUBTYPE
])
/* the API version must be greater or equal */
goto
out
;
if
((
min_ver
[
FW_VER_MAJOR
]
!=
WLCORE_FW_VER_IGNORE
)
&&
else
if
(
min_ver
[
FW_VER_SUBTYPE
]
>
fw_ver
[
FW_VER_SUBTYPE
]
)
(
min_ver
[
FW_VER_MAJOR
]
>
fw_ver
[
FW_VER_MAJOR
])
)
goto
fail
;
goto
fail
;
if
(
min_ver
[
FW_VER_MINOR
]
<
fw_ver
[
FW_VER_MINOR
])
/* if the API version is equal... */
goto
out
;
if
(((
min_ver
[
FW_VER_MAJOR
]
==
WLCORE_FW_VER_IGNORE
)
||
else
if
(
min_ver
[
FW_VER_MINOR
]
>
fw_ver
[
FW_VER_MINOR
])
(
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
;
goto
fail
;
out:
return
0
;
return
0
;
fail:
fail:
wl1271_error
(
"Your WiFi FW version (%u.%u.%u.%u.%u) is outdated.
\n
"
for
(
i
=
0
;
i
<
NUM_FW_VER
;
i
++
)
"Please use at least FW %u.%u.%u.%u.%u.
\n
"
if
(
min_ver
[
i
]
==
WLCORE_FW_VER_IGNORE
)
"You can get more information at:
\n
"
snprintf
(
min_fw_str
,
sizeof
(
min_fw_str
),
"http://wireless.kernel.org/en/users/Drivers/wl12xx"
,
"%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_CHIP
],
fw_ver
[
FW_VER_IF_TYPE
],
fw_ver
[
FW_VER_MAJOR
],
fw_ver
[
FW_VER_SUBTYPE
],
fw_ver
[
FW_VER_MAJOR
],
fw_ver
[
FW_VER_SUBTYPE
],
fw_ver
[
FW_VER_MINOR
],
min_ver
[
FW_VER_CHIP
],
fw_ver
[
FW_VER_MINOR
],
min_fw_str
);
min_ver
[
FW_VER_IF_TYPE
],
min_ver
[
FW_VER_MAJOR
],
min_ver
[
FW_VER_SUBTYPE
],
min_ver
[
FW_VER_MINOR
]);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
...
@@ -491,7 +501,7 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
...
@@ -491,7 +501,7 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
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"
,
wl1271_debug
(
DEBUG_MAILBOX
,
"MBOX ptrs: 0x%x 0x%x"
,
wl
->
mbox_ptr
[
0
],
wl
->
mbox_ptr
[
1
]);
wl
->
mbox_ptr
[
0
],
wl
->
mbox_ptr
[
1
]);
...
@@ -508,23 +518,6 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
...
@@ -508,23 +518,6 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
*/
*/
/* unmask required mbox events */
/* 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
);
ret
=
wl1271_event_unmask
(
wl
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
wl1271_error
(
"EVENT mask setting failed"
);
wl1271_error
(
"EVENT mask setting failed"
);
...
...
drivers/net/wireless/ti/wlcore/cmd.c
浏览文件 @
56e1bd77
此差异已折叠。
点击以展开。
drivers/net/wireless/ti/wlcore/cmd.h
浏览文件 @
56e1bd77
...
@@ -31,6 +31,8 @@ struct acx_header;
...
@@ -31,6 +31,8 @@ struct acx_header;
int
wl1271_cmd_send
(
struct
wl1271
*
wl
,
u16
id
,
void
*
buf
,
size_t
len
,
int
wl1271_cmd_send
(
struct
wl1271
*
wl
,
u16
id
,
void
*
buf
,
size_t
len
,
size_t
res_len
);
size_t
res_len
);
int
wlcore_cmd_send_failsafe
(
struct
wl1271
*
wl
,
u16
id
,
void
*
buf
,
size_t
len
,
size_t
res_len
,
unsigned
long
valid_rets
);
int
wl12xx_cmd_role_enable
(
struct
wl1271
*
wl
,
u8
*
addr
,
u8
role_type
,
int
wl12xx_cmd_role_enable
(
struct
wl1271
*
wl
,
u8
*
addr
,
u8
role_type
,
u8
*
role_id
);
u8
*
role_id
);
int
wl12xx_cmd_role_disable
(
struct
wl1271
*
wl
,
u8
*
role_id
);
int
wl12xx_cmd_role_disable
(
struct
wl1271
*
wl
,
u8
*
role_id
);
...
@@ -39,11 +41,14 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif);
...
@@ -39,11 +41,14 @@ 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_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_stop_ap
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
int
wl12xx_cmd_role_start_ibss
(
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
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_test
(
struct
wl1271
*
wl
,
void
*
buf
,
size_t
buf_len
,
u8
answer
);
int
wl1271_cmd_interrogate
(
struct
wl1271
*
wl
,
u16
id
,
void
*
buf
,
size_t
len
);
int
wl1271_cmd_interrogate
(
struct
wl1271
*
wl
,
u16
id
,
void
*
buf
,
size_t
len
);
int
wl1271_cmd_configure
(
struct
wl1271
*
wl
,
u16
id
,
void
*
buf
,
size_t
len
);
int
wl1271_cmd_configure
(
struct
wl1271
*
wl
,
u16
id
,
void
*
buf
,
size_t
len
);
int
wlcore_cmd_configure_failsafe
(
struct
wl1271
*
wl
,
u16
id
,
void
*
buf
,
size_t
len
,
unsigned
long
valid_rets
);
int
wl1271_cmd_data_path
(
struct
wl1271
*
wl
,
bool
enable
);
int
wl1271_cmd_data_path
(
struct
wl1271
*
wl
,
bool
enable
);
int
wl1271_cmd_ps_mode
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
int
wl1271_cmd_ps_mode
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
ps_mode
,
u16
auto_ps_timeout
);
u8
ps_mode
,
u16
auto_ps_timeout
);
...
@@ -75,22 +80,30 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif,
...
@@ -75,22 +80,30 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u16
action
,
u8
id
,
u8
key_type
,
u16
action
,
u8
id
,
u8
key_type
,
u8
key_size
,
const
u8
*
key
,
u8
hlid
,
u32
tx_seq_32
,
u8
key_size
,
const
u8
*
key
,
u8
hlid
,
u32
tx_seq_32
,
u16
tx_seq_16
);
u16
tx_seq_16
);
int
wl12xx_cmd_set_peer_state
(
struct
wl1271
*
wl
,
u8
hlid
);
int
wl12xx_cmd_set_peer_state
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
int
wl12xx_roc
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
role_id
);
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_croc
(
struct
wl1271
*
wl
,
u8
role_id
);
int
wl12xx_cmd_add_peer
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
int
wl12xx_cmd_add_peer
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
ieee80211_sta
*
sta
,
u8
hlid
);
struct
ieee80211_sta
*
sta
,
u8
hlid
);
int
wl12xx_cmd_remove_peer
(
struct
wl1271
*
wl
,
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_config_fwlog
(
struct
wl1271
*
wl
);
int
wl12xx_cmd_start_fwlog
(
struct
wl1271
*
wl
);
int
wl12xx_cmd_start_fwlog
(
struct
wl1271
*
wl
);
int
wl12xx_cmd_stop_fwlog
(
struct
wl1271
*
wl
);
int
wl12xx_cmd_stop_fwlog
(
struct
wl1271
*
wl
);
int
wl12xx_cmd_channel_switch
(
struct
wl1271
*
wl
,
int
wl12xx_cmd_channel_switch
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
struct
wl12xx_vif
*
wlvif
,
struct
ieee80211_channel_switch
*
ch_switch
);
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
,
int
wl12xx_allocate_link
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
,
u8
*
hlid
);
u8
*
hlid
);
void
wl12xx_free_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
{
enum
wl1271_commands
{
CMD_INTERROGATE
=
1
,
/* use this to read information elements */
CMD_INTERROGATE
=
1
,
/* use this to read information elements */
...
@@ -149,8 +162,11 @@ enum wl1271_commands {
...
@@ -149,8 +162,11 @@ enum wl1271_commands {
CMD_WFD_START_DISCOVERY
=
45
,
CMD_WFD_START_DISCOVERY
=
45
,
CMD_WFD_STOP_DISCOVERY
=
46
,
CMD_WFD_STOP_DISCOVERY
=
46
,
CMD_WFD_ATTRIBUTE_CONFIG
=
47
,
CMD_WFD_ATTRIBUTE_CONFIG
=
47
,
CMD_NOP
=
48
,
CMD_GENERIC_CFG
=
48
,
CMD_LAST_COMMAND
,
CMD_NOP
=
49
,
/* start of 18xx specific commands */
CMD_DFS_CHANNEL_CONFIG
=
60
,
MAX_COMMAND_ID
=
0xFFFF
,
MAX_COMMAND_ID
=
0xFFFF
,
};
};
...
@@ -167,8 +183,8 @@ enum cmd_templ {
...
@@ -167,8 +183,8 @@ enum cmd_templ {
CMD_TEMPL_PS_POLL
,
CMD_TEMPL_PS_POLL
,
CMD_TEMPL_KLV
,
CMD_TEMPL_KLV
,
CMD_TEMPL_DISCONNECT
,
CMD_TEMPL_DISCONNECT
,
CMD_TEMPL_APP_PROBE_REQ_2_4
,
CMD_TEMPL_APP_PROBE_REQ_2_4
_LEGACY
,
CMD_TEMPL_APP_PROBE_REQ_5
,
CMD_TEMPL_APP_PROBE_REQ_5
_LEGACY
,
CMD_TEMPL_BAR
,
/* for firmware internal use only */
CMD_TEMPL_BAR
,
/* for firmware internal use only */
CMD_TEMPL_CTS
,
/*
CMD_TEMPL_CTS
,
/*
* For CTS-to-self (FastCTS) mechanism
* For CTS-to-self (FastCTS) mechanism
...
@@ -179,6 +195,8 @@ enum cmd_templ {
...
@@ -179,6 +195,8 @@ enum cmd_templ {
CMD_TEMPL_DEAUTH_AP
,
CMD_TEMPL_DEAUTH_AP
,
CMD_TEMPL_TEMPORARY
,
CMD_TEMPL_TEMPORARY
,
CMD_TEMPL_LINK_MEASUREMENT_REPORT
,
CMD_TEMPL_LINK_MEASUREMENT_REPORT
,
CMD_TEMPL_PROBE_REQ_2_4_PERIODIC
,
CMD_TEMPL_PROBE_REQ_5_PERIODIC
,
CMD_TEMPL_MAX
=
0xff
CMD_TEMPL_MAX
=
0xff
};
};
...
@@ -220,7 +238,8 @@ enum {
...
@@ -220,7 +238,8 @@ enum {
CMD_STATUS_FW_RESET
=
22
,
/* Driver internal use.*/
CMD_STATUS_FW_RESET
=
22
,
/* Driver internal use.*/
CMD_STATUS_TEMPLATE_OOM
=
23
,
CMD_STATUS_TEMPLATE_OOM
=
23
,
CMD_STATUS_NO_RX_BA_SESSION
=
24
,
CMD_STATUS_NO_RX_BA_SESSION
=
24
,
MAX_COMMAND_STATUS
=
0xff
MAX_COMMAND_STATUS
};
};
#define CMDMBOX_HEADER_LEN 4
#define CMDMBOX_HEADER_LEN 4
...
@@ -345,7 +364,15 @@ struct wl12xx_cmd_role_start {
...
@@ -345,7 +364,15 @@ struct wl12xx_cmd_role_start {
u8
reset_tsf
;
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
ap
;
};
};
}
__packed
;
}
__packed
;
...
@@ -515,7 +542,14 @@ struct wl12xx_cmd_set_peer_state {
...
@@ -515,7 +542,14 @@ struct wl12xx_cmd_set_peer_state {
u8
hlid
;
u8
hlid
;
u8
state
;
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
;
}
__packed
;
struct
wl12xx_cmd_roc
{
struct
wl12xx_cmd_roc
{
...
@@ -558,7 +592,7 @@ struct wl12xx_cmd_add_peer {
...
@@ -558,7 +592,7 @@ struct wl12xx_cmd_add_peer {
u8
bss_index
;
u8
bss_index
;
u8
sp_len
;
u8
sp_len
;
u8
wmm
;
u8
wmm
;
u8
padding1
;
u8
session_id
;
}
__packed
;
}
__packed
;
struct
wl12xx_cmd_remove_peer
{
struct
wl12xx_cmd_remove_peer
{
...
@@ -597,6 +631,13 @@ enum wl12xx_fwlogger_output {
...
@@ -597,6 +631,13 @@ enum wl12xx_fwlogger_output {
WL12XX_FWLOG_OUTPUT_HOST
,
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
wl12xx_cmd_config_fwlog
{
struct
wl1271_cmd_header
header
;
struct
wl1271_cmd_header
header
;
...
@@ -626,27 +667,13 @@ struct wl12xx_cmd_stop_fwlog {
...
@@ -626,27 +667,13 @@ struct wl12xx_cmd_stop_fwlog {
struct
wl1271_cmd_header
header
;
struct
wl1271_cmd_header
header
;
}
__packed
;
}
__packed
;
struct
wl12xx_cmd_channel_switch
{
struct
wl12xx_cmd_
stop_
channel_switch
{
struct
wl1271_cmd_header
header
;
struct
wl1271_cmd_header
header
;
u8
role_id
;
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
];
u8
padding
[
3
];
}
__packed
;
}
__packed
;
struct
wl12xx_cmd_stop_channel_switch
{
struct
wl1271_cmd_header
header
;
}
__packed
;
/* Used to check radio status after calibration */
/* Used to check radio status after calibration */
#define MAX_TLV_LENGTH 500
#define MAX_TLV_LENGTH 500
#define TEST_CMD_P2G_CAL 2
/* TX BiP */
#define TEST_CMD_P2G_CAL 2
/* TX BiP */
...
...
drivers/net/wireless/ti/wlcore/conf.h
浏览文件 @
56e1bd77
...
@@ -57,20 +57,49 @@ enum {
...
@@ -57,20 +57,49 @@ enum {
};
};
enum
{
enum
{
CONF_HW_RATE_INDEX_1MBPS
=
0
,
CONF_HW_RATE_INDEX_1MBPS
=
0
,
CONF_HW_RATE_INDEX_2MBPS
=
1
,
CONF_HW_RATE_INDEX_2MBPS
=
1
,
CONF_HW_RATE_INDEX_5_5MBPS
=
2
,
CONF_HW_RATE_INDEX_5_5MBPS
=
2
,
CONF_HW_RATE_INDEX_6MBPS
=
3
,
CONF_HW_RATE_INDEX_11MBPS
=
3
,
CONF_HW_RATE_INDEX_9MBPS
=
4
,
CONF_HW_RATE_INDEX_6MBPS
=
4
,
CONF_HW_RATE_INDEX_11MBPS
=
5
,
CONF_HW_RATE_INDEX_9MBPS
=
5
,
CONF_HW_RATE_INDEX_12MBPS
=
6
,
CONF_HW_RATE_INDEX_12MBPS
=
6
,
CONF_HW_RATE_INDEX_18MBPS
=
7
,
CONF_HW_RATE_INDEX_18MBPS
=
7
,
CONF_HW_RATE_INDEX_22MBPS
=
8
,
CONF_HW_RATE_INDEX_24MBPS
=
8
,
CONF_HW_RATE_INDEX_24MBPS
=
9
,
CONF_HW_RATE_INDEX_36MBPS
=
9
,
CONF_HW_RATE_INDEX_36MBPS
=
10
,
CONF_HW_RATE_INDEX_48MBPS
=
10
,
CONF_HW_RATE_INDEX_48MBPS
=
11
,
CONF_HW_RATE_INDEX_54MBPS
=
11
,
CONF_HW_RATE_INDEX_54MBPS
=
12
,
CONF_HW_RATE_INDEX_MCS0
=
12
,
CONF_HW_RATE_INDEX_MAX
=
CONF_HW_RATE_INDEX_54MBPS
,
CONF_HW_RATE_INDEX_MCS1
=
13
,
CONF_HW_RATE_INDEX_MCS2
=
14
,
CONF_HW_RATE_INDEX_MCS3
=
15
,
CONF_HW_RATE_INDEX_MCS4
=
16
,
CONF_HW_RATE_INDEX_MCS5
=
17
,
CONF_HW_RATE_INDEX_MCS6
=
18
,
CONF_HW_RATE_INDEX_MCS7
=
19
,
CONF_HW_RATE_INDEX_MCS7_SGI
=
20
,
CONF_HW_RATE_INDEX_MCS0_40MHZ
=
21
,
CONF_HW_RATE_INDEX_MCS1_40MHZ
=
22
,
CONF_HW_RATE_INDEX_MCS2_40MHZ
=
23
,
CONF_HW_RATE_INDEX_MCS3_40MHZ
=
24
,
CONF_HW_RATE_INDEX_MCS4_40MHZ
=
25
,
CONF_HW_RATE_INDEX_MCS5_40MHZ
=
26
,
CONF_HW_RATE_INDEX_MCS6_40MHZ
=
27
,
CONF_HW_RATE_INDEX_MCS7_40MHZ
=
28
,
CONF_HW_RATE_INDEX_MCS7_40MHZ_SGI
=
29
,
/* MCS8+ rates overlap with 40Mhz rates */
CONF_HW_RATE_INDEX_MCS8
=
21
,
CONF_HW_RATE_INDEX_MCS9
=
22
,
CONF_HW_RATE_INDEX_MCS10
=
23
,
CONF_HW_RATE_INDEX_MCS11
=
24
,
CONF_HW_RATE_INDEX_MCS12
=
25
,
CONF_HW_RATE_INDEX_MCS13
=
26
,
CONF_HW_RATE_INDEX_MCS14
=
27
,
CONF_HW_RATE_INDEX_MCS15
=
28
,
CONF_HW_RATE_INDEX_MCS15_SGI
=
29
,
CONF_HW_RATE_INDEX_MAX
=
CONF_HW_RATE_INDEX_MCS7_40MHZ_SGI
,
};
};
#define CONF_HW_RXTX_RATE_UNSUPPORTED 0xff
#define CONF_HW_RXTX_RATE_UNSUPPORTED 0xff
...
@@ -415,11 +444,11 @@ struct conf_rx_settings {
...
@@ -415,11 +444,11 @@ struct conf_rx_settings {
#define CONF_TX_RATE_MASK_BASIC_P2P CONF_HW_BIT_RATE_6MBPS
#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
* 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.
* 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_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | \
CONF_HW_BIT_RATE_6MBPS | CONF_HW_BIT_RATE_9MBPS | \
CONF_HW_BIT_RATE_6MBPS | CONF_HW_BIT_RATE_9MBPS | \
CONF_HW_BIT_RATE_11MBPS | CONF_HW_BIT_RATE_12MBPS | \
CONF_HW_BIT_RATE_11MBPS | CONF_HW_BIT_RATE_12MBPS | \
...
@@ -677,6 +706,18 @@ struct conf_tx_settings {
...
@@ -677,6 +706,18 @@ struct conf_tx_settings {
/* Time in ms for Tx watchdog timer to expire */
/* Time in ms for Tx watchdog timer to expire */
u32
tx_watchdog_timeout
;
u32
tx_watchdog_timeout
;
/*
* when a slow link has this much packets pending, it becomes a low
* priority link, scheduling-wise
*/
u8
slow_link_thold
;
/*
* when a fast link has this much packets pending, it becomes a low
* priority link, scheduling-wise
*/
u8
fast_link_thold
;
}
__packed
;
}
__packed
;
enum
{
enum
{
...
@@ -1047,6 +1088,7 @@ struct conf_roam_trigger_settings {
...
@@ -1047,6 +1088,7 @@ struct conf_roam_trigger_settings {
struct
conf_scan_settings
{
struct
conf_scan_settings
{
/*
/*
* The minimum time to wait on each channel for active scans
* The minimum time to wait on each channel for active scans
* This value will be used whenever there's a connected interface.
*
*
* Range: u32 tu/1000
* Range: u32 tu/1000
*/
*/
...
@@ -1054,24 +1096,37 @@ struct conf_scan_settings {
...
@@ -1054,24 +1096,37 @@ struct conf_scan_settings {
/*
/*
* The maximum time to wait on each channel for active scans
* The maximum time to wait on each channel for active scans
* This value will be currently used whenever there's a
* connected interface. It shouldn't exceed 30000 (~30ms) to avoid
* possible interference of voip traffic going on while scanning.
*
*
* Range: u32 tu/1000
* Range: u32 tu/1000
*/
*/
u32
max_dwell_time_active
;
u32
max_dwell_time_active
;
/*
/* The minimum time to wait on each channel for active scans
* The minimum time to wait on each channel for passive scans
* when it's possible to have longer scan dwell times.
* Currently this is used whenever we're idle on all interfaces.
* Longer dwell times improve detection of networks within a
* single scan.
*
*
* Range: u32 tu/1000
* Range: u32 tu/1000
*/
*/
u32
min_dwell_time_
passive
;
u32
min_dwell_time_
active_long
;
/*
/* The maximum time to wait on each channel for active scans
* The maximum time to wait on each channel for passive scans
* when it's possible to have longer scan dwell times.
* See min_dwell_time_active_long
*
*
* Range: u32 tu/1000
* Range: u32 tu/1000
*/
*/
u32
max_dwell_time_passive
;
u32
max_dwell_time_active_long
;
/* time to wait on the channel for passive scans (in TU/1000) */
u32
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
* Number of probe requests to transmit on each active scan channel
...
@@ -1276,12 +1331,20 @@ struct conf_hangover_settings {
...
@@ -1276,12 +1331,20 @@ struct conf_hangover_settings {
u8
window_size
;
u8
window_size
;
}
__packed
;
}
__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
* 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, the two LSB are the lower driver's private conf
* version.
* version.
*/
*/
#define WLCORE_CONF_VERSION (0x000
2
<< 16)
#define WLCORE_CONF_VERSION (0x000
5
<< 16)
#define WLCORE_CONF_MASK 0xffff0000
#define WLCORE_CONF_MASK 0xffff0000
#define WLCORE_CONF_SIZE (sizeof(struct wlcore_conf_header) + \
#define WLCORE_CONF_SIZE (sizeof(struct wlcore_conf_header) + \
sizeof(struct wlcore_conf))
sizeof(struct wlcore_conf))
...
@@ -1309,6 +1372,7 @@ struct wlcore_conf {
...
@@ -1309,6 +1372,7 @@ struct wlcore_conf {
struct
conf_fwlog
fwlog
;
struct
conf_fwlog
fwlog
;
struct
conf_rate_policy_settings
rate
;
struct
conf_rate_policy_settings
rate
;
struct
conf_hangover_settings
hangover
;
struct
conf_hangover_settings
hangover
;
struct
conf_recovery_settings
recovery
;
}
__packed
;
}
__packed
;
struct
wlcore_conf_file
{
struct
wlcore_conf_file
{
...
...
drivers/net/wireless/ti/wlcore/debugfs.c
浏览文件 @
56e1bd77
...
@@ -490,7 +490,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
...
@@ -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_HEX
(
chip
.
id
);
DRIVER_STATE_PRINT_STR
(
chip
.
fw_ver_str
);
DRIVER_STATE_PRINT_STR
(
chip
.
fw_ver_str
);
DRIVER_STATE_PRINT_STR
(
chip
.
phy_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_INT
#undef DRIVER_STATE_PRINT_LONG
#undef DRIVER_STATE_PRINT_LONG
...
@@ -560,7 +560,6 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf,
...
@@ -560,7 +560,6 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf,
if
(
wlvif
->
bss_type
==
BSS_TYPE_STA_BSS
||
if
(
wlvif
->
bss_type
==
BSS_TYPE_STA_BSS
||
wlvif
->
bss_type
==
BSS_TYPE_IBSS
)
{
wlvif
->
bss_type
==
BSS_TYPE_IBSS
)
{
VIF_STATE_PRINT_INT
(
sta
.
hlid
);
VIF_STATE_PRINT_INT
(
sta
.
hlid
);
VIF_STATE_PRINT_INT
(
sta
.
ba_rx_bitmap
);
VIF_STATE_PRINT_INT
(
sta
.
basic_rate_idx
);
VIF_STATE_PRINT_INT
(
sta
.
basic_rate_idx
);
VIF_STATE_PRINT_INT
(
sta
.
ap_rate_idx
);
VIF_STATE_PRINT_INT
(
sta
.
ap_rate_idx
);
VIF_STATE_PRINT_INT
(
sta
.
p2p_rate_idx
);
VIF_STATE_PRINT_INT
(
sta
.
p2p_rate_idx
);
...
@@ -577,6 +576,10 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf,
...
@@ -577,6 +576,10 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf,
VIF_STATE_PRINT_INT
(
ap
.
ucast_rate_idx
[
3
]);
VIF_STATE_PRINT_INT
(
ap
.
ucast_rate_idx
[
3
]);
}
}
VIF_STATE_PRINT_INT
(
last_tx_hlid
);
VIF_STATE_PRINT_INT
(
last_tx_hlid
);
VIF_STATE_PRINT_INT
(
tx_queue_count
[
0
]);
VIF_STATE_PRINT_INT
(
tx_queue_count
[
1
]);
VIF_STATE_PRINT_INT
(
tx_queue_count
[
2
]);
VIF_STATE_PRINT_INT
(
tx_queue_count
[
3
]);
VIF_STATE_PRINT_LHEX
(
links_map
[
0
]);
VIF_STATE_PRINT_LHEX
(
links_map
[
0
]);
VIF_STATE_PRINT_NSTR
(
ssid
,
wlvif
->
ssid_len
);
VIF_STATE_PRINT_NSTR
(
ssid
,
wlvif
->
ssid_len
);
VIF_STATE_PRINT_INT
(
band
);
VIF_STATE_PRINT_INT
(
band
);
...
@@ -589,7 +592,6 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf,
...
@@ -589,7 +592,6 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf,
VIF_STATE_PRINT_INT
(
beacon_int
);
VIF_STATE_PRINT_INT
(
beacon_int
);
VIF_STATE_PRINT_INT
(
default_key
);
VIF_STATE_PRINT_INT
(
default_key
);
VIF_STATE_PRINT_INT
(
aid
);
VIF_STATE_PRINT_INT
(
aid
);
VIF_STATE_PRINT_INT
(
session_counter
);
VIF_STATE_PRINT_INT
(
psm_entry_retry
);
VIF_STATE_PRINT_INT
(
psm_entry_retry
);
VIF_STATE_PRINT_INT
(
power_level
);
VIF_STATE_PRINT_INT
(
power_level
);
VIF_STATE_PRINT_INT
(
rssi_thold
);
VIF_STATE_PRINT_INT
(
rssi_thold
);
...
@@ -993,7 +995,7 @@ static ssize_t sleep_auth_write(struct file *file,
...
@@ -993,7 +995,7 @@ static ssize_t sleep_auth_write(struct file *file,
return
-
EINVAL
;
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_warning
(
"sleep_auth must be between 0 and %d"
,
WL1271_PSM_MAX
);
WL1271_PSM_MAX
);
return
-
ERANGE
;
return
-
ERANGE
;
...
...
drivers/net/wireless/ti/wlcore/event.c
浏览文件 @
56e1bd77
...
@@ -29,34 +29,39 @@
...
@@ -29,34 +29,39 @@
#include "scan.h"
#include "scan.h"
#include "wl12xx_80211.h"
#include "wl12xx_80211.h"
static
void
wl1271_event_rssi_trigger
(
struct
wl1271
*
wl
,
void
wlcore_event_rssi_trigger
(
struct
wl1271
*
wl
,
s8
*
metric_arr
)
struct
wl12xx_vif
*
wlvif
,
struct
event_mailbox
*
mbox
)
{
{
struct
ieee80211_vif
*
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
struct
wl12xx_vif
*
wlvif
;
struct
ieee80211_vif
*
vif
;
enum
nl80211_cqm_rssi_threshold_event
event
;
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
);
wl1271_debug
(
DEBUG_EVENT
,
"RSSI trigger metric: %d"
,
metric
);
if
(
metric
<=
wlvif
->
rssi_thold
)
/* TODO: check actual multi-role support */
event
=
NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW
;
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
else
if
(
metric
<=
wlvif
->
rssi_thold
)
event
=
NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH
;
event
=
NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW
;
else
if
(
event
!=
wlvif
->
last_rssi_event
)
event
=
NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH
;
ieee80211_cqm_rssi_notify
(
vif
,
event
,
GFP_KERNEL
);
wlvif
->
last_rssi_event
=
event
;
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
)
static
void
wl1271_stop_ba_event
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
)
{
{
struct
ieee80211_vif
*
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
struct
ieee80211_vif
*
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
if
(
wlvif
->
bss_type
!=
BSS_TYPE_AP_BSS
)
{
if
(
wlvif
->
bss_type
!=
BSS_TYPE_AP_BSS
)
{
if
(
!
wlvif
->
sta
.
ba_rx_bitmap
)
u8
hlid
=
wlvif
->
sta
.
hlid
;
if
(
!
wl
->
links
[
hlid
].
ba_bitmap
)
return
;
return
;
ieee80211_stop_rx_ba_session
(
vif
,
wl
vif
->
sta
.
ba_rx
_bitmap
,
ieee80211_stop_rx_ba_session
(
vif
,
wl
->
links
[
hlid
].
ba
_bitmap
,
vif
->
bss_conf
.
bssid
);
vif
->
bss_conf
.
bssid
);
}
else
{
}
else
{
u8
hlid
;
u8
hlid
;
...
@@ -74,8 +79,7 @@ static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif)
...
@@ -74,8 +79,7 @@ static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif)
}
}
}
}
static
void
wl12xx_event_soft_gemini_sense
(
struct
wl1271
*
wl
,
void
wlcore_event_soft_gemini_sense
(
struct
wl1271
*
wl
,
u8
enable
)
u8
enable
)
{
{
struct
wl12xx_vif
*
wlvif
;
struct
wl12xx_vif
*
wlvif
;
...
@@ -87,201 +91,169 @@ static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl,
...
@@ -87,201 +91,169 @@ static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl,
wl1271_recalc_rx_streaming
(
wl
,
wlvif
);
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_completed
(
struct
wl1271
*
wl
,
u8
status
)
{
{
wl1271_debug
(
DEBUG_EVENT
,
"MBOX DUMP:"
);
wl1271_debug
(
DEBUG_EVENT
,
"PERIODIC_SCAN_COMPLETE_EVENT (status 0x%0x)"
,
wl1271_debug
(
DEBUG_EVENT
,
"
\t
vector: 0x%x"
,
mbox
->
events_vector
);
status
);
wl1271_debug
(
DEBUG_EVENT
,
"
\t
mask: 0x%x"
,
mbox
->
events_mask
);
if
(
wl
->
sched_vif
)
{
ieee80211_sched_scan_stopped
(
wl
->
hw
);
wl
->
sched_vif
=
NULL
;
}
}
}
EXPORT_SYMBOL_GPL
(
wlcore_event_sched_scan_completed
);
static
int
wl1271_event_process
(
struct
wl1271
*
wl
)
void
wlcore_event_ba_rx_constraint
(
struct
wl1271
*
wl
,
unsigned
long
roles_bitmap
,
unsigned
long
allowed_bitmap
)
{
{
struct
event_mailbox
*
mbox
=
wl
->
mbox
;
struct
ieee80211_vif
*
vif
;
struct
wl12xx_vif
*
wlvif
;
struct
wl12xx_vif
*
wlvif
;
u32
vector
;
bool
disconnect_sta
=
false
;
unsigned
long
sta_bitmap
=
0
;
int
ret
;
wl1271_event_mbox_dump
(
mbox
);
vector
=
le32_to_cpu
(
mbox
->
events_vector
);
vector
&=
~
(
le32_to_cpu
(
mbox
->
events_mask
));
wl1271_debug
(
DEBUG_EVENT
,
"vector: 0x%x"
,
vector
);
if
(
vector
&
SCAN_COMPLETE_EVENT_ID
)
{
wl1271_debug
(
DEBUG_EVENT
,
"%s: roles=0x%lx allowed=0x%lx"
,
wl1271_debug
(
DEBUG_EVENT
,
"status: 0x%x"
,
__func__
,
roles_bitmap
,
allowed_bitmap
);
mbox
->
scheduled_scan_status
);
wl1271_scan_stm
(
wl
,
wl
->
scan_vif
);
}
if
(
vector
&
PERIODIC_SCAN_REPORT_EVENT_ID
)
{
wl12xx_for_each_wlvif
(
wl
,
wlvif
)
{
wl1271_debug
(
DEBUG_EVENT
,
"PERIODIC_SCAN_REPORT_EVENT "
if
(
wlvif
->
role_id
==
WL12XX_INVALID_ROLE_ID
||
"(status 0x%0x)"
,
mbox
->
scheduled_scan_status
);
!
test_bit
(
wlvif
->
role_id
,
&
roles_bitmap
))
continue
;
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
)
{
void
wlcore_event_channel_switch
(
struct
wl1271
*
wl
,
wl1271_debug
(
DEBUG_EVENT
,
"PERIODIC_SCAN_COMPLETE_EVENT "
unsigned
long
roles_bitmap
,
"(status 0x%0x)"
,
mbox
->
scheduled_scan_status
);
bool
success
)
if
(
wl
->
sched_scanning
)
{
{
ieee80211_sched_scan_stopped
(
wl
->
hw
);
struct
wl12xx_vif
*
wlvif
;
wl
->
sched_scanning
=
false
;
struct
ieee80211_vif
*
vif
;
}
}
if
(
vector
&
SOFT_GEMINI_SENSE_EVENT_ID
)
wl1271_debug
(
DEBUG_EVENT
,
"%s: roles=0x%lx success=%d"
,
wl12xx_event_soft_gemini_sense
(
wl
,
__func__
,
roles_bitmap
,
success
);
mbox
->
soft_gemini_sense_info
);
/*
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
* We are HW_MONITOR device. On beacon loss - queue
if
(
wlvif
->
role_id
==
WL12XX_INVALID_ROLE_ID
||
* connection loss work. Cancel it on REGAINED event.
!
test_bit
(
wlvif
->
role_id
,
&
roles_bitmap
))
*/
continue
;
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."
);
/*
if
(
!
test_and_clear_bit
(
WLVIF_FLAG_CS_PROGRESS
,
* if the work is already queued, it should take place. We
&
wlvif
->
flags
))
* don't want to delay the connection loss indication
continue
;
* any more.
*/
ieee80211_queue_delayed_work
(
wl
->
hw
,
&
wl
->
connection_loss_work
,
msecs_to_jiffies
(
delay
));
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
ieee80211_cqm_rssi_notify
(
ieee80211_chswitch_done
(
vif
,
success
);
vif
,
cancel_delayed_work
(
&
wlvif
->
channel_switch_work
);
NL80211_CQM_RSSI_BEACON_LOSS_EVENT
,
GFP_KERNEL
);
}
}
}
}
EXPORT_SYMBOL_GPL
(
wlcore_event_channel_switch
);
if
(
vector
&
REGAINED_BSS_EVENT_ID
)
{
void
wlcore_event_dummy_packet
(
struct
wl1271
*
wl
)
/* TODO: check for multi-role */
{
wl1271_info
(
"Beacon regained."
);
wl1271_debug
(
DEBUG_EVENT
,
"DUMMY_PACKET_ID_EVENT_ID"
);
cancel_delayed_work
(
&
wl
->
connection_loss_work
);
wl1271_tx_dummy_packet
(
wl
);
}
/* sanity check - we can't lose and gain the beacon together */
EXPORT_SYMBOL_GPL
(
wlcore_event_dummy_packet
);
WARN
(
vector
&
BSS_LOSE_EVENT_ID
,
"Concurrent beacon loss and gain from FW"
);
}
if
(
vector
&
RSSI_SNR_TRIGGER_0_EVENT_ID
)
{
static
void
wlcore_disconnect_sta
(
struct
wl1271
*
wl
,
unsigned
long
sta_bitmap
)
/* TODO: check actual multi-role support */
{
wl1271_debug
(
DEBUG_EVENT
,
"RSSI_SNR_TRIGGER_0_EVENT"
);
u32
num_packets
=
wl
->
conf
.
tx
.
max_tx_retries
;
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
struct
wl12xx_vif
*
wlvif
;
wl1271_event_rssi_trigger
(
wl
,
wlvif
,
mbox
);
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
)
{
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
u8
role_id
=
mbox
->
role_id
;
addr
=
wl
->
links
[
h
].
addr
;
wl1271_debug
(
DEBUG_EVENT
,
"BA_SESSION_RX_CONSTRAINT_EVENT_ID. "
"ba_allowed = 0x%x, role_id=%d"
,
mbox
->
rx_ba_allowed
,
role_id
);
wl12xx_for_each_wlvif
(
wl
,
wlvif
)
{
rcu_read_lock
();
if
(
role_id
!=
0xff
&&
role_id
!=
wlvif
->
role_id
)
sta
=
ieee80211_find_sta
(
vif
,
addr
);
continue
;
if
(
sta
)
{
wl1271_debug
(
DEBUG_EVENT
,
"remove sta %d"
,
h
);
wlvif
->
ba_allowed
=
!!
mbox
->
rx_ba_allowed
;
ieee80211_report_low_ack
(
sta
,
num_packets
);
if
(
!
wlvif
->
ba_allowed
)
wl1271_stop_ba_event
(
wl
,
wlvif
);
}
}
rcu_read_unlock
();
}
}
}
if
(
vector
&
CHANNEL_SWITCH_COMPLETE_EVENT_ID
)
{
void
wlcore_event_max_tx_failure
(
struct
wl1271
*
wl
,
unsigned
long
sta_bitmap
)
wl1271_debug
(
DEBUG_EVENT
,
"CHANNEL_SWITCH_COMPLETE_EVENT_ID. "
{
"status = 0x%x"
,
wl1271_debug
(
DEBUG_EVENT
,
"MAX_TX_FAILURE_EVENT_ID"
);
mbox
->
channel_switch_status
);
wlcore_disconnect_sta
(
wl
,
sta_bitmap
);
/*
}
* That event uses for two cases:
EXPORT_SYMBOL_GPL
(
wlcore_event_max_tx_failure
);
* 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
);
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
))
{
void
wlcore_event_roc_complete
(
struct
wl1271
*
wl
)
wl1271_debug
(
DEBUG_EVENT
,
"DUMMY_PACKET_ID_EVENT_ID"
);
{
ret
=
wl1271_tx_dummy_packet
(
wl
);
wl1271_debug
(
DEBUG_EVENT
,
"REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID"
);
if
(
ret
<
0
)
if
(
wl
->
roc_vif
)
return
ret
;
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.
*
We are HW_MONITOR device. On beacon loss - queue
*
In AP mode the offending station is disconnected
.
*
connection loss work. Cancel it on REGAINED event
.
*/
*/
if
(
vector
&
MAX_TX_RETRY_EVENT_ID
)
{
struct
wl12xx_vif
*
wlvif
;
wl1271_debug
(
DEBUG_EVENT
,
"MAX_TX_RETRY_EVENT_ID"
);
struct
ieee80211_vif
*
vif
;
sta_bitmap
|=
le16_to_cpu
(
mbox
->
sta_tx_retry_exceeded
);
int
delay
=
wl
->
conf
.
conn
.
synch_fail_thold
*
disconnect_sta
=
true
;
wl
->
conf
.
conn
.
bss_lose_timeout
;
}
if
(
vector
&
INACTIVE_STA_EVENT_ID
)
{
wl1271_info
(
"Beacon loss detected. roles:0x%lx"
,
roles_bitmap
);
wl1271_debug
(
DEBUG_EVENT
,
"INACTIVE_STA_EVENT_ID"
);
sta_bitmap
|=
le16_to_cpu
(
mbox
->
sta_aging_status
);
disconnect_sta
=
true
;
}
if
(
disconnect_sta
)
{
wl12xx_for_each_wlvif_sta
(
wl
,
wlvif
)
{
u32
num_packets
=
wl
->
conf
.
tx
.
max_tx_retries
;
if
(
wlvif
->
role_id
==
WL12XX_INVALID_ROLE_ID
||
struct
ieee80211_sta
*
sta
;
!
test_bit
(
wlvif
->
role_id
,
&
roles_bitmap
))
const
u8
*
addr
;
continue
;
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
;
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
();
vif
=
wl12xx_wlvif_to_vif
(
wlvif
);
sta
=
ieee80211_find_sta
(
vif
,
addr
);
ieee80211_cqm_rssi_notify
(
if
(
sta
)
{
vif
,
wl1271_debug
(
DEBUG_EVENT
,
"remove sta %d"
,
h
);
NL80211_CQM_RSSI_BEACON_LOSS_EVENT
,
ieee80211_report_low_ack
(
sta
,
num_packets
);
GFP_KERNEL
);
}
rcu_read_unlock
();
}
}
}
return
0
;
}
}
EXPORT_SYMBOL_GPL
(
wlcore_event_beacon_loss
);
int
wl1271_event_unmask
(
struct
wl1271
*
wl
)
int
wl1271_event_unmask
(
struct
wl1271
*
wl
)
{
{
...
@@ -305,12 +277,12 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
...
@@ -305,12 +277,12 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
/* first we read the mbox descriptor */
/* first we read the mbox descriptor */
ret
=
wlcore_read
(
wl
,
wl
->
mbox_ptr
[
mbox_num
],
wl
->
mbox
,
ret
=
wlcore_read
(
wl
,
wl
->
mbox_ptr
[
mbox_num
],
wl
->
mbox
,
sizeof
(
*
wl
->
mbox
)
,
false
);
wl
->
mbox_size
,
false
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
/* process the descriptor */
/* process the descriptor */
ret
=
wl
1271_event_proces
s
(
wl
);
ret
=
wl
->
ops
->
process_mailbox_event
s
(
wl
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
...
...
drivers/net/wireless/ti/wlcore/event.h
浏览文件 @
56e1bd77
...
@@ -46,33 +46,17 @@ enum {
...
@@ -46,33 +46,17 @@ enum {
RSSI_SNR_TRIGGER_5_EVENT_ID
=
BIT
(
5
),
RSSI_SNR_TRIGGER_5_EVENT_ID
=
BIT
(
5
),
RSSI_SNR_TRIGGER_6_EVENT_ID
=
BIT
(
6
),
RSSI_SNR_TRIGGER_6_EVENT_ID
=
BIT
(
6
),
RSSI_SNR_TRIGGER_7_EVENT_ID
=
BIT
(
7
),
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
,
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
{
enum
{
EVENT_ENTER_POWER_SAVE_FAIL
=
0
,
EVENT_ENTER_POWER_SAVE_FAIL
=
0
,
EVENT_ENTER_POWER_SAVE_SUCCESS
,
EVENT_ENTER_POWER_SAVE_SUCCESS
,
...
@@ -80,61 +64,24 @@ enum {
...
@@ -80,61 +64,24 @@ enum {
#define NUM_OF_RSSI_SNR_TRIGGERS 8
#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
;
struct
wl1271
;
int
wl1271_event_unmask
(
struct
wl1271
*
wl
);
int
wl1271_event_unmask
(
struct
wl1271
*
wl
);
int
wl1271_event_handle
(
struct
wl1271
*
wl
,
u8
mbox
);
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_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
#endif
drivers/net/wireless/ti/wlcore/hw_ops.h
浏览文件 @
56e1bd77
...
@@ -201,4 +201,45 @@ wlcore_hw_pre_pkt_send(struct wl1271 *wl, u32 buf_offset, u32 last_len)
...
@@ -201,4 +201,45 @@ wlcore_hw_pre_pkt_send(struct wl1271 *wl, u32 buf_offset, u32 last_len)
return
buf_offset
;
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
);
}
static
inline
int
wlcore_hw_set_peer_cap
(
struct
wl1271
*
wl
,
struct
ieee80211_sta_ht_cap
*
ht_cap
,
bool
allow_ht_operation
,
u32
rate_set
,
u8
hlid
)
{
if
(
wl
->
ops
->
set_peer_cap
)
return
wl
->
ops
->
set_peer_cap
(
wl
,
ht_cap
,
allow_ht_operation
,
rate_set
,
hlid
);
return
0
;
}
static
inline
bool
wlcore_hw_lnk_high_prio
(
struct
wl1271
*
wl
,
u8
hlid
,
struct
wl1271_link
*
lnk
)
{
if
(
!
wl
->
ops
->
lnk_high_prio
)
BUG_ON
(
1
);
return
wl
->
ops
->
lnk_high_prio
(
wl
,
hlid
,
lnk
);
}
static
inline
bool
wlcore_hw_lnk_low_prio
(
struct
wl1271
*
wl
,
u8
hlid
,
struct
wl1271_link
*
lnk
)
{
if
(
!
wl
->
ops
->
lnk_low_prio
)
BUG_ON
(
1
);
return
wl
->
ops
->
lnk_low_prio
(
wl
,
hlid
,
lnk
);
}
#endif
#endif
drivers/net/wireless/ti/wlcore/init.c
浏览文件 @
56e1bd77
...
@@ -41,14 +41,14 @@ int wl1271_init_templates_config(struct wl1271 *wl)
...
@@ -41,14 +41,14 @@ int wl1271_init_templates_config(struct wl1271 *wl)
/* send empty templates for fw memory reservation */
/* send empty templates for fw memory reservation */
ret
=
wl1271_cmd_template_set
(
wl
,
WL12XX_INVALID_ROLE_ID
,
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
,
WL1271_CMD_TEMPL_MAX_SIZE
,
0
,
WL1271_RATE_AUTOMATIC
);
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
ret
=
wl1271_cmd_template_set
(
wl
,
WL12XX_INVALID_ROLE_ID
,
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
,
NULL
,
WL1271_CMD_TEMPL_MAX_SIZE
,
0
,
WL1271_RATE_AUTOMATIC
);
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
if
(
ret
<
0
)
...
@@ -56,14 +56,16 @@ int wl1271_init_templates_config(struct wl1271 *wl)
...
@@ -56,14 +56,16 @@ int wl1271_init_templates_config(struct wl1271 *wl)
if
(
wl
->
quirks
&
WLCORE_QUIRK_DUAL_PROBE_TMPL
)
{
if
(
wl
->
quirks
&
WLCORE_QUIRK_DUAL_PROBE_TMPL
)
{
ret
=
wl1271_cmd_template_set
(
wl
,
WL12XX_INVALID_ROLE_ID
,
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
,
WL1271_CMD_TEMPL_MAX_SIZE
,
0
,
WL1271_RATE_AUTOMATIC
);
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
ret
=
wl1271_cmd_template_set
(
wl
,
WL12XX_INVALID_ROLE_ID
,
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
,
WL1271_CMD_TEMPL_MAX_SIZE
,
0
,
WL1271_RATE_AUTOMATIC
);
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
if
(
ret
<
0
)
...
@@ -463,7 +465,7 @@ int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif)
...
@@ -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
))
if
((
wlvif
->
basic_rate_set
&
CONF_TX_OFDM_RATES
))
supported_rates
=
CONF_TX_OFDM_RATES
;
supported_rates
=
CONF_TX_OFDM_RATES
;
else
else
supported_rates
=
CONF_TX_
AP_
ENABLED_RATES
;
supported_rates
=
CONF_TX_ENABLED_RATES
;
/* unconditionally enable HT rates */
/* unconditionally enable HT rates */
supported_rates
|=
CONF_TX_MCS_RATES
;
supported_rates
|=
CONF_TX_MCS_RATES
;
...
@@ -575,9 +577,6 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif)
...
@@ -575,9 +577,6 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif)
/* Configure for power according to debugfs */
/* Configure for power according to debugfs */
if
(
sta_auth
!=
WL1271_PSM_ILLEGAL
)
if
(
sta_auth
!=
WL1271_PSM_ILLEGAL
)
ret
=
wl1271_acx_sleep_auth
(
wl
,
sta_auth
);
ret
=
wl1271_acx_sleep_auth
(
wl
,
sta_auth
);
/* Configure for power always on */
else
if
(
wl
->
quirks
&
WLCORE_QUIRK_NO_ELP
)
ret
=
wl1271_acx_sleep_auth
(
wl
,
WL1271_PSM_CAM
);
/* Configure for ELP power saving */
/* Configure for ELP power saving */
else
else
ret
=
wl1271_acx_sleep_auth
(
wl
,
WL1271_PSM_ELP
);
ret
=
wl1271_acx_sleep_auth
(
wl
,
WL1271_PSM_ELP
);
...
@@ -679,6 +678,10 @@ int wl1271_hw_init(struct wl1271 *wl)
...
@@ -679,6 +678,10 @@ int wl1271_hw_init(struct wl1271 *wl)
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
ret
=
wlcore_cmd_regdomain_config_locked
(
wl
);
if
(
ret
<
0
)
return
ret
;
/* Bluetooth WLAN coexistence */
/* Bluetooth WLAN coexistence */
ret
=
wl1271_init_pta
(
wl
);
ret
=
wl1271_init_pta
(
wl
);
if
(
ret
<
0
)
if
(
ret
<
0
)
...
...
drivers/net/wireless/ti/wlcore/io.h
浏览文件 @
56e1bd77
...
@@ -105,13 +105,13 @@ static inline int __must_check wlcore_raw_read32(struct wl1271 *wl, int addr,
...
@@ -105,13 +105,13 @@ static inline int __must_check wlcore_raw_read32(struct wl1271 *wl, int addr,
{
{
int
ret
;
int
ret
;
ret
=
wlcore_raw_read
(
wl
,
addr
,
&
wl
->
buffer_32
,
ret
=
wlcore_raw_read
(
wl
,
addr
,
wl
->
buffer_32
,
sizeof
(
wl
->
buffer_32
),
false
);
sizeof
(
*
wl
->
buffer_32
),
false
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
if
(
val
)
if
(
val
)
*
val
=
le32_to_cpu
(
wl
->
buffer_32
);
*
val
=
le32_to_cpu
(
*
wl
->
buffer_32
);
return
0
;
return
0
;
}
}
...
@@ -119,9 +119,9 @@ static inline int __must_check wlcore_raw_read32(struct wl1271 *wl, int addr,
...
@@ -119,9 +119,9 @@ static inline int __must_check wlcore_raw_read32(struct wl1271 *wl, int addr,
static
inline
int
__must_check
wlcore_raw_write32
(
struct
wl1271
*
wl
,
int
addr
,
static
inline
int
__must_check
wlcore_raw_write32
(
struct
wl1271
*
wl
,
int
addr
,
u32
val
)
u32
val
)
{
{
wl
->
buffer_32
=
cpu_to_le32
(
val
);
*
wl
->
buffer_32
=
cpu_to_le32
(
val
);
return
wlcore_raw_write
(
wl
,
addr
,
&
wl
->
buffer_32
,
return
wlcore_raw_write
(
wl
,
addr
,
wl
->
buffer_32
,
sizeof
(
wl
->
buffer_32
),
false
);
sizeof
(
*
wl
->
buffer_32
),
false
);
}
}
static
inline
int
__must_check
wlcore_read
(
struct
wl1271
*
wl
,
int
addr
,
static
inline
int
__must_check
wlcore_read
(
struct
wl1271
*
wl
,
int
addr
,
...
...
drivers/net/wireless/ti/wlcore/main.c
浏览文件 @
56e1bd77
此差异已折叠。
点击以展开。
drivers/net/wireless/ti/wlcore/ps.c
浏览文件 @
56e1bd77
...
@@ -151,9 +151,6 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)
...
@@ -151,9 +151,6 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)
wl12xx_queue_recovery_work
(
wl
);
wl12xx_queue_recovery_work
(
wl
);
ret
=
-
ETIMEDOUT
;
ret
=
-
ETIMEDOUT
;
goto
err
;
goto
err
;
}
else
if
(
ret
<
0
)
{
wl1271_error
(
"ELP wakeup completion error."
);
goto
err
;
}
}
}
}
...
@@ -242,11 +239,12 @@ static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid)
...
@@ -242,11 +239,12 @@ static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid)
struct
ieee80211_tx_info
*
info
;
struct
ieee80211_tx_info
*
info
;
unsigned
long
flags
;
unsigned
long
flags
;
int
filtered
[
NUM_TX_QUEUES
];
int
filtered
[
NUM_TX_QUEUES
];
struct
wl1271_link
*
lnk
=
&
wl
->
links
[
hlid
];
/* filter all frames currently in the low level queues for this hlid */
/* filter all frames currently in the low level queues for this hlid */
for
(
i
=
0
;
i
<
NUM_TX_QUEUES
;
i
++
)
{
for
(
i
=
0
;
i
<
NUM_TX_QUEUES
;
i
++
)
{
filtered
[
i
]
=
0
;
filtered
[
i
]
=
0
;
while
((
skb
=
skb_dequeue
(
&
wl
->
links
[
hlid
].
tx_queue
[
i
])))
{
while
((
skb
=
skb_dequeue
(
&
lnk
->
tx_queue
[
i
])))
{
filtered
[
i
]
++
;
filtered
[
i
]
++
;
if
(
WARN_ON
(
wl12xx_is_dummy_packet
(
wl
,
skb
)))
if
(
WARN_ON
(
wl12xx_is_dummy_packet
(
wl
,
skb
)))
...
@@ -260,8 +258,11 @@ static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid)
...
@@ -260,8 +258,11 @@ static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid)
}
}
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
for
(
i
=
0
;
i
<
NUM_TX_QUEUES
;
i
++
)
for
(
i
=
0
;
i
<
NUM_TX_QUEUES
;
i
++
)
{
wl
->
tx_queue_count
[
i
]
-=
filtered
[
i
];
wl
->
tx_queue_count
[
i
]
-=
filtered
[
i
];
if
(
lnk
->
wlvif
)
lnk
->
wlvif
->
tx_queue_count
[
i
]
-=
filtered
[
i
];
}
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
wl1271_handle_tx_low_watermark
(
wl
);
wl1271_handle_tx_low_watermark
(
wl
);
...
...
drivers/net/wireless/ti/wlcore/rx.c
浏览文件 @
56e1bd77
...
@@ -92,11 +92,16 @@ static void wl1271_rx_status(struct wl1271 *wl,
...
@@ -92,11 +92,16 @@ static void wl1271_rx_status(struct wl1271 *wl,
status
->
flag
|=
RX_FLAG_IV_STRIPPED
|
RX_FLAG_MMIC_STRIPPED
|
status
->
flag
|=
RX_FLAG_IV_STRIPPED
|
RX_FLAG_MMIC_STRIPPED
|
RX_FLAG_DECRYPTED
;
RX_FLAG_DECRYPTED
;
if
(
unlikely
(
desc_err_code
==
WL1271_RX_DESC_MIC_FAIL
))
{
if
(
unlikely
(
desc_err_code
&
WL1271_RX_DESC_MIC_FAIL
))
{
status
->
flag
|=
RX_FLAG_MMIC_ERROR
;
status
->
flag
|=
RX_FLAG_MMIC_ERROR
;
wl1271_warning
(
"Michael MIC error"
);
wl1271_warning
(
"Michael MIC error. Desc: 0x%x"
,
desc_err_code
);
}
}
}
}
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
,
static
int
wl1271_rx_handle_data
(
struct
wl1271
*
wl
,
u8
*
data
,
u32
length
,
...
@@ -108,7 +113,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
...
@@ -108,7 +113,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
u8
*
buf
;
u8
*
buf
;
u8
beacon
=
0
;
u8
beacon
=
0
;
u8
is_data
=
0
;
u8
is_data
=
0
;
u8
reserved
=
0
;
u8
reserved
=
0
,
offset_to_data
=
0
;
u16
seq_num
;
u16
seq_num
;
u32
pkt_data_len
;
u32
pkt_data_len
;
...
@@ -128,6 +133,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
...
@@ -128,6 +133,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
if
(
rx_align
==
WLCORE_RX_BUF_UNALIGNED
)
if
(
rx_align
==
WLCORE_RX_BUF_UNALIGNED
)
reserved
=
RX_BUF_ALIGN
;
reserved
=
RX_BUF_ALIGN
;
else
if
(
rx_align
==
WLCORE_RX_BUF_PADDED
)
offset_to_data
=
RX_BUF_ALIGN
;
/* the data read starts with the descriptor */
/* the data read starts with the descriptor */
desc
=
(
struct
wl1271_rx_descriptor
*
)
data
;
desc
=
(
struct
wl1271_rx_descriptor
*
)
data
;
...
@@ -139,19 +146,15 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
...
@@ -139,19 +146,15 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
return
0
;
return
0
;
}
}
switch
(
desc
->
status
&
WL1271_RX_DESC_STATUS_MASK
)
{
/* discard corrupted packets */
/* discard corrupted packets */
case
WL1271_RX_DESC_DRIVER_RX_Q_FAIL
:
if
(
desc
->
status
&
WL1271_RX_DESC_DECRYPT_FAIL
)
{
case
WL1271_RX_DESC_DECRYPT_FAIL
:
hdr
=
(
void
*
)(
data
+
sizeof
(
*
desc
)
+
offset_to_data
);
wl1271_warning
(
"corrupted packet in RX with status: 0x%x"
,
wl1271_warning
(
"corrupted packet in RX: status: 0x%x len: %d"
,
desc
->
status
&
WL1271_RX_DESC_STATUS_MASK
);
desc
->
status
&
WL1271_RX_DESC_STATUS_MASK
,
return
-
EINVAL
;
pkt_data_len
);
case
WL1271_RX_DESC_SUCCESS
:
wl1271_dump
((
DEBUG_RX
|
DEBUG_CMD
),
"PKT: "
,
data
+
sizeof
(
*
desc
),
case
WL1271_RX_DESC_MIC_FAIL
:
min
(
pkt_data_len
,
break
;
ieee80211_hdrlen
(
hdr
->
frame_control
)));
default:
wl1271_error
(
"invalid RX descriptor status: 0x%x"
,
desc
->
status
&
WL1271_RX_DESC_STATUS_MASK
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
...
...
drivers/net/wireless/ti/wlcore/rx.h
浏览文件 @
56e1bd77
...
@@ -84,12 +84,11 @@
...
@@ -84,12 +84,11 @@
* Bits 3-5 - process_id tag (AP mode FW)
* Bits 3-5 - process_id tag (AP mode FW)
* Bits 6-7 - reserved
* Bits 6-7 - reserved
*/
*/
#define WL1271_RX_DESC_STATUS_MASK 0x0
3
#define WL1271_RX_DESC_STATUS_MASK 0x0
7
#define WL1271_RX_DESC_SUCCESS 0x00
#define WL1271_RX_DESC_SUCCESS 0x00
#define WL1271_RX_DESC_DECRYPT_FAIL 0x01
#define WL1271_RX_DESC_DECRYPT_FAIL 0x01
#define WL1271_RX_DESC_MIC_FAIL 0x02
#define WL1271_RX_DESC_MIC_FAIL 0x02
#define WL1271_RX_DESC_DRIVER_RX_Q_FAIL 0x03
#define RX_MEM_BLOCK_MASK 0xFF
#define RX_MEM_BLOCK_MASK 0xFF
#define RX_BUF_SIZE_MASK 0xFFF00
#define RX_BUF_SIZE_MASK 0xFFF00
...
...
drivers/net/wireless/ti/wlcore/scan.c
浏览文件 @
56e1bd77
此差异已折叠。
点击以展开。
drivers/net/wireless/ti/wlcore/scan.h
浏览文件 @
56e1bd77
此差异已折叠。
点击以展开。
drivers/net/wireless/ti/wlcore/sdio.c
浏览文件 @
56e1bd77
...
@@ -326,8 +326,7 @@ static void wl1271_remove(struct sdio_func *func)
...
@@ -326,8 +326,7 @@ static void wl1271_remove(struct sdio_func *func)
/* Undo decrement done above in wl1271_probe */
/* Undo decrement done above in wl1271_probe */
pm_runtime_get_noresume
(
&
func
->
dev
);
pm_runtime_get_noresume
(
&
func
->
dev
);
platform_device_del
(
glue
->
core
);
platform_device_unregister
(
glue
->
core
);
platform_device_put
(
glue
->
core
);
kfree
(
glue
);
kfree
(
glue
);
}
}
...
...
drivers/net/wireless/ti/wlcore/spi.c
浏览文件 @
56e1bd77
此差异已折叠。
点击以展开。
drivers/net/wireless/ti/wlcore/tx.c
浏览文件 @
56e1bd77
此差异已折叠。
点击以展开。
drivers/net/wireless/ti/wlcore/tx.h
浏览文件 @
56e1bd77
此差异已折叠。
点击以展开。
drivers/net/wireless/ti/wlcore/wlcore.h
浏览文件 @
56e1bd77
此差异已折叠。
点击以展开。
drivers/net/wireless/ti/wlcore/wlcore_i.h
浏览文件 @
56e1bd77
此差异已折叠。
点击以展开。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录