]> err.no Git - linux-2.6/blobdiff - drivers/net/wireless/rt2x00/rt2x00mac.c
rt2x00: Use rt2x00 queue numbering
[linux-2.6] / drivers / net / wireless / rt2x00 / rt2x00mac.c
index a54f6873e9ea2ff271853162e08c4e4494bdb699..d4ceab7646e7cfffe3f3f218cf32d162720236ab 100644 (file)
@@ -81,6 +81,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
 {
        struct rt2x00_dev *rt2x00dev = hw->priv;
        struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
+       enum data_queue_qid qid = mac80211_queue_to_qid(control->queue);
        struct data_queue *queue;
        struct skb_frame_desc *skbdesc;
        u16 frame_control;
@@ -99,12 +100,15 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
        /*
         * Determine which queue to put packet on.
         */
-       queue = rt2x00queue_get_queue(rt2x00dev, control->queue);
+       if (control->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM &&
+           test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags))
+               queue = rt2x00queue_get_queue(rt2x00dev, QID_ATIM);
+       else
+               queue = rt2x00queue_get_queue(rt2x00dev, qid);
        if (unlikely(!queue)) {
                ERROR(rt2x00dev,
                      "Attempt to send packet over invalid queue %d.\n"
-                     "Please file bug report to %s.\n",
-                     control->queue, DRV_PROJECT);
+                     "Please file bug report to %s.\n", qid, DRV_PROJECT);
                dev_kfree_skb_any(skb);
                return NETDEV_TX_OK;
        }
@@ -114,11 +118,16 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
         * create and queue that frame first. But make sure we have
         * at least enough entries available to send this CTS/RTS
         * frame as well as the data frame.
+        * Note that when the driver has set the set_rts_threshold()
+        * callback function it doesn't need software generation of
+        * neither RTS or CTS-to-self frames and handles everything
+        * inside the hardware.
         */
        frame_control = le16_to_cpu(ieee80211hdr->frame_control);
        if (!is_rts_frame(frame_control) && !is_cts_frame(frame_control) &&
            (control->flags & (IEEE80211_TXCTL_USE_RTS_CTS |
-                              IEEE80211_TXCTL_USE_CTS_PROTECT))) {
+                              IEEE80211_TXCTL_USE_CTS_PROTECT)) &&
+           !rt2x00dev->ops->hw->set_rts_threshold) {
                if (rt2x00queue_available(queue) <= 1) {
                        ieee80211_stop_queue(rt2x00dev->hw, control->queue);
                        return NETDEV_TX_BUSY;
@@ -145,7 +154,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
                ieee80211_stop_queue(rt2x00dev->hw, control->queue);
 
        if (rt2x00dev->ops->lib->kick_tx_queue)
-               rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue);
+               rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, qid);
 
        return NETDEV_TX_OK;
 }
@@ -178,8 +187,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
 {
        struct rt2x00_dev *rt2x00dev = hw->priv;
        struct rt2x00_intf *intf = vif_to_intf(conf->vif);
-       struct data_queue *queue =
-           rt2x00queue_get_queue(rt2x00dev, RT2X00_BCN_QUEUE_BEACON);
+       struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON);
        struct queue_entry *entry = NULL;
        unsigned int i;
 
@@ -192,13 +200,12 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
                return -ENODEV;
 
        /*
-        * When we don't support mixed interfaces (a combination
-        * of sta and ap virtual interfaces) then we can only
-        * add this interface when the rival interface count is 0.
+        * We don't support mixed combinations of sta and ap virtual
+        * interfaces. We can only add this interface when the rival
+        * interface count is 0.
         */
-       if (!test_bit(DRIVER_SUPPORT_MIXED_INTERFACES, &rt2x00dev->flags) &&
-           ((conf->type == IEEE80211_IF_TYPE_AP && rt2x00dev->intf_sta_count) ||
-            (conf->type != IEEE80211_IF_TYPE_AP && rt2x00dev->intf_ap_count)))
+       if ((conf->type == IEEE80211_IF_TYPE_AP && rt2x00dev->intf_sta_count) ||
+           (conf->type != IEEE80211_IF_TYPE_AP && rt2x00dev->intf_ap_count))
                return -ENOBUFS;
 
        /*
@@ -249,6 +256,13 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
         */
        rt2x00lib_config_intf(rt2x00dev, intf, conf->type, intf->mac, NULL);
 
+       /*
+        * Some filters depend on the current working mode. We can force
+        * an update during the next configure_filter() run by mac80211 by
+        * resetting the current packet_filter state.
+        */
+       rt2x00dev->packet_filter = 0;
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_add_interface);
@@ -376,6 +390,50 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_config_interface);
 
+void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
+                               unsigned int changed_flags,
+                               unsigned int *total_flags,
+                               int mc_count, struct dev_addr_list *mc_list)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+
+       /*
+        * Mask off any flags we are going to ignore
+        * from the total_flags field.
+        */
+       *total_flags &=
+           FIF_ALLMULTI |
+           FIF_FCSFAIL |
+           FIF_PLCPFAIL |
+           FIF_CONTROL |
+           FIF_OTHER_BSS |
+           FIF_PROMISC_IN_BSS;
+
+       /*
+        * Apply some rules to the filters:
+        * - Some filters imply different filters to be set.
+        * - Some things we can't filter out at all.
+        * - Multicast filter seems to kill broadcast traffic so never use it.
+        */
+       *total_flags |= FIF_ALLMULTI;
+       if (*total_flags & FIF_OTHER_BSS ||
+           *total_flags & FIF_PROMISC_IN_BSS)
+               *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
+
+       /*
+        * Check if there is any work left for us.
+        */
+       if (rt2x00dev->packet_filter == *total_flags)
+               return;
+       rt2x00dev->packet_filter = *total_flags;
+
+       if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
+               rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags);
+       else
+               queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter);
+
 int rt2x00mac_get_stats(struct ieee80211_hw *hw,
                        struct ieee80211_low_level_stats *stats)
 {
@@ -415,6 +473,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
 {
        struct rt2x00_dev *rt2x00dev = hw->priv;
        struct rt2x00_intf *intf = vif_to_intf(vif);
+       unsigned int delayed = 0;
 
        /*
         * When the association status has changed we must reset the link
@@ -429,20 +488,32 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
                        rt2x00dev->intf_associated++;
                else
                        rt2x00dev->intf_associated--;
+
+               if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
+                       rt2x00leds_led_assoc(rt2x00dev,
+                                            !!rt2x00dev->intf_associated);
+               else
+                       delayed |= DELAYED_LED_ASSOC;
        }
 
        /*
-        * When the preamble mode has changed, we should perform additional
-        * configuration steps. For all other changes we are already done.
+        * When the erp information has changed, we should perform
+        * additional configuration steps. For all other changes we are done.
         */
        if (changes & BSS_CHANGED_ERP_PREAMBLE) {
-               rt2x00lib_config_preamble(rt2x00dev, intf,
-                                         bss_conf->use_short_preamble);
+               if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
+                       rt2x00lib_config_erp(rt2x00dev, intf, bss_conf);
+               else
+                       delayed |= DELAYED_CONFIG_ERP;
+       }
 
-               spin_lock(&intf->lock);
-               memcpy(&intf->conf, bss_conf, sizeof(*bss_conf));
-               spin_unlock(&intf->lock);
+       spin_lock(&intf->lock);
+       memcpy(&intf->conf, bss_conf, sizeof(*bss_conf));
+       if (delayed) {
+               intf->delayed_flags |= delayed;
+               queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work);
        }
+       spin_unlock(&intf->lock);
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed);