Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
333c0dbf
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
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看板
提交
333c0dbf
编写于
7月 06, 2011
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'for-linville' of
git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx
上级
115f9450
95dac04f
变更
24
展开全部
隐藏空白更改
内联
并排
Showing
24 changed file
with
1176 addition
and
244 deletion
+1176
-244
drivers/net/wireless/wl12xx/Kconfig
drivers/net/wireless/wl12xx/Kconfig
+1
-1
drivers/net/wireless/wl12xx/acx.c
drivers/net/wireless/wl12xx/acx.c
+48
-1
drivers/net/wireless/wl12xx/acx.h
drivers/net/wireless/wl12xx/acx.h
+16
-0
drivers/net/wireless/wl12xx/boot.c
drivers/net/wireless/wl12xx/boot.c
+33
-0
drivers/net/wireless/wl12xx/cmd.c
drivers/net/wireless/wl12xx/cmd.c
+91
-3
drivers/net/wireless/wl12xx/cmd.h
drivers/net/wireless/wl12xx/cmd.h
+62
-0
drivers/net/wireless/wl12xx/conf.h
drivers/net/wireless/wl12xx/conf.h
+55
-0
drivers/net/wireless/wl12xx/debugfs.c
drivers/net/wireless/wl12xx/debugfs.c
+136
-2
drivers/net/wireless/wl12xx/event.c
drivers/net/wireless/wl12xx/event.c
+25
-11
drivers/net/wireless/wl12xx/ini.h
drivers/net/wireless/wl12xx/ini.h
+3
-0
drivers/net/wireless/wl12xx/init.c
drivers/net/wireless/wl12xx/init.c
+19
-0
drivers/net/wireless/wl12xx/io.c
drivers/net/wireless/wl12xx/io.c
+4
-3
drivers/net/wireless/wl12xx/io.h
drivers/net/wireless/wl12xx/io.h
+14
-0
drivers/net/wireless/wl12xx/main.c
drivers/net/wireless/wl12xx/main.c
+484
-106
drivers/net/wireless/wl12xx/ps.c
drivers/net/wireless/wl12xx/ps.c
+7
-5
drivers/net/wireless/wl12xx/rx.c
drivers/net/wireless/wl12xx/rx.c
+34
-5
drivers/net/wireless/wl12xx/rx.h
drivers/net/wireless/wl12xx/rx.h
+12
-0
drivers/net/wireless/wl12xx/scan.c
drivers/net/wireless/wl12xx/scan.c
+30
-33
drivers/net/wireless/wl12xx/scan.h
drivers/net/wireless/wl12xx/scan.h
+7
-10
drivers/net/wireless/wl12xx/sdio.c
drivers/net/wireless/wl12xx/sdio.c
+28
-43
drivers/net/wireless/wl12xx/spi.c
drivers/net/wireless/wl12xx/spi.c
+1
-14
drivers/net/wireless/wl12xx/testmode.c
drivers/net/wireless/wl12xx/testmode.c
+1
-1
drivers/net/wireless/wl12xx/tx.c
drivers/net/wireless/wl12xx/tx.c
+29
-4
drivers/net/wireless/wl12xx/wl12xx.h
drivers/net/wireless/wl12xx/wl12xx.h
+36
-2
未找到文件。
drivers/net/wireless/wl12xx/Kconfig
浏览文件 @
333c0dbf
...
...
@@ -11,7 +11,6 @@ config WL12XX
depends on WL12XX_MENU && GENERIC_HARDIRQS
depends on INET
select FW_LOADER
select CRC7
---help---
This module adds support for wireless adapters based on TI wl1271 and
TI wl1273 chipsets. This module does *not* include support for wl1251.
...
...
@@ -33,6 +32,7 @@ config WL12XX_HT
config WL12XX_SPI
tristate "TI wl12xx SPI support"
depends on WL12XX && SPI_MASTER
select CRC7
---help---
This module adds support for the SPI interface of adapters using
TI wl12xx chipsets. Select this if your platform is using
...
...
drivers/net/wireless/wl12xx/acx.c
浏览文件 @
333c0dbf
...
...
@@ -25,7 +25,6 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/crc7.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
...
...
@@ -1068,6 +1067,7 @@ int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
mem_conf
->
tx_free_req
=
mem
->
min_req_tx_blocks
;
mem_conf
->
rx_free_req
=
mem
->
min_req_rx_blocks
;
mem_conf
->
tx_min
=
mem
->
tx_min
;
mem_conf
->
fwlog_blocks
=
wl
->
conf
.
fwlog
.
mem_blocks
;
ret
=
wl1271_cmd_configure
(
wl
,
ACX_MEM_CFG
,
mem_conf
,
sizeof
(
*
mem_conf
));
...
...
@@ -1577,6 +1577,53 @@ int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime)
return
ret
;
}
int
wl1271_acx_ps_rx_streaming
(
struct
wl1271
*
wl
,
bool
enable
)
{
struct
wl1271_acx_ps_rx_streaming
*
rx_streaming
;
u32
conf_queues
,
enable_queues
;
int
i
,
ret
=
0
;
wl1271_debug
(
DEBUG_ACX
,
"acx ps rx streaming"
);
rx_streaming
=
kzalloc
(
sizeof
(
*
rx_streaming
),
GFP_KERNEL
);
if
(
!
rx_streaming
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
conf_queues
=
wl
->
conf
.
rx_streaming
.
queues
;
if
(
enable
)
enable_queues
=
conf_queues
;
else
enable_queues
=
0
;
for
(
i
=
0
;
i
<
8
;
i
++
)
{
/*
* Skip non-changed queues, to avoid redundant acxs.
* this check assumes conf.rx_streaming.queues can't
* be changed while rx_streaming is enabled.
*/
if
(
!
(
conf_queues
&
BIT
(
i
)))
continue
;
rx_streaming
->
tid
=
i
;
rx_streaming
->
enable
=
enable_queues
&
BIT
(
i
);
rx_streaming
->
period
=
wl
->
conf
.
rx_streaming
.
interval
;
rx_streaming
->
timeout
=
wl
->
conf
.
rx_streaming
.
interval
;
ret
=
wl1271_cmd_configure
(
wl
,
ACX_PS_RX_STREAMING
,
rx_streaming
,
sizeof
(
*
rx_streaming
));
if
(
ret
<
0
)
{
wl1271_warning
(
"acx ps rx streaming failed: %d"
,
ret
);
goto
out
;
}
}
out:
kfree
(
rx_streaming
);
return
ret
;
}
int
wl1271_acx_max_tx_retry
(
struct
wl1271
*
wl
)
{
struct
wl1271_acx_max_tx_retry
*
acx
=
NULL
;
...
...
drivers/net/wireless/wl12xx/acx.h
浏览文件 @
333c0dbf
...
...
@@ -828,6 +828,8 @@ struct wl1271_acx_sta_config_memory {
u8
tx_free_req
;
u8
rx_free_req
;
u8
tx_min
;
u8
fwlog_blocks
;
u8
padding
[
3
];
}
__packed
;
struct
wl1271_acx_mem_map
{
...
...
@@ -1153,6 +1155,19 @@ struct wl1271_acx_fw_tsf_information {
u8
padding
[
3
];
}
__packed
;
struct
wl1271_acx_ps_rx_streaming
{
struct
acx_header
header
;
u8
tid
;
u8
enable
;
/* interval between triggers (10-100 msec) */
u8
period
;
/* timeout before first trigger (0-200 msec) */
u8
timeout
;
}
__packed
;
struct
wl1271_acx_max_tx_retry
{
struct
acx_header
header
;
...
...
@@ -1384,6 +1399,7 @@ int wl1271_acx_set_ba_session(struct wl1271 *wl,
int
wl1271_acx_set_ba_receiver_session
(
struct
wl1271
*
wl
,
u8
tid_index
,
u16
ssn
,
bool
enable
);
int
wl1271_acx_tsf_info
(
struct
wl1271
*
wl
,
u64
*
mactime
);
int
wl1271_acx_ps_rx_streaming
(
struct
wl1271
*
wl
,
bool
enable
);
int
wl1271_acx_max_tx_retry
(
struct
wl1271
*
wl
);
int
wl1271_acx_config_ps
(
struct
wl1271
*
wl
);
int
wl1271_acx_set_inconnection_sta
(
struct
wl1271
*
wl
,
u8
*
addr
);
...
...
drivers/net/wireless/wl12xx/boot.c
浏览文件 @
333c0dbf
...
...
@@ -102,6 +102,33 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
wl1271_write32
(
wl
,
ACX_REG_ECPU_CONTROL
,
cpu_ctrl
);
}
static
unsigned
int
wl12xx_get_fw_ver_quirks
(
struct
wl1271
*
wl
)
{
unsigned
int
quirks
=
0
;
unsigned
int
*
fw_ver
=
wl
->
chip
.
fw_ver
;
/* Only for wl127x */
if
((
fw_ver
[
FW_VER_CHIP
]
==
FW_VER_CHIP_WL127X
)
&&
/* Check STA version */
(((
fw_ver
[
FW_VER_IF_TYPE
]
==
FW_VER_IF_TYPE_STA
)
&&
(
fw_ver
[
FW_VER_MINOR
]
<
FW_VER_MINOR_1_SPARE_STA_MIN
))
||
/* Check AP version */
((
fw_ver
[
FW_VER_IF_TYPE
]
==
FW_VER_IF_TYPE_AP
)
&&
(
fw_ver
[
FW_VER_MINOR
]
<
FW_VER_MINOR_1_SPARE_AP_MIN
))))
quirks
|=
WL12XX_QUIRK_USE_2_SPARE_BLOCKS
;
/* 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
))
quirks
|=
WL12XX_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
)
quirks
|=
WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED
;
return
quirks
;
}
static
void
wl1271_parse_fw_ver
(
struct
wl1271
*
wl
)
{
int
ret
;
...
...
@@ -116,6 +143,9 @@ static void wl1271_parse_fw_ver(struct wl1271 *wl)
memset
(
wl
->
chip
.
fw_ver
,
0
,
sizeof
(
wl
->
chip
.
fw_ver
));
return
;
}
/* Check if any quirks are needed with older fw versions */
wl
->
quirks
|=
wl12xx_get_fw_ver_quirks
(
wl
);
}
static
void
wl1271_boot_fw_version
(
struct
wl1271
*
wl
)
...
...
@@ -749,6 +779,9 @@ int wl1271_load_firmware(struct wl1271 *wl)
clk
|=
(
wl
->
ref_clock
<<
1
)
<<
4
;
}
if
(
wl
->
quirks
&
WL12XX_QUIRK_LPD_MODE
)
clk
|=
SCRATCH_ENABLE_LPD
;
wl1271_write32
(
wl
,
DRPW_SCRATCH_START
,
clk
);
wl1271_set_partition
(
wl
,
&
part_table
[
PART_WORK
]);
...
...
drivers/net/wireless/wl12xx/cmd.c
浏览文件 @
333c0dbf
...
...
@@ -23,7 +23,6 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/crc7.h>
#include <linux/spi/spi.h>
#include <linux/etherdevice.h>
#include <linux/ieee80211.h>
...
...
@@ -106,7 +105,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
fail:
WARN_ON
(
1
);
ieee80211_queue_work
(
wl
->
hw
,
&
wl
->
recovery_work
);
wl12xx_queue_recovery_work
(
wl
);
return
ret
;
}
...
...
@@ -135,6 +134,11 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
/* Override the REF CLK from the NVS with the one from platform data */
gen_parms
->
general_params
.
ref_clock
=
wl
->
ref_clock
;
/* LPD mode enable (bits 6-7) in WL1271 AP mode only */
if
(
wl
->
quirks
&
WL12XX_QUIRK_LPD_MODE
)
gen_parms
->
general_params
.
general_settings
|=
GENERAL_SETTINGS_DRPW_LPD
;
ret
=
wl1271_cmd_test
(
wl
,
gen_parms
,
sizeof
(
*
gen_parms
),
answer
);
if
(
ret
<
0
)
{
wl1271_warning
(
"CMD_INI_FILE_GENERAL_PARAM failed"
);
...
...
@@ -352,7 +356,7 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
ret
=
wl1271_cmd_wait_for_event_or_timeout
(
wl
,
mask
);
if
(
ret
!=
0
)
{
ieee80211_queue_work
(
wl
->
hw
,
&
wl
->
recovery_work
);
wl12xx_queue_recovery_work
(
wl
);
return
ret
;
}
...
...
@@ -1223,3 +1227,87 @@ int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid)
out:
return
ret
;
}
int
wl12xx_cmd_config_fwlog
(
struct
wl1271
*
wl
)
{
struct
wl12xx_cmd_config_fwlog
*
cmd
;
int
ret
=
0
;
wl1271_debug
(
DEBUG_CMD
,
"cmd config firmware logger"
);
cmd
=
kzalloc
(
sizeof
(
*
cmd
),
GFP_KERNEL
);
if
(
!
cmd
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
cmd
->
logger_mode
=
wl
->
conf
.
fwlog
.
mode
;
cmd
->
log_severity
=
wl
->
conf
.
fwlog
.
severity
;
cmd
->
timestamp
=
wl
->
conf
.
fwlog
.
timestamp
;
cmd
->
output
=
wl
->
conf
.
fwlog
.
output
;
cmd
->
threshold
=
wl
->
conf
.
fwlog
.
threshold
;
ret
=
wl1271_cmd_send
(
wl
,
CMD_CONFIG_FWLOGGER
,
cmd
,
sizeof
(
*
cmd
),
0
);
if
(
ret
<
0
)
{
wl1271_error
(
"failed to send config firmware logger command"
);
goto
out_free
;
}
out_free:
kfree
(
cmd
);
out:
return
ret
;
}
int
wl12xx_cmd_start_fwlog
(
struct
wl1271
*
wl
)
{
struct
wl12xx_cmd_start_fwlog
*
cmd
;
int
ret
=
0
;
wl1271_debug
(
DEBUG_CMD
,
"cmd start firmware logger"
);
cmd
=
kzalloc
(
sizeof
(
*
cmd
),
GFP_KERNEL
);
if
(
!
cmd
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
ret
=
wl1271_cmd_send
(
wl
,
CMD_START_FWLOGGER
,
cmd
,
sizeof
(
*
cmd
),
0
);
if
(
ret
<
0
)
{
wl1271_error
(
"failed to send start firmware logger command"
);
goto
out_free
;
}
out_free:
kfree
(
cmd
);
out:
return
ret
;
}
int
wl12xx_cmd_stop_fwlog
(
struct
wl1271
*
wl
)
{
struct
wl12xx_cmd_stop_fwlog
*
cmd
;
int
ret
=
0
;
wl1271_debug
(
DEBUG_CMD
,
"cmd stop firmware logger"
);
cmd
=
kzalloc
(
sizeof
(
*
cmd
),
GFP_KERNEL
);
if
(
!
cmd
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
ret
=
wl1271_cmd_send
(
wl
,
CMD_STOP_FWLOGGER
,
cmd
,
sizeof
(
*
cmd
),
0
);
if
(
ret
<
0
)
{
wl1271_error
(
"failed to send stop firmware logger command"
);
goto
out_free
;
}
out_free:
kfree
(
cmd
);
out:
return
ret
;
}
drivers/net/wireless/wl12xx/cmd.h
浏览文件 @
333c0dbf
...
...
@@ -70,6 +70,9 @@ int wl1271_cmd_start_bss(struct wl1271 *wl);
int
wl1271_cmd_stop_bss
(
struct
wl1271
*
wl
);
int
wl1271_cmd_add_sta
(
struct
wl1271
*
wl
,
struct
ieee80211_sta
*
sta
,
u8
hlid
);
int
wl1271_cmd_remove_sta
(
struct
wl1271
*
wl
,
u8
hlid
);
int
wl12xx_cmd_config_fwlog
(
struct
wl1271
*
wl
);
int
wl12xx_cmd_start_fwlog
(
struct
wl1271
*
wl
);
int
wl12xx_cmd_stop_fwlog
(
struct
wl1271
*
wl
);
enum
wl1271_commands
{
CMD_INTERROGATE
=
1
,
/*use this to read information elements*/
...
...
@@ -107,6 +110,9 @@ enum wl1271_commands {
CMD_START_PERIODIC_SCAN
=
50
,
CMD_STOP_PERIODIC_SCAN
=
51
,
CMD_SET_STA_STATE
=
52
,
CMD_CONFIG_FWLOGGER
=
53
,
CMD_START_FWLOGGER
=
54
,
CMD_STOP_FWLOGGER
=
55
,
/* AP mode commands */
CMD_BSS_START
=
60
,
...
...
@@ -575,4 +581,60 @@ struct wl1271_cmd_remove_sta {
u8
padding1
;
}
__packed
;
/*
* Continuous mode - packets are transferred to the host periodically
* via the data path.
* On demand - Log messages are stored in a cyclic buffer in the
* firmware, and only transferred to the host when explicitly requested
*/
enum
wl12xx_fwlogger_log_mode
{
WL12XX_FWLOG_CONTINUOUS
,
WL12XX_FWLOG_ON_DEMAND
};
/* Include/exclude timestamps from the log messages */
enum
wl12xx_fwlogger_timestamp
{
WL12XX_FWLOG_TIMESTAMP_DISABLED
,
WL12XX_FWLOG_TIMESTAMP_ENABLED
};
/*
* Logs can be routed to the debug pinouts (where available), to the host bus
* (SDIO/SPI), or dropped
*/
enum
wl12xx_fwlogger_output
{
WL12XX_FWLOG_OUTPUT_NONE
,
WL12XX_FWLOG_OUTPUT_DBG_PINS
,
WL12XX_FWLOG_OUTPUT_HOST
,
};
struct
wl12xx_cmd_config_fwlog
{
struct
wl1271_cmd_header
header
;
/* See enum wl12xx_fwlogger_log_mode */
u8
logger_mode
;
/* Minimum log level threshold */
u8
log_severity
;
/* Include/exclude timestamps from the log messages */
u8
timestamp
;
/* See enum wl1271_fwlogger_output */
u8
output
;
/* Regulates the frequency of log messages */
u8
threshold
;
u8
padding
[
3
];
}
__packed
;
struct
wl12xx_cmd_start_fwlog
{
struct
wl1271_cmd_header
header
;
}
__packed
;
struct
wl12xx_cmd_stop_fwlog
{
struct
wl1271_cmd_header
header
;
}
__packed
;
#endif
/* __WL1271_CMD_H__ */
drivers/net/wireless/wl12xx/conf.h
浏览文件 @
333c0dbf
...
...
@@ -1248,6 +1248,59 @@ struct conf_fm_coex {
u8
swallow_clk_diff
;
};
struct
conf_rx_streaming_settings
{
/*
* RX Streaming duration (in msec) from last tx/rx
*
* Range: u32
*/
u32
duration
;
/*
* Bitmap of tids to be polled during RX streaming.
* (Note: it doesn't look like it really matters)
*
* Range: 0x1-0xff
*/
u8
queues
;
/*
* RX Streaming interval.
* (Note:this value is also used as the rx streaming timeout)
* Range: 0 (disabled), 10 - 100
*/
u8
interval
;
/*
* enable rx streaming also when there is no coex activity
*/
u8
always
;
};
struct
conf_fwlog
{
/* Continuous or on-demand */
u8
mode
;
/*
* Number of memory blocks dedicated for the FW logger
*
* Range: 1-3, or 0 to disable the FW logger
*/
u8
mem_blocks
;
/* Minimum log level threshold */
u8
severity
;
/* Include/exclude timestamps from the log messages */
u8
timestamp
;
/* See enum wl1271_fwlogger_output */
u8
output
;
/* Regulates the frequency of log messages */
u8
threshold
;
};
struct
conf_drv_settings
{
struct
conf_sg_settings
sg
;
struct
conf_rx_settings
rx
;
...
...
@@ -1263,6 +1316,8 @@ struct conf_drv_settings {
struct
conf_memory_settings
mem_wl127x
;
struct
conf_memory_settings
mem_wl128x
;
struct
conf_fm_coex
fm_coex
;
struct
conf_rx_streaming_settings
rx_streaming
;
struct
conf_fwlog
fwlog
;
u8
hci_io_ds
;
};
...
...
drivers/net/wireless/wl12xx/debugfs.c
浏览文件 @
333c0dbf
...
...
@@ -71,6 +71,14 @@ static const struct file_operations name## _ops = { \
if (!entry || IS_ERR(entry)) \
goto err; \
#define DEBUGFS_ADD_PREFIX(prefix, name, parent) \
do { \
entry = debugfs_create_file(#name, 0400, parent, \
wl, &prefix## _## name## _ops); \
if (!entry || IS_ERR(entry)) \
goto err; \
} while (0);
#define DEBUGFS_FWSTATS_FILE(sub, name, fmt) \
static ssize_t sub## _ ##name## _read(struct file *file, \
char __user *userbuf, \
...
...
@@ -298,7 +306,7 @@ static ssize_t start_recovery_write(struct file *file,
struct
wl1271
*
wl
=
file
->
private_data
;
mutex_lock
(
&
wl
->
mutex
);
ieee80211_queue_work
(
wl
->
hw
,
&
wl
->
recovery_work
);
wl12xx_queue_recovery_work
(
wl
);
mutex_unlock
(
&
wl
->
mutex
);
return
count
;
...
...
@@ -527,11 +535,129 @@ static const struct file_operations beacon_interval_ops = {
.
llseek
=
default_llseek
,
};
static
ssize_t
rx_streaming_interval_write
(
struct
file
*
file
,
const
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
wl1271
*
wl
=
file
->
private_data
;
char
buf
[
10
];
size_t
len
;
unsigned
long
value
;
int
ret
;
len
=
min
(
count
,
sizeof
(
buf
)
-
1
);
if
(
copy_from_user
(
buf
,
user_buf
,
len
))
return
-
EFAULT
;
buf
[
len
]
=
'\0'
;
ret
=
kstrtoul
(
buf
,
0
,
&
value
);
if
(
ret
<
0
)
{
wl1271_warning
(
"illegal value in rx_streaming_interval!"
);
return
-
EINVAL
;
}
/* valid values: 0, 10-100 */
if
(
value
&&
(
value
<
10
||
value
>
100
))
{
wl1271_warning
(
"value is not in range!"
);
return
-
ERANGE
;
}
mutex_lock
(
&
wl
->
mutex
);
wl
->
conf
.
rx_streaming
.
interval
=
value
;
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out
;
wl1271_recalc_rx_streaming
(
wl
);
wl1271_ps_elp_sleep
(
wl
);
out:
mutex_unlock
(
&
wl
->
mutex
);
return
count
;
}
static
ssize_t
rx_streaming_interval_read
(
struct
file
*
file
,
char
__user
*
userbuf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
wl1271
*
wl
=
file
->
private_data
;
return
wl1271_format_buffer
(
userbuf
,
count
,
ppos
,
"%d
\n
"
,
wl
->
conf
.
rx_streaming
.
interval
);
}
static
const
struct
file_operations
rx_streaming_interval_ops
=
{
.
read
=
rx_streaming_interval_read
,
.
write
=
rx_streaming_interval_write
,
.
open
=
wl1271_open_file_generic
,
.
llseek
=
default_llseek
,
};
static
ssize_t
rx_streaming_always_write
(
struct
file
*
file
,
const
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
wl1271
*
wl
=
file
->
private_data
;
char
buf
[
10
];
size_t
len
;
unsigned
long
value
;
int
ret
;
len
=
min
(
count
,
sizeof
(
buf
)
-
1
);
if
(
copy_from_user
(
buf
,
user_buf
,
len
))
return
-
EFAULT
;
buf
[
len
]
=
'\0'
;
ret
=
kstrtoul
(
buf
,
0
,
&
value
);
if
(
ret
<
0
)
{
wl1271_warning
(
"illegal value in rx_streaming_write!"
);
return
-
EINVAL
;
}
/* valid values: 0, 10-100 */
if
(
!
(
value
==
0
||
value
==
1
))
{
wl1271_warning
(
"value is not in valid!"
);
return
-
EINVAL
;
}
mutex_lock
(
&
wl
->
mutex
);
wl
->
conf
.
rx_streaming
.
always
=
value
;
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out
;
wl1271_recalc_rx_streaming
(
wl
);
wl1271_ps_elp_sleep
(
wl
);
out:
mutex_unlock
(
&
wl
->
mutex
);
return
count
;
}
static
ssize_t
rx_streaming_always_read
(
struct
file
*
file
,
char
__user
*
userbuf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
wl1271
*
wl
=
file
->
private_data
;
return
wl1271_format_buffer
(
userbuf
,
count
,
ppos
,
"%d
\n
"
,
wl
->
conf
.
rx_streaming
.
always
);
}
static
const
struct
file_operations
rx_streaming_always_ops
=
{
.
read
=
rx_streaming_always_read
,
.
write
=
rx_streaming_always_write
,
.
open
=
wl1271_open_file_generic
,
.
llseek
=
default_llseek
,
};
static
int
wl1271_debugfs_add_files
(
struct
wl1271
*
wl
,
struct
dentry
*
rootdir
)
{
int
ret
=
0
;
struct
dentry
*
entry
,
*
stats
;
struct
dentry
*
entry
,
*
stats
,
*
streaming
;
stats
=
debugfs_create_dir
(
"fw-statistics"
,
rootdir
);
if
(
!
stats
||
IS_ERR
(
stats
))
{
...
...
@@ -640,6 +766,14 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,
DEBUGFS_ADD
(
dtim_interval
,
rootdir
);
DEBUGFS_ADD
(
beacon_interval
,
rootdir
);
streaming
=
debugfs_create_dir
(
"rx_streaming"
,
rootdir
);
if
(
!
streaming
||
IS_ERR
(
streaming
))
goto
err
;
DEBUGFS_ADD_PREFIX
(
rx_streaming
,
interval
,
streaming
);
DEBUGFS_ADD_PREFIX
(
rx_streaming
,
always
,
streaming
);
return
0
;
err:
...
...
drivers/net/wireless/wl12xx/event.c
浏览文件 @
333c0dbf
...
...
@@ -133,10 +133,13 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
if
(
ret
<
0
)
break
;
/* enable beacon early termination */
ret
=
wl1271_acx_bet_enable
(
wl
,
true
);
if
(
ret
<
0
)
break
;
/*
* BET has only a minor effect in 5GHz and masks
* channel switch IEs, so we only enable BET on 2.4GHz
*/
if
(
wl
->
band
==
IEEE80211_BAND_2GHZ
)
/* enable beacon early termination */
ret
=
wl1271_acx_bet_enable
(
wl
,
true
);
if
(
wl
->
ps_compl
)
{
complete
(
wl
->
ps_compl
);
...
...
@@ -183,6 +186,21 @@ static void wl1271_stop_ba_event(struct wl1271 *wl, u8 ba_allowed)
ieee80211_stop_rx_ba_session
(
wl
->
vif
,
wl
->
ba_rx_bitmap
,
wl
->
bssid
);
}
static
void
wl12xx_event_soft_gemini_sense
(
struct
wl1271
*
wl
,
u8
enable
)
{
if
(
enable
)
{
/* disable dynamic PS when requested by the firmware */
ieee80211_disable_dyn_ps
(
wl
->
vif
);
set_bit
(
WL1271_FLAG_SOFT_GEMINI
,
&
wl
->
flags
);
}
else
{
ieee80211_enable_dyn_ps
(
wl
->
vif
);
clear_bit
(
WL1271_FLAG_SOFT_GEMINI
,
&
wl
->
flags
);
wl1271_recalc_rx_streaming
(
wl
);
}
}
static
void
wl1271_event_mbox_dump
(
struct
event_mailbox
*
mbox
)
{
wl1271_debug
(
DEBUG_EVENT
,
"MBOX DUMP:"
);
...
...
@@ -226,14 +244,10 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
}
}
/* disable dynamic PS when requested by the firmware */
if
(
vector
&
SOFT_GEMINI_SENSE_EVENT_ID
&&
wl
->
bss_type
==
BSS_TYPE_STA_BSS
)
{
if
(
mbox
->
soft_gemini_sense_info
)
ieee80211_disable_dyn_ps
(
wl
->
vif
);
else
ieee80211_enable_dyn_ps
(
wl
->
vif
);
}
wl
->
bss_type
==
BSS_TYPE_STA_BSS
)
wl12xx_event_soft_gemini_sense
(
wl
,
mbox
->
soft_gemini_sense_info
);
/*
* The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon
...
...
drivers/net/wireless/wl12xx/ini.h
浏览文件 @
333c0dbf
...
...
@@ -24,6 +24,9 @@
#ifndef __INI_H__
#define __INI_H__
#define GENERAL_SETTINGS_DRPW_LPD 0xc0
#define SCRATCH_ENABLE_LPD BIT(25)
#define WL1271_INI_MAX_SMART_REFLEX_PARAM 16
struct
wl1271_ini_general_params
{
...
...
drivers/net/wireless/wl12xx/init.c
浏览文件 @
333c0dbf
...
...
@@ -321,6 +321,20 @@ static int wl1271_init_beacon_broadcast(struct wl1271 *wl)
return
0
;
}
static
int
wl12xx_init_fwlog
(
struct
wl1271
*
wl
)
{
int
ret
;
if
(
wl
->
quirks
&
WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED
)
return
0
;
ret
=
wl12xx_cmd_config_fwlog
(
wl
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
static
int
wl1271_sta_hw_init
(
struct
wl1271
*
wl
)
{
int
ret
;
...
...
@@ -382,6 +396,11 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
if
(
ret
<
0
)
return
ret
;
/* Configure the FW logger */
ret
=
wl12xx_init_fwlog
(
wl
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
...
...
drivers/net/wireless/wl12xx/io.c
浏览文件 @
333c0dbf
...
...
@@ -23,7 +23,6 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/crc7.h>
#include <linux/spi/spi.h>
#include "wl12xx.h"
...
...
@@ -128,12 +127,14 @@ EXPORT_SYMBOL_GPL(wl1271_set_partition);
void
wl1271_io_reset
(
struct
wl1271
*
wl
)
{
wl
->
if_ops
->
reset
(
wl
);
if
(
wl
->
if_ops
->
reset
)
wl
->
if_ops
->
reset
(
wl
);
}
void
wl1271_io_init
(
struct
wl1271
*
wl
)
{
wl
->
if_ops
->
init
(
wl
);
if
(
wl
->
if_ops
->
init
)
wl
->
if_ops
->
init
(
wl
);
}
void
wl1271_top_reg_write
(
struct
wl1271
*
wl
,
int
addr
,
u16
val
)
...
...
drivers/net/wireless/wl12xx/io.h
浏览文件 @
333c0dbf
...
...
@@ -128,6 +128,20 @@ static inline void wl1271_write(struct wl1271 *wl, int addr, void *buf,
wl1271_raw_write
(
wl
,
physical
,
buf
,
len
,
fixed
);
}
static
inline
void
wl1271_read_hwaddr
(
struct
wl1271
*
wl
,
int
hwaddr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
int
physical
;
int
addr
;
/* Addresses are stored internally as addresses to 32 bytes blocks */
addr
=
hwaddr
<<
5
;
physical
=
wl1271_translate_addr
(
wl
,
addr
);
wl1271_raw_read
(
wl
,
physical
,
buf
,
len
,
fixed
);
}
static
inline
u32
wl1271_read32
(
struct
wl1271
*
wl
,
int
addr
)
{
return
wl1271_raw_read32
(
wl
,
wl1271_translate_addr
(
wl
,
addr
));
...
...
drivers/net/wireless/wl12xx/main.c
浏览文件 @
333c0dbf
此差异已折叠。
点击以展开。
drivers/net/wireless/wl12xx/ps.c
浏览文件 @
333c0dbf
...
...
@@ -118,7 +118,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)
&
compl
,
msecs_to_jiffies
(
WL1271_WAKEUP_TIMEOUT
));
if
(
ret
==
0
)
{
wl1271_error
(
"ELP wakeup timeout!"
);
ieee80211_queue_work
(
wl
->
hw
,
&
wl
->
recovery_work
);
wl12xx_queue_recovery_work
(
wl
);
ret
=
-
ETIMEDOUT
;
goto
err
;
}
else
if
(
ret
<
0
)
{
...
...
@@ -169,9 +169,11 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
wl1271_debug
(
DEBUG_PSM
,
"leaving psm"
);
/* disable beacon early termination */
ret
=
wl1271_acx_bet_enable
(
wl
,
false
);
if
(
ret
<
0
)
return
ret
;
if
(
wl
->
band
==
IEEE80211_BAND_2GHZ
)
{
ret
=
wl1271_acx_bet_enable
(
wl
,
false
);
if
(
ret
<
0
)
return
ret
;
}
/* disable beacon filtering */
ret
=
wl1271_acx_beacon_filter_opt
(
wl
,
false
);
...
...
@@ -202,7 +204,7 @@ static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid)
info
=
IEEE80211_SKB_CB
(
skb
);
info
->
flags
|=
IEEE80211_TX_STAT_TX_FILTERED
;
info
->
status
.
rates
[
0
].
idx
=
-
1
;
ieee80211_tx_status
(
wl
->
hw
,
skb
);
ieee80211_tx_status
_ni
(
wl
->
hw
,
skb
);
filtered
++
;
}
}
...
...
drivers/net/wireless/wl12xx/rx.c
浏览文件 @
333c0dbf
...
...
@@ -22,6 +22,7 @@
*/
#include <linux/gfp.h>
#include <linux/sched.h>
#include "wl12xx.h"
#include "acx.h"
...
...
@@ -95,6 +96,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
struct
ieee80211_hdr
*
hdr
;
u8
*
buf
;
u8
beacon
=
0
;
u8
is_data
=
0
;
/*
* In PLT mode we seem to get frames and mac80211 warns about them,
...
...
@@ -106,6 +108,13 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
/* the data read starts with the descriptor */
desc
=
(
struct
wl1271_rx_descriptor
*
)
data
;
if
(
desc
->
packet_class
==
WL12XX_RX_CLASS_LOGGER
)
{
size_t
len
=
length
-
sizeof
(
*
desc
);
wl12xx_copy_fwlog
(
wl
,
data
+
sizeof
(
*
desc
),
len
);
wake_up_interruptible
(
&
wl
->
fwlog_waitq
);
return
0
;
}
switch
(
desc
->
status
&
WL1271_RX_DESC_STATUS_MASK
)
{
/* discard corrupted packets */
case
WL1271_RX_DESC_DRIVER_RX_Q_FAIL
:
...
...
@@ -137,6 +146,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
hdr
=
(
struct
ieee80211_hdr
*
)
skb
->
data
;
if
(
ieee80211_is_beacon
(
hdr
->
frame_control
))
beacon
=
1
;
if
(
ieee80211_is_data_present
(
hdr
->
frame_control
))
is_data
=
1
;
wl1271_rx_status
(
wl
,
desc
,
IEEE80211_SKB_RXCB
(
skb
),
beacon
);
...
...
@@ -147,9 +158,9 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
skb_trim
(
skb
,
skb
->
len
-
desc
->
pad_len
);
skb_queue_tail
(
&
wl
->
deferred_rx_queue
,
skb
);
ieee80211_queue_work
(
wl
->
hw
,
&
wl
->
netstack_work
);
queue_work
(
wl
->
freezable_wq
,
&
wl
->
netstack_work
);
return
0
;
return
is_data
;
}
void
wl1271_rx
(
struct
wl1271
*
wl
,
struct
wl1271_fw_common_status
*
status
)
...
...
@@ -162,6 +173,8 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
u32
mem_block
;
u32
pkt_length
;
u32
pkt_offset
;
bool
is_ap
=
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
);
bool
had_data
=
false
;
while
(
drv_rx_counter
!=
fw_rx_counter
)
{
buf_size
=
0
;
...
...
@@ -214,9 +227,11 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
* conditions, in that case the received frame will just
* be dropped.
*/
wl1271_rx_handle_data
(
wl
,
wl
->
aggr_buf
+
pkt_offset
,
pkt_length
);
if
(
wl1271_rx_handle_data
(
wl
,
wl
->
aggr_buf
+
pkt_offset
,
pkt_length
)
==
1
)
had_data
=
true
;
wl
->
rx_counter
++
;
drv_rx_counter
++
;
drv_rx_counter
&=
NUM_RX_PKT_DESC_MOD_MASK
;
...
...
@@ -230,6 +245,20 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
*/
if
(
wl
->
quirks
&
WL12XX_QUIRK_END_OF_TRANSACTION
)
wl1271_write32
(
wl
,
RX_DRIVER_COUNTER_ADDRESS
,
wl
->
rx_counter
);
if
(
!
is_ap
&&
wl
->
conf
.
rx_streaming
.
interval
&&
had_data
&&
(
wl
->
conf
.
rx_streaming
.
always
||
test_bit
(
WL1271_FLAG_SOFT_GEMINI
,
&
wl
->
flags
)))
{
u32
timeout
=
wl
->
conf
.
rx_streaming
.
duration
;
/* restart rx streaming */
if
(
!
test_bit
(
WL1271_FLAG_RX_STREAMING_STARTED
,
&
wl
->
flags
))
ieee80211_queue_work
(
wl
->
hw
,
&
wl
->
rx_streaming_enable_work
);
mod_timer
(
&
wl
->
rx_streaming_timer
,
jiffies
+
msecs_to_jiffies
(
timeout
));
}
}
void
wl1271_set_default_filters
(
struct
wl1271
*
wl
)
...
...
drivers/net/wireless/wl12xx/rx.h
浏览文件 @
333c0dbf
...
...
@@ -97,6 +97,18 @@
#define RX_BUF_SIZE_MASK 0xFFF00
#define RX_BUF_SIZE_SHIFT_DIV 6
enum
{
WL12XX_RX_CLASS_UNKNOWN
,
WL12XX_RX_CLASS_MANAGEMENT
,
WL12XX_RX_CLASS_DATA
,
WL12XX_RX_CLASS_QOS_DATA
,
WL12XX_RX_CLASS_BCN_PRBRSP
,
WL12XX_RX_CLASS_EAPOL
,
WL12XX_RX_CLASS_BA_EVENT
,
WL12XX_RX_CLASS_AMSDU
,
WL12XX_RX_CLASS_LOGGER
,
};
struct
wl1271_rx_descriptor
{
__le16
length
;
u8
status
;
...
...
drivers/net/wireless/wl12xx/scan.c
浏览文件 @
333c0dbf
...
...
@@ -62,7 +62,7 @@ void wl1271_scan_complete_work(struct work_struct *work)
if
(
wl
->
scan
.
failed
)
{
wl1271_info
(
"Scan completed due to error."
);
ieee80211_queue_work
(
wl
->
hw
,
&
wl
->
recovery_work
);
wl12xx_queue_recovery_work
(
wl
);
}
out:
...
...
@@ -326,7 +326,7 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,
struct
cfg80211_sched_scan_request
*
req
,
struct
conn_scan_ch_params
*
channels
,
u32
band
,
bool
radar
,
bool
passive
,
int
start
)
int
start
,
int
max_channels
)
{
struct
conf_sched_scan_settings
*
c
=
&
wl
->
conf
.
sched_scan
;
int
i
,
j
;
...
...
@@ -334,7 +334,7 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,
bool
force_passive
=
!
req
->
n_ssids
;
for
(
i
=
0
,
j
=
start
;
i
<
req
->
n_channels
&&
j
<
MAX_CHANNELS_ALL_BANDS
;
i
<
req
->
n_channels
&&
j
<
max_channels
;
i
++
)
{
flags
=
req
->
channels
[
i
]
->
flags
;
...
...
@@ -380,46 +380,42 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,
return
j
-
start
;
}
static
int
static
bool
wl1271_scan_sched_scan_channels
(
struct
wl1271
*
wl
,
struct
cfg80211_sched_scan_request
*
req
,
struct
wl1271_cmd_sched_scan_config
*
cfg
)
{
int
idx
=
0
;
cfg
->
passive
[
0
]
=
wl1271_scan_get_sched_scan_channels
(
wl
,
req
,
cfg
->
channels
,
wl1271_scan_get_sched_scan_channels
(
wl
,
req
,
cfg
->
channels
_2
,
IEEE80211_BAND_2GHZ
,
false
,
true
,
idx
);
idx
+=
cfg
->
passive
[
0
];
false
,
true
,
0
,
MAX_CHANNELS_2GHZ
);
cfg
->
active
[
0
]
=
wl1271_scan_get_sched_scan_channels
(
wl
,
req
,
cfg
->
channels
,
wl1271_scan_get_sched_scan_channels
(
wl
,
req
,
cfg
->
channels
_2
,
IEEE80211_BAND_2GHZ
,
false
,
false
,
idx
);
/*
* 5GHz channels always start at position 14, not immediately
* after the last 2.4GHz channel
*/
idx
=
14
;
false
,
false
,
cfg
->
passive
[
0
],
MAX_CHANNELS_2GHZ
);
cfg
->
passive
[
1
]
=
wl1271_scan_get_sched_scan_channels
(
wl
,
req
,
cfg
->
channels
,
wl1271_scan_get_sched_scan_channels
(
wl
,
req
,
cfg
->
channels
_5
,
IEEE80211_BAND_5GHZ
,
false
,
true
,
idx
);
idx
+=
cfg
->
passive
[
1
];
false
,
true
,
0
,
MAX_CHANNELS_5GHZ
);
cfg
->
dfs
=
wl1271_scan_get_sched_scan_channels
(
wl
,
req
,
cfg
->
channels
,
wl1271_scan_get_sched_scan_channels
(
wl
,
req
,
cfg
->
channels
_5
,
IEEE80211_BAND_5GHZ
,
true
,
true
,
idx
);
idx
+=
cfg
->
dfs
;
true
,
true
,
cfg
->
passive
[
1
],
MAX_CHANNELS_5GHZ
);
cfg
->
active
[
1
]
=
wl1271_scan_get_sched_scan_channels
(
wl
,
req
,
cfg
->
channels
,
wl1271_scan_get_sched_scan_channels
(
wl
,
req
,
cfg
->
channels
_5
,
IEEE80211_BAND_5GHZ
,
false
,
false
,
idx
);
idx
+=
cfg
->
active
[
1
];
false
,
false
,
cfg
->
passive
[
1
]
+
cfg
->
dfs
,
MAX_CHANNELS_5GHZ
);
/* 802.11j channels are not supported yet */
cfg
->
passive
[
2
]
=
0
;
cfg
->
active
[
2
]
=
0
;
wl1271_debug
(
DEBUG_SCAN
,
" 2.4GHz: active %d passive %d"
,
cfg
->
active
[
0
],
cfg
->
passive
[
0
]);
...
...
@@ -427,7 +423,9 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl,
cfg
->
active
[
1
],
cfg
->
passive
[
1
]);
wl1271_debug
(
DEBUG_SCAN
,
" DFS: %d"
,
cfg
->
dfs
);
return
idx
;
return
cfg
->
passive
[
0
]
||
cfg
->
active
[
0
]
||
cfg
->
passive
[
1
]
||
cfg
->
active
[
1
]
||
cfg
->
dfs
||
cfg
->
passive
[
2
]
||
cfg
->
active
[
2
];
}
int
wl1271_scan_sched_scan_config
(
struct
wl1271
*
wl
,
...
...
@@ -436,7 +434,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
{
struct
wl1271_cmd_sched_scan_config
*
cfg
=
NULL
;
struct
conf_sched_scan_settings
*
c
=
&
wl
->
conf
.
sched_scan
;
int
i
,
total_channels
,
ret
;
int
i
,
ret
;
bool
force_passive
=
!
req
->
n_ssids
;
wl1271_debug
(
DEBUG_CMD
,
"cmd sched_scan scan config"
);
...
...
@@ -471,8 +469,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
cfg
->
ssid_len
=
0
;
}
total_channels
=
wl1271_scan_sched_scan_channels
(
wl
,
req
,
cfg
);
if
(
total_channels
==
0
)
{
if
(
!
wl1271_scan_sched_scan_channels
(
wl
,
req
,
cfg
))
{
wl1271_error
(
"scan channel list is empty"
);
ret
=
-
EINVAL
;
goto
out
;
...
...
drivers/net/wireless/wl12xx/scan.h
浏览文件 @
333c0dbf
...
...
@@ -112,18 +112,13 @@ struct wl1271_cmd_trigger_scan_to {
__le32
timeout
;
}
__packed
;
#define MAX_CHANNELS_ALL_BANDS 41
#define MAX_CHANNELS_2GHZ 14
#define MAX_CHANNELS_5GHZ 23
#define MAX_CHANNELS_4GHZ 4
#define SCAN_MAX_CYCLE_INTERVALS 16
#define SCAN_MAX_BANDS 3
enum
{
SCAN_CHANNEL_TYPE_2GHZ_PASSIVE
,
SCAN_CHANNEL_TYPE_2GHZ_ACTIVE
,
SCAN_CHANNEL_TYPE_5GHZ_PASSIVE
,
SCAN_CHANNEL_TYPE_5GHZ_ACTIVE
,
SCAN_CHANNEL_TYPE_5GHZ_DFS
,
};
enum
{
SCAN_SSID_FILTER_ANY
=
0
,
SCAN_SSID_FILTER_SPECIFIC
=
1
,
...
...
@@ -182,7 +177,9 @@ struct wl1271_cmd_sched_scan_config {
u8
padding
[
3
];
struct
conn_scan_ch_params
channels
[
MAX_CHANNELS_ALL_BANDS
];
struct
conn_scan_ch_params
channels_2
[
MAX_CHANNELS_2GHZ
];
struct
conn_scan_ch_params
channels_5
[
MAX_CHANNELS_5GHZ
];
struct
conn_scan_ch_params
channels_4
[
MAX_CHANNELS_4GHZ
];
}
__packed
;
...
...
drivers/net/wireless/wl12xx/sdio.c
浏览文件 @
333c0dbf
...
...
@@ -23,7 +23,6 @@
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/crc7.h>
#include <linux/vmalloc.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
...
...
@@ -45,7 +44,7 @@
#define SDIO_DEVICE_ID_TI_WL1271 0x4076
#endif
static
const
struct
sdio_device_id
wl1271_devices
[]
=
{
static
const
struct
sdio_device_id
wl1271_devices
[]
__devinitconst
=
{
{
SDIO_DEVICE
(
SDIO_VENDOR_ID_TI
,
SDIO_DEVICE_ID_TI_WL1271
)
},
{}
};
...
...
@@ -107,14 +106,6 @@ static void wl1271_sdio_enable_interrupts(struct wl1271 *wl)
enable_irq
(
wl
->
irq
);
}
static
void
wl1271_sdio_reset
(
struct
wl1271
*
wl
)
{
}
static
void
wl1271_sdio_init
(
struct
wl1271
*
wl
)
{
}
static
void
wl1271_sdio_raw_read
(
struct
wl1271
*
wl
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
...
...
@@ -170,10 +161,12 @@ static int wl1271_sdio_power_on(struct wl1271 *wl)
struct
sdio_func
*
func
=
wl_to_func
(
wl
);
int
ret
;
/* Make sure the card will not be powered off by runtime PM */
ret
=
pm_runtime_get_sync
(
&
func
->
dev
);
if
(
ret
<
0
)
goto
out
;
/* If enabled, tell runtime PM not to power off the card */
if
(
pm_runtime_enabled
(
&
func
->
dev
))
{
ret
=
pm_runtime_get_sync
(
&
func
->
dev
);
if
(
ret
)
goto
out
;
}
/* Runtime PM might be disabled, so power up the card manually */
ret
=
mmc_power_restore_host
(
func
->
card
->
host
);
...
...
@@ -200,8 +193,11 @@ static int wl1271_sdio_power_off(struct wl1271 *wl)
if
(
ret
<
0
)
return
ret
;
/* Let runtime PM know the card is powered off */
return
pm_runtime_put_sync
(
&
func
->
dev
);
/* If enabled, let runtime PM know the card is powered off */
if
(
pm_runtime_enabled
(
&
func
->
dev
))
ret
=
pm_runtime_put_sync
(
&
func
->
dev
);
return
ret
;
}
static
int
wl1271_sdio_set_power
(
struct
wl1271
*
wl
,
bool
enable
)
...
...
@@ -215,8 +211,6 @@ static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
static
struct
wl1271_if_operations
sdio_ops
=
{
.
read
=
wl1271_sdio_raw_read
,
.
write
=
wl1271_sdio_raw_write
,
.
reset
=
wl1271_sdio_reset
,
.
init
=
wl1271_sdio_init
,
.
power
=
wl1271_sdio_set_power
,
.
dev
=
wl1271_sdio_wl_to_dev
,
.
enable_irq
=
wl1271_sdio_enable_interrupts
,
...
...
@@ -278,17 +272,19 @@ static int __devinit wl1271_probe(struct sdio_func *func,
goto
out_free
;
}
enable_irq_wake
(
wl
->
irq
);
device_init_wakeup
(
wl1271_sdio_wl_to_dev
(
wl
),
1
);
disable_irq
(
wl
->
irq
);
ret
=
enable_irq_wake
(
wl
->
irq
);
if
(
!
ret
)
{
wl
->
irq_wake_enabled
=
true
;
device_init_wakeup
(
wl1271_sdio_wl_to_dev
(
wl
),
1
);
/* if sdio can keep power while host is suspended, enable wow */
mmcflags
=
sdio_get_host_pm_caps
(
func
);
wl1271_debug
(
DEBUG_SDIO
,
"sdio PM caps = 0x%x"
,
mmcflags
);
/* if sdio can keep power while host is suspended, enable wow */
mmcflags
=
sdio_get_host_pm_caps
(
func
);
wl1271_debug
(
DEBUG_SDIO
,
"sdio PM caps = 0x%x"
,
mmcflags
);
if
(
mmcflags
&
MMC_PM_KEEP_POWER
)
hw
->
wiphy
->
wowlan
.
flags
=
WIPHY_WOWLAN_ANY
;
if
(
mmcflags
&
MMC_PM_KEEP_POWER
)
hw
->
wiphy
->
wowlan
.
flags
=
WIPHY_WOWLAN_ANY
;
}
disable_irq
(
wl
->
irq
);
ret
=
wl1271_init_ieee80211
(
wl
);
if
(
ret
)
...
...
@@ -303,8 +299,6 @@ static int __devinit wl1271_probe(struct sdio_func *func,
/* Tell PM core that we don't need the card to be powered now */
pm_runtime_put_noidle
(
&
func
->
dev
);
wl1271_notice
(
"initialized"
);
return
0
;
out_irq:
...
...
@@ -324,8 +318,10 @@ static void __devexit wl1271_remove(struct sdio_func *func)
pm_runtime_get_noresume
(
&
func
->
dev
);
wl1271_unregister_hw
(
wl
);
device_init_wakeup
(
wl1271_sdio_wl_to_dev
(
wl
),
0
);
disable_irq_wake
(
wl
->
irq
);
if
(
wl
->
irq_wake_enabled
)
{
device_init_wakeup
(
wl1271_sdio_wl_to_dev
(
wl
),
0
);
disable_irq_wake
(
wl
->
irq
);
}
free_irq
(
wl
->
irq
,
wl
);
wl1271_free_hw
(
wl
);
}
...
...
@@ -402,23 +398,12 @@ static struct sdio_driver wl1271_sdio_driver = {
static
int
__init
wl1271_init
(
void
)
{
int
ret
;
ret
=
sdio_register_driver
(
&
wl1271_sdio_driver
);
if
(
ret
<
0
)
{
wl1271_error
(
"failed to register sdio driver: %d"
,
ret
);
goto
out
;
}
out:
return
ret
;
return
sdio_register_driver
(
&
wl1271_sdio_driver
);
}
static
void
__exit
wl1271_exit
(
void
)
{
sdio_unregister_driver
(
&
wl1271_sdio_driver
);
wl1271_notice
(
"unloaded"
);
}
module_init
(
wl1271_init
);
...
...
drivers/net/wireless/wl12xx/spi.c
浏览文件 @
333c0dbf
...
...
@@ -435,8 +435,6 @@ static int __devinit wl1271_probe(struct spi_device *spi)
if
(
ret
)
goto
out_irq
;
wl1271_notice
(
"initialized"
);
return
0
;
out_irq:
...
...
@@ -473,23 +471,12 @@ static struct spi_driver wl1271_spi_driver = {
static
int
__init
wl1271_init
(
void
)
{
int
ret
;
ret
=
spi_register_driver
(
&
wl1271_spi_driver
);
if
(
ret
<
0
)
{
wl1271_error
(
"failed to register spi driver: %d"
,
ret
);
goto
out
;
}
out:
return
ret
;
return
spi_register_driver
(
&
wl1271_spi_driver
);
}
static
void
__exit
wl1271_exit
(
void
)
{
spi_unregister_driver
(
&
wl1271_spi_driver
);
wl1271_notice
(
"unloaded"
);
}
module_init
(
wl1271_init
);
...
...
drivers/net/wireless/wl12xx/testmode.c
浏览文件 @
333c0dbf
...
...
@@ -260,7 +260,7 @@ static int wl1271_tm_cmd_recover(struct wl1271 *wl, struct nlattr *tb[])
{
wl1271_debug
(
DEBUG_TESTMODE
,
"testmode cmd recover"
);
ieee80211_queue_work
(
wl
->
hw
,
&
wl
->
recovery_work
);
wl12xx_queue_recovery_work
(
wl
);
return
0
;
}
...
...
drivers/net/wireless/wl12xx/tx.c
浏览文件 @
333c0dbf
...
...
@@ -562,17 +562,29 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb)
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
}
static
bool
wl1271_tx_is_data_present
(
struct
sk_buff
*
skb
)
{
struct
ieee80211_hdr
*
hdr
=
(
struct
ieee80211_hdr
*
)(
skb
->
data
);
return
ieee80211_is_data_present
(
hdr
->
frame_control
);
}
void
wl1271_tx_work_locked
(
struct
wl1271
*
wl
)
{
struct
sk_buff
*
skb
;
u32
buf_offset
=
0
;
bool
sent_packets
=
false
;
bool
had_data
=
false
;
bool
is_ap
=
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
);
int
ret
;
if
(
unlikely
(
wl
->
state
==
WL1271_STATE_OFF
))
return
;
while
((
skb
=
wl1271_skb_dequeue
(
wl
)))
{
if
(
wl1271_tx_is_data_present
(
skb
))
had_data
=
true
;
ret
=
wl1271_prepare_tx_frame
(
wl
,
skb
,
buf_offset
);
if
(
ret
==
-
EAGAIN
)
{
/*
...
...
@@ -619,6 +631,19 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
wl1271_handle_tx_low_watermark
(
wl
);
}
if
(
!
is_ap
&&
wl
->
conf
.
rx_streaming
.
interval
&&
had_data
&&
(
wl
->
conf
.
rx_streaming
.
always
||
test_bit
(
WL1271_FLAG_SOFT_GEMINI
,
&
wl
->
flags
)))
{
u32
timeout
=
wl
->
conf
.
rx_streaming
.
duration
;
/* enable rx streaming */
if
(
!
test_bit
(
WL1271_FLAG_RX_STREAMING_STARTED
,
&
wl
->
flags
))
ieee80211_queue_work
(
wl
->
hw
,
&
wl
->
rx_streaming_enable_work
);
mod_timer
(
&
wl
->
rx_streaming_timer
,
jiffies
+
msecs_to_jiffies
(
timeout
));
}
}
void
wl1271_tx_work
(
struct
work_struct
*
work
)
...
...
@@ -702,7 +727,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
/* return the packet to the stack */
skb_queue_tail
(
&
wl
->
deferred_tx_queue
,
skb
);
ieee80211_queue_work
(
wl
->
hw
,
&
wl
->
netstack_work
);
queue_work
(
wl
->
freezable_wq
,
&
wl
->
netstack_work
);
wl1271_free_tx_id
(
wl
,
result
->
id
);
}
...
...
@@ -757,7 +782,7 @@ void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid)
info
=
IEEE80211_SKB_CB
(
skb
);
info
->
status
.
rates
[
0
].
idx
=
-
1
;
info
->
status
.
rates
[
0
].
count
=
0
;
ieee80211_tx_status
(
wl
->
hw
,
skb
);
ieee80211_tx_status
_ni
(
wl
->
hw
,
skb
);
total
++
;
}
}
...
...
@@ -795,7 +820,7 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
info
=
IEEE80211_SKB_CB
(
skb
);
info
->
status
.
rates
[
0
].
idx
=
-
1
;
info
->
status
.
rates
[
0
].
count
=
0
;
ieee80211_tx_status
(
wl
->
hw
,
skb
);
ieee80211_tx_status
_ni
(
wl
->
hw
,
skb
);
}
}
}
...
...
@@ -838,7 +863,7 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
info
->
status
.
rates
[
0
].
idx
=
-
1
;
info
->
status
.
rates
[
0
].
count
=
0
;
ieee80211_tx_status
(
wl
->
hw
,
skb
);
ieee80211_tx_status
_ni
(
wl
->
hw
,
skb
);
}
}
}
...
...
drivers/net/wireless/wl12xx/wl12xx.h
浏览文件 @
333c0dbf
...
...
@@ -226,6 +226,8 @@ enum {
#define FW_VER_MINOR_1_SPARE_STA_MIN 58
#define FW_VER_MINOR_1_SPARE_AP_MIN 47
#define FW_VER_MINOR_FWLOG_STA_MIN 70
struct
wl1271_chip
{
u32
id
;
char
fw_ver_str
[
ETHTOOL_BUSINFO_LEN
];
...
...
@@ -284,8 +286,7 @@ struct wl1271_fw_sta_status {
u8
tx_total
;
u8
reserved1
;
__le16
reserved2
;
/* Total structure size is 68 bytes */
u32
padding
;
__le32
log_start_addr
;
}
__packed
;
struct
wl1271_fw_full_status
{
...
...
@@ -359,6 +360,9 @@ enum wl12xx_flags {
WL1271_FLAG_DUMMY_PACKET_PENDING
,
WL1271_FLAG_SUSPENDED
,
WL1271_FLAG_PENDING_WORK
,
WL1271_FLAG_SOFT_GEMINI
,
WL1271_FLAG_RX_STREAMING_STARTED
,
WL1271_FLAG_RECOVERY_IN_PROGRESS
,
};
struct
wl1271_link
{
...
...
@@ -443,6 +447,7 @@ struct wl1271 {
struct
sk_buff_head
deferred_tx_queue
;
struct
work_struct
tx_work
;
struct
workqueue_struct
*
freezable_wq
;
/* Pending TX frames */
unsigned
long
tx_frames_map
[
BITS_TO_LONGS
(
ACX_TX_DESCRIPTORS
)];
...
...
@@ -468,6 +473,15 @@ struct wl1271 {
/* Network stack work */
struct
work_struct
netstack_work
;
/* FW log buffer */
u8
*
fwlog
;
/* Number of valid bytes in the FW log buffer */
ssize_t
fwlog_size
;
/* Sysfs FW log entry readers wait queue */
wait_queue_head_t
fwlog_waitq
;
/* Hardware recovery work */
struct
work_struct
recovery_work
;
...
...
@@ -508,6 +522,11 @@ struct wl1271 {
/* Default key (for WEP) */
u32
default_key
;
/* Rx Streaming */
struct
work_struct
rx_streaming_enable_work
;
struct
work_struct
rx_streaming_disable_work
;
struct
timer_list
rx_streaming_timer
;
unsigned
int
filters
;
unsigned
int
rx_config
;
unsigned
int
rx_filter
;
...
...
@@ -573,6 +592,7 @@ struct wl1271 {
* (currently, only "ANY" trigger is supported)
*/
bool
wow_enabled
;
bool
irq_wake_enabled
;
/*
* AP-mode - links indexed by HLID. The global and broadcast links
...
...
@@ -602,6 +622,9 @@ struct wl1271_station {
int
wl1271_plt_start
(
struct
wl1271
*
wl
);
int
wl1271_plt_stop
(
struct
wl1271
*
wl
);
int
wl1271_recalc_rx_streaming
(
struct
wl1271
*
wl
);
void
wl12xx_queue_recovery_work
(
struct
wl1271
*
wl
);
size_t
wl12xx_copy_fwlog
(
struct
wl1271
*
wl
,
u8
*
memblock
,
size_t
maxlen
);
#define JOIN_TIMEOUT 5000
/* 5000 milliseconds to join */
...
...
@@ -637,4 +660,15 @@ int wl1271_plt_stop(struct wl1271 *wl);
/* WL128X requires aggregated packets to be aligned to the SDIO block size */
#define WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT BIT(2)
/*
* WL127X AP mode requires Low Power DRPw (LPD) enable to reduce power
* consumption
*/
#define WL12XX_QUIRK_LPD_MODE BIT(3)
/* Older firmwares did not implement the FW logger over bus feature */
#define WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED BIT(4)
#define WL12XX_HW_BLOCK_SIZE 256
#endif
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录