Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
46bf6958
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 3 年多
通知
13
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
46bf6958
编写于
10月 05, 2010
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'wireless-next' of
git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx
上级
e7480bbb
4b48e687
变更
23
展开全部
隐藏空白更改
内联
并排
Showing
23 changed file
with
784 addition
and
538 deletion
+784
-538
MAINTAINERS
MAINTAINERS
+1
-1
arch/arm/mach-omap2/board-zoom-peripherals.c
arch/arm/mach-omap2/board-zoom-peripherals.c
+1
-1
drivers/net/wireless/wl12xx/wl1271.h
drivers/net/wireless/wl12xx/wl1271.h
+15
-14
drivers/net/wireless/wl12xx/wl1271_acx.c
drivers/net/wireless/wl12xx/wl1271_acx.c
+0
-34
drivers/net/wireless/wl12xx/wl1271_acx.h
drivers/net/wireless/wl12xx/wl1271_acx.h
+0
-31
drivers/net/wireless/wl12xx/wl1271_boot.c
drivers/net/wireless/wl12xx/wl1271_boot.c
+27
-12
drivers/net/wireless/wl12xx/wl1271_cmd.c
drivers/net/wireless/wl12xx/wl1271_cmd.c
+72
-50
drivers/net/wireless/wl12xx/wl1271_cmd.h
drivers/net/wireless/wl12xx/wl1271_cmd.h
+30
-43
drivers/net/wireless/wl12xx/wl1271_conf.h
drivers/net/wireless/wl12xx/wl1271_conf.h
+77
-1
drivers/net/wireless/wl12xx/wl1271_event.c
drivers/net/wireless/wl12xx/wl1271_event.c
+10
-5
drivers/net/wireless/wl12xx/wl1271_init.c
drivers/net/wireless/wl12xx/wl1271_init.c
+20
-19
drivers/net/wireless/wl12xx/wl1271_main.c
drivers/net/wireless/wl12xx/wl1271_main.c
+258
-135
drivers/net/wireless/wl12xx/wl1271_ps.c
drivers/net/wireless/wl12xx/wl1271_ps.c
+16
-4
drivers/net/wireless/wl12xx/wl1271_ps.h
drivers/net/wireless/wl12xx/wl1271_ps.h
+1
-1
drivers/net/wireless/wl12xx/wl1271_rx.c
drivers/net/wireless/wl12xx/wl1271_rx.c
+47
-16
drivers/net/wireless/wl12xx/wl1271_scan.c
drivers/net/wireless/wl12xx/wl1271_scan.c
+65
-14
drivers/net/wireless/wl12xx/wl1271_scan.h
drivers/net/wireless/wl12xx/wl1271_scan.h
+3
-3
drivers/net/wireless/wl12xx/wl1271_sdio.c
drivers/net/wireless/wl12xx/wl1271_sdio.c
+1
-2
drivers/net/wireless/wl12xx/wl1271_spi.c
drivers/net/wireless/wl12xx/wl1271_spi.c
+87
-56
drivers/net/wireless/wl12xx/wl1271_testmode.c
drivers/net/wireless/wl12xx/wl1271_testmode.c
+1
-13
drivers/net/wireless/wl12xx/wl1271_tx.c
drivers/net/wireless/wl12xx/wl1271_tx.c
+39
-66
drivers/net/wireless/wl12xx/wl1271_tx.h
drivers/net/wireless/wl12xx/wl1271_tx.h
+0
-17
include/linux/wl12xx.h
include/linux/wl12xx.h
+13
-0
未找到文件。
MAINTAINERS
浏览文件 @
46bf6958
...
...
@@ -6321,7 +6321,7 @@ WL1271 WIRELESS DRIVER
M: Luciano Coelho <luciano.coelho@nokia.com>
L: linux-wireless@vger.kernel.org
W: http://wireless.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/l
inville/wireless-testing
.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/l
uca/wl12xx
.git
S: Maintained
F: drivers/net/wireless/wl12xx/wl1271*
F: include/linux/wl12xx.h
...
...
arch/arm/mach-omap2/board-zoom-peripherals.c
浏览文件 @
46bf6958
...
...
@@ -213,7 +213,7 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
{
.
name
=
"wl1271"
,
.
mmc
=
3
,
.
wires
=
4
,
.
caps
=
MMC_CAP_4_BIT_DATA
,
.
gpio_wp
=
-
EINVAL
,
.
gpio_cd
=
-
EINVAL
,
.
nonremovable
=
true
,
...
...
drivers/net/wireless/wl12xx/wl1271.h
浏览文件 @
46bf6958
...
...
@@ -117,10 +117,7 @@ enum {
#define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
#define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
/*
* Enable/disable 802.11a support for WL1273
*/
#undef WL1271_80211A_ENABLED
#define WL1271_CIPHER_SUITE_GEM 0x00147201
#define WL1271_BUSY_WORD_CNT 1
#define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32))
...
...
@@ -133,6 +130,8 @@ enum {
#define ACX_TX_DESCRIPTORS 32
#define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
enum
wl1271_state
{
WL1271_STATE_OFF
,
WL1271_STATE_ON
,
...
...
@@ -301,6 +300,7 @@ struct wl1271_rx_mem_pool_addr {
struct
wl1271_scan
{
struct
cfg80211_scan_request
*
req
;
bool
*
scanned_ch
;
bool
failed
;
u8
state
;
u8
ssid
[
IW_ESSID_MAX_SIZE
+
1
];
size_t
ssid_len
;
...
...
@@ -350,6 +350,7 @@ struct wl1271 {
#define WL1271_FLAG_IDLE (10)
#define WL1271_FLAG_IDLE_REQUESTED (11)
#define WL1271_FLAG_PSPOLL_FAILURE (12)
#define WL1271_FLAG_STA_STATE_SENT (13)
unsigned
long
flags
;
struct
wl1271_partition_set
part
;
...
...
@@ -362,6 +363,7 @@ struct wl1271 {
u8
*
fw
;
size_t
fw_len
;
struct
wl1271_nvs_file
*
nvs
;
size_t
nvs_len
;
s8
hw_pg_ver
;
...
...
@@ -408,9 +410,15 @@ struct wl1271 {
/* Rx memory pool address */
struct
wl1271_rx_mem_pool_addr
rx_mem_pool_addr
;
/* Intermediate buffer, used for packet aggregation */
u8
*
aggr_buf
;
/* The target interrupt mask */
struct
work_struct
irq_work
;
/* Hardware recovery work */
struct
work_struct
recovery_work
;
/* The mbox event mask */
u32
event_mask
;
...
...
@@ -419,6 +427,7 @@ struct wl1271 {
/* Are we currently scanning */
struct
wl1271_scan
scan
;
struct
delayed_work
scan_complete_work
;
/* Our association ID */
u16
aid
;
...
...
@@ -475,6 +484,8 @@ struct wl1271 {
bool
sg_enabled
;
bool
enable_11a
;
struct
list_head
list
;
/* Most recently reported noise in dBm */
...
...
@@ -498,14 +509,4 @@ int wl1271_plt_stop(struct wl1271 *wl);
#define WL1271_PRE_POWER_ON_SLEEP 20
/* in miliseconds */
#define WL1271_POWER_ON_SLEEP 200
/* in miliseconds */
static
inline
bool
wl1271_11a_enabled
(
void
)
{
/* FIXME: this could be determined based on the NVS-INI file */
#ifdef WL1271_80211A_ENABLED
return
true
;
#else
return
false
;
#endif
}
#endif
drivers/net/wireless/wl12xx/wl1271_acx.c
浏览文件 @
46bf6958
...
...
@@ -86,40 +86,6 @@ int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth)
return
ret
;
}
int
wl1271_acx_fw_version
(
struct
wl1271
*
wl
,
char
*
buf
,
size_t
len
)
{
struct
acx_revision
*
rev
;
int
ret
;
wl1271_debug
(
DEBUG_ACX
,
"acx fw rev"
);
rev
=
kzalloc
(
sizeof
(
*
rev
),
GFP_KERNEL
);
if
(
!
rev
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
ret
=
wl1271_cmd_interrogate
(
wl
,
ACX_FW_REV
,
rev
,
sizeof
(
*
rev
));
if
(
ret
<
0
)
{
wl1271_warning
(
"ACX_FW_REV interrogate failed"
);
goto
out
;
}
/* be careful with the buffer sizes */
strncpy
(
buf
,
rev
->
fw_version
,
min
(
len
,
sizeof
(
rev
->
fw_version
)));
/*
* if the firmware version string is exactly
* sizeof(rev->fw_version) long or fw_len is less than
* sizeof(rev->fw_version) it won't be null terminated
*/
buf
[
min
(
len
,
sizeof
(
rev
->
fw_version
))
-
1
]
=
'\0'
;
out:
kfree
(
rev
);
return
ret
;
}
int
wl1271_acx_tx_power
(
struct
wl1271
*
wl
,
int
power
)
{
struct
acx_current_tx_power
*
acx
;
...
...
drivers/net/wireless/wl12xx/wl1271_acx.h
浏览文件 @
46bf6958
...
...
@@ -100,35 +100,6 @@ struct acx_error_counter {
__le32
seq_num_miss
;
}
__packed
;
struct
acx_revision
{
struct
acx_header
header
;
/*
* The WiLink firmware version, an ASCII string x.x.x.x,
* that uniquely identifies the current firmware.
* The left most digit is incremented each time a
* significant change is made to the firmware, such as
* code redesign or new platform support.
* The second digit is incremented when major enhancements
* are added or major fixes are made.
* The third digit is incremented for each GA release.
* The fourth digit is incremented for each build.
* The first two digits identify a firmware release version,
* in other words, a unique set of features.
* The first three digits identify a GA release.
*/
char
fw_version
[
20
];
/*
* This 4 byte field specifies the WiLink hardware version.
* bits 0 - 15: Reserved.
* bits 16 - 23: Version ID - The WiLink version ID
* (1 = first spin, 2 = second spin, and so on).
* bits 24 - 31: Chip ID - The WiLink chip ID.
*/
__le32
hw_version
;
}
__packed
;
enum
wl1271_psm_mode
{
/* Active mode */
WL1271_PSM_CAM
=
0
,
...
...
@@ -1060,7 +1031,6 @@ enum {
ACX_PEER_HT_CAP
=
0x0057
,
ACX_HT_BSS_OPERATION
=
0x0058
,
ACX_COEX_ACTIVITY
=
0x0059
,
ACX_SET_SMART_REFLEX_DEBUG
=
0x005A
,
ACX_SET_DCO_ITRIM_PARAMS
=
0x0061
,
DOT11_RX_MSDU_LIFE_TIME
=
0x1004
,
DOT11_CUR_TX_PWR
=
0x100D
,
...
...
@@ -1077,7 +1047,6 @@ enum {
int
wl1271_acx_wake_up_conditions
(
struct
wl1271
*
wl
);
int
wl1271_acx_sleep_auth
(
struct
wl1271
*
wl
,
u8
sleep_auth
);
int
wl1271_acx_fw_version
(
struct
wl1271
*
wl
,
char
*
buf
,
size_t
len
);
int
wl1271_acx_tx_power
(
struct
wl1271
*
wl
,
int
power
);
int
wl1271_acx_feature_cfg
(
struct
wl1271
*
wl
);
int
wl1271_acx_mem_map
(
struct
wl1271
*
wl
,
...
...
drivers/net/wireless/wl12xx/wl1271_boot.c
浏览文件 @
46bf6958
...
...
@@ -225,6 +225,28 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
if
(
wl
->
nvs
==
NULL
)
return
-
ENODEV
;
/*
* FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band
* configurations) can be removed when those NVS files stop floating
* around.
*/
if
(
wl
->
nvs_len
==
sizeof
(
struct
wl1271_nvs_file
)
||
wl
->
nvs_len
==
WL1271_INI_LEGACY_NVS_FILE_SIZE
)
{
if
(
wl
->
nvs
->
general_params
.
dual_mode_select
)
wl
->
enable_11a
=
true
;
}
if
(
wl
->
nvs_len
!=
sizeof
(
struct
wl1271_nvs_file
)
&&
(
wl
->
nvs_len
!=
WL1271_INI_LEGACY_NVS_FILE_SIZE
||
wl
->
enable_11a
))
{
wl1271_error
(
"nvs size is not as expected: %zu != %zu"
,
wl
->
nvs_len
,
sizeof
(
struct
wl1271_nvs_file
));
kfree
(
wl
->
nvs
);
wl
->
nvs
=
NULL
;
wl
->
nvs_len
=
0
;
return
-
EILSEQ
;
}
/* only the first part of the NVS needs to be uploaded */
nvs_len
=
sizeof
(
wl
->
nvs
->
nvs
);
nvs_ptr
=
(
u8
*
)
wl
->
nvs
->
nvs
;
...
...
@@ -251,8 +273,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
burst_len
=
nvs_ptr
[
0
];
dest_addr
=
(
nvs_ptr
[
1
]
&
0xfe
)
|
((
u32
)(
nvs_ptr
[
2
]
<<
8
));
/* FIXME: Due to our new wl1271_translate_reg_addr function,
we need to add the REGISTER_BASE to the destination */
/*
* Due to our new wl1271_translate_reg_addr function,
* we need to add the REGISTER_BASE to the destination
*/
dest_addr
+=
REGISTERS_BASE
;
/* We move our pointer to the data */
...
...
@@ -280,8 +304,6 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
ALIGN
(
nvs_ptr
-
(
u8
*
)
wl
->
nvs
->
nvs
+
7
,
4
);
nvs_len
-=
nvs_ptr
-
(
u8
*
)
wl
->
nvs
->
nvs
;
/* FIXME: The driver sets the partition here, but this is not needed,
since it sets to the same one as currently in use */
/* Now we must set the partition correctly */
wl1271_set_partition
(
wl
,
&
part_table
[
PART_WORK
]);
...
...
@@ -291,9 +313,6 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
return
-
ENOMEM
;
/* And finally we upload the NVS tables */
/* FIXME: In wl1271, we upload everything at once.
No endianness handling needed here?! The ref driver doesn't do
anything about it at this point */
wl1271_write
(
wl
,
CMD_MBOX_ADDRESS
,
nvs_aligned
,
nvs_len
,
false
);
kfree
(
nvs_aligned
);
...
...
@@ -491,10 +510,7 @@ int wl1271_boot(struct wl1271 *wl)
wl1271_debug
(
DEBUG_BOOT
,
"pause1 0x%x"
,
pause
);
pause
&=
~
(
WU_COUNTER_PAUSE_VAL
);
/* FIXME: This should probably be
* WU_COUNTER_PAUSE_VAL instead of
* 0x3ff (magic number ). How does
* this work?! */
pause
&=
~
(
WU_COUNTER_PAUSE_VAL
);
pause
|=
WU_COUNTER_PAUSE_VAL
;
wl1271_write32
(
wl
,
WU_COUNTER_PAUSE
,
pause
);
...
...
@@ -548,7 +564,6 @@ int wl1271_boot(struct wl1271 *wl)
if
(
ret
<
0
)
goto
out
;
/* FIXME: Need to check whether this is really what we want */
wl1271_write32
(
wl
,
ACX_REG_INTERRUPT_MASK
,
WL1271_ACX_ALL_EVENTS_VECTOR
);
...
...
drivers/net/wireless/wl12xx/wl1271_cmd.c
浏览文件 @
46bf6958
...
...
@@ -94,6 +94,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
status
=
le16_to_cpu
(
cmd
->
status
);
if
(
status
!=
CMD_STATUS_SUCCESS
)
{
wl1271_error
(
"command execute failure %d"
,
status
);
ieee80211_queue_work
(
wl
->
hw
,
&
wl
->
recovery_work
);
ret
=
-
EIO
;
}
...
...
@@ -170,6 +171,39 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
return
ret
;
}
int
wl1271_cmd_ext_radio_parms
(
struct
wl1271
*
wl
)
{
struct
wl1271_ext_radio_parms_cmd
*
ext_radio_parms
;
struct
conf_rf_settings
*
rf
=
&
wl
->
conf
.
rf
;
int
ret
;
if
(
!
wl
->
nvs
)
return
-
ENODEV
;
ext_radio_parms
=
kzalloc
(
sizeof
(
*
ext_radio_parms
),
GFP_KERNEL
);
if
(
!
ext_radio_parms
)
return
-
ENOMEM
;
ext_radio_parms
->
test
.
id
=
TEST_CMD_INI_FILE_RF_EXTENDED_PARAM
;
memcpy
(
ext_radio_parms
->
tx_per_channel_power_compensation_2
,
rf
->
tx_per_channel_power_compensation_2
,
CONF_TX_PWR_COMPENSATION_LEN_2
);
memcpy
(
ext_radio_parms
->
tx_per_channel_power_compensation_5
,
rf
->
tx_per_channel_power_compensation_5
,
CONF_TX_PWR_COMPENSATION_LEN_5
);
wl1271_dump
(
DEBUG_CMD
,
"TEST_CMD_INI_FILE_EXT_RADIO_PARAM: "
,
ext_radio_parms
,
sizeof
(
*
ext_radio_parms
));
ret
=
wl1271_cmd_test
(
wl
,
ext_radio_parms
,
sizeof
(
*
ext_radio_parms
),
0
);
if
(
ret
<
0
)
wl1271_warning
(
"TEST_CMD_INI_FILE_RF_EXTENDED_PARAM failed"
);
kfree
(
ext_radio_parms
);
return
ret
;
}
/*
* Poll the mailbox event field until any of the bits in the mask is set or a
* timeout occurs (WL1271_EVENT_TIMEOUT in msecs)
...
...
@@ -182,8 +216,10 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
timeout
=
jiffies
+
msecs_to_jiffies
(
WL1271_EVENT_TIMEOUT
);
do
{
if
(
time_after
(
jiffies
,
timeout
))
if
(
time_after
(
jiffies
,
timeout
))
{
ieee80211_queue_work
(
wl
->
hw
,
&
wl
->
recovery_work
);
return
-
ETIMEDOUT
;
}
msleep
(
1
);
...
...
@@ -390,18 +426,11 @@ int wl1271_cmd_data_path(struct wl1271 *wl, bool enable)
return
ret
;
}
int
wl1271_cmd_ps_mode
(
struct
wl1271
*
wl
,
u8
ps_mode
,
bool
send
)
int
wl1271_cmd_ps_mode
(
struct
wl1271
*
wl
,
u8
ps_mode
,
u32
rates
,
bool
send
)
{
struct
wl1271_cmd_ps_params
*
ps_params
=
NULL
;
int
ret
=
0
;
/* FIXME: this should be in ps.c */
ret
=
wl1271_acx_wake_up_conditions
(
wl
);
if
(
ret
<
0
)
{
wl1271_error
(
"couldn't set wake up conditions"
);
goto
out
;
}
wl1271_debug
(
DEBUG_CMD
,
"cmd set ps mode"
);
ps_params
=
kzalloc
(
sizeof
(
*
ps_params
),
GFP_KERNEL
);
...
...
@@ -412,9 +441,9 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send)
ps_params
->
ps_mode
=
ps_mode
;
ps_params
->
send_null_data
=
send
;
ps_params
->
retries
=
5
;
ps_params
->
hang_over_period
=
1
;
ps_params
->
null_data_rate
=
cpu_to_le32
(
wl
->
basic_rate_set
);
ps_params
->
retries
=
wl
->
conf
.
conn
.
psm_entry_nullfunc_retries
;
ps_params
->
hang_over_period
=
wl
->
conf
.
conn
.
psm_entry_hangover_period
;
ps_params
->
null_data_rate
=
cpu_to_le32
(
rates
);
ret
=
wl1271_cmd_send
(
wl
,
CMD_SET_PS_MODE
,
ps_params
,
sizeof
(
*
ps_params
),
0
);
...
...
@@ -428,41 +457,6 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send)
return
ret
;
}
int
wl1271_cmd_read_memory
(
struct
wl1271
*
wl
,
u32
addr
,
void
*
answer
,
size_t
len
)
{
struct
cmd_read_write_memory
*
cmd
;
int
ret
=
0
;
wl1271_debug
(
DEBUG_CMD
,
"cmd read memory"
);
cmd
=
kzalloc
(
sizeof
(
*
cmd
),
GFP_KERNEL
);
if
(
!
cmd
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
WARN_ON
(
len
>
MAX_READ_SIZE
);
len
=
min_t
(
size_t
,
len
,
MAX_READ_SIZE
);
cmd
->
addr
=
cpu_to_le32
(
addr
);
cmd
->
size
=
cpu_to_le32
(
len
);
ret
=
wl1271_cmd_send
(
wl
,
CMD_READ_MEMORY
,
cmd
,
sizeof
(
*
cmd
),
sizeof
(
*
cmd
));
if
(
ret
<
0
)
{
wl1271_error
(
"read memory command failed: %d"
,
ret
);
goto
out
;
}
/* the read command got in */
memcpy
(
answer
,
cmd
->
value
,
len
);
out:
kfree
(
cmd
);
return
ret
;
}
int
wl1271_cmd_template_set
(
struct
wl1271
*
wl
,
u16
template_id
,
void
*
buf
,
size_t
buf_len
,
int
index
,
u32
rates
)
{
...
...
@@ -523,7 +517,7 @@ int wl1271_cmd_build_null_data(struct wl1271 *wl)
}
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_NULL_DATA
,
ptr
,
size
,
0
,
WL1271_RATE_AUTOMATIC
);
wl
->
basic_rate
);
out:
dev_kfree_skb
(
skb
);
...
...
@@ -546,7 +540,7 @@ int wl1271_cmd_build_klv_null_data(struct wl1271 *wl)
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_KLV
,
skb
->
data
,
skb
->
len
,
CMD_TEMPL_KLV_IDX_NULL_DATA
,
WL1271_RATE_AUTOMATIC
);
wl
->
basic_rate
);
out:
dev_kfree_skb
(
skb
);
...
...
@@ -623,7 +617,7 @@ int wl1271_build_qos_null_data(struct wl1271 *wl)
return
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_QOS_NULL_DATA
,
&
template
,
sizeof
(
template
),
0
,
WL1271_RATE_AUTOMATIC
);
wl
->
basic_rate
);
}
int
wl1271_cmd_set_default_wep_key
(
struct
wl1271
*
wl
,
u8
id
)
...
...
@@ -746,3 +740,31 @@ int wl1271_cmd_disconnect(struct wl1271 *wl)
out:
return
ret
;
}
int
wl1271_cmd_set_sta_state
(
struct
wl1271
*
wl
)
{
struct
wl1271_cmd_set_sta_state
*
cmd
;
int
ret
=
0
;
wl1271_debug
(
DEBUG_CMD
,
"cmd set sta state"
);
cmd
=
kzalloc
(
sizeof
(
*
cmd
),
GFP_KERNEL
);
if
(
!
cmd
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
cmd
->
state
=
WL1271_CMD_STA_STATE_CONNECTED
;
ret
=
wl1271_cmd_send
(
wl
,
CMD_SET_STA_STATE
,
cmd
,
sizeof
(
*
cmd
),
0
);
if
(
ret
<
0
)
{
wl1271_error
(
"failed to send set STA state command"
);
goto
out_free
;
}
out_free:
kfree
(
cmd
);
out:
return
ret
;
}
drivers/net/wireless/wl12xx/wl1271_cmd.h
浏览文件 @
46bf6958
...
...
@@ -33,12 +33,13 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
size_t
res_len
);
int
wl1271_cmd_general_parms
(
struct
wl1271
*
wl
);
int
wl1271_cmd_radio_parms
(
struct
wl1271
*
wl
);
int
wl1271_cmd_ext_radio_parms
(
struct
wl1271
*
wl
);
int
wl1271_cmd_join
(
struct
wl1271
*
wl
,
u8
bss_type
);
int
wl1271_cmd_test
(
struct
wl1271
*
wl
,
void
*
buf
,
size_t
buf_len
,
u8
answer
);
int
wl1271_cmd_interrogate
(
struct
wl1271
*
wl
,
u16
id
,
void
*
buf
,
size_t
len
);
int
wl1271_cmd_configure
(
struct
wl1271
*
wl
,
u16
id
,
void
*
buf
,
size_t
len
);
int
wl1271_cmd_data_path
(
struct
wl1271
*
wl
,
bool
enable
);
int
wl1271_cmd_ps_mode
(
struct
wl1271
*
wl
,
u8
ps_mode
,
bool
send
);
int
wl1271_cmd_ps_mode
(
struct
wl1271
*
wl
,
u8
ps_mode
,
u32
rates
,
bool
send
);
int
wl1271_cmd_read_memory
(
struct
wl1271
*
wl
,
u32
addr
,
void
*
answer
,
size_t
len
);
int
wl1271_cmd_template_set
(
struct
wl1271
*
wl
,
u16
template_id
,
...
...
@@ -55,6 +56,7 @@ int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
u8
key_size
,
const
u8
*
key
,
const
u8
*
addr
,
u32
tx_seq_32
,
u16
tx_seq_16
);
int
wl1271_cmd_disconnect
(
struct
wl1271
*
wl
);
int
wl1271_cmd_set_sta_state
(
struct
wl1271
*
wl
);
enum
wl1271_commands
{
CMD_INTERROGATE
=
1
,
/*use this to read information elements*/
...
...
@@ -160,41 +162,6 @@ enum {
MAX_COMMAND_STATUS
=
0xff
};
/*
* CMD_READ_MEMORY
*
* The host issues this command to read the WiLink device memory/registers.
*
* Note: The Base Band address has special handling (16 bits registers and
* addresses). For more information, see the hardware specification.
*/
/*
* CMD_WRITE_MEMORY
*
* The host issues this command to write the WiLink device memory/registers.
*
* The Base Band address has special handling (16 bits registers and
* addresses). For more information, see the hardware specification.
*/
#define MAX_READ_SIZE 256
struct
cmd_read_write_memory
{
struct
wl1271_cmd_header
header
;
/* The address of the memory to read from or write to.*/
__le32
addr
;
/* The amount of data in bytes to read from or write to the WiLink
* device.*/
__le32
size
;
/* The actual value read from or written to the Wilink. The source
of this field is the Host in WRITE command or the Wilink in READ
command. */
u8
value
[
MAX_READ_SIZE
];
}
__packed
;
#define CMDMBOX_HEADER_LEN 4
#define CMDMBOX_INFO_ELEM_HEADER_LEN 4
...
...
@@ -313,7 +280,7 @@ enum wl1271_cmd_key_type {
KEY_WEP
=
1
,
KEY_TKIP
=
2
,
KEY_AES
=
3
,
KEY_GEM
=
4
KEY_GEM
=
4
,
};
/* FIXME: Add description for key-types */
...
...
@@ -358,13 +325,14 @@ enum wl1271_channel_tune_bands {
WL1271_CHANNEL_TUNE_BAND_4_9
};
#define WL1271_PD_REFERENCE_POINT_BAND_B_G 0
#define WL1271_PD_REFERENCE_POINT_BAND_B_G
0
#define TEST_CMD_P2G_CAL 0x02
#define TEST_CMD_CHANNEL_TUNE 0x0d
#define TEST_CMD_UPDATE_PD_REFERENCE_POINT 0x1d
#define TEST_CMD_INI_FILE_RADIO_PARAM 0x19
#define TEST_CMD_INI_FILE_GENERAL_PARAM 0x1E
#define TEST_CMD_P2G_CAL 0x02
#define TEST_CMD_CHANNEL_TUNE 0x0d
#define TEST_CMD_UPDATE_PD_REFERENCE_POINT 0x1d
#define TEST_CMD_INI_FILE_RADIO_PARAM 0x19
#define TEST_CMD_INI_FILE_GENERAL_PARAM 0x1E
#define TEST_CMD_INI_FILE_RF_EXTENDED_PARAM 0x26
struct
wl1271_general_parms_cmd
{
struct
wl1271_cmd_header
header
;
...
...
@@ -397,6 +365,16 @@ struct wl1271_radio_parms_cmd {
u8
padding3
[
2
];
}
__packed
;
struct
wl1271_ext_radio_parms_cmd
{
struct
wl1271_cmd_header
header
;
struct
wl1271_cmd_test_header
test
;
u8
tx_per_channel_power_compensation_2
[
CONF_TX_PWR_COMPENSATION_LEN_2
];
u8
tx_per_channel_power_compensation_5
[
CONF_TX_PWR_COMPENSATION_LEN_5
];
u8
padding
[
3
];
}
__packed
;
struct
wl1271_cmd_cal_channel_tune
{
struct
wl1271_cmd_header
header
;
...
...
@@ -469,4 +447,13 @@ struct wl1271_cmd_disconnect {
u8
padding
;
}
__packed
;
#define WL1271_CMD_STA_STATE_CONNECTED 1
struct
wl1271_cmd_set_sta_state
{
struct
wl1271_cmd_header
header
;
u8
state
;
u8
padding
[
3
];
}
__packed
;
#endif
/* __WL1271_CMD_H__ */
drivers/net/wireless/wl12xx/wl1271_conf.h
浏览文件 @
46bf6958
...
...
@@ -595,7 +595,7 @@ struct conf_tx_ac_category {
u16
tx_op_limit
;
};
#define CONF_TX_MAX_TID_COUNT
7
#define CONF_TX_MAX_TID_COUNT
8
enum
{
CONF_CHANNEL_TYPE_DCF
=
0
,
/* DC/LEGACY*/
...
...
@@ -911,6 +911,22 @@ struct conf_conn_settings {
*/
u8
psm_entry_retries
;
/*
* Specifies the maximum number of times to try transmit the PSM entry
* null-func frame for each PSM entry attempt
*
* Range 0 - 255
*/
u8
psm_entry_nullfunc_retries
;
/*
* Specifies the time to linger in active mode after successfully
* transmitting the PSM entry null-func frame.
*
* Range 0 - 255 TU's
*/
u8
psm_entry_hangover_period
;
/*
*
* Specifies the interval of the connection keep-alive null-func
...
...
@@ -1016,6 +1032,64 @@ struct conf_roam_trigger_settings {
u8
avg_weight_snr_data
;
};
struct
conf_scan_settings
{
/*
* The minimum time to wait on each channel for active scans
*
* Range: 0 - 65536 tu
*/
u16
min_dwell_time_active
;
/*
* The maximum time to wait on each channel for active scans
*
* Range: 0 - 65536 tu
*/
u16
max_dwell_time_active
;
/*
* The maximum time to wait on each channel for passive scans
*
* Range: 0 - 65536 tu
*/
u16
min_dwell_time_passive
;
/*
* The maximum time to wait on each channel for passive scans
*
* Range: 0 - 65536 tu
*/
u16
max_dwell_time_passive
;
/*
* Number of probe requests to transmit on each active scan channel
*
* Range: u8
*/
u16
num_probe_reqs
;
};
/* these are number of channels on the band divided by two, rounded up */
#define CONF_TX_PWR_COMPENSATION_LEN_2 7
#define CONF_TX_PWR_COMPENSATION_LEN_5 18
struct
conf_rf_settings
{
/*
* Per channel power compensation for 2.4GHz
*
* Range: s8
*/
u8
tx_per_channel_power_compensation_2
[
CONF_TX_PWR_COMPENSATION_LEN_2
];
/*
* Per channel power compensation for 5GHz
*
* Range: s8
*/
u8
tx_per_channel_power_compensation_5
[
CONF_TX_PWR_COMPENSATION_LEN_5
];
};
struct
conf_drv_settings
{
struct
conf_sg_settings
sg
;
struct
conf_rx_settings
rx
;
...
...
@@ -1024,6 +1098,8 @@ struct conf_drv_settings {
struct
conf_itrim_settings
itrim
;
struct
conf_pm_config_settings
pm_config
;
struct
conf_roam_trigger_settings
roam_trigger
;
struct
conf_scan_settings
scan
;
struct
conf_rf_settings
rf
;
};
#endif
drivers/net/wireless/wl12xx/wl1271_event.c
浏览文件 @
46bf6958
...
...
@@ -41,6 +41,9 @@ void wl1271_pspoll_work(struct work_struct *work)
mutex_lock
(
&
wl
->
mutex
);
if
(
unlikely
(
wl
->
state
==
WL1271_STATE_OFF
))
goto
out
;
if
(
!
test_and_clear_bit
(
WL1271_FLAG_PSPOLL_FAILURE
,
&
wl
->
flags
))
goto
out
;
...
...
@@ -52,7 +55,7 @@ void wl1271_pspoll_work(struct work_struct *work)
* delivery failure occurred, and no-one changed state since, so
* we should go back to powersave.
*/
wl1271_ps_set_mode
(
wl
,
STATION_POWER_SAVE_MODE
,
true
);
wl1271_ps_set_mode
(
wl
,
STATION_POWER_SAVE_MODE
,
wl
->
basic_rate
,
true
);
out:
mutex_unlock
(
&
wl
->
mutex
);
...
...
@@ -70,7 +73,8 @@ static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl)
/* force active mode receive data from the AP */
if
(
test_bit
(
WL1271_FLAG_PSM
,
&
wl
->
flags
))
{
ret
=
wl1271_ps_set_mode
(
wl
,
STATION_ACTIVE_MODE
,
true
);
ret
=
wl1271_ps_set_mode
(
wl
,
STATION_ACTIVE_MODE
,
wl
->
basic_rate
,
true
);
if
(
ret
<
0
)
return
;
set_bit
(
WL1271_FLAG_PSPOLL_FAILURE
,
&
wl
->
flags
);
...
...
@@ -91,6 +95,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
bool
*
beacon_loss
)
{
int
ret
=
0
;
u32
total_retries
=
wl
->
conf
.
conn
.
psm_entry_retries
;
wl1271_debug
(
DEBUG_EVENT
,
"ps_status: 0x%x"
,
mbox
->
ps_status
);
...
...
@@ -104,10 +109,10 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
break
;
}
if
(
wl
->
psm_entry_retry
<
wl
->
conf
.
conn
.
psm_entry
_retries
)
{
if
(
wl
->
psm_entry_retry
<
total
_retries
)
{
wl
->
psm_entry_retry
++
;
ret
=
wl1271_ps_set_mode
(
wl
,
STATION_POWER_SAVE_MODE
,
true
);
wl
->
basic_rate
,
true
);
}
else
{
wl1271_info
(
"No ack to nullfunc from AP."
);
wl
->
psm_entry_retry
=
0
;
...
...
@@ -143,7 +148,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
/* make sure the firmware goes to active mode - the frame to
be sent next will indicate to the AP, that we are active. */
ret
=
wl1271_ps_set_mode
(
wl
,
STATION_ACTIVE_MODE
,
false
);
wl
->
basic_rate
,
false
);
break
;
case
EVENT_EXIT_POWER_SAVE_SUCCESS
:
default:
...
...
drivers/net/wireless/wl12xx/wl1271_init.c
浏览文件 @
46bf6958
...
...
@@ -53,6 +53,7 @@ static int wl1271_init_hwenc_config(struct wl1271 *wl)
int
wl1271_init_templates_config
(
struct
wl1271
*
wl
)
{
int
ret
,
i
;
size_t
size
;
/* send empty templates for fw memory reservation */
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_CFG_PROBE_REQ_2_4
,
NULL
,
...
...
@@ -61,14 +62,12 @@ int wl1271_init_templates_config(struct wl1271 *wl)
if
(
ret
<
0
)
return
ret
;
if
(
wl1271_11a_enabled
())
{
size_t
size
=
sizeof
(
struct
wl12xx_probe_req_template
);
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_CFG_PROBE_REQ_5
,
NULL
,
size
,
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
return
ret
;
}
size
=
sizeof
(
struct
wl12xx_probe_req_template
);
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_CFG_PROBE_REQ_5
,
NULL
,
size
,
0
,
WL1271_RATE_AUTOMATIC
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_cmd_template_set
(
wl
,
CMD_TEMPL_NULL_DATA
,
NULL
,
sizeof
(
struct
wl12xx_null_data_template
),
...
...
@@ -223,6 +222,10 @@ int wl1271_hw_init(struct wl1271 *wl)
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_cmd_ext_radio_parms
(
wl
);
if
(
ret
<
0
)
return
ret
;
/* Template settings */
ret
=
wl1271_init_templates_config
(
wl
);
if
(
ret
<
0
)
...
...
@@ -291,8 +294,16 @@ int wl1271_hw_init(struct wl1271 *wl)
if
(
ret
<
0
)
goto
out_free_memmap
;
/* Default TID configuration */
/* Default TID/AC configuration */
BUG_ON
(
wl
->
conf
.
tx
.
tid_conf_count
!=
wl
->
conf
.
tx
.
ac_conf_count
);
for
(
i
=
0
;
i
<
wl
->
conf
.
tx
.
tid_conf_count
;
i
++
)
{
conf_ac
=
&
wl
->
conf
.
tx
.
ac_conf
[
i
];
ret
=
wl1271_acx_ac_cfg
(
wl
,
conf_ac
->
ac
,
conf_ac
->
cw_min
,
conf_ac
->
cw_max
,
conf_ac
->
aifsn
,
conf_ac
->
tx_op_limit
);
if
(
ret
<
0
)
goto
out_free_memmap
;
conf_tid
=
&
wl
->
conf
.
tx
.
tid_conf
[
i
];
ret
=
wl1271_acx_tid_cfg
(
wl
,
conf_tid
->
queue_id
,
conf_tid
->
channel_type
,
...
...
@@ -305,16 +316,6 @@ int wl1271_hw_init(struct wl1271 *wl)
goto
out_free_memmap
;
}
/* Default AC configuration */
for
(
i
=
0
;
i
<
wl
->
conf
.
tx
.
ac_conf_count
;
i
++
)
{
conf_ac
=
&
wl
->
conf
.
tx
.
ac_conf
[
i
];
ret
=
wl1271_acx_ac_cfg
(
wl
,
conf_ac
->
ac
,
conf_ac
->
cw_min
,
conf_ac
->
cw_max
,
conf_ac
->
aifsn
,
conf_ac
->
tx_op_limit
);
if
(
ret
<
0
)
goto
out_free_memmap
;
}
/* Configure TX rate classes */
ret
=
wl1271_acx_rate_policies
(
wl
);
if
(
ret
<
0
)
...
...
drivers/net/wireless/wl12xx/wl1271_main.c
浏览文件 @
46bf6958
此差异已折叠。
点击以展开。
drivers/net/wireless/wl12xx/wl1271_ps.c
浏览文件 @
46bf6958
...
...
@@ -39,6 +39,9 @@ void wl1271_elp_work(struct work_struct *work)
mutex_lock
(
&
wl
->
mutex
);
if
(
unlikely
(
wl
->
state
==
WL1271_STATE_OFF
))
goto
out
;
if
(
test_bit
(
WL1271_FLAG_IN_ELP
,
&
wl
->
flags
)
||
(
!
test_bit
(
WL1271_FLAG_PSM
,
&
wl
->
flags
)
&&
!
test_bit
(
WL1271_FLAG_IDLE
,
&
wl
->
flags
)))
...
...
@@ -61,7 +64,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
test_bit
(
WL1271_FLAG_IDLE
,
&
wl
->
flags
))
{
cancel_delayed_work
(
&
wl
->
elp_work
);
ieee80211_queue_delayed_work
(
wl
->
hw
,
&
wl
->
elp_work
,
msecs_to_jiffies
(
ELP_ENTRY_DELAY
));
msecs_to_jiffies
(
ELP_ENTRY_DELAY
));
}
}
...
...
@@ -96,6 +99,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake)
&
compl
,
msecs_to_jiffies
(
WL1271_WAKEUP_TIMEOUT
));
if
(
ret
==
0
)
{
wl1271_error
(
"ELP wakeup timeout!"
);
ieee80211_queue_work
(
wl
->
hw
,
&
wl
->
recovery_work
);
ret
=
-
ETIMEDOUT
;
goto
err
;
}
else
if
(
ret
<
0
)
{
...
...
@@ -121,7 +125,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake)
}
int
wl1271_ps_set_mode
(
struct
wl1271
*
wl
,
enum
wl1271_cmd_ps_mode
mode
,
bool
send
)
u32
rates
,
bool
send
)
{
int
ret
;
...
...
@@ -129,7 +133,14 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
case
STATION_POWER_SAVE_MODE
:
wl1271_debug
(
DEBUG_PSM
,
"entering psm"
);
ret
=
wl1271_cmd_ps_mode
(
wl
,
STATION_POWER_SAVE_MODE
,
send
);
ret
=
wl1271_acx_wake_up_conditions
(
wl
);
if
(
ret
<
0
)
{
wl1271_error
(
"couldn't set wake up conditions"
);
return
ret
;
}
ret
=
wl1271_cmd_ps_mode
(
wl
,
STATION_POWER_SAVE_MODE
,
rates
,
send
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -152,7 +163,8 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_cmd_ps_mode
(
wl
,
STATION_ACTIVE_MODE
,
send
);
ret
=
wl1271_cmd_ps_mode
(
wl
,
STATION_ACTIVE_MODE
,
rates
,
send
);
if
(
ret
<
0
)
return
ret
;
...
...
drivers/net/wireless/wl12xx/wl1271_ps.h
浏览文件 @
46bf6958
...
...
@@ -28,7 +28,7 @@
#include "wl1271_acx.h"
int
wl1271_ps_set_mode
(
struct
wl1271
*
wl
,
enum
wl1271_cmd_ps_mode
mode
,
bool
send
);
u32
rates
,
bool
send
);
void
wl1271_ps_elp_sleep
(
struct
wl1271
*
wl
);
int
wl1271_ps_elp_wakeup
(
struct
wl1271
*
wl
,
bool
chip_awake
);
void
wl1271_elp_work
(
struct
work_struct
*
work
);
...
...
drivers/net/wireless/wl12xx/wl1271_rx.c
浏览文件 @
46bf6958
...
...
@@ -74,7 +74,7 @@ static void wl1271_rx_status(struct wl1271 *wl,
}
}
static
void
wl1271_rx_handle_data
(
struct
wl1271
*
wl
,
u32
length
)
static
int
wl1271_rx_handle_data
(
struct
wl1271
*
wl
,
u8
*
data
,
u32
length
)
{
struct
wl1271_rx_descriptor
*
desc
;
struct
sk_buff
*
skb
;
...
...
@@ -87,16 +87,16 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
* workaround this by not retrieving them at all.
*/
if
(
unlikely
(
wl
->
state
==
WL1271_STATE_PLT
))
return
;
return
-
EINVAL
;
skb
=
__dev_alloc_skb
(
length
,
GFP_KERNEL
);
if
(
!
skb
)
{
wl1271_error
(
"Couldn't allocate RX frame"
);
return
;
return
-
ENOMEM
;
}
buf
=
skb_put
(
skb
,
length
);
wl1271_read
(
wl
,
WL1271_SLV_MEM_DATA
,
buf
,
length
,
true
);
memcpy
(
buf
,
data
,
length
);
/* the data read starts with the descriptor */
desc
=
(
struct
wl1271_rx_descriptor
*
)
buf
;
...
...
@@ -116,6 +116,8 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
skb_trim
(
skb
,
skb
->
len
-
desc
->
pad_len
);
ieee80211_rx_ni
(
wl
->
hw
,
skb
);
return
0
;
}
void
wl1271_rx
(
struct
wl1271
*
wl
,
struct
wl1271_fw_status
*
status
)
...
...
@@ -124,31 +126,60 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
u32
buf_size
;
u32
fw_rx_counter
=
status
->
fw_rx_counter
&
NUM_RX_PKT_DESC_MOD_MASK
;
u32
drv_rx_counter
=
wl
->
rx_counter
&
NUM_RX_PKT_DESC_MOD_MASK
;
u32
rx_counter
;
u32
mem_block
;
u32
pkt_length
;
u32
pkt_offset
;
while
(
drv_rx_counter
!=
fw_rx_counter
)
{
mem_block
=
wl1271_rx_get_mem_block
(
status
,
drv_rx_counter
);
buf_size
=
wl1271_rx_get_buf_size
(
status
,
drv_rx_counter
);
buf_size
=
0
;
rx_counter
=
drv_rx_counter
;
while
(
rx_counter
!=
fw_rx_counter
)
{
pkt_length
=
wl1271_rx_get_buf_size
(
status
,
rx_counter
);
if
(
buf_size
+
pkt_length
>
WL1271_AGGR_BUFFER_SIZE
)
break
;
buf_size
+=
pkt_length
;
rx_counter
++
;
rx_counter
&=
NUM_RX_PKT_DESC_MOD_MASK
;
}
if
(
buf_size
==
0
)
{
wl1271_warning
(
"received empty data"
);
break
;
}
/*
* Choose the block we want to read
* For aggregated packets, only the first memory block should
* be retrieved. The FW takes care of the rest.
*/
mem_block
=
wl1271_rx_get_mem_block
(
status
,
drv_rx_counter
);
wl
->
rx_mem_pool_addr
.
addr
=
(
mem_block
<<
8
)
+
le32_to_cpu
(
wl_mem_map
->
packet_memory_pool_start
);
wl
->
rx_mem_pool_addr
.
addr_extra
=
wl
->
rx_mem_pool_addr
.
addr
+
4
;
/* Choose the block we want to read */
wl1271_write
(
wl
,
WL1271_SLV_REG_DATA
,
&
wl
->
rx_mem_pool_addr
,
sizeof
(
wl
->
rx_mem_pool_addr
),
false
);
wl1271_rx_handle_data
(
wl
,
buf_size
);
wl
->
rx_counter
++
;
drv_rx_counter
=
wl
->
rx_counter
&
NUM_RX_PKT_DESC_MOD_MASK
;
sizeof
(
wl
->
rx_mem_pool_addr
),
false
);
/* Read all available packets at once */
wl1271_read
(
wl
,
WL1271_SLV_MEM_DATA
,
wl
->
aggr_buf
,
buf_size
,
true
);
/* Split data into separate packets */
pkt_offset
=
0
;
while
(
pkt_offset
<
buf_size
)
{
pkt_length
=
wl1271_rx_get_buf_size
(
status
,
drv_rx_counter
);
if
(
wl1271_rx_handle_data
(
wl
,
wl
->
aggr_buf
+
pkt_offset
,
pkt_length
)
<
0
)
break
;
wl
->
rx_counter
++
;
drv_rx_counter
++
;
drv_rx_counter
&=
NUM_RX_PKT_DESC_MOD_MASK
;
pkt_offset
+=
pkt_length
;
}
}
wl1271_write32
(
wl
,
RX_DRIVER_COUNTER_ADDRESS
,
wl
->
rx_counter
);
wl1271_write32
(
wl
,
RX_DRIVER_COUNTER_ADDRESS
,
cpu_to_le32
(
wl
->
rx_counter
)
);
}
drivers/net/wireless/wl12xx/wl1271_scan.c
浏览文件 @
46bf6958
...
...
@@ -28,11 +28,43 @@
#include "wl1271_scan.h"
#include "wl1271_acx.h"
void
wl1271_scan_complete_work
(
struct
work_struct
*
work
)
{
struct
delayed_work
*
dwork
;
struct
wl1271
*
wl
;
dwork
=
container_of
(
work
,
struct
delayed_work
,
work
);
wl
=
container_of
(
dwork
,
struct
wl1271
,
scan_complete_work
);
wl1271_debug
(
DEBUG_SCAN
,
"Scanning complete"
);
mutex_lock
(
&
wl
->
mutex
);
if
(
wl
->
scan
.
state
==
WL1271_SCAN_STATE_IDLE
)
{
mutex_unlock
(
&
wl
->
mutex
);
return
;
}
wl
->
scan
.
state
=
WL1271_SCAN_STATE_IDLE
;
kfree
(
wl
->
scan
.
scanned_ch
);
wl
->
scan
.
scanned_ch
=
NULL
;
mutex_unlock
(
&
wl
->
mutex
);
ieee80211_scan_completed
(
wl
->
hw
,
false
);
if
(
wl
->
scan
.
failed
)
{
wl1271_info
(
"Scan completed due to error."
);
ieee80211_queue_work
(
wl
->
hw
,
&
wl
->
recovery_work
);
}
}
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
;
...
...
@@ -60,10 +92,17 @@ static int wl1271_get_scan_channels(struct wl1271 *wl,
wl1271_debug
(
DEBUG_SCAN
,
"beacon_found %d"
,
req
->
channels
[
i
]
->
beacon_found
);
channels
[
j
].
min_duration
=
cpu_to_le32
(
WL1271_SCAN_CHAN_MIN_DURATION
);
channels
[
j
].
max_duration
=
cpu_to_le32
(
WL1271_SCAN_CHAN_MAX_DURATION
);
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
->
min_dwell_time_passive
);
channels
[
j
].
max_duration
=
cpu_to_le32
(
c
->
max_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
;
...
...
@@ -100,8 +139,11 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
/* We always use high priority scans */
scan_options
=
WL1271_SCAN_OPT_PRIORITY_HIGH
;
if
(
passive
)
/* No SSIDs means that we have a forced passive scan */
if
(
passive
||
wl
->
scan
.
req
->
n_ssids
==
0
)
scan_options
|=
WL1271_SCAN_OPT_PASSIVE
;
cmd
->
params
.
scan_options
=
cpu_to_le16
(
scan_options
);
cmd
->
params
.
n_ch
=
wl1271_get_scan_channels
(
wl
,
wl
->
scan
.
req
,
...
...
@@ -117,7 +159,7 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
cmd
->
params
.
rx_filter_options
=
cpu_to_le32
(
CFG_RX_PRSP_EN
|
CFG_RX_MGMT_EN
|
CFG_RX_BCN_EN
);
cmd
->
params
.
n_probe_reqs
=
WL1271_SCAN_PROBE_REQS
;
cmd
->
params
.
n_probe_reqs
=
wl
->
conf
.
scan
.
num_probe_reqs
;
cmd
->
params
.
tx_rate
=
cpu_to_le32
(
basic_rate
);
cmd
->
params
.
tid_trigger
=
0
;
cmd
->
params
.
scan_tag
=
WL1271_SCAN_DEFAULT_TAG
;
...
...
@@ -165,7 +207,7 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
void
wl1271_scan_stm
(
struct
wl1271
*
wl
)
{
int
ret
;
int
ret
=
0
;
switch
(
wl
->
scan
.
state
)
{
case
WL1271_SCAN_STATE_IDLE
:
...
...
@@ -185,7 +227,7 @@ void wl1271_scan_stm(struct wl1271 *wl)
ret
=
wl1271_scan_send
(
wl
,
IEEE80211_BAND_2GHZ
,
true
,
wl
->
conf
.
tx
.
basic_rate
);
if
(
ret
==
WL1271_NOTHING_TO_SCAN
)
{
if
(
wl
1271_11a_enabled
()
)
if
(
wl
->
enable_11a
)
wl
->
scan
.
state
=
WL1271_SCAN_STATE_5GHZ_ACTIVE
;
else
wl
->
scan
.
state
=
WL1271_SCAN_STATE_DONE
;
...
...
@@ -215,18 +257,22 @@ void wl1271_scan_stm(struct wl1271 *wl)
break
;
case
WL1271_SCAN_STATE_DONE
:
ieee80211_scan_completed
(
wl
->
hw
,
false
);
kfree
(
wl
->
scan
.
scanned_ch
);
wl
->
scan
.
scanned_ch
=
NULL
;
wl
->
scan
.
state
=
WL1271_SCAN_STATE_IDLE
;
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
));
}
}
int
wl1271_scan
(
struct
wl1271
*
wl
,
const
u8
*
ssid
,
size_t
ssid_len
,
...
...
@@ -249,6 +295,11 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
wl
->
scan
.
scanned_ch
=
kzalloc
(
req
->
n_channels
*
sizeof
(
*
wl
->
scan
.
scanned_ch
),
GFP_KERNEL
);
/* we assume failure so that timeout scenarios are handled correctly */
wl
->
scan
.
failed
=
true
;
ieee80211_queue_delayed_work
(
wl
->
hw
,
&
wl
->
scan_complete_work
,
msecs_to_jiffies
(
WL1271_SCAN_TIMEOUT
));
wl1271_scan_stm
(
wl
);
return
0
;
...
...
drivers/net/wireless/wl12xx/wl1271_scan.h
浏览文件 @
46bf6958
...
...
@@ -32,6 +32,7 @@ int wl1271_scan_build_probe_req(struct wl1271 *wl,
const
u8
*
ssid
,
size_t
ssid_len
,
const
u8
*
ie
,
size_t
ie_len
,
u8
band
);
void
wl1271_scan_stm
(
struct
wl1271
*
wl
);
void
wl1271_scan_complete_work
(
struct
work_struct
*
work
);
#define WL1271_SCAN_MAX_CHANNELS 24
#define WL1271_SCAN_DEFAULT_TAG 1
...
...
@@ -39,11 +40,10 @@ void wl1271_scan_stm(struct wl1271 *wl);
#define WL1271_SCAN_OPT_ACTIVE 0
#define WL1271_SCAN_OPT_PASSIVE 1
#define WL1271_SCAN_OPT_PRIORITY_HIGH 4
#define WL1271_SCAN_CHAN_MIN_DURATION 30000
/* TU */
#define WL1271_SCAN_CHAN_MAX_DURATION 60000
/* TU */
#define WL1271_SCAN_BAND_2_4_GHZ 0
#define WL1271_SCAN_BAND_5_GHZ 1
#define WL1271_SCAN_PROBE_REQS 3
#define WL1271_SCAN_TIMEOUT 10000
/* msec */
enum
{
WL1271_SCAN_STATE_IDLE
,
...
...
drivers/net/wireless/wl12xx/wl1271_sdio.c
浏览文件 @
46bf6958
...
...
@@ -274,9 +274,8 @@ static void __devexit wl1271_remove(struct sdio_func *func)
{
struct
wl1271
*
wl
=
sdio_get_drvdata
(
func
);
free_irq
(
wl
->
irq
,
wl
);
wl1271_unregister_hw
(
wl
);
free_irq
(
wl
->
irq
,
wl
);
wl1271_free_hw
(
wl
);
}
...
...
drivers/net/wireless/wl12xx/wl1271_spi.c
浏览文件 @
46bf6958
...
...
@@ -63,6 +63,11 @@
((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32))
#define HW_ACCESS_WSPI_INIT_CMD_MASK 0
/* HW limitation: maximum possible chunk size is 4095 bytes */
#define WSPI_MAX_CHUNK_SIZE 4092
#define WSPI_MAX_NUM_OF_CHUNKS (WL1271_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE)
static
inline
struct
spi_device
*
wl_to_spi
(
struct
wl1271
*
wl
)
{
return
wl
->
if_priv
;
...
...
@@ -202,90 +207,117 @@ static int wl1271_spi_read_busy(struct wl1271 *wl)
static
void
wl1271_spi_raw_read
(
struct
wl1271
*
wl
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
struct
spi_transfer
t
[
3
];
struct
spi_transfer
t
[
2
];
struct
spi_message
m
;
u32
*
busy_buf
;
u32
*
cmd
;
u32
chunk_len
;
cmd
=
&
wl
->
buffer_cmd
;
busy_buf
=
wl
->
buffer_busyword
;
while
(
len
>
0
)
{
chunk_len
=
min
((
size_t
)
WSPI_MAX_CHUNK_SIZE
,
len
)
;
*
cmd
=
0
;
*
cmd
|=
WSPI_CMD_READ
;
*
cmd
|=
(
len
<<
WSPI_CMD_BYTE_LENGTH_OFFSET
)
&
WSPI_CMD_BYTE_LENGTH
;
*
cmd
|=
addr
&
WSPI_CMD_BYTE_ADDR
;
cmd
=
&
wl
->
buffer_cmd
;
busy_buf
=
wl
->
buffer_busyword
;
if
(
fixed
)
*
cmd
|=
WSPI_CMD_FIXED
;
*
cmd
=
0
;
*
cmd
|=
WSPI_CMD_READ
;
*
cmd
|=
(
chunk_len
<<
WSPI_CMD_BYTE_LENGTH_OFFSET
)
&
WSPI_CMD_BYTE_LENGTH
;
*
cmd
|=
addr
&
WSPI_CMD_BYTE_ADDR
;
spi_message_init
(
&
m
);
memset
(
t
,
0
,
sizeof
(
t
))
;
if
(
fixed
)
*
cmd
|=
WSPI_CMD_FIXED
;
t
[
0
].
tx_buf
=
cmd
;
t
[
0
].
len
=
4
;
t
[
0
].
cs_change
=
true
;
spi_message_add_tail
(
&
t
[
0
],
&
m
);
spi_message_init
(
&
m
);
memset
(
t
,
0
,
sizeof
(
t
));
/* Busy and non busy words read */
t
[
1
].
rx_buf
=
busy_buf
;
t
[
1
].
len
=
WL1271_BUSY_WORD_LEN
;
t
[
1
].
cs_change
=
true
;
spi_message_add_tail
(
&
t
[
1
],
&
m
);
t
[
0
].
tx_buf
=
cmd
;
t
[
0
].
len
=
4
;
t
[
0
].
cs_change
=
true
;
spi_message_add_tail
(
&
t
[
0
],
&
m
);
spi_sync
(
wl_to_spi
(
wl
),
&
m
);
/* Busy and non busy words read */
t
[
1
].
rx_buf
=
busy_buf
;
t
[
1
].
len
=
WL1271_BUSY_WORD_LEN
;
t
[
1
].
cs_change
=
true
;
spi_message_add_tail
(
&
t
[
1
],
&
m
);
if
(
!
(
busy_buf
[
WL1271_BUSY_WORD_CNT
-
1
]
&
0x1
)
&&
wl1271_spi_read_busy
(
wl
))
{
memset
(
buf
,
0
,
len
);
return
;
}
spi_sync
(
wl_to_spi
(
wl
),
&
m
);
spi_message_init
(
&
m
);
memset
(
t
,
0
,
sizeof
(
t
));
if
(
!
(
busy_buf
[
WL1271_BUSY_WORD_CNT
-
1
]
&
0x1
)
&&
wl1271_spi_read_busy
(
wl
))
{
memset
(
buf
,
0
,
chunk_len
);
return
;
}
t
[
0
].
rx_buf
=
buf
;
t
[
0
].
len
=
len
;
t
[
0
].
cs_change
=
true
;
spi_message_add_tail
(
&
t
[
0
],
&
m
);
spi_message_init
(
&
m
);
memset
(
t
,
0
,
sizeof
(
t
));
spi_sync
(
wl_to_spi
(
wl
),
&
m
);
t
[
0
].
rx_buf
=
buf
;
t
[
0
].
len
=
chunk_len
;
t
[
0
].
cs_change
=
true
;
spi_message_add_tail
(
&
t
[
0
],
&
m
);
spi_sync
(
wl_to_spi
(
wl
),
&
m
);
wl1271_dump
(
DEBUG_SPI
,
"spi_read cmd -> "
,
cmd
,
sizeof
(
*
cmd
));
wl1271_dump
(
DEBUG_SPI
,
"spi_read buf <- "
,
buf
,
chunk_len
);
wl1271_dump
(
DEBUG_SPI
,
"spi_read cmd -> "
,
cmd
,
sizeof
(
*
cmd
));
wl1271_dump
(
DEBUG_SPI
,
"spi_read buf <- "
,
buf
,
len
);
if
(
!
fixed
)
addr
+=
chunk_len
;
buf
+=
chunk_len
;
len
-=
chunk_len
;
}
}
static
void
wl1271_spi_raw_write
(
struct
wl1271
*
wl
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
struct
spi_transfer
t
[
2
];
struct
spi_transfer
t
[
2
*
WSPI_MAX_NUM_OF_CHUNKS
];
struct
spi_message
m
;
u32
commands
[
WSPI_MAX_NUM_OF_CHUNKS
];
u32
*
cmd
;
u32
chunk_len
;
int
i
;
cmd
=
&
wl
->
buffer_cmd
;
*
cmd
=
0
;
*
cmd
|=
WSPI_CMD_WRITE
;
*
cmd
|=
(
len
<<
WSPI_CMD_BYTE_LENGTH_OFFSET
)
&
WSPI_CMD_BYTE_LENGTH
;
*
cmd
|=
addr
&
WSPI_CMD_BYTE_ADDR
;
if
(
fixed
)
*
cmd
|=
WSPI_CMD_FIXED
;
WARN_ON
(
len
>
WL1271_AGGR_BUFFER_SIZE
);
spi_message_init
(
&
m
);
memset
(
t
,
0
,
sizeof
(
t
));
t
[
0
].
tx_buf
=
cmd
;
t
[
0
].
len
=
sizeof
(
*
cmd
);
spi_message_add_tail
(
&
t
[
0
],
&
m
);
cmd
=
&
commands
[
0
];
i
=
0
;
while
(
len
>
0
)
{
chunk_len
=
min
((
size_t
)
WSPI_MAX_CHUNK_SIZE
,
len
);
t
[
1
].
tx_buf
=
buf
;
t
[
1
].
len
=
len
;
spi_message_add_tail
(
&
t
[
1
],
&
m
);
*
cmd
=
0
;
*
cmd
|=
WSPI_CMD_WRITE
;
*
cmd
|=
(
chunk_len
<<
WSPI_CMD_BYTE_LENGTH_OFFSET
)
&
WSPI_CMD_BYTE_LENGTH
;
*
cmd
|=
addr
&
WSPI_CMD_BYTE_ADDR
;
spi_sync
(
wl_to_spi
(
wl
),
&
m
);
if
(
fixed
)
*
cmd
|=
WSPI_CMD_FIXED
;
wl1271_dump
(
DEBUG_SPI
,
"spi_write cmd -> "
,
cmd
,
sizeof
(
*
cmd
));
wl1271_dump
(
DEBUG_SPI
,
"spi_write buf -> "
,
buf
,
len
);
t
[
i
].
tx_buf
=
cmd
;
t
[
i
].
len
=
sizeof
(
*
cmd
);
spi_message_add_tail
(
&
t
[
i
++
],
&
m
);
t
[
i
].
tx_buf
=
buf
;
t
[
i
].
len
=
chunk_len
;
spi_message_add_tail
(
&
t
[
i
++
],
&
m
);
wl1271_dump
(
DEBUG_SPI
,
"spi_write cmd -> "
,
cmd
,
sizeof
(
*
cmd
));
wl1271_dump
(
DEBUG_SPI
,
"spi_write buf -> "
,
buf
,
chunk_len
);
if
(
!
fixed
)
addr
+=
chunk_len
;
buf
+=
chunk_len
;
len
-=
chunk_len
;
cmd
++
;
}
spi_sync
(
wl_to_spi
(
wl
),
&
m
);
}
static
irqreturn_t
wl1271_irq
(
int
irq
,
void
*
cookie
)
...
...
@@ -416,9 +448,8 @@ static int __devexit wl1271_remove(struct spi_device *spi)
{
struct
wl1271
*
wl
=
dev_get_drvdata
(
&
spi
->
dev
);
free_irq
(
wl
->
irq
,
wl
);
wl1271_unregister_hw
(
wl
);
free_irq
(
wl
->
irq
,
wl
);
wl1271_free_hw
(
wl
);
return
0
;
...
...
drivers/net/wireless/wl12xx/wl1271_testmode.c
浏览文件 @
46bf6958
...
...
@@ -199,19 +199,6 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[])
buf
=
nla_data
(
tb
[
WL1271_TM_ATTR_DATA
]);
len
=
nla_len
(
tb
[
WL1271_TM_ATTR_DATA
]);
/*
* FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band
* configurations) can be removed when those NVS files stop floating
* around.
*/
if
(
len
!=
sizeof
(
struct
wl1271_nvs_file
)
&&
(
len
!=
WL1271_INI_LEGACY_NVS_FILE_SIZE
||
wl1271_11a_enabled
()))
{
wl1271_error
(
"nvs size is not as expected: %zu != %zu"
,
len
,
sizeof
(
struct
wl1271_nvs_file
));
return
-
EMSGSIZE
;
}
mutex_lock
(
&
wl
->
mutex
);
kfree
(
wl
->
nvs
);
...
...
@@ -224,6 +211,7 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[])
}
memcpy
(
wl
->
nvs
,
buf
,
len
);
wl
->
nvs_len
=
len
;
wl1271_debug
(
DEBUG_TESTMODE
,
"testmode pushed nvs"
);
...
...
drivers/net/wireless/wl12xx/wl1271_tx.c
浏览文件 @
46bf6958
...
...
@@ -43,13 +43,17 @@ static int wl1271_tx_id(struct wl1271 *wl, struct sk_buff *skb)
return
-
EBUSY
;
}
static
int
wl1271_tx_allocate
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
,
u32
extra
)
static
int
wl1271_tx_allocate
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
,
u32
extra
,
u32
buf_offset
)
{
struct
wl1271_tx_hw_descr
*
desc
;
u32
total_len
=
skb
->
len
+
sizeof
(
struct
wl1271_tx_hw_descr
)
+
extra
;
u32
total_blocks
;
int
id
,
ret
=
-
EBUSY
;
if
(
buf_offset
+
total_len
>
WL1271_AGGR_BUFFER_SIZE
)
return
-
EBUSY
;
/* allocate free identifier for the packet */
id
=
wl1271_tx_id
(
wl
,
skb
);
if
(
id
<
0
)
...
...
@@ -82,7 +86,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra)
return
ret
;
}
static
int
wl1271_tx_fill_hdr
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
,
static
void
wl1271_tx_fill_hdr
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
,
u32
extra
,
struct
ieee80211_tx_info
*
control
)
{
struct
timespec
ts
;
...
...
@@ -110,9 +114,9 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
/* configure the tx attributes */
tx_attr
=
wl
->
session_counter
<<
TX_HW_ATTR_OFST_SESSION_COUNTER
;
/* queue */
/* queue
(we use same identifiers for tid's and ac's
*/
ac
=
wl1271_tx_get_queue
(
skb_get_queue_mapping
(
skb
));
desc
->
tid
=
wl1271_tx_ac_to_tid
(
ac
)
;
desc
->
tid
=
ac
;
desc
->
aid
=
TX_HW_DEFAULT_AID
;
desc
->
reserved
=
0
;
...
...
@@ -133,59 +137,17 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
desc
->
tx_attr
=
cpu_to_le16
(
tx_attr
);
wl1271_debug
(
DEBUG_TX
,
"tx_fill_hdr: pad: %d"
,
pad
);
return
0
;
}
static
int
wl1271_tx_send_packet
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
,
struct
ieee80211_tx_info
*
control
)
{
struct
wl1271_tx_hw_descr
*
desc
;
int
len
;
/* FIXME: This is a workaround for getting non-aligned packets.
This happens at least with EAPOL packets from the user space.
Our DMA requires packets to be aligned on a 4-byte boundary.
*/
if
(
unlikely
((
long
)
skb
->
data
&
0x03
))
{
int
offset
=
(
4
-
(
long
)
skb
->
data
)
&
0x03
;
wl1271_debug
(
DEBUG_TX
,
"skb offset %d"
,
offset
);
/* check whether the current skb can be used */
if
(
!
skb_cloned
(
skb
)
&&
(
skb_tailroom
(
skb
)
>=
offset
))
{
unsigned
char
*
src
=
skb
->
data
;
/* align the buffer on a 4-byte boundary */
skb_reserve
(
skb
,
offset
);
memmove
(
skb
->
data
,
src
,
skb
->
len
);
}
else
{
wl1271_info
(
"No handler, fixme!"
);
return
-
EINVAL
;
}
}
len
=
WL1271_TX_ALIGN
(
skb
->
len
);
/* perform a fixed address block write with the packet */
wl1271_write
(
wl
,
WL1271_SLV_MEM_DATA
,
skb
->
data
,
len
,
true
);
/* write packet new counter into the write access register */
wl
->
tx_packets_count
++
;
desc
=
(
struct
wl1271_tx_hw_descr
*
)
skb
->
data
;
wl1271_debug
(
DEBUG_TX
,
"tx id %u skb 0x%p payload %u (%u words)"
,
desc
->
id
,
skb
,
len
,
desc
->
length
);
return
0
;
}
/* caller must hold wl->mutex */
static
int
wl1271_tx_frame
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
)
static
int
wl1271_prepare_tx_frame
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
,
u32
buf_offset
)
{
struct
ieee80211_tx_info
*
info
;
u32
extra
=
0
;
int
ret
=
0
;
u8
idx
;
u32
total_len
;
if
(
!
skb
)
return
-
EINVAL
;
...
...
@@ -208,19 +170,22 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb)
}
}
ret
=
wl1271_tx_allocate
(
wl
,
skb
,
extra
);
ret
=
wl1271_tx_allocate
(
wl
,
skb
,
extra
,
buf_offset
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_tx_fill_hdr
(
wl
,
skb
,
extra
,
info
);
if
(
ret
<
0
)
return
ret
;
wl1271_tx_fill_hdr
(
wl
,
skb
,
extra
,
info
);
ret
=
wl1271_tx_send_packet
(
wl
,
skb
,
info
);
if
(
ret
<
0
)
return
ret
;
/*
* The length of each packet is stored in terms of words. Thus, we must
* pad the skb data to make sure its length is aligned.
* The number of padding bytes is computed and set in wl1271_tx_fill_hdr
*/
total_len
=
WL1271_TX_ALIGN
(
skb
->
len
);
memcpy
(
wl
->
aggr_buf
+
buf_offset
,
skb
->
data
,
skb
->
len
);
memset
(
wl
->
aggr_buf
+
buf_offset
+
skb
->
len
,
0
,
total_len
-
skb
->
len
);
return
ret
;
return
total_len
;
}
u32
wl1271_tx_enabled_rates_get
(
struct
wl1271
*
wl
,
u32
rate_set
)
...
...
@@ -245,7 +210,7 @@ void wl1271_tx_work(struct work_struct *work)
struct
sk_buff
*
skb
;
bool
woken_up
=
false
;
u32
sta_rates
=
0
;
u32
prev_tx_packets_coun
t
;
u32
buf_offse
t
;
int
ret
;
/* check if the rates supported by the AP have changed */
...
...
@@ -262,14 +227,15 @@ void wl1271_tx_work(struct work_struct *work)
if
(
unlikely
(
wl
->
state
==
WL1271_STATE_OFF
))
goto
out
;
prev_tx_packets_count
=
wl
->
tx_packets_count
;
/* if rates have changed, re-configure the rate policy */
if
(
unlikely
(
sta_rates
))
{
wl
->
rate_set
=
wl1271_tx_enabled_rates_get
(
wl
,
sta_rates
);
wl1271_acx_rate_policies
(
wl
);
}
/* Prepare the transfer buffer, by aggregating all
* available packets */
buf_offset
=
0
;
while
((
skb
=
skb_dequeue
(
&
wl
->
tx_queue
)))
{
if
(
!
woken_up
)
{
ret
=
wl1271_ps_elp_wakeup
(
wl
,
false
);
...
...
@@ -278,21 +244,30 @@ void wl1271_tx_work(struct work_struct *work)
woken_up
=
true
;
}
ret
=
wl1271_
tx_frame
(
wl
,
skb
);
ret
=
wl1271_
prepare_tx_frame
(
wl
,
skb
,
buf_offset
);
if
(
ret
==
-
EBUSY
)
{
/* firmware buffer is full, lets stop transmitting. */
/*
* Either the firmware buffer is full, or the
* aggregation buffer is.
* Queue back last skb, and stop aggregating.
*/
skb_queue_head
(
&
wl
->
tx_queue
,
skb
);
goto
out_ack
;
}
else
if
(
ret
<
0
)
{
dev_kfree_skb
(
skb
);
goto
out_ack
;
}
buf_offset
+=
ret
;
wl
->
tx_packets_count
++
;
}
out_ack:
/* interrupt the firmware with the new packets */
if
(
prev_tx_packets_count
!=
wl
->
tx_packets_count
)
if
(
buf_offset
)
{
wl1271_write
(
wl
,
WL1271_SLV_MEM_DATA
,
wl
->
aggr_buf
,
buf_offset
,
true
);
/* interrupt the firmware with the new packets */
wl1271_write32
(
wl
,
WL1271_HOST_WR_ACCESS
,
wl
->
tx_packets_count
);
}
out:
if
(
woken_up
)
...
...
@@ -422,8 +397,6 @@ void wl1271_tx_reset(struct wl1271 *wl)
struct
sk_buff
*
skb
;
/* TX failure */
/* control->flags = 0; FIXME */
while
((
skb
=
skb_dequeue
(
&
wl
->
tx_queue
)))
{
wl1271_debug
(
DEBUG_TX
,
"freeing skb 0x%p"
,
skb
);
ieee80211_tx_status
(
wl
->
hw
,
skb
);
...
...
drivers/net/wireless/wl12xx/wl1271_tx.h
浏览文件 @
46bf6958
...
...
@@ -139,23 +139,6 @@ static inline int wl1271_tx_get_queue(int queue)
}
}
/* wl1271 tx descriptor needs the tid and we need to convert it from ac */
static
inline
int
wl1271_tx_ac_to_tid
(
int
ac
)
{
switch
(
ac
)
{
case
0
:
return
0
;
case
1
:
return
2
;
case
2
:
return
4
;
case
3
:
return
6
;
default:
return
0
;
}
}
void
wl1271_tx_work
(
struct
work_struct
*
work
);
void
wl1271_tx_complete
(
struct
wl1271
*
wl
);
void
wl1271_tx_reset
(
struct
wl1271
*
wl
);
...
...
include/linux/wl12xx.h
浏览文件 @
46bf6958
...
...
@@ -32,7 +32,20 @@ struct wl12xx_platform_data {
int
board_ref_clock
;
};
#ifdef CONFIG_WL12XX_PLATFORM_DATA
int
wl12xx_set_platform_data
(
const
struct
wl12xx_platform_data
*
data
);
#else
static
inline
int
wl12xx_set_platform_data
(
const
struct
wl12xx_platform_data
*
data
)
{
return
-
ENOSYS
;
}
#endif
const
struct
wl12xx_platform_data
*
wl12xx_get_platform_data
(
void
);
#endif
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录