0003-wifi.patch 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299
  1. From 582e2708b267722ff0b91a71307f321e2c840159 Mon Sep 17 00:00:00 2001
  2. From: Tsuchiya Yuto <kitakar@gmail.com>
  3. Date: Thu, 24 Sep 2020 18:02:06 +0900
  4. Subject: [PATCH] mwifiex: pcie: skip cancel_work_sync() on reset failure path
  5. If a reset is performed, but even the reset fails for some reasons (e.g.,
  6. on Surface devices, the fw reset requires another quirks),
  7. cancel_work_sync() hangs in mwifiex_cleanup_pcie().
  8. # reset performed after firmware went into bad state
  9. kernel: mwifiex_pcie 0000:01:00.0: WLAN FW already running! Skip FW dnld
  10. kernel: mwifiex_pcie 0000:01:00.0: WLAN FW is active
  11. # but even the reset failed
  12. kernel: mwifiex_pcie 0000:01:00.0: mwifiex_cmd_timeout_func: Timeout cmd id = 0xfa, act = 0xa000
  13. kernel: mwifiex_pcie 0000:01:00.0: num_data_h2c_failure = 0
  14. kernel: mwifiex_pcie 0000:01:00.0: num_cmd_h2c_failure = 0
  15. kernel: mwifiex_pcie 0000:01:00.0: is_cmd_timedout = 1
  16. kernel: mwifiex_pcie 0000:01:00.0: num_tx_timeout = 0
  17. kernel: mwifiex_pcie 0000:01:00.0: last_cmd_index = 2
  18. kernel: mwifiex_pcie 0000:01:00.0: last_cmd_id: 16 00 a4 00 fa 00 a4 00 7f 00
  19. kernel: mwifiex_pcie 0000:01:00.0: last_cmd_act: 00 00 00 00 00 a0 00 00 00 00
  20. kernel: mwifiex_pcie 0000:01:00.0: last_cmd_resp_index = 0
  21. kernel: mwifiex_pcie 0000:01:00.0: last_cmd_resp_id: 16 80 7f 80 16 80 a4 80 7f 80
  22. kernel: mwifiex_pcie 0000:01:00.0: last_event_index = 1
  23. kernel: mwifiex_pcie 0000:01:00.0: last_event: 58 00 58 00 58 00 58 00 58 00
  24. kernel: mwifiex_pcie 0000:01:00.0: data_sent=0 cmd_sent=1
  25. kernel: mwifiex_pcie 0000:01:00.0: ps_mode=0 ps_state=0
  26. kernel: mwifiex_pcie 0000:01:00.0: info: _mwifiex_fw_dpc: unregister device
  27. # mwifiex_pcie_work hanged
  28. kernel: INFO: task kworker/0:0:24857 blocked for more than 122 seconds.
  29. kernel: Tainted: G W OE 5.3.11-arch1-1 #1
  30. kernel: "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
  31. kernel: kworker/0:0 D 0 24857 2 0x80004000
  32. kernel: Workqueue: events mwifiex_pcie_work [mwifiex_pcie]
  33. kernel: Call Trace:
  34. kernel: ? __schedule+0x27f/0x6d0
  35. kernel: schedule+0x43/0xd0
  36. kernel: schedule_timeout+0x299/0x3d0
  37. kernel: ? __switch_to_asm+0x40/0x70
  38. kernel: wait_for_common+0xeb/0x190
  39. kernel: ? wake_up_q+0x60/0x60
  40. kernel: __flush_work+0x130/0x1e0
  41. kernel: ? flush_workqueue_prep_pwqs+0x130/0x130
  42. kernel: __cancel_work_timer+0x123/0x1b0
  43. kernel: mwifiex_cleanup_pcie+0x28/0xd0 [mwifiex_pcie]
  44. kernel: mwifiex_free_adapter+0x24/0xe0 [mwifiex]
  45. kernel: _mwifiex_fw_dpc+0x28d/0x520 [mwifiex]
  46. kernel: mwifiex_reinit_sw+0x15d/0x2c0 [mwifiex]
  47. kernel: mwifiex_pcie_reset_done+0x50/0x80 [mwifiex_pcie]
  48. kernel: pci_try_reset_function+0x38/0x70
  49. kernel: process_one_work+0x1d1/0x3a0
  50. kernel: worker_thread+0x4a/0x3d0
  51. kernel: kthread+0xfb/0x130
  52. kernel: ? process_one_work+0x3a0/0x3a0
  53. kernel: ? kthread_park+0x80/0x80
  54. kernel: ret_from_fork+0x35/0x40
  55. This is a deadlock caused by calling cancel_work_sync() in
  56. mwifiex_cleanup_pcie():
  57. - Device resets are done via mwifiex_pcie_card_reset()
  58. - which schedules card->work to call mwifiex_pcie_card_reset_work()
  59. - which calls pci_try_reset_function().
  60. - This leads to mwifiex_pcie_reset_done() be called on the same workqueue,
  61. which in turn calls
  62. - mwifiex_reinit_sw() and that calls
  63. - _mwifiex_fw_dpc().
  64. The problem is now that _mwifiex_fw_dpc() calls mwifiex_free_adapter()
  65. in case firmware initialization fails. That ends up calling
  66. mwifiex_cleanup_pcie().
  67. Note that all those calls are still running on the workqueue. So when
  68. mwifiex_cleanup_pcie() now calls cancel_work_sync(), it's really waiting
  69. on itself to complete, causing a deadlock.
  70. This commit fixes the deadlock by skipping cancel_work_sync() on a reset
  71. failure path.
  72. After this commit, when reset fails, the following output is
  73. expected to be shown:
  74. kernel: mwifiex_pcie 0000:03:00.0: info: _mwifiex_fw_dpc: unregister device
  75. kernel: mwifiex: Failed to bring up adapter: -5
  76. kernel: mwifiex_pcie 0000:03:00.0: reinit failed: -5
  77. To reproduce this issue, for example, try putting the root port of wifi
  78. into D3 (replace "00:1d.3" with your setup).
  79. # put into D3 (root port)
  80. sudo setpci -v -s 00:1d.3 CAP_PM+4.b=0b
  81. Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
  82. Patchset: wifi
  83. ---
  84. drivers/net/wireless/marvell/mwifiex/pcie.c | 18 +++++++++++++++++-
  85. drivers/net/wireless/marvell/mwifiex/pcie.h | 2 ++
  86. 2 files changed, 19 insertions(+), 1 deletion(-)
  87. diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
  88. index fc1706d0647d..58c9623c3a91 100644
  89. --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
  90. +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
  91. @@ -377,6 +377,8 @@ static void mwifiex_pcie_reset_prepare(struct pci_dev *pdev)
  92. clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags);
  93. clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags);
  94. mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
  95. +
  96. + card->pci_reset_ongoing = true;
  97. }
  98. /*
  99. @@ -405,6 +407,8 @@ static void mwifiex_pcie_reset_done(struct pci_dev *pdev)
  100. dev_err(&pdev->dev, "reinit failed: %d\n", ret);
  101. else
  102. mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
  103. +
  104. + card->pci_reset_ongoing = false;
  105. }
  106. static const struct pci_error_handlers mwifiex_pcie_err_handler = {
  107. @@ -2995,7 +2999,19 @@ static void mwifiex_cleanup_pcie(struct mwifiex_adapter *adapter)
  108. int ret;
  109. u32 fw_status;
  110. - cancel_work_sync(&card->work);
  111. + /* Perform the cancel_work_sync() only when we're not resetting
  112. + * the card. It's because that function never returns if we're
  113. + * in reset path. If we're here when resetting the card, it means
  114. + * that we failed to reset the card (reset failure path).
  115. + */
  116. + if (!card->pci_reset_ongoing) {
  117. + mwifiex_dbg(adapter, MSG, "performing cancel_work_sync()...\n");
  118. + cancel_work_sync(&card->work);
  119. + mwifiex_dbg(adapter, MSG, "cancel_work_sync() done\n");
  120. + } else {
  121. + mwifiex_dbg(adapter, MSG,
  122. + "skipped cancel_work_sync() because we're in card reset failure path\n");
  123. + }
  124. ret = mwifiex_read_reg(adapter, reg->fw_status, &fw_status);
  125. if (fw_status == FIRMWARE_READY_PCIE) {
  126. diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h
  127. index f7ce9b6db6b4..72d0c01ff359 100644
  128. --- a/drivers/net/wireless/marvell/mwifiex/pcie.h
  129. +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h
  130. @@ -391,6 +391,8 @@ struct pcie_service_card {
  131. struct mwifiex_msix_context share_irq_ctx;
  132. struct work_struct work;
  133. unsigned long work_flags;
  134. +
  135. + bool pci_reset_ongoing;
  136. };
  137. static inline int
  138. --
  139. 2.30.1
  140. From ab13f94d3cde1dd9e1e86546ed6469f76018207b Mon Sep 17 00:00:00 2001
  141. From: Tsuchiya Yuto <kitakar@gmail.com>
  142. Date: Mon, 28 Sep 2020 17:46:49 +0900
  143. Subject: [PATCH] mwifiex: pcie: add DMI-based quirk impl for Surface devices
  144. This commit adds quirk implementation based on DMI matching with DMI
  145. table for Surface devices.
  146. This implementation can be used for quirks later.
  147. Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
  148. Patchset: wifi
  149. ---
  150. drivers/net/wireless/marvell/mwifiex/Makefile | 1 +
  151. drivers/net/wireless/marvell/mwifiex/pcie.c | 4 +
  152. drivers/net/wireless/marvell/mwifiex/pcie.h | 1 +
  153. .../wireless/marvell/mwifiex/pcie_quirks.c | 114 ++++++++++++++++++
  154. .../wireless/marvell/mwifiex/pcie_quirks.h | 11 ++
  155. 5 files changed, 131 insertions(+)
  156. create mode 100644 drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
  157. create mode 100644 drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
  158. diff --git a/drivers/net/wireless/marvell/mwifiex/Makefile b/drivers/net/wireless/marvell/mwifiex/Makefile
  159. index fdfd9bf15ed4..8a1e7c5b9c6e 100644
  160. --- a/drivers/net/wireless/marvell/mwifiex/Makefile
  161. +++ b/drivers/net/wireless/marvell/mwifiex/Makefile
  162. @@ -49,6 +49,7 @@ mwifiex_sdio-y += sdio.o
  163. obj-$(CONFIG_MWIFIEX_SDIO) += mwifiex_sdio.o
  164. mwifiex_pcie-y += pcie.o
  165. +mwifiex_pcie-y += pcie_quirks.o
  166. obj-$(CONFIG_MWIFIEX_PCIE) += mwifiex_pcie.o
  167. mwifiex_usb-y += usb.o
  168. diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
  169. index 58c9623c3a91..faf0c82e0b2c 100644
  170. --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
  171. +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
  172. @@ -27,6 +27,7 @@
  173. #include "wmm.h"
  174. #include "11n.h"
  175. #include "pcie.h"
  176. +#include "pcie_quirks.h"
  177. #define PCIE_VERSION "1.0"
  178. #define DRV_NAME "Marvell mwifiex PCIe"
  179. @@ -261,6 +262,9 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
  180. return ret;
  181. }
  182. + /* check quirks */
  183. + mwifiex_initialize_quirks(card);
  184. +
  185. if (mwifiex_add_card(card, &card->fw_done, &pcie_ops,
  186. MWIFIEX_PCIE, &pdev->dev)) {
  187. pr_err("%s failed\n", __func__);
  188. diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h
  189. index 72d0c01ff359..f7e968306a0c 100644
  190. --- a/drivers/net/wireless/marvell/mwifiex/pcie.h
  191. +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h
  192. @@ -393,6 +393,7 @@ struct pcie_service_card {
  193. unsigned long work_flags;
  194. bool pci_reset_ongoing;
  195. + unsigned long quirks;
  196. };
  197. static inline int
  198. diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
  199. new file mode 100644
  200. index 000000000000..929aee2b0a60
  201. --- /dev/null
  202. +++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
  203. @@ -0,0 +1,114 @@
  204. +// SPDX-License-Identifier: GPL-2.0
  205. +/*
  206. + * File for PCIe quirks.
  207. + */
  208. +
  209. +/* The low-level PCI operations will be performed in this file. Therefore,
  210. + * let's use dev_*() instead of mwifiex_dbg() here to avoid troubles (e.g.
  211. + * to avoid using mwifiex_adapter struct before init or wifi is powered
  212. + * down, or causes NULL ptr deref).
  213. + */
  214. +
  215. +#include <linux/dmi.h>
  216. +
  217. +#include "pcie_quirks.h"
  218. +
  219. +/* quirk table based on DMI matching */
  220. +static const struct dmi_system_id mwifiex_quirk_table[] = {
  221. + {
  222. + .ident = "Surface Pro 4",
  223. + .matches = {
  224. + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  225. + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 4"),
  226. + },
  227. + .driver_data = 0,
  228. + },
  229. + {
  230. + .ident = "Surface Pro 5",
  231. + .matches = {
  232. + /* match for SKU here due to generic product name "Surface Pro" */
  233. + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  234. + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "Surface_Pro_1796"),
  235. + },
  236. + .driver_data = 0,
  237. + },
  238. + {
  239. + .ident = "Surface Pro 5 (LTE)",
  240. + .matches = {
  241. + /* match for SKU here due to generic product name "Surface Pro" */
  242. + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  243. + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "Surface_Pro_1807"),
  244. + },
  245. + .driver_data = 0,
  246. + },
  247. + {
  248. + .ident = "Surface Pro 6",
  249. + .matches = {
  250. + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  251. + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 6"),
  252. + },
  253. + .driver_data = 0,
  254. + },
  255. + {
  256. + .ident = "Surface Book 1",
  257. + .matches = {
  258. + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  259. + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Book"),
  260. + },
  261. + .driver_data = 0,
  262. + },
  263. + {
  264. + .ident = "Surface Book 2",
  265. + .matches = {
  266. + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  267. + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Book 2"),
  268. + },
  269. + .driver_data = 0,
  270. + },
  271. + {
  272. + .ident = "Surface Laptop 1",
  273. + .matches = {
  274. + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  275. + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Laptop"),
  276. + },
  277. + .driver_data = 0,
  278. + },
  279. + {
  280. + .ident = "Surface Laptop 2",
  281. + .matches = {
  282. + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  283. + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Laptop 2"),
  284. + },
  285. + .driver_data = 0,
  286. + },
  287. + {
  288. + .ident = "Surface 3",
  289. + .matches = {
  290. + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  291. + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface 3"),
  292. + },
  293. + .driver_data = 0,
  294. + },
  295. + {
  296. + .ident = "Surface Pro 3",
  297. + .matches = {
  298. + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  299. + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 3"),
  300. + },
  301. + .driver_data = 0,
  302. + },
  303. + {}
  304. +};
  305. +
  306. +void mwifiex_initialize_quirks(struct pcie_service_card *card)
  307. +{
  308. + struct pci_dev *pdev = card->dev;
  309. + const struct dmi_system_id *dmi_id;
  310. +
  311. + dmi_id = dmi_first_match(mwifiex_quirk_table);
  312. + if (dmi_id)
  313. + card->quirks = (uintptr_t)dmi_id->driver_data;
  314. +
  315. + if (!card->quirks)
  316. + dev_info(&pdev->dev, "no quirks enabled\n");
  317. +}
  318. diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
  319. new file mode 100644
  320. index 000000000000..5326ae7e5671
  321. --- /dev/null
  322. +++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
  323. @@ -0,0 +1,11 @@
  324. +/* SPDX-License-Identifier: GPL-2.0 */
  325. +/*
  326. + * Header file for PCIe quirks.
  327. + */
  328. +
  329. +#include "pcie.h"
  330. +
  331. +/* quirks */
  332. +// quirk flags can be added here
  333. +
  334. +void mwifiex_initialize_quirks(struct pcie_service_card *card);
  335. --
  336. 2.30.1
  337. From 90eedd60f6dfb6578f0f9c09520b6169adc87d74 Mon Sep 17 00:00:00 2001
  338. From: Tsuchiya Yuto <kitakar@gmail.com>
  339. Date: Tue, 29 Sep 2020 17:25:22 +0900
  340. Subject: [PATCH] mwifiex: pcie: add reset_d3cold quirk for Surface gen4+
  341. devices
  342. To reset mwifiex on Surface gen4+ (Pro 4 or later gen) devices, it
  343. seems that putting the wifi device into D3cold is required according
  344. to errata.inf file on Windows installation (Windows/INF/errata.inf).
  345. This patch adds a function that performs power-cycle (put into D3cold
  346. then D0) and call the function at the end of reset_prepare().
  347. Note: Need to also reset the parent device (bridge) of wifi on SB1;
  348. it might be because the bridge of wifi always reports it's in D3hot.
  349. When I tried to reset only the wifi device (not touching parent), it gave
  350. the following error and the reset failed:
  351. acpi device:4b: Cannot transition to power state D0 for parent in D3hot
  352. mwifiex_pcie 0000:03:00.0: can't change power state from D3cold to D0 (config space inaccessible)
  353. Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
  354. Patchset: wifi
  355. ---
  356. drivers/net/wireless/marvell/mwifiex/pcie.c | 7 ++
  357. .../wireless/marvell/mwifiex/pcie_quirks.c | 73 +++++++++++++++++--
  358. .../wireless/marvell/mwifiex/pcie_quirks.h | 3 +-
  359. 3 files changed, 74 insertions(+), 9 deletions(-)
  360. diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
  361. index faf0c82e0b2c..828957cd5449 100644
  362. --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
  363. +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
  364. @@ -380,6 +380,13 @@ static void mwifiex_pcie_reset_prepare(struct pci_dev *pdev)
  365. mwifiex_shutdown_sw(adapter);
  366. clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags);
  367. clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags);
  368. +
  369. + /* For Surface gen4+ devices, we need to put wifi into D3cold right
  370. + * before performing FLR
  371. + */
  372. + if (card->quirks & QUIRK_FW_RST_D3COLD)
  373. + mwifiex_pcie_reset_d3cold_quirk(pdev);
  374. +
  375. mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
  376. card->pci_reset_ongoing = true;
  377. diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
  378. index 929aee2b0a60..edc739c542fe 100644
  379. --- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
  380. +++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
  381. @@ -21,7 +21,7 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
  382. DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  383. DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 4"),
  384. },
  385. - .driver_data = 0,
  386. + .driver_data = (void *)QUIRK_FW_RST_D3COLD,
  387. },
  388. {
  389. .ident = "Surface Pro 5",
  390. @@ -30,7 +30,7 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
  391. DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  392. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "Surface_Pro_1796"),
  393. },
  394. - .driver_data = 0,
  395. + .driver_data = (void *)QUIRK_FW_RST_D3COLD,
  396. },
  397. {
  398. .ident = "Surface Pro 5 (LTE)",
  399. @@ -39,7 +39,7 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
  400. DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  401. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "Surface_Pro_1807"),
  402. },
  403. - .driver_data = 0,
  404. + .driver_data = (void *)QUIRK_FW_RST_D3COLD,
  405. },
  406. {
  407. .ident = "Surface Pro 6",
  408. @@ -47,7 +47,7 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
  409. DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  410. DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 6"),
  411. },
  412. - .driver_data = 0,
  413. + .driver_data = (void *)QUIRK_FW_RST_D3COLD,
  414. },
  415. {
  416. .ident = "Surface Book 1",
  417. @@ -55,7 +55,7 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
  418. DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  419. DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Book"),
  420. },
  421. - .driver_data = 0,
  422. + .driver_data = (void *)QUIRK_FW_RST_D3COLD,
  423. },
  424. {
  425. .ident = "Surface Book 2",
  426. @@ -63,7 +63,7 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
  427. DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  428. DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Book 2"),
  429. },
  430. - .driver_data = 0,
  431. + .driver_data = (void *)QUIRK_FW_RST_D3COLD,
  432. },
  433. {
  434. .ident = "Surface Laptop 1",
  435. @@ -71,7 +71,7 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
  436. DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  437. DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Laptop"),
  438. },
  439. - .driver_data = 0,
  440. + .driver_data = (void *)QUIRK_FW_RST_D3COLD,
  441. },
  442. {
  443. .ident = "Surface Laptop 2",
  444. @@ -79,7 +79,7 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
  445. DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  446. DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Laptop 2"),
  447. },
  448. - .driver_data = 0,
  449. + .driver_data = (void *)QUIRK_FW_RST_D3COLD,
  450. },
  451. {
  452. .ident = "Surface 3",
  453. @@ -111,4 +111,61 @@ void mwifiex_initialize_quirks(struct pcie_service_card *card)
  454. if (!card->quirks)
  455. dev_info(&pdev->dev, "no quirks enabled\n");
  456. + if (card->quirks & QUIRK_FW_RST_D3COLD)
  457. + dev_info(&pdev->dev, "quirk reset_d3cold enabled\n");
  458. +}
  459. +
  460. +static void mwifiex_pcie_set_power_d3cold(struct pci_dev *pdev)
  461. +{
  462. + dev_info(&pdev->dev, "putting into D3cold...\n");
  463. +
  464. + pci_save_state(pdev);
  465. + if (pci_is_enabled(pdev))
  466. + pci_disable_device(pdev);
  467. + pci_set_power_state(pdev, PCI_D3cold);
  468. +}
  469. +
  470. +static int mwifiex_pcie_set_power_d0(struct pci_dev *pdev)
  471. +{
  472. + int ret;
  473. +
  474. + dev_info(&pdev->dev, "putting into D0...\n");
  475. +
  476. + pci_set_power_state(pdev, PCI_D0);
  477. + ret = pci_enable_device(pdev);
  478. + if (ret) {
  479. + dev_err(&pdev->dev, "pci_enable_device failed\n");
  480. + return ret;
  481. + }
  482. + pci_restore_state(pdev);
  483. +
  484. + return 0;
  485. +}
  486. +
  487. +int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev)
  488. +{
  489. + struct pci_dev *parent_pdev = pci_upstream_bridge(pdev);
  490. + int ret;
  491. +
  492. + /* Power-cycle (put into D3cold then D0) */
  493. + dev_info(&pdev->dev, "Using reset_d3cold quirk to perform FW reset\n");
  494. +
  495. + /* We need to perform power-cycle also for bridge of wifi because
  496. + * on some devices (e.g. Surface Book 1), the OS for some reasons
  497. + * can't know the real power state of the bridge.
  498. + * When tried to power-cycle only wifi, the reset failed with the
  499. + * following dmesg log:
  500. + * "Cannot transition to power state D0 for parent in D3hot".
  501. + */
  502. + mwifiex_pcie_set_power_d3cold(pdev);
  503. + mwifiex_pcie_set_power_d3cold(parent_pdev);
  504. +
  505. + ret = mwifiex_pcie_set_power_d0(parent_pdev);
  506. + if (ret)
  507. + return ret;
  508. + ret = mwifiex_pcie_set_power_d0(pdev);
  509. + if (ret)
  510. + return ret;
  511. +
  512. + return 0;
  513. }
  514. diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
  515. index 5326ae7e5671..8b9dcb5070d8 100644
  516. --- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
  517. +++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
  518. @@ -6,6 +6,7 @@
  519. #include "pcie.h"
  520. /* quirks */
  521. -// quirk flags can be added here
  522. +#define QUIRK_FW_RST_D3COLD BIT(0)
  523. void mwifiex_initialize_quirks(struct pcie_service_card *card);
  524. +int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev);
  525. --
  526. 2.30.1
  527. From d4c3664053583b97dbcdeea4dc37da854215f471 Mon Sep 17 00:00:00 2001
  528. From: Tsuchiya Yuto <kitakar@gmail.com>
  529. Date: Tue, 29 Sep 2020 17:32:22 +0900
  530. Subject: [PATCH] mwifiex: pcie: add reset_wsid quirk for Surface 3
  531. This commit adds reset_wsid quirk and uses this quirk for Surface 3 on
  532. card reset.
  533. To reset mwifiex on Surface 3, it seems that calling the _DSM method
  534. exists in \_SB.WSID [1] device is required.
  535. On Surface 3, calling the _DSM method removes/re-probes the card by
  536. itself. So, need to place the reset function before performing FLR and
  537. skip performing any other reset-related works.
  538. Note that Surface Pro 3 also has the WSID device [2], but it seems to need
  539. more work. This commit only supports Surface 3 yet.
  540. [1] https://github.com/linux-surface/acpidumps/blob/05cba925f3a515f222acb5b3551a032ddde958fe/surface_3/dsdt.dsl#L11947-L12011
  541. [2] https://github.com/linux-surface/acpidumps/blob/05cba925f3a515f222acb5b3551a032ddde958fe/surface_pro_3/dsdt.dsl#L12164-L12216
  542. Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
  543. Patchset: wifi
  544. ---
  545. drivers/net/wireless/marvell/mwifiex/pcie.c | 10 +++
  546. .../wireless/marvell/mwifiex/pcie_quirks.c | 77 ++++++++++++++++++-
  547. .../wireless/marvell/mwifiex/pcie_quirks.h | 5 ++
  548. 3 files changed, 91 insertions(+), 1 deletion(-)
  549. diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
  550. index 828957cd5449..263d918767bd 100644
  551. --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
  552. +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
  553. @@ -2817,6 +2817,16 @@ static void mwifiex_pcie_card_reset_work(struct mwifiex_adapter *adapter)
  554. {
  555. struct pcie_service_card *card = adapter->card;
  556. + /* On Surface 3, reset_wsid method removes then re-probes card by
  557. + * itself. So, need to place it here and skip performing any other
  558. + * reset-related works.
  559. + */
  560. + if (card->quirks & QUIRK_FW_RST_WSID_S3) {
  561. + mwifiex_pcie_reset_wsid_quirk(card->dev);
  562. + /* skip performing any other reset-related works */
  563. + return;
  564. + }
  565. +
  566. /* We can't afford to wait here; remove() might be waiting on us. If we
  567. * can't grab the device lock, maybe we'll get another chance later.
  568. */
  569. diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
  570. index edc739c542fe..f0a6fa0a7ae5 100644
  571. --- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
  572. +++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
  573. @@ -9,10 +9,21 @@
  574. * down, or causes NULL ptr deref).
  575. */
  576. +#include <linux/acpi.h>
  577. #include <linux/dmi.h>
  578. #include "pcie_quirks.h"
  579. +/* For reset_wsid quirk */
  580. +#define ACPI_WSID_PATH "\\_SB.WSID"
  581. +#define WSID_REV 0x0
  582. +#define WSID_FUNC_WIFI_PWR_OFF 0x1
  583. +#define WSID_FUNC_WIFI_PWR_ON 0x2
  584. +/* WSID _DSM UUID: "534ea3bf-fcc2-4e7a-908f-a13978f0c7ef" */
  585. +static const guid_t wsid_dsm_guid =
  586. + GUID_INIT(0x534ea3bf, 0xfcc2, 0x4e7a,
  587. + 0x90, 0x8f, 0xa1, 0x39, 0x78, 0xf0, 0xc7, 0xef);
  588. +
  589. /* quirk table based on DMI matching */
  590. static const struct dmi_system_id mwifiex_quirk_table[] = {
  591. {
  592. @@ -87,7 +98,7 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
  593. DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  594. DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface 3"),
  595. },
  596. - .driver_data = 0,
  597. + .driver_data = (void *)QUIRK_FW_RST_WSID_S3,
  598. },
  599. {
  600. .ident = "Surface Pro 3",
  601. @@ -113,6 +124,9 @@ void mwifiex_initialize_quirks(struct pcie_service_card *card)
  602. dev_info(&pdev->dev, "no quirks enabled\n");
  603. if (card->quirks & QUIRK_FW_RST_D3COLD)
  604. dev_info(&pdev->dev, "quirk reset_d3cold enabled\n");
  605. + if (card->quirks & QUIRK_FW_RST_WSID_S3)
  606. + dev_info(&pdev->dev,
  607. + "quirk reset_wsid for Surface 3 enabled\n");
  608. }
  609. static void mwifiex_pcie_set_power_d3cold(struct pci_dev *pdev)
  610. @@ -169,3 +183,64 @@ int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev)
  611. return 0;
  612. }
  613. +
  614. +int mwifiex_pcie_reset_wsid_quirk(struct pci_dev *pdev)
  615. +{
  616. + acpi_handle handle;
  617. + union acpi_object *obj;
  618. + acpi_status status;
  619. +
  620. + dev_info(&pdev->dev, "Using reset_wsid quirk to perform FW reset\n");
  621. +
  622. + status = acpi_get_handle(NULL, ACPI_WSID_PATH, &handle);
  623. + if (ACPI_FAILURE(status)) {
  624. + dev_err(&pdev->dev, "No ACPI handle for path %s\n",
  625. + ACPI_WSID_PATH);
  626. + return -ENODEV;
  627. + }
  628. +
  629. + if (!acpi_has_method(handle, "_DSM")) {
  630. + dev_err(&pdev->dev, "_DSM method not found\n");
  631. + return -ENODEV;
  632. + }
  633. +
  634. + if (!acpi_check_dsm(handle, &wsid_dsm_guid,
  635. + WSID_REV, WSID_FUNC_WIFI_PWR_OFF)) {
  636. + dev_err(&pdev->dev,
  637. + "_DSM method doesn't support wifi power off func\n");
  638. + return -ENODEV;
  639. + }
  640. +
  641. + if (!acpi_check_dsm(handle, &wsid_dsm_guid,
  642. + WSID_REV, WSID_FUNC_WIFI_PWR_ON)) {
  643. + dev_err(&pdev->dev,
  644. + "_DSM method doesn't support wifi power on func\n");
  645. + return -ENODEV;
  646. + }
  647. +
  648. + /* card will be removed immediately after this call on Surface 3 */
  649. + dev_info(&pdev->dev, "turning wifi off...\n");
  650. + obj = acpi_evaluate_dsm(handle, &wsid_dsm_guid,
  651. + WSID_REV, WSID_FUNC_WIFI_PWR_OFF,
  652. + NULL);
  653. + if (!obj) {
  654. + dev_err(&pdev->dev,
  655. + "device _DSM execution failed for turning wifi off\n");
  656. + return -EIO;
  657. + }
  658. + ACPI_FREE(obj);
  659. +
  660. + /* card will be re-probed immediately after this call on Surface 3 */
  661. + dev_info(&pdev->dev, "turning wifi on...\n");
  662. + obj = acpi_evaluate_dsm(handle, &wsid_dsm_guid,
  663. + WSID_REV, WSID_FUNC_WIFI_PWR_ON,
  664. + NULL);
  665. + if (!obj) {
  666. + dev_err(&pdev->dev,
  667. + "device _DSM execution failed for turning wifi on\n");
  668. + return -EIO;
  669. + }
  670. + ACPI_FREE(obj);
  671. +
  672. + return 0;
  673. +}
  674. diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
  675. index 8b9dcb5070d8..3ef7440418e3 100644
  676. --- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
  677. +++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
  678. @@ -7,6 +7,11 @@
  679. /* quirks */
  680. #define QUIRK_FW_RST_D3COLD BIT(0)
  681. +/* Surface 3 and Surface Pro 3 have the same _DSM method but need to
  682. + * be handled differently. Currently, only S3 is supported.
  683. + */
  684. +#define QUIRK_FW_RST_WSID_S3 BIT(1)
  685. void mwifiex_initialize_quirks(struct pcie_service_card *card);
  686. int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev);
  687. +int mwifiex_pcie_reset_wsid_quirk(struct pci_dev *pdev);
  688. --
  689. 2.30.1
  690. From ff7424694a69509c694c0ff5a968e6e43fe9315a Mon Sep 17 00:00:00 2001
  691. From: Tsuchiya Yuto <kitakar@gmail.com>
  692. Date: Wed, 30 Sep 2020 18:08:24 +0900
  693. Subject: [PATCH] mwifiex: pcie: (OEMB) add quirk for Surface 3 with broken DMI
  694. table
  695. (made referring to http://git.osdn.net/view?p=android-x86/kernel.git;a=commitdiff;h=18e2e857c57633b25b3b4120f212224a108cd883)
  696. On some Surface 3, the DMI table gets corrupted for unknown reasons
  697. and breaks existing DMI matching used for device-specific quirks.
  698. This commit adds the (broken) DMI info for the affected Surface 3.
  699. On affected systems, DMI info will look like this:
  700. $ grep . /sys/devices/virtual/dmi/id/{bios_vendor,board_name,board_vendor,\
  701. chassis_vendor,product_name,sys_vendor}
  702. /sys/devices/virtual/dmi/id/bios_vendor:American Megatrends Inc.
  703. /sys/devices/virtual/dmi/id/board_name:OEMB
  704. /sys/devices/virtual/dmi/id/board_vendor:OEMB
  705. /sys/devices/virtual/dmi/id/chassis_vendor:OEMB
  706. /sys/devices/virtual/dmi/id/product_name:OEMB
  707. /sys/devices/virtual/dmi/id/sys_vendor:OEMB
  708. Expected:
  709. $ grep . /sys/devices/virtual/dmi/id/{bios_vendor,board_name,board_vendor,\
  710. chassis_vendor,product_name,sys_vendor}
  711. /sys/devices/virtual/dmi/id/bios_vendor:American Megatrends Inc.
  712. /sys/devices/virtual/dmi/id/board_name:Surface 3
  713. /sys/devices/virtual/dmi/id/board_vendor:Microsoft Corporation
  714. /sys/devices/virtual/dmi/id/chassis_vendor:Microsoft Corporation
  715. /sys/devices/virtual/dmi/id/product_name:Surface 3
  716. /sys/devices/virtual/dmi/id/sys_vendor:Microsoft Corporation
  717. Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
  718. Patchset: wifi
  719. ---
  720. drivers/net/wireless/marvell/mwifiex/pcie_quirks.c | 9 +++++++++
  721. 1 file changed, 9 insertions(+)
  722. diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
  723. index f0a6fa0a7ae5..34dcd84f02a6 100644
  724. --- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
  725. +++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
  726. @@ -100,6 +100,15 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
  727. },
  728. .driver_data = (void *)QUIRK_FW_RST_WSID_S3,
  729. },
  730. + {
  731. + .ident = "Surface 3",
  732. + .matches = {
  733. + DMI_EXACT_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
  734. + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "OEMB"),
  735. + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "OEMB"),
  736. + },
  737. + .driver_data = (void *)QUIRK_FW_RST_WSID_S3,
  738. + },
  739. {
  740. .ident = "Surface Pro 3",
  741. .matches = {
  742. --
  743. 2.30.1
  744. From 861079133a6881425e234bdc62da525f37c60386 Mon Sep 17 00:00:00 2001
  745. From: Tsuchiya Yuto <kitakar@gmail.com>
  746. Date: Thu, 24 Sep 2020 01:56:34 +0900
  747. Subject: [PATCH] mwifiex: pcie: use shutdown_sw()/reinit_sw() on
  748. suspend()/resume()
  749. There are issues with S0ix achievement and AP scanning after suspend
  750. with the current Host Sleep method.
  751. When using the Host Sleep method, it prevents the platform to reach S0ix
  752. during suspend. Also, after suspend, sometimes AP scanning won't work,
  753. resulting in non-working wifi.
  754. To fix such issues, perform shutdown_sw()/reinit_sw() instead of Host
  755. Sleep.
  756. As a side effect, this patch disables wakeups (means that Wake-On-WLAN
  757. can't be used anymore, if it was working before), and might also reset
  758. some internal states.
  759. Note that suspend() no longer checks if it's already suspended.
  760. With the previous Host Sleep method, the check was done by looking at
  761. adapter->hs_activated in mwifiex_enable_hs() [sta_ioctl.c], but not
  762. MWIFIEX_IS_SUSPENDED. So, what the previous method checked was instead
  763. Host Sleep state, not suspend itself. Therefore, there is no need to check
  764. the suspend state now.
  765. Also removed comment for suspend state check at top of suspend()
  766. accordingly.
  767. Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
  768. Patchset: wifi
  769. ---
  770. drivers/net/wireless/marvell/mwifiex/main.c | 4 +--
  771. drivers/net/wireless/marvell/mwifiex/pcie.c | 29 +++++++--------------
  772. 2 files changed, 12 insertions(+), 21 deletions(-)
  773. diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
  774. index 5894566ec480..99cc391e4afb 100644
  775. --- a/drivers/net/wireless/marvell/mwifiex/main.c
  776. +++ b/drivers/net/wireless/marvell/mwifiex/main.c
  777. @@ -1453,7 +1453,7 @@ static void mwifiex_uninit_sw(struct mwifiex_adapter *adapter)
  778. }
  779. /*
  780. - * This function gets called during PCIe function level reset.
  781. + * This function can be used for shutting down the adapter SW.
  782. */
  783. int mwifiex_shutdown_sw(struct mwifiex_adapter *adapter)
  784. {
  785. @@ -1481,7 +1481,7 @@ int mwifiex_shutdown_sw(struct mwifiex_adapter *adapter)
  786. }
  787. EXPORT_SYMBOL_GPL(mwifiex_shutdown_sw);
  788. -/* This function gets called during PCIe function level reset. Required
  789. +/* This function can be used for reinitting the adapter SW. Required
  790. * code is extracted from mwifiex_add_card()
  791. */
  792. int
  793. diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
  794. index 263d918767bd..bd6791dc3a0f 100644
  795. --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
  796. +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
  797. @@ -145,8 +145,7 @@ static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter)
  798. * registered functions must have drivers with suspend and resume
  799. * methods. Failing that the kernel simply removes the whole card.
  800. *
  801. - * If already not suspended, this function allocates and sends a host
  802. - * sleep activate request to the firmware and turns off the traffic.
  803. + * This function shuts down the adapter.
  804. */
  805. static int mwifiex_pcie_suspend(struct device *dev)
  806. {
  807. @@ -154,31 +153,21 @@ static int mwifiex_pcie_suspend(struct device *dev)
  808. struct pcie_service_card *card = dev_get_drvdata(dev);
  809. - /* Might still be loading firmware */
  810. - wait_for_completion(&card->fw_done);
  811. -
  812. adapter = card->adapter;
  813. if (!adapter) {
  814. dev_err(dev, "adapter is not valid\n");
  815. return 0;
  816. }
  817. - mwifiex_enable_wake(adapter);
  818. -
  819. - /* Enable the Host Sleep */
  820. - if (!mwifiex_enable_hs(adapter)) {
  821. + /* Shut down SW */
  822. + if (mwifiex_shutdown_sw(adapter)) {
  823. mwifiex_dbg(adapter, ERROR,
  824. "cmd: failed to suspend\n");
  825. - clear_bit(MWIFIEX_IS_HS_ENABLING, &adapter->work_flags);
  826. - mwifiex_disable_wake(adapter);
  827. return -EFAULT;
  828. }
  829. - flush_workqueue(adapter->workqueue);
  830. -
  831. /* Indicate device suspended */
  832. set_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags);
  833. - clear_bit(MWIFIEX_IS_HS_ENABLING, &adapter->work_flags);
  834. return 0;
  835. }
  836. @@ -188,13 +177,13 @@ static int mwifiex_pcie_suspend(struct device *dev)
  837. * registered functions must have drivers with suspend and resume
  838. * methods. Failing that the kernel simply removes the whole card.
  839. *
  840. - * If already not resumed, this function turns on the traffic and
  841. - * sends a host sleep cancel request to the firmware.
  842. + * If already not resumed, this function reinits the adapter.
  843. */
  844. static int mwifiex_pcie_resume(struct device *dev)
  845. {
  846. struct mwifiex_adapter *adapter;
  847. struct pcie_service_card *card = dev_get_drvdata(dev);
  848. + int ret;
  849. if (!card->adapter) {
  850. @@ -212,9 +201,11 @@ static int mwifiex_pcie_resume(struct device *dev)
  851. clear_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags);
  852. - mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
  853. - MWIFIEX_ASYNC_CMD);
  854. - mwifiex_disable_wake(adapter);
  855. + ret = mwifiex_reinit_sw(adapter);
  856. + if (ret)
  857. + dev_err(dev, "reinit failed: %d\n", ret);
  858. + else
  859. + mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
  860. return 0;
  861. }
  862. --
  863. 2.30.1
  864. From e5b5d7b27a53fcff871603a3c7fb4f505d029c00 Mon Sep 17 00:00:00 2001
  865. From: Tsuchiya Yuto <kitakar@gmail.com>
  866. Date: Mon, 24 Aug 2020 17:11:35 +0900
  867. Subject: [PATCH] mwifiex: pcie: add enable_device_dump module parameter
  868. The devicve_dump may take a little bit long time and users may want to
  869. disable the dump for daily usage.
  870. This commit adds a new module parameter and disables device_dump by
  871. default.
  872. Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
  873. Patchset: wifi
  874. ---
  875. drivers/net/wireless/marvell/mwifiex/pcie.c | 11 +++++++++++
  876. 1 file changed, 11 insertions(+)
  877. diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
  878. index bd6791dc3a0f..d7ff898c1767 100644
  879. --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
  880. +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
  881. @@ -34,6 +34,11 @@
  882. static struct mwifiex_if_ops pcie_ops;
  883. +static bool enable_device_dump;
  884. +module_param(enable_device_dump, bool, 0644);
  885. +MODULE_PARM_DESC(enable_device_dump,
  886. + "enable device_dump (default: disabled)");
  887. +
  888. static const struct of_device_id mwifiex_pcie_of_match_table[] = {
  889. { .compatible = "pci11ab,2b42" },
  890. { .compatible = "pci1b4b,2b42" },
  891. @@ -2791,6 +2796,12 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
  892. static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter)
  893. {
  894. + if (!enable_device_dump) {
  895. + mwifiex_dbg(adapter, MSG,
  896. + "device_dump is disabled by module parameter\n");
  897. + return;
  898. + }
  899. +
  900. adapter->devdump_data = vzalloc(MWIFIEX_FW_DUMP_SIZE);
  901. if (!adapter->devdump_data) {
  902. mwifiex_dbg(adapter, ERROR,
  903. --
  904. 2.30.1
  905. From d27add3beb83d75f4e20559ace0341946533ef17 Mon Sep 17 00:00:00 2001
  906. From: Tsuchiya Yuto <kitakar@gmail.com>
  907. Date: Sun, 4 Oct 2020 00:11:49 +0900
  908. Subject: [PATCH] mwifiex: pcie: disable bridge_d3 for Surface gen4+
  909. Currently, mwifiex fw will crash after suspend on recent kernel series.
  910. On Windows, it seems that the root port of wifi will never enter D3 state
  911. (stay on D0 state). And on Linux, disabling the D3 state for the
  912. bridge fixes fw crashing after suspend.
  913. This commit disables the D3 state of root port on driver initialization
  914. and fixes fw crashing after suspend.
  915. Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
  916. Patchset: wifi
  917. ---
  918. drivers/net/wireless/marvell/mwifiex/pcie.c | 7 +++++
  919. .../wireless/marvell/mwifiex/pcie_quirks.c | 27 +++++++++++++------
  920. .../wireless/marvell/mwifiex/pcie_quirks.h | 1 +
  921. 3 files changed, 27 insertions(+), 8 deletions(-)
  922. diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
  923. index d7ff898c1767..5249b209eb02 100644
  924. --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
  925. +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
  926. @@ -226,6 +226,7 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
  927. const struct pci_device_id *ent)
  928. {
  929. struct pcie_service_card *card;
  930. + struct pci_dev *parent_pdev = pci_upstream_bridge(pdev);
  931. int ret;
  932. pr_debug("info: vendor=0x%4.04X device=0x%4.04X rev=%d\n",
  933. @@ -267,6 +268,12 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
  934. return -1;
  935. }
  936. + /* disable bridge_d3 for Surface gen4+ devices to fix fw crashing
  937. + * after suspend
  938. + */
  939. + if (card->quirks & QUIRK_NO_BRIDGE_D3)
  940. + parent_pdev->bridge_d3 = false;
  941. +
  942. return 0;
  943. }
  944. diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
  945. index 34dcd84f02a6..a2aeb2af907e 100644
  946. --- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
  947. +++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
  948. @@ -32,7 +32,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
  949. DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  950. DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 4"),
  951. },
  952. - .driver_data = (void *)QUIRK_FW_RST_D3COLD,
  953. + .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
  954. + QUIRK_NO_BRIDGE_D3),
  955. },
  956. {
  957. .ident = "Surface Pro 5",
  958. @@ -41,7 +42,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
  959. DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  960. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "Surface_Pro_1796"),
  961. },
  962. - .driver_data = (void *)QUIRK_FW_RST_D3COLD,
  963. + .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
  964. + QUIRK_NO_BRIDGE_D3),
  965. },
  966. {
  967. .ident = "Surface Pro 5 (LTE)",
  968. @@ -50,7 +52,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
  969. DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  970. DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "Surface_Pro_1807"),
  971. },
  972. - .driver_data = (void *)QUIRK_FW_RST_D3COLD,
  973. + .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
  974. + QUIRK_NO_BRIDGE_D3),
  975. },
  976. {
  977. .ident = "Surface Pro 6",
  978. @@ -58,7 +61,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
  979. DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  980. DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 6"),
  981. },
  982. - .driver_data = (void *)QUIRK_FW_RST_D3COLD,
  983. + .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
  984. + QUIRK_NO_BRIDGE_D3),
  985. },
  986. {
  987. .ident = "Surface Book 1",
  988. @@ -66,7 +70,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
  989. DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  990. DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Book"),
  991. },
  992. - .driver_data = (void *)QUIRK_FW_RST_D3COLD,
  993. + .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
  994. + QUIRK_NO_BRIDGE_D3),
  995. },
  996. {
  997. .ident = "Surface Book 2",
  998. @@ -74,7 +79,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
  999. DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  1000. DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Book 2"),
  1001. },
  1002. - .driver_data = (void *)QUIRK_FW_RST_D3COLD,
  1003. + .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
  1004. + QUIRK_NO_BRIDGE_D3),
  1005. },
  1006. {
  1007. .ident = "Surface Laptop 1",
  1008. @@ -82,7 +88,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
  1009. DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  1010. DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Laptop"),
  1011. },
  1012. - .driver_data = (void *)QUIRK_FW_RST_D3COLD,
  1013. + .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
  1014. + QUIRK_NO_BRIDGE_D3),
  1015. },
  1016. {
  1017. .ident = "Surface Laptop 2",
  1018. @@ -90,7 +97,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
  1019. DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
  1020. DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Laptop 2"),
  1021. },
  1022. - .driver_data = (void *)QUIRK_FW_RST_D3COLD,
  1023. + .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
  1024. + QUIRK_NO_BRIDGE_D3),
  1025. },
  1026. {
  1027. .ident = "Surface 3",
  1028. @@ -136,6 +144,9 @@ void mwifiex_initialize_quirks(struct pcie_service_card *card)
  1029. if (card->quirks & QUIRK_FW_RST_WSID_S3)
  1030. dev_info(&pdev->dev,
  1031. "quirk reset_wsid for Surface 3 enabled\n");
  1032. + if (card->quirks & QUIRK_NO_BRIDGE_D3)
  1033. + dev_info(&pdev->dev,
  1034. + "quirk no_brigde_d3 enabled\n");
  1035. }
  1036. static void mwifiex_pcie_set_power_d3cold(struct pci_dev *pdev)
  1037. diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
  1038. index 3ef7440418e3..a95ebac06e13 100644
  1039. --- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
  1040. +++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
  1041. @@ -11,6 +11,7 @@
  1042. * be handled differently. Currently, only S3 is supported.
  1043. */
  1044. #define QUIRK_FW_RST_WSID_S3 BIT(1)
  1045. +#define QUIRK_NO_BRIDGE_D3 BIT(2)
  1046. void mwifiex_initialize_quirks(struct pcie_service_card *card);
  1047. int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev);
  1048. --
  1049. 2.30.1
  1050. From b19749fd1a6563a4d7d76bcc503b383bd112665d Mon Sep 17 00:00:00 2001
  1051. From: Tsuchiya Yuto <kitakar@gmail.com>
  1052. Date: Sun, 4 Oct 2020 00:25:48 +0900
  1053. Subject: [PATCH] mwifiex: add allow_ps_mode module parameter
  1054. This commit adds the allow_ps_mode module parameter and set it false
  1055. (disallowed) by default, to make ps_mode (power_save) control easier.
  1056. On some setups (e.g., with 5GHz AP), power_save causes connection
  1057. completely unstable. So, we need to disable it. However, userspace tools
  1058. may try to enable it. For this reason, we need to tell userspace that
  1059. power_save is disallowed by default.
  1060. When this parameter is set to false, changing the power_save mode will
  1061. be disallowed like the following:
  1062. $ sudo iw dev mlan0 set power_save on
  1063. command failed: Operation not permitted (-1)
  1064. Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
  1065. Patchset: wifi
  1066. ---
  1067. drivers/net/wireless/marvell/mwifiex/cfg80211.c | 16 ++++++++++++++++
  1068. 1 file changed, 16 insertions(+)
  1069. diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
  1070. index 9e6dc289ec3e..20f5ee3fe7e3 100644
  1071. --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
  1072. +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
  1073. @@ -25,6 +25,11 @@
  1074. static char *reg_alpha2;
  1075. module_param(reg_alpha2, charp, 0);
  1076. +static bool allow_ps_mode;
  1077. +module_param(allow_ps_mode, bool, 0644);
  1078. +MODULE_PARM_DESC(allow_ps_mode,
  1079. + "allow WiFi power management to be enabled. (default: disallowed)");
  1080. +
  1081. static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = {
  1082. {
  1083. .max = 3, .types = BIT(NL80211_IFTYPE_STATION) |
  1084. @@ -439,6 +444,17 @@ mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy,
  1085. ps_mode = enabled;
  1086. + /* Allow ps_mode to be enabled only when allow_ps_mode is true */
  1087. + if (ps_mode && !allow_ps_mode) {
  1088. + mwifiex_dbg(priv->adapter, MSG,
  1089. + "Enabling ps_mode disallowed by modparam\n");
  1090. +
  1091. + /* Return -EPERM to inform userspace tools that setting
  1092. + * power_save to be enabled is not permitted.
  1093. + */
  1094. + return -EPERM;
  1095. + }
  1096. +
  1097. return mwifiex_drv_set_power(priv, &ps_mode);
  1098. }
  1099. --
  1100. 2.30.1
  1101. From c86b4bca63e8d57ddab8e484c158e0dde4044e5e Mon Sep 17 00:00:00 2001
  1102. From: Tsuchiya Yuto <kitakar@gmail.com>
  1103. Date: Sun, 4 Oct 2020 00:38:48 +0900
  1104. Subject: [PATCH] mwifiex: print message when changing ps_mode
  1105. Users may want to know the ps_mode state change (e.g., diagnosing
  1106. connection issues). This commit adds the print when changing ps_mode.
  1107. Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
  1108. Patchset: wifi
  1109. ---
  1110. drivers/net/wireless/marvell/mwifiex/cfg80211.c | 7 +++++++
  1111. 1 file changed, 7 insertions(+)
  1112. diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
  1113. index 20f5ee3fe7e3..8020a2929069 100644
  1114. --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
  1115. +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
  1116. @@ -455,6 +455,13 @@ mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy,
  1117. return -EPERM;
  1118. }
  1119. + if (ps_mode)
  1120. + mwifiex_dbg(priv->adapter, MSG,
  1121. + "Enabling ps_mode, disable if unstable.\n");
  1122. + else
  1123. + mwifiex_dbg(priv->adapter, MSG,
  1124. + "Disabling ps_mode.\n");
  1125. +
  1126. return mwifiex_drv_set_power(priv, &ps_mode);
  1127. }
  1128. --
  1129. 2.30.1
  1130. From 0bffe54a88dab69db359641bec117adf8a8dc7ab Mon Sep 17 00:00:00 2001
  1131. From: Tsuchiya Yuto <kitakar@gmail.com>
  1132. Date: Sun, 4 Oct 2020 00:59:37 +0900
  1133. Subject: [PATCH] mwifiex: disable ps_mode explicitly by default instead
  1134. At least on Surface devices, the ps_mode causes connection unstable,
  1135. especially with 5GHz APs. Then, it eventually causes fw crashing.
  1136. This commit disables ps_mode by default instead of enabling it.
  1137. Required code is extracted from mwifiex_drv_set_power().
  1138. Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
  1139. Patchset: wifi
  1140. ---
  1141. drivers/net/wireless/marvell/mwifiex/sta_cmd.c | 11 ++++++++---
  1142. 1 file changed, 8 insertions(+), 3 deletions(-)
  1143. diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
  1144. index 4ed10cf82f9a..ed0fffb9eba6 100644
  1145. --- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
  1146. +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
  1147. @@ -2340,14 +2340,19 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
  1148. return -1;
  1149. if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) {
  1150. - /* Enable IEEE PS by default */
  1151. - priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP;
  1152. + /* Disable IEEE PS by default */
  1153. + priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM;
  1154. ret = mwifiex_send_cmd(priv,
  1155. HostCmd_CMD_802_11_PS_MODE_ENH,
  1156. - EN_AUTO_PS, BITMAP_STA_PS, NULL,
  1157. + DIS_AUTO_PS, BITMAP_STA_PS, NULL,
  1158. true);
  1159. if (ret)
  1160. return -1;
  1161. + ret = mwifiex_send_cmd(priv,
  1162. + HostCmd_CMD_802_11_PS_MODE_ENH,
  1163. + GET_PS, 0, NULL, false);
  1164. + if (ret)
  1165. + return -1;
  1166. }
  1167. if (drcs) {
  1168. --
  1169. 2.30.1