summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 5b05b2a)
raw | patch | inline | side by side (parent: 5b05b2a)
author | Hauke Mehrtens <hauke@hauke-m.de> | |
Sun, 22 May 2011 10:47:07 +0000 (12:47 +0200) | ||
committer | Luis R. Rodriguez <lrodriguez@atheros.com> | |
Mon, 23 May 2011 21:05:32 +0000 (14:05 -0700) |
Backporting kfree_rcu() in compat does not work as
struct rcu_head->func is always interpreted as a pointer in older
kernel versions, but when using kfree_rcu() it is set to an offset.
rcu_head->func is used in some functions in the kernel not backported
by compat-wireless.
This patch is based on the patch posted by Ignacy Gawedzki <i@lri.fr>
on the mailing list.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
struct rcu_head->func is always interpreted as a pointer in older
kernel versions, but when using kfree_rcu() it is set to an offset.
rcu_head->func is used in some functions in the kernel not backported
by compat-wireless.
This patch is based on the patch posted by Ignacy Gawedzki <i@lri.fr>
on the mailing list.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
patches/41-no-kfree-rcu.patch | [new file with mode: 0644] | patch | blob |
diff --git a/patches/41-no-kfree-rcu.patch b/patches/41-no-kfree-rcu.patch
--- /dev/null
@@ -0,0 +1,83 @@
+--- a/net/mac80211/agg-tx.c
++++ b/net/mac80211/agg-tx.c
+@@ -144,6 +144,16 @@ void ieee80211_assign_tid_tx(struct sta_
+ rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], tid_tx);
+ }
+
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,40))
++static void kfree_tid_tx(struct rcu_head *rcu_head)
++{
++ struct tid_ampdu_tx *tid_tx =
++ container_of(rcu_head, struct tid_ampdu_tx, rcu_head);
++
++ kfree(tid_tx);
++}
++#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,40)) */
++
+ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
+ enum ieee80211_back_parties initiator,
+ bool tx)
+@@ -166,7 +176,11 @@ int ___ieee80211_stop_tx_ba_session(stru
+ /* not even started yet! */
+ ieee80211_assign_tid_tx(sta, tid, NULL);
+ spin_unlock_bh(&sta->lock);
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,40))
+ kfree_rcu(tid_tx, rcu_head);
++#else
++ call_rcu(&tid_tx->rcu_head, kfree_tid_tx);
++#endif
+ return 0;
+ }
+
+@@ -325,7 +339,11 @@ void ieee80211_tx_ba_session_handle_star
+ spin_unlock_bh(&sta->lock);
+
+ ieee80211_wake_queue_agg(local, tid);
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,40))
+ kfree_rcu(tid_tx, rcu_head);
++#else
++ call_rcu(&tid_tx->rcu_head, kfree_tid_tx);
++#endif
+ return;
+ }
+
+@@ -710,7 +728,11 @@ void ieee80211_stop_tx_ba_cb(struct ieee
+
+ ieee80211_agg_splice_finish(local, tid);
+
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,40))
+ kfree_rcu(tid_tx, rcu_head);
++#else
++ call_rcu(&tid_tx->rcu_head, kfree_tid_tx);
++#endif
+
+ unlock_sta:
+ spin_unlock_bh(&sta->lock);
+--- a/net/mac80211/work.c
++++ b/net/mac80211/work.c
+@@ -65,10 +65,25 @@ static void run_again(struct ieee80211_l
+ mod_timer(&local->work_timer, timeout);
+ }
+
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,40))
+ void free_work(struct ieee80211_work *wk)
+ {
+ kfree_rcu(wk, rcu_head);
+ }
++#else
++static void work_free_rcu(struct rcu_head *head)
++{
++ struct ieee80211_work *wk =
++ container_of(head, struct ieee80211_work, rcu_head);
++
++ kfree(wk);
++}
++
++void free_work(struct ieee80211_work *wk)
++{
++ call_rcu(&wk->rcu_head, work_free_rcu);
++}
++#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,40)) */
+
+ static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len,
+ struct ieee80211_supported_band *sband,