This patch reduces mdev usage by replacing struct net_device *
arguments that are never used except for dereferencing to get
struct ieee80211_local from ieee80211_ptr by struct
ieee80211_local directly.

Also, this patch changes ieee80211_rx_mgmt to no longer be callable
when local->apdev is NULL. All callers are updated accordingly,
in most cases actually increasing performance by not allocating
skbs when they won't be given to anyone anyway.

Instead of abusing ieee80211_rx_mgmt also introduce
ieee80211_rx_monitor.

Signed-off-by: Johannes Berg <[EMAIL PROTECTED]>

--- wireless-dev.orig/net/d80211/ieee80211.c    2006-11-19 20:13:56.079275208 
+0100
+++ wireless-dev/net/d80211/ieee80211.c 2006-11-19 20:13:56.719275208 +0100
@@ -210,9 +210,16 @@ static void ieee80211_key_threshold_noti
                                           struct ieee80211_key *key,
                                           struct sta_info *sta)
 {
+       struct ieee80211_local *local = dev->ieee80211_ptr;
        struct sk_buff *skb;
        struct ieee80211_msg_key_notification *msg;
 
+       /* if no one will get it anyway, don't even allocate it.
+        * unlikely because this is only relevant for APs
+        * where the device must be open... */
+       if (unlikely(!local->apdev))
+               return;
+
        skb = dev_alloc_skb(sizeof(struct ieee80211_frame_info) +
                            sizeof(struct ieee80211_msg_key_notification));
        if (!skb)
@@ -230,7 +237,7 @@ static void ieee80211_key_threshold_noti
 
        key->tx_rx_count = 0;
 
-       ieee80211_rx_mgmt(dev, skb, NULL,
+       ieee80211_rx_mgmt(local, skb, NULL,
                          ieee80211_msg_key_threshold_notification);
 }
 
@@ -2526,45 +2533,11 @@ ieee80211_get_rate(struct ieee80211_loca
        return NULL;
 }
 
-
 void
-ieee80211_rx_mgmt(struct net_device *dev, struct sk_buff *skb,
-                 struct ieee80211_rx_status *status, u32 msg_type)
+ieee80211_fill_frame_info(struct ieee80211_local *local,
+                         struct ieee80211_frame_info *fi,
+                         struct ieee80211_rx_status *status)
 {
-       struct ieee80211_local *local = dev->ieee80211_ptr;
-        struct ieee80211_frame_info *fi;
-        size_t hlen;
-        struct ieee80211_sub_if_data *sdata;
-
-       if (msg_type != ieee80211_msg_monitor)
-               dev = local->apdev;
-       if (!dev) {
-               dev_kfree_skb(skb);
-               return;
-       }
-        skb->dev = dev;
-
-        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
-       if (skb_headroom(skb) < sizeof(struct ieee80211_frame_info)) {
-               I802_DEBUG_INC(local->rx_expand_skb_head);
-               if (pskb_expand_head(skb, sizeof(struct ieee80211_frame_info),
-                                    0, GFP_ATOMIC)) {
-                       dev_kfree_skb(skb);
-                        return;
-               }
-       }
-
-       hlen = sizeof(struct ieee80211_frame_info);
-       if (msg_type == ieee80211_msg_monitor)
-               hlen -= sizeof(fi->msg_type);
-
-       fi = (struct ieee80211_frame_info *) skb_push(skb, hlen);
-        memset(fi, 0, hlen);
-       if (msg_type != ieee80211_msg_monitor)
-               fi->msg_type = htonl(msg_type);
-       fi->version = htonl(IEEE80211_FI_VERSION);
-        fi->length = htonl(hlen);
         if (status) {
                 struct timespec ts;
                struct ieee80211_rate *rate;
@@ -2615,27 +2588,104 @@ ieee80211_rx_mgmt(struct net_device *dev
                 fi->ssi_noise = 0x00000000;
                 fi->encoding = 0;
        } else {
+               /* clear everything because we really don't know.
+                * the msg_type field isn't present on monitor frames
+                * so we don't know whether it will be present or not,
+                * but it's ok to not clear it since it'll be assigned
+                * anyway */
+               memset(fi, 0, sizeof(*fi) - sizeof(fi->msg_type));
+
                 fi->ssi_type = htonl(ieee80211_ssi_none);
         }
+       fi->version = htonl(IEEE80211_FI_VERSION);
+       fi->length = cpu_to_be32(sizeof(*fi) - sizeof(fi->msg_type));
+}
+
+/* this routine is actually not just for this, but also
+ * for pushing fake 'management' frames into userspace.
+ * it shall be replaced by a netlink-based system. */
+void
+ieee80211_rx_mgmt(struct ieee80211_local *local, struct sk_buff *skb,
+                 struct ieee80211_rx_status *status, u32 msg_type)
+{
+       struct ieee80211_frame_info *fi;
+       const size_t hlen = sizeof(struct ieee80211_frame_info);
+       struct ieee80211_sub_if_data *sdata;
+
+       skb->dev = local->apdev;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(local->apdev);
+
+       if (skb_headroom(skb) < hlen) {
+               I802_DEBUG_INC(local->rx_expand_skb_head);
+               if (pskb_expand_head(skb, hlen, 0, GFP_ATOMIC)) {
+                       dev_kfree_skb(skb);
+                        return;
+               }
+       }
+
+       fi = (struct ieee80211_frame_info *) skb_push(skb, hlen);
 
-        sdata->stats.rx_packets++;
-        sdata->stats.rx_bytes += skb->len;
+       ieee80211_fill_frame_info(local, fi, status);
+       fi->msg_type = htonl(msg_type);
 
-        skb->mac.raw = skb->data;
+       sdata->stats.rx_packets++;
+       sdata->stats.rx_bytes += skb->len;
+
+       skb->mac.raw = skb->data;
        skb->ip_summed = CHECKSUM_UNNECESSARY;
        skb->pkt_type = PACKET_OTHERHOST;
-       skb->protocol = __constant_htons(ETH_P_802_2);
+       skb->protocol = htons(ETH_P_802_2);
        memset(skb->cb, 0, sizeof(skb->cb));
-        netif_rx(skb);
+       netif_rx(skb);
 }
 
+void
+ieee80211_rx_monitor(struct net_device *dev, struct sk_buff *skb,
+                    struct ieee80211_rx_status *status)
+{
+       struct ieee80211_local *local = dev->ieee80211_ptr;
+       struct ieee80211_frame_info *fi;
+       struct ieee80211_sub_if_data *sdata;
+       const size_t hlen = sizeof(struct ieee80211_frame_info)
+                               - sizeof(fi->msg_type);
+
+       skb->dev = dev;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+       if (skb_headroom(skb) < hlen) {
+               I802_DEBUG_INC(local->rx_expand_skb_head);
+               if (pskb_expand_head(skb, hlen, 0, GFP_ATOMIC)) {
+                       dev_kfree_skb(skb);
+                        return;
+               }
+       }
+
+       fi = (struct ieee80211_frame_info *) skb_push(skb, hlen);
+
+       ieee80211_fill_frame_info(local, fi, status);
+       sdata->stats.rx_packets++;
+       sdata->stats.rx_bytes += skb->len;
+
+       skb->mac.raw = skb->data;
+       skb->ip_summed = CHECKSUM_UNNECESSARY;
+       skb->pkt_type = PACKET_OTHERHOST;
+       skb->protocol = htons(ETH_P_802_2);
+       memset(skb->cb, 0, sizeof(skb->cb));
+       netif_rx(skb);
+}
 
 int ieee80211_radar_status(struct net_device *dev, int channel, int radar,
                           int radar_type)
 {
+       struct ieee80211_local *local = dev->ieee80211_ptr;
        struct sk_buff *skb;
        struct ieee80211_radar_info *msg;
 
+       if (!local->apdev)
+               return 0;
+
        skb = dev_alloc_skb(sizeof(struct ieee80211_frame_info) +
                            sizeof(struct ieee80211_radar_info));
 
@@ -2649,7 +2699,7 @@ int ieee80211_radar_status(struct net_de
        msg->radar = radar;
        msg->radar_type = radar_type;
 
-       ieee80211_rx_mgmt(dev, skb, NULL, ieee80211_msg_radar);
+       ieee80211_rx_mgmt(local, skb, NULL, ieee80211_msg_radar);
        return 0;
 }
 EXPORT_SYMBOL(ieee80211_radar_status);
@@ -2657,9 +2707,15 @@ EXPORT_SYMBOL(ieee80211_radar_status);
 int ieee80211_set_aid_for_sta(struct net_device *dev, u8 *peer_address,
                              u16 aid)
 {
+       struct ieee80211_local *local = dev->ieee80211_ptr;
        struct sk_buff *skb;
        struct ieee80211_msg_set_aid_for_sta *msg;
 
+       /* unlikely because if this event only happens for APs,
+        * which require an open ap device. */
+       if (unlikely(!local->apdev))
+               return 0;
+
        skb = dev_alloc_skb(sizeof(struct ieee80211_frame_info) +
                            sizeof(struct ieee80211_msg_set_aid_for_sta));
 
@@ -2672,7 +2728,7 @@ int ieee80211_set_aid_for_sta(struct net
        memcpy(msg->sta_address, peer_address, ETH_ALEN);
        msg->aid = aid;
 
-       ieee80211_rx_mgmt(dev, skb, NULL, ieee80211_msg_set_aid_for_sta);
+       ieee80211_rx_mgmt(local, skb, NULL, ieee80211_msg_set_aid_for_sta);
        return 0;
 }
 EXPORT_SYMBOL(ieee80211_set_aid_for_sta);
@@ -3007,8 +3063,7 @@ static ieee80211_txrx_result
 ieee80211_rx_h_monitor(struct ieee80211_txrx_data *rx)
 {
        if (rx->sdata->type == IEEE80211_IF_TYPE_MNTR) {
-               ieee80211_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status,
-                                  ieee80211_msg_monitor);
+               ieee80211_rx_monitor(rx->dev, rx->skb, rx->u.rx.status);
                return TXRX_QUEUED;
        }
 
@@ -3080,7 +3135,10 @@ ieee80211_rx_h_check(struct ieee80211_tx
                        return TXRX_DROP;
                }
 
-               ieee80211_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status,
+               if (!rx->local->apdev)
+                       return TXRX_DROP;
+
+               ieee80211_rx_mgmt(rx->local, rx->skb, rx->u.rx.status,
                                  ieee80211_msg_sta_not_assoc);
                return TXRX_QUEUED;
        }
@@ -3116,8 +3174,10 @@ ieee80211_rx_h_check(struct ieee80211_tx
                                       MAC_ARG(hdr->addr1),
                                       MAC_ARG(hdr->addr2),
                                       MAC_ARG(hdr->addr3));
+                               if (!rx->local->apdev)
+                                       return TXRX_DROP;
                                ieee80211_rx_mgmt(
-                                       rx->dev, rx->skb, rx->u.rx.status,
+                                       rx->local, rx->skb, rx->u.rx.status,
                                        ieee80211_msg_wep_frame_unknown_key);
                                return TXRX_QUEUED;
                        }
@@ -3267,7 +3327,9 @@ ieee80211_rx_h_802_1x_pae(struct ieee802
            rx->sdata->type != IEEE80211_IF_TYPE_STA && rx->u.rx.ra_match) {
                /* Pass both encrypted and unencrypted EAPOL frames to user
                 * space for processing. */
-               ieee80211_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status,
+               if (!rx->local->apdev)
+                       return TXRX_DROP;
+               ieee80211_rx_mgmt(rx->local, rx->skb, rx->u.rx.status,
                                   ieee80211_msg_normal);
                return TXRX_QUEUED;
        }
@@ -3328,7 +3390,9 @@ ieee80211_rx_h_mgmt(struct ieee80211_txr
                ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status);
        } else {
                /* Management frames are sent to hostapd for processing */
-               ieee80211_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status,
+               if (!rx->local->apdev)
+                       return TXRX_DROP;
+               ieee80211_rx_mgmt(rx->local, rx->skb, rx->u.rx.status,
                                  ieee80211_msg_normal);
        }
        return TXRX_QUEUED;
@@ -3368,7 +3432,10 @@ ieee80211_rx_h_passive_scan(struct ieee8
                            rx->skb->len > FCS_LEN)
                                skb_trim(rx->skb, rx->skb->len - FCS_LEN);
 
-                        ieee80211_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status,
+                       if (!rx->local->apdev)
+                               return TXRX_DROP;
+                       ieee80211_rx_mgmt(rx->local, rx->skb,
+                                         rx->u.rx.status,
                                           ieee80211_msg_passive_scan);
                         return TXRX_QUEUED;
                 } else {
@@ -3502,7 +3569,9 @@ static void ieee80211_rx_michael_mic_rep
        /* TODO: consider verifying the MIC error report with software
         * implementation if we get too many spurious reports from the
         * hardware. */
-       ieee80211_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status,
+       if (!rx->local->apdev)
+               goto ignore;
+       ieee80211_rx_mgmt(rx->local, rx->skb, rx->u.rx.status,
                          ieee80211_msg_michael_mic_failure);
        return;
 
@@ -4148,7 +4217,8 @@ void ieee80211_tx_status(struct net_devi
                        local->dot11FailedCount++;
         }
 
-        if (!(status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS)) {
+        if (!(status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS)
+            || unlikely(!local->apdev)) {
                dev_kfree_skb(skb);
                return;
        }
@@ -4167,7 +4237,7 @@ void ieee80211_tx_status(struct net_devi
        skb = skb2;
 
         /* Send frame to hostapd */
-        ieee80211_rx_mgmt(dev, skb, NULL, msg_type);
+        ieee80211_rx_mgmt(local, skb, NULL, msg_type);
 }
 EXPORT_SYMBOL(ieee80211_tx_status);
 
--- wireless-dev.orig/net/d80211/ieee80211_i.h  2006-11-19 20:13:56.069275208 
+0100
+++ wireless-dev/net/d80211/ieee80211_i.h       2006-11-19 20:13:56.719275208 
+0100
@@ -571,7 +571,7 @@ struct ieee80211_key *ieee80211_key_allo
                                          int idx, size_t key_len, gfp_t flags);
 void ieee80211_key_free(struct ieee80211_key *key);
 void ieee80211_key_release(struct kobject *kobj);
-void ieee80211_rx_mgmt(struct net_device *dev, struct sk_buff *skb,
+void ieee80211_rx_mgmt(struct ieee80211_local *local, struct sk_buff *skb,
                       struct ieee80211_rx_status *status, u32 msg_type);
 void ieee80211_prepare_rates(struct ieee80211_local *local);
 void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx);
--- wireless-dev.orig/net/d80211/wpa.c  2006-11-19 20:13:51.199275208 +0100
+++ wireless-dev/net/d80211/wpa.c       2006-11-19 20:13:56.719275208 +0100
@@ -267,7 +267,10 @@ ieee80211_rx_h_michael_mic_verify(struct
                        kfree(buf);
                } while (0);
 
-               ieee80211_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status,
+               if (!rx->local->apdev)
+                       return TXRX_DROP;
+
+               ieee80211_rx_mgmt(rx->local, rx->skb, rx->u.rx.status,
                                  ieee80211_msg_michael_mic_failure);
 
                return TXRX_QUEUED;
--- wireless-dev.orig/include/net/d80211_common.h       2006-11-19 
20:13:51.249275208 +0100
+++ wireless-dev/include/net/d80211_common.h    2006-11-19 20:13:56.719275208 
+0100
@@ -50,7 +50,7 @@ enum ieee80211_msg_type {
        ieee80211_msg_passive_scan = 3,
        ieee80211_msg_wep_frame_unknown_key = 4,
        ieee80211_msg_michael_mic_failure = 5,
-       ieee80211_msg_monitor = 6,
+       /* hole at 6, was monitor but never sent to userspace */
        ieee80211_msg_sta_not_assoc = 7,
        ieee80211_msg_set_aid_for_sta = 8 /* used by Intersil MVC driver */,
        ieee80211_msg_key_threshold_notification = 9,


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to