347-brcmfmac-Add-necessary-memory-barriers-for-SDIO.patch 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. From: Hante Meuleman <[email protected]>
  2. Date: Wed, 18 Mar 2015 13:25:22 +0100
  3. Subject: [PATCH] brcmfmac: Add necessary memory barriers for SDIO.
  4. SDIO uses a thread to handle all communication with the device,
  5. for this data is exchanged between threads. This data needs proper
  6. memory barriers to make sure that data "exchange" is going correct.
  7. Reviewed-by: Arend Van Spriel <[email protected]>
  8. Reviewed-by: Franky (Zhenhui) Lin <[email protected]>
  9. Reviewed-by: Pieter-Paul Giesberts <[email protected]>
  10. Reviewed-by: Daniel (Deognyoun) Kim <[email protected]>
  11. Signed-off-by: Hante Meuleman <[email protected]>
  12. Signed-off-by: Arend van Spriel <[email protected]>
  13. Signed-off-by: Kalle Valo <[email protected]>
  14. ---
  15. --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
  16. +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
  17. @@ -507,8 +507,8 @@ struct brcmf_sdio {
  18. struct workqueue_struct *brcmf_wq;
  19. struct work_struct datawork;
  20. - atomic_t dpc_tskcnt;
  21. - atomic_t dpc_running;
  22. + bool dpc_triggered;
  23. + bool dpc_running;
  24. bool txoff; /* Transmit flow-controlled */
  25. struct brcmf_sdio_count sdcnt;
  26. @@ -2713,6 +2713,7 @@ static void brcmf_sdio_dpc(struct brcmf_
  27. err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf,
  28. bus->ctrl_frame_len);
  29. bus->ctrl_frame_err = err;
  30. + wmb();
  31. bus->ctrl_frame_stat = false;
  32. }
  33. sdio_release_host(bus->sdiodev->func[1]);
  34. @@ -2734,6 +2735,7 @@ static void brcmf_sdio_dpc(struct brcmf_
  35. sdio_claim_host(bus->sdiodev->func[1]);
  36. if (bus->ctrl_frame_stat) {
  37. bus->ctrl_frame_err = -ENODEV;
  38. + wmb();
  39. bus->ctrl_frame_stat = false;
  40. brcmf_sdio_wait_event_wakeup(bus);
  41. }
  42. @@ -2744,7 +2746,7 @@ static void brcmf_sdio_dpc(struct brcmf_
  43. (!atomic_read(&bus->fcstate) &&
  44. brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
  45. data_ok(bus))) {
  46. - atomic_inc(&bus->dpc_tskcnt);
  47. + bus->dpc_triggered = true;
  48. }
  49. }
  50. @@ -2940,6 +2942,7 @@ brcmf_sdio_bus_txctl(struct device *dev,
  51. /* Send from dpc */
  52. bus->ctrl_frame_buf = msg;
  53. bus->ctrl_frame_len = msglen;
  54. + wmb();
  55. bus->ctrl_frame_stat = true;
  56. brcmf_sdio_trigger_dpc(bus);
  57. @@ -2958,6 +2961,7 @@ brcmf_sdio_bus_txctl(struct device *dev,
  58. if (!ret) {
  59. brcmf_dbg(SDIO, "ctrl_frame complete, err=%d\n",
  60. bus->ctrl_frame_err);
  61. + rmb();
  62. ret = bus->ctrl_frame_err;
  63. }
  64. @@ -3526,8 +3530,8 @@ done:
  65. void brcmf_sdio_trigger_dpc(struct brcmf_sdio *bus)
  66. {
  67. - if (atomic_read(&bus->dpc_tskcnt) == 0) {
  68. - atomic_inc(&bus->dpc_tskcnt);
  69. + if (!bus->dpc_triggered) {
  70. + bus->dpc_triggered = true;
  71. queue_work(bus->brcmf_wq, &bus->datawork);
  72. }
  73. }
  74. @@ -3558,7 +3562,7 @@ void brcmf_sdio_isr(struct brcmf_sdio *b
  75. if (!bus->intr)
  76. brcmf_err("isr w/o interrupt configured!\n");
  77. - atomic_inc(&bus->dpc_tskcnt);
  78. + bus->dpc_triggered = true;
  79. queue_work(bus->brcmf_wq, &bus->datawork);
  80. }
  81. @@ -3578,7 +3582,7 @@ static void brcmf_sdio_bus_watchdog(stru
  82. if (!bus->intr ||
  83. (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) {
  84. - if (atomic_read(&bus->dpc_tskcnt) == 0) {
  85. + if (!bus->dpc_triggered) {
  86. u8 devpend;
  87. sdio_claim_host(bus->sdiodev->func[1]);
  88. @@ -3596,7 +3600,7 @@ static void brcmf_sdio_bus_watchdog(stru
  89. bus->sdcnt.pollcnt++;
  90. atomic_set(&bus->ipend, 1);
  91. - atomic_inc(&bus->dpc_tskcnt);
  92. + bus->dpc_triggered = true;
  93. queue_work(bus->brcmf_wq, &bus->datawork);
  94. }
  95. }
  96. @@ -3623,17 +3627,21 @@ static void brcmf_sdio_bus_watchdog(stru
  97. #endif /* DEBUG */
  98. /* On idle timeout clear activity flag and/or turn off clock */
  99. - if ((atomic_read(&bus->dpc_tskcnt) == 0) &&
  100. - (atomic_read(&bus->dpc_running) == 0) &&
  101. - (bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) {
  102. - bus->idlecount++;
  103. - if (bus->idlecount > bus->idletime) {
  104. - brcmf_dbg(SDIO, "idle\n");
  105. - sdio_claim_host(bus->sdiodev->func[1]);
  106. - brcmf_sdio_wd_timer(bus, 0);
  107. + if (!bus->dpc_triggered) {
  108. + rmb();
  109. + if ((!bus->dpc_running) && (bus->idletime > 0) &&
  110. + (bus->clkstate == CLK_AVAIL)) {
  111. + bus->idlecount++;
  112. + if (bus->idlecount > bus->idletime) {
  113. + brcmf_dbg(SDIO, "idle\n");
  114. + sdio_claim_host(bus->sdiodev->func[1]);
  115. + brcmf_sdio_wd_timer(bus, 0);
  116. + bus->idlecount = 0;
  117. + brcmf_sdio_bus_sleep(bus, true, false);
  118. + sdio_release_host(bus->sdiodev->func[1]);
  119. + }
  120. + } else {
  121. bus->idlecount = 0;
  122. - brcmf_sdio_bus_sleep(bus, true, false);
  123. - sdio_release_host(bus->sdiodev->func[1]);
  124. }
  125. } else {
  126. bus->idlecount = 0;
  127. @@ -3645,13 +3653,14 @@ static void brcmf_sdio_dataworker(struct
  128. struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio,
  129. datawork);
  130. - while (atomic_read(&bus->dpc_tskcnt)) {
  131. - atomic_set(&bus->dpc_running, 1);
  132. - atomic_set(&bus->dpc_tskcnt, 0);
  133. + bus->dpc_running = true;
  134. + wmb();
  135. + while (ACCESS_ONCE(bus->dpc_triggered)) {
  136. + bus->dpc_triggered = false;
  137. brcmf_sdio_dpc(bus);
  138. bus->idlecount = 0;
  139. - atomic_set(&bus->dpc_running, 0);
  140. }
  141. + bus->dpc_running = false;
  142. if (brcmf_sdiod_freezing(bus->sdiodev)) {
  143. brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DOWN);
  144. brcmf_sdiod_try_freeze(bus->sdiodev);
  145. @@ -4144,8 +4153,8 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
  146. bus->watchdog_tsk = NULL;
  147. }
  148. /* Initialize DPC thread */
  149. - atomic_set(&bus->dpc_tskcnt, 0);
  150. - atomic_set(&bus->dpc_running, 0);
  151. + bus->dpc_triggered = false;
  152. + bus->dpc_running = false;
  153. /* Assign bus interface call back */
  154. bus->sdiodev->bus_if->dev = bus->sdiodev->dev;