Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
b376704b
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
b376704b
编写于
5月 13, 2011
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'for-linville' of
git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx
上级
1159024d
9439064c
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
728 addition
and
16 deletion
+728
-16
drivers/net/wireless/wl12xx/boot.c
drivers/net/wireless/wl12xx/boot.c
+3
-1
drivers/net/wireless/wl12xx/conf.h
drivers/net/wireless/wl12xx/conf.h
+21
-0
drivers/net/wireless/wl12xx/debugfs.c
drivers/net/wireless/wl12xx/debugfs.c
+1
-0
drivers/net/wireless/wl12xx/event.c
drivers/net/wireless/wl12xx/event.c
+23
-0
drivers/net/wireless/wl12xx/main.c
drivers/net/wireless/wl12xx/main.c
+247
-13
drivers/net/wireless/wl12xx/ps.h
drivers/net/wireless/wl12xx/ps.h
+2
-0
drivers/net/wireless/wl12xx/scan.c
drivers/net/wireless/wl12xx/scan.c
+243
-0
drivers/net/wireless/wl12xx/scan.h
drivers/net/wireless/wl12xx/scan.h
+114
-0
drivers/net/wireless/wl12xx/sdio.c
drivers/net/wireless/wl12xx/sdio.c
+63
-1
drivers/net/wireless/wl12xx/wl12xx.h
drivers/net/wireless/wl12xx/wl12xx.h
+11
-1
未找到文件。
drivers/net/wireless/wl12xx/boot.c
浏览文件 @
b376704b
...
@@ -478,7 +478,9 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
...
@@ -478,7 +478,9 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
DISCONNECT_EVENT_COMPLETE_ID
|
DISCONNECT_EVENT_COMPLETE_ID
|
RSSI_SNR_TRIGGER_0_EVENT_ID
|
RSSI_SNR_TRIGGER_0_EVENT_ID
|
PSPOLL_DELIVERY_FAILURE_EVENT_ID
|
PSPOLL_DELIVERY_FAILURE_EVENT_ID
|
SOFT_GEMINI_SENSE_EVENT_ID
;
SOFT_GEMINI_SENSE_EVENT_ID
|
PERIODIC_SCAN_REPORT_EVENT_ID
|
PERIODIC_SCAN_COMPLETE_EVENT_ID
;
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
wl
->
event_mask
|=
STA_REMOVE_COMPLETE_EVENT_ID
;
wl
->
event_mask
|=
STA_REMOVE_COMPLETE_EVENT_ID
;
...
...
drivers/net/wireless/wl12xx/conf.h
浏览文件 @
b376704b
...
@@ -1147,6 +1147,26 @@ struct conf_scan_settings {
...
@@ -1147,6 +1147,26 @@ struct conf_scan_settings {
};
};
struct
conf_sched_scan_settings
{
/* minimum time to wait on the channel for active scans (in TUs) */
u16
min_dwell_time_active
;
/* maximum time to wait on the channel for active scans (in TUs) */
u16
max_dwell_time_active
;
/* time to wait on the channel for passive scans (in TUs) */
u32
dwell_time_passive
;
/* number of probe requests to send on each channel in active scans */
u8
num_probe_reqs
;
/* RSSI threshold to be used for filtering */
s8
rssi_threshold
;
/* SNR threshold to be used for filtering */
s8
snr_threshold
;
};
/* these are number of channels on the band divided by two, rounded up */
/* 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_2 7
#define CONF_TX_PWR_COMPENSATION_LEN_5 18
#define CONF_TX_PWR_COMPENSATION_LEN_5 18
...
@@ -1234,6 +1254,7 @@ struct conf_drv_settings {
...
@@ -1234,6 +1254,7 @@ struct conf_drv_settings {
struct
conf_pm_config_settings
pm_config
;
struct
conf_pm_config_settings
pm_config
;
struct
conf_roam_trigger_settings
roam_trigger
;
struct
conf_roam_trigger_settings
roam_trigger
;
struct
conf_scan_settings
scan
;
struct
conf_scan_settings
scan
;
struct
conf_sched_scan_settings
sched_scan
;
struct
conf_rf_settings
rf
;
struct
conf_rf_settings
rf
;
struct
conf_ht_setting
ht
;
struct
conf_ht_setting
ht
;
struct
conf_memory_settings
mem_wl127x
;
struct
conf_memory_settings
mem_wl127x
;
...
...
drivers/net/wireless/wl12xx/debugfs.c
浏览文件 @
b376704b
...
@@ -377,6 +377,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
...
@@ -377,6 +377,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
DRIVER_STATE_PRINT_HEX
(
platform_quirks
);
DRIVER_STATE_PRINT_HEX
(
platform_quirks
);
DRIVER_STATE_PRINT_HEX
(
chip
.
id
);
DRIVER_STATE_PRINT_HEX
(
chip
.
id
);
DRIVER_STATE_PRINT_STR
(
chip
.
fw_ver_str
);
DRIVER_STATE_PRINT_STR
(
chip
.
fw_ver_str
);
DRIVER_STATE_PRINT_INT
(
sched_scanning
);
#undef DRIVER_STATE_PRINT_INT
#undef DRIVER_STATE_PRINT_INT
#undef DRIVER_STATE_PRINT_LONG
#undef DRIVER_STATE_PRINT_LONG
...
...
drivers/net/wireless/wl12xx/event.c
浏览文件 @
b376704b
...
@@ -135,6 +135,13 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
...
@@ -135,6 +135,13 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
/* enable beacon early termination */
/* enable beacon early termination */
ret
=
wl1271_acx_bet_enable
(
wl
,
true
);
ret
=
wl1271_acx_bet_enable
(
wl
,
true
);
if
(
ret
<
0
)
break
;
if
(
wl
->
ps_compl
)
{
complete
(
wl
->
ps_compl
);
wl
->
ps_compl
=
NULL
;
}
break
;
break
;
default:
default:
break
;
break
;
...
@@ -188,6 +195,22 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
...
@@ -188,6 +195,22 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
wl1271_scan_stm
(
wl
);
wl1271_scan_stm
(
wl
);
}
}
if
(
vector
&
PERIODIC_SCAN_REPORT_EVENT_ID
)
{
wl1271_debug
(
DEBUG_EVENT
,
"PERIODIC_SCAN_REPORT_EVENT "
"(status 0x%0x)"
,
mbox
->
scheduled_scan_status
);
wl1271_scan_sched_scan_results
(
wl
);
}
if
(
vector
&
PERIODIC_SCAN_COMPLETE_EVENT_ID
)
{
wl1271_debug
(
DEBUG_EVENT
,
"PERIODIC_SCAN_COMPLETE_EVENT "
"(status 0x%0x)"
,
mbox
->
scheduled_scan_status
);
if
(
wl
->
sched_scanning
)
{
wl1271_scan_sched_scan_stop
(
wl
);
ieee80211_sched_scan_stopped
(
wl
->
hw
);
}
}
/* disable dynamic PS when requested by the firmware */
/* disable dynamic PS when requested by the firmware */
if
(
vector
&
SOFT_GEMINI_SENSE_EVENT_ID
&&
if
(
vector
&
SOFT_GEMINI_SENSE_EVENT_ID
&&
wl
->
bss_type
==
BSS_TYPE_STA_BSS
)
{
wl
->
bss_type
==
BSS_TYPE_STA_BSS
)
{
...
...
drivers/net/wireless/wl12xx/main.c
浏览文件 @
b376704b
...
@@ -257,12 +257,16 @@ static struct conf_drv_settings default_conf = {
...
@@ -257,12 +257,16 @@ static struct conf_drv_settings default_conf = {
.
wake_up_event
=
CONF_WAKE_UP_EVENT_DTIM
,
.
wake_up_event
=
CONF_WAKE_UP_EVENT_DTIM
,
.
listen_interval
=
1
,
.
listen_interval
=
1
,
.
bcn_filt_mode
=
CONF_BCN_FILT_MODE_ENABLED
,
.
bcn_filt_mode
=
CONF_BCN_FILT_MODE_ENABLED
,
.
bcn_filt_ie_count
=
1
,
.
bcn_filt_ie_count
=
2
,
.
bcn_filt_ie
=
{
.
bcn_filt_ie
=
{
[
0
]
=
{
[
0
]
=
{
.
ie
=
WLAN_EID_CHANNEL_SWITCH
,
.
ie
=
WLAN_EID_CHANNEL_SWITCH
,
.
rule
=
CONF_BCN_RULE_PASS_ON_APPEARANCE
,
.
rule
=
CONF_BCN_RULE_PASS_ON_APPEARANCE
,
}
},
[
1
]
=
{
.
ie
=
WLAN_EID_HT_INFORMATION
,
.
rule
=
CONF_BCN_RULE_PASS_ON_CHANGE
,
},
},
},
.
synch_fail_thold
=
10
,
.
synch_fail_thold
=
10
,
.
bss_lose_timeout
=
100
,
.
bss_lose_timeout
=
100
,
...
@@ -302,6 +306,15 @@ static struct conf_drv_settings default_conf = {
...
@@ -302,6 +306,15 @@ static struct conf_drv_settings default_conf = {
.
max_dwell_time_passive
=
100000
,
.
max_dwell_time_passive
=
100000
,
.
num_probe_reqs
=
2
,
.
num_probe_reqs
=
2
,
},
},
.
sched_scan
=
{
/* sched_scan requires dwell times in TU instead of TU/1000 */
.
min_dwell_time_active
=
8
,
.
max_dwell_time_active
=
30
,
.
dwell_time_passive
=
100
,
.
num_probe_reqs
=
2
,
.
rssi_threshold
=
-
90
,
.
snr_threshold
=
0
,
},
.
rf
=
{
.
rf
=
{
.
tx_per_channel_power_compensation_2
=
{
.
tx_per_channel_power_compensation_2
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
...
@@ -975,6 +988,11 @@ static void wl1271_recovery_work(struct work_struct *work)
...
@@ -975,6 +988,11 @@ static void wl1271_recovery_work(struct work_struct *work)
/* Prevent spurious TX during FW restart */
/* Prevent spurious TX during FW restart */
ieee80211_stop_queues
(
wl
->
hw
);
ieee80211_stop_queues
(
wl
->
hw
);
if
(
wl
->
sched_scanning
)
{
ieee80211_sched_scan_stopped
(
wl
->
hw
);
wl
->
sched_scanning
=
false
;
}
/* reboot the chipset */
/* reboot the chipset */
__wl1271_op_remove_interface
(
wl
,
false
);
__wl1271_op_remove_interface
(
wl
,
false
);
ieee80211_restart_hw
(
wl
->
hw
);
ieee80211_restart_hw
(
wl
->
hw
);
...
@@ -1332,6 +1350,150 @@ static struct notifier_block wl1271_dev_notifier = {
...
@@ -1332,6 +1350,150 @@ static struct notifier_block wl1271_dev_notifier = {
.
notifier_call
=
wl1271_dev_notify
,
.
notifier_call
=
wl1271_dev_notify
,
};
};
static
int
wl1271_configure_suspend
(
struct
wl1271
*
wl
)
{
int
ret
;
if
(
wl
->
bss_type
!=
BSS_TYPE_STA_BSS
)
return
0
;
mutex_lock
(
&
wl
->
mutex
);
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out_unlock
;
/* enter psm if needed*/
if
(
!
test_bit
(
WL1271_FLAG_PSM
,
&
wl
->
flags
))
{
DECLARE_COMPLETION_ONSTACK
(
compl
);
wl
->
ps_compl
=
&
compl
;
ret
=
wl1271_ps_set_mode
(
wl
,
STATION_POWER_SAVE_MODE
,
wl
->
basic_rate
,
true
);
if
(
ret
<
0
)
goto
out_sleep
;
/* we must unlock here so we will be able to get events */
wl1271_ps_elp_sleep
(
wl
);
mutex_unlock
(
&
wl
->
mutex
);
ret
=
wait_for_completion_timeout
(
&
compl
,
msecs_to_jiffies
(
WL1271_PS_COMPLETE_TIMEOUT
));
if
(
ret
<=
0
)
{
wl1271_warning
(
"couldn't enter ps mode!"
);
ret
=
-
EBUSY
;
goto
out
;
}
/* take mutex again, and wakeup */
mutex_lock
(
&
wl
->
mutex
);
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out_unlock
;
}
out_sleep:
wl1271_ps_elp_sleep
(
wl
);
out_unlock:
mutex_unlock
(
&
wl
->
mutex
);
out:
return
ret
;
}
static
void
wl1271_configure_resume
(
struct
wl1271
*
wl
)
{
int
ret
;
if
(
wl
->
bss_type
!=
BSS_TYPE_STA_BSS
)
return
;
mutex_lock
(
&
wl
->
mutex
);
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out
;
/* exit psm if it wasn't configured */
if
(
!
test_bit
(
WL1271_FLAG_PSM_REQUESTED
,
&
wl
->
flags
))
wl1271_ps_set_mode
(
wl
,
STATION_ACTIVE_MODE
,
wl
->
basic_rate
,
true
);
wl1271_ps_elp_sleep
(
wl
);
out:
mutex_unlock
(
&
wl
->
mutex
);
}
static
int
wl1271_op_suspend
(
struct
ieee80211_hw
*
hw
,
struct
cfg80211_wowlan
*
wow
)
{
struct
wl1271
*
wl
=
hw
->
priv
;
wl1271_debug
(
DEBUG_MAC80211
,
"mac80211 suspend wow=%d"
,
!!
wow
);
wl
->
wow_enabled
=
!!
wow
;
if
(
wl
->
wow_enabled
)
{
int
ret
;
ret
=
wl1271_configure_suspend
(
wl
);
if
(
ret
<
0
)
{
wl1271_warning
(
"couldn't prepare device to suspend"
);
return
ret
;
}
/* flush any remaining work */
wl1271_debug
(
DEBUG_MAC80211
,
"flushing remaining works"
);
flush_delayed_work
(
&
wl
->
scan_complete_work
);
/*
* disable and re-enable interrupts in order to flush
* the threaded_irq
*/
wl1271_disable_interrupts
(
wl
);
/*
* set suspended flag to avoid triggering a new threaded_irq
* work. no need for spinlock as interrupts are disabled.
*/
set_bit
(
WL1271_FLAG_SUSPENDED
,
&
wl
->
flags
);
wl1271_enable_interrupts
(
wl
);
flush_work
(
&
wl
->
tx_work
);
flush_delayed_work
(
&
wl
->
pspoll_work
);
flush_delayed_work
(
&
wl
->
elp_work
);
}
return
0
;
}
static
int
wl1271_op_resume
(
struct
ieee80211_hw
*
hw
)
{
struct
wl1271
*
wl
=
hw
->
priv
;
wl1271_debug
(
DEBUG_MAC80211
,
"mac80211 resume wow=%d"
,
wl
->
wow_enabled
);
/*
* re-enable irq_work enqueuing, and call irq_work directly if
* there is a pending work.
*/
if
(
wl
->
wow_enabled
)
{
struct
wl1271
*
wl
=
hw
->
priv
;
unsigned
long
flags
;
bool
run_irq_work
=
false
;
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
clear_bit
(
WL1271_FLAG_SUSPENDED
,
&
wl
->
flags
);
if
(
test_and_clear_bit
(
WL1271_FLAG_PENDING_WORK
,
&
wl
->
flags
))
run_irq_work
=
true
;
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
if
(
run_irq_work
)
{
wl1271_debug
(
DEBUG_MAC80211
,
"run postponed irq_work directly"
);
wl1271_irq
(
0
,
wl
);
wl1271_enable_interrupts
(
wl
);
}
wl1271_configure_resume
(
wl
);
}
return
0
;
}
static
int
wl1271_op_start
(
struct
ieee80211_hw
*
hw
)
static
int
wl1271_op_start
(
struct
ieee80211_hw
*
hw
)
{
{
wl1271_debug
(
DEBUG_MAC80211
,
"mac80211 start"
);
wl1271_debug
(
DEBUG_MAC80211
,
"mac80211 start"
);
...
@@ -1563,6 +1725,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
...
@@ -1563,6 +1725,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *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_fw_ps_map
=
0
;
wl
->
ap_ps_map
=
0
;
wl
->
ap_ps_map
=
0
;
wl
->
sched_scanning
=
false
;
/*
/*
* this is performed after the cancel_work calls and the associated
* this is performed after the cancel_work calls and the associated
...
@@ -1765,6 +1928,13 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle)
...
@@ -1765,6 +1928,13 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle)
wl
->
session_counter
++
;
wl
->
session_counter
++
;
if
(
wl
->
session_counter
>=
SESSION_COUNTER_MAX
)
if
(
wl
->
session_counter
>=
SESSION_COUNTER_MAX
)
wl
->
session_counter
=
0
;
wl
->
session_counter
=
0
;
/* The current firmware only supports sched_scan in idle */
if
(
wl
->
sched_scanning
)
{
wl1271_scan_sched_scan_stop
(
wl
);
ieee80211_sched_scan_stopped
(
wl
->
hw
);
}
ret
=
wl1271_dummy_join
(
wl
);
ret
=
wl1271_dummy_join
(
wl
);
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
out
;
goto
out
;
...
@@ -2317,6 +2487,60 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
...
@@ -2317,6 +2487,60 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
return
ret
;
return
ret
;
}
}
static
int
wl1271_op_sched_scan_start
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
,
struct
cfg80211_sched_scan_request
*
req
,
struct
ieee80211_sched_scan_ies
*
ies
)
{
struct
wl1271
*
wl
=
hw
->
priv
;
int
ret
;
wl1271_debug
(
DEBUG_MAC80211
,
"wl1271_op_sched_scan_start"
);
mutex_lock
(
&
wl
->
mutex
);
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out
;
ret
=
wl1271_scan_sched_scan_config
(
wl
,
req
,
ies
);
if
(
ret
<
0
)
goto
out_sleep
;
ret
=
wl1271_scan_sched_scan_start
(
wl
);
if
(
ret
<
0
)
goto
out_sleep
;
wl
->
sched_scanning
=
true
;
out_sleep:
wl1271_ps_elp_sleep
(
wl
);
out:
mutex_unlock
(
&
wl
->
mutex
);
return
ret
;
}
static
void
wl1271_op_sched_scan_stop
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
)
{
struct
wl1271
*
wl
=
hw
->
priv
;
int
ret
;
wl1271_debug
(
DEBUG_MAC80211
,
"wl1271_op_sched_scan_stop"
);
mutex_lock
(
&
wl
->
mutex
);
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out
;
wl1271_scan_sched_scan_stop
(
wl
);
wl1271_ps_elp_sleep
(
wl
);
out:
mutex_unlock
(
&
wl
->
mutex
);
}
static
int
wl1271_op_set_frag_threshold
(
struct
ieee80211_hw
*
hw
,
u32
value
)
static
int
wl1271_op_set_frag_threshold
(
struct
ieee80211_hw
*
hw
,
u32
value
)
{
{
struct
wl1271
*
wl
=
hw
->
priv
;
struct
wl1271
*
wl
=
hw
->
priv
;
...
@@ -2376,20 +2600,24 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
...
@@ -2376,20 +2600,24 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
static
int
wl1271_ssid_set
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
,
static
int
wl1271_ssid_set
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
,
int
offset
)
int
offset
)
{
{
u8
*
ptr
=
skb
->
data
+
offset
;
u8
ssid_len
;
const
u8
*
ptr
=
cfg80211_find_ie
(
WLAN_EID_SSID
,
skb
->
data
+
offset
,
skb
->
len
-
offset
);
/* find the location of the ssid in the beacon */
if
(
!
ptr
)
{
while
(
ptr
<
skb
->
data
+
skb
->
len
)
{
wl1271_error
(
"No SSID in IEs!"
);
if
(
ptr
[
0
]
==
WLAN_EID_SSID
)
{
return
-
ENOENT
;
wl
->
ssid_len
=
ptr
[
1
];
memcpy
(
wl
->
ssid
,
ptr
+
2
,
wl
->
ssid_len
);
return
0
;
}
ptr
+=
(
ptr
[
1
]
+
2
);
}
}
wl1271_error
(
"No SSID in IEs!
\n
"
);
ssid_len
=
ptr
[
1
];
return
-
ENOENT
;
if
(
ssid_len
>
IEEE80211_MAX_SSID_LEN
)
{
wl1271_error
(
"SSID is too long!"
);
return
-
EINVAL
;
}
wl
->
ssid_len
=
ssid_len
;
memcpy
(
wl
->
ssid
,
ptr
+
2
,
ssid_len
);
return
0
;
}
}
static
int
wl1271_bss_erp_info_changed
(
struct
wl1271
*
wl
,
static
int
wl1271_bss_erp_info_changed
(
struct
wl1271
*
wl
,
...
@@ -3422,12 +3650,16 @@ static const struct ieee80211_ops wl1271_ops = {
...
@@ -3422,12 +3650,16 @@ static const struct ieee80211_ops wl1271_ops = {
.
stop
=
wl1271_op_stop
,
.
stop
=
wl1271_op_stop
,
.
add_interface
=
wl1271_op_add_interface
,
.
add_interface
=
wl1271_op_add_interface
,
.
remove_interface
=
wl1271_op_remove_interface
,
.
remove_interface
=
wl1271_op_remove_interface
,
.
suspend
=
wl1271_op_suspend
,
.
resume
=
wl1271_op_resume
,
.
config
=
wl1271_op_config
,
.
config
=
wl1271_op_config
,
.
prepare_multicast
=
wl1271_op_prepare_multicast
,
.
prepare_multicast
=
wl1271_op_prepare_multicast
,
.
configure_filter
=
wl1271_op_configure_filter
,
.
configure_filter
=
wl1271_op_configure_filter
,
.
tx
=
wl1271_op_tx
,
.
tx
=
wl1271_op_tx
,
.
set_key
=
wl1271_op_set_key
,
.
set_key
=
wl1271_op_set_key
,
.
hw_scan
=
wl1271_op_hw_scan
,
.
hw_scan
=
wl1271_op_hw_scan
,
.
sched_scan_start
=
wl1271_op_sched_scan_start
,
.
sched_scan_stop
=
wl1271_op_sched_scan_stop
,
.
bss_info_changed
=
wl1271_op_bss_info_changed
,
.
bss_info_changed
=
wl1271_op_bss_info_changed
,
.
set_frag_threshold
=
wl1271_op_set_frag_threshold
,
.
set_frag_threshold
=
wl1271_op_set_frag_threshold
,
.
set_rts_threshold
=
wl1271_op_set_rts_threshold
,
.
set_rts_threshold
=
wl1271_op_set_rts_threshold
,
...
@@ -3626,6 +3858,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
...
@@ -3626,6 +3858,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
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_REPORTS_TX_ACK_STATUS
|
IEEE80211_HW_SPECTRUM_MGMT
|
IEEE80211_HW_AP_LINK_PS
;
IEEE80211_HW_AP_LINK_PS
;
wl
->
hw
->
wiphy
->
cipher_suites
=
cipher_suites
;
wl
->
hw
->
wiphy
->
cipher_suites
=
cipher_suites
;
...
@@ -3747,6 +3980,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
...
@@ -3747,6 +3980,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl
->
ap_fw_ps_map
=
0
;
wl
->
ap_fw_ps_map
=
0
;
wl
->
quirks
=
0
;
wl
->
quirks
=
0
;
wl
->
platform_quirks
=
0
;
wl
->
platform_quirks
=
0
;
wl
->
sched_scanning
=
false
;
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
++
)
...
...
drivers/net/wireless/wl12xx/ps.h
浏览文件 @
b376704b
...
@@ -35,4 +35,6 @@ void wl1271_elp_work(struct work_struct *work);
...
@@ -35,4 +35,6 @@ 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_start
(
struct
wl1271
*
wl
,
u8
hlid
,
bool
clean_queues
);
void
wl1271_ps_link_end
(
struct
wl1271
*
wl
,
u8
hlid
);
void
wl1271_ps_link_end
(
struct
wl1271
*
wl
,
u8
hlid
);
#define WL1271_PS_COMPLETE_TIMEOUT 500
#endif
/* __WL1271_PS_H__ */
#endif
/* __WL1271_PS_H__ */
drivers/net/wireless/wl12xx/scan.c
浏览文件 @
b376704b
...
@@ -320,3 +320,246 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
...
@@ -320,3 +320,246 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
return
0
;
return
0
;
}
}
static
int
wl1271_scan_get_sched_scan_channels
(
struct
wl1271
*
wl
,
struct
cfg80211_sched_scan_request
*
req
,
struct
conn_scan_ch_params
*
channels
,
u32
band
,
bool
radar
,
bool
passive
,
int
start
)
{
struct
conf_sched_scan_settings
*
c
=
&
wl
->
conf
.
sched_scan
;
int
i
,
j
;
u32
flags
;
for
(
i
=
0
,
j
=
start
;
i
<
req
->
n_channels
&&
j
<
MAX_CHANNELS_ALL_BANDS
;
i
++
)
{
flags
=
req
->
channels
[
i
]
->
flags
;
if
(
!
(
flags
&
IEEE80211_CHAN_DISABLED
)
&&
((
flags
&
IEEE80211_CHAN_PASSIVE_SCAN
)
==
passive
)
&&
((
flags
&
IEEE80211_CHAN_RADAR
)
==
radar
)
&&
(
req
->
channels
[
i
]
->
band
==
band
))
{
wl1271_debug
(
DEBUG_SCAN
,
"band %d, center_freq %d "
,
req
->
channels
[
i
]
->
band
,
req
->
channels
[
i
]
->
center_freq
);
wl1271_debug
(
DEBUG_SCAN
,
"hw_value %d, flags %X"
,
req
->
channels
[
i
]
->
hw_value
,
req
->
channels
[
i
]
->
flags
);
wl1271_debug
(
DEBUG_SCAN
,
"max_power %d"
,
req
->
channels
[
i
]
->
max_power
);
if
(
flags
&
IEEE80211_CHAN_PASSIVE_SCAN
)
{
channels
[
j
].
passive_duration
=
cpu_to_le16
(
c
->
dwell_time_passive
);
}
else
{
channels
[
j
].
min_duration
=
cpu_to_le16
(
c
->
min_dwell_time_active
);
channels
[
j
].
max_duration
=
cpu_to_le16
(
c
->
max_dwell_time_active
);
}
channels
[
j
].
tx_power_att
=
req
->
channels
[
j
]
->
max_power
;
channels
[
j
].
channel
=
req
->
channels
[
i
]
->
hw_value
;
j
++
;
}
}
return
j
-
start
;
}
static
int
wl1271_scan_sched_scan_channels
(
struct
wl1271
*
wl
,
struct
cfg80211_sched_scan_request
*
req
,
struct
wl1271_cmd_sched_scan_config
*
cfg
)
{
int
idx
=
0
;
cfg
->
passive
[
0
]
=
wl1271_scan_get_sched_scan_channels
(
wl
,
req
,
cfg
->
channels
,
IEEE80211_BAND_2GHZ
,
false
,
true
,
idx
);
idx
+=
cfg
->
passive
[
0
];
cfg
->
active
[
0
]
=
wl1271_scan_get_sched_scan_channels
(
wl
,
req
,
cfg
->
channels
,
IEEE80211_BAND_2GHZ
,
false
,
false
,
idx
);
idx
+=
cfg
->
active
[
0
];
cfg
->
passive
[
1
]
=
wl1271_scan_get_sched_scan_channels
(
wl
,
req
,
cfg
->
channels
,
IEEE80211_BAND_5GHZ
,
false
,
true
,
idx
);
idx
+=
cfg
->
passive
[
1
];
cfg
->
active
[
1
]
=
wl1271_scan_get_sched_scan_channels
(
wl
,
req
,
cfg
->
channels
,
IEEE80211_BAND_5GHZ
,
false
,
false
,
14
);
idx
+=
cfg
->
active
[
1
];
cfg
->
dfs
=
wl1271_scan_get_sched_scan_channels
(
wl
,
req
,
cfg
->
channels
,
IEEE80211_BAND_5GHZ
,
true
,
false
,
idx
);
idx
+=
cfg
->
dfs
;
wl1271_debug
(
DEBUG_SCAN
,
" 2.4GHz: active %d passive %d"
,
cfg
->
active
[
0
],
cfg
->
passive
[
0
]);
wl1271_debug
(
DEBUG_SCAN
,
" 5GHz: active %d passive %d"
,
cfg
->
active
[
1
],
cfg
->
passive
[
1
]);
return
idx
;
}
int
wl1271_scan_sched_scan_config
(
struct
wl1271
*
wl
,
struct
cfg80211_sched_scan_request
*
req
,
struct
ieee80211_sched_scan_ies
*
ies
)
{
struct
wl1271_cmd_sched_scan_config
*
cfg
=
NULL
;
struct
conf_sched_scan_settings
*
c
=
&
wl
->
conf
.
sched_scan
;
int
i
,
total_channels
,
ret
;
wl1271_debug
(
DEBUG_CMD
,
"cmd sched_scan scan config"
);
cfg
=
kzalloc
(
sizeof
(
*
cfg
),
GFP_KERNEL
);
if
(
!
cfg
)
return
-
ENOMEM
;
cfg
->
rssi_threshold
=
c
->
rssi_threshold
;
cfg
->
snr_threshold
=
c
->
snr_threshold
;
cfg
->
n_probe_reqs
=
c
->
num_probe_reqs
;
/* cycles set to 0 it means infinite (until manually stopped) */
cfg
->
cycles
=
0
;
/* report APs when at least 1 is found */
cfg
->
report_after
=
1
;
/* don't stop scanning automatically when something is found */
cfg
->
terminate
=
0
;
cfg
->
tag
=
WL1271_SCAN_DEFAULT_TAG
;
/* don't filter on BSS type */
cfg
->
bss_type
=
SCAN_BSS_TYPE_ANY
;
/* currently NL80211 supports only a single interval */
for
(
i
=
0
;
i
<
SCAN_MAX_CYCLE_INTERVALS
;
i
++
)
cfg
->
intervals
[
i
]
=
cpu_to_le32
(
req
->
interval
);
if
(
req
->
ssids
[
0
].
ssid_len
&&
req
->
ssids
[
0
].
ssid
)
{
cfg
->
filter_type
=
SCAN_SSID_FILTER_SPECIFIC
;
cfg
->
ssid_len
=
req
->
ssids
[
0
].
ssid_len
;
memcpy
(
cfg
->
ssid
,
req
->
ssids
[
0
].
ssid
,
req
->
ssids
[
0
].
ssid_len
);
}
else
{
cfg
->
filter_type
=
SCAN_SSID_FILTER_ANY
;
cfg
->
ssid_len
=
0
;
}
total_channels
=
wl1271_scan_sched_scan_channels
(
wl
,
req
,
cfg
);
if
(
total_channels
==
0
)
{
wl1271_error
(
"scan channel list is empty"
);
ret
=
-
EINVAL
;
goto
out
;
}
if
(
cfg
->
active
[
0
])
{
ret
=
wl1271_cmd_build_probe_req
(
wl
,
req
->
ssids
[
0
].
ssid
,
req
->
ssids
[
0
].
ssid_len
,
ies
->
ie
[
IEEE80211_BAND_2GHZ
],
ies
->
len
[
IEEE80211_BAND_2GHZ
],
IEEE80211_BAND_2GHZ
);
if
(
ret
<
0
)
{
wl1271_error
(
"2.4GHz PROBE request template failed"
);
goto
out
;
}
}
if
(
cfg
->
active
[
1
])
{
ret
=
wl1271_cmd_build_probe_req
(
wl
,
req
->
ssids
[
0
].
ssid
,
req
->
ssids
[
0
].
ssid_len
,
ies
->
ie
[
IEEE80211_BAND_5GHZ
],
ies
->
len
[
IEEE80211_BAND_5GHZ
],
IEEE80211_BAND_5GHZ
);
if
(
ret
<
0
)
{
wl1271_error
(
"5GHz PROBE request template failed"
);
goto
out
;
}
}
wl1271_dump
(
DEBUG_SCAN
,
"SCAN_CFG: "
,
cfg
,
sizeof
(
*
cfg
));
ret
=
wl1271_cmd_send
(
wl
,
CMD_CONNECTION_SCAN_CFG
,
cfg
,
sizeof
(
*
cfg
),
0
);
if
(
ret
<
0
)
{
wl1271_error
(
"SCAN configuration failed"
);
goto
out
;
}
out:
kfree
(
cfg
);
return
ret
;
}
int
wl1271_scan_sched_scan_start
(
struct
wl1271
*
wl
)
{
struct
wl1271_cmd_sched_scan_start
*
start
;
int
ret
=
0
;
wl1271_debug
(
DEBUG_CMD
,
"cmd periodic scan start"
);
if
(
wl
->
bss_type
!=
BSS_TYPE_STA_BSS
)
return
-
EOPNOTSUPP
;
if
(
!
test_bit
(
WL1271_FLAG_IDLE
,
&
wl
->
flags
))
return
-
EBUSY
;
start
=
kzalloc
(
sizeof
(
*
start
),
GFP_KERNEL
);
if
(
!
start
)
return
-
ENOMEM
;
start
->
tag
=
WL1271_SCAN_DEFAULT_TAG
;
ret
=
wl1271_cmd_send
(
wl
,
CMD_START_PERIODIC_SCAN
,
start
,
sizeof
(
*
start
),
0
);
if
(
ret
<
0
)
{
wl1271_error
(
"failed to send scan start command"
);
goto
out_free
;
}
out_free:
kfree
(
start
);
return
ret
;
}
void
wl1271_scan_sched_scan_results
(
struct
wl1271
*
wl
)
{
wl1271_debug
(
DEBUG_SCAN
,
"got periodic scan results"
);
ieee80211_sched_scan_results
(
wl
->
hw
);
}
void
wl1271_scan_sched_scan_stop
(
struct
wl1271
*
wl
)
{
struct
wl1271_cmd_sched_scan_stop
*
stop
;
int
ret
=
0
;
wl1271_debug
(
DEBUG_CMD
,
"cmd periodic scan stop"
);
/* FIXME: what to do if alloc'ing to stop fails? */
stop
=
kzalloc
(
sizeof
(
*
stop
),
GFP_KERNEL
);
if
(
!
stop
)
{
wl1271_error
(
"failed to alloc memory to send sched scan stop"
);
return
;
}
stop
->
tag
=
WL1271_SCAN_DEFAULT_TAG
;
ret
=
wl1271_cmd_send
(
wl
,
CMD_STOP_PERIODIC_SCAN
,
stop
,
sizeof
(
*
stop
),
0
);
if
(
ret
<
0
)
{
wl1271_error
(
"failed to send sched scan stop command"
);
goto
out_free
;
}
wl
->
sched_scanning
=
false
;
out_free:
kfree
(
stop
);
}
drivers/net/wireless/wl12xx/scan.h
浏览文件 @
b376704b
...
@@ -33,6 +33,12 @@ int wl1271_scan_build_probe_req(struct wl1271 *wl,
...
@@ -33,6 +33,12 @@ int wl1271_scan_build_probe_req(struct wl1271 *wl,
const
u8
*
ie
,
size_t
ie_len
,
u8
band
);
const
u8
*
ie
,
size_t
ie_len
,
u8
band
);
void
wl1271_scan_stm
(
struct
wl1271
*
wl
);
void
wl1271_scan_stm
(
struct
wl1271
*
wl
);
void
wl1271_scan_complete_work
(
struct
work_struct
*
work
);
void
wl1271_scan_complete_work
(
struct
work_struct
*
work
);
int
wl1271_scan_sched_scan_config
(
struct
wl1271
*
wl
,
struct
cfg80211_sched_scan_request
*
req
,
struct
ieee80211_sched_scan_ies
*
ies
);
int
wl1271_scan_sched_scan_start
(
struct
wl1271
*
wl
);
void
wl1271_scan_sched_scan_stop
(
struct
wl1271
*
wl
);
void
wl1271_scan_sched_scan_results
(
struct
wl1271
*
wl
);
#define WL1271_SCAN_MAX_CHANNELS 24
#define WL1271_SCAN_MAX_CHANNELS 24
#define WL1271_SCAN_DEFAULT_TAG 1
#define WL1271_SCAN_DEFAULT_TAG 1
...
@@ -106,4 +112,112 @@ struct wl1271_cmd_trigger_scan_to {
...
@@ -106,4 +112,112 @@ struct wl1271_cmd_trigger_scan_to {
__le32
timeout
;
__le32
timeout
;
}
__packed
;
}
__packed
;
#define MAX_CHANNELS_ALL_BANDS 41
#define SCAN_MAX_CYCLE_INTERVALS 16
#define SCAN_MAX_BANDS 3
enum
{
SCAN_CHANNEL_TYPE_2GHZ_PASSIVE
,
SCAN_CHANNEL_TYPE_2GHZ_ACTIVE
,
SCAN_CHANNEL_TYPE_5GHZ_PASSIVE
,
SCAN_CHANNEL_TYPE_5GHZ_ACTIVE
,
SCAN_CHANNEL_TYPE_5GHZ_DFS
,
};
enum
{
SCAN_SSID_FILTER_ANY
=
0
,
SCAN_SSID_FILTER_SPECIFIC
=
1
,
SCAN_SSID_FILTER_LIST
=
2
,
SCAN_SSID_FILTER_DISABLED
=
3
};
enum
{
SCAN_BSS_TYPE_INDEPENDENT
,
SCAN_BSS_TYPE_INFRASTRUCTURE
,
SCAN_BSS_TYPE_ANY
,
};
struct
conn_scan_ch_params
{
__le16
min_duration
;
__le16
max_duration
;
__le16
passive_duration
;
u8
channel
;
u8
tx_power_att
;
/* bit 0: DFS channel; bit 1: DFS enabled */
u8
flags
;
u8
padding
[
3
];
}
__packed
;
struct
wl1271_cmd_sched_scan_config
{
struct
wl1271_cmd_header
header
;
__le32
intervals
[
SCAN_MAX_CYCLE_INTERVALS
];
s8
rssi_threshold
;
/* for filtering (in dBm) */
s8
snr_threshold
;
/* for filtering (in dB) */
u8
cycles
;
/* maximum number of scan cycles */
u8
report_after
;
/* report when this number of results are received */
u8
terminate
;
/* stop scanning after reporting */
u8
tag
;
u8
bss_type
;
/* for filtering */
u8
filter_type
;
u8
ssid_len
;
/* For SCAN_SSID_FILTER_SPECIFIC */
u8
ssid
[
IW_ESSID_MAX_SIZE
];
u8
n_probe_reqs
;
/* Number of probes requests per channel */
u8
passive
[
SCAN_MAX_BANDS
];
u8
active
[
SCAN_MAX_BANDS
];
u8
dfs
;
u8
padding
[
3
];
struct
conn_scan_ch_params
channels
[
MAX_CHANNELS_ALL_BANDS
];
}
__packed
;
#define SCHED_SCAN_MAX_SSIDS 8
enum
{
SCAN_SSID_TYPE_PUBLIC
=
0
,
SCAN_SSID_TYPE_HIDDEN
=
1
,
};
struct
wl1271_ssid
{
u8
type
;
u8
len
;
u8
ssid
[
IW_ESSID_MAX_SIZE
];
/* u8 padding[2]; */
}
__packed
;
struct
wl1271_cmd_sched_scan_ssid_list
{
struct
wl1271_cmd_header
header
;
u8
n_ssids
;
struct
wl1271_ssid
ssids
[
SCHED_SCAN_MAX_SSIDS
];
u8
padding
[
3
];
}
__packed
;
struct
wl1271_cmd_sched_scan_start
{
struct
wl1271_cmd_header
header
;
u8
tag
;
u8
padding
[
3
];
}
__packed
;
struct
wl1271_cmd_sched_scan_stop
{
struct
wl1271_cmd_header
header
;
u8
tag
;
u8
padding
[
3
];
}
__packed
;
#endif
/* __WL1271_SCAN_H__ */
#endif
/* __WL1271_SCAN_H__ */
drivers/net/wireless/wl12xx/sdio.c
浏览文件 @
b376704b
...
@@ -82,6 +82,16 @@ static irqreturn_t wl1271_hardirq(int irq, void *cookie)
...
@@ -82,6 +82,16 @@ static irqreturn_t wl1271_hardirq(int irq, void *cookie)
complete
(
wl
->
elp_compl
);
complete
(
wl
->
elp_compl
);
wl
->
elp_compl
=
NULL
;
wl
->
elp_compl
=
NULL
;
}
}
if
(
test_bit
(
WL1271_FLAG_SUSPENDED
,
&
wl
->
flags
))
{
/* don't enqueue a work right now. mark it as pending */
set_bit
(
WL1271_FLAG_PENDING_WORK
,
&
wl
->
flags
);
wl1271_debug
(
DEBUG_IRQ
,
"should not enqueue work"
);
disable_irq_nosync
(
wl
->
irq
);
pm_wakeup_event
(
wl1271_sdio_wl_to_dev
(
wl
),
0
);
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
return
IRQ_HANDLED
;
}
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
return
IRQ_WAKE_THREAD
;
return
IRQ_WAKE_THREAD
;
...
@@ -221,6 +231,7 @@ static int __devinit wl1271_probe(struct sdio_func *func,
...
@@ -221,6 +231,7 @@ static int __devinit wl1271_probe(struct sdio_func *func,
const
struct
wl12xx_platform_data
*
wlan_data
;
const
struct
wl12xx_platform_data
*
wlan_data
;
struct
wl1271
*
wl
;
struct
wl1271
*
wl
;
unsigned
long
irqflags
;
unsigned
long
irqflags
;
mmc_pm_flag_t
mmcflags
;
int
ret
;
int
ret
;
/* We are only able to handle the wlan function */
/* We are only able to handle the wlan function */
...
@@ -267,8 +278,18 @@ static int __devinit wl1271_probe(struct sdio_func *func,
...
@@ -267,8 +278,18 @@ static int __devinit wl1271_probe(struct sdio_func *func,
goto
out_free
;
goto
out_free
;
}
}
enable_irq_wake
(
wl
->
irq
);
device_init_wakeup
(
wl1271_sdio_wl_to_dev
(
wl
),
1
);
disable_irq
(
wl
->
irq
);
disable_irq
(
wl
->
irq
);
/* if sdio can keep power while host is suspended, enable wow */
mmcflags
=
sdio_get_host_pm_caps
(
func
);
wl1271_debug
(
DEBUG_SDIO
,
"sdio PM caps = 0x%x"
,
mmcflags
);
if
(
mmcflags
&
MMC_PM_KEEP_POWER
)
hw
->
wiphy
->
wowlan
.
flags
=
WIPHY_WOWLAN_ANY
;
ret
=
wl1271_init_ieee80211
(
wl
);
ret
=
wl1271_init_ieee80211
(
wl
);
if
(
ret
)
if
(
ret
)
goto
out_irq
;
goto
out_irq
;
...
@@ -303,6 +324,8 @@ static void __devexit wl1271_remove(struct sdio_func *func)
...
@@ -303,6 +324,8 @@ static void __devexit wl1271_remove(struct sdio_func *func)
pm_runtime_get_noresume
(
&
func
->
dev
);
pm_runtime_get_noresume
(
&
func
->
dev
);
wl1271_unregister_hw
(
wl
);
wl1271_unregister_hw
(
wl
);
device_init_wakeup
(
wl1271_sdio_wl_to_dev
(
wl
),
0
);
disable_irq_wake
(
wl
->
irq
);
free_irq
(
wl
->
irq
,
wl
);
free_irq
(
wl
->
irq
,
wl
);
wl1271_free_hw
(
wl
);
wl1271_free_hw
(
wl
);
}
}
...
@@ -311,11 +334,50 @@ static int wl1271_suspend(struct device *dev)
...
@@ -311,11 +334,50 @@ static int wl1271_suspend(struct device *dev)
{
{
/* Tell MMC/SDIO core it's OK to power down the card
/* Tell MMC/SDIO core it's OK to power down the card
* (if it isn't already), but not to remove it completely */
* (if it isn't already), but not to remove it completely */
return
0
;
struct
sdio_func
*
func
=
dev_to_sdio_func
(
dev
);
struct
wl1271
*
wl
=
sdio_get_drvdata
(
func
);
mmc_pm_flag_t
sdio_flags
;
int
ret
=
0
;
wl1271_debug
(
DEBUG_MAC80211
,
"wl1271 suspend. wow_enabled: %d"
,
wl
->
wow_enabled
);
/* check whether sdio should keep power */
if
(
wl
->
wow_enabled
)
{
sdio_flags
=
sdio_get_host_pm_caps
(
func
);
if
(
!
(
sdio_flags
&
MMC_PM_KEEP_POWER
))
{
wl1271_error
(
"can't keep power while host "
"is suspended"
);
ret
=
-
EINVAL
;
goto
out
;
}
/* keep power while host suspended */
ret
=
sdio_set_host_pm_flags
(
func
,
MMC_PM_KEEP_POWER
);
if
(
ret
)
{
wl1271_error
(
"error while trying to keep power"
);
goto
out
;
}
/* release host */
sdio_release_host
(
func
);
}
out:
return
ret
;
}
}
static
int
wl1271_resume
(
struct
device
*
dev
)
static
int
wl1271_resume
(
struct
device
*
dev
)
{
{
struct
sdio_func
*
func
=
dev_to_sdio_func
(
dev
);
struct
wl1271
*
wl
=
sdio_get_drvdata
(
func
);
wl1271_debug
(
DEBUG_MAC80211
,
"wl1271 resume"
);
if
(
wl
->
wow_enabled
)
{
/* claim back host */
sdio_claim_host
(
func
);
}
return
0
;
return
0
;
}
}
...
...
drivers/net/wireless/wl12xx/wl12xx.h
浏览文件 @
b376704b
...
@@ -351,13 +351,14 @@ enum wl12xx_flags {
...
@@ -351,13 +351,14 @@ enum wl12xx_flags {
WL1271_FLAG_PSM_REQUESTED
,
WL1271_FLAG_PSM_REQUESTED
,
WL1271_FLAG_IRQ_RUNNING
,
WL1271_FLAG_IRQ_RUNNING
,
WL1271_FLAG_IDLE
,
WL1271_FLAG_IDLE
,
WL1271_FLAG_IDLE_REQUESTED
,
WL1271_FLAG_PSPOLL_FAILURE
,
WL1271_FLAG_PSPOLL_FAILURE
,
WL1271_FLAG_STA_STATE_SENT
,
WL1271_FLAG_STA_STATE_SENT
,
WL1271_FLAG_FW_TX_BUSY
,
WL1271_FLAG_FW_TX_BUSY
,
WL1271_FLAG_AP_STARTED
,
WL1271_FLAG_AP_STARTED
,
WL1271_FLAG_IF_INITIALIZED
,
WL1271_FLAG_IF_INITIALIZED
,
WL1271_FLAG_DUMMY_PACKET_PENDING
,
WL1271_FLAG_DUMMY_PACKET_PENDING
,
WL1271_FLAG_SUSPENDED
,
WL1271_FLAG_PENDING_WORK
,
};
};
struct
wl1271_link
{
struct
wl1271_link
{
...
@@ -480,6 +481,8 @@ struct wl1271 {
...
@@ -480,6 +481,8 @@ struct wl1271 {
struct
wl1271_scan
scan
;
struct
wl1271_scan
scan
;
struct
delayed_work
scan_complete_work
;
struct
delayed_work
scan_complete_work
;
bool
sched_scanning
;
/* probe-req template for the current AP */
/* probe-req template for the current AP */
struct
sk_buff
*
probereq
;
struct
sk_buff
*
probereq
;
...
@@ -510,6 +513,7 @@ struct wl1271 {
...
@@ -510,6 +513,7 @@ struct wl1271 {
unsigned
int
rx_filter
;
unsigned
int
rx_filter
;
struct
completion
*
elp_compl
;
struct
completion
*
elp_compl
;
struct
completion
*
ps_compl
;
struct
delayed_work
elp_work
;
struct
delayed_work
elp_work
;
struct
delayed_work
pspoll_work
;
struct
delayed_work
pspoll_work
;
...
@@ -563,6 +567,12 @@ struct wl1271 {
...
@@ -563,6 +567,12 @@ struct wl1271 {
int
tcxo_clock
;
int
tcxo_clock
;
/*
* wowlan trigger was configured during suspend.
* (currently, only "ANY" trigger is supported)
*/
bool
wow_enabled
;
/*
/*
* AP-mode - links indexed by HLID. The global and broadcast links
* AP-mode - links indexed by HLID. The global and broadcast links
* are always active.
* are always active.
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录