Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
e55034e9
Commit
e55034e9
authored
Apr 25, 2011
by
John W. Linville
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-linville' of
git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx
parents
73b48099
cf27d867
Changes
29
Hide whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
1324 additions
and
289 deletions
+1324
-289
drivers/net/wireless/wl12xx/Kconfig
drivers/net/wireless/wl12xx/Kconfig
+1
-1
drivers/net/wireless/wl12xx/acx.c
drivers/net/wireless/wl12xx/acx.c
+47
-12
drivers/net/wireless/wl12xx/acx.h
drivers/net/wireless/wl12xx/acx.h
+11
-0
drivers/net/wireless/wl12xx/boot.c
drivers/net/wireless/wl12xx/boot.c
+236
-43
drivers/net/wireless/wl12xx/boot.h
drivers/net/wireless/wl12xx/boot.h
+52
-0
drivers/net/wireless/wl12xx/cmd.c
drivers/net/wireless/wl12xx/cmd.c
+91
-6
drivers/net/wireless/wl12xx/cmd.h
drivers/net/wireless/wl12xx/cmd.h
+34
-0
drivers/net/wireless/wl12xx/conf.h
drivers/net/wireless/wl12xx/conf.h
+6
-11
drivers/net/wireless/wl12xx/debugfs.c
drivers/net/wireless/wl12xx/debugfs.c
+1
-1
drivers/net/wireless/wl12xx/event.c
drivers/net/wireless/wl12xx/event.c
+12
-5
drivers/net/wireless/wl12xx/event.h
drivers/net/wireless/wl12xx/event.h
+4
-1
drivers/net/wireless/wl12xx/ini.h
drivers/net/wireless/wl12xx/ini.h
+96
-2
drivers/net/wireless/wl12xx/init.c
drivers/net/wireless/wl12xx/init.c
+40
-5
drivers/net/wireless/wl12xx/init.h
drivers/net/wireless/wl12xx/init.h
+1
-0
drivers/net/wireless/wl12xx/io.c
drivers/net/wireless/wl12xx/io.c
+11
-0
drivers/net/wireless/wl12xx/io.h
drivers/net/wireless/wl12xx/io.h
+3
-0
drivers/net/wireless/wl12xx/main.c
drivers/net/wireless/wl12xx/main.c
+276
-67
drivers/net/wireless/wl12xx/ps.c
drivers/net/wireless/wl12xx/ps.c
+0
-3
drivers/net/wireless/wl12xx/reg.h
drivers/net/wireless/wl12xx/reg.h
+2
-13
drivers/net/wireless/wl12xx/rx.c
drivers/net/wireless/wl12xx/rx.c
+24
-20
drivers/net/wireless/wl12xx/scan.c
drivers/net/wireless/wl12xx/scan.c
+10
-7
drivers/net/wireless/wl12xx/sdio.c
drivers/net/wireless/wl12xx/sdio.c
+24
-3
drivers/net/wireless/wl12xx/sdio_test.c
drivers/net/wireless/wl12xx/sdio_test.c
+17
-3
drivers/net/wireless/wl12xx/spi.c
drivers/net/wireless/wl12xx/spi.c
+14
-3
drivers/net/wireless/wl12xx/testmode.c
drivers/net/wireless/wl12xx/testmode.c
+5
-1
drivers/net/wireless/wl12xx/tx.c
drivers/net/wireless/wl12xx/tx.c
+176
-58
drivers/net/wireless/wl12xx/tx.h
drivers/net/wireless/wl12xx/tx.h
+50
-10
drivers/net/wireless/wl12xx/wl12xx.h
drivers/net/wireless/wl12xx/wl12xx.h
+56
-9
include/linux/wl12xx.h
include/linux/wl12xx.h
+24
-5
No files found.
drivers/net/wireless/wl12xx/Kconfig
View file @
e55034e9
...
...
@@ -3,7 +3,7 @@ menuconfig WL12XX_MENU
depends on MAC80211 && EXPERIMENTAL
---help---
This will enable TI wl12xx driver support for the following chips:
wl1271
and wl127
3.
wl1271
, wl1273, wl1281 and wl128
3.
The drivers make use of the mac80211 stack.
config WL12XX
...
...
drivers/net/wireless/wl12xx/acx.c
View file @
e55034e9
...
...
@@ -965,10 +965,13 @@ int wl1271_acx_ap_mem_cfg(struct wl1271 *wl)
}
/* memory config */
mem_conf
->
num_stations
=
wl
->
conf
.
mem
.
num_stations
;
mem_conf
->
rx_mem_block_num
=
wl
->
conf
.
mem
.
rx_block_num
;
mem_conf
->
tx_min_mem_block_num
=
wl
->
conf
.
mem
.
tx_min_block_num
;
mem_conf
->
num_ssid_profiles
=
wl
->
conf
.
mem
.
ssid_profiles
;
/* FIXME: for now we always use mem_wl127x for AP, because it
* doesn't support dynamic memory and we don't have the
* optimal values for wl128x without dynamic memory yet */
mem_conf
->
num_stations
=
wl
->
conf
.
mem_wl127x
.
num_stations
;
mem_conf
->
rx_mem_block_num
=
wl
->
conf
.
mem_wl127x
.
rx_block_num
;
mem_conf
->
tx_min_mem_block_num
=
wl
->
conf
.
mem_wl127x
.
tx_min_block_num
;
mem_conf
->
num_ssid_profiles
=
wl
->
conf
.
mem_wl127x
.
ssid_profiles
;
mem_conf
->
total_tx_descriptors
=
cpu_to_le32
(
ACX_TX_DESCRIPTORS
);
ret
=
wl1271_cmd_configure
(
wl
,
ACX_MEM_CFG
,
mem_conf
,
...
...
@@ -986,6 +989,7 @@ int wl1271_acx_ap_mem_cfg(struct wl1271 *wl)
int
wl1271_acx_sta_mem_cfg
(
struct
wl1271
*
wl
)
{
struct
wl1271_acx_sta_config_memory
*
mem_conf
;
struct
conf_memory_settings
*
mem
;
int
ret
;
wl1271_debug
(
DEBUG_ACX
,
"wl1271 mem cfg"
);
...
...
@@ -996,16 +1000,21 @@ int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
goto
out
;
}
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
mem
=
&
wl
->
conf
.
mem_wl128x
;
else
mem
=
&
wl
->
conf
.
mem_wl127x
;
/* memory config */
mem_conf
->
num_stations
=
wl
->
conf
.
mem
.
num_stations
;
mem_conf
->
rx_mem_block_num
=
wl
->
conf
.
mem
.
rx_block_num
;
mem_conf
->
tx_min_mem_block_num
=
wl
->
conf
.
mem
.
tx_min_block_num
;
mem_conf
->
num_ssid_profiles
=
wl
->
conf
.
mem
.
ssid_profiles
;
mem_conf
->
num_stations
=
mem
->
num_stations
;
mem_conf
->
rx_mem_block_num
=
mem
->
rx_block_num
;
mem_conf
->
tx_min_mem_block_num
=
mem
->
tx_min_block_num
;
mem_conf
->
num_ssid_profiles
=
mem
->
ssid_profiles
;
mem_conf
->
total_tx_descriptors
=
cpu_to_le32
(
ACX_TX_DESCRIPTORS
);
mem_conf
->
dyn_mem_enable
=
wl
->
conf
.
mem
.
dynamic_memory
;
mem_conf
->
tx_free_req
=
wl
->
conf
.
mem
.
min_req_tx_blocks
;
mem_conf
->
rx_free_req
=
wl
->
conf
.
mem
.
min_req_rx_blocks
;
mem_conf
->
tx_min
=
wl
->
conf
.
mem
.
tx_min
;
mem_conf
->
dyn_mem_enable
=
mem
->
dynamic_memory
;
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
;
ret
=
wl1271_cmd_configure
(
wl
,
ACX_MEM_CFG
,
mem_conf
,
sizeof
(
*
mem_conf
));
...
...
@@ -1019,6 +1028,32 @@ int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
return
ret
;
}
int
wl1271_acx_host_if_cfg_bitmap
(
struct
wl1271
*
wl
,
u32
host_cfg_bitmap
)
{
struct
wl1271_acx_host_config_bitmap
*
bitmap_conf
;
int
ret
;
bitmap_conf
=
kzalloc
(
sizeof
(
*
bitmap_conf
),
GFP_KERNEL
);
if
(
!
bitmap_conf
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
bitmap_conf
->
host_cfg_bitmap
=
cpu_to_le32
(
host_cfg_bitmap
);
ret
=
wl1271_cmd_configure
(
wl
,
ACX_HOST_IF_CFG_BITMAP
,
bitmap_conf
,
sizeof
(
*
bitmap_conf
));
if
(
ret
<
0
)
{
wl1271_warning
(
"wl1271 bitmap config opt failed: %d"
,
ret
);
goto
out
;
}
out:
kfree
(
bitmap_conf
);
return
ret
;
}
int
wl1271_acx_init_mem_config
(
struct
wl1271
*
wl
)
{
int
ret
;
...
...
drivers/net/wireless/wl12xx/acx.h
View file @
e55034e9
...
...
@@ -939,6 +939,16 @@ struct wl1271_acx_keep_alive_config {
u8
padding
;
}
__packed
;
#define HOST_IF_CFG_RX_FIFO_ENABLE BIT(0)
#define HOST_IF_CFG_TX_EXTRA_BLKS_SWAP BIT(1)
#define HOST_IF_CFG_TX_PAD_TO_SDIO_BLK BIT(3)
struct
wl1271_acx_host_config_bitmap
{
struct
acx_header
header
;
__le32
host_cfg_bitmap
;
}
__packed
;
enum
{
WL1271_ACX_TRIG_TYPE_LEVEL
=
0
,
WL1271_ACX_TRIG_TYPE_EDGE
,
...
...
@@ -1275,6 +1285,7 @@ int wl1271_acx_tx_config_options(struct wl1271 *wl);
int
wl1271_acx_ap_mem_cfg
(
struct
wl1271
*
wl
);
int
wl1271_acx_sta_mem_cfg
(
struct
wl1271
*
wl
);
int
wl1271_acx_init_mem_config
(
struct
wl1271
*
wl
);
int
wl1271_acx_host_if_cfg_bitmap
(
struct
wl1271
*
wl
,
u32
host_cfg_bitmap
);
int
wl1271_acx_init_rx_interrupt
(
struct
wl1271
*
wl
);
int
wl1271_acx_smart_reflex
(
struct
wl1271
*
wl
);
int
wl1271_acx_bet_enable
(
struct
wl1271
*
wl
,
bool
enable
);
...
...
drivers/net/wireless/wl12xx/boot.c
View file @
e55034e9
...
...
@@ -22,6 +22,7 @@
*/
#include <linux/slab.h>
#include <linux/wl12xx.h>
#include "acx.h"
#include "reg.h"
...
...
@@ -243,33 +244,57 @@ 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
)
{
/* for now 11a is unsupported in AP mode */
if
(
wl
->
bss_type
!=
BSS_TYPE_AP_BSS
&&
wl
->
nvs
->
general_params
.
dual_mode_select
)
wl
->
enable_11a
=
true
;
}
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
{
struct
wl128x_nvs_file
*
nvs
=
(
struct
wl128x_nvs_file
*
)
wl
->
nvs
;
if
(
wl
->
nvs_len
==
sizeof
(
struct
wl128x_nvs_file
))
{
if
(
nvs
->
general_params
.
dual_mode_select
)
wl
->
enable_11a
=
true
;
}
else
{
wl1271_error
(
"nvs size is not as expected: %zu != %zu"
,
wl
->
nvs_len
,
sizeof
(
struct
wl128x_nvs_file
));
kfree
(
wl
->
nvs
);
wl
->
nvs
=
NULL
;
wl
->
nvs_len
=
0
;
return
-
EILSEQ
;
}
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
(
nvs
->
nvs
);
nvs_ptr
=
(
u8
*
)
nvs
->
nvs
;
}
else
{
struct
wl1271_nvs_file
*
nvs
=
(
struct
wl1271_nvs_file
*
)
wl
->
nvs
;
/*
* 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
)
{
/* for now 11a is unsupported in AP mode */
if
(
wl
->
bss_type
!=
BSS_TYPE_AP_BSS
&&
nvs
->
general_params
.
dual_mode_select
)
wl
->
enable_11a
=
true
;
}
/* only the first part of the NVS needs to be uploaded */
nvs_len
=
sizeof
(
wl
->
nvs
->
nvs
);
nvs_ptr
=
(
u8
*
)
wl
->
nvs
->
nvs
;
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
(
nvs
->
nvs
);
nvs_ptr
=
(
u8
*
)
nvs
->
nvs
;
}
/* update current MAC address to NVS */
nvs_ptr
[
11
]
=
wl
->
mac_addr
[
0
];
...
...
@@ -319,10 +344,13 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
/*
* We've reached the first zero length, the first NVS table
* is located at an aligned offset which is at least 7 bytes further.
* NOTE: The wl->nvs->nvs element must be first, in order to
* simplify the casting, we assume it is at the beginning of
* the wl->nvs structure.
*/
nvs_ptr
=
(
u8
*
)
wl
->
nvs
->
nvs
+
ALIGN
(
nvs_ptr
-
(
u8
*
)
wl
->
nvs
->
nvs
+
7
,
4
);
nvs_len
-=
nvs_ptr
-
(
u8
*
)
wl
->
nvs
->
nvs
;
nvs_ptr
=
(
u8
*
)
wl
->
nvs
+
ALIGN
(
nvs_ptr
-
(
u8
*
)
wl
->
nvs
+
7
,
4
);
nvs_len
-=
nvs_ptr
-
(
u8
*
)
wl
->
nvs
;
/* Now we must set the partition correctly */
wl1271_set_partition
(
wl
,
&
part_table
[
PART_WORK
]);
...
...
@@ -454,6 +482,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
wl
->
event_mask
|=
STA_REMOVE_COMPLETE_EVENT_ID
;
else
wl
->
event_mask
|=
DUMMY_PACKET_EVENT_ID
;
ret
=
wl1271_event_unmask
(
wl
);
if
(
ret
<
0
)
{
...
...
@@ -493,24 +523,159 @@ static void wl1271_boot_hw_version(struct wl1271 *wl)
wl
->
quirks
|=
WL12XX_QUIRK_END_OF_TRANSACTION
;
}
/* uploads NVS and firmware */
int
wl1271_load_firmware
(
struct
wl1271
*
wl
)
static
int
wl128x_switch_tcxo_to_fref
(
struct
wl1271
*
wl
)
{
int
ret
=
0
;
u32
tmp
,
clk
,
pause
;
u16
spare_reg
;
/* Mask bits [2] & [8:4] in the sys_clk_cfg register */
spare_reg
=
wl1271_top_reg_read
(
wl
,
WL_SPARE_REG
);
if
(
spare_reg
==
0xFFFF
)
return
-
EFAULT
;
spare_reg
|=
(
BIT
(
3
)
|
BIT
(
5
)
|
BIT
(
6
));
wl1271_top_reg_write
(
wl
,
WL_SPARE_REG
,
spare_reg
);
/* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */
wl1271_top_reg_write
(
wl
,
SYS_CLK_CFG_REG
,
WL_CLK_REQ_TYPE_PG2
|
MCS_PLL_CLK_SEL_FREF
);
/* Delay execution for 15msec, to let the HW settle */
mdelay
(
15
);
return
0
;
}
static
bool
wl128x_is_tcxo_valid
(
struct
wl1271
*
wl
)
{
u16
tcxo_detection
;
tcxo_detection
=
wl1271_top_reg_read
(
wl
,
TCXO_CLK_DETECT_REG
);
if
(
tcxo_detection
&
TCXO_DET_FAILED
)
return
false
;
return
true
;
}
static
bool
wl128x_is_fref_valid
(
struct
wl1271
*
wl
)
{
u16
fref_detection
;
fref_detection
=
wl1271_top_reg_read
(
wl
,
FREF_CLK_DETECT_REG
);
if
(
fref_detection
&
FREF_CLK_DETECT_FAIL
)
return
false
;
return
true
;
}
static
int
wl128x_manually_configure_mcs_pll
(
struct
wl1271
*
wl
)
{
wl1271_top_reg_write
(
wl
,
MCS_PLL_M_REG
,
MCS_PLL_M_REG_VAL
);
wl1271_top_reg_write
(
wl
,
MCS_PLL_N_REG
,
MCS_PLL_N_REG_VAL
);
wl1271_top_reg_write
(
wl
,
MCS_PLL_CONFIG_REG
,
MCS_PLL_CONFIG_REG_VAL
);
return
0
;
}
static
int
wl128x_configure_mcs_pll
(
struct
wl1271
*
wl
,
int
clk
)
{
u16
spare_reg
;
u16
pll_config
;
u8
input_freq
;
/* Mask bits [3:1] in the sys_clk_cfg register */
spare_reg
=
wl1271_top_reg_read
(
wl
,
WL_SPARE_REG
);
if
(
spare_reg
==
0xFFFF
)
return
-
EFAULT
;
spare_reg
|=
BIT
(
2
);
wl1271_top_reg_write
(
wl
,
WL_SPARE_REG
,
spare_reg
);
/* Handle special cases of the TCXO clock */
if
(
wl
->
tcxo_clock
==
WL12XX_TCXOCLOCK_16_8
||
wl
->
tcxo_clock
==
WL12XX_TCXOCLOCK_33_6
)
return
wl128x_manually_configure_mcs_pll
(
wl
);
/* Set the input frequency according to the selected clock source */
input_freq
=
(
clk
&
1
)
+
1
;
pll_config
=
wl1271_top_reg_read
(
wl
,
MCS_PLL_CONFIG_REG
);
if
(
pll_config
==
0xFFFF
)
return
-
EFAULT
;
pll_config
|=
(
input_freq
<<
MCS_SEL_IN_FREQ_SHIFT
);
pll_config
|=
MCS_PLL_ENABLE_HP
;
wl1271_top_reg_write
(
wl
,
MCS_PLL_CONFIG_REG
,
pll_config
);
return
0
;
}
/*
* WL128x has two clocks input - TCXO and FREF.
* TCXO is the main clock of the device, while FREF is used to sync
* between the GPS and the cellular modem.
* In cases where TCXO is 32.736MHz or 16.368MHz, the FREF will be used
* as the WLAN/BT main clock.
*/
static
int
wl128x_boot_clk
(
struct
wl1271
*
wl
,
int
*
selected_clock
)
{
u16
sys_clk_cfg
;
/* For XTAL-only modes, FREF will be used after switching from TCXO */
if
(
wl
->
ref_clock
==
WL12XX_REFCLOCK_26_XTAL
||
wl
->
ref_clock
==
WL12XX_REFCLOCK_38_XTAL
)
{
if
(
!
wl128x_switch_tcxo_to_fref
(
wl
))
return
-
EINVAL
;
goto
fref_clk
;
}
/* Query the HW, to determine which clock source we should use */
sys_clk_cfg
=
wl1271_top_reg_read
(
wl
,
SYS_CLK_CFG_REG
);
if
(
sys_clk_cfg
==
0xFFFF
)
return
-
EINVAL
;
if
(
sys_clk_cfg
&
PRCM_CM_EN_MUX_WLAN_FREF
)
goto
fref_clk
;
/* If TCXO is either 32.736MHz or 16.368MHz, switch to FREF */
if
(
wl
->
tcxo_clock
==
WL12XX_TCXOCLOCK_16_368
||
wl
->
tcxo_clock
==
WL12XX_TCXOCLOCK_32_736
)
{
if
(
!
wl128x_switch_tcxo_to_fref
(
wl
))
return
-
EINVAL
;
goto
fref_clk
;
}
/* TCXO clock is selected */
if
(
!
wl128x_is_tcxo_valid
(
wl
))
return
-
EINVAL
;
*
selected_clock
=
wl
->
tcxo_clock
;
goto
config_mcs_pll
;
fref_clk:
/* FREF clock is selected */
if
(
!
wl128x_is_fref_valid
(
wl
))
return
-
EINVAL
;
*
selected_clock
=
wl
->
ref_clock
;
config_mcs_pll:
return
wl128x_configure_mcs_pll
(
wl
,
*
selected_clock
);
}
static
int
wl127x_boot_clk
(
struct
wl1271
*
wl
)
{
u32
pause
;
u32
clk
;
wl1271_boot_hw_version
(
wl
);
if
(
wl
->
ref_clock
==
0
||
wl
->
ref_clock
==
2
||
wl
->
ref_clock
==
4
)
if
(
wl
->
ref_clock
==
CONF_REF_CLK_19_2_E
||
wl
->
ref_clock
==
CONF_REF_CLK_38_4_E
||
wl
->
ref_clock
==
CONF_REF_CLK_38_4_M_XTAL
)
/* ref clk: 19.2/38.4/38.4-XTAL */
clk
=
0x3
;
else
if
(
wl
->
ref_clock
==
1
||
wl
->
ref_clock
==
3
)
else
if
(
wl
->
ref_clock
==
CONF_REF_CLK_26_E
||
wl
->
ref_clock
==
CONF_REF_CLK_52_E
)
/* ref clk: 26/52 */
clk
=
0x5
;
else
return
-
EINVAL
;
if
(
wl
->
ref_clock
!=
0
)
{
if
(
wl
->
ref_clock
!=
CONF_REF_CLK_19_2_E
)
{
u16
val
;
/* Set clock type (open drain) */
val
=
wl1271_top_reg_read
(
wl
,
OCP_REG_CLK_TYPE
);
...
...
@@ -540,6 +705,26 @@ int wl1271_load_firmware(struct wl1271 *wl)
pause
|=
WU_COUNTER_PAUSE_VAL
;
wl1271_write32
(
wl
,
WU_COUNTER_PAUSE
,
pause
);
return
0
;
}
/* uploads NVS and firmware */
int
wl1271_load_firmware
(
struct
wl1271
*
wl
)
{
int
ret
=
0
;
u32
tmp
,
clk
;
int
selected_clock
=
-
1
;
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
{
ret
=
wl128x_boot_clk
(
wl
,
&
selected_clock
);
if
(
ret
<
0
)
goto
out
;
}
else
{
ret
=
wl127x_boot_clk
(
wl
);
if
(
ret
<
0
)
goto
out
;
}
/* Continue the ELP wake up sequence */
wl1271_write32
(
wl
,
WELP_ARM_COMMAND
,
WELP_ARM_COMMAND_VAL
);
udelay
(
500
);
...
...
@@ -555,7 +740,12 @@ int wl1271_load_firmware(struct wl1271 *wl)
wl1271_debug
(
DEBUG_BOOT
,
"clk2 0x%x"
,
clk
);
clk
|=
(
wl
->
ref_clock
<<
1
)
<<
4
;
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
{
clk
|=
((
selected_clock
&
0x3
)
<<
1
)
<<
4
;
}
else
{
clk
|=
(
wl
->
ref_clock
<<
1
)
<<
4
;
}
wl1271_write32
(
wl
,
DRPW_SCRATCH_START
,
clk
);
wl1271_set_partition
(
wl
,
&
part_table
[
PART_WORK
]);
...
...
@@ -585,16 +775,12 @@ int wl1271_load_firmware(struct wl1271 *wl)
/* 6. read the EEPROM parameters */
tmp
=
wl1271_read32
(
wl
,
SCR_PAD2
);
ret
=
wl1271_boot_write_irq_polarity
(
wl
);
if
(
ret
<
0
)
goto
out
;
wl1271_write32
(
wl
,
ACX_REG_INTERRUPT_MASK
,
WL1271_ACX_ALL_EVENTS_VECTOR
);
/* WL1271: The reference driver skips steps 7 to 10 (jumps directly
* to upload_fw) */
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
wl1271_top_reg_write
(
wl
,
SDIO_IO_DS
,
wl
->
conf
.
hci_io_ds
);
ret
=
wl1271_boot_upload_firmware
(
wl
);
if
(
ret
<
0
)
goto
out
;
...
...
@@ -618,6 +804,13 @@ int wl1271_boot(struct wl1271 *wl)
if
(
ret
<
0
)
goto
out
;
ret
=
wl1271_boot_write_irq_polarity
(
wl
);
if
(
ret
<
0
)
goto
out
;
wl1271_write32
(
wl
,
ACX_REG_INTERRUPT_MASK
,
WL1271_ACX_ALL_EVENTS_VECTOR
);
/* Enable firmware interrupts now */
wl1271_boot_enable_interrupts
(
wl
);
...
...
drivers/net/wireless/wl12xx/boot.h
View file @
e55034e9
...
...
@@ -74,4 +74,56 @@ struct wl1271_static_data {
#define FREF_CLK_POLARITY_BITS 0xfffff8ff
#define CLK_REQ_OUTN_SEL 0x700
/* PLL configuration algorithm for wl128x */
#define SYS_CLK_CFG_REG 0x2200
/* Bit[0] - 0-TCXO, 1-FREF */
#define MCS_PLL_CLK_SEL_FREF BIT(0)
/* Bit[3:2] - 01-TCXO, 10-FREF */
#define WL_CLK_REQ_TYPE_FREF BIT(3)
#define WL_CLK_REQ_TYPE_PG2 (BIT(3) | BIT(2))
/* Bit[4] - 0-TCXO, 1-FREF */
#define PRCM_CM_EN_MUX_WLAN_FREF BIT(4)
#define TCXO_ILOAD_INT_REG 0x2264
#define TCXO_CLK_DETECT_REG 0x2266
#define TCXO_DET_FAILED BIT(4)
#define FREF_ILOAD_INT_REG 0x2084
#define FREF_CLK_DETECT_REG 0x2086
#define FREF_CLK_DETECT_FAIL BIT(4)
/* Use this reg for masking during driver access */
#define WL_SPARE_REG 0x2320
#define WL_SPARE_VAL BIT(2)
/* Bit[6:5:3] - mask wl write SYS_CLK_CFG[8:5:2:4] */
#define WL_SPARE_MASK_8526 (BIT(6) | BIT(5) | BIT(3))
#define PLL_LOCK_COUNTERS_REG 0xD8C
#define PLL_LOCK_COUNTERS_COEX 0x0F
#define PLL_LOCK_COUNTERS_MCS 0xF0
#define MCS_PLL_OVERRIDE_REG 0xD90
#define MCS_PLL_CONFIG_REG 0xD92
#define MCS_SEL_IN_FREQ_MASK 0x0070
#define MCS_SEL_IN_FREQ_SHIFT 4
#define MCS_PLL_CONFIG_REG_VAL 0x73
#define MCS_PLL_ENABLE_HP (BIT(0) | BIT(1))
#define MCS_PLL_M_REG 0xD94
#define MCS_PLL_N_REG 0xD96
#define MCS_PLL_M_REG_VAL 0xC8
#define MCS_PLL_N_REG_VAL 0x07
#define SDIO_IO_DS 0xd14
/* SDIO/wSPI DS configuration values */
enum
{
HCI_IO_DS_8MA
=
0
,
HCI_IO_DS_4MA
=
1
,
/* default */
HCI_IO_DS_6MA
=
2
,
HCI_IO_DS_2MA
=
3
,
};
/* end PLL configuration algorithm for wl128x */
#endif
drivers/net/wireless/wl12xx/cmd.c
View file @
e55034e9
...
...
@@ -110,7 +110,47 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
int
wl1271_cmd_general_parms
(
struct
wl1271
*
wl
)
{
struct
wl1271_general_parms_cmd
*
gen_parms
;
struct
wl1271_ini_general_params
*
gp
=
&
wl
->
nvs
->
general_params
;
struct
wl1271_ini_general_params
*
gp
=
&
((
struct
wl1271_nvs_file
*
)
wl
->
nvs
)
->
general_params
;
bool
answer
=
false
;
int
ret
;
if
(
!
wl
->
nvs
)
return
-
ENODEV
;
gen_parms
=
kzalloc
(
sizeof
(
*
gen_parms
),
GFP_KERNEL
);
if
(
!
gen_parms
)
return
-
ENOMEM
;
gen_parms
->
test
.
id
=
TEST_CMD_INI_FILE_GENERAL_PARAM
;
memcpy
(
&
gen_parms
->
general_params
,
gp
,
sizeof
(
*
gp
));
if
(
gp
->
tx_bip_fem_auto_detect
)
answer
=
true
;
ret
=
wl1271_cmd_test
(
wl
,
gen_parms
,
sizeof
(
*
gen_parms
),
answer
);
if
(
ret
<
0
)
{
wl1271_warning
(
"CMD_INI_FILE_GENERAL_PARAM failed"
);
goto
out
;
}
gp
->
tx_bip_fem_manufacturer
=
gen_parms
->
general_params
.
tx_bip_fem_manufacturer
;
wl1271_debug
(
DEBUG_CMD
,
"FEM autodetect: %s, manufacturer: %d
\n
"
,
answer
?
"auto"
:
"manual"
,
gp
->
tx_bip_fem_manufacturer
);
out:
kfree
(
gen_parms
);
return
ret
;
}
int
wl128x_cmd_general_parms
(
struct
wl1271
*
wl
)
{
struct
wl128x_general_parms_cmd
*
gen_parms
;
struct
wl128x_ini_general_params
*
gp
=
&
((
struct
wl128x_nvs_file
*
)
wl
->
nvs
)
->
general_params
;
bool
answer
=
false
;
int
ret
;
...
...
@@ -147,8 +187,9 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
int
wl1271_cmd_radio_parms
(
struct
wl1271
*
wl
)
{
struct
wl1271_nvs_file
*
nvs
=
(
struct
wl1271_nvs_file
*
)
wl
->
nvs
;
struct
wl1271_radio_parms_cmd
*
radio_parms
;
struct
wl1271_ini_general_params
*
gp
=
&
wl
->
nvs
->
general_params
;
struct
wl1271_ini_general_params
*
gp
=
&
nvs
->
general_params
;
int
ret
;
if
(
!
wl
->
nvs
)
...
...
@@ -161,18 +202,18 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
radio_parms
->
test
.
id
=
TEST_CMD_INI_FILE_RADIO_PARAM
;
/* 2.4GHz parameters */
memcpy
(
&
radio_parms
->
static_params_2
,
&
wl
->
nvs
->
stat_radio_params_2
,
memcpy
(
&
radio_parms
->
static_params_2
,
&
nvs
->
stat_radio_params_2
,
sizeof
(
struct
wl1271_ini_band_params_2
));
memcpy
(
&
radio_parms
->
dyn_params_2
,
&
wl
->
nvs
->
dyn_radio_params_2
[
gp
->
tx_bip_fem_manufacturer
].
params
,
&
nvs
->
dyn_radio_params_2
[
gp
->
tx_bip_fem_manufacturer
].
params
,
sizeof
(
struct
wl1271_ini_fem_params_2
));
/* 5GHz parameters */
memcpy
(
&
radio_parms
->
static_params_5
,
&
wl
->
nvs
->
stat_radio_params_5
,
&
nvs
->
stat_radio_params_5
,
sizeof
(
struct
wl1271_ini_band_params_5
));
memcpy
(
&
radio_parms
->
dyn_params_5
,
&
wl
->
nvs
->
dyn_radio_params_5
[
gp
->
tx_bip_fem_manufacturer
].
params
,
&
nvs
->
dyn_radio_params_5
[
gp
->
tx_bip_fem_manufacturer
].
params
,
sizeof
(
struct
wl1271_ini_fem_params_5
));
wl1271_dump
(
DEBUG_CMD
,
"TEST_CMD_INI_FILE_RADIO_PARAM: "
,
...
...
@@ -186,6 +227,50 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
return
ret
;
}
int
wl128x_cmd_radio_parms
(
struct
wl1271
*
wl
)
{
struct
wl128x_nvs_file
*
nvs
=
(
struct
wl128x_nvs_file
*
)
wl
->
nvs
;
struct
wl128x_radio_parms_cmd
*
radio_parms
;
struct
wl128x_ini_general_params
*
gp
=
&
nvs
->
general_params
;
int
ret
;
if
(
!
wl
->
nvs
)
return
-
ENODEV
;
radio_parms
=
kzalloc
(
sizeof
(
*
radio_parms
),
GFP_KERNEL
);
if
(
!
radio_parms
)
return
-
ENOMEM
;
radio_parms
->
test
.
id
=
TEST_CMD_INI_FILE_RADIO_PARAM
;
/* 2.4GHz parameters */
memcpy
(
&
radio_parms
->
static_params_2
,
&
nvs
->
stat_radio_params_2
,
sizeof
(
struct
wl128x_ini_band_params_2
));
memcpy
(
&
radio_parms
->
dyn_params_2
,
&
nvs
->
dyn_radio_params_2
[
gp
->
tx_bip_fem_manufacturer
].
params
,
sizeof
(
struct
wl128x_ini_fem_params_2
));
/* 5GHz parameters */
memcpy
(
&
radio_parms
->
static_params_5
,
&
nvs
->
stat_radio_params_5
,
sizeof
(
struct
wl128x_ini_band_params_5
));
memcpy
(
&
radio_parms
->
dyn_params_5
,
&
nvs
->
dyn_radio_params_5
[
gp
->
tx_bip_fem_manufacturer
].
params
,
sizeof
(
struct
wl128x_ini_fem_params_5
));
radio_parms
->
fem_vendor_and_options
=
nvs
->
fem_vendor_and_options
;
wl1271_dump
(
DEBUG_CMD
,
"TEST_CMD_INI_FILE_RADIO_PARAM: "
,
radio_parms
,
sizeof
(
*
radio_parms
));
ret
=
wl1271_cmd_test
(
wl
,
radio_parms
,
sizeof
(
*
radio_parms
),
0
);
if
(
ret
<
0
)
wl1271_warning
(
"CMD_INI_FILE_RADIO_PARAM failed"
);
kfree
(
radio_parms
);
return
ret
;
}
int
wl1271_cmd_ext_radio_parms
(
struct
wl1271
*
wl
)
{
struct
wl1271_ext_radio_parms_cmd
*
ext_radio_parms
;
...
...
drivers/net/wireless/wl12xx/cmd.h
View file @
e55034e9
...
...
@@ -32,7 +32,9 @@ struct acx_header;
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
wl128x_cmd_general_parms
(
struct
wl1271
*
wl
);
int
wl1271_cmd_radio_parms
(
struct
wl1271
*
wl
);
int
wl128x_cmd_radio_parms
(
struct
wl1271
*
wl
);
int
wl1271_cmd_ext_radio_parms
(
struct
wl1271
*
wl
);
int
wl1271_cmd_join
(
struct
wl1271
*
wl
,
u8
bss_type
);
int
wl1271_cmd_test
(
struct
wl1271
*
wl
,
void
*
buf
,
size_t
buf_len
,
u8
answer
);
...
...
@@ -415,6 +417,21 @@ struct wl1271_general_parms_cmd {
u8
padding
[
3
];
}
__packed
;
struct
wl128x_general_parms_cmd
{
struct
wl1271_cmd_header
header
;
struct
wl1271_cmd_test_header
test
;
struct
wl128x_ini_general_params
general_params
;
u8
sr_debug_table
[
WL1271_INI_MAX_SMART_REFLEX_PARAM
];
u8
sr_sen_n_p
;
u8
sr_sen_n_p_gain
;
u8
sr_sen_nrn
;
u8
sr_sen_prn
;
u8
padding
[
3
];
}
__packed
;
struct
wl1271_radio_parms_cmd
{
struct
wl1271_cmd_header
header
;
...
...
@@ -431,6 +448,23 @@ struct wl1271_radio_parms_cmd {
u8
padding3
[
2
];
}
__packed
;
struct
wl128x_radio_parms_cmd
{
struct
wl1271_cmd_header
header
;
struct
wl1271_cmd_test_header
test
;
/* Static radio parameters */
struct
wl128x_ini_band_params_2
static_params_2
;
struct
wl128x_ini_band_params_5
static_params_5
;
u8
fem_vendor_and_options
;
/* Dynamic radio parameters */
struct
wl128x_ini_fem_params_2
dyn_params_2
;
u8
padding2
;
struct
wl128x_ini_fem_params_5
dyn_params_5
;
}
__packed
;
struct
wl1271_ext_radio_parms_cmd
{
struct
wl1271_cmd_header
header
;
...
...
drivers/net/wireless/wl12xx/conf.h
View file @
e55034e9
...
...
@@ -1004,7 +1004,9 @@ enum {
CONF_REF_CLK_19_2_E
,
CONF_REF_CLK_26_E
,
CONF_REF_CLK_38_4_E
,
CONF_REF_CLK_52_E
CONF_REF_CLK_52_E
,
CONF_REF_CLK_38_4_M_XTAL
,
CONF_REF_CLK_26_M_XTAL
,
};
enum
single_dual_band_enum
{
...
...
@@ -1018,15 +1020,6 @@ enum single_dual_band_enum {
#define CONF_NUMBER_OF_CHANNELS_2_4 14
#define CONF_NUMBER_OF_CHANNELS_5 35
struct
conf_radio_parms
{
/*
* FEM parameter set to use
*
* Range: 0 or 1
*/
u8
fem
;
};
struct
conf_itrim_settings
{
/* enable dco itrim */
u8
enable
;
...
...
@@ -1202,7 +1195,9 @@ struct conf_drv_settings {
struct
conf_scan_settings
scan
;
struct
conf_rf_settings
rf
;
struct
conf_ht_setting
ht
;
struct
conf_memory_settings
mem
;
struct
conf_memory_settings
mem_wl127x
;
struct
conf_memory_settings
mem_wl128x
;
u8
hci_io_ds
;
};
#endif
drivers/net/wireless/wl12xx/debugfs.c
View file @
e55034e9
...
...
@@ -267,7 +267,7 @@ static ssize_t gpio_power_write(struct file *file,
}
buf
[
len
]
=
'\0'
;
ret
=
strict_
strtoul
(
buf
,
0
,
&
value
);
ret
=
k
strtoul
(
buf
,
0
,
&
value
);
if
(
ret
<
0
)
{
wl1271_warning
(
"illegal value in gpio_power"
);
return
-
EINVAL
;
...
...
drivers/net/wireless/wl12xx/event.c
View file @
e55034e9
...
...
@@ -33,6 +33,7 @@ void wl1271_pspoll_work(struct work_struct *work)
{
struct
delayed_work
*
dwork
;
struct
wl1271
*
wl
;
int
ret
;
dwork
=
container_of
(
work
,
struct
delayed_work
,
work
);
wl
=
container_of
(
dwork
,
struct
wl1271
,
pspoll_work
);
...
...
@@ -55,8 +56,13 @@ void wl1271_pspoll_work(struct work_struct *work)
* delivery failure occurred, and no-one changed state since, so
* we should go back to powersave.
*/
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out
;
wl1271_ps_set_mode
(
wl
,
STATION_POWER_SAVE_MODE
,
wl
->
basic_rate
,
true
);
wl1271_ps_elp_sleep
(
wl
);
out:
mutex_unlock
(
&
wl
->
mutex
);
};
...
...
@@ -129,11 +135,6 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
/* enable beacon early termination */
ret
=
wl1271_acx_bet_enable
(
wl
,
true
);
if
(
ret
<
0
)
break
;
/* go to extremely low power mode */
wl1271_ps_elp_sleep
(
wl
);
break
;
default:
break
;
...
...
@@ -228,6 +229,12 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
wl1271_event_rssi_trigger
(
wl
,
mbox
);
}
if
((
vector
&
DUMMY_PACKET_EVENT_ID
)
&&
!
is_ap
)
{
wl1271_debug
(
DEBUG_EVENT
,
"DUMMY_PACKET_ID_EVENT_ID"
);
if
(
wl
->
vif
)
wl1271_tx_dummy_packet
(
wl
);
}
if
(
wl
->
vif
&&
beacon_loss
)
ieee80211_connection_loss
(
wl
->
vif
);
...
...
drivers/net/wireless/wl12xx/event.h
View file @
e55034e9
...
...
@@ -59,7 +59,10 @@ enum {
BSS_LOSE_EVENT_ID
=
BIT
(
18
),
REGAINED_BSS_EVENT_ID
=
BIT
(
19
),
ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID
=
BIT
(
20
),
STA_REMOVE_COMPLETE_EVENT_ID
=
BIT
(
21
),
/* AP */
/* STA: dummy paket for dynamic mem blocks */
DUMMY_PACKET_EVENT_ID
=
BIT
(
21
),
/* AP: STA remove complete */
STA_REMOVE_COMPLETE_EVENT_ID
=
BIT
(
21
),
SOFT_GEMINI_SENSE_EVENT_ID
=
BIT
(
22
),
SOFT_GEMINI_PREDICTION_EVENT_ID
=
BIT
(
23
),
SOFT_GEMINI_AVALANCHE_EVENT_ID
=
BIT
(
24
),
...
...
drivers/net/wireless/wl12xx/ini.h
View file @
e55034e9
...
...
@@ -41,6 +41,28 @@ struct wl1271_ini_general_params {
u8
srf3
[
WL1271_INI_MAX_SMART_REFLEX_PARAM
];
}
__packed
;
#define WL128X_INI_MAX_SETTINGS_PARAM 4
struct
wl128x_ini_general_params
{
u8
ref_clock
;
u8
settling_time
;
u8
clk_valid_on_wakeup
;
u8
tcxo_ref_clock
;
u8
tcxo_settling_time
;
u8
tcxo_valid_on_wakeup
;
u8
tcxo_ldo_voltage
;
u8
xtal_itrim_val
;
u8
platform_conf
;
u8
dual_mode_select
;
u8
tx_bip_fem_auto_detect
;
u8
tx_bip_fem_manufacturer
;
u8
general_settings
[
WL128X_INI_MAX_SETTINGS_PARAM
];
u8
sr_state
;
u8
srf1
[
WL1271_INI_MAX_SMART_REFLEX_PARAM
];
u8
srf2
[
WL1271_INI_MAX_SMART_REFLEX_PARAM
];
u8
srf3
[
WL1271_INI_MAX_SMART_REFLEX_PARAM
];
}
__packed
;
#define WL1271_INI_RSSI_PROCESS_COMPENS_SIZE 15
struct
wl1271_ini_band_params_2
{
...
...
@@ -49,9 +71,16 @@ struct wl1271_ini_band_params_2 {
u8
rx_rssi_process_compens
[
WL1271_INI_RSSI_PROCESS_COMPENS_SIZE
];
}
__packed
;
#define WL1271_INI_RATE_GROUP_COUNT 6
#define WL1271_INI_CHANNEL_COUNT_2 14
struct
wl128x_ini_band_params_2
{
u8
rx_trace_insertion_loss
;
u8
tx_trace_loss
[
WL1271_INI_CHANNEL_COUNT_2
];
u8
rx_rssi_process_compens
[
WL1271_INI_RSSI_PROCESS_COMPENS_SIZE
];
}
__packed
;
#define WL1271_INI_RATE_GROUP_COUNT 6
struct
wl1271_ini_fem_params_2
{
__le16
tx_bip_ref_pd_voltage
;
u8
tx_bip_ref_power
;
...
...
@@ -68,6 +97,28 @@ struct wl1271_ini_fem_params_2 {
u8
normal_to_degraded_high_thr
;
}
__packed
;
#define WL128X_INI_RATE_GROUP_COUNT 7
/* low and high temperatures */
#define WL128X_INI_PD_VS_TEMPERATURE_RANGES 2
struct
wl128x_ini_fem_params_2
{
__le16
tx_bip_ref_pd_voltage
;
u8
tx_bip_ref_power
;
u8
tx_bip_ref_offset
;
u8
tx_per_rate_pwr_limits_normal
[
WL128X_INI_RATE_GROUP_COUNT
];
u8
tx_per_rate_pwr_limits_degraded
[
WL128X_INI_RATE_GROUP_COUNT
];
u8
tx_per_rate_pwr_limits_extreme
[
WL128X_INI_RATE_GROUP_COUNT
];
u8
tx_per_chan_pwr_limits_11b
[
WL1271_INI_CHANNEL_COUNT_2
];
u8
tx_per_chan_pwr_limits_ofdm
[
WL1271_INI_CHANNEL_COUNT_2
];
u8
tx_pd_vs_rate_offsets
[
WL128X_INI_RATE_GROUP_COUNT
];
u8
tx_ibias
[
WL128X_INI_RATE_GROUP_COUNT
+
1
];
u8
tx_pd_vs_chan_offsets
[
WL1271_INI_CHANNEL_COUNT_2
];
u8
tx_pd_vs_temperature
[
WL128X_INI_PD_VS_TEMPERATURE_RANGES
];
u8
rx_fem_insertion_loss
;
u8
degraded_low_to_normal_thr
;
u8
normal_to_degraded_high_thr
;
}
__packed
;
#define WL1271_INI_CHANNEL_COUNT_5 35
#define WL1271_INI_SUB_BAND_COUNT_5 7
...
...
@@ -77,6 +128,12 @@ struct wl1271_ini_band_params_5 {
u8
rx_rssi_process_compens
[
WL1271_INI_RSSI_PROCESS_COMPENS_SIZE
];
}
__packed
;
struct
wl128x_ini_band_params_5
{
u8
rx_trace_insertion_loss
[
WL1271_INI_SUB_BAND_COUNT_5
];
u8
tx_trace_loss
[
WL1271_INI_CHANNEL_COUNT_5
];
u8
rx_rssi_process_compens
[
WL1271_INI_RSSI_PROCESS_COMPENS_SIZE
];
}
__packed
;
struct
wl1271_ini_fem_params_5
{
__le16
tx_bip_ref_pd_voltage
[
WL1271_INI_SUB_BAND_COUNT_5
];
u8
tx_bip_ref_power
[
WL1271_INI_SUB_BAND_COUNT_5
];
...
...
@@ -92,6 +149,23 @@ struct wl1271_ini_fem_params_5 {
u8
normal_to_degraded_high_thr
;
}
__packed
;
struct
wl128x_ini_fem_params_5
{
__le16
tx_bip_ref_pd_voltage
[
WL1271_INI_SUB_BAND_COUNT_5
];
u8
tx_bip_ref_power
[
WL1271_INI_SUB_BAND_COUNT_5
];
u8
tx_bip_ref_offset
[
WL1271_INI_SUB_BAND_COUNT_5
];
u8
tx_per_rate_pwr_limits_normal
[
WL128X_INI_RATE_GROUP_COUNT
];
u8
tx_per_rate_pwr_limits_degraded
[
WL128X_INI_RATE_GROUP_COUNT
];
u8
tx_per_rate_pwr_limits_extreme
[
WL128X_INI_RATE_GROUP_COUNT
];
u8
tx_per_chan_pwr_limits_ofdm
[
WL1271_INI_CHANNEL_COUNT_5
];
u8
tx_pd_vs_rate_offsets
[
WL128X_INI_RATE_GROUP_COUNT
];
u8
tx_ibias
[
WL128X_INI_RATE_GROUP_COUNT
];
u8
tx_pd_vs_chan_offsets
[
WL1271_INI_CHANNEL_COUNT_5
];
u8
tx_pd_vs_temperature
[
WL1271_INI_SUB_BAND_COUNT_5
*
WL128X_INI_PD_VS_TEMPERATURE_RANGES
];
u8
rx_fem_insertion_loss
[
WL1271_INI_SUB_BAND_COUNT_5
];
u8
degraded_low_to_normal_thr
;
u8
normal_to_degraded_high_thr
;
}
__packed
;
/* NVS data structure */
#define WL1271_INI_NVS_SECTION_SIZE 468
...
...
@@ -100,7 +174,7 @@ struct wl1271_ini_fem_params_5 {
#define WL1271_INI_LEGACY_NVS_FILE_SIZE 800
struct
wl1271_nvs_file
{
/* NVS section */
/* NVS section
- must be first!
*/
u8
nvs
[
WL1271_INI_NVS_SECTION_SIZE
];
/* INI section */
...
...
@@ -120,4 +194,24 @@ struct wl1271_nvs_file {
}
dyn_radio_params_5
[
WL1271_INI_FEM_MODULE_COUNT
];
}
__packed
;
struct
wl128x_nvs_file
{
/* NVS section - must be first! */
u8
nvs
[
WL1271_INI_NVS_SECTION_SIZE
];
/* INI section */
struct
wl128x_ini_general_params
general_params
;
u8
fem_vendor_and_options
;
struct
wl128x_ini_band_params_2
stat_radio_params_2
;
u8
padding2
;
struct
{
struct
wl128x_ini_fem_params_2
params
;
u8
padding
;
}
dyn_radio_params_2
[
WL1271_INI_FEM_MODULE_COUNT
];
struct
wl128x_ini_band_params_5
stat_radio_params_5
;
u8
padding3
;
struct
{
struct
wl128x_ini_fem_params_5
params
;
u8
padding
;
}
dyn_radio_params_5
[
WL1271_INI_FEM_MODULE_COUNT
];
}
__packed
;
#endif
drivers/net/wireless/wl12xx/init.c
View file @
e55034e9
...
...
@@ -31,6 +31,7 @@
#include "cmd.h"
#include "reg.h"
#include "tx.h"
#include "io.h"
int
wl1271_sta_init_templates_config
(
struct
wl1271
*
wl
)
{
...
...
@@ -321,9 +322,11 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
{
int
ret
;
ret
=
wl1271_cmd_ext_radio_parms
(
wl
);
if
(
ret
<
0
)
return
ret
;
if
(
wl
->
chip
.
id
!=
CHIP_ID_1283_PG20
)
{
ret
=
wl1271_cmd_ext_radio_parms
(
wl
);
if
(
ret
<
0
)
return
ret
;
}
/* PS config */
ret
=
wl1271_acx_config_ps
(
wl
);
...
...
@@ -504,6 +507,27 @@ static int wl1271_set_ba_policies(struct wl1271 *wl)
return
ret
;
}
int
wl1271_chip_specific_init
(
struct
wl1271
*
wl
)
{
int
ret
=
0
;
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
{
u32
host_cfg_bitmap
=
HOST_IF_CFG_RX_FIFO_ENABLE
;
if
(
wl
->
quirks
&
WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT
)
/* Enable SDIO padding */
host_cfg_bitmap
|=
HOST_IF_CFG_TX_PAD_TO_SDIO_BLK
;
/* Must be before wl1271_acx_init_mem_config() */
ret
=
wl1271_acx_host_if_cfg_bitmap
(
wl
,
host_cfg_bitmap
);
if
(
ret
<
0
)
goto
out
;
}
out:
return
ret
;
}
int
wl1271_hw_init
(
struct
wl1271
*
wl
)
{
struct
conf_tx_ac_category
*
conf_ac
;
...
...
@@ -511,11 +535,22 @@ int wl1271_hw_init(struct wl1271 *wl)
int
ret
,
i
;
bool
is_ap
=
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
);
ret
=
wl1271_cmd_general_parms
(
wl
);
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
ret
=
wl128x_cmd_general_parms
(
wl
);
else
ret
=
wl1271_cmd_general_parms
(
wl
);
if
(
ret
<
0
)
return
ret
;
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
ret
=
wl128x_cmd_radio_parms
(
wl
);
else
ret
=
wl1271_cmd_radio_parms
(
wl
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_cmd_radio_parms
(
wl
);
/* Chip-specific init */
ret
=
wl1271_chip_specific_init
(
wl
);
if
(
ret
<
0
)
return
ret
;
...
...
drivers/net/wireless/wl12xx/init.h
View file @
e55034e9
...
...
@@ -31,6 +31,7 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl);
int
wl1271_init_phy_config
(
struct
wl1271
*
wl
);
int
wl1271_init_pta
(
struct
wl1271
*
wl
);
int
wl1271_init_energy_detection
(
struct
wl1271
*
wl
);
int
wl1271_chip_specific_init
(
struct
wl1271
*
wl
);
int
wl1271_hw_init
(
struct
wl1271
*
wl
);
#endif
drivers/net/wireless/wl12xx/io.c
View file @
e55034e9
...
...
@@ -29,6 +29,7 @@
#include "wl12xx.h"
#include "wl12xx_80211.h"
#include "io.h"
#include "tx.h"
#define OCP_CMD_LOOP 32
...
...
@@ -43,6 +44,16 @@
#define OCP_STATUS_REQ_FAILED 0x20000
#define OCP_STATUS_RESP_ERROR 0x30000
bool
wl1271_set_block_size
(
struct
wl1271
*
wl
)
{
if
(
wl
->
if_ops
->
set_block_size
)
{
wl
->
if_ops
->
set_block_size
(
wl
,
WL12XX_BUS_BLOCK_SIZE
);
return
true
;
}
return
false
;
}
void
wl1271_disable_interrupts
(
struct
wl1271
*
wl
)
{
wl
->
if_ops
->
disable_irq
(
wl
);
...
...
drivers/net/wireless/wl12xx/io.h
View file @
e55034e9
...
...
@@ -169,5 +169,8 @@ int wl1271_init_ieee80211(struct wl1271 *wl);
struct
ieee80211_hw
*
wl1271_alloc_hw
(
void
);
int
wl1271_free_hw
(
struct
wl1271
*
wl
);
irqreturn_t
wl1271_irq
(
int
irq
,
void
*
data
);
bool
wl1271_set_block_size
(
struct
wl1271
*
wl
);
int
wl1271_tx_dummy_packet
(
struct
wl1271
*
wl
);
void
wl1271_configure_filters
(
struct
wl1271
*
wl
,
unsigned
int
filters
);
#endif
drivers/net/wireless/wl12xx/main.c
View file @
e55034e9
...
...
@@ -30,6 +30,7 @@
#include <linux/vmalloc.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/wl12xx.h>
#include "wl12xx.h"
#include "wl12xx_80211.h"
...
...
@@ -54,7 +55,7 @@ static struct conf_drv_settings default_conf = {
[
CONF_SG_BT_PER_THRESHOLD
]
=
7500
,
[
CONF_SG_HV3_MAX_OVERRIDE
]
=
0
,
[
CONF_SG_BT_NFS_SAMPLE_INTERVAL
]
=
400
,
[
CONF_SG_BT_LOAD_RATIO
]
=
5
0
,
[
CONF_SG_BT_LOAD_RATIO
]
=
20
0
,
[
CONF_SG_AUTO_PS_MODE
]
=
1
,
[
CONF_SG_AUTO_SCAN_PROBE_REQ
]
=
170
,
[
CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3
]
=
50
,
...
...
@@ -254,7 +255,7 @@ static struct conf_drv_settings default_conf = {
.
ps_poll_threshold
=
10
,
.
ps_poll_recovery_period
=
700
,
.
bet_enable
=
CONF_BET_MODE_ENABLE
,
.
bet_max_consecutive
=
1
0
,
.
bet_max_consecutive
=
5
0
,
.
psm_entry_retries
=
5
,
.
psm_exit_retries
=
255
,
.
psm_entry_nullfunc_retries
=
3
,
...
...
@@ -298,7 +299,7 @@ static struct conf_drv_settings default_conf = {
.
tx_ba_win_size
=
64
,
.
inactivity_timeout
=
10000
,
},
.
mem
=
{
.
mem
_wl127x
=
{
.
num_stations
=
1
,
.
ssid_profiles
=
1
,
.
rx_block_num
=
70
,
...
...
@@ -307,7 +308,18 @@ static struct conf_drv_settings default_conf = {
.
min_req_tx_blocks
=
100
,
.
min_req_rx_blocks
=
22
,
.
tx_min
=
27
,
}
},
.
mem_wl128x
=
{
.
num_stations
=
1
,
.
ssid_profiles
=
1
,
.
rx_block_num
=
40
,
.
tx_min_block_num
=
40
,
.
dynamic_memory
=
1
,
.
min_req_tx_blocks
=
45
,
.
min_req_rx_blocks
=
22
,
.
tx_min
=
27
,
},
.
hci_io_ds
=
HCI_IO_DS_6MA
,
};
static
void
__wl1271_op_remove_interface
(
struct
wl1271
*
wl
);
...
...
@@ -329,6 +341,7 @@ static struct platform_device wl1271_device = {
},
};
static
DEFINE_MUTEX
(
wl_list_mutex
);
static
LIST_HEAD
(
wl_list
);
static
int
wl1271_dev_notify
(
struct
notifier_block
*
me
,
unsigned
long
what
,
...
...
@@ -359,10 +372,12 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
return
NOTIFY_DONE
;
wl_temp
=
hw
->
priv
;
mutex_lock
(
&
wl_list_mutex
);
list_for_each_entry
(
wl
,
&
wl_list
,
list
)
{
if
(
wl
==
wl_temp
)
break
;
}
mutex_unlock
(
&
wl_list_mutex
);
if
(
wl
!=
wl_temp
)
return
NOTIFY_DONE
;
...
...
@@ -438,15 +453,30 @@ static int wl1271_plt_init(struct wl1271 *wl)
struct
conf_tx_tid
*
conf_tid
;
int
ret
,
i
;
ret
=
wl1271_cmd_general_parms
(
wl
);
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
ret
=
wl128x_cmd_general_parms
(
wl
);
else
ret
=
wl1271_cmd_general_parms
(
wl
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_cmd_radio_parms
(
wl
);
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
ret
=
wl128x_cmd_radio_parms
(
wl
);
else
ret
=
wl1271_cmd_radio_parms
(
wl
);
if
(
ret
<
0
)
return
ret
;
if
(
wl
->
chip
.
id
!=
CHIP_ID_1283_PG20
)
{
ret
=
wl1271_cmd_ext_radio_parms
(
wl
);
if
(
ret
<
0
)
return
ret
;
}
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_cmd_ext_radio_parms
(
wl
);
/* Chip-specific initializations */
ret
=
wl1271_chip_specific_init
(
wl
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -593,15 +623,17 @@ static void wl1271_fw_status(struct wl1271 *wl,
{
struct
wl1271_fw_common_status
*
status
=
&
full_status
->
common
;
struct
timespec
ts
;
u32
total
=
0
;
u32
old_tx_blk_count
=
wl
->
tx_blocks_available
;
u32
freed_blocks
=
0
;
int
i
;
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
{
wl1271_raw_read
(
wl
,
FW_STATUS_ADDR
,
status
,
sizeof
(
struct
wl1271_fw_ap_status
),
false
);
else
}
else
{
wl1271_raw_read
(
wl
,
FW_STATUS_ADDR
,
status
,
sizeof
(
struct
wl1271_fw_sta_status
),
false
);
}
wl1271_debug
(
DEBUG_IRQ
,
"intr: 0x%x (fw_rx_counter = %d, "
"drv_rx_counter = %d, tx_results_counter = %d)"
,
...
...
@@ -612,22 +644,37 @@ static void wl1271_fw_status(struct wl1271 *wl,
/* update number of available TX blocks */
for
(
i
=
0
;
i
<
NUM_TX_QUEUES
;
i
++
)
{
u32
cnt
=
le32_to_cpu
(
status
->
tx_released_blks
[
i
])
-
wl
->
tx_blocks_freed
[
i
];
freed_blocks
+
=
le32_to_cpu
(
status
->
tx_released_blks
[
i
])
-
wl
->
tx_blocks_freed
[
i
];
wl
->
tx_blocks_freed
[
i
]
=
le32_to_cpu
(
status
->
tx_released_blks
[
i
]);
wl
->
tx_blocks_available
+=
cnt
;
total
+=
cnt
;
}
/* if more blocks are available now, tx work can be scheduled */
if
(
total
)
clear_bit
(
WL1271_FLAG_FW_TX_BUSY
,
&
wl
->
flags
);
wl
->
tx_allocated_blocks
-=
freed_blocks
;
/* for AP update num of allocated TX blocks per link and ps status */
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
{
/* Update num of allocated TX blocks per link and ps status */
wl1271_irq_update_links_status
(
wl
,
&
full_status
->
ap
);
wl
->
tx_blocks_available
+=
freed_blocks
;
}
else
{
int
avail
=
full_status
->
sta
.
tx_total
-
wl
->
tx_allocated_blocks
;
/*
* The FW might change the total number of TX memblocks before
* we get a notification about blocks being released. Thus, the
* available blocks calculation might yield a temporary result
* which is lower than the actual available blocks. Keeping in
* mind that only blocks that were allocated can be moved from
* TX to RX, tx_blocks_available should never decrease here.
*/
wl
->
tx_blocks_available
=
max
((
int
)
wl
->
tx_blocks_available
,
avail
);
}
/* if more blocks are available now, tx work can be scheduled */
if
(
wl
->
tx_blocks_available
>
old_tx_blk_count
)
clear_bit
(
WL1271_FLAG_FW_TX_BUSY
,
&
wl
->
flags
);
/* update the host-chipset time offset */
getnstimeofday
(
&
ts
);
...
...
@@ -674,6 +721,13 @@ irqreturn_t wl1271_irq(int irq, void *cookie)
set_bit
(
WL1271_FLAG_TX_PENDING
,
&
wl
->
flags
);
cancel_work_sync
(
&
wl
->
tx_work
);
/*
* In case edge triggered interrupt must be used, we cannot iterate
* more than once without introducing race conditions with the hardirq.
*/
if
(
wl
->
platform_quirks
&
WL12XX_PLATFORM_QUIRK_EDGE_IRQ
)
loopcount
=
1
;
mutex_lock
(
&
wl
->
mutex
);
wl1271_debug
(
DEBUG_IRQ
,
"IRQ work"
);
...
...
@@ -785,11 +839,17 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
switch
(
wl
->
bss_type
)
{
case
BSS_TYPE_AP_BSS
:
fw_name
=
WL1271_AP_FW_NAME
;
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
fw_name
=
WL128X_AP_FW_NAME
;
else
fw_name
=
WL127X_AP_FW_NAME
;
break
;
case
BSS_TYPE_IBSS
:
case
BSS_TYPE_STA_BSS
:
fw_name
=
WL1271_FW_NAME
;
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
fw_name
=
WL128X_FW_NAME
;
else
fw_name
=
WL1271_FW_NAME
;
break
;
default:
wl1271_error
(
"no compatible firmware for bss_type %d"
,
...
...
@@ -838,14 +898,14 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
const
struct
firmware
*
fw
;
int
ret
;
ret
=
request_firmware
(
&
fw
,
WL12
71
_NVS_NAME
,
wl1271_wl_to_dev
(
wl
));
ret
=
request_firmware
(
&
fw
,
WL12
XX
_NVS_NAME
,
wl1271_wl_to_dev
(
wl
));
if
(
ret
<
0
)
{
wl1271_error
(
"could not get nvs file: %d"
,
ret
);
return
ret
;
}
wl
->
nvs
=
kmemdup
(
fw
->
data
,
sizeof
(
struct
wl1271_nvs_file
)
,
GFP_KERNEL
);
wl
->
nvs
=
kmemdup
(
fw
->
data
,
fw
->
size
,
GFP_KERNEL
);
if
(
!
wl
->
nvs
)
{
wl1271_error
(
"could not allocate memory for the nvs file"
);
...
...
@@ -954,6 +1014,17 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
if
(
ret
<
0
)
goto
out
;
break
;
case
CHIP_ID_1283_PG20
:
wl1271_debug
(
DEBUG_BOOT
,
"chip id 0x%x (1283 PG20)"
,
wl
->
chip
.
id
);
ret
=
wl1271_setup
(
wl
);
if
(
ret
<
0
)
goto
out
;
if
(
wl1271_set_block_size
(
wl
))
wl
->
quirks
|=
WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT
;
break
;
case
CHIP_ID_1283_PG10
:
default:
wl1271_warning
(
"unsupported chip id: 0x%x"
,
wl
->
chip
.
id
);
ret
=
-
ENODEV
;
...
...
@@ -978,6 +1049,24 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
return
ret
;
}
static
unsigned
int
wl1271_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
;
return
quirks
;
}
int
wl1271_plt_start
(
struct
wl1271
*
wl
)
{
int
retries
=
WL1271_BOOT_RETRIES
;
...
...
@@ -1013,6 +1102,9 @@ int wl1271_plt_start(struct wl1271 *wl)
wl
->
state
=
WL1271_STATE_PLT
;
wl1271_notice
(
"firmware booted in PLT mode (%s)"
,
wl
->
chip
.
fw_ver_str
);
/* Check if any quirks are needed with older fw versions */
wl
->
quirks
|=
wl1271_get_fw_ver_quirks
(
wl
);
goto
out
;
irq_disable:
...
...
@@ -1040,7 +1132,7 @@ int wl1271_plt_start(struct wl1271 *wl)
return
ret
;
}
int
__wl1271_plt_stop
(
struct
wl1271
*
wl
)
static
int
__wl1271_plt_stop
(
struct
wl1271
*
wl
)
{
int
ret
=
0
;
...
...
@@ -1124,6 +1216,69 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
}
int
wl1271_tx_dummy_packet
(
struct
wl1271
*
wl
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
set_bit
(
WL1271_FLAG_DUMMY_PACKET_PENDING
,
&
wl
->
flags
);
wl
->
tx_queue_count
++
;
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
/* The FW is low on RX memory blocks, so send the dummy packet asap */
if
(
!
test_bit
(
WL1271_FLAG_FW_TX_BUSY
,
&
wl
->
flags
))
wl1271_tx_work_locked
(
wl
);
/*
* If the FW TX is busy, TX work will be scheduled by the threaded
* interrupt handler function
*/
return
0
;
}
/*
* The size of the dummy packet should be at least 1400 bytes. However, in
* order to minimize the number of bus transactions, aligning it to 512 bytes
* boundaries could be beneficial, performance wise
*/
#define TOTAL_TX_DUMMY_PACKET_SIZE (ALIGN(1400, 512))
static
struct
sk_buff
*
wl12xx_alloc_dummy_packet
(
struct
wl1271
*
wl
)
{
struct
sk_buff
*
skb
;
struct
ieee80211_hdr_3addr
*
hdr
;
unsigned
int
dummy_packet_size
;
dummy_packet_size
=
TOTAL_TX_DUMMY_PACKET_SIZE
-
sizeof
(
struct
wl1271_tx_hw_descr
)
-
sizeof
(
*
hdr
);
skb
=
dev_alloc_skb
(
TOTAL_TX_DUMMY_PACKET_SIZE
);
if
(
!
skb
)
{
wl1271_warning
(
"Failed to allocate a dummy packet skb"
);
return
NULL
;
}
skb_reserve
(
skb
,
sizeof
(
struct
wl1271_tx_hw_descr
));
hdr
=
(
struct
ieee80211_hdr_3addr
*
)
skb_put
(
skb
,
sizeof
(
*
hdr
));
memset
(
hdr
,
0
,
sizeof
(
*
hdr
));
hdr
->
frame_control
=
cpu_to_le16
(
IEEE80211_FTYPE_DATA
|
IEEE80211_STYPE_NULLFUNC
|
IEEE80211_FCTL_TODS
);
memset
(
skb_put
(
skb
,
dummy_packet_size
),
0
,
dummy_packet_size
);
/* Dummy packets require the TID to be management */
skb
->
priority
=
WL1271_TID_MGMT
;
/* Initialize all fields that might be used */
skb
->
queue_mapping
=
0
;
memset
(
IEEE80211_SKB_CB
(
skb
),
0
,
sizeof
(
struct
ieee80211_tx_info
));
return
skb
;
}
static
struct
notifier_block
wl1271_dev_notifier
=
{
.
notifier_call
=
wl1271_dev_notify
,
};
...
...
@@ -1174,6 +1329,16 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
goto
out
;
}
/*
* in some very corner case HW recovery scenarios its possible to
* get here before __wl1271_op_remove_interface is complete, so
* opt out if that is the case.
*/
if
(
test_bit
(
WL1271_FLAG_IF_INITIALIZED
,
&
wl
->
flags
))
{
ret
=
-
EBUSY
;
goto
out
;
}
switch
(
vif
->
type
)
{
case
NL80211_IFTYPE_STATION
:
wl
->
bss_type
=
BSS_TYPE_STA_BSS
;
...
...
@@ -1242,6 +1407,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
wl
->
vif
=
vif
;
wl
->
state
=
WL1271_STATE_ON
;
set_bit
(
WL1271_FLAG_IF_INITIALIZED
,
&
wl
->
flags
);
wl1271_info
(
"firmware booted (%s)"
,
wl
->
chip
.
fw_ver_str
);
/* update hw/fw version info in wiphy struct */
...
...
@@ -1249,6 +1415,9 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
strncpy
(
wiphy
->
fw_version
,
wl
->
chip
.
fw_ver_str
,
sizeof
(
wiphy
->
fw_version
));
/* Check if any quirks are needed with older fw versions */
wl
->
quirks
|=
wl1271_get_fw_ver_quirks
(
wl
);
/*
* Now we know if 11a is supported (info from the NVS), so disable
* 11a channels if not supported
...
...
@@ -1262,8 +1431,10 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
out:
mutex_unlock
(
&
wl
->
mutex
);
mutex_lock
(
&
wl_list_mutex
);
if
(
!
ret
)
list_add
(
&
wl
->
list
,
&
wl_list
);
mutex_unlock
(
&
wl_list_mutex
);
return
ret
;
}
...
...
@@ -1274,11 +1445,15 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl)
wl1271_debug
(
DEBUG_MAC80211
,
"mac80211 remove interface"
);
/* because of hardware recovery, we may get here twice */
if
(
wl
->
state
!=
WL1271_STATE_ON
)
return
;
wl1271_info
(
"down"
);
mutex_lock
(
&
wl_list_mutex
);
list_del
(
&
wl
->
list
);
WARN_ON
(
wl
->
state
!=
WL1271_STATE_ON
);
mutex_unlock
(
&
wl_list_mutex
);
/* enable dyn ps just in case (if left on due to fw crash etc) */
if
(
wl
->
bss_type
==
BSS_TYPE_STA_BSS
)
...
...
@@ -1286,12 +1461,15 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl)
if
(
wl
->
scan
.
state
!=
WL1271_SCAN_STATE_IDLE
)
{
wl
->
scan
.
state
=
WL1271_SCAN_STATE_IDLE
;
kfree
(
wl
->
scan
.
scanned_ch
);
wl
->
scan
.
scanned_ch
=
NULL
;
memset
(
wl
->
scan
.
scanned_ch
,
0
,
sizeof
(
wl
->
scan
.
scanned_ch
));
wl
->
scan
.
req
=
NULL
;
ieee80211_scan_completed
(
wl
->
hw
,
true
);
}
/*
* this must be before the cancel_work calls below, so that the work
* functions don't perform further work.
*/
wl
->
state
=
WL1271_STATE_OFF
;
mutex_unlock
(
&
wl
->
mutex
);
...
...
@@ -1321,6 +1499,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl)
wl
->
psm_entry_retry
=
0
;
wl
->
power_level
=
WL1271_DEFAULT_POWER_LEVEL
;
wl
->
tx_blocks_available
=
0
;
wl
->
tx_allocated_blocks
=
0
;
wl
->
tx_results_count
=
0
;
wl
->
tx_packets_count
=
0
;
wl
->
tx_security_last_seq
=
0
;
...
...
@@ -1328,7 +1507,6 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl)
wl
->
time_offset
=
0
;
wl
->
session_counter
=
0
;
wl
->
rate_set
=
CONF_TX_RATE_MASK_BASIC
;
wl
->
flags
=
0
;
wl
->
vif
=
NULL
;
wl
->
filters
=
0
;
wl1271_free_ap_keys
(
wl
);
...
...
@@ -1336,6 +1514,13 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl)
wl
->
ap_fw_ps_map
=
0
;
wl
->
ap_ps_map
=
0
;
/*
* this is performed after the cancel_work calls and the associated
* mutex_lock, so that wl1271_op_add_interface does not accidentally
* get executed before all these vars have been reset.
*/
wl
->
flags
=
0
;
for
(
i
=
0
;
i
<
NUM_TX_QUEUES
;
i
++
)
wl
->
tx_blocks_freed
[
i
]
=
0
;
...
...
@@ -1368,7 +1553,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
cancel_work_sync
(
&
wl
->
recovery_work
);
}
static
void
wl1271_configure_filters
(
struct
wl1271
*
wl
,
unsigned
int
filters
)
void
wl1271_configure_filters
(
struct
wl1271
*
wl
,
unsigned
int
filters
)
{
wl1271_set_default_filters
(
wl
);
...
...
@@ -1431,10 +1616,10 @@ static int wl1271_join(struct wl1271 *wl, bool set_assoc)
* One of the side effects of the JOIN command is that is clears
* WPA/WPA2 keys from the chipset. Performing a JOIN while associated
* to a WPA/WPA2 access point will therefore kill the data-path.
* Currently the
re is no supported scenario for JOIN during
*
association - if it becomes a supported scenario, the WPA/WPA2 keys
*
must be handled somehow.
*
* Currently the
only valid scenario for JOIN during association
*
is on roaming, in which case we will also be given new keys.
*
Keep the below message for now, unless it starts bothering
*
users who really like to roam a lot :)
*/
if
(
test_bit
(
WL1271_FLAG_STA_ASSOCIATED
,
&
wl
->
flags
))
wl1271_info
(
"JOIN while associated."
);
...
...
@@ -1490,7 +1675,7 @@ static int wl1271_unjoin(struct wl1271 *wl)
clear_bit
(
WL1271_FLAG_JOINED
,
&
wl
->
flags
);
memset
(
wl
->
bssid
,
0
,
ETH_ALEN
);
/* stop filter
t
ing packets based on bssid */
/* stop filtering packets based on bssid */
wl1271_configure_filters
(
wl
,
FIF_OTHER_BSS
);
out:
...
...
@@ -1569,7 +1754,12 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
mutex_lock
(
&
wl
->
mutex
);
if
(
unlikely
(
wl
->
state
==
WL1271_STATE_OFF
))
{
ret
=
-
EAGAIN
;
/* we support configuring the channel and band while off */
if
((
changed
&
IEEE80211_CONF_CHANGE_CHANNEL
))
{
wl
->
band
=
conf
->
channel
->
band
;
wl
->
channel
=
channel
;
}
goto
out
;
}
...
...
@@ -2650,32 +2840,31 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
conf_tid
->
ack_policy
=
CONF_ACK_POLICY_LEGACY
;
conf_tid
->
apsd_conf
[
0
]
=
0
;
conf_tid
->
apsd_conf
[
1
]
=
0
;
}
else
{
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out
;
goto
out
;
}
/*
* the txop is confed in units of 32us by the mac80211,
* we need us
*/
ret
=
wl1271_acx_ac_cfg
(
wl
,
wl1271_tx_get_queue
(
queue
),
params
->
cw_min
,
params
->
cw_max
,
params
->
aifs
,
params
->
txop
<<
5
);
if
(
ret
<
0
)
goto
out_sleep
;
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out
;
ret
=
wl1271_acx_tid_cfg
(
wl
,
wl1271_tx_get_queue
(
queue
),
CONF_CHANNEL_TYPE_EDCF
,
wl1271_tx_get_queue
(
queue
),
ps_scheme
,
CONF_ACK_POLICY_LEGACY
,
0
,
0
);
if
(
ret
<
0
)
goto
out_sleep
;
/*
* the txop is confed in units of 32us by the mac80211,
* we need us
*/
ret
=
wl1271_acx_ac_cfg
(
wl
,
wl1271_tx_get_queue
(
queue
),
params
->
cw_min
,
params
->
cw_max
,
params
->
aifs
,
params
->
txop
<<
5
);
if
(
ret
<
0
)
goto
out_sleep
;
ret
=
wl1271_acx_tid_cfg
(
wl
,
wl1271_tx_get_queue
(
queue
),
CONF_CHANNEL_TYPE_EDCF
,
wl1271_tx_get_queue
(
queue
),
ps_scheme
,
CONF_ACK_POLICY_LEGACY
,
0
,
0
);
out_sleep:
wl1271_ps_elp_sleep
(
wl
);
}
wl1271_ps_elp_sleep
(
wl
);
out:
mutex_unlock
(
&
wl
->
mutex
);
...
...
@@ -2847,10 +3036,11 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw,
return
ret
;
}
int
wl1271_op_ampdu_action
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
,
enum
ieee80211_ampdu_mlme_action
action
,
struct
ieee80211_sta
*
sta
,
u16
tid
,
u16
*
ssn
,
u8
buf_size
)
static
int
wl1271_op_ampdu_action
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
,
enum
ieee80211_ampdu_mlme_action
action
,
struct
ieee80211_sta
*
sta
,
u16
tid
,
u16
*
ssn
,
u8
buf_size
)
{
struct
wl1271
*
wl
=
hw
->
priv
;
int
ret
;
...
...
@@ -3003,7 +3193,8 @@ static const u8 wl1271_rate_to_idx_2ghz[] = {
#ifdef CONFIG_WL12XX_HT
#define WL12XX_HT_CAP { \
.cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20, \
.cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | \
(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT), \
.ht_supported = true, \
.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K, \
.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, \
...
...
@@ -3207,8 +3398,7 @@ static ssize_t wl1271_sysfs_store_bt_coex_state(struct device *dev,
unsigned
long
res
;
int
ret
;
ret
=
strict_strtoul
(
buf
,
10
,
&
res
);
ret
=
kstrtoul
(
buf
,
10
,
&
res
);
if
(
ret
<
0
)
{
wl1271_warning
(
"incorrect value written to bt_coex_mode"
);
return
count
;
...
...
@@ -3273,7 +3463,11 @@ int wl1271_register_hw(struct wl1271 *wl)
ret
=
wl1271_fetch_nvs
(
wl
);
if
(
ret
==
0
)
{
u8
*
nvs_ptr
=
(
u8
*
)
wl
->
nvs
->
nvs
;
/* NOTE: The wl->nvs->nvs element must be first, in
* order to simplify the casting, we assume it is at
* the beginning of the wl->nvs structure.
*/
u8
*
nvs_ptr
=
(
u8
*
)
wl
->
nvs
;
wl
->
mac_addr
[
0
]
=
nvs_ptr
[
11
];
wl
->
mac_addr
[
1
]
=
nvs_ptr
[
10
];
...
...
@@ -3358,6 +3552,10 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
wl
->
hw
->
wiphy
->
max_scan_ie_len
=
WL1271_CMD_TEMPL_MAX_SIZE
-
sizeof
(
struct
ieee80211_header
);
/* make sure all our channels fit in the scanned_ch bitmask */
BUILD_BUG_ON
(
ARRAY_SIZE
(
wl1271_channels
)
+
ARRAY_SIZE
(
wl1271_channels_5ghz
)
>
WL1271_MAX_CHANNELS
);
/*
* We keep local copies of the band structs because we need to
* modify them on a per-device basis.
...
...
@@ -3458,6 +3656,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl
->
ap_ps_map
=
0
;
wl
->
ap_fw_ps_map
=
0
;
wl
->
quirks
=
0
;
wl
->
platform_quirks
=
0
;
memset
(
wl
->
tx_frames_map
,
0
,
sizeof
(
wl
->
tx_frames_map
));
for
(
i
=
0
;
i
<
ACX_TX_DESCRIPTORS
;
i
++
)
...
...
@@ -3478,11 +3677,17 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
goto
err_hw
;
}
wl
->
dummy_packet
=
wl12xx_alloc_dummy_packet
(
wl
);
if
(
!
wl
->
dummy_packet
)
{
ret
=
-
ENOMEM
;
goto
err_aggr
;
}
/* Register platform device */
ret
=
platform_device_register
(
wl
->
plat_dev
);
if
(
ret
)
{
wl1271_error
(
"couldn't register platform device"
);
goto
err_
aggr
;
goto
err_
dummy_packet
;
}
dev_set_drvdata
(
&
wl
->
plat_dev
->
dev
,
wl
);
...
...
@@ -3508,6 +3713,9 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
err_platform:
platform_device_unregister
(
wl
->
plat_dev
);
err_dummy_packet:
dev_kfree_skb
(
wl
->
dummy_packet
);
err_aggr:
free_pages
((
unsigned
long
)
wl
->
aggr_buf
,
order
);
...
...
@@ -3527,6 +3735,7 @@ EXPORT_SYMBOL_GPL(wl1271_alloc_hw);
int
wl1271_free_hw
(
struct
wl1271
*
wl
)
{
platform_device_unregister
(
wl
->
plat_dev
);
dev_kfree_skb
(
wl
->
dummy_packet
);
free_pages
((
unsigned
long
)
wl
->
aggr_buf
,
get_order
(
WL1271_AGGR_BUFFER_SIZE
));
kfree
(
wl
->
plat_dev
);
...
...
drivers/net/wireless/wl12xx/ps.c
View file @
e55034e9
...
...
@@ -149,9 +149,6 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
case
STATION_ACTIVE_MODE
:
default:
wl1271_debug
(
DEBUG_PSM
,
"leaving psm"
);
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
return
ret
;
/* disable beacon early termination */
ret
=
wl1271_acx_bet_enable
(
wl
,
false
);
...
...
drivers/net/wireless/wl12xx/reg.h
View file @
e55034e9
...
...
@@ -207,6 +207,8 @@
#define CHIP_ID_1271_PG10 (0x4030101)
#define CHIP_ID_1271_PG20 (0x4030111)
#define CHIP_ID_1283_PG10 (0x05030101)
#define CHIP_ID_1283_PG20 (0x05030111)
#define ENABLE (REGISTERS_BASE + 0x5450)
...
...
@@ -452,24 +454,11 @@
#define HI_CFG_UART_TX_OUT_GPIO_14 0x00000200
#define HI_CFG_UART_TX_OUT_GPIO_7 0x00000400
/*
* NOTE: USE_ACTIVE_HIGH compilation flag should be defined in makefile
* for platforms using active high interrupt level
*/
#ifdef USE_ACTIVE_HIGH
#define HI_CFG_DEF_VAL \
(HI_CFG_UART_ENABLE | \
HI_CFG_RST232_ENABLE | \
HI_CFG_CLOCK_REQ_SELECT | \
HI_CFG_HOST_INT_ENABLE)
#else
#define HI_CFG_DEF_VAL \
(HI_CFG_UART_ENABLE | \
HI_CFG_RST232_ENABLE | \
HI_CFG_CLOCK_REQ_SELECT | \
HI_CFG_HOST_INT_ENABLE)
#endif
#define REF_FREQ_19_2 0
#define REF_FREQ_26_0 1
...
...
drivers/net/wireless/wl12xx/rx.c
View file @
e55034e9
...
...
@@ -48,18 +48,14 @@ static void wl1271_rx_status(struct wl1271 *wl,
struct
ieee80211_rx_status
*
status
,
u8
beacon
)
{
enum
ieee80211_band
desc_band
;
memset
(
status
,
0
,
sizeof
(
struct
ieee80211_rx_status
));
status
->
band
=
wl
->
band
;
if
((
desc
->
flags
&
WL1271_RX_DESC_BAND_MASK
)
==
WL1271_RX_DESC_BAND_BG
)
desc_
band
=
IEEE80211_BAND_2GHZ
;
status
->
band
=
IEEE80211_BAND_2GHZ
;
else
desc_
band
=
IEEE80211_BAND_5GHZ
;
status
->
band
=
IEEE80211_BAND_5GHZ
;
status
->
rate_idx
=
wl1271_rate_to_idx
(
desc
->
rate
,
desc_
band
);
status
->
rate_idx
=
wl1271_rate_to_idx
(
desc
->
rate
,
status
->
band
);
#ifdef CONFIG_WL12XX_HT
/* 11n support */
...
...
@@ -76,7 +72,8 @@ static void wl1271_rx_status(struct wl1271 *wl,
*/
wl
->
noise
=
desc
->
rssi
-
(
desc
->
snr
>>
1
);
status
->
freq
=
ieee80211_channel_to_frequency
(
desc
->
channel
,
desc_band
);
status
->
freq
=
ieee80211_channel_to_frequency
(
desc
->
channel
,
status
->
band
);
if
(
desc
->
flags
&
WL1271_RX_DESC_ENCRYPT_MASK
)
{
status
->
flag
|=
RX_FLAG_IV_STRIPPED
|
RX_FLAG_MMIC_STRIPPED
;
...
...
@@ -163,18 +160,25 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
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
;
wl1271_write
(
wl
,
WL1271_SLV_REG_DATA
,
&
wl
->
rx_mem_pool_addr
,
sizeof
(
wl
->
rx_mem_pool_addr
),
false
);
if
(
wl
->
chip
.
id
!=
CHIP_ID_1283_PG20
)
{
/*
* 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
;
wl1271_write
(
wl
,
WL1271_SLV_REG_DATA
,
&
wl
->
rx_mem_pool_addr
,
sizeof
(
wl
->
rx_mem_pool_addr
),
false
);
}
/* Read all available packets at once */
wl1271_read
(
wl
,
WL1271_SLV_MEM_DATA
,
wl
->
aggr_buf
,
...
...
drivers/net/wireless/wl12xx/scan.c
View file @
e55034e9
...
...
@@ -48,8 +48,7 @@ void wl1271_scan_complete_work(struct work_struct *work)
goto
out
;
wl
->
scan
.
state
=
WL1271_SCAN_STATE_IDLE
;
kfree
(
wl
->
scan
.
scanned_ch
);
wl
->
scan
.
scanned_ch
=
NULL
;
memset
(
wl
->
scan
.
scanned_ch
,
0
,
sizeof
(
wl
->
scan
.
scanned_ch
));
wl
->
scan
.
req
=
NULL
;
ieee80211_scan_completed
(
wl
->
hw
,
false
);
...
...
@@ -87,7 +86,7 @@ static int wl1271_get_scan_channels(struct wl1271 *wl,
flags
=
req
->
channels
[
i
]
->
flags
;
if
(
!
wl
->
scan
.
scanned_ch
[
i
]
&&
if
(
!
test_bit
(
i
,
wl
->
scan
.
scanned_ch
)
&&
!
(
flags
&
IEEE80211_CHAN_DISABLED
)
&&
((
!!
(
flags
&
IEEE80211_CHAN_PASSIVE_SCAN
))
==
passive
)
&&
(
req
->
channels
[
i
]
->
band
==
band
))
{
...
...
@@ -124,7 +123,7 @@ static int wl1271_get_scan_channels(struct wl1271 *wl,
memset
(
&
channels
[
j
].
bssid_msb
,
0xff
,
2
);
/* Mark the channels we already used */
wl
->
scan
.
scanned_ch
[
i
]
=
true
;
set_bit
(
i
,
wl
->
scan
.
scanned_ch
)
;
j
++
;
}
...
...
@@ -291,6 +290,12 @@ void wl1271_scan_stm(struct wl1271 *wl)
int
wl1271_scan
(
struct
wl1271
*
wl
,
const
u8
*
ssid
,
size_t
ssid_len
,
struct
cfg80211_scan_request
*
req
)
{
/*
* cfg80211 should guarantee that we don't get more channels
* than what we have registered.
*/
BUG_ON
(
req
->
n_channels
>
WL1271_MAX_CHANNELS
);
if
(
wl
->
scan
.
state
!=
WL1271_SCAN_STATE_IDLE
)
return
-
EBUSY
;
...
...
@@ -304,10 +309,8 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
}
wl
->
scan
.
req
=
req
;
memset
(
wl
->
scan
.
scanned_ch
,
0
,
sizeof
(
wl
->
scan
.
scanned_ch
));
wl
->
scan
.
scanned_ch
=
kcalloc
(
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
,
...
...
drivers/net/wireless/wl12xx/sdio.c
View file @
e55034e9
...
...
@@ -51,6 +51,13 @@ static const struct sdio_device_id wl1271_devices[] = {
};
MODULE_DEVICE_TABLE
(
sdio
,
wl1271_devices
);
static
void
wl1271_sdio_set_block_size
(
struct
wl1271
*
wl
,
unsigned
int
blksz
)
{
sdio_claim_host
(
wl
->
if_priv
);
sdio_set_block_size
(
wl
->
if_priv
,
blksz
);
sdio_release_host
(
wl
->
if_priv
);
}
static
inline
struct
sdio_func
*
wl_to_func
(
struct
wl1271
*
wl
)
{
return
wl
->
if_priv
;
...
...
@@ -203,7 +210,8 @@ static struct wl1271_if_operations sdio_ops = {
.
power
=
wl1271_sdio_set_power
,
.
dev
=
wl1271_sdio_wl_to_dev
,
.
enable_irq
=
wl1271_sdio_enable_interrupts
,
.
disable_irq
=
wl1271_sdio_disable_interrupts
.
disable_irq
=
wl1271_sdio_disable_interrupts
,
.
set_block_size
=
wl1271_sdio_set_block_size
,
};
static
int
__devinit
wl1271_probe
(
struct
sdio_func
*
func
,
...
...
@@ -212,6 +220,7 @@ static int __devinit wl1271_probe(struct sdio_func *func,
struct
ieee80211_hw
*
hw
;
const
struct
wl12xx_platform_data
*
wlan_data
;
struct
wl1271
*
wl
;
unsigned
long
irqflags
;
int
ret
;
/* We are only able to handle the wlan function */
...
...
@@ -230,6 +239,9 @@ static int __devinit wl1271_probe(struct sdio_func *func,
/* Grab access to FN0 for ELP reg. */
func
->
card
->
quirks
|=
MMC_QUIRK_LENIENT_FN0
;
/* Use block mode for transferring over one block size of data */
func
->
card
->
quirks
|=
MMC_QUIRK_BLKSZ_FOR_BYTE_MODE
;
wlan_data
=
wl12xx_get_platform_data
();
if
(
IS_ERR
(
wlan_data
))
{
ret
=
PTR_ERR
(
wlan_data
);
...
...
@@ -239,9 +251,16 @@ static int __devinit wl1271_probe(struct sdio_func *func,
wl
->
irq
=
wlan_data
->
irq
;
wl
->
ref_clock
=
wlan_data
->
board_ref_clock
;
wl
->
tcxo_clock
=
wlan_data
->
board_tcxo_clock
;
wl
->
platform_quirks
=
wlan_data
->
platform_quirks
;
if
(
wl
->
platform_quirks
&
WL12XX_PLATFORM_QUIRK_EDGE_IRQ
)
irqflags
=
IRQF_TRIGGER_RISING
;
else
irqflags
=
IRQF_TRIGGER_HIGH
|
IRQF_ONESHOT
;
ret
=
request_threaded_irq
(
wl
->
irq
,
wl1271_hardirq
,
wl1271_irq
,
IRQF_TRIGGER_HIGH
|
IRQF_ONESHOT
,
irqflags
,
DRIVER_NAME
,
wl
);
if
(
ret
<
0
)
{
wl1271_error
(
"request_irq() failed: %d"
,
ret
);
...
...
@@ -343,4 +362,6 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR
(
"Luciano Coelho <coelho@ti.com>"
);
MODULE_AUTHOR
(
"Juuso Oikarinen <juuso.oikarinen@nokia.com>"
);
MODULE_FIRMWARE
(
WL1271_FW_NAME
);
MODULE_FIRMWARE
(
WL1271_AP_FW_NAME
);
MODULE_FIRMWARE
(
WL128X_FW_NAME
);
MODULE_FIRMWARE
(
WL127X_AP_FW_NAME
);
MODULE_FIRMWARE
(
WL128X_AP_FW_NAME
);
drivers/net/wireless/wl12xx/sdio_test.c
View file @
e55034e9
...
...
@@ -189,7 +189,12 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
const
struct
firmware
*
fw
;
int
ret
;
ret
=
request_firmware
(
&
fw
,
WL1271_FW_NAME
,
wl1271_wl_to_dev
(
wl
));
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
ret
=
request_firmware
(
&
fw
,
WL128X_FW_NAME
,
wl1271_wl_to_dev
(
wl
));
else
ret
=
request_firmware
(
&
fw
,
WL1271_FW_NAME
,
wl1271_wl_to_dev
(
wl
));
if
(
ret
<
0
)
{
wl1271_error
(
"could not get firmware: %d"
,
ret
);
...
...
@@ -227,14 +232,14 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
const
struct
firmware
*
fw
;
int
ret
;
ret
=
request_firmware
(
&
fw
,
WL12
71
_NVS_NAME
,
wl1271_wl_to_dev
(
wl
));
ret
=
request_firmware
(
&
fw
,
WL12
XX
_NVS_NAME
,
wl1271_wl_to_dev
(
wl
));
if
(
ret
<
0
)
{
wl1271_error
(
"could not get nvs file: %d"
,
ret
);
return
ret
;
}
wl
->
nvs
=
kmemdup
(
fw
->
data
,
sizeof
(
struct
wl1271_nvs_file
)
,
GFP_KERNEL
);
wl
->
nvs
=
kmemdup
(
fw
->
data
,
fw
->
size
,
GFP_KERNEL
);
if
(
!
wl
->
nvs
)
{
wl1271_error
(
"could not allocate memory for the nvs file"
);
...
...
@@ -288,6 +293,11 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
wl1271_notice
(
"chip id 0x%x (1271 PG20)"
,
wl
->
chip
.
id
);
break
;
case
CHIP_ID_1283_PG20
:
wl1271_notice
(
"chip id 0x%x (1283 PG20)"
,
wl
->
chip
.
id
);
break
;
case
CHIP_ID_1283_PG10
:
default:
wl1271_warning
(
"unsupported chip id: 0x%x"
,
wl
->
chip
.
id
);
return
-
ENODEV
;
...
...
@@ -407,6 +417,9 @@ static int __devinit wl1271_probe(struct sdio_func *func,
/* Grab access to FN0 for ELP reg. */
func
->
card
->
quirks
|=
MMC_QUIRK_LENIENT_FN0
;
/* Use block mode for transferring over one block size of data */
func
->
card
->
quirks
|=
MMC_QUIRK_BLKSZ_FOR_BYTE_MODE
;
wlan_data
=
wl12xx_get_platform_data
();
if
(
IS_ERR
(
wlan_data
))
{
ret
=
PTR_ERR
(
wlan_data
);
...
...
@@ -416,6 +429,7 @@ static int __devinit wl1271_probe(struct sdio_func *func,
wl
->
irq
=
wlan_data
->
irq
;
wl
->
ref_clock
=
wlan_data
->
board_ref_clock
;
wl
->
tcxo_clock
=
wlan_data
->
board_tcxo_clock
;
sdio_set_drvdata
(
func
,
wl_test
);
...
...
drivers/net/wireless/wl12xx/spi.c
View file @
e55034e9
...
...
@@ -355,7 +355,8 @@ static struct wl1271_if_operations spi_ops = {
.
power
=
wl1271_spi_set_power
,
.
dev
=
wl1271_spi_wl_to_dev
,
.
enable_irq
=
wl1271_spi_enable_interrupts
,
.
disable_irq
=
wl1271_spi_disable_interrupts
.
disable_irq
=
wl1271_spi_disable_interrupts
,
.
set_block_size
=
NULL
,
};
static
int
__devinit
wl1271_probe
(
struct
spi_device
*
spi
)
...
...
@@ -363,6 +364,7 @@ static int __devinit wl1271_probe(struct spi_device *spi)
struct
wl12xx_platform_data
*
pdata
;
struct
ieee80211_hw
*
hw
;
struct
wl1271
*
wl
;
unsigned
long
irqflags
;
int
ret
;
pdata
=
spi
->
dev
.
platform_data
;
...
...
@@ -400,6 +402,13 @@ static int __devinit wl1271_probe(struct spi_device *spi)
}
wl
->
ref_clock
=
pdata
->
board_ref_clock
;
wl
->
tcxo_clock
=
pdata
->
board_tcxo_clock
;
wl
->
platform_quirks
=
pdata
->
platform_quirks
;
if
(
wl
->
platform_quirks
&
WL12XX_PLATFORM_QUIRK_EDGE_IRQ
)
irqflags
=
IRQF_TRIGGER_RISING
;
else
irqflags
=
IRQF_TRIGGER_HIGH
|
IRQF_ONESHOT
;
wl
->
irq
=
spi
->
irq
;
if
(
wl
->
irq
<
0
)
{
...
...
@@ -409,7 +418,7 @@ static int __devinit wl1271_probe(struct spi_device *spi)
}
ret
=
request_threaded_irq
(
wl
->
irq
,
wl1271_hardirq
,
wl1271_irq
,
IRQF_TRIGGER_HIGH
|
IRQF_ONESHOT
,
irqflags
,
DRIVER_NAME
,
wl
);
if
(
ret
<
0
)
{
wl1271_error
(
"request_irq() failed: %d"
,
ret
);
...
...
@@ -490,5 +499,7 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR
(
"Luciano Coelho <coelho@ti.com>"
);
MODULE_AUTHOR
(
"Juuso Oikarinen <juuso.oikarinen@nokia.com>"
);
MODULE_FIRMWARE
(
WL1271_FW_NAME
);
MODULE_FIRMWARE
(
WL1271_AP_FW_NAME
);
MODULE_FIRMWARE
(
WL128X_FW_NAME
);
MODULE_FIRMWARE
(
WL127X_AP_FW_NAME
);
MODULE_FIRMWARE
(
WL128X_AP_FW_NAME
);
MODULE_ALIAS
(
"spi:wl1271"
);
drivers/net/wireless/wl12xx/testmode.c
View file @
e55034e9
...
...
@@ -27,6 +27,7 @@
#include "wl12xx.h"
#include "acx.h"
#include "reg.h"
#define WL1271_TM_MAX_DATA_LENGTH 1024
...
...
@@ -204,7 +205,10 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[])
kfree
(
wl
->
nvs
);
if
(
len
!=
sizeof
(
struct
wl1271_nvs_file
))
if
((
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
&&
(
len
!=
sizeof
(
struct
wl128x_nvs_file
)))
return
-
EINVAL
;
else
if
(
len
!=
sizeof
(
struct
wl1271_nvs_file
))
return
-
EINVAL
;
wl
->
nvs
=
kzalloc
(
len
,
GFP_KERNEL
);
...
...
drivers/net/wireless/wl12xx/tx.c
View file @
e55034e9
...
...
@@ -70,6 +70,28 @@ static void wl1271_free_tx_id(struct wl1271 *wl, int id)
}
}
static
int
wl1271_tx_update_filters
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
)
{
struct
ieee80211_hdr
*
hdr
;
hdr
=
(
struct
ieee80211_hdr
*
)(
skb
->
data
+
sizeof
(
struct
wl1271_tx_hw_descr
));
/*
* stop bssid-based filtering before transmitting authentication
* requests. this way the hw will never drop authentication
* responses coming from BSSIDs it isn't familiar with (e.g. on
* roaming)
*/
if
(
!
ieee80211_is_auth
(
hdr
->
frame_control
))
return
0
;
wl1271_configure_filters
(
wl
,
FIF_OTHER_BSS
);
return
wl1271_acx_rx_config
(
wl
,
wl
->
rx_config
,
wl
->
rx_filter
);
}
static
void
wl1271_tx_ap_update_inconnection_sta
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
)
{
...
...
@@ -127,13 +149,29 @@ u8 wl1271_tx_get_hlid(struct sk_buff *skb)
}
}
static
unsigned
int
wl12xx_calc_packet_alignment
(
struct
wl1271
*
wl
,
unsigned
int
packet_length
)
{
if
(
wl
->
quirks
&
WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT
)
return
ALIGN
(
packet_length
,
WL12XX_BUS_BLOCK_SIZE
);
else
return
ALIGN
(
packet_length
,
WL1271_TX_ALIGN_TO
);
}
static
int
wl1271_tx_allocate
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
,
u32
extra
,
u32
buf_offset
,
u8
hlid
)
{
struct
wl1271_tx_hw_descr
*
desc
;
u32
total_len
=
skb
->
len
+
sizeof
(
struct
wl1271_tx_hw_descr
)
+
extra
;
u32
len
;
u32
total_blocks
;
int
id
,
ret
=
-
EBUSY
;
u32
spare_blocks
;
if
(
unlikely
(
wl
->
quirks
&
WL12XX_QUIRK_USE_2_SPARE_BLOCKS
))
spare_blocks
=
2
;
else
spare_blocks
=
1
;
if
(
buf_offset
+
total_len
>
WL1271_AGGR_BUFFER_SIZE
)
return
-
EAGAIN
;
...
...
@@ -145,17 +183,27 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
/* approximate the number of blocks required for this packet
in the firmware */
total_blocks
=
total_len
+
TX_HW_BLOCK_SIZE
-
1
;
total_blocks
=
total_blocks
/
TX_HW_BLOCK_SIZE
+
TX_HW_BLOCK_SPARE
;
len
=
wl12xx_calc_packet_alignment
(
wl
,
total_len
);
total_blocks
=
(
len
+
TX_HW_BLOCK_SIZE
-
1
)
/
TX_HW_BLOCK_SIZE
+
spare_blocks
;
if
(
total_blocks
<=
wl
->
tx_blocks_available
)
{
desc
=
(
struct
wl1271_tx_hw_descr
*
)
skb_push
(
skb
,
total_len
-
skb
->
len
);
desc
->
extra_mem_blocks
=
TX_HW_BLOCK_SPARE
;
desc
->
total_mem_blocks
=
total_blocks
;
/* HW descriptor fields change between wl127x and wl128x */
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
{
desc
->
wl128x_mem
.
total_mem_blocks
=
total_blocks
;
}
else
{
desc
->
wl127x_mem
.
extra_blocks
=
spare_blocks
;
desc
->
wl127x_mem
.
total_mem_blocks
=
total_blocks
;
}
desc
->
id
=
id
;
wl
->
tx_blocks_available
-=
total_blocks
;
wl
->
tx_allocated_blocks
+=
total_blocks
;
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
wl
->
links
[
hlid
].
allocated_blks
+=
total_blocks
;
...
...
@@ -172,13 +220,18 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
return
ret
;
}
static
bool
wl12xx_is_dummy_packet
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
)
{
return
wl
->
dummy_packet
==
skb
;
}
static
void
wl1271_tx_fill_hdr
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
,
u32
extra
,
struct
ieee80211_tx_info
*
control
,
u8
hlid
)
{
struct
timespec
ts
;
struct
wl1271_tx_hw_descr
*
desc
;
int
pad
,
ac
,
rate_idx
;
int
aligned_len
,
ac
,
rate_idx
;
s64
hosttime
;
u16
tx_attr
;
...
...
@@ -202,12 +255,25 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
else
desc
->
life_time
=
cpu_to_le16
(
TX_HW_AP_MODE_PKT_LIFETIME_TU
);
/* configure the tx attributes */
tx_attr
=
wl
->
session_counter
<<
TX_HW_ATTR_OFST_SESSION_COUNTER
;
/* queue (we use same identifiers for tid's and ac's */
/* queue */
ac
=
wl1271_tx_get_queue
(
skb_get_queue_mapping
(
skb
));
desc
->
tid
=
ac
;
desc
->
tid
=
skb
->
priority
;
if
(
wl12xx_is_dummy_packet
(
wl
,
skb
))
{
/*
* FW expects the dummy packet to have an invalid session id -
* any session id that is different than the one set in the join
*/
tx_attr
=
((
~
wl
->
session_counter
)
<<
TX_HW_ATTR_OFST_SESSION_COUNTER
)
&
TX_HW_ATTR_SESSION_COUNTER
;
tx_attr
|=
TX_HW_ATTR_TX_DUMMY_REQ
;
}
else
{
/* configure the tx attributes */
tx_attr
=
wl
->
session_counter
<<
TX_HW_ATTR_OFST_SESSION_COUNTER
;
}
if
(
wl
->
bss_type
!=
BSS_TYPE_AP_BSS
)
{
desc
->
aid
=
hlid
;
...
...
@@ -237,20 +303,37 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
tx_attr
|=
rate_idx
<<
TX_HW_ATTR_OFST_RATE_POLICY
;
desc
->
reserved
=
0
;
/* align the length (and store in terms of words) */
pad
=
ALIGN
(
skb
->
len
,
WL1271_TX_ALIGN_TO
);
desc
->
length
=
cpu_to_le16
(
pad
>>
2
);
aligned_len
=
wl12xx_calc_packet_alignment
(
wl
,
skb
->
len
);
/* calculate number of padding bytes */
pad
=
pad
-
skb
->
len
;
tx_attr
|=
pad
<<
TX_HW_ATTR_OFST_LAST_WORD_PAD
;
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
{
desc
->
wl128x_mem
.
extra_bytes
=
aligned_len
-
skb
->
len
;
desc
->
length
=
cpu_to_le16
(
aligned_len
>>
2
)
;
desc
->
tx_attr
=
cpu_to_le16
(
tx_attr
);
wl1271_debug
(
DEBUG_TX
,
"tx_fill_hdr: hlid: %d "
"tx_attr: 0x%x len: %d life: %d mem: %d"
,
desc
->
hlid
,
tx_attr
,
le16_to_cpu
(
desc
->
length
),
le16_to_cpu
(
desc
->
life_time
),
desc
->
wl128x_mem
.
total_mem_blocks
);
}
else
{
int
pad
;
/* Store the aligned length in terms of words */
desc
->
length
=
cpu_to_le16
(
aligned_len
>>
2
);
/* calculate number of padding bytes */
pad
=
aligned_len
-
skb
->
len
;
tx_attr
|=
pad
<<
TX_HW_ATTR_OFST_LAST_WORD_PAD
;
wl1271_debug
(
DEBUG_TX
,
"tx_fill_hdr: pad: %d hlid: %d "
"tx_attr: 0x%x len: %d life: %d mem: %d"
,
pad
,
desc
->
hlid
,
le16_to_cpu
(
desc
->
tx_attr
),
le16_to_cpu
(
desc
->
length
),
le16_to_cpu
(
desc
->
life_time
),
desc
->
total_mem_blocks
);
wl1271_debug
(
DEBUG_TX
,
"tx_fill_hdr: pad: %d hlid: %d "
"tx_attr: 0x%x len: %d life: %d mem: %d"
,
pad
,
desc
->
hlid
,
tx_attr
,
le16_to_cpu
(
desc
->
length
),
le16_to_cpu
(
desc
->
life_time
),
desc
->
wl127x_mem
.
total_mem_blocks
);
}
desc
->
tx_attr
=
cpu_to_le16
(
tx_attr
);
}
/* caller must hold wl->mutex */
...
...
@@ -300,19 +383,29 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
{
wl1271_tx_ap_update_inconnection_sta
(
wl
,
skb
);
wl1271_tx_regulate_link
(
wl
,
hlid
);
}
else
{
wl1271_tx_update_filters
(
wl
,
skb
);
}
wl1271_tx_fill_hdr
(
wl
,
skb
,
extra
,
info
,
hlid
);
/*
* 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
* 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.
* In special cases, we want to align to a specific block size
* (eg. for wl128x with SDIO we align to 256).
*/
total_len
=
ALIGN
(
skb
->
len
,
WL1271_TX_ALIGN_TO
);
total_len
=
wl12xx_calc_packet_alignment
(
wl
,
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
);
/* Revert side effects in the dummy packet skb, so it can be reused */
if
(
wl12xx_is_dummy_packet
(
wl
,
skb
))
skb_pull
(
skb
,
sizeof
(
struct
wl1271_tx_hw_descr
));
return
total_len
;
}
...
...
@@ -425,10 +518,23 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl)
static
struct
sk_buff
*
wl1271_skb_dequeue
(
struct
wl1271
*
wl
)
{
unsigned
long
flags
;
struct
sk_buff
*
skb
=
NULL
;
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
return
wl1271_ap_skb_dequeue
(
wl
);
skb
=
wl1271_ap_skb_dequeue
(
wl
);
else
skb
=
wl1271_sta_skb_dequeue
(
wl
);
if
(
!
skb
&&
test_and_clear_bit
(
WL1271_FLAG_DUMMY_PACKET_PENDING
,
&
wl
->
flags
))
{
skb
=
wl
->
dummy_packet
;
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
wl
->
tx_queue_count
--
;
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
}
return
wl1271_sta_skb_dequeue
(
wl
)
;
return
skb
;
}
static
void
wl1271_skb_queue_head
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
)
...
...
@@ -436,7 +542,9 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb)
unsigned
long
flags
;
int
q
=
wl1271_tx_get_queue
(
skb_get_queue_mapping
(
skb
));
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
{
if
(
wl12xx_is_dummy_packet
(
wl
,
skb
))
{
set_bit
(
WL1271_FLAG_DUMMY_PACKET_PENDING
,
&
wl
->
flags
);
}
else
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
{
u8
hlid
=
wl1271_tx_get_hlid
(
skb
);
skb_queue_head
(
&
wl
->
links
[
hlid
].
tx_queue
[
q
],
skb
);
...
...
@@ -454,22 +562,14 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb)
void
wl1271_tx_work_locked
(
struct
wl1271
*
wl
)
{
struct
sk_buff
*
skb
;
bool
woken_up
=
false
;
u32
buf_offset
=
0
;
bool
sent_packets
=
false
;
int
ret
;
if
(
unlikely
(
wl
->
state
==
WL1271_STATE_OFF
))
goto
out
;
return
;
while
((
skb
=
wl1271_skb_dequeue
(
wl
)))
{
if
(
!
woken_up
)
{
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out_ack
;
woken_up
=
true
;
}
ret
=
wl1271_prepare_tx_frame
(
wl
,
skb
,
buf_offset
);
if
(
ret
==
-
EAGAIN
)
{
/*
...
...
@@ -516,18 +616,22 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
wl1271_handle_tx_low_watermark
(
wl
);
}
out:
if
(
woken_up
)
wl1271_ps_elp_sleep
(
wl
);
}
void
wl1271_tx_work
(
struct
work_struct
*
work
)
{
struct
wl1271
*
wl
=
container_of
(
work
,
struct
wl1271
,
tx_work
);
int
ret
;
mutex_lock
(
&
wl
->
mutex
);
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out
;
wl1271_tx_work_locked
(
wl
);
wl1271_ps_elp_wakeup
(
wl
);
out:
mutex_unlock
(
&
wl
->
mutex
);
}
...
...
@@ -549,6 +653,11 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
skb
=
wl
->
tx_frames
[
id
];
info
=
IEEE80211_SKB_CB
(
skb
);
if
(
wl12xx_is_dummy_packet
(
wl
,
skb
))
{
wl1271_free_tx_id
(
wl
,
id
);
return
;
}
/* update the TX status info */
if
(
result
->
status
==
TX_SUCCESS
)
{
if
(
!
(
info
->
flags
&
IEEE80211_TX_CTL_NO_ACK
))
...
...
@@ -678,10 +787,13 @@ void wl1271_tx_reset(struct wl1271 *wl)
while
((
skb
=
skb_dequeue
(
&
wl
->
tx_queue
[
i
])))
{
wl1271_debug
(
DEBUG_TX
,
"freeing skb 0x%p"
,
skb
);
info
=
IEEE80211_SKB_CB
(
skb
);
info
->
status
.
rates
[
0
].
idx
=
-
1
;
info
->
status
.
rates
[
0
].
count
=
0
;
ieee80211_tx_status
(
wl
->
hw
,
skb
);
if
(
!
wl12xx_is_dummy_packet
(
wl
,
skb
))
{
info
=
IEEE80211_SKB_CB
(
skb
);
info
->
status
.
rates
[
0
].
idx
=
-
1
;
info
->
status
.
rates
[
0
].
count
=
0
;
ieee80211_tx_status
(
wl
->
hw
,
skb
);
}
}
}
}
...
...
@@ -702,21 +814,27 @@ void wl1271_tx_reset(struct wl1271 *wl)
wl1271_free_tx_id
(
wl
,
i
);
wl1271_debug
(
DEBUG_TX
,
"freeing skb 0x%p"
,
skb
);
/* Remove private headers before passing the skb to mac80211 */
info
=
IEEE80211_SKB_CB
(
skb
);
skb_pull
(
skb
,
sizeof
(
struct
wl1271_tx_hw_descr
));
if
(
info
->
control
.
hw_key
&&
info
->
control
.
hw_key
->
cipher
==
WLAN_CIPHER_SUITE_TKIP
)
{
int
hdrlen
=
ieee80211_get_hdrlen_from_skb
(
skb
);
memmove
(
skb
->
data
+
WL1271_TKIP_IV_SPACE
,
skb
->
data
,
hdrlen
);
skb_pull
(
skb
,
WL1271_TKIP_IV_SPACE
);
}
if
(
!
wl12xx_is_dummy_packet
(
wl
,
skb
))
{
/*
* Remove private headers before passing the skb to
* mac80211
*/
info
=
IEEE80211_SKB_CB
(
skb
);
skb_pull
(
skb
,
sizeof
(
struct
wl1271_tx_hw_descr
));
if
(
info
->
control
.
hw_key
&&
info
->
control
.
hw_key
->
cipher
==
WLAN_CIPHER_SUITE_TKIP
)
{
int
hdrlen
=
ieee80211_get_hdrlen_from_skb
(
skb
);
memmove
(
skb
->
data
+
WL1271_TKIP_IV_SPACE
,
skb
->
data
,
hdrlen
);
skb_pull
(
skb
,
WL1271_TKIP_IV_SPACE
);
}
info
->
status
.
rates
[
0
].
idx
=
-
1
;
info
->
status
.
rates
[
0
].
count
=
0
;
info
->
status
.
rates
[
0
].
idx
=
-
1
;
info
->
status
.
rates
[
0
].
count
=
0
;
ieee80211_tx_status
(
wl
->
hw
,
skb
);
ieee80211_tx_status
(
wl
->
hw
,
skb
);
}
}
}
...
...
drivers/net/wireless/wl12xx/tx.h
View file @
e55034e9
...
...
@@ -25,7 +25,6 @@
#ifndef __TX_H__
#define __TX_H__
#define TX_HW_BLOCK_SPARE 2
#define TX_HW_BLOCK_SIZE 252
#define TX_HW_MGMT_PKT_LIFETIME_TU 2000
...
...
@@ -41,6 +40,7 @@
BIT(8) | BIT(9))
#define TX_HW_ATTR_LAST_WORD_PAD (BIT(10) | BIT(11))
#define TX_HW_ATTR_TX_CMPLT_REQ BIT(12)
#define TX_HW_ATTR_TX_DUMMY_REQ BIT(13)
#define TX_HW_ATTR_OFST_SAVE_RETRIES 0
#define TX_HW_ATTR_OFST_HEADER_PAD 1
...
...
@@ -55,20 +55,60 @@
#define WL1271_TX_ALIGN_TO 4
#define WL1271_TKIP_IV_SPACE 4
/* Used for management frames and dummy packets */
#define WL1271_TID_MGMT 7
struct
wl127x_tx_mem
{
/*
* Number of extra memory blocks to allocate for this packet
* in addition to the number of blocks derived from the packet
* length.
*/
u8
extra_blocks
;
/*
* Total number of memory blocks allocated by the host for
* this packet. Must be equal or greater than the actual
* blocks number allocated by HW.
*/
u8
total_mem_blocks
;
}
__packed
;
struct
wl128x_tx_mem
{
/*
* Total number of memory blocks allocated by the host for
* this packet.
*/
u8
total_mem_blocks
;
/*
* Number of extra bytes, at the end of the frame. the host
* uses this padding to complete each frame to integer number
* of SDIO blocks.
*/
u8
extra_bytes
;
}
__packed
;
/*
* On wl128x based devices, when TX packets are aggregated, each packet
* size must be aligned to the SDIO block size. The maximum block size
* is bounded by the type of the padded bytes field that is sent to the
* FW. Currently the type is u8, so the maximum block size is 256 bytes.
*/
#define WL12XX_BUS_BLOCK_SIZE min(512u, \
(1u << (8 * sizeof(((struct wl128x_tx_mem *) 0)->extra_bytes))))
struct
wl1271_tx_hw_descr
{
/* Length of packet in words, including descriptor+header+data */
__le16
length
;
/* Number of extra memory blocks to allocate for this packet in
addition to the number of blocks derived from the packet length */
u8
extra_mem_blocks
;
/* Total number of memory blocks allocated by the host for this packet.
Must be equal or greater than the actual blocks number allocated by
HW!! */
u8
total_mem_blocks
;
union
{
struct
wl127x_tx_mem
wl127x_mem
;
struct
wl128x_tx_mem
wl128x_mem
;
}
__packed
;
/* Device time (in us) when the packet arrived to the driver */
__le32
start_time
;
/* Max delay in TUs until transmission. The last device time the
packet can be transmitted is: startTime+(1024*LifeTime) */
/*
* Max delay in TUs until transmission. The last device time the
* packet can be transmitted is: start_time + (1024 * life_time)
*/
__le16
life_time
;
/* Bitwise fields - see TX_ATTR... definitions above. */
__le16
tx_attr
;
...
...
drivers/net/wireless/wl12xx/wl12xx.h
View file @
e55034e9
...
...
@@ -131,9 +131,16 @@ extern u32 wl12xx_debug_level;
#define WL1271_FW_NAME "ti-connectivity/wl1271-fw-2.bin"
#define WL1271_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin"
#define WL128X_FW_NAME "ti-connectivity/wl128x-fw.bin"
#define WL127X_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin"
#define WL128X_AP_FW_NAME "ti-connectivity/wl128x-fw-ap.bin"
#define WL1271_NVS_NAME "ti-connectivity/wl1271-nvs.bin"
/*
* wl127x and wl128x are using the same NVS file name. However, the
* ini parameters between them are different. The driver validates
* the correct NVS size in wl1271_boot_upload_nvs().
*/
#define WL12XX_NVS_NAME "ti-connectivity/wl1271-nvs.bin"
#define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
#define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
...
...
@@ -200,13 +207,29 @@ struct wl1271_partition_set {
struct
wl1271
;
#define WL12XX_NUM_FW_VER 5
enum
{
FW_VER_CHIP
,
FW_VER_IF_TYPE
,
FW_VER_MAJOR
,
FW_VER_SUBTYPE
,
FW_VER_MINOR
,
NUM_FW_VER
};
#define FW_VER_CHIP_WL127X 6
#define FW_VER_CHIP_WL128X 7
#define FW_VER_IF_TYPE_STA 1
#define FW_VER_IF_TYPE_AP 2
#define FW_VER_MINOR_1_SPARE_STA_MIN 58
#define FW_VER_MINOR_1_SPARE_AP_MIN 47
/* FIXME: I'm not sure about this structure name */
struct
wl1271_chip
{
u32
id
;
char
fw_ver_str
[
ETHTOOL_BUSINFO_LEN
];
unsigned
int
fw_ver
[
WL12XX_
NUM_FW_VER
];
unsigned
int
fw_ver
[
NUM_FW_VER
];
};
struct
wl1271_stats
{
...
...
@@ -261,6 +284,8 @@ struct wl1271_fw_sta_status {
u8
tx_total
;
u8
reserved1
;
__le16
reserved2
;
/* Total structure size is 68 bytes */
u32
padding
;
}
__packed
;
struct
wl1271_fw_full_status
{
...
...
@@ -277,9 +302,10 @@ struct wl1271_rx_mem_pool_addr {
u32
addr_extra
;
};
#define WL1271_MAX_CHANNELS 64
struct
wl1271_scan
{
struct
cfg80211_scan_request
*
req
;
bool
*
scanned_ch
;
unsigned
long
scanned_ch
[
BITS_TO_LONGS
(
WL1271_MAX_CHANNELS
)]
;
bool
failed
;
u8
state
;
u8
ssid
[
IW_ESSID_MAX_SIZE
+
1
];
...
...
@@ -297,6 +323,7 @@ struct wl1271_if_operations {
struct
device
*
(
*
dev
)(
struct
wl1271
*
wl
);
void
(
*
enable_irq
)(
struct
wl1271
*
wl
);
void
(
*
disable_irq
)(
struct
wl1271
*
wl
);
void
(
*
set_block_size
)
(
struct
wl1271
*
wl
,
unsigned
int
blksz
);
};
#define MAX_NUM_KEYS 14
...
...
@@ -327,7 +354,9 @@ enum wl12xx_flags {
WL1271_FLAG_PSPOLL_FAILURE
,
WL1271_FLAG_STA_STATE_SENT
,
WL1271_FLAG_FW_TX_BUSY
,
WL1271_FLAG_AP_STARTED
WL1271_FLAG_AP_STARTED
,
WL1271_FLAG_IF_INITIALIZED
,
WL1271_FLAG_DUMMY_PACKET_PENDING
,
};
struct
wl1271_link
{
...
...
@@ -371,7 +400,7 @@ struct wl1271 {
u8
*
fw
;
size_t
fw_len
;
u8
fw_bss_type
;
struct
wl1271_nvs_file
*
nvs
;
void
*
nvs
;
size_t
nvs_len
;
s8
hw_pg_ver
;
...
...
@@ -389,6 +418,7 @@ struct wl1271 {
/* Accounting for allocated / available TX blocks on HW */
u32
tx_blocks_freed
[
NUM_TX_QUEUES
];
u32
tx_blocks_available
;
u32
tx_allocated_blocks
;
u32
tx_results_count
;
/* Transmitted TX packets counter for chipset interface */
...
...
@@ -430,6 +460,9 @@ struct wl1271 {
/* Intermediate buffer, used for packet aggregation */
u8
*
aggr_buf
;
/* Reusable dummy packet template */
struct
sk_buff
*
dummy_packet
;
/* Network stack work */
struct
work_struct
netstack_work
;
...
...
@@ -527,6 +560,8 @@ struct wl1271 {
bool
ba_support
;
u8
ba_rx_bitmap
;
int
tcxo_clock
;
/*
* AP-mode - links indexed by HLID. The global and broadcast links
* are always active.
...
...
@@ -544,6 +579,9 @@ struct wl1271 {
/* Quirks of specific hardware revisions */
unsigned
int
quirks
;
/* Platform limitations */
unsigned
int
platform_quirks
;
};
struct
wl1271_station
{
...
...
@@ -576,6 +614,15 @@ int wl1271_plt_stop(struct wl1271 *wl);
/* Quirks */
/* Each RX/TX transaction requires an end-of-transaction transfer */
#define WL12XX_QUIRK_END_OF_TRANSACTION BIT(0)
#define WL12XX_QUIRK_END_OF_TRANSACTION BIT(0)
/*
* Older firmwares use 2 spare TX blocks
* (for STA < 6.1.3.50.58 or for AP < 6.2.0.0.47)
*/
#define WL12XX_QUIRK_USE_2_SPARE_BLOCKS BIT(1)
/* WL128X requires aggregated packets to be aligned to the SDIO block size */
#define WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT BIT(2)
#endif
include/linux/wl12xx.h
View file @
e55034e9
...
...
@@ -24,12 +24,26 @@
#ifndef _LINUX_WL12XX_H
#define _LINUX_WL12XX_H
/*
The board r
eference clock values */
/*
R
eference clock values */
enum
{
WL12XX_REFCLOCK_19
=
0
,
/* 19.2 MHz */
WL12XX_REFCLOCK_26
=
1
,
/* 26 MHz */
WL12XX_REFCLOCK_38
=
2
,
/* 38.4 MHz */
WL12XX_REFCLOCK_54
=
3
,
/* 54 MHz */
WL12XX_REFCLOCK_19
=
0
,
/* 19.2 MHz */
WL12XX_REFCLOCK_26
=
1
,
/* 26 MHz */
WL12XX_REFCLOCK_38
=
2
,
/* 38.4 MHz */
WL12XX_REFCLOCK_52
=
3
,
/* 52 MHz */
WL12XX_REFCLOCK_38_XTAL
=
4
,
/* 38.4 MHz, XTAL */
WL12XX_REFCLOCK_26_XTAL
=
5
,
/* 26 MHz, XTAL */
};
/* TCXO clock values */
enum
{
WL12XX_TCXOCLOCK_19_2
=
0
,
/* 19.2MHz */
WL12XX_TCXOCLOCK_26
=
1
,
/* 26 MHz */
WL12XX_TCXOCLOCK_38_4
=
2
,
/* 38.4MHz */
WL12XX_TCXOCLOCK_52
=
3
,
/* 52 MHz */
WL12XX_TCXOCLOCK_16_368
=
4
,
/* 16.368 MHz */
WL12XX_TCXOCLOCK_32_736
=
5
,
/* 32.736 MHz */
WL12XX_TCXOCLOCK_16_8
=
6
,
/* 16.8 MHz */
WL12XX_TCXOCLOCK_33_6
=
7
,
/* 33.6 MHz */
};
struct
wl12xx_platform_data
{
...
...
@@ -38,8 +52,13 @@ struct wl12xx_platform_data {
int
irq
;
bool
use_eeprom
;
int
board_ref_clock
;
int
board_tcxo_clock
;
unsigned
long
platform_quirks
;
};
/* Platform does not support level trigger interrupts */
#define WL12XX_PLATFORM_QUIRK_EDGE_IRQ BIT(0)
#ifdef CONFIG_WL12XX_PLATFORM_DATA
int
wl12xx_set_platform_data
(
const
struct
wl12xx_platform_data
*
data
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment