*
  * @tx_frames_pending: Check if there is any pending frame in the hardware
  *     queues before entering power save.
+ *
+ * @set_bitrate_mask: Set a mask of rates to be used for rate control selection
+ *     when transmitting a frame. Currently only legacy rates are handled.
+ *     The callback can sleep.
  */
 struct ieee80211_ops {
        void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
        void (*get_ringparam)(struct ieee80211_hw *hw,
                              u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);
        bool (*tx_frames_pending)(struct ieee80211_hw *hw);
+       int (*set_bitrate_mask)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                               const struct cfg80211_bitrate_mask *mask);
 };
 
 /**
 
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       int i;
-
-       /*
-        * This _could_ be supported by providing a hook for
-        * drivers for this function, but at this point it
-        * doesn't seem worth bothering.
-        */
-       if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)
-               return -EOPNOTSUPP;
+       int i, ret;
 
+       if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) {
+               ret = drv_set_bitrate_mask(local, sdata, mask);
+               if (ret)
+                       return ret;
+       }
 
        for (i = 0; i < IEEE80211_NUM_BANDS; i++)
                sdata->rc_rateidx_mask[i] = mask->control[i].legacy;
 
 
        return ret;
 }
+
+static inline int drv_set_bitrate_mask(struct ieee80211_local *local,
+                                      struct ieee80211_sub_if_data *sdata,
+                                      const struct cfg80211_bitrate_mask *mask)
+{
+       int ret = -EOPNOTSUPP;
+
+       might_sleep();
+
+       trace_drv_set_bitrate_mask(local, sdata, mask);
+       if (local->ops->set_bitrate_mask)
+               ret = local->ops->set_bitrate_mask(&local->hw,
+                                                  &sdata->vif, mask);
+       trace_drv_return_int(local, ret);
+
+       return ret;
+}
+
 #endif /* __MAC80211_DRIVER_OPS */
 
        TP_ARGS(local)
 );
 
+TRACE_EVENT(drv_set_bitrate_mask,
+       TP_PROTO(struct ieee80211_local *local,
+                struct ieee80211_sub_if_data *sdata,
+                const struct cfg80211_bitrate_mask *mask),
+
+       TP_ARGS(local, sdata, mask),
+
+       TP_STRUCT__entry(
+               LOCAL_ENTRY
+               VIF_ENTRY
+               __field(u32, legacy_2g)
+               __field(u32, legacy_5g)
+       ),
+
+       TP_fast_assign(
+               LOCAL_ASSIGN;
+               VIF_ASSIGN;
+               __entry->legacy_2g = mask->control[IEEE80211_BAND_2GHZ].legacy;
+               __entry->legacy_5g = mask->control[IEEE80211_BAND_5GHZ].legacy;
+       ),
+
+       TP_printk(
+               LOCAL_PR_FMT  VIF_PR_FMT " 2G Mask:0x%x 5G Mask:0x%x",
+               LOCAL_PR_ARG, VIF_PR_ARG, __entry->legacy_2g, __entry->legacy_5g
+       )
+);
+
 /*
  * Tracing for API calls that drivers call.
  */