aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/tx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-06-30 09:10:44 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-07-02 15:48:33 -0400
commitd9e8a70fa20dc3eaa00859a6eac0adfaef910c77 (patch)
tree8a9b5ce1da7243ab80b3aad35ce52f2dcd5cbc39 /net/mac80211/tx.c
parentacdfe9b4417fd04093bdaf8c0a4255ebfabc21a1 (diff)
mac80211: get rid of function pointers in TX path
This changes the TX path to no longer use function pointers for TX handlers but rather invoke them directly. If debugging is enabled, mark the TX handlers noinline because otherwise they all get inlined into invoke_tx_handlers() which makes it harder to see where a bug is. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r--net/mac80211/tx.c63
1 files changed, 29 insertions, 34 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 8f1c574bc8fb..7b930d3c2fba 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -220,7 +220,7 @@ static int inline is_ieee80211_device(struct net_device *dev,
220 220
221/* tx handlers */ 221/* tx handlers */
222 222
223static ieee80211_tx_result 223static ieee80211_tx_result debug_noinline
224ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) 224ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
225{ 225{
226#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 226#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
@@ -274,7 +274,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
274 return TX_CONTINUE; 274 return TX_CONTINUE;
275} 275}
276 276
277static ieee80211_tx_result 277static ieee80211_tx_result debug_noinline
278ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) 278ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
279{ 279{
280 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; 280 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
@@ -432,7 +432,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
432 return TX_CONTINUE; 432 return TX_CONTINUE;
433} 433}
434 434
435static ieee80211_tx_result 435static ieee80211_tx_result debug_noinline
436ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx) 436ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx)
437{ 437{
438 if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED)) 438 if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED))
@@ -444,7 +444,7 @@ ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx)
444 return ieee80211_tx_h_multicast_ps_buf(tx); 444 return ieee80211_tx_h_multicast_ps_buf(tx);
445} 445}
446 446
447static ieee80211_tx_result 447static ieee80211_tx_result debug_noinline
448ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) 448ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
449{ 449{
450 struct ieee80211_key *key; 450 struct ieee80211_key *key;
@@ -493,7 +493,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
493 return TX_CONTINUE; 493 return TX_CONTINUE;
494} 494}
495 495
496static ieee80211_tx_result 496static ieee80211_tx_result debug_noinline
497ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) 497ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
498{ 498{
499 struct rate_selection rsel; 499 struct rate_selection rsel;
@@ -537,7 +537,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
537 return TX_CONTINUE; 537 return TX_CONTINUE;
538} 538}
539 539
540static ieee80211_tx_result 540static ieee80211_tx_result debug_noinline
541ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) 541ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
542{ 542{
543 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; 543 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
@@ -632,7 +632,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
632 return TX_CONTINUE; 632 return TX_CONTINUE;
633} 633}
634 634
635static ieee80211_tx_result 635static ieee80211_tx_result debug_noinline
636ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) 636ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
637{ 637{
638 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; 638 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
@@ -724,7 +724,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
724 return TX_DROP; 724 return TX_DROP;
725} 725}
726 726
727static ieee80211_tx_result 727static ieee80211_tx_result debug_noinline
728ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) 728ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
729{ 729{
730 if (!tx->key) 730 if (!tx->key)
@@ -744,7 +744,7 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
744 return TX_DROP; 744 return TX_DROP;
745} 745}
746 746
747static ieee80211_tx_result 747static ieee80211_tx_result debug_noinline
748ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx) 748ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx)
749{ 749{
750 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; 750 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
@@ -774,7 +774,7 @@ ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx)
774 return TX_CONTINUE; 774 return TX_CONTINUE;
775} 775}
776 776
777static ieee80211_tx_result 777static ieee80211_tx_result debug_noinline
778ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) 778ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
779{ 779{
780 int i; 780 int i;
@@ -795,24 +795,6 @@ ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
795} 795}
796 796
797 797
798typedef ieee80211_tx_result (*ieee80211_tx_handler)(struct ieee80211_tx_data *);
799static ieee80211_tx_handler ieee80211_tx_handlers[] =
800{
801 ieee80211_tx_h_check_assoc,
802 ieee80211_tx_h_sequence,
803 ieee80211_tx_h_ps_buf,
804 ieee80211_tx_h_select_key,
805 ieee80211_tx_h_michael_mic_add,
806 ieee80211_tx_h_rate_ctrl,
807 ieee80211_tx_h_misc,
808 ieee80211_tx_h_fragment,
809 /* handlers after fragment must be aware of tx info fragmentation! */
810 ieee80211_tx_h_encrypt,
811 ieee80211_tx_h_calculate_duration,
812 ieee80211_tx_h_stats,
813 NULL
814};
815
816/* actual transmit path */ 798/* actual transmit path */
817 799
818/* 800/*
@@ -1111,16 +1093,29 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
1111static int invoke_tx_handlers(struct ieee80211_tx_data *tx) 1093static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
1112{ 1094{
1113 struct sk_buff *skb = tx->skb; 1095 struct sk_buff *skb = tx->skb;
1114 ieee80211_tx_handler *handler;
1115 ieee80211_tx_result res = TX_DROP; 1096 ieee80211_tx_result res = TX_DROP;
1116 int i; 1097 int i;
1117 1098
1118 for (handler = ieee80211_tx_handlers; *handler != NULL; handler++) { 1099#define CALL_TXH(txh) \
1119 res = (*handler)(tx); 1100 res = txh(tx); \
1120 if (res != TX_CONTINUE) 1101 if (res != TX_CONTINUE) \
1121 break; 1102 goto txh_done;
1122 } 1103
1104 CALL_TXH(ieee80211_tx_h_check_assoc)
1105 CALL_TXH(ieee80211_tx_h_sequence)
1106 CALL_TXH(ieee80211_tx_h_ps_buf)
1107 CALL_TXH(ieee80211_tx_h_select_key)
1108 CALL_TXH(ieee80211_tx_h_michael_mic_add)
1109 CALL_TXH(ieee80211_tx_h_rate_ctrl)
1110 CALL_TXH(ieee80211_tx_h_misc)
1111 CALL_TXH(ieee80211_tx_h_fragment)
1112 /* handlers after fragment must be aware of tx info fragmentation! */
1113 CALL_TXH(ieee80211_tx_h_encrypt)
1114 CALL_TXH(ieee80211_tx_h_calculate_duration)
1115 CALL_TXH(ieee80211_tx_h_stats)
1116#undef CALL_TXH
1123 1117
1118 txh_done:
1124 if (unlikely(res == TX_DROP)) { 1119 if (unlikely(res == TX_DROP)) {
1125 I802_DEBUG_INC(tx->local->tx_handlers_drop); 1120 I802_DEBUG_INC(tx->local->tx_handlers_drop);
1126 dev_kfree_skb(skb); 1121 dev_kfree_skb(skb);