317-ath9k-Check-for-active-GO-in-mgd_prepare_tx.patch 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. From: Sujith Manoharan <[email protected]>
  2. Date: Fri, 17 Oct 2014 07:40:22 +0530
  3. Subject: [PATCH] ath9k: Check for active GO in mgd_prepare_tx()
  4. If a GO interface is active when we receive a
  5. mgd_prepare_tx() call, then we need to send
  6. out a new NoA before switching to a new context.
  7. Signed-off-by: Sujith Manoharan <[email protected]>
  8. ---
  9. --- a/drivers/net/wireless/ath/ath9k/ath9k.h
  10. +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
  11. @@ -385,6 +385,7 @@ struct ath_chanctx_sched {
  12. bool wait_switch;
  13. bool force_noa_update;
  14. bool extend_absence;
  15. + bool mgd_prepare_tx;
  16. enum ath_chanctx_state state;
  17. u8 beacon_miss;
  18. @@ -977,6 +978,7 @@ struct ath_softc {
  19. struct ath_chanctx_sched sched;
  20. struct ath_offchannel offchannel;
  21. struct ath_chanctx *next_chan;
  22. + struct completion go_beacon;
  23. #endif
  24. unsigned long driver_data;
  25. --- a/drivers/net/wireless/ath/ath9k/channel.c
  26. +++ b/drivers/net/wireless/ath/ath9k/channel.c
  27. @@ -421,6 +421,9 @@ void ath_chanctx_event(struct ath_softc
  28. "Move chanctx state from WAIT_FOR_TIMER to WAIT_FOR_BEACON\n");
  29. }
  30. + if (sc->sched.mgd_prepare_tx)
  31. + sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
  32. +
  33. /*
  34. * When a context becomes inactive, for example,
  35. * disassociation of a station context, the NoA
  36. @@ -547,6 +550,15 @@ void ath_chanctx_event(struct ath_softc
  37. }
  38. sc->sched.beacon_pending = false;
  39. +
  40. + if (sc->sched.mgd_prepare_tx) {
  41. + sc->sched.mgd_prepare_tx = false;
  42. + complete(&sc->go_beacon);
  43. + ath_dbg(common, CHAN_CTX,
  44. + "Beacon sent, complete go_beacon\n");
  45. + break;
  46. + }
  47. +
  48. if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON)
  49. break;
  50. @@ -1263,6 +1275,8 @@ void ath9k_init_channel_context(struct a
  51. (unsigned long)sc);
  52. setup_timer(&sc->sched.timer, ath_chanctx_timer,
  53. (unsigned long)sc);
  54. +
  55. + init_completion(&sc->go_beacon);
  56. }
  57. void ath9k_deinit_channel_context(struct ath_softc *sc)
  58. --- a/drivers/net/wireless/ath/ath9k/main.c
  59. +++ b/drivers/net/wireless/ath/ath9k/main.c
  60. @@ -2474,7 +2474,11 @@ static void ath9k_mgd_prepare_tx(struct
  61. struct ath_softc *sc = hw->priv;
  62. struct ath_common *common = ath9k_hw_common(sc->sc_ah);
  63. struct ath_vif *avp = (struct ath_vif *) vif->drv_priv;
  64. + struct ath_beacon_config *cur_conf;
  65. + struct ath_chanctx *go_ctx;
  66. + unsigned long timeout;
  67. bool changed = false;
  68. + u32 beacon_int;
  69. if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
  70. return;
  71. @@ -2485,19 +2489,46 @@ static void ath9k_mgd_prepare_tx(struct
  72. mutex_lock(&sc->mutex);
  73. spin_lock_bh(&sc->chan_lock);
  74. - if (sc->next_chan || (sc->cur_chan != avp->chanctx)) {
  75. - sc->next_chan = avp->chanctx;
  76. + if (sc->next_chan || (sc->cur_chan != avp->chanctx))
  77. changed = true;
  78. + spin_unlock_bh(&sc->chan_lock);
  79. +
  80. + if (!changed)
  81. + goto out;
  82. +
  83. + go_ctx = ath_is_go_chanctx_present(sc);
  84. +
  85. + if (go_ctx) {
  86. + /*
  87. + * Wait till the GO interface gets a chance
  88. + * to send out an NoA.
  89. + */
  90. + spin_lock_bh(&sc->chan_lock);
  91. + sc->sched.mgd_prepare_tx = true;
  92. + cur_conf = &go_ctx->beacon;
  93. + beacon_int = TU_TO_USEC(cur_conf->beacon_interval);
  94. + spin_unlock_bh(&sc->chan_lock);
  95. +
  96. + timeout = usecs_to_jiffies(beacon_int);
  97. + init_completion(&sc->go_beacon);
  98. +
  99. + if (wait_for_completion_timeout(&sc->go_beacon,
  100. + timeout) == 0)
  101. + ath_dbg(common, CHAN_CTX,
  102. + "Failed to send new NoA\n");
  103. }
  104. +
  105. ath_dbg(common, CHAN_CTX,
  106. - "%s: Set chanctx state to FORCE_ACTIVE, changed: %d\n",
  107. - __func__, changed);
  108. + "%s: Set chanctx state to FORCE_ACTIVE for vif: %pM\n",
  109. + __func__, vif->addr);
  110. +
  111. + spin_lock_bh(&sc->chan_lock);
  112. + sc->next_chan = avp->chanctx;
  113. sc->sched.state = ATH_CHANCTX_STATE_FORCE_ACTIVE;
  114. spin_unlock_bh(&sc->chan_lock);
  115. - if (changed)
  116. - ath_chanctx_set_next(sc, true);
  117. -
  118. + ath_chanctx_set_next(sc, true);
  119. +out:
  120. mutex_unlock(&sc->mutex);
  121. }