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
42774986
Commit
42774986
authored
Feb 23, 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
9077f218
b622d992
Changes
11
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
478 additions
and
77 deletions
+478
-77
drivers/net/wireless/wl12xx/acx.c
drivers/net/wireless/wl12xx/acx.c
+26
-2
drivers/net/wireless/wl12xx/acx.h
drivers/net/wireless/wl12xx/acx.h
+9
-0
drivers/net/wireless/wl12xx/init.c
drivers/net/wireless/wl12xx/init.c
+1
-1
drivers/net/wireless/wl12xx/main.c
drivers/net/wireless/wl12xx/main.c
+118
-29
drivers/net/wireless/wl12xx/ps.c
drivers/net/wireless/wl12xx/ps.c
+78
-0
drivers/net/wireless/wl12xx/ps.h
drivers/net/wireless/wl12xx/ps.h
+2
-0
drivers/net/wireless/wl12xx/rx.c
drivers/net/wireless/wl12xx/rx.c
+3
-3
drivers/net/wireless/wl12xx/rx.h
drivers/net/wireless/wl12xx/rx.h
+0
-4
drivers/net/wireless/wl12xx/tx.c
drivers/net/wireless/wl12xx/tx.c
+201
-36
drivers/net/wireless/wl12xx/tx.h
drivers/net/wireless/wl12xx/tx.h
+3
-2
drivers/net/wireless/wl12xx/wl12xx.h
drivers/net/wireless/wl12xx/wl12xx.h
+37
-0
No files found.
drivers/net/wireless/wl12xx/acx.c
View file @
42774986
...
@@ -1328,10 +1328,9 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
...
@@ -1328,10 +1328,9 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
/* get data from A-MPDU parameters field */
/* get data from A-MPDU parameters field */
acx
->
ampdu_max_length
=
ht_cap
->
ampdu_factor
;
acx
->
ampdu_max_length
=
ht_cap
->
ampdu_factor
;
acx
->
ampdu_min_spacing
=
ht_cap
->
ampdu_density
;
acx
->
ampdu_min_spacing
=
ht_cap
->
ampdu_density
;
memcpy
(
acx
->
mac_address
,
mac_address
,
ETH_ALEN
);
}
}
memcpy
(
acx
->
mac_address
,
mac_address
,
ETH_ALEN
);
acx
->
ht_capabilites
=
cpu_to_le32
(
ht_capabilites
);
acx
->
ht_capabilites
=
cpu_to_le32
(
ht_capabilites
);
ret
=
wl1271_cmd_configure
(
wl
,
ACX_PEER_HT_CAP
,
acx
,
sizeof
(
*
acx
));
ret
=
wl1271_cmd_configure
(
wl
,
ACX_PEER_HT_CAP
,
acx
,
sizeof
(
*
acx
));
...
@@ -1542,3 +1541,28 @@ int wl1271_acx_config_ps(struct wl1271 *wl)
...
@@ -1542,3 +1541,28 @@ int wl1271_acx_config_ps(struct wl1271 *wl)
kfree
(
config_ps
);
kfree
(
config_ps
);
return
ret
;
return
ret
;
}
}
int
wl1271_acx_set_inconnection_sta
(
struct
wl1271
*
wl
,
u8
*
addr
)
{
struct
wl1271_acx_inconnection_sta
*
acx
=
NULL
;
int
ret
;
wl1271_debug
(
DEBUG_ACX
,
"acx set inconnaction sta %pM"
,
addr
);
acx
=
kzalloc
(
sizeof
(
*
acx
),
GFP_KERNEL
);
if
(
!
acx
)
return
-
ENOMEM
;
memcpy
(
acx
->
addr
,
addr
,
ETH_ALEN
);
ret
=
wl1271_cmd_configure
(
wl
,
ACX_UPDATE_INCONNECTION_STA_LIST
,
acx
,
sizeof
(
*
acx
));
if
(
ret
<
0
)
{
wl1271_warning
(
"acx set inconnaction sta failed: %d"
,
ret
);
goto
out
;
}
out:
kfree
(
acx
);
return
ret
;
}
drivers/net/wireless/wl12xx/acx.h
View file @
42774986
...
@@ -1155,6 +1155,13 @@ struct wl1271_acx_config_ps {
...
@@ -1155,6 +1155,13 @@ struct wl1271_acx_config_ps {
__le32
null_data_rate
;
__le32
null_data_rate
;
}
__packed
;
}
__packed
;
struct
wl1271_acx_inconnection_sta
{
struct
acx_header
header
;
u8
addr
[
ETH_ALEN
];
u8
padding1
[
2
];
}
__packed
;
enum
{
enum
{
ACX_WAKE_UP_CONDITIONS
=
0x0002
,
ACX_WAKE_UP_CONDITIONS
=
0x0002
,
ACX_MEM_CFG
=
0x0003
,
ACX_MEM_CFG
=
0x0003
,
...
@@ -1215,6 +1222,7 @@ enum {
...
@@ -1215,6 +1222,7 @@ enum {
ACX_GEN_FW_CMD
=
0x0070
,
ACX_GEN_FW_CMD
=
0x0070
,
ACX_HOST_IF_CFG_BITMAP
=
0x0071
,
ACX_HOST_IF_CFG_BITMAP
=
0x0071
,
ACX_MAX_TX_FAILURE
=
0x0072
,
ACX_MAX_TX_FAILURE
=
0x0072
,
ACX_UPDATE_INCONNECTION_STA_LIST
=
0x0073
,
DOT11_RX_MSDU_LIFE_TIME
=
0x1004
,
DOT11_RX_MSDU_LIFE_TIME
=
0x1004
,
DOT11_CUR_TX_PWR
=
0x100D
,
DOT11_CUR_TX_PWR
=
0x100D
,
DOT11_RX_DOT11_MODE
=
0x1012
,
DOT11_RX_DOT11_MODE
=
0x1012
,
...
@@ -1290,5 +1298,6 @@ int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
...
@@ -1290,5 +1298,6 @@ int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
int
wl1271_acx_tsf_info
(
struct
wl1271
*
wl
,
u64
*
mactime
);
int
wl1271_acx_tsf_info
(
struct
wl1271
*
wl
,
u64
*
mactime
);
int
wl1271_acx_max_tx_retry
(
struct
wl1271
*
wl
);
int
wl1271_acx_max_tx_retry
(
struct
wl1271
*
wl
);
int
wl1271_acx_config_ps
(
struct
wl1271
*
wl
);
int
wl1271_acx_config_ps
(
struct
wl1271
*
wl
);
int
wl1271_acx_set_inconnection_sta
(
struct
wl1271
*
wl
,
u8
*
addr
);
#endif
/* __WL1271_ACX_H__ */
#endif
/* __WL1271_ACX_H__ */
drivers/net/wireless/wl12xx/init.c
View file @
42774986
...
@@ -483,7 +483,7 @@ static void wl1271_check_ba_support(struct wl1271 *wl)
...
@@ -483,7 +483,7 @@ static void wl1271_check_ba_support(struct wl1271 *wl)
static
int
wl1271_set_ba_policies
(
struct
wl1271
*
wl
)
static
int
wl1271_set_ba_policies
(
struct
wl1271
*
wl
)
{
{
u8
tid_index
;
u8
tid_index
;
u8
ret
=
0
;
int
ret
=
0
;
/* Reset the BA RX indicators */
/* Reset the BA RX indicators */
wl
->
ba_rx_bitmap
=
0
;
wl
->
ba_rx_bitmap
=
0
;
...
...
drivers/net/wireless/wl12xx/main.c
View file @
42774986
...
@@ -482,6 +482,10 @@ static int wl1271_plt_init(struct wl1271 *wl)
...
@@ -482,6 +482,10 @@ static int wl1271_plt_init(struct wl1271 *wl)
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
out_free_memmap
;
goto
out_free_memmap
;
ret
=
wl1271_acx_sta_mem_cfg
(
wl
);
if
(
ret
<
0
)
goto
out_free_memmap
;
/* Default fragmentation threshold */
/* Default fragmentation threshold */
ret
=
wl1271_acx_frag_threshold
(
wl
,
wl
->
conf
.
tx
.
frag_threshold
);
ret
=
wl1271_acx_frag_threshold
(
wl
,
wl
->
conf
.
tx
.
frag_threshold
);
if
(
ret
<
0
)
if
(
ret
<
0
)
...
@@ -533,6 +537,57 @@ static int wl1271_plt_init(struct wl1271 *wl)
...
@@ -533,6 +537,57 @@ static int wl1271_plt_init(struct wl1271 *wl)
return
ret
;
return
ret
;
}
}
static
void
wl1271_irq_ps_regulate_link
(
struct
wl1271
*
wl
,
u8
hlid
,
u8
tx_blks
)
{
bool
fw_ps
;
/* only regulate station links */
if
(
hlid
<
WL1271_AP_STA_HLID_START
)
return
;
fw_ps
=
test_bit
(
hlid
,
(
unsigned
long
*
)
&
wl
->
ap_fw_ps_map
);
/*
* Wake up from high level PS if the STA is asleep with too little
* blocks in FW or if the STA is awake.
*/
if
(
!
fw_ps
||
tx_blks
<
WL1271_PS_STA_MAX_BLOCKS
)
wl1271_ps_link_end
(
wl
,
hlid
);
/* Start high-level PS if the STA is asleep with enough blocks in FW */
else
if
(
fw_ps
&&
tx_blks
>=
WL1271_PS_STA_MAX_BLOCKS
)
wl1271_ps_link_start
(
wl
,
hlid
,
true
);
}
static
void
wl1271_irq_update_links_status
(
struct
wl1271
*
wl
,
struct
wl1271_fw_ap_status
*
status
)
{
u32
cur_fw_ps_map
;
u8
hlid
;
cur_fw_ps_map
=
le32_to_cpu
(
status
->
link_ps_bitmap
);
if
(
wl
->
ap_fw_ps_map
!=
cur_fw_ps_map
)
{
wl1271_debug
(
DEBUG_PSM
,
"link ps prev 0x%x cur 0x%x changed 0x%x"
,
wl
->
ap_fw_ps_map
,
cur_fw_ps_map
,
wl
->
ap_fw_ps_map
^
cur_fw_ps_map
);
wl
->
ap_fw_ps_map
=
cur_fw_ps_map
;
}
for
(
hlid
=
WL1271_AP_STA_HLID_START
;
hlid
<
AP_MAX_LINKS
;
hlid
++
)
{
u8
cnt
=
status
->
tx_lnk_free_blks
[
hlid
]
-
wl
->
links
[
hlid
].
prev_freed_blks
;
wl
->
links
[
hlid
].
prev_freed_blks
=
status
->
tx_lnk_free_blks
[
hlid
];
wl
->
links
[
hlid
].
allocated_blks
-=
cnt
;
wl1271_irq_ps_regulate_link
(
wl
,
hlid
,
wl
->
links
[
hlid
].
allocated_blks
);
}
}
static
void
wl1271_fw_status
(
struct
wl1271
*
wl
,
static
void
wl1271_fw_status
(
struct
wl1271
*
wl
,
struct
wl1271_fw_full_status
*
full_status
)
struct
wl1271_fw_full_status
*
full_status
)
{
{
...
@@ -570,6 +625,10 @@ static void wl1271_fw_status(struct wl1271 *wl,
...
@@ -570,6 +625,10 @@ static void wl1271_fw_status(struct wl1271 *wl,
if
(
total
)
if
(
total
)
clear_bit
(
WL1271_FLAG_FW_TX_BUSY
,
&
wl
->
flags
);
clear_bit
(
WL1271_FLAG_FW_TX_BUSY
,
&
wl
->
flags
);
/* for AP update num of allocated TX blocks per link and ps status */
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
wl1271_irq_update_links_status
(
wl
,
&
full_status
->
ap
);
/* update the host-chipset time offset */
/* update the host-chipset time offset */
getnstimeofday
(
&
ts
);
getnstimeofday
(
&
ts
);
wl
->
time_offset
=
(
timespec_to_ns
(
&
ts
)
>>
10
)
-
wl
->
time_offset
=
(
timespec_to_ns
(
&
ts
)
>>
10
)
-
...
@@ -980,14 +1039,32 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
...
@@ -980,14 +1039,32 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
struct
wl1271
*
wl
=
hw
->
priv
;
struct
wl1271
*
wl
=
hw
->
priv
;
unsigned
long
flags
;
unsigned
long
flags
;
int
q
;
int
q
;
u8
hlid
=
0
;
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
wl
->
tx_queue_count
++
;
wl
->
tx_queue_count
++
;
/*
* The workqueue is slow to process the tx_queue and we need stop
* the queue here, otherwise the queue will get too long.
*/
if
(
wl
->
tx_queue_count
>=
WL1271_TX_QUEUE_HIGH_WATERMARK
)
{
wl1271_debug
(
DEBUG_TX
,
"op_tx: stopping queues"
);
ieee80211_stop_queues
(
wl
->
hw
);
set_bit
(
WL1271_FLAG_TX_QUEUE_STOPPED
,
&
wl
->
flags
);
}
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
/* queue the packet */
/* queue the packet */
q
=
wl1271_tx_get_queue
(
skb_get_queue_mapping
(
skb
));
q
=
wl1271_tx_get_queue
(
skb_get_queue_mapping
(
skb
));
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
{
hlid
=
wl1271_tx_get_hlid
(
skb
);
wl1271_debug
(
DEBUG_TX
,
"queue skb hlid %d q %d"
,
hlid
,
q
);
skb_queue_tail
(
&
wl
->
links
[
hlid
].
tx_queue
[
q
],
skb
);
}
else
{
skb_queue_tail
(
&
wl
->
tx_queue
[
q
],
skb
);
skb_queue_tail
(
&
wl
->
tx_queue
[
q
],
skb
);
}
/*
/*
* The chip specific setup must run before the first TX packet -
* The chip specific setup must run before the first TX packet -
...
@@ -997,19 +1074,6 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
...
@@ -997,19 +1074,6 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
if
(
!
test_bit
(
WL1271_FLAG_FW_TX_BUSY
,
&
wl
->
flags
))
if
(
!
test_bit
(
WL1271_FLAG_FW_TX_BUSY
,
&
wl
->
flags
))
ieee80211_queue_work
(
wl
->
hw
,
&
wl
->
tx_work
);
ieee80211_queue_work
(
wl
->
hw
,
&
wl
->
tx_work
);
/*
* The workqueue is slow to process the tx_queue and we need stop
* the queue here, otherwise the queue will get too long.
*/
if
(
wl
->
tx_queue_count
>=
WL1271_TX_QUEUE_HIGH_WATERMARK
)
{
wl1271_debug
(
DEBUG_TX
,
"op_tx: stopping queues"
);
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
ieee80211_stop_queues
(
wl
->
hw
);
set_bit
(
WL1271_FLAG_TX_QUEUE_STOPPED
,
&
wl
->
flags
);
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
}
return
NETDEV_TX_OK
;
return
NETDEV_TX_OK
;
}
}
...
@@ -1221,6 +1285,8 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl)
...
@@ -1221,6 +1285,8 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl)
wl
->
filters
=
0
;
wl
->
filters
=
0
;
wl1271_free_ap_keys
(
wl
);
wl1271_free_ap_keys
(
wl
);
memset
(
wl
->
ap_hlid_map
,
0
,
sizeof
(
wl
->
ap_hlid_map
));
memset
(
wl
->
ap_hlid_map
,
0
,
sizeof
(
wl
->
ap_hlid_map
));
wl
->
ap_fw_ps_map
=
0
;
wl
->
ap_ps_map
=
0
;
for
(
i
=
0
;
i
<
NUM_TX_QUEUES
;
i
++
)
for
(
i
=
0
;
i
<
NUM_TX_QUEUES
;
i
++
)
wl
->
tx_blocks_freed
[
i
]
=
0
;
wl
->
tx_blocks_freed
[
i
]
=
0
;
...
@@ -2218,6 +2284,8 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
...
@@ -2218,6 +2284,8 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
u32
sta_rate_set
=
0
;
u32
sta_rate_set
=
0
;
int
ret
;
int
ret
;
struct
ieee80211_sta
*
sta
;
struct
ieee80211_sta
*
sta
;
bool
sta_exists
=
false
;
struct
ieee80211_sta_ht_cap
sta_ht_cap
;
if
(
is_ibss
)
{
if
(
is_ibss
)
{
ret
=
wl1271_bss_beacon_info_changed
(
wl
,
vif
,
bss_conf
,
ret
=
wl1271_bss_beacon_info_changed
(
wl
,
vif
,
bss_conf
,
...
@@ -2289,16 +2357,20 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
...
@@ -2289,16 +2357,20 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
if
(
sta
->
ht_cap
.
ht_supported
)
if
(
sta
->
ht_cap
.
ht_supported
)
sta_rate_set
|=
sta_rate_set
|=
(
sta
->
ht_cap
.
mcs
.
rx_mask
[
0
]
<<
HW_HT_RATES_OFFSET
);
(
sta
->
ht_cap
.
mcs
.
rx_mask
[
0
]
<<
HW_HT_RATES_OFFSET
);
sta_ht_cap
=
sta
->
ht_cap
;
sta_exists
=
true
;
}
rcu_read_unlock
();
if
(
sta_exists
)
{
/* handle new association with HT and HT information change */
/* handle new association with HT and HT information change */
if
((
changed
&
BSS_CHANGED_HT
)
&&
if
((
changed
&
BSS_CHANGED_HT
)
&&
(
bss_conf
->
channel_type
!=
NL80211_CHAN_NO_HT
))
{
(
bss_conf
->
channel_type
!=
NL80211_CHAN_NO_HT
))
{
ret
=
wl1271_acx_set_ht_capabilities
(
wl
,
&
sta
->
ht_cap
,
ret
=
wl1271_acx_set_ht_capabilities
(
wl
,
&
sta
_
ht_cap
,
true
);
true
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
wl1271_warning
(
"Set ht cap true failed %d"
,
wl1271_warning
(
"Set ht cap true failed %d"
,
ret
);
ret
);
rcu_read_unlock
();
goto
out
;
goto
out
;
}
}
ret
=
wl1271_acx_set_ht_information
(
wl
,
ret
=
wl1271_acx_set_ht_information
(
wl
,
...
@@ -2306,23 +2378,20 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
...
@@ -2306,23 +2378,20 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
wl1271_warning
(
"Set ht information failed %d"
,
wl1271_warning
(
"Set ht information failed %d"
,
ret
);
ret
);
rcu_read_unlock
();
goto
out
;
goto
out
;
}
}
}
}
/* handle new association without HT and disassociation */
/* handle new association without HT and disassociation */
else
if
(
changed
&
BSS_CHANGED_ASSOC
)
{
else
if
(
changed
&
BSS_CHANGED_ASSOC
)
{
ret
=
wl1271_acx_set_ht_capabilities
(
wl
,
&
sta
->
ht_cap
,
ret
=
wl1271_acx_set_ht_capabilities
(
wl
,
&
sta
_
ht_cap
,
false
);
false
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
wl1271_warning
(
"Set ht cap false failed %d"
,
wl1271_warning
(
"Set ht cap false failed %d"
,
ret
);
ret
);
rcu_read_unlock
();
goto
out
;
goto
out
;
}
}
}
}
}
}
rcu_read_unlock
();
if
((
changed
&
BSS_CHANGED_ASSOC
))
{
if
((
changed
&
BSS_CHANGED_ASSOC
))
{
if
(
bss_conf
->
assoc
)
{
if
(
bss_conf
->
assoc
)
{
...
@@ -2612,7 +2681,7 @@ static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx,
...
@@ -2612,7 +2681,7 @@ static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx,
return
0
;
return
0
;
}
}
static
int
wl1271_allocate_
hlid
(
struct
wl1271
*
wl
,
static
int
wl1271_allocate_
sta
(
struct
wl1271
*
wl
,
struct
ieee80211_sta
*
sta
,
struct
ieee80211_sta
*
sta
,
u8
*
hlid
)
u8
*
hlid
)
{
{
...
@@ -2626,18 +2695,25 @@ static int wl1271_allocate_hlid(struct wl1271 *wl,
...
@@ -2626,18 +2695,25 @@ static int wl1271_allocate_hlid(struct wl1271 *wl,
}
}
wl_sta
=
(
struct
wl1271_station
*
)
sta
->
drv_priv
;
wl_sta
=
(
struct
wl1271_station
*
)
sta
->
drv_priv
;
__set_bit
(
id
,
wl
->
ap_hlid_map
);
__set_bit
(
id
,
wl
->
ap_hlid_map
);
wl_sta
->
hlid
=
WL1271_AP_STA_HLID_START
+
id
;
wl_sta
->
hlid
=
WL1271_AP_STA_HLID_START
+
id
;
*
hlid
=
wl_sta
->
hlid
;
*
hlid
=
wl_sta
->
hlid
;
memcpy
(
wl
->
links
[
wl_sta
->
hlid
].
addr
,
sta
->
addr
,
ETH_ALEN
);
return
0
;
return
0
;
}
}
static
void
wl1271_free_
hlid
(
struct
wl1271
*
wl
,
u8
hlid
)
static
void
wl1271_free_
sta
(
struct
wl1271
*
wl
,
u8
hlid
)
{
{
int
id
=
hlid
-
WL1271_AP_STA_HLID_START
;
int
id
=
hlid
-
WL1271_AP_STA_HLID_START
;
if
(
WARN_ON
(
!
test_bit
(
id
,
wl
->
ap_hlid_map
)))
return
;
__clear_bit
(
id
,
wl
->
ap_hlid_map
);
__clear_bit
(
id
,
wl
->
ap_hlid_map
);
memset
(
wl
->
links
[
hlid
].
addr
,
0
,
ETH_ALEN
);
wl1271_tx_reset_link_queues
(
wl
,
hlid
);
__clear_bit
(
hlid
,
&
wl
->
ap_ps_map
);
__clear_bit
(
hlid
,
(
unsigned
long
*
)
&
wl
->
ap_fw_ps_map
);
}
}
static
int
wl1271_op_sta_add
(
struct
ieee80211_hw
*
hw
,
static
int
wl1271_op_sta_add
(
struct
ieee80211_hw
*
hw
,
...
@@ -2658,13 +2734,13 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw,
...
@@ -2658,13 +2734,13 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw,
wl1271_debug
(
DEBUG_MAC80211
,
"mac80211 add sta %d"
,
(
int
)
sta
->
aid
);
wl1271_debug
(
DEBUG_MAC80211
,
"mac80211 add sta %d"
,
(
int
)
sta
->
aid
);
ret
=
wl1271_allocate_
hlid
(
wl
,
sta
,
&
hlid
);
ret
=
wl1271_allocate_
sta
(
wl
,
sta
,
&
hlid
);
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
out
;
goto
out
;
ret
=
wl1271_ps_elp_wakeup
(
wl
,
false
);
ret
=
wl1271_ps_elp_wakeup
(
wl
,
false
);
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
out
;
goto
out
_free_sta
;
ret
=
wl1271_cmd_add_sta
(
wl
,
sta
,
hlid
);
ret
=
wl1271_cmd_add_sta
(
wl
,
sta
,
hlid
);
if
(
ret
<
0
)
if
(
ret
<
0
)
...
@@ -2673,6 +2749,10 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw,
...
@@ -2673,6 +2749,10 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw,
out_sleep:
out_sleep:
wl1271_ps_elp_sleep
(
wl
);
wl1271_ps_elp_sleep
(
wl
);
out_free_sta:
if
(
ret
<
0
)
wl1271_free_sta
(
wl
,
hlid
);
out:
out:
mutex_unlock
(
&
wl
->
mutex
);
mutex_unlock
(
&
wl
->
mutex
);
return
ret
;
return
ret
;
...
@@ -2709,7 +2789,7 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw,
...
@@ -2709,7 +2789,7 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw,
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
out_sleep
;
goto
out_sleep
;
wl1271_free_
hlid
(
wl
,
wl_sta
->
hlid
);
wl1271_free_
sta
(
wl
,
wl_sta
->
hlid
);
out_sleep:
out_sleep:
wl1271_ps_elp_sleep
(
wl
);
wl1271_ps_elp_sleep
(
wl
);
...
@@ -3212,7 +3292,9 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
...
@@ -3212,7 +3292,9 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
IEEE80211_HW_SUPPORTS_UAPSD
|
IEEE80211_HW_SUPPORTS_UAPSD
|
IEEE80211_HW_HAS_RATE_CONTROL
|
IEEE80211_HW_HAS_RATE_CONTROL
|
IEEE80211_HW_CONNECTION_MONITOR
|
IEEE80211_HW_CONNECTION_MONITOR
|
IEEE80211_HW_SUPPORTS_CQM_RSSI
;
IEEE80211_HW_SUPPORTS_CQM_RSSI
|
IEEE80211_HW_REPORTS_TX_ACK_STATUS
|
IEEE80211_HW_AP_LINK_PS
;
wl
->
hw
->
wiphy
->
cipher_suites
=
cipher_suites
;
wl
->
hw
->
wiphy
->
cipher_suites
=
cipher_suites
;
wl
->
hw
->
wiphy
->
n_cipher_suites
=
ARRAY_SIZE
(
cipher_suites
);
wl
->
hw
->
wiphy
->
n_cipher_suites
=
ARRAY_SIZE
(
cipher_suites
);
...
@@ -3264,7 +3346,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
...
@@ -3264,7 +3346,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
struct
ieee80211_hw
*
hw
;
struct
ieee80211_hw
*
hw
;
struct
platform_device
*
plat_dev
=
NULL
;
struct
platform_device
*
plat_dev
=
NULL
;
struct
wl1271
*
wl
;
struct
wl1271
*
wl
;
int
i
,
ret
;
int
i
,
j
,
ret
;
unsigned
int
order
;
unsigned
int
order
;
hw
=
ieee80211_alloc_hw
(
sizeof
(
*
wl
),
&
wl1271_ops
);
hw
=
ieee80211_alloc_hw
(
sizeof
(
*
wl
),
&
wl1271_ops
);
...
@@ -3292,6 +3374,10 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
...
@@ -3292,6 +3374,10 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
for
(
i
=
0
;
i
<
NUM_TX_QUEUES
;
i
++
)
for
(
i
=
0
;
i
<
NUM_TX_QUEUES
;
i
++
)
skb_queue_head_init
(
&
wl
->
tx_queue
[
i
]);
skb_queue_head_init
(
&
wl
->
tx_queue
[
i
]);
for
(
i
=
0
;
i
<
NUM_TX_QUEUES
;
i
++
)
for
(
j
=
0
;
j
<
AP_MAX_LINKS
;
j
++
)
skb_queue_head_init
(
&
wl
->
links
[
j
].
tx_queue
[
i
]);
INIT_DELAYED_WORK
(
&
wl
->
elp_work
,
wl1271_elp_work
);
INIT_DELAYED_WORK
(
&
wl
->
elp_work
,
wl1271_elp_work
);
INIT_DELAYED_WORK
(
&
wl
->
pspoll_work
,
wl1271_pspoll_work
);
INIT_DELAYED_WORK
(
&
wl
->
pspoll_work
,
wl1271_pspoll_work
);
INIT_WORK
(
&
wl
->
irq_work
,
wl1271_irq_work
);
INIT_WORK
(
&
wl
->
irq_work
,
wl1271_irq_work
);
...
@@ -3317,6 +3403,9 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
...
@@ -3317,6 +3403,9 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl
->
bss_type
=
MAX_BSS_TYPE
;
wl
->
bss_type
=
MAX_BSS_TYPE
;
wl
->
set_bss_type
=
MAX_BSS_TYPE
;
wl
->
set_bss_type
=
MAX_BSS_TYPE
;
wl
->
fw_bss_type
=
MAX_BSS_TYPE
;
wl
->
fw_bss_type
=
MAX_BSS_TYPE
;
wl
->
last_tx_hlid
=
0
;
wl
->
ap_ps_map
=
0
;
wl
->
ap_fw_ps_map
=
0
;
memset
(
wl
->
tx_frames_map
,
0
,
sizeof
(
wl
->
tx_frames_map
));
memset
(
wl
->
tx_frames_map
,
0
,
sizeof
(
wl
->
tx_frames_map
));
for
(
i
=
0
;
i
<
ACX_TX_DESCRIPTORS
;
i
++
)
for
(
i
=
0
;
i
<
ACX_TX_DESCRIPTORS
;
i
++
)
...
@@ -3412,5 +3501,5 @@ module_param_named(debug_level, wl12xx_debug_level, uint, S_IRUSR | S_IWUSR);
...
@@ -3412,5 +3501,5 @@ module_param_named(debug_level, wl12xx_debug_level, uint, S_IRUSR | S_IWUSR);
MODULE_PARM_DESC
(
debug_level
,
"wl12xx debugging level"
);
MODULE_PARM_DESC
(
debug_level
,
"wl12xx debugging level"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Luciano Coelho <
luciano.coelho@nokia
.com>"
);
MODULE_AUTHOR
(
"Luciano Coelho <
coelho@ti
.com>"
);
MODULE_AUTHOR
(
"Juuso Oikarinen <juuso.oikarinen@nokia.com>"
);
MODULE_AUTHOR
(
"Juuso Oikarinen <juuso.oikarinen@nokia.com>"
);
drivers/net/wireless/wl12xx/ps.c
View file @
42774986
...
@@ -24,6 +24,7 @@
...
@@ -24,6 +24,7 @@
#include "reg.h"
#include "reg.h"
#include "ps.h"
#include "ps.h"
#include "io.h"
#include "io.h"
#include "tx.h"
#define WL1271_WAKEUP_TIMEOUT 500
#define WL1271_WAKEUP_TIMEOUT 500
...
@@ -173,4 +174,81 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
...
@@ -173,4 +174,81 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
return
ret
;
return
ret
;
}
}
static
void
wl1271_ps_filter_frames
(
struct
wl1271
*
wl
,
u8
hlid
)
{
int
i
,
filtered
=
0
;
struct
sk_buff
*
skb
;
struct
ieee80211_tx_info
*
info
;
unsigned
long
flags
;
/* filter all frames currently the low level queus for this hlid */
for
(
i
=
0
;
i
<
NUM_TX_QUEUES
;
i
++
)
{
while
((
skb
=
skb_dequeue
(
&
wl
->
links
[
hlid
].
tx_queue
[
i
])))
{
info
=
IEEE80211_SKB_CB
(
skb
);
info
->
flags
|=
IEEE80211_TX_STAT_TX_FILTERED
;
info
->
status
.
rates
[
0
].
idx
=
-
1
;
ieee80211_tx_status
(
wl
->
hw
,
skb
);
filtered
++
;
}
}
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
wl
->
tx_queue_count
-=
filtered
;
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
wl1271_handle_tx_low_watermark
(
wl
);
}
void
wl1271_ps_link_start
(
struct
wl1271
*
wl
,
u8
hlid
,
bool
clean_queues
)
{
struct
ieee80211_sta
*
sta
;
if
(
test_bit
(
hlid
,
&
wl
->
ap_ps_map
))
return
;
wl1271_debug
(
DEBUG_PSM
,
"start mac80211 PSM on hlid %d blks %d "
"clean_queues %d"
,
hlid
,
wl
->
links
[
hlid
].
allocated_blks
,
clean_queues
);
rcu_read_lock
();
sta
=
ieee80211_find_sta
(
wl
->
vif
,
wl
->
links
[
hlid
].
addr
);
if
(
!
sta
)
{
wl1271_error
(
"could not find sta %pM for starting ps"
,
wl
->
links
[
hlid
].
addr
);
rcu_read_unlock
();
return
;
}
ieee80211_sta_ps_transition_ni
(
sta
,
true
);
rcu_read_unlock
();
/* do we want to filter all frames from this link's queues? */
if
(
clean_queues
)
wl1271_ps_filter_frames
(
wl
,
hlid
);
__set_bit
(
hlid
,
&
wl
->
ap_ps_map
);
}
void
wl1271_ps_link_end
(
struct
wl1271
*
wl
,
u8
hlid
)
{
struct
ieee80211_sta
*
sta
;
if
(
!
test_bit
(
hlid
,
&
wl
->
ap_ps_map
))
return
;
wl1271_debug
(
DEBUG_PSM
,
"end mac80211 PSM on hlid %d"
,
hlid
);
__clear_bit
(
hlid
,
&
wl
->
ap_ps_map
);
rcu_read_lock
();
sta
=
ieee80211_find_sta
(
wl
->
vif
,
wl
->
links
[
hlid
].
addr
);
if
(
!
sta
)
{
wl1271_error
(
"could not find sta %pM for ending ps"
,
wl
->
links
[
hlid
].
addr
);
goto
end
;
}
ieee80211_sta_ps_transition_ni
(
sta
,
false
);
end:
rcu_read_unlock
();
}
drivers/net/wireless/wl12xx/ps.h
View file @
42774986
...
@@ -32,5 +32,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
...
@@ -32,5 +32,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
void
wl1271_ps_elp_sleep
(
struct
wl1271
*
wl
);
void
wl1271_ps_elp_sleep
(
struct
wl1271
*
wl
);
int
wl1271_ps_elp_wakeup
(
struct
wl1271
*
wl
,
bool
chip_awake
);
int
wl1271_ps_elp_wakeup
(
struct
wl1271
*
wl
,
bool
chip_awake
);
void
wl1271_elp_work
(
struct
work_struct
*
work
);
void
wl1271_elp_work
(
struct
work_struct
*
work
);
void
wl1271_ps_link_start
(
struct
wl1271
*
wl
,
u8
hlid
,
bool
clean_queues
);
void
wl1271_ps_link_end
(
struct
wl1271
*
wl
,
u8
hlid
);
#endif
/* __WL1271_PS_H__ */
#endif
/* __WL1271_PS_H__ */
drivers/net/wireless/wl12xx/rx.c
View file @
42774986
...
@@ -92,7 +92,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
...
@@ -92,7 +92,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
{
{
struct
wl1271_rx_descriptor
*
desc
;
struct
wl1271_rx_descriptor
*
desc
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
u16
*
fc
;
struct
ieee80211_hdr
*
hdr
;
u8
*
buf
;
u8
*
buf
;
u8
beacon
=
0
;
u8
beacon
=
0
;
...
@@ -118,8 +118,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
...
@@ -118,8 +118,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
/* now we pull the descriptor out of the buffer */
/* now we pull the descriptor out of the buffer */
skb_pull
(
skb
,
sizeof
(
*
desc
));
skb_pull
(
skb
,
sizeof
(
*
desc
));
fc
=
(
u16
*
)
skb
->
data
;
hdr
=
(
struct
ieee80211_hdr
*
)
skb
->
data
;
if
(
(
*
fc
&
IEEE80211_FCTL_STYPE
)
==
IEEE80211_STYPE_BEACON
)
if
(
ieee80211_is_beacon
(
hdr
->
frame_control
)
)
beacon
=
1
;
beacon
=
1
;
wl1271_rx_status
(
wl
,
desc
,
IEEE80211_SKB_RXCB
(
skb
),
beacon
);
wl1271_rx_status
(
wl
,
desc
,
IEEE80211_SKB_RXCB
(
skb
),
beacon
);
...
...
drivers/net/wireless/wl12xx/rx.h
View file @
42774986
...
@@ -30,10 +30,6 @@
...
@@ -30,10 +30,6 @@
#define WL1271_RX_MAX_RSSI -30
#define WL1271_RX_MAX_RSSI -30
#define WL1271_RX_MIN_RSSI -95
#define WL1271_RX_MIN_RSSI -95
#define WL1271_RX_ALIGN_TO 4
#define WL1271_RX_ALIGN(len) (((len) + WL1271_RX_ALIGN_TO - 1) & \
~(WL1271_RX_ALIGN_TO - 1))
#define SHORT_PREAMBLE_BIT BIT(0)
#define SHORT_PREAMBLE_BIT BIT(0)
#define OFDM_RATE_BIT BIT(6)
#define OFDM_RATE_BIT BIT(6)
#define PBCC_RATE_BIT BIT(7)
#define PBCC_RATE_BIT BIT(7)
...
...
drivers/net/wireless/wl12xx/tx.c
View file @
42774986
This diff is collapsed.
Click to expand it.
drivers/net/wireless/wl12xx/tx.h
View file @
42774986
...
@@ -53,8 +53,6 @@
...
@@ -53,8 +53,6 @@
#define TX_HW_RESULT_QUEUE_LEN_MASK 0xf
#define TX_HW_RESULT_QUEUE_LEN_MASK 0xf
#define WL1271_TX_ALIGN_TO 4
#define WL1271_TX_ALIGN_TO 4
#define WL1271_TX_ALIGN(len) (((len) + WL1271_TX_ALIGN_TO - 1) & \
~(WL1271_TX_ALIGN_TO - 1))
#define WL1271_TKIP_IV_SPACE 4
#define WL1271_TKIP_IV_SPACE 4
struct
wl1271_tx_hw_descr
{
struct
wl1271_tx_hw_descr
{
...
@@ -152,5 +150,8 @@ void wl1271_tx_flush(struct wl1271 *wl);
...
@@ -152,5 +150,8 @@ void wl1271_tx_flush(struct wl1271 *wl);
u8
wl1271_rate_to_idx
(
int
rate
,
enum
ieee80211_band
band
);
u8
wl1271_rate_to_idx
(
int
rate
,
enum
ieee80211_band
band
);
u32
wl1271_tx_enabled_rates_get
(
struct
wl1271
*
wl
,
u32
rate_set
);
u32
wl1271_tx_enabled_rates_get
(
struct
wl1271
*
wl
,
u32
rate_set
);
u32
wl1271_tx_min_rate_get
(
struct
wl1271
*
wl
);
u32
wl1271_tx_min_rate_get
(
struct
wl1271
*
wl
);
u8
wl1271_tx_get_hlid
(
struct
sk_buff
*
skb
);
void
wl1271_tx_reset_link_queues
(
struct
wl1271
*
wl
,
u8
hlid
);
void
wl1271_handle_tx_low_watermark
(
struct
wl1271
*
wl
);
#endif
#endif
drivers/net/wireless/wl12xx/wl12xx.h
View file @
42774986
...
@@ -153,6 +153,17 @@ extern u32 wl12xx_debug_level;
...
@@ -153,6 +153,17 @@ extern u32 wl12xx_debug_level;
#define WL1271_AP_BROADCAST_HLID 1
#define WL1271_AP_BROADCAST_HLID 1
#define WL1271_AP_STA_HLID_START 2
#define WL1271_AP_STA_HLID_START 2
/*
* When in AP-mode, we allow (at least) this number of mem-blocks
* to be transmitted to FW for a STA in PS-mode. Only when packets are
* present in the FW buffers it will wake the sleeping STA. We want to put
* enough packets for the driver to transmit all of its buffered data before
* the STA goes to sleep again. But we don't want to take too much mem-blocks
* as it might hurt the throughput of active STAs.
* The number of blocks (18) is enough for 2 large packets.
*/
#define WL1271_PS_STA_MAX_BLOCKS (2 * 9)
#define WL1271_AP_BSS_INDEX 0
#define WL1271_AP_BSS_INDEX 0
#define WL1271_AP_DEF_INACTIV_SEC 300
#define WL1271_AP_DEF_INACTIV_SEC 300
#define WL1271_AP_DEF_BEACON_EXP 20
#define WL1271_AP_DEF_BEACON_EXP 20
...
@@ -319,6 +330,17 @@ enum wl12xx_flags {
...
@@ -319,6 +330,17 @@ enum wl12xx_flags {
WL1271_FLAG_AP_STARTED
WL1271_FLAG_AP_STARTED
};
};
struct
wl1271_link
{
/* AP-mode - TX queue per AC in link */
struct
sk_buff_head
tx_queue
[
NUM_TX_QUEUES
];
/* accounting for allocated / available TX blocks in FW */
u8
allocated_blks
;
u8
prev_freed_blks
;
u8
addr
[
ETH_ALEN
];
};
struct
wl1271
{
struct
wl1271
{
struct
platform_device
*
plat_dev
;
struct
platform_device
*
plat_dev
;
struct
ieee80211_hw
*
hw
;
struct
ieee80211_hw
*
hw
;
...
@@ -498,6 +520,21 @@ struct wl1271 {
...
@@ -498,6 +520,21 @@ struct wl1271 {
/* RX BA constraint value */
/* RX BA constraint value */
bool
ba_support
;
bool
ba_support
;
u8
ba_rx_bitmap
;
u8
ba_rx_bitmap
;
/*
* AP-mode - links indexed by HLID. The global and broadcast links
* are always active.
*/
struct
wl1271_link
links
[
AP_MAX_LINKS
];
/* the hlid of the link where the last transmitted skb came from */
int
last_tx_hlid
;
/* AP-mode - a bitmap of links currently in PS mode according to FW */
u32
ap_fw_ps_map
;
/* AP-mode - a bitmap of links currently in PS mode in mac80211 */
unsigned
long
ap_ps_map
;
};
};
struct
wl1271_station
{
struct
wl1271_station
{
...
...
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