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
46bf6958
Commit
46bf6958
authored
Oct 05, 2010
by
John W. Linville
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'wireless-next' of
git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx
parents
e7480bbb
4b48e687
Changes
23
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
784 additions
and
538 deletions
+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
No files found.
MAINTAINERS
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
46bf6958
...
...
@@ -124,28 +124,28 @@ static struct conf_drv_settings default_conf = {
},
.
ac_conf_count
=
4
,
.
ac_conf
=
{
[
0
]
=
{
[
CONF_TX_AC_BE
]
=
{
.
ac
=
CONF_TX_AC_BE
,
.
cw_min
=
15
,
.
cw_max
=
63
,
.
aifsn
=
3
,
.
tx_op_limit
=
0
,
},
[
1
]
=
{
[
CONF_TX_AC_BK
]
=
{
.
ac
=
CONF_TX_AC_BK
,
.
cw_min
=
15
,
.
cw_max
=
63
,
.
aifsn
=
7
,
.
tx_op_limit
=
0
,
},
[
2
]
=
{
[
CONF_TX_AC_VI
]
=
{
.
ac
=
CONF_TX_AC_VI
,
.
cw_min
=
15
,
.
cw_max
=
63
,
.
aifsn
=
CONF_TX_AIFS_PIFS
,
.
tx_op_limit
=
3008
,
},
[
3
]
=
{
[
CONF_TX_AC_VO
]
=
{
.
ac
=
CONF_TX_AC_VO
,
.
cw_min
=
15
,
.
cw_max
=
63
,
...
...
@@ -153,64 +153,40 @@ static struct conf_drv_settings default_conf = {
.
tx_op_limit
=
1504
,
},
},
.
tid_conf_count
=
7
,
.
tid_conf_count
=
4
,
.
tid_conf
=
{
[
0
]
=
{
.
queue_id
=
0
,
.
channel_type
=
CONF_CHANNEL_TYPE_DCF
,
.
tsid
=
CONF_TX_AC_BE
,
.
ps_scheme
=
CONF_PS_SCHEME_LEGACY
,
.
ack_policy
=
CONF_ACK_POLICY_LEGACY
,
.
apsd_conf
=
{
0
,
0
},
},
[
1
]
=
{
.
queue_id
=
1
,
.
channel_type
=
CONF_CHANNEL_TYPE_DCF
,
[
CONF_TX_AC_BE
]
=
{
.
queue_id
=
CONF_TX_AC_BE
,
.
channel_type
=
CONF_CHANNEL_TYPE_EDCF
,
.
tsid
=
CONF_TX_AC_BE
,
.
ps_scheme
=
CONF_PS_SCHEME_LEGACY
,
.
ack_policy
=
CONF_ACK_POLICY_LEGACY
,
.
apsd_conf
=
{
0
,
0
},
},
[
2
]
=
{
.
queue_id
=
2
,
.
channel_type
=
CONF_CHANNEL_TYPE_DCF
,
.
tsid
=
CONF_TX_AC_B
E
,
[
CONF_TX_AC_BK
]
=
{
.
queue_id
=
CONF_TX_AC_BK
,
.
channel_type
=
CONF_CHANNEL_TYPE_
E
DCF
,
.
tsid
=
CONF_TX_AC_B
K
,
.
ps_scheme
=
CONF_PS_SCHEME_LEGACY
,
.
ack_policy
=
CONF_ACK_POLICY_LEGACY
,
.
apsd_conf
=
{
0
,
0
},
},
[
3
]
=
{
.
queue_id
=
3
,
.
channel_type
=
CONF_CHANNEL_TYPE_DCF
,
.
tsid
=
CONF_TX_AC_BE
,
.
ps_scheme
=
CONF_PS_SCHEME_LEGACY
,
.
ack_policy
=
CONF_ACK_POLICY_LEGACY
,
.
apsd_conf
=
{
0
,
0
},
},
[
4
]
=
{
.
queue_id
=
4
,
.
channel_type
=
CONF_CHANNEL_TYPE_DCF
,
.
tsid
=
CONF_TX_AC_BE
,
[
CONF_TX_AC_VI
]
=
{
.
queue_id
=
CONF_TX_AC_VI
,
.
channel_type
=
CONF_CHANNEL_TYPE_EDCF
,
.
tsid
=
CONF_TX_AC_VI
,
.
ps_scheme
=
CONF_PS_SCHEME_LEGACY
,
.
ack_policy
=
CONF_ACK_POLICY_LEGACY
,
.
apsd_conf
=
{
0
,
0
},
},
[
5
]
=
{
.
queue_id
=
5
,
.
channel_type
=
CONF_CHANNEL_TYPE_DCF
,
.
tsid
=
CONF_TX_AC_
BE
,
[
CONF_TX_AC_VO
]
=
{
.
queue_id
=
CONF_TX_AC_VO
,
.
channel_type
=
CONF_CHANNEL_TYPE_
E
DCF
,
.
tsid
=
CONF_TX_AC_
VO
,
.
ps_scheme
=
CONF_PS_SCHEME_LEGACY
,
.
ack_policy
=
CONF_ACK_POLICY_LEGACY
,
.
apsd_conf
=
{
0
,
0
},
},
[
6
]
=
{
.
queue_id
=
6
,
.
channel_type
=
CONF_CHANNEL_TYPE_DCF
,
.
tsid
=
CONF_TX_AC_BE
,
.
ps_scheme
=
CONF_PS_SCHEME_LEGACY
,
.
ack_policy
=
CONF_ACK_POLICY_LEGACY
,
.
apsd_conf
=
{
0
,
0
},
}
},
.
frag_threshold
=
IEEE80211_MAX_FRAG_THRESHOLD
,
.
tx_compl_timeout
=
700
,
...
...
@@ -238,7 +214,9 @@ static struct conf_drv_settings default_conf = {
.
ps_poll_recovery_period
=
700
,
.
bet_enable
=
CONF_BET_MODE_ENABLE
,
.
bet_max_consecutive
=
10
,
.
psm_entry_retries
=
3
,
.
psm_entry_retries
=
5
,
.
psm_entry_nullfunc_retries
=
3
,
.
psm_entry_hangover_period
=
1
,
.
keep_alive_interval
=
55000
,
.
max_listen_interval
=
20
,
},
...
...
@@ -251,15 +229,34 @@ static struct conf_drv_settings default_conf = {
.
host_fast_wakeup_support
=
false
},
.
roam_trigger
=
{
/* FIXME: due to firmware bug, must use value 1 for now */
.
trigger_pacing
=
1
,
.
avg_weight_rssi_beacon
=
20
,
.
avg_weight_rssi_data
=
10
,
.
avg_weight_snr_beacon
=
20
,
.
avg_weight_snr_data
=
10
}
},
.
scan
=
{
.
min_dwell_time_active
=
7500
,
.
max_dwell_time_active
=
30000
,
.
min_dwell_time_passive
=
30000
,
.
max_dwell_time_passive
=
60000
,
.
num_probe_reqs
=
2
,
},
.
rf
=
{
.
tx_per_channel_power_compensation_2
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
},
.
tx_per_channel_power_compensation_5
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
},
},
};
static
void
__wl1271_op_remove_interface
(
struct
wl1271
*
wl
);
static
void
wl1271_device_release
(
struct
device
*
dev
)
{
...
...
@@ -277,6 +274,67 @@ static struct platform_device wl1271_device = {
static
LIST_HEAD
(
wl_list
);
static
int
wl1271_dev_notify
(
struct
notifier_block
*
me
,
unsigned
long
what
,
void
*
arg
)
{
struct
net_device
*
dev
=
arg
;
struct
wireless_dev
*
wdev
;
struct
wiphy
*
wiphy
;
struct
ieee80211_hw
*
hw
;
struct
wl1271
*
wl
;
struct
wl1271
*
wl_temp
;
int
ret
=
0
;
/* Check that this notification is for us. */
if
(
what
!=
NETDEV_CHANGE
)
return
NOTIFY_DONE
;
wdev
=
dev
->
ieee80211_ptr
;
if
(
wdev
==
NULL
)
return
NOTIFY_DONE
;
wiphy
=
wdev
->
wiphy
;
if
(
wiphy
==
NULL
)
return
NOTIFY_DONE
;
hw
=
wiphy_priv
(
wiphy
);
if
(
hw
==
NULL
)
return
NOTIFY_DONE
;
wl_temp
=
hw
->
priv
;
list_for_each_entry
(
wl
,
&
wl_list
,
list
)
{
if
(
wl
==
wl_temp
)
break
;
}
if
(
wl
!=
wl_temp
)
return
NOTIFY_DONE
;
mutex_lock
(
&
wl
->
mutex
);
if
(
wl
->
state
==
WL1271_STATE_OFF
)
goto
out
;
if
(
!
test_bit
(
WL1271_FLAG_STA_ASSOCIATED
,
&
wl
->
flags
))
goto
out
;
ret
=
wl1271_ps_elp_wakeup
(
wl
,
false
);
if
(
ret
<
0
)
goto
out
;
if
((
dev
->
operstate
==
IF_OPER_UP
)
&&
!
test_and_set_bit
(
WL1271_FLAG_STA_STATE_SENT
,
&
wl
->
flags
))
{
wl1271_cmd_set_sta_state
(
wl
);
wl1271_info
(
"Association completed."
);
}
wl1271_ps_elp_sleep
(
wl
);
out:
mutex_unlock
(
&
wl
->
mutex
);
return
NOTIFY_OK
;
}
static
void
wl1271_conf_init
(
struct
wl1271
*
wl
)
{
...
...
@@ -309,6 +367,10 @@ static int wl1271_plt_init(struct wl1271 *wl)
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_cmd_ext_radio_parms
(
wl
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_init_templates_config
(
wl
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -346,8 +408,16 @@ static int wl1271_plt_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
,
...
...
@@ -360,16 +430,6 @@ static int wl1271_plt_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
;
}
/* Enable data path */
ret
=
wl1271_cmd_data_path
(
wl
,
1
);
if
(
ret
<
0
)
...
...
@@ -562,20 +622,6 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
return
ret
;
}
/*
* FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band
* configurations) can be removed when those NVS files stop floating
* around.
*/
if
(
fw
->
size
!=
sizeof
(
struct
wl1271_nvs_file
)
&&
(
fw
->
size
!=
WL1271_INI_LEGACY_NVS_FILE_SIZE
||
wl1271_11a_enabled
()))
{
wl1271_error
(
"nvs size is not as expected: %zu != %zu"
,
fw
->
size
,
sizeof
(
struct
wl1271_nvs_file
));
ret
=
-
EILSEQ
;
goto
out
;
}
wl
->
nvs
=
kmemdup
(
fw
->
data
,
sizeof
(
struct
wl1271_nvs_file
),
GFP_KERNEL
);
if
(
!
wl
->
nvs
)
{
...
...
@@ -584,12 +630,37 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
goto
out
;
}
wl
->
nvs_len
=
fw
->
size
;
out:
release_firmware
(
fw
);
return
ret
;
}
static
void
wl1271_recovery_work
(
struct
work_struct
*
work
)
{
struct
wl1271
*
wl
=
container_of
(
work
,
struct
wl1271
,
recovery_work
);
mutex_lock
(
&
wl
->
mutex
);
if
(
wl
->
state
!=
WL1271_STATE_ON
)
goto
out
;
wl1271_info
(
"Hardware recovery in progress."
);
if
(
test_bit
(
WL1271_FLAG_STA_ASSOCIATED
,
&
wl
->
flags
))
ieee80211_connection_loss
(
wl
->
vif
);
/* reboot the chipset */
__wl1271_op_remove_interface
(
wl
);
ieee80211_restart_hw
(
wl
->
hw
);
out:
mutex_unlock
(
&
wl
->
mutex
);
}
static
void
wl1271_fw_wakeup
(
struct
wl1271
*
wl
)
{
u32
elp_reg
;
...
...
@@ -610,8 +681,6 @@ static int wl1271_setup(struct wl1271 *wl)
return
-
ENOMEM
;
}
INIT_WORK
(
&
wl
->
irq_work
,
wl1271_irq_work
);
INIT_WORK
(
&
wl
->
tx_work
,
wl1271_tx_work
);
return
0
;
}
...
...
@@ -768,10 +837,12 @@ int wl1271_plt_stop(struct wl1271 *wl)
out:
mutex_unlock
(
&
wl
->
mutex
);
cancel_work_sync
(
&
wl
->
irq_work
);
cancel_work_sync
(
&
wl
->
recovery_work
);
return
ret
;
}
static
int
wl1271_op_tx
(
struct
ieee80211_hw
*
hw
,
struct
sk_buff
*
skb
)
{
struct
wl1271
*
wl
=
hw
->
priv
;
...
...
@@ -814,6 +885,10 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
return
NETDEV_TX_OK
;
}
static
struct
notifier_block
wl1271_dev_notifier
=
{
.
notifier_call
=
wl1271_dev_notify
,
};
static
int
wl1271_op_start
(
struct
ieee80211_hw
*
hw
)
{
wl1271_debug
(
DEBUG_MAC80211
,
"mac80211 start"
);
...
...
@@ -930,13 +1005,10 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
return
ret
;
}
static
void
wl1271_op_remove_interface
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
)
static
void
__wl1271_op_remove_interface
(
struct
wl1271
*
wl
)
{
struct
wl1271
*
wl
=
hw
->
priv
;
int
i
;
mutex_lock
(
&
wl
->
mutex
);
wl1271_debug
(
DEBUG_MAC80211
,
"mac80211 remove interface"
);
wl1271_info
(
"down"
);
...
...
@@ -950,10 +1022,10 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
ieee80211_enable_dyn_ps
(
wl
->
vif
);
if
(
wl
->
scan
.
state
!=
WL1271_SCAN_STATE_IDLE
)
{
ieee80211_scan_completed
(
wl
->
hw
,
true
);
wl
->
scan
.
state
=
WL1271_SCAN_STATE_IDLE
;
kfree
(
wl
->
scan
.
scanned_ch
);
wl
->
scan
.
scanned_ch
=
NULL
;
ieee80211_scan_completed
(
wl
->
hw
,
true
);
}
wl
->
state
=
WL1271_STATE_OFF
;
...
...
@@ -962,9 +1034,11 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
mutex_unlock
(
&
wl
->
mutex
);
cancel_delayed_work_sync
(
&
wl
->
scan_complete_work
);
cancel_work_sync
(
&
wl
->
irq_work
);
cancel_work_sync
(
&
wl
->
tx_work
);
cancel_delayed_work_sync
(
&
wl
->
pspoll_work
);
cancel_delayed_work_sync
(
&
wl
->
elp_work
);
mutex_lock
(
&
wl
->
mutex
);
...
...
@@ -1006,8 +1080,19 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
wl
->
tx_res_if
=
NULL
;
kfree
(
wl
->
target_mem_map
);
wl
->
target_mem_map
=
NULL
;
}
static
void
wl1271_op_remove_interface
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
)
{
struct
wl1271
*
wl
=
hw
->
priv
;
mutex_lock
(
&
wl
->
mutex
);
WARN_ON
(
wl
->
vif
!=
vif
);
__wl1271_op_remove_interface
(
wl
);
mutex_unlock
(
&
wl
->
mutex
);
cancel_work_sync
(
&
wl
->
recovery_work
);
}
static
void
wl1271_configure_filters
(
struct
wl1271
*
wl
,
unsigned
int
filters
)
...
...
@@ -1289,7 +1374,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
if
(
test_bit
(
WL1271_FLAG_STA_ASSOCIATED
,
&
wl
->
flags
))
{
wl1271_debug
(
DEBUG_PSM
,
"psm enabled"
);
ret
=
wl1271_ps_set_mode
(
wl
,
STATION_POWER_SAVE_MODE
,
true
);
wl
->
basic_rate
,
true
);
}
}
else
if
(
!
(
conf
->
flags
&
IEEE80211_CONF_PS
)
&&
test_bit
(
WL1271_FLAG_PSM_REQUESTED
,
&
wl
->
flags
))
{
...
...
@@ -1299,7 +1384,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
if
(
test_bit
(
WL1271_FLAG_PSM
,
&
wl
->
flags
))
ret
=
wl1271_ps_set_mode
(
wl
,
STATION_ACTIVE_MODE
,
true
);
wl
->
basic_rate
,
true
);
}
if
(
conf
->
power_level
!=
wl
->
power_level
)
{
...
...
@@ -1476,6 +1561,11 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
tx_seq_32
=
WL1271_TX_SECURITY_HI32
(
wl
->
tx_security_seq
);
tx_seq_16
=
WL1271_TX_SECURITY_LO16
(
wl
->
tx_security_seq
);
break
;
case
WL1271_CIPHER_SUITE_GEM
:
key_type
=
KEY_GEM
;
tx_seq_32
=
WL1271_TX_SECURITY_HI32
(
wl
->
tx_security_seq
);
tx_seq_16
=
WL1271_TX_SECURITY_LO16
(
wl
->
tx_security_seq
);
break
;
default:
wl1271_error
(
"Unknown key algo 0x%x"
,
key_conf
->
cipher
);
...
...
@@ -1559,10 +1649,7 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
if
(
ret
<
0
)
goto
out
;
if
(
wl1271_11a_enabled
())
ret
=
wl1271_scan
(
hw
->
priv
,
ssid
,
len
,
req
);
else
ret
=
wl1271_scan
(
hw
->
priv
,
ssid
,
len
,
req
);
ret
=
wl1271_scan
(
hw
->
priv
,
ssid
,
len
,
req
);
wl1271_ps_elp_sleep
(
wl
);
...
...
@@ -1777,12 +1864,15 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
if
(
test_bit
(
WL1271_FLAG_PSM_REQUESTED
,
&
wl
->
flags
)
&&
!
test_bit
(
WL1271_FLAG_PSM
,
&
wl
->
flags
))
{
mode
=
STATION_POWER_SAVE_MODE
;
ret
=
wl1271_ps_set_mode
(
wl
,
mode
,
true
);
ret
=
wl1271_ps_set_mode
(
wl
,
mode
,
wl
->
basic_rate
,
true
);
if
(
ret
<
0
)
goto
out_sleep
;
}
}
else
{
/* use defaults when not associated */
clear_bit
(
WL1271_FLAG_STA_STATE_SENT
,
&
wl
->
flags
);
clear_bit
(
WL1271_FLAG_STA_ASSOCIATED
,
&
wl
->
flags
);
wl
->
aid
=
0
;
...
...
@@ -1994,21 +2084,24 @@ static struct ieee80211_rate wl1271_rates[] = {
.
hw_value_short
=
CONF_HW_BIT_RATE_54MBPS
,
},
};
/* can't be const, mac80211 writes to this */
/*
* Can't be const, mac80211 writes to this. The order of the channels here
* is designed to improve scanning.
*/
static
struct
ieee80211_channel
wl1271_channels
[]
=
{
{
.
hw_value
=
1
,
.
center_freq
=
2412
,
.
max_power
=
25
},
{
.
hw_value
=
2
,
.
center_freq
=
2417
,
.
max_power
=
25
},
{
.
hw_value
=
3
,
.
center_freq
=
2422
,
.
max_power
=
25
},
{
.
hw_value
=
4
,
.
center_freq
=
2427
,
.
max_power
=
25
},
{
.
hw_value
=
5
,
.
center_freq
=
2432
,
.
max_power
=
25
},
{
.
hw_value
=
6
,
.
center_freq
=
2437
,
.
max_power
=
25
},
{
.
hw_value
=
7
,
.
center_freq
=
2442
,
.
max_power
=
25
},
{
.
hw_value
=
8
,
.
center_freq
=
2447
,
.
max_power
=
25
},
{
.
hw_value
=
9
,
.
center_freq
=
2452
,
.
max_power
=
25
},
{
.
hw_value
=
10
,
.
center_freq
=
2457
,
.
max_power
=
25
},
{
.
hw_value
=
11
,
.
center_freq
=
2462
,
.
max_power
=
25
},
{
.
hw_value
=
12
,
.
center_freq
=
2467
,
.
max_power
=
25
},
{
.
hw_value
=
13
,
.
center_freq
=
2472
,
.
max_power
=
25
},
{
.
hw_value
=
4
,
.
center_freq
=
2427
,
.
max_power
=
25
},
{
.
hw_value
=
8
,
.
center_freq
=
2447
,
.
max_power
=
25
},
{
.
hw_value
=
12
,
.
center_freq
=
2467
,
.
max_power
=
25
},
{
.
hw_value
=
3
,
.
center_freq
=
2422
,
.
max_power
=
25
},
{
.
hw_value
=
7
,
.
center_freq
=
2442
,
.
max_power
=
25
},
{
.
hw_value
=
11
,
.
center_freq
=
2462
,
.
max_power
=
25
},
{
.
hw_value
=
2
,
.
center_freq
=
2417
,
.
max_power
=
25
},
{
.
hw_value
=
6
,
.
center_freq
=
2437
,
.
max_power
=
25
},
{
.
hw_value
=
10
,
.
center_freq
=
2457
,
.
max_power
=
25
},
};
/* mapping to indexes for wl1271_rates */
...
...
@@ -2077,49 +2170,52 @@ static struct ieee80211_rate wl1271_rates_5ghz[] = {
.
hw_value_short
=
CONF_HW_BIT_RATE_54MBPS
,
},
};
/* 5 GHz band channels for WL1273 */
/*
* 5 GHz band channels for WL1273 - can't be const, mac80211 writes to this.
* The order of the channels here is designed to improve scanning.
*/
static
struct
ieee80211_channel
wl1271_channels_5ghz
[]
=
{
{
.
hw_value
=
183
,
.
center_freq
=
4915
},
{
.
hw_value
=
184
,
.
center_freq
=
4920
},
{
.
hw_value
=
185
,
.
center_freq
=
4925
},
{
.
hw_value
=
187
,
.
center_freq
=
4935
},
{
.
hw_value
=
188
,
.
center_freq
=
4940
},
{
.
hw_value
=
189
,
.
center_freq
=
4945
},
{
.
hw_value
=
192
,
.
center_freq
=
4960
},
{
.
hw_value
=
196
,
.
center_freq
=
4980
},
{
.
hw_value
=
7
,
.
center_freq
=
5035
},
{
.
hw_value
=
8
,
.
center_freq
=
5040
},
{
.
hw_value
=
9
,
.
center_freq
=
5045
},
{
.
hw_value
=
11
,
.
center_freq
=
5055
},
{
.
hw_value
=
12
,
.
center_freq
=
5060
},
{
.
hw_value
=
16
,
.
center_freq
=
5080
},
{
.
hw_value
=
34
,
.
center_freq
=
5170
},
{
.
hw_value
=
36
,
.
center_freq
=
5180
},
{
.
hw_value
=
38
,
.
center_freq
=
5190
},
{
.
hw_value
=
40
,
.
center_freq
=
5200
},
{
.
hw_value
=
42
,
.
center_freq
=
5210
},
{
.
hw_value
=
44
,
.
center_freq
=
5220
},
{
.
hw_value
=
46
,
.
center_freq
=
5230
},
{
.
hw_value
=
48
,
.
center_freq
=
5240
},
{
.
hw_value
=
52
,
.
center_freq
=
5260
},
{
.
hw_value
=
56
,
.
center_freq
=
5280
},
{
.
hw_value
=
60
,
.
center_freq
=
5300
},
{
.
hw_value
=
64
,
.
center_freq
=
5320
},
{
.
hw_value
=
100
,
.
center_freq
=
5500
},
{
.
hw_value
=
104
,
.
center_freq
=
5520
},
{
.
hw_value
=
108
,
.
center_freq
=
5540
},
{
.
hw_value
=
112
,
.
center_freq
=
5560
},
{
.
hw_value
=
116
,
.
center_freq
=
5580
},
{
.
hw_value
=
120
,
.
center_freq
=
5600
},
{
.
hw_value
=
124
,
.
center_freq
=
5620
},
{
.
hw_value
=
128
,
.
center_freq
=
5640
},
{
.
hw_value
=
132
,
.
center_freq
=
5660
},
{
.
hw_value
=
157
,
.
center_freq
=
5785
},
{
.
hw_value
=
184
,
.
center_freq
=
4920
},
{
.
hw_value
=
189
,
.
center_freq
=
4945
},
{
.
hw_value
=
9
,
.
center_freq
=
5045
},
{
.
hw_value
=
36
,
.
center_freq
=
5180
},
{
.
hw_value
=
46
,
.
center_freq
=
5230
},
{
.
hw_value
=
64
,
.
center_freq
=
5320
},
{
.
hw_value
=
116
,
.
center_freq
=
5580
},
{
.
hw_value
=
136
,
.
center_freq
=
5680
},
{
.
hw_value
=
192
,
.
center_freq
=
4960
},
{
.
hw_value
=
11
,
.
center_freq
=
5055
},
{
.
hw_value
=
38
,
.
center_freq
=
5190
},
{
.
hw_value
=
48
,
.
center_freq
=
5240
},
{
.
hw_value
=
100
,
.
center_freq
=
5500
},
{
.
hw_value
=
120
,
.
center_freq
=
5600
},
{
.
hw_value
=
140
,
.
center_freq
=
5700
},
{
.
hw_value
=
185
,
.
center_freq
=
4925
},
{
.
hw_value
=
196
,
.
center_freq
=
4980
},
{
.
hw_value
=
12
,
.
center_freq
=
5060
},
{
.
hw_value
=
40
,
.
center_freq
=
5200
},
{
.
hw_value
=
52
,
.
center_freq
=
5260
},
{
.
hw_value
=
104
,
.
center_freq
=
5520
},
{
.
hw_value
=
124
,
.
center_freq
=
5620
},
{
.
hw_value
=
149
,
.
center_freq
=
5745
},
{
.
hw_value
=
153
,
.
center_freq
=
5765
},
{
.
hw_value
=
157
,
.
center_freq
=
5785
},
{
.
hw_value
=
161
,
.
center_freq
=
5805
},
{
.
hw_value
=
187
,
.
center_freq
=
4935
},
{
.
hw_value
=
7
,
.
center_freq
=
5035
},
{
.
hw_value
=
16
,
.
center_freq
=
5080
},
{
.
hw_value
=
42
,
.
center_freq
=
5210
},
{
.
hw_value
=
56
,
.
center_freq
=
5280
},
{
.
hw_value
=
108
,
.
center_freq
=
5540
},
{
.
hw_value
=
128
,
.
center_freq
=
5640
},
{
.
hw_value
=
153
,
.
center_freq
=
5765
},
{
.
hw_value
=
165
,
.
center_freq
=
5825
},
};
...
...
@@ -2212,8 +2308,7 @@ static ssize_t wl1271_sysfs_show_bt_coex_state(struct device *dev,
struct
wl1271
*
wl
=
dev_get_drvdata
(
dev
);
ssize_t
len
;
/* FIXME: what's the maximum length of buf? page size?*/
len
=
500
;
len
=
PAGE_SIZE
;
mutex_lock
(
&
wl
->
mutex
);
len
=
snprintf
(
buf
,
len
,
"%d
\n\n
0 - off
\n
1 - on
\n
"
,
...
...
@@ -2274,8 +2369,7 @@ static ssize_t wl1271_sysfs_show_hw_pg_ver(struct device *dev,
struct
wl1271
*
wl
=
dev_get_drvdata
(
dev
);
ssize_t
len
;
/* FIXME: what's the maximum length of buf? page size?*/
len
=
500
;
len
=
PAGE_SIZE
;
mutex_lock
(
&
wl
->
mutex
);
if
(
wl
->
hw_pg_ver
>=
0
)
...
...
@@ -2307,6 +2401,8 @@ int wl1271_register_hw(struct wl1271 *wl)
wl
->
mac80211_registered
=
true
;
register_netdevice_notifier
(
&
wl1271_dev_notifier
);
wl1271_notice
(
"loaded"
);
return
0
;
...
...
@@ -2315,6 +2411,7 @@ EXPORT_SYMBOL_GPL(wl1271_register_hw);
void
wl1271_unregister_hw
(
struct
wl1271
*
wl
)
{
unregister_netdevice_notifier
(
&
wl1271_dev_notifier
);
ieee80211_unregister_hw
(
wl
->
hw
);
wl
->
mac80211_registered
=
false
;
...
...
@@ -2323,6 +2420,14 @@ EXPORT_SYMBOL_GPL(wl1271_unregister_hw);
int
wl1271_init_ieee80211
(
struct
wl1271
*
wl
)
{
static
const
u32
cipher_suites
[]
=
{
WLAN_CIPHER_SUITE_WEP40
,
WLAN_CIPHER_SUITE_WEP104
,
WLAN_CIPHER_SUITE_TKIP
,
WLAN_CIPHER_SUITE_CCMP
,
WL1271_CIPHER_SUITE_GEM
,
};
/* The tx descriptor buffer and the TKIP space. */
wl
->
hw
->
extra_tx_headroom
=
WL1271_TKIP_IV_SPACE
+
sizeof
(
struct
wl1271_tx_hw_descr
);
...
...
@@ -2340,13 +2445,14 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
IEEE80211_HW_CONNECTION_MONITOR
|
IEEE80211_HW_SUPPORTS_CQM_RSSI
;
wl
->
hw
->
wiphy
->
cipher_suites
=
cipher_suites
;
wl
->
hw
->
wiphy
->
n_cipher_suites
=
ARRAY_SIZE
(
cipher_suites
);
wl
->
hw
->
wiphy
->
interface_modes
=
BIT
(
NL80211_IFTYPE_STATION
)
|
BIT
(
NL80211_IFTYPE_ADHOC
);
wl
->
hw
->
wiphy
->
max_scan_ssids
=
1
;
wl
->
hw
->
wiphy
->
bands
[
IEEE80211_BAND_2GHZ
]
=
&
wl1271_band_2ghz
;
if
(
wl1271_11a_enabled
())
wl
->
hw
->
wiphy
->
bands
[
IEEE80211_BAND_5GHZ
]
=
&
wl1271_band_5ghz
;
wl
->
hw
->
wiphy
->
bands
[
IEEE80211_BAND_5GHZ
]
=
&
wl1271_band_5ghz
;
wl
->
hw
->
queues
=
4
;
wl
->
hw
->
max_rates
=
1
;
...
...
@@ -2365,6 +2471,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
struct
platform_device
*
plat_dev
=
NULL
;
struct
wl1271
*
wl
;
int
i
,
ret
;
unsigned
int
order
;
hw
=
ieee80211_alloc_hw
(
sizeof
(
*
wl
),
&
wl1271_ops
);
if
(
!
hw
)
{
...
...
@@ -2392,6 +2499,10 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
INIT_DELAYED_WORK
(
&
wl
->
elp_work
,
wl1271_elp_work
);
INIT_DELAYED_WORK
(
&
wl
->
pspoll_work
,
wl1271_pspoll_work
);
INIT_WORK
(
&
wl
->
irq_work
,
wl1271_irq_work
);
INIT_WORK
(
&
wl
->
tx_work
,
wl1271_tx_work
);
INIT_WORK
(
&
wl
->
recovery_work
,
wl1271_recovery_work
);
INIT_DELAYED_WORK
(
&
wl
->
scan_complete_work
,
wl1271_scan_complete_work
);
wl
->
channel
=
WL1271_DEFAULT_CHANNEL
;
wl
->
beacon_int
=
WL1271_DEFAULT_BEACON_INT
;
wl
->
default_key
=
0
;
...
...
@@ -2423,11 +2534,18 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl1271_debugfs_init
(
wl
);
order
=
get_order
(
WL1271_AGGR_BUFFER_SIZE
);
wl
->
aggr_buf
=
(
u8
*
)
__get_free_pages
(
GFP_KERNEL
,
order
);
if
(
!
wl
->
aggr_buf
)
{
ret
=
-
ENOMEM
;
goto
err_hw
;
}
/* Register platform device */
ret
=
platform_device_register
(
wl
->
plat_dev
);
if
(
ret
)
{
wl1271_error
(
"couldn't register platform device"
);
goto
err_
hw
;
goto
err_
aggr
;
}
dev_set_drvdata
(
&
wl
->
plat_dev
->
dev
,
wl
);
...
...
@@ -2453,6 +2571,9 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
err_platform:
platform_device_unregister
(
wl
->
plat_dev
);
err_aggr:
free_pages
((
unsigned
long
)
wl
->
aggr_buf
,
order
);
err_hw:
wl1271_debugfs_exit
(
wl
);
kfree
(
plat_dev
);
...
...
@@ -2469,6 +2590,8 @@ EXPORT_SYMBOL_GPL(wl1271_alloc_hw);
int
wl1271_free_hw
(
struct
wl1271
*
wl
)
{
platform_device_unregister
(
wl
->
plat_dev
);
free_pages
((
unsigned
long
)
wl
->
aggr_buf
,
get_order
(
WL1271_AGGR_BUFFER_SIZE
));
kfree
(
wl
->
plat_dev
);
wl1271_debugfs_exit
(
wl
);
...
...
drivers/net/wireless/wl12xx/wl1271_ps.c
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
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