diff options
author | John W. Linville <linville@tuxdriver.com> | 2010-07-29 16:14:13 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-08-16 14:39:46 -0400 |
commit | 4e6cbfd09c66893e5134c9896e9af353c2322b66 (patch) | |
tree | 274e8374c2b097058a5152da3bf6cf62d99dbad7 /net | |
parent | 68e887ef21dfd9adcf896ef92a9676bf9036a0aa (diff) |
mac80211: support use of NAPI for bottom-half processing
This patch implement basic infrastructure to support use of NAPI by
mac80211-based hardware drivers.
Because mac80211 devices can support multiple netdevs, a dummy netdev
is used for interfacing with the NAPI code in the core of the network
stack. That structure is hidden from the hardware drivers, but the
actual napi_struct is exposed in the ieee80211_hw structure so that the
poll routines in drivers can retrieve that structure. Hardware drivers
can also specify their own weight value for NAPI polling.
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/ieee80211_i.h | 5 | ||||
-rw-r--r-- | net/mac80211/iface.c | 4 | ||||
-rw-r--r-- | net/mac80211/main.c | 30 |
3 files changed, 39 insertions, 0 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 65e0ed6c2975..79d56454484a 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -870,6 +870,11 @@ struct ieee80211_local { | |||
870 | struct dentry *keys; | 870 | struct dentry *keys; |
871 | } debugfs; | 871 | } debugfs; |
872 | #endif | 872 | #endif |
873 | |||
874 | /* dummy netdev for use w/ NAPI */ | ||
875 | struct net_device napi_dev; | ||
876 | |||
877 | struct napi_struct napi; | ||
873 | }; | 878 | }; |
874 | 879 | ||
875 | static inline struct ieee80211_sub_if_data * | 880 | static inline struct ieee80211_sub_if_data * |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index ebbe264e2b0b..c1008a9d7bfb 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -187,6 +187,8 @@ static int ieee80211_open(struct net_device *dev) | |||
187 | res = drv_start(local); | 187 | res = drv_start(local); |
188 | if (res) | 188 | if (res) |
189 | goto err_del_bss; | 189 | goto err_del_bss; |
190 | if (local->ops->napi_poll) | ||
191 | napi_enable(&local->napi); | ||
190 | /* we're brought up, everything changes */ | 192 | /* we're brought up, everything changes */ |
191 | hw_reconf_flags = ~0; | 193 | hw_reconf_flags = ~0; |
192 | ieee80211_led_radio(local, true); | 194 | ieee80211_led_radio(local, true); |
@@ -519,6 +521,8 @@ static int ieee80211_stop(struct net_device *dev) | |||
519 | ieee80211_recalc_ps(local, -1); | 521 | ieee80211_recalc_ps(local, -1); |
520 | 522 | ||
521 | if (local->open_count == 0) { | 523 | if (local->open_count == 0) { |
524 | if (local->ops->napi_poll) | ||
525 | napi_disable(&local->napi); | ||
522 | ieee80211_clear_tx_pending(local); | 526 | ieee80211_clear_tx_pending(local); |
523 | ieee80211_stop_device(local); | 527 | ieee80211_stop_device(local); |
524 | 528 | ||
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 798a91b100cc..1ed956c9cb8b 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -390,6 +390,30 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, | |||
390 | } | 390 | } |
391 | #endif | 391 | #endif |
392 | 392 | ||
393 | static int ieee80211_napi_poll(struct napi_struct *napi, int budget) | ||
394 | { | ||
395 | struct ieee80211_local *local = | ||
396 | container_of(napi, struct ieee80211_local, napi); | ||
397 | |||
398 | return local->ops->napi_poll(&local->hw, budget); | ||
399 | } | ||
400 | |||
401 | void ieee80211_napi_schedule(struct ieee80211_hw *hw) | ||
402 | { | ||
403 | struct ieee80211_local *local = hw_to_local(hw); | ||
404 | |||
405 | napi_schedule(&local->napi); | ||
406 | } | ||
407 | EXPORT_SYMBOL(ieee80211_napi_schedule); | ||
408 | |||
409 | void ieee80211_napi_complete(struct ieee80211_hw *hw) | ||
410 | { | ||
411 | struct ieee80211_local *local = hw_to_local(hw); | ||
412 | |||
413 | napi_complete(&local->napi); | ||
414 | } | ||
415 | EXPORT_SYMBOL(ieee80211_napi_complete); | ||
416 | |||
393 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | 417 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, |
394 | const struct ieee80211_ops *ops) | 418 | const struct ieee80211_ops *ops) |
395 | { | 419 | { |
@@ -494,6 +518,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
494 | skb_queue_head_init(&local->skb_queue); | 518 | skb_queue_head_init(&local->skb_queue); |
495 | skb_queue_head_init(&local->skb_queue_unreliable); | 519 | skb_queue_head_init(&local->skb_queue_unreliable); |
496 | 520 | ||
521 | /* init dummy netdev for use w/ NAPI */ | ||
522 | init_dummy_netdev(&local->napi_dev); | ||
523 | |||
497 | return local_to_hw(local); | 524 | return local_to_hw(local); |
498 | } | 525 | } |
499 | EXPORT_SYMBOL(ieee80211_alloc_hw); | 526 | EXPORT_SYMBOL(ieee80211_alloc_hw); |
@@ -683,6 +710,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
683 | goto fail_ifa; | 710 | goto fail_ifa; |
684 | #endif | 711 | #endif |
685 | 712 | ||
713 | netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll, | ||
714 | local->hw.napi_weight); | ||
715 | |||
686 | return 0; | 716 | return 0; |
687 | 717 | ||
688 | #ifdef CONFIG_INET | 718 | #ifdef CONFIG_INET |