341-v5.2-0001-brcmfmac-fix-WARNING-during-USB-disconnect-in-case-o.patch 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. From c80d26e81ef1802f30364b4ad1955c1443a592b9 Mon Sep 17 00:00:00 2001
  2. From: Piotr Figiel <p.figiel@camlintechnologies.com>
  3. Date: Mon, 4 Mar 2019 15:42:49 +0000
  4. Subject: [PATCH] brcmfmac: fix WARNING during USB disconnect in case of
  5. unempty psq
  6. brcmu_pkt_buf_free_skb emits WARNING when attempting to free a sk_buff
  7. which is part of any queue. After USB disconnect this may have happened
  8. when brcmf_fws_hanger_cleanup() is called as per-interface psq was never
  9. cleaned when removing the interface.
  10. Change brcmf_fws_macdesc_cleanup() in a way that it removes the
  11. corresponding packets from hanger table (to avoid double-free when
  12. brcmf_fws_hanger_cleanup() is called) and add a call to clean-up the
  13. interface specific packet queue.
  14. Below is a WARNING during USB disconnect with Raspberry Pi WiFi dongle
  15. running in AP mode. This was reproducible when the interface was
  16. transmitting during the disconnect and is fixed with this commit.
  17. ------------[ cut here ]------------
  18. WARNING: CPU: 0 PID: 1171 at drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c:49 brcmu_pkt_buf_free_skb+0x3c/0x40
  19. Modules linked in: nf_log_ipv4 nf_log_common xt_LOG xt_limit iptable_mangle xt_connmark xt_tcpudp xt_conntrack nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 iptable_filter ip_tables x_tables usb_f_mass_storage usb_f_rndis u_ether cdc_acm smsc95xx usbnet ci_hdrc_imx ci_hdrc ulpi usbmisc_imx 8250_exar 8250_pci 8250 8250_base libcomposite configfs udc_core
  20. CPU: 0 PID: 1171 Comm: kworker/0:0 Not tainted 4.19.23-00075-gde33ed8 #99
  21. Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
  22. Workqueue: usb_hub_wq hub_event
  23. [<8010ff84>] (unwind_backtrace) from [<8010bb64>] (show_stack+0x10/0x14)
  24. [<8010bb64>] (show_stack) from [<80840278>] (dump_stack+0x88/0x9c)
  25. [<80840278>] (dump_stack) from [<8011f5ec>] (__warn+0xfc/0x114)
  26. [<8011f5ec>] (__warn) from [<8011f71c>] (warn_slowpath_null+0x40/0x48)
  27. [<8011f71c>] (warn_slowpath_null) from [<805a476c>] (brcmu_pkt_buf_free_skb+0x3c/0x40)
  28. [<805a476c>] (brcmu_pkt_buf_free_skb) from [<805bb6c4>] (brcmf_fws_cleanup+0x1e4/0x22c)
  29. [<805bb6c4>] (brcmf_fws_cleanup) from [<805bc854>] (brcmf_fws_del_interface+0x58/0x68)
  30. [<805bc854>] (brcmf_fws_del_interface) from [<805b66ac>] (brcmf_remove_interface+0x40/0x150)
  31. [<805b66ac>] (brcmf_remove_interface) from [<805b6870>] (brcmf_detach+0x6c/0xb0)
  32. [<805b6870>] (brcmf_detach) from [<805bdbb8>] (brcmf_usb_disconnect+0x30/0x4c)
  33. [<805bdbb8>] (brcmf_usb_disconnect) from [<805e5d64>] (usb_unbind_interface+0x5c/0x1e0)
  34. [<805e5d64>] (usb_unbind_interface) from [<804aab10>] (device_release_driver_internal+0x154/0x1ec)
  35. [<804aab10>] (device_release_driver_internal) from [<804a97f4>] (bus_remove_device+0xcc/0xf8)
  36. [<804a97f4>] (bus_remove_device) from [<804a6fc0>] (device_del+0x118/0x308)
  37. [<804a6fc0>] (device_del) from [<805e488c>] (usb_disable_device+0xa0/0x1c8)
  38. [<805e488c>] (usb_disable_device) from [<805dcf98>] (usb_disconnect+0x70/0x1d8)
  39. [<805dcf98>] (usb_disconnect) from [<805ddd84>] (hub_event+0x464/0xf50)
  40. [<805ddd84>] (hub_event) from [<80135a70>] (process_one_work+0x138/0x3f8)
  41. [<80135a70>] (process_one_work) from [<80135d5c>] (worker_thread+0x2c/0x554)
  42. [<80135d5c>] (worker_thread) from [<8013b1a0>] (kthread+0x124/0x154)
  43. [<8013b1a0>] (kthread) from [<801010e8>] (ret_from_fork+0x14/0x2c)
  44. Exception stack(0xecf8dfb0 to 0xecf8dff8)
  45. dfa0: 00000000 00000000 00000000 00000000
  46. dfc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  47. dfe0: 00000000 00000000 00000000 00000000 00000013 00000000
  48. ---[ end trace 38d234018e9e2a90 ]---
  49. ------------[ cut here ]------------
  50. Signed-off-by: Piotr Figiel <p.figiel@camlintechnologies.com>
  51. Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
  52. ---
  53. .../broadcom/brcm80211/brcmfmac/fwsignal.c | 42 +++++++++++--------
  54. 1 file changed, 24 insertions(+), 18 deletions(-)
  55. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
  56. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
  57. @@ -579,24 +579,6 @@ static bool brcmf_fws_ifidx_match(struct
  58. return ifidx == *(int *)arg;
  59. }
  60. -static void brcmf_fws_psq_flush(struct brcmf_fws_info *fws, struct pktq *q,
  61. - int ifidx)
  62. -{
  63. - bool (*matchfn)(struct sk_buff *, void *) = NULL;
  64. - struct sk_buff *skb;
  65. - int prec;
  66. -
  67. - if (ifidx != -1)
  68. - matchfn = brcmf_fws_ifidx_match;
  69. - for (prec = 0; prec < q->num_prec; prec++) {
  70. - skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx);
  71. - while (skb) {
  72. - brcmu_pkt_buf_free_skb(skb);
  73. - skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx);
  74. - }
  75. - }
  76. -}
  77. -
  78. static void brcmf_fws_hanger_init(struct brcmf_fws_hanger *hanger)
  79. {
  80. int i;
  81. @@ -668,6 +650,28 @@ static inline int brcmf_fws_hanger_poppk
  82. return 0;
  83. }
  84. +static void brcmf_fws_psq_flush(struct brcmf_fws_info *fws, struct pktq *q,
  85. + int ifidx)
  86. +{
  87. + bool (*matchfn)(struct sk_buff *, void *) = NULL;
  88. + struct sk_buff *skb;
  89. + int prec;
  90. + u32 hslot;
  91. +
  92. + if (ifidx != -1)
  93. + matchfn = brcmf_fws_ifidx_match;
  94. + for (prec = 0; prec < q->num_prec; prec++) {
  95. + skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx);
  96. + while (skb) {
  97. + hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
  98. + brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
  99. + true);
  100. + brcmu_pkt_buf_free_skb(skb);
  101. + skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx);
  102. + }
  103. + }
  104. +}
  105. +
  106. static int brcmf_fws_hanger_mark_suppressed(struct brcmf_fws_hanger *h,
  107. u32 slot_id)
  108. {
  109. @@ -2174,6 +2178,8 @@ void brcmf_fws_del_interface(struct brcm
  110. brcmf_fws_lock(fws);
  111. ifp->fws_desc = NULL;
  112. brcmf_dbg(TRACE, "deleting %s\n", entry->name);
  113. + brcmf_fws_macdesc_cleanup(fws, &fws->desc.iface[ifp->ifidx],
  114. + ifp->ifidx);
  115. brcmf_fws_macdesc_deinit(entry);
  116. brcmf_fws_cleanup(fws, ifp->ifidx);
  117. brcmf_fws_unlock(fws);