1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright(c) 2018-2019 Realtek Corporation
12 static int rtw_ips_pwr_up(struct rtw_dev
*rtwdev
)
16 ret
= rtw_core_start(rtwdev
);
18 rtw_err(rtwdev
, "leave idle state failed\n");
20 rtw_set_channel(rtwdev
);
21 rtw_flag_clear(rtwdev
, RTW_FLAG_INACTIVE_PS
);
26 int rtw_enter_ips(struct rtw_dev
*rtwdev
)
28 rtw_flag_set(rtwdev
, RTW_FLAG_INACTIVE_PS
);
30 rtw_coex_ips_notify(rtwdev
, COEX_IPS_ENTER
);
32 rtw_core_stop(rtwdev
);
37 static void rtw_restore_port_cfg_iter(void *data
, u8
*mac
,
38 struct ieee80211_vif
*vif
)
40 struct rtw_dev
*rtwdev
= data
;
41 struct rtw_vif
*rtwvif
= (struct rtw_vif
*)vif
->drv_priv
;
44 rtw_vif_port_config(rtwdev
, rtwvif
, config
);
47 int rtw_leave_ips(struct rtw_dev
*rtwdev
)
51 ret
= rtw_ips_pwr_up(rtwdev
);
53 rtw_err(rtwdev
, "failed to leave ips state\n");
57 rtw_iterate_vifs_atomic(rtwdev
, rtw_restore_port_cfg_iter
, rtwdev
);
59 rtw_coex_ips_notify(rtwdev
, COEX_IPS_LEAVE
);
64 static void rtw_leave_lps_core(struct rtw_dev
*rtwdev
)
66 struct rtw_lps_conf
*conf
= &rtwdev
->lps_conf
;
68 conf
->state
= RTW_ALL_ON
;
69 conf
->awake_interval
= 1;
73 rtw_fw_set_pwr_mode(rtwdev
);
74 rtw_flag_clear(rtwdev
, RTW_FLAG_LEISURE_PS
);
76 rtw_coex_lps_notify(rtwdev
, COEX_LPS_DISABLE
);
79 static void rtw_enter_lps_core(struct rtw_dev
*rtwdev
)
81 struct rtw_lps_conf
*conf
= &rtwdev
->lps_conf
;
83 conf
->state
= RTW_RF_OFF
;
84 conf
->awake_interval
= 1;
88 rtw_coex_lps_notify(rtwdev
, COEX_LPS_ENABLE
);
90 rtw_fw_set_pwr_mode(rtwdev
);
91 rtw_flag_set(rtwdev
, RTW_FLAG_LEISURE_PS
);
94 void rtw_lps_work(struct work_struct
*work
)
96 struct rtw_dev
*rtwdev
= container_of(work
, struct rtw_dev
,
98 struct rtw_lps_conf
*conf
= &rtwdev
->lps_conf
;
99 struct rtw_vif
*rtwvif
= conf
->rtwvif
;
101 if (WARN_ON(!rtwvif
))
104 if (conf
->mode
== RTW_MODE_LPS
)
105 rtw_enter_lps_core(rtwdev
);
107 rtw_leave_lps_core(rtwdev
);
110 void rtw_enter_lps_irqsafe(struct rtw_dev
*rtwdev
, struct rtw_vif
*rtwvif
)
112 struct rtw_lps_conf
*conf
= &rtwdev
->lps_conf
;
117 conf
->mode
= RTW_MODE_LPS
;
118 conf
->rtwvif
= rtwvif
;
119 rtwvif
->in_lps
= true;
121 ieee80211_queue_delayed_work(rtwdev
->hw
, &rtwdev
->lps_work
, 0);
124 void rtw_leave_lps_irqsafe(struct rtw_dev
*rtwdev
, struct rtw_vif
*rtwvif
)
126 struct rtw_lps_conf
*conf
= &rtwdev
->lps_conf
;
131 conf
->mode
= RTW_MODE_ACTIVE
;
132 conf
->rtwvif
= rtwvif
;
133 rtwvif
->in_lps
= false;
135 ieee80211_queue_delayed_work(rtwdev
->hw
, &rtwdev
->lps_work
, 0);
138 bool rtw_in_lps(struct rtw_dev
*rtwdev
)
140 return rtw_flag_check(rtwdev
, RTW_FLAG_LEISURE_PS
);
143 void rtw_enter_lps(struct rtw_dev
*rtwdev
, struct rtw_vif
*rtwvif
)
145 struct rtw_lps_conf
*conf
= &rtwdev
->lps_conf
;
147 if (WARN_ON(!rtwvif
))
153 conf
->mode
= RTW_MODE_LPS
;
154 conf
->rtwvif
= rtwvif
;
155 rtwvif
->in_lps
= true;
157 rtw_enter_lps_core(rtwdev
);
160 void rtw_leave_lps(struct rtw_dev
*rtwdev
, struct rtw_vif
*rtwvif
)
162 struct rtw_lps_conf
*conf
= &rtwdev
->lps_conf
;
164 if (WARN_ON(!rtwvif
))
170 conf
->mode
= RTW_MODE_ACTIVE
;
171 conf
->rtwvif
= rtwvif
;
172 rtwvif
->in_lps
= false;
174 rtw_leave_lps_core(rtwdev
);