]> Pileus Git - ~andy/linux/blobdiff - net/mac80211/ht.c
mac80211: implement SMPS for AP
[~andy/linux] / net / mac80211 / ht.c
index 529bf58bc14511beae95c4ff250ec54eff5c9710..9a8be8f69224d0be11fe9b10a0176a2f5a0002f1 100644 (file)
@@ -448,14 +448,25 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
        return 0;
 }
 
-void ieee80211_request_smps_work(struct work_struct *work)
+void ieee80211_request_smps_mgd_work(struct work_struct *work)
 {
        struct ieee80211_sub_if_data *sdata =
                container_of(work, struct ieee80211_sub_if_data,
                             u.mgd.request_smps_work);
 
        sdata_lock(sdata);
-       __ieee80211_request_smps(sdata, sdata->u.mgd.driver_smps_mode);
+       __ieee80211_request_smps_mgd(sdata, sdata->u.mgd.driver_smps_mode);
+       sdata_unlock(sdata);
+}
+
+void ieee80211_request_smps_ap_work(struct work_struct *work)
+{
+       struct ieee80211_sub_if_data *sdata =
+               container_of(work, struct ieee80211_sub_if_data,
+                            u.ap.request_smps_work);
+
+       sdata_lock(sdata);
+       __ieee80211_request_smps_ap(sdata, sdata->u.ap.driver_smps_mode);
        sdata_unlock(sdata);
 }
 
@@ -464,19 +475,29 @@ void ieee80211_request_smps(struct ieee80211_vif *vif,
 {
        struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
 
-       if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
+       if (WARN_ON_ONCE(vif->type != NL80211_IFTYPE_STATION &&
+                        vif->type != NL80211_IFTYPE_AP))
                return;
 
        if (WARN_ON(smps_mode == IEEE80211_SMPS_OFF))
                smps_mode = IEEE80211_SMPS_AUTOMATIC;
 
-       if (sdata->u.mgd.driver_smps_mode == smps_mode)
-               return;
-
-       sdata->u.mgd.driver_smps_mode = smps_mode;
-
-       ieee80211_queue_work(&sdata->local->hw,
-                            &sdata->u.mgd.request_smps_work);
+       if (vif->type == NL80211_IFTYPE_STATION) {
+               if (sdata->u.mgd.driver_smps_mode == smps_mode)
+                       return;
+               sdata->u.mgd.driver_smps_mode = smps_mode;
+               ieee80211_queue_work(&sdata->local->hw,
+                                    &sdata->u.mgd.request_smps_work);
+       } else {
+               /* AUTOMATIC is meaningless in AP mode */
+               if (WARN_ON_ONCE(smps_mode == IEEE80211_SMPS_AUTOMATIC))
+                       return;
+               if (sdata->u.ap.driver_smps_mode == smps_mode)
+                       return;
+               sdata->u.ap.driver_smps_mode = smps_mode;
+               ieee80211_queue_work(&sdata->local->hw,
+                                    &sdata->u.ap.request_smps_work);
+       }
 }
 /* this might change ... don't want non-open drivers using it */
 EXPORT_SYMBOL_GPL(ieee80211_request_smps);