]> err.no Git - linux-2.6/blobdiff - net/mac80211/main.c
mac80211: Decrease number of explicit ->tx_queue references.
[linux-2.6] / net / mac80211 / main.c
index 5c5396edad3233f730be3852c2a7f8955a03f287..2968baa66b91fa870d03e82e54084640d39364c4 100644 (file)
@@ -151,9 +151,7 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
        /* FIX: what would be proper limits for MTU?
         * This interface uses 802.3 frames. */
        if (new_mtu < 256 ||
-               new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) {
-               printk(KERN_WARNING "%s: invalid MTU %d\n",
-                      dev->name, new_mtu);
+           new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) {
                return -EINVAL;
        }
 
@@ -184,10 +182,11 @@ static int ieee80211_open(struct net_device *dev)
 {
        struct ieee80211_sub_if_data *sdata, *nsdata;
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct sta_info *sta;
        struct ieee80211_if_init_conf conf;
+       u32 changed = 0;
        int res;
        bool need_hw_reconfig = 0;
-       struct sta_info *sta;
 
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
@@ -331,7 +330,8 @@ static int ieee80211_open(struct net_device *dev)
                        goto err_stop;
 
                ieee80211_if_config(dev);
-               ieee80211_reset_erp_info(dev);
+               changed |= ieee80211_reset_erp_info(dev);
+               ieee80211_bss_info_change_notify(sdata, changed);
                ieee80211_enable_keys(sdata);
 
                if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
@@ -535,8 +535,6 @@ static int ieee80211_stop(struct net_device *dev)
                                local->sta_hw_scanning = 0;
                }
 
-               flush_workqueue(local->hw.workqueue);
-
                sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
                kfree(sdata->u.sta.extra_ie);
                sdata->u.sta.extra_ie = NULL;
@@ -560,6 +558,8 @@ static int ieee80211_stop(struct net_device *dev)
 
                ieee80211_led_radio(local, 0);
 
+               flush_workqueue(local->hw.workqueue);
+
                tasklet_disable(&local->tx_pending_tasklet);
                tasklet_disable(&local->tasklet);
        }
@@ -570,6 +570,7 @@ static int ieee80211_stop(struct net_device *dev)
 int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
 {
        struct ieee80211_local *local = hw_to_local(hw);
+       struct netdev_queue *txq;
        struct sta_info *sta;
        struct ieee80211_sub_if_data *sdata;
        u16 start_seq_num = 0;
@@ -589,7 +590,9 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
 
        sta = sta_info_get(local, ra);
        if (!sta) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
                printk(KERN_DEBUG "Could not find the station\n");
+#endif
                ret = -ENOENT;
                goto exit;
        }
@@ -617,9 +620,11 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
        sta->ampdu_mlme.tid_tx[tid] =
                        kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC);
        if (!sta->ampdu_mlme.tid_tx[tid]) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
                if (net_ratelimit())
                        printk(KERN_ERR "allocate tx mlme to tid %d failed\n",
                                        tid);
+#endif
                ret = -ENOMEM;
                goto err_unlock_sta;
        }
@@ -632,7 +637,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
 
        /* ensure that TX flow won't interrupt us
         * until the end of the call to requeue function */
-       spin_lock_bh(&local->mdev->queue_lock);
+       txq = &local->mdev->tx_queue;
+       spin_lock_bh(&txq->lock);
 
        /* create a new queue for this aggregation */
        ret = ieee80211_ht_agg_queue_add(local, sta, tid);
@@ -671,7 +677,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
 
        /* Will put all the packets in the new SW queue */
        ieee80211_requeue(local, ieee802_1d_to_ac[tid]);
-       spin_unlock_bh(&local->mdev->queue_lock);
+       spin_unlock_bh(&txq->lock);
        spin_unlock_bh(&sta->lock);
 
        /* send an addBA request */
@@ -689,13 +695,15 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
        sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires =
                                jiffies + ADDBA_RESP_INTERVAL;
        add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
+#ifdef CONFIG_MAC80211_HT_DEBUG
        printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid);
+#endif
        goto exit;
 
 err_unlock_queue:
        kfree(sta->ampdu_mlme.tid_tx[tid]);
        sta->ampdu_mlme.tid_tx[tid] = NULL;
-       spin_unlock_bh(&local->mdev->queue_lock);
+       spin_unlock_bh(&txq->lock);
        ret = -EBUSY;
 err_unlock_sta:
        spin_unlock_bh(&sta->lock);
@@ -771,8 +779,10 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
        DECLARE_MAC_BUF(mac);
 
        if (tid >= STA_TID_NUM) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
                printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
                                tid, STA_TID_NUM);
+#endif
                return;
        }
 
@@ -780,8 +790,10 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
        sta = sta_info_get(local, ra);
        if (!sta) {
                rcu_read_unlock();
+#ifdef CONFIG_MAC80211_HT_DEBUG
                printk(KERN_DEBUG "Could not find station: %s\n",
                                print_mac(mac, ra));
+#endif
                return;
        }
 
@@ -789,8 +801,10 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
        spin_lock_bh(&sta->lock);
 
        if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
                printk(KERN_DEBUG "addBA was not requested yet, state is %d\n",
                                *state);
+#endif
                spin_unlock_bh(&sta->lock);
                rcu_read_unlock();
                return;
@@ -801,7 +815,9 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
        *state |= HT_ADDBA_DRV_READY_MSK;
 
        if (*state == HT_AGG_STATE_OPERATIONAL) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
                printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid);
+#endif
                ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
        }
        spin_unlock_bh(&sta->lock);
@@ -812,14 +828,17 @@ EXPORT_SYMBOL(ieee80211_start_tx_ba_cb);
 void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
 {
        struct ieee80211_local *local = hw_to_local(hw);
+       struct netdev_queue *txq;
        struct sta_info *sta;
        u8 *state;
        int agg_queue;
        DECLARE_MAC_BUF(mac);
 
        if (tid >= STA_TID_NUM) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
                printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
                                tid, STA_TID_NUM);
+#endif
                return;
        }
 
@@ -831,8 +850,10 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
        rcu_read_lock();
        sta = sta_info_get(local, ra);
        if (!sta) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
                printk(KERN_DEBUG "Could not find station: %s\n",
                                print_mac(mac, ra));
+#endif
                rcu_read_unlock();
                return;
        }
@@ -842,7 +863,9 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
         * ieee80211_stop_tx_ba_session will let only
         * one stop call to pass through per sta/tid */
        if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
                printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n");
+#endif
                rcu_read_unlock();
                return;
        }
@@ -855,10 +878,11 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
 
        /* avoid ordering issues: we are the only one that can modify
         * the content of the qdiscs */
-       spin_lock_bh(&local->mdev->queue_lock);
+       txq = &local->mdev->tx_queue;
+       spin_lock_bh(&txq->lock);
        /* remove the queue for this aggregation */
        ieee80211_ht_agg_queue_remove(local, sta, tid, 1);
-       spin_unlock_bh(&local->mdev->queue_lock);
+       spin_unlock_bh(&txq->lock);
 
        /* we just requeued the all the frames that were in the removed
         * queue, and since we might miss a softirq we do netif_schedule.
@@ -884,9 +908,11 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
        struct sk_buff *skb = dev_alloc_skb(0);
 
        if (unlikely(!skb)) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
                if (net_ratelimit())
                        printk(KERN_WARNING "%s: Not enough memory, "
                               "dropping start BA session", skb->dev->name);
+#endif
                return;
        }
        ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
@@ -907,9 +933,11 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
        struct sk_buff *skb = dev_alloc_skb(0);
 
        if (unlikely(!skb)) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
                if (net_ratelimit())
                        printk(KERN_WARNING "%s: Not enough memory, "
                               "dropping stop BA session", skb->dev->name);
+#endif
                return;
        }
        ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
@@ -1168,15 +1196,13 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
                                             changed);
 }
 
-void ieee80211_reset_erp_info(struct net_device *dev)
+u32 ieee80211_reset_erp_info(struct net_device *dev)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
        sdata->bss_conf.use_cts_prot = 0;
        sdata->bss_conf.use_short_preamble = 0;
-       ieee80211_bss_info_change_notify(sdata,
-                                        BSS_CHANGED_ERP_CTS_PROT |
-                                        BSS_CHANGED_ERP_PREAMBLE);
+       return BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE;
 }
 
 void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
@@ -1236,9 +1262,8 @@ static void ieee80211_tasklet_handler(unsigned long data)
                                                 ra_tid->ra, ra_tid->tid);
                        dev_kfree_skb(skb);
                        break ;
-               default: /* should never get here! */
-                       printk(KERN_ERR "%s: Unknown message type (%d)\n",
-                              wiphy_name(local->hw.wiphy), skb->pkt_type);
+               default:
+                       WARN_ON(1);
                        dev_kfree_skb(skb);
                        break;
                }
@@ -1365,12 +1390,14 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
                return;
        }
 
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
        if (net_ratelimit())
                printk(KERN_DEBUG "%s: dropped TX filtered frame, "
                       "queue_len=%d PS=%d @%lu\n",
                       wiphy_name(local->hw.wiphy),
                       skb_queue_len(&sta->tx_filtered),
                       !!test_sta_flags(sta, WLAN_STA_PS), jiffies);
+#endif
        dev_kfree_skb(skb);
 }
 
@@ -1381,14 +1408,15 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
        struct ieee80211_local *local = hw_to_local(hw);
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        u16 frag, type;
+       __le16 fc;
        struct ieee80211_tx_status_rtap_hdr *rthdr;
        struct ieee80211_sub_if_data *sdata;
        struct net_device *prev_dev = NULL;
+       struct sta_info *sta;
 
        rcu_read_lock();
 
        if (info->status.excessive_retries) {
-               struct sta_info *sta;
                sta = sta_info_get(local, hdr->addr1);
                if (sta) {
                        if (test_sta_flags(sta, WLAN_STA_PS)) {
@@ -1403,8 +1431,24 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
                }
        }
 
+       fc = hdr->frame_control;
+
+       if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) &&
+           (ieee80211_is_data_qos(fc))) {
+               u16 tid, ssn;
+               u8 *qc;
+               sta = sta_info_get(local, hdr->addr1);
+               if (sta) {
+                       qc = ieee80211_get_qos_ctl(hdr);
+                       tid = qc[0] & 0xf;
+                       ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10)
+                                               & IEEE80211_SCTL_SEQ);
+                       ieee80211_send_bar(sta->sdata->dev, hdr->addr1,
+                                          tid, ssn);
+               }
+       }
+
        if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
-               struct sta_info *sta;
                sta = sta_info_get(local, hdr->addr1);
                if (sta) {
                        ieee80211_handle_filtered_frame(local, sta, skb);
@@ -1691,7 +1735,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        list_add_tail(&sdata->list, &local->interfaces);
 
        name = wiphy_dev(local->hw.wiphy)->driver->name;
-       local->hw.workqueue = create_singlethread_workqueue(name);
+       local->hw.workqueue = create_freezeable_workqueue(name);
        if (!local->hw.workqueue) {
                result = -ENOMEM;
                goto fail_workqueue;