/* rx handlers */
 
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_local *local = rx->local;
 }
 
 
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_hdr *hdr;
 }
 
 
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
        return sent;
 }
 
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 {
        struct sta_info *sta = rx->sta;
        return NULL;
 }
 
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_hdr *hdr;
        return RX_CONTINUE;
 }
 
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
        return RX_QUEUED;
 }
 
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx)
 {
        u16 fc = rx->fc;
        }
 }
 
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
 {
        struct net_device *dev = rx->dev;
        return RX_QUEUED;
 }
 
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
 {
        struct net_device *dev = rx->dev;
        return RX_QUEUED;
 }
 
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_local *local = rx->local;
        return RX_CONTINUE;
 }
 
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_sub_if_data *sdata;
        dev_kfree_skb(skb);
 }
 
-typedef ieee80211_rx_result (*ieee80211_rx_handler)(struct ieee80211_rx_data *);
-static ieee80211_rx_handler ieee80211_rx_handlers[] =
-{
-       ieee80211_rx_h_passive_scan,
-       ieee80211_rx_h_check,
-       ieee80211_rx_h_decrypt,
-       ieee80211_rx_h_sta_process,
-       ieee80211_rx_h_defragment,
-       ieee80211_rx_h_ps_poll,
-       ieee80211_rx_h_michael_mic_verify,
-       /* this must be after decryption - so header is counted in MPDU mic
-        * must be before pae and data, so QOS_DATA format frames
-        * are not passed to user space by these functions
-        */
-       ieee80211_rx_h_remove_qos_control,
-       ieee80211_rx_h_amsdu,
-       ieee80211_rx_h_data,
-       ieee80211_rx_h_ctrl,
-       ieee80211_rx_h_mgmt,
-       NULL
-};
 
 static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
                                         struct ieee80211_rx_data *rx,
                                         struct sk_buff *skb)
 {
-       ieee80211_rx_handler *handler;
        ieee80211_rx_result res = RX_DROP_MONITOR;
 
        rx->skb = skb;
        rx->sdata = sdata;
        rx->dev = sdata->dev;
 
-       for (handler = ieee80211_rx_handlers; *handler != NULL; handler++) {
-               res = (*handler)(rx);
-
-               switch (res) {
-               case RX_CONTINUE:
-                       continue;
-               case RX_DROP_UNUSABLE:
-               case RX_DROP_MONITOR:
-                       I802_DEBUG_INC(sdata->local->rx_handlers_drop);
-                       if (rx->sta)
-                               rx->sta->rx_dropped++;
-                       break;
-               case RX_QUEUED:
-                       I802_DEBUG_INC(sdata->local->rx_handlers_queued);
-                       break;
-               }
-               break;
-       }
-
+#define CALL_RXH(rxh)          \
+       res = rxh(rx);          \
+       if (res != RX_CONTINUE) \
+               goto rxh_done;
+
+       CALL_RXH(ieee80211_rx_h_passive_scan)
+       CALL_RXH(ieee80211_rx_h_check)
+       CALL_RXH(ieee80211_rx_h_decrypt)
+       CALL_RXH(ieee80211_rx_h_sta_process)
+       CALL_RXH(ieee80211_rx_h_defragment)
+       CALL_RXH(ieee80211_rx_h_ps_poll)
+       CALL_RXH(ieee80211_rx_h_michael_mic_verify)
+       /* must be after MMIC verify so header is counted in MPDU mic */
+       CALL_RXH(ieee80211_rx_h_remove_qos_control)
+       CALL_RXH(ieee80211_rx_h_amsdu)
+       CALL_RXH(ieee80211_rx_h_data)
+       CALL_RXH(ieee80211_rx_h_ctrl)
+       CALL_RXH(ieee80211_rx_h_mgmt)
+
+#undef CALL_RXH
+
+ rxh_done:
        switch (res) {
-       case RX_CONTINUE:
        case RX_DROP_MONITOR:
+               I802_DEBUG_INC(sdata->local->rx_handlers_drop);
+               if (rx->sta)
+                       rx->sta->rx_dropped++;
+               /* fall through */
+       case RX_CONTINUE:
                ieee80211_rx_cooked_monitor(rx);
                break;
        case RX_DROP_UNUSABLE:
+               I802_DEBUG_INC(sdata->local->rx_handlers_drop);
+               if (rx->sta)
+                       rx->sta->rx_dropped++;
                dev_kfree_skb(rx->skb);
                break;
+       case RX_QUEUED:
+               I802_DEBUG_INC(sdata->local->rx_handlers_queued);
+               break;
        }
 }