354-mac80211-calculate-hash-for-fq-without-holding-fq-lo.patch 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. From: Felix Fietkau <[email protected]>
  2. Date: Sat, 16 Mar 2019 17:57:38 +0100
  3. Subject: [PATCH] mac80211: calculate hash for fq without holding fq->lock
  4. in itxq enqueue
  5. Reduces lock contention on enqueue/dequeue of iTXQ packets
  6. Signed-off-by: Felix Fietkau <[email protected]>
  7. ---
  8. --- a/include/net/fq_impl.h
  9. +++ b/include/net/fq_impl.h
  10. @@ -107,21 +107,23 @@ begin:
  11. return skb;
  12. }
  13. +static u32 fq_flow_idx(struct fq *fq, struct sk_buff *skb)
  14. +{
  15. + u32 hash = skb_get_hash_perturb(skb, fq->perturbation);
  16. +
  17. + return reciprocal_scale(hash, fq->flows_cnt);
  18. +}
  19. +
  20. static struct fq_flow *fq_flow_classify(struct fq *fq,
  21. - struct fq_tin *tin,
  22. + struct fq_tin *tin, u32 idx,
  23. struct sk_buff *skb,
  24. fq_flow_get_default_t get_default_func)
  25. {
  26. struct fq_flow *flow;
  27. - u32 hash;
  28. - u32 idx;
  29. lockdep_assert_held(&fq->lock);
  30. - hash = skb_get_hash_perturb(skb, fq->perturbation);
  31. - idx = reciprocal_scale(hash, fq->flows_cnt);
  32. flow = &fq->flows[idx];
  33. -
  34. if (flow->tin && flow->tin != tin) {
  35. flow = get_default_func(fq, tin, idx, skb);
  36. tin->collisions++;
  37. @@ -153,7 +155,7 @@ static void fq_recalc_backlog(struct fq
  38. }
  39. static void fq_tin_enqueue(struct fq *fq,
  40. - struct fq_tin *tin,
  41. + struct fq_tin *tin, u32 idx,
  42. struct sk_buff *skb,
  43. fq_skb_free_t free_func,
  44. fq_flow_get_default_t get_default_func)
  45. @@ -163,7 +165,7 @@ static void fq_tin_enqueue(struct fq *fq
  46. lockdep_assert_held(&fq->lock);
  47. - flow = fq_flow_classify(fq, tin, skb, get_default_func);
  48. + flow = fq_flow_classify(fq, tin, idx, skb, get_default_func);
  49. flow->tin = tin;
  50. flow->backlog += skb->len;
  51. --- a/net/mac80211/tx.c
  52. +++ b/net/mac80211/tx.c
  53. @@ -1390,11 +1390,15 @@ static void ieee80211_txq_enqueue(struct
  54. {
  55. struct fq *fq = &local->fq;
  56. struct fq_tin *tin = &txqi->tin;
  57. + u32 flow_idx = fq_flow_idx(fq, skb);
  58. ieee80211_set_skb_enqueue_time(skb);
  59. - fq_tin_enqueue(fq, tin, skb,
  60. +
  61. + spin_lock_bh(&fq->lock);
  62. + fq_tin_enqueue(fq, tin, flow_idx, skb,
  63. fq_skb_free_func,
  64. fq_flow_get_default_func);
  65. + spin_unlock_bh(&fq->lock);
  66. }
  67. static bool fq_vlan_filter_func(struct fq *fq, struct fq_tin *tin,
  68. @@ -1564,7 +1568,6 @@ static bool ieee80211_queue_skb(struct i
  69. struct sta_info *sta,
  70. struct sk_buff *skb)
  71. {
  72. - struct fq *fq = &local->fq;
  73. struct ieee80211_vif *vif;
  74. struct txq_info *txqi;
  75. @@ -1582,9 +1585,7 @@ static bool ieee80211_queue_skb(struct i
  76. if (!txqi)
  77. return false;
  78. - spin_lock_bh(&fq->lock);
  79. ieee80211_txq_enqueue(local, txqi, skb);
  80. - spin_unlock_bh(&fq->lock);
  81. schedule_and_wake_txq(local, txqi);
  82. @@ -3198,6 +3199,7 @@ static bool ieee80211_amsdu_aggregate(st
  83. u8 max_subframes = sta->sta.max_amsdu_subframes;
  84. int max_frags = local->hw.max_tx_fragments;
  85. int max_amsdu_len = sta->sta.max_amsdu_len;
  86. + u32 flow_idx;
  87. int orig_truesize;
  88. __be16 len;
  89. void *data;
  90. @@ -3220,6 +3222,8 @@ static bool ieee80211_amsdu_aggregate(st
  91. max_amsdu_len = min_t(int, max_amsdu_len,
  92. sta->sta.max_rc_amsdu_len);
  93. + flow_idx = fq_flow_idx(fq, skb);
  94. +
  95. spin_lock_bh(&fq->lock);
  96. /* TODO: Ideally aggregation should be done on dequeue to remain
  97. @@ -3227,7 +3231,8 @@ static bool ieee80211_amsdu_aggregate(st
  98. */
  99. tin = &txqi->tin;
  100. - flow = fq_flow_classify(fq, tin, skb, fq_flow_get_default_func);
  101. + flow = fq_flow_classify(fq, tin, flow_idx, skb,
  102. + fq_flow_get_default_func);
  103. head = skb_peek_tail(&flow->queue);
  104. if (!head)
  105. goto unlock;