0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/module.h>
0010 #include <linux/if_ether.h>
0011 #include "cw1200.h"
0012 #include "pm.h"
0013 #include "sta.h"
0014 #include "bh.h"
0015 #include "hwbus.h"
0016
0017 #define CW1200_BEACON_SKIPPING_MULTIPLIER 3
0018
0019 struct cw1200_udp_port_filter {
0020 struct wsm_udp_port_filter_hdr hdr;
0021
0022 struct wsm_udp_port_filter filters[WSM_MAX_FILTER_ELEMENTS];
0023 } __packed;
0024
0025 struct cw1200_ether_type_filter {
0026 struct wsm_ether_type_filter_hdr hdr;
0027
0028 struct wsm_ether_type_filter filters[WSM_MAX_FILTER_ELEMENTS];
0029 } __packed;
0030
0031 static struct cw1200_udp_port_filter cw1200_udp_port_filter_on = {
0032 .hdr.num = 2,
0033 .filters = {
0034 [0] = {
0035 .action = WSM_FILTER_ACTION_FILTER_OUT,
0036 .type = WSM_FILTER_PORT_TYPE_DST,
0037 .port = __cpu_to_le16(67),
0038 },
0039 [1] = {
0040 .action = WSM_FILTER_ACTION_FILTER_OUT,
0041 .type = WSM_FILTER_PORT_TYPE_DST,
0042 .port = __cpu_to_le16(68),
0043 },
0044 }
0045 };
0046
0047 static struct wsm_udp_port_filter_hdr cw1200_udp_port_filter_off = {
0048 .num = 0,
0049 };
0050
0051 #ifndef ETH_P_WAPI
0052 #define ETH_P_WAPI 0x88B4
0053 #endif
0054
0055 static struct cw1200_ether_type_filter cw1200_ether_type_filter_on = {
0056 .hdr.num = 4,
0057 .filters = {
0058 [0] = {
0059 .action = WSM_FILTER_ACTION_FILTER_IN,
0060 .type = __cpu_to_le16(ETH_P_IP),
0061 },
0062 [1] = {
0063 .action = WSM_FILTER_ACTION_FILTER_IN,
0064 .type = __cpu_to_le16(ETH_P_PAE),
0065 },
0066 [2] = {
0067 .action = WSM_FILTER_ACTION_FILTER_IN,
0068 .type = __cpu_to_le16(ETH_P_WAPI),
0069 },
0070 [3] = {
0071 .action = WSM_FILTER_ACTION_FILTER_IN,
0072 .type = __cpu_to_le16(ETH_P_ARP),
0073 },
0074 },
0075 };
0076
0077 static struct wsm_ether_type_filter_hdr cw1200_ether_type_filter_off = {
0078 .num = 0,
0079 };
0080
0081
0082 struct cw1200_suspend_state {
0083 unsigned long bss_loss_tmo;
0084 unsigned long join_tmo;
0085 unsigned long direct_probe;
0086 unsigned long link_id_gc;
0087 bool beacon_skipping;
0088 u8 prev_ps_mode;
0089 };
0090
0091 static void cw1200_pm_stay_awake_tmo(struct timer_list *unused)
0092 {
0093
0094 }
0095
0096 int cw1200_pm_init(struct cw1200_pm_state *pm,
0097 struct cw1200_common *priv)
0098 {
0099 spin_lock_init(&pm->lock);
0100
0101 timer_setup(&pm->stay_awake, cw1200_pm_stay_awake_tmo, 0);
0102
0103 return 0;
0104 }
0105
0106 void cw1200_pm_deinit(struct cw1200_pm_state *pm)
0107 {
0108 del_timer_sync(&pm->stay_awake);
0109 }
0110
0111 void cw1200_pm_stay_awake(struct cw1200_pm_state *pm,
0112 unsigned long tmo)
0113 {
0114 long cur_tmo;
0115 spin_lock_bh(&pm->lock);
0116 cur_tmo = pm->stay_awake.expires - jiffies;
0117 if (!timer_pending(&pm->stay_awake) || cur_tmo < (long)tmo)
0118 mod_timer(&pm->stay_awake, jiffies + tmo);
0119 spin_unlock_bh(&pm->lock);
0120 }
0121
0122 static long cw1200_suspend_work(struct delayed_work *work)
0123 {
0124 int ret = cancel_delayed_work(work);
0125 long tmo;
0126 if (ret > 0) {
0127
0128 tmo = work->timer.expires - jiffies;
0129 if (tmo < 0)
0130 tmo = 0;
0131 } else {
0132 tmo = -1;
0133 }
0134 return tmo;
0135 }
0136
0137 static int cw1200_resume_work(struct cw1200_common *priv,
0138 struct delayed_work *work,
0139 unsigned long tmo)
0140 {
0141 if ((long)tmo < 0)
0142 return 1;
0143
0144 return queue_delayed_work(priv->workqueue, work, tmo);
0145 }
0146
0147 int cw1200_can_suspend(struct cw1200_common *priv)
0148 {
0149 if (atomic_read(&priv->bh_rx)) {
0150 wiphy_dbg(priv->hw->wiphy, "Suspend interrupted.\n");
0151 return 0;
0152 }
0153 return 1;
0154 }
0155 EXPORT_SYMBOL_GPL(cw1200_can_suspend);
0156
0157 int cw1200_wow_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
0158 {
0159 struct cw1200_common *priv = hw->priv;
0160 struct cw1200_pm_state *pm_state = &priv->pm_state;
0161 struct cw1200_suspend_state *state;
0162 int ret;
0163
0164 spin_lock_bh(&pm_state->lock);
0165 ret = timer_pending(&pm_state->stay_awake);
0166 spin_unlock_bh(&pm_state->lock);
0167 if (ret)
0168 return -EAGAIN;
0169
0170
0171 if (priv->tx_queue_stats.num_queued)
0172 return -EBUSY;
0173
0174
0175 if (!mutex_trylock(&priv->conf_mutex))
0176 return -EBUSY;
0177
0178
0179
0180
0181
0182 if (priv->channel_switch_in_progress)
0183 goto revert1;
0184
0185
0186 if (priv->join_pending)
0187 goto revert1;
0188
0189
0190 if (down_trylock(&priv->scan.lock))
0191 goto revert1;
0192
0193
0194 wsm_lock_tx_async(priv);
0195
0196
0197
0198
0199 if (wait_event_timeout(priv->bh_evt_wq,
0200 !priv->hw_bufs_used, HZ / 10) <= 0)
0201 goto revert2;
0202
0203
0204 wsm_set_udp_port_filter(priv, &cw1200_udp_port_filter_on.hdr);
0205
0206
0207 wsm_set_ether_type_filter(priv, &cw1200_ether_type_filter_on.hdr);
0208
0209
0210 state = kzalloc(sizeof(struct cw1200_suspend_state), GFP_KERNEL);
0211 if (!state)
0212 goto revert3;
0213
0214
0215 if (!priv->vif->p2p &&
0216 priv->join_status == CW1200_JOIN_STATUS_STA &&
0217 priv->powersave_mode.mode != WSM_PSM_PS) {
0218 state->prev_ps_mode = priv->powersave_mode.mode;
0219 priv->powersave_mode.mode = WSM_PSM_PS;
0220 cw1200_set_pm(priv, &priv->powersave_mode);
0221 if (wait_event_interruptible_timeout(priv->ps_mode_switch_done,
0222 !priv->ps_mode_switch_in_progress, 1*HZ) <= 0) {
0223 goto revert4;
0224 }
0225 }
0226
0227
0228 state->bss_loss_tmo =
0229 cw1200_suspend_work(&priv->bss_loss_work);
0230 state->join_tmo =
0231 cw1200_suspend_work(&priv->join_timeout);
0232 state->direct_probe =
0233 cw1200_suspend_work(&priv->scan.probe_work);
0234 state->link_id_gc =
0235 cw1200_suspend_work(&priv->link_id_gc_work);
0236
0237 cancel_delayed_work_sync(&priv->clear_recent_scan_work);
0238 atomic_set(&priv->recent_scan, 0);
0239
0240
0241 if (priv->join_status == CW1200_JOIN_STATUS_STA &&
0242 priv->join_dtim_period &&
0243 !priv->has_multicast_subscription) {
0244 state->beacon_skipping = true;
0245 wsm_set_beacon_wakeup_period(priv,
0246 priv->join_dtim_period,
0247 CW1200_BEACON_SKIPPING_MULTIPLIER * priv->join_dtim_period);
0248 }
0249
0250
0251 if (cw1200_bh_suspend(priv))
0252 goto revert5;
0253
0254 ret = timer_pending(&priv->mcast_timeout);
0255 if (ret)
0256 goto revert6;
0257
0258
0259 pm_state->suspend_state = state;
0260
0261
0262 ret = priv->hwbus_ops->power_mgmt(priv->hwbus_priv, true);
0263 if (ret) {
0264 wiphy_err(priv->hw->wiphy,
0265 "PM request failed: %d. WoW is disabled.\n", ret);
0266 cw1200_wow_resume(hw);
0267 return -EBUSY;
0268 }
0269
0270
0271 if (atomic_read(&priv->bh_rx)) {
0272 cw1200_wow_resume(hw);
0273 return -EAGAIN;
0274 }
0275
0276 return 0;
0277
0278 revert6:
0279 WARN_ON(cw1200_bh_resume(priv));
0280 revert5:
0281 cw1200_resume_work(priv, &priv->bss_loss_work,
0282 state->bss_loss_tmo);
0283 cw1200_resume_work(priv, &priv->join_timeout,
0284 state->join_tmo);
0285 cw1200_resume_work(priv, &priv->scan.probe_work,
0286 state->direct_probe);
0287 cw1200_resume_work(priv, &priv->link_id_gc_work,
0288 state->link_id_gc);
0289 revert4:
0290 kfree(state);
0291 revert3:
0292 wsm_set_udp_port_filter(priv, &cw1200_udp_port_filter_off);
0293 wsm_set_ether_type_filter(priv, &cw1200_ether_type_filter_off);
0294 revert2:
0295 wsm_unlock_tx(priv);
0296 up(&priv->scan.lock);
0297 revert1:
0298 mutex_unlock(&priv->conf_mutex);
0299 return -EBUSY;
0300 }
0301
0302 int cw1200_wow_resume(struct ieee80211_hw *hw)
0303 {
0304 struct cw1200_common *priv = hw->priv;
0305 struct cw1200_pm_state *pm_state = &priv->pm_state;
0306 struct cw1200_suspend_state *state;
0307
0308 state = pm_state->suspend_state;
0309 pm_state->suspend_state = NULL;
0310
0311
0312 priv->hwbus_ops->power_mgmt(priv->hwbus_priv, false);
0313
0314
0315
0316
0317
0318 up(&priv->scan.lock);
0319
0320
0321 WARN_ON(cw1200_bh_resume(priv));
0322
0323
0324 if (!priv->vif->p2p && priv->join_status == CW1200_JOIN_STATUS_STA) {
0325 priv->powersave_mode.mode = state->prev_ps_mode;
0326 cw1200_set_pm(priv, &priv->powersave_mode);
0327 }
0328
0329 if (state->beacon_skipping) {
0330 wsm_set_beacon_wakeup_period(priv, priv->beacon_int *
0331 priv->join_dtim_period >
0332 MAX_BEACON_SKIP_TIME_MS ? 1 :
0333 priv->join_dtim_period, 0);
0334 state->beacon_skipping = false;
0335 }
0336
0337
0338 cw1200_resume_work(priv, &priv->bss_loss_work,
0339 state->bss_loss_tmo);
0340 cw1200_resume_work(priv, &priv->join_timeout,
0341 state->join_tmo);
0342 cw1200_resume_work(priv, &priv->scan.probe_work,
0343 state->direct_probe);
0344 cw1200_resume_work(priv, &priv->link_id_gc_work,
0345 state->link_id_gc);
0346
0347
0348 wsm_set_udp_port_filter(priv, &cw1200_udp_port_filter_off);
0349
0350
0351 wsm_set_ether_type_filter(priv, &cw1200_ether_type_filter_off);
0352
0353
0354 wsm_unlock_tx(priv);
0355
0356
0357 mutex_unlock(&priv->conf_mutex);
0358
0359
0360 kfree(state);
0361
0362 return 0;
0363 }