337-brcmfmac-Fix-possible-race-condition.patch 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. From: Hante Meuleman <[email protected]>
  2. Date: Fri, 6 Mar 2015 18:40:40 +0100
  3. Subject: [PATCH] brcmfmac: Fix possible race-condition.
  4. SDIO is using a "shared" variable to handoff ctl frames to DPC
  5. and to see when they are done. In a timeout situation this can
  6. lead to erroneous situation where DPC started to handle the ctl
  7. frame while the timeout expired. This patch will fix this by
  8. adding locking around the shared variable.
  9. Reviewed-by: Arend Van Spriel <[email protected]>
  10. Reviewed-by: Franky (Zhenhui) Lin <[email protected]>
  11. Reviewed-by: Pieter-Paul Giesberts <[email protected]>
  12. Reviewed-by: Daniel (Deognyoun) Kim <[email protected]>
  13. Signed-off-by: Hante Meuleman <[email protected]>
  14. Signed-off-by: Arend van Spriel <[email protected]>
  15. Signed-off-by: Kalle Valo <[email protected]>
  16. ---
  17. --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
  18. +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
  19. @@ -2700,11 +2700,13 @@ static void brcmf_sdio_dpc(struct brcmf_
  20. if (bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL) &&
  21. data_ok(bus)) {
  22. sdio_claim_host(bus->sdiodev->func[1]);
  23. - err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf,
  24. - bus->ctrl_frame_len);
  25. + if (bus->ctrl_frame_stat) {
  26. + err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf,
  27. + bus->ctrl_frame_len);
  28. + bus->ctrl_frame_err = err;
  29. + bus->ctrl_frame_stat = false;
  30. + }
  31. sdio_release_host(bus->sdiodev->func[1]);
  32. - bus->ctrl_frame_err = err;
  33. - bus->ctrl_frame_stat = false;
  34. brcmf_sdio_wait_event_wakeup(bus);
  35. }
  36. /* Send queued frames (limit 1 if rx may still be pending) */
  37. @@ -2720,9 +2722,13 @@ static void brcmf_sdio_dpc(struct brcmf_
  38. brcmf_err("failed backplane access over SDIO, halting operation\n");
  39. atomic_set(&bus->intstatus, 0);
  40. if (bus->ctrl_frame_stat) {
  41. - bus->ctrl_frame_err = -ENODEV;
  42. - bus->ctrl_frame_stat = false;
  43. - brcmf_sdio_wait_event_wakeup(bus);
  44. + sdio_claim_host(bus->sdiodev->func[1]);
  45. + if (bus->ctrl_frame_stat) {
  46. + bus->ctrl_frame_err = -ENODEV;
  47. + bus->ctrl_frame_stat = false;
  48. + brcmf_sdio_wait_event_wakeup(bus);
  49. + }
  50. + sdio_release_host(bus->sdiodev->func[1]);
  51. }
  52. } else if (atomic_read(&bus->intstatus) ||
  53. atomic_read(&bus->ipend) > 0 ||
  54. @@ -2930,15 +2936,20 @@ brcmf_sdio_bus_txctl(struct device *dev,
  55. brcmf_sdio_trigger_dpc(bus);
  56. wait_event_interruptible_timeout(bus->ctrl_wait, !bus->ctrl_frame_stat,
  57. msecs_to_jiffies(CTL_DONE_TIMEOUT));
  58. -
  59. - if (!bus->ctrl_frame_stat) {
  60. + ret = 0;
  61. + if (bus->ctrl_frame_stat) {
  62. + sdio_claim_host(bus->sdiodev->func[1]);
  63. + if (bus->ctrl_frame_stat) {
  64. + brcmf_dbg(SDIO, "ctrl_frame timeout\n");
  65. + bus->ctrl_frame_stat = false;
  66. + ret = -ETIMEDOUT;
  67. + }
  68. + sdio_release_host(bus->sdiodev->func[1]);
  69. + }
  70. + if (!ret) {
  71. brcmf_dbg(SDIO, "ctrl_frame complete, err=%d\n",
  72. bus->ctrl_frame_err);
  73. ret = bus->ctrl_frame_err;
  74. - } else {
  75. - brcmf_dbg(SDIO, "ctrl_frame timeout\n");
  76. - bus->ctrl_frame_stat = false;
  77. - ret = -ETIMEDOUT;
  78. }
  79. if (ret)