12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376 |
- From 55a8d7c9af472a0d194ac6d74e11445dcf5e8aea Mon Sep 17 00:00:00 2001
- From: Tsuchiya Yuto <kitakar@gmail.com>
- Date: Thu, 24 Sep 2020 18:02:06 +0900
- Subject: [PATCH] mwifiex: pcie: skip cancel_work_sync() on reset failure path
- If a reset is performed, but even the reset fails for some reasons (e.g.,
- on Surface devices, the fw reset requires another quirks),
- cancel_work_sync() hangs in mwifiex_cleanup_pcie().
- # reset performed after firmware went into bad state
- kernel: mwifiex_pcie 0000:01:00.0: WLAN FW already running! Skip FW dnld
- kernel: mwifiex_pcie 0000:01:00.0: WLAN FW is active
- # but even the reset failed
- kernel: mwifiex_pcie 0000:01:00.0: mwifiex_cmd_timeout_func: Timeout cmd id = 0xfa, act = 0xa000
- kernel: mwifiex_pcie 0000:01:00.0: num_data_h2c_failure = 0
- kernel: mwifiex_pcie 0000:01:00.0: num_cmd_h2c_failure = 0
- kernel: mwifiex_pcie 0000:01:00.0: is_cmd_timedout = 1
- kernel: mwifiex_pcie 0000:01:00.0: num_tx_timeout = 0
- kernel: mwifiex_pcie 0000:01:00.0: last_cmd_index = 2
- kernel: mwifiex_pcie 0000:01:00.0: last_cmd_id: 16 00 a4 00 fa 00 a4 00 7f 00
- kernel: mwifiex_pcie 0000:01:00.0: last_cmd_act: 00 00 00 00 00 a0 00 00 00 00
- kernel: mwifiex_pcie 0000:01:00.0: last_cmd_resp_index = 0
- kernel: mwifiex_pcie 0000:01:00.0: last_cmd_resp_id: 16 80 7f 80 16 80 a4 80 7f 80
- kernel: mwifiex_pcie 0000:01:00.0: last_event_index = 1
- kernel: mwifiex_pcie 0000:01:00.0: last_event: 58 00 58 00 58 00 58 00 58 00
- kernel: mwifiex_pcie 0000:01:00.0: data_sent=0 cmd_sent=1
- kernel: mwifiex_pcie 0000:01:00.0: ps_mode=0 ps_state=0
- kernel: mwifiex_pcie 0000:01:00.0: info: _mwifiex_fw_dpc: unregister device
- # mwifiex_pcie_work hanged
- kernel: INFO: task kworker/0:0:24857 blocked for more than 122 seconds.
- kernel: Tainted: G W OE 5.3.11-arch1-1 #1
- kernel: "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
- kernel: kworker/0:0 D 0 24857 2 0x80004000
- kernel: Workqueue: events mwifiex_pcie_work [mwifiex_pcie]
- kernel: Call Trace:
- kernel: ? __schedule+0x27f/0x6d0
- kernel: schedule+0x43/0xd0
- kernel: schedule_timeout+0x299/0x3d0
- kernel: ? __switch_to_asm+0x40/0x70
- kernel: wait_for_common+0xeb/0x190
- kernel: ? wake_up_q+0x60/0x60
- kernel: __flush_work+0x130/0x1e0
- kernel: ? flush_workqueue_prep_pwqs+0x130/0x130
- kernel: __cancel_work_timer+0x123/0x1b0
- kernel: mwifiex_cleanup_pcie+0x28/0xd0 [mwifiex_pcie]
- kernel: mwifiex_free_adapter+0x24/0xe0 [mwifiex]
- kernel: _mwifiex_fw_dpc+0x28d/0x520 [mwifiex]
- kernel: mwifiex_reinit_sw+0x15d/0x2c0 [mwifiex]
- kernel: mwifiex_pcie_reset_done+0x50/0x80 [mwifiex_pcie]
- kernel: pci_try_reset_function+0x38/0x70
- kernel: process_one_work+0x1d1/0x3a0
- kernel: worker_thread+0x4a/0x3d0
- kernel: kthread+0xfb/0x130
- kernel: ? process_one_work+0x3a0/0x3a0
- kernel: ? kthread_park+0x80/0x80
- kernel: ret_from_fork+0x35/0x40
- This is a deadlock caused by calling cancel_work_sync() in
- mwifiex_cleanup_pcie():
- - Device resets are done via mwifiex_pcie_card_reset()
- - which schedules card->work to call mwifiex_pcie_card_reset_work()
- - which calls pci_try_reset_function().
- - This leads to mwifiex_pcie_reset_done() be called on the same workqueue,
- which in turn calls
- - mwifiex_reinit_sw() and that calls
- - _mwifiex_fw_dpc().
- The problem is now that _mwifiex_fw_dpc() calls mwifiex_free_adapter()
- in case firmware initialization fails. That ends up calling
- mwifiex_cleanup_pcie().
- Note that all those calls are still running on the workqueue. So when
- mwifiex_cleanup_pcie() now calls cancel_work_sync(), it's really waiting
- on itself to complete, causing a deadlock.
- This commit fixes the deadlock by skipping cancel_work_sync() on a reset
- failure path.
- After this commit, when reset fails, the following output is
- expected to be shown:
- kernel: mwifiex_pcie 0000:03:00.0: info: _mwifiex_fw_dpc: unregister device
- kernel: mwifiex: Failed to bring up adapter: -5
- kernel: mwifiex_pcie 0000:03:00.0: reinit failed: -5
- To reproduce this issue, for example, try putting the root port of wifi
- into D3 (replace "00:1d.3" with your setup).
- # put into D3 (root port)
- sudo setpci -v -s 00:1d.3 CAP_PM+4.b=0b
- Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
- Patchset: wifi
- ---
- drivers/net/wireless/marvell/mwifiex/pcie.c | 18 +++++++++++++++++-
- drivers/net/wireless/marvell/mwifiex/pcie.h | 2 ++
- 2 files changed, 19 insertions(+), 1 deletion(-)
- diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
- index 87b4ccca4b9a..00138d6129f4 100644
- --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
- +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
- @@ -377,6 +377,8 @@ static void mwifiex_pcie_reset_prepare(struct pci_dev *pdev)
- clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags);
- clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags);
- mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
- +
- + card->pci_reset_ongoing = true;
- }
-
- /*
- @@ -405,6 +407,8 @@ static void mwifiex_pcie_reset_done(struct pci_dev *pdev)
- dev_err(&pdev->dev, "reinit failed: %d\n", ret);
- else
- mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
- +
- + card->pci_reset_ongoing = false;
- }
-
- static const struct pci_error_handlers mwifiex_pcie_err_handler = {
- @@ -2995,7 +2999,19 @@ static void mwifiex_cleanup_pcie(struct mwifiex_adapter *adapter)
- int ret;
- u32 fw_status;
-
- - cancel_work_sync(&card->work);
- + /* Perform the cancel_work_sync() only when we're not resetting
- + * the card. It's because that function never returns if we're
- + * in reset path. If we're here when resetting the card, it means
- + * that we failed to reset the card (reset failure path).
- + */
- + if (!card->pci_reset_ongoing) {
- + mwifiex_dbg(adapter, MSG, "performing cancel_work_sync()...\n");
- + cancel_work_sync(&card->work);
- + mwifiex_dbg(adapter, MSG, "cancel_work_sync() done\n");
- + } else {
- + mwifiex_dbg(adapter, MSG,
- + "skipped cancel_work_sync() because we're in card reset failure path\n");
- + }
-
- ret = mwifiex_read_reg(adapter, reg->fw_status, &fw_status);
- if (fw_status == FIRMWARE_READY_PCIE) {
- diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h
- index fc59b522f670..048f4db6027a 100644
- --- a/drivers/net/wireless/marvell/mwifiex/pcie.h
- +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h
- @@ -391,6 +391,8 @@ struct pcie_service_card {
- struct mwifiex_msix_context share_irq_ctx;
- struct work_struct work;
- unsigned long work_flags;
- +
- + bool pci_reset_ongoing;
- };
-
- static inline int
- --
- 2.29.2
- From 5f0c4f9b2190f49e42605c722d90ac7cde94353d Mon Sep 17 00:00:00 2001
- From: Tsuchiya Yuto <kitakar@gmail.com>
- Date: Mon, 28 Sep 2020 17:46:49 +0900
- Subject: [PATCH] mwifiex: pcie: add DMI-based quirk impl for Surface devices
- This commit adds quirk implementation based on DMI matching with DMI
- table for Surface devices.
- This implementation can be used for quirks later.
- Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
- Patchset: wifi
- ---
- drivers/net/wireless/marvell/mwifiex/Makefile | 1 +
- drivers/net/wireless/marvell/mwifiex/pcie.c | 4 +
- drivers/net/wireless/marvell/mwifiex/pcie.h | 1 +
- .../wireless/marvell/mwifiex/pcie_quirks.c | 114 ++++++++++++++++++
- .../wireless/marvell/mwifiex/pcie_quirks.h | 11 ++
- 5 files changed, 131 insertions(+)
- create mode 100644 drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
- create mode 100644 drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
- diff --git a/drivers/net/wireless/marvell/mwifiex/Makefile b/drivers/net/wireless/marvell/mwifiex/Makefile
- index fdfd9bf15ed4..8a1e7c5b9c6e 100644
- --- a/drivers/net/wireless/marvell/mwifiex/Makefile
- +++ b/drivers/net/wireless/marvell/mwifiex/Makefile
- @@ -49,6 +49,7 @@ mwifiex_sdio-y += sdio.o
- obj-$(CONFIG_MWIFIEX_SDIO) += mwifiex_sdio.o
-
- mwifiex_pcie-y += pcie.o
- +mwifiex_pcie-y += pcie_quirks.o
- obj-$(CONFIG_MWIFIEX_PCIE) += mwifiex_pcie.o
-
- mwifiex_usb-y += usb.o
- diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
- index 00138d6129f4..899ce2657880 100644
- --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
- +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
- @@ -27,6 +27,7 @@
- #include "wmm.h"
- #include "11n.h"
- #include "pcie.h"
- +#include "pcie_quirks.h"
-
- #define PCIE_VERSION "1.0"
- #define DRV_NAME "Marvell mwifiex PCIe"
- @@ -261,6 +262,9 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
- return ret;
- }
-
- + /* check quirks */
- + mwifiex_initialize_quirks(card);
- +
- if (mwifiex_add_card(card, &card->fw_done, &pcie_ops,
- MWIFIEX_PCIE, &pdev->dev)) {
- pr_err("%s failed\n", __func__);
- diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h
- index 048f4db6027a..51566380f8da 100644
- --- a/drivers/net/wireless/marvell/mwifiex/pcie.h
- +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h
- @@ -393,6 +393,7 @@ struct pcie_service_card {
- unsigned long work_flags;
-
- bool pci_reset_ongoing;
- + unsigned long quirks;
- };
-
- static inline int
- diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
- new file mode 100644
- index 000000000000..929aee2b0a60
- --- /dev/null
- +++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
- @@ -0,0 +1,114 @@
- +// SPDX-License-Identifier: GPL-2.0
- +/*
- + * File for PCIe quirks.
- + */
- +
- +/* The low-level PCI operations will be performed in this file. Therefore,
- + * let's use dev_*() instead of mwifiex_dbg() here to avoid troubles (e.g.
- + * to avoid using mwifiex_adapter struct before init or wifi is powered
- + * down, or causes NULL ptr deref).
- + */
- +
- +#include <linux/dmi.h>
- +
- +#include "pcie_quirks.h"
- +
- +/* quirk table based on DMI matching */
- +static const struct dmi_system_id mwifiex_quirk_table[] = {
- + {
- + .ident = "Surface Pro 4",
- + .matches = {
- + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 4"),
- + },
- + .driver_data = 0,
- + },
- + {
- + .ident = "Surface Pro 5",
- + .matches = {
- + /* match for SKU here due to generic product name "Surface Pro" */
- + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "Surface_Pro_1796"),
- + },
- + .driver_data = 0,
- + },
- + {
- + .ident = "Surface Pro 5 (LTE)",
- + .matches = {
- + /* match for SKU here due to generic product name "Surface Pro" */
- + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "Surface_Pro_1807"),
- + },
- + .driver_data = 0,
- + },
- + {
- + .ident = "Surface Pro 6",
- + .matches = {
- + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 6"),
- + },
- + .driver_data = 0,
- + },
- + {
- + .ident = "Surface Book 1",
- + .matches = {
- + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Book"),
- + },
- + .driver_data = 0,
- + },
- + {
- + .ident = "Surface Book 2",
- + .matches = {
- + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Book 2"),
- + },
- + .driver_data = 0,
- + },
- + {
- + .ident = "Surface Laptop 1",
- + .matches = {
- + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Laptop"),
- + },
- + .driver_data = 0,
- + },
- + {
- + .ident = "Surface Laptop 2",
- + .matches = {
- + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Laptop 2"),
- + },
- + .driver_data = 0,
- + },
- + {
- + .ident = "Surface 3",
- + .matches = {
- + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface 3"),
- + },
- + .driver_data = 0,
- + },
- + {
- + .ident = "Surface Pro 3",
- + .matches = {
- + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 3"),
- + },
- + .driver_data = 0,
- + },
- + {}
- +};
- +
- +void mwifiex_initialize_quirks(struct pcie_service_card *card)
- +{
- + struct pci_dev *pdev = card->dev;
- + const struct dmi_system_id *dmi_id;
- +
- + dmi_id = dmi_first_match(mwifiex_quirk_table);
- + if (dmi_id)
- + card->quirks = (uintptr_t)dmi_id->driver_data;
- +
- + if (!card->quirks)
- + dev_info(&pdev->dev, "no quirks enabled\n");
- +}
- diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
- new file mode 100644
- index 000000000000..5326ae7e5671
- --- /dev/null
- +++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
- @@ -0,0 +1,11 @@
- +/* SPDX-License-Identifier: GPL-2.0 */
- +/*
- + * Header file for PCIe quirks.
- + */
- +
- +#include "pcie.h"
- +
- +/* quirks */
- +// quirk flags can be added here
- +
- +void mwifiex_initialize_quirks(struct pcie_service_card *card);
- --
- 2.29.2
- From aa4a3ba7776db9ba12c57d0ad705ed298f27d9dd Mon Sep 17 00:00:00 2001
- From: Tsuchiya Yuto <kitakar@gmail.com>
- Date: Tue, 29 Sep 2020 17:25:22 +0900
- Subject: [PATCH] mwifiex: pcie: add reset_d3cold quirk for Surface gen4+
- devices
- To reset mwifiex on Surface gen4+ (Pro 4 or later gen) devices, it
- seems that putting the wifi device into D3cold is required according
- to errata.inf file on Windows installation (Windows/INF/errata.inf).
- This patch adds a function that performs power-cycle (put into D3cold
- then D0) and call the function at the end of reset_prepare().
- Note: Need to also reset the parent device (bridge) of wifi on SB1;
- it might be because the bridge of wifi always reports it's in D3hot.
- When I tried to reset only the wifi device (not touching parent), it gave
- the following error and the reset failed:
- acpi device:4b: Cannot transition to power state D0 for parent in D3hot
- mwifiex_pcie 0000:03:00.0: can't change power state from D3cold to D0 (config space inaccessible)
- Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
- Patchset: wifi
- ---
- drivers/net/wireless/marvell/mwifiex/pcie.c | 7 ++
- .../wireless/marvell/mwifiex/pcie_quirks.c | 73 +++++++++++++++++--
- .../wireless/marvell/mwifiex/pcie_quirks.h | 3 +-
- 3 files changed, 74 insertions(+), 9 deletions(-)
- diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
- index 899ce2657880..45488c2bc1c1 100644
- --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
- +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
- @@ -380,6 +380,13 @@ static void mwifiex_pcie_reset_prepare(struct pci_dev *pdev)
- mwifiex_shutdown_sw(adapter);
- clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags);
- clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags);
- +
- + /* For Surface gen4+ devices, we need to put wifi into D3cold right
- + * before performing FLR
- + */
- + if (card->quirks & QUIRK_FW_RST_D3COLD)
- + mwifiex_pcie_reset_d3cold_quirk(pdev);
- +
- mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
-
- card->pci_reset_ongoing = true;
- diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
- index 929aee2b0a60..edc739c542fe 100644
- --- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
- +++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
- @@ -21,7 +21,7 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
- DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 4"),
- },
- - .driver_data = 0,
- + .driver_data = (void *)QUIRK_FW_RST_D3COLD,
- },
- {
- .ident = "Surface Pro 5",
- @@ -30,7 +30,7 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
- DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "Surface_Pro_1796"),
- },
- - .driver_data = 0,
- + .driver_data = (void *)QUIRK_FW_RST_D3COLD,
- },
- {
- .ident = "Surface Pro 5 (LTE)",
- @@ -39,7 +39,7 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
- DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "Surface_Pro_1807"),
- },
- - .driver_data = 0,
- + .driver_data = (void *)QUIRK_FW_RST_D3COLD,
- },
- {
- .ident = "Surface Pro 6",
- @@ -47,7 +47,7 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
- DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 6"),
- },
- - .driver_data = 0,
- + .driver_data = (void *)QUIRK_FW_RST_D3COLD,
- },
- {
- .ident = "Surface Book 1",
- @@ -55,7 +55,7 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
- DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Book"),
- },
- - .driver_data = 0,
- + .driver_data = (void *)QUIRK_FW_RST_D3COLD,
- },
- {
- .ident = "Surface Book 2",
- @@ -63,7 +63,7 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
- DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Book 2"),
- },
- - .driver_data = 0,
- + .driver_data = (void *)QUIRK_FW_RST_D3COLD,
- },
- {
- .ident = "Surface Laptop 1",
- @@ -71,7 +71,7 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
- DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Laptop"),
- },
- - .driver_data = 0,
- + .driver_data = (void *)QUIRK_FW_RST_D3COLD,
- },
- {
- .ident = "Surface Laptop 2",
- @@ -79,7 +79,7 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
- DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Laptop 2"),
- },
- - .driver_data = 0,
- + .driver_data = (void *)QUIRK_FW_RST_D3COLD,
- },
- {
- .ident = "Surface 3",
- @@ -111,4 +111,61 @@ void mwifiex_initialize_quirks(struct pcie_service_card *card)
-
- if (!card->quirks)
- dev_info(&pdev->dev, "no quirks enabled\n");
- + if (card->quirks & QUIRK_FW_RST_D3COLD)
- + dev_info(&pdev->dev, "quirk reset_d3cold enabled\n");
- +}
- +
- +static void mwifiex_pcie_set_power_d3cold(struct pci_dev *pdev)
- +{
- + dev_info(&pdev->dev, "putting into D3cold...\n");
- +
- + pci_save_state(pdev);
- + if (pci_is_enabled(pdev))
- + pci_disable_device(pdev);
- + pci_set_power_state(pdev, PCI_D3cold);
- +}
- +
- +static int mwifiex_pcie_set_power_d0(struct pci_dev *pdev)
- +{
- + int ret;
- +
- + dev_info(&pdev->dev, "putting into D0...\n");
- +
- + pci_set_power_state(pdev, PCI_D0);
- + ret = pci_enable_device(pdev);
- + if (ret) {
- + dev_err(&pdev->dev, "pci_enable_device failed\n");
- + return ret;
- + }
- + pci_restore_state(pdev);
- +
- + return 0;
- +}
- +
- +int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev)
- +{
- + struct pci_dev *parent_pdev = pci_upstream_bridge(pdev);
- + int ret;
- +
- + /* Power-cycle (put into D3cold then D0) */
- + dev_info(&pdev->dev, "Using reset_d3cold quirk to perform FW reset\n");
- +
- + /* We need to perform power-cycle also for bridge of wifi because
- + * on some devices (e.g. Surface Book 1), the OS for some reasons
- + * can't know the real power state of the bridge.
- + * When tried to power-cycle only wifi, the reset failed with the
- + * following dmesg log:
- + * "Cannot transition to power state D0 for parent in D3hot".
- + */
- + mwifiex_pcie_set_power_d3cold(pdev);
- + mwifiex_pcie_set_power_d3cold(parent_pdev);
- +
- + ret = mwifiex_pcie_set_power_d0(parent_pdev);
- + if (ret)
- + return ret;
- + ret = mwifiex_pcie_set_power_d0(pdev);
- + if (ret)
- + return ret;
- +
- + return 0;
- }
- diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
- index 5326ae7e5671..8b9dcb5070d8 100644
- --- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
- +++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
- @@ -6,6 +6,7 @@
- #include "pcie.h"
-
- /* quirks */
- -// quirk flags can be added here
- +#define QUIRK_FW_RST_D3COLD BIT(0)
-
- void mwifiex_initialize_quirks(struct pcie_service_card *card);
- +int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev);
- --
- 2.29.2
- From b71f152c8b9f3b07bf64c00db1cc54808104fb9e Mon Sep 17 00:00:00 2001
- From: Tsuchiya Yuto <kitakar@gmail.com>
- Date: Tue, 29 Sep 2020 17:32:22 +0900
- Subject: [PATCH] mwifiex: pcie: add reset_wsid quirk for Surface 3
- This commit adds reset_wsid quirk and uses this quirk for Surface 3 on
- card reset.
- To reset mwifiex on Surface 3, it seems that calling the _DSM method
- exists in \_SB.WSID [1] device is required.
- On Surface 3, calling the _DSM method removes/re-probes the card by
- itself. So, need to place the reset function before performing FLR and
- skip performing any other reset-related works.
- Note that Surface Pro 3 also has the WSID device [2], but it seems to need
- more work. This commit only supports Surface 3 yet.
- [1] https://github.com/linux-surface/acpidumps/blob/05cba925f3a515f222acb5b3551a032ddde958fe/surface_3/dsdt.dsl#L11947-L12011
- [2] https://github.com/linux-surface/acpidumps/blob/05cba925f3a515f222acb5b3551a032ddde958fe/surface_pro_3/dsdt.dsl#L12164-L12216
- Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
- Patchset: wifi
- ---
- drivers/net/wireless/marvell/mwifiex/pcie.c | 10 +++
- .../wireless/marvell/mwifiex/pcie_quirks.c | 77 ++++++++++++++++++-
- .../wireless/marvell/mwifiex/pcie_quirks.h | 5 ++
- 3 files changed, 91 insertions(+), 1 deletion(-)
- diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
- index 45488c2bc1c1..daae572ce94e 100644
- --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
- +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
- @@ -2817,6 +2817,16 @@ static void mwifiex_pcie_card_reset_work(struct mwifiex_adapter *adapter)
- {
- struct pcie_service_card *card = adapter->card;
-
- + /* On Surface 3, reset_wsid method removes then re-probes card by
- + * itself. So, need to place it here and skip performing any other
- + * reset-related works.
- + */
- + if (card->quirks & QUIRK_FW_RST_WSID_S3) {
- + mwifiex_pcie_reset_wsid_quirk(card->dev);
- + /* skip performing any other reset-related works */
- + return;
- + }
- +
- /* We can't afford to wait here; remove() might be waiting on us. If we
- * can't grab the device lock, maybe we'll get another chance later.
- */
- diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
- index edc739c542fe..f0a6fa0a7ae5 100644
- --- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
- +++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
- @@ -9,10 +9,21 @@
- * down, or causes NULL ptr deref).
- */
-
- +#include <linux/acpi.h>
- #include <linux/dmi.h>
-
- #include "pcie_quirks.h"
-
- +/* For reset_wsid quirk */
- +#define ACPI_WSID_PATH "\\_SB.WSID"
- +#define WSID_REV 0x0
- +#define WSID_FUNC_WIFI_PWR_OFF 0x1
- +#define WSID_FUNC_WIFI_PWR_ON 0x2
- +/* WSID _DSM UUID: "534ea3bf-fcc2-4e7a-908f-a13978f0c7ef" */
- +static const guid_t wsid_dsm_guid =
- + GUID_INIT(0x534ea3bf, 0xfcc2, 0x4e7a,
- + 0x90, 0x8f, 0xa1, 0x39, 0x78, 0xf0, 0xc7, 0xef);
- +
- /* quirk table based on DMI matching */
- static const struct dmi_system_id mwifiex_quirk_table[] = {
- {
- @@ -87,7 +98,7 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
- DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface 3"),
- },
- - .driver_data = 0,
- + .driver_data = (void *)QUIRK_FW_RST_WSID_S3,
- },
- {
- .ident = "Surface Pro 3",
- @@ -113,6 +124,9 @@ void mwifiex_initialize_quirks(struct pcie_service_card *card)
- dev_info(&pdev->dev, "no quirks enabled\n");
- if (card->quirks & QUIRK_FW_RST_D3COLD)
- dev_info(&pdev->dev, "quirk reset_d3cold enabled\n");
- + if (card->quirks & QUIRK_FW_RST_WSID_S3)
- + dev_info(&pdev->dev,
- + "quirk reset_wsid for Surface 3 enabled\n");
- }
-
- static void mwifiex_pcie_set_power_d3cold(struct pci_dev *pdev)
- @@ -169,3 +183,64 @@ int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev)
-
- return 0;
- }
- +
- +int mwifiex_pcie_reset_wsid_quirk(struct pci_dev *pdev)
- +{
- + acpi_handle handle;
- + union acpi_object *obj;
- + acpi_status status;
- +
- + dev_info(&pdev->dev, "Using reset_wsid quirk to perform FW reset\n");
- +
- + status = acpi_get_handle(NULL, ACPI_WSID_PATH, &handle);
- + if (ACPI_FAILURE(status)) {
- + dev_err(&pdev->dev, "No ACPI handle for path %s\n",
- + ACPI_WSID_PATH);
- + return -ENODEV;
- + }
- +
- + if (!acpi_has_method(handle, "_DSM")) {
- + dev_err(&pdev->dev, "_DSM method not found\n");
- + return -ENODEV;
- + }
- +
- + if (!acpi_check_dsm(handle, &wsid_dsm_guid,
- + WSID_REV, WSID_FUNC_WIFI_PWR_OFF)) {
- + dev_err(&pdev->dev,
- + "_DSM method doesn't support wifi power off func\n");
- + return -ENODEV;
- + }
- +
- + if (!acpi_check_dsm(handle, &wsid_dsm_guid,
- + WSID_REV, WSID_FUNC_WIFI_PWR_ON)) {
- + dev_err(&pdev->dev,
- + "_DSM method doesn't support wifi power on func\n");
- + return -ENODEV;
- + }
- +
- + /* card will be removed immediately after this call on Surface 3 */
- + dev_info(&pdev->dev, "turning wifi off...\n");
- + obj = acpi_evaluate_dsm(handle, &wsid_dsm_guid,
- + WSID_REV, WSID_FUNC_WIFI_PWR_OFF,
- + NULL);
- + if (!obj) {
- + dev_err(&pdev->dev,
- + "device _DSM execution failed for turning wifi off\n");
- + return -EIO;
- + }
- + ACPI_FREE(obj);
- +
- + /* card will be re-probed immediately after this call on Surface 3 */
- + dev_info(&pdev->dev, "turning wifi on...\n");
- + obj = acpi_evaluate_dsm(handle, &wsid_dsm_guid,
- + WSID_REV, WSID_FUNC_WIFI_PWR_ON,
- + NULL);
- + if (!obj) {
- + dev_err(&pdev->dev,
- + "device _DSM execution failed for turning wifi on\n");
- + return -EIO;
- + }
- + ACPI_FREE(obj);
- +
- + return 0;
- +}
- diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
- index 8b9dcb5070d8..3ef7440418e3 100644
- --- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
- +++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
- @@ -7,6 +7,11 @@
-
- /* quirks */
- #define QUIRK_FW_RST_D3COLD BIT(0)
- +/* Surface 3 and Surface Pro 3 have the same _DSM method but need to
- + * be handled differently. Currently, only S3 is supported.
- + */
- +#define QUIRK_FW_RST_WSID_S3 BIT(1)
-
- void mwifiex_initialize_quirks(struct pcie_service_card *card);
- int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev);
- +int mwifiex_pcie_reset_wsid_quirk(struct pci_dev *pdev);
- --
- 2.29.2
- From 8436fce91900d6d49d815022e474eb49ce20af9b Mon Sep 17 00:00:00 2001
- From: Tsuchiya Yuto <kitakar@gmail.com>
- Date: Wed, 30 Sep 2020 18:08:24 +0900
- Subject: [PATCH] mwifiex: pcie: (OEMB) add quirk for Surface 3 with broken DMI
- table
- (made referring to http://git.osdn.net/view?p=android-x86/kernel.git;a=commitdiff;h=18e2e857c57633b25b3b4120f212224a108cd883)
- On some Surface 3, the DMI table gets corrupted for unknown reasons
- and breaks existing DMI matching used for device-specific quirks.
- This commit adds the (broken) DMI info for the affected Surface 3.
- On affected systems, DMI info will look like this:
- $ grep . /sys/devices/virtual/dmi/id/{bios_vendor,board_name,board_vendor,\
- chassis_vendor,product_name,sys_vendor}
- /sys/devices/virtual/dmi/id/bios_vendor:American Megatrends Inc.
- /sys/devices/virtual/dmi/id/board_name:OEMB
- /sys/devices/virtual/dmi/id/board_vendor:OEMB
- /sys/devices/virtual/dmi/id/chassis_vendor:OEMB
- /sys/devices/virtual/dmi/id/product_name:OEMB
- /sys/devices/virtual/dmi/id/sys_vendor:OEMB
- Expected:
- $ grep . /sys/devices/virtual/dmi/id/{bios_vendor,board_name,board_vendor,\
- chassis_vendor,product_name,sys_vendor}
- /sys/devices/virtual/dmi/id/bios_vendor:American Megatrends Inc.
- /sys/devices/virtual/dmi/id/board_name:Surface 3
- /sys/devices/virtual/dmi/id/board_vendor:Microsoft Corporation
- /sys/devices/virtual/dmi/id/chassis_vendor:Microsoft Corporation
- /sys/devices/virtual/dmi/id/product_name:Surface 3
- /sys/devices/virtual/dmi/id/sys_vendor:Microsoft Corporation
- Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
- Patchset: wifi
- ---
- drivers/net/wireless/marvell/mwifiex/pcie_quirks.c | 9 +++++++++
- 1 file changed, 9 insertions(+)
- diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
- index f0a6fa0a7ae5..34dcd84f02a6 100644
- --- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
- +++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
- @@ -100,6 +100,15 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
- },
- .driver_data = (void *)QUIRK_FW_RST_WSID_S3,
- },
- + {
- + .ident = "Surface 3",
- + .matches = {
- + DMI_EXACT_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
- + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "OEMB"),
- + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "OEMB"),
- + },
- + .driver_data = (void *)QUIRK_FW_RST_WSID_S3,
- + },
- {
- .ident = "Surface Pro 3",
- .matches = {
- --
- 2.29.2
- From 358752a3b7f02e10d03d71846b5c21a391582025 Mon Sep 17 00:00:00 2001
- From: Tsuchiya Yuto <kitakar@gmail.com>
- Date: Thu, 24 Sep 2020 01:56:29 +0900
- Subject: [PATCH] mwifiex: fix mwifiex_shutdown_sw() causing sw reset failure
- When FLR is performed but without fw reset for some reasons (e.g. on
- Surface devices, fw reset requires another quirk), it fails to reset
- properly. You can trigger the issue on such devices via debugfs entry
- for reset:
- $ echo 1 | sudo tee /sys/kernel/debug/mwifiex/mlan0/reset
- and the resulting dmesg log:
- mwifiex_pcie 0000:03:00.0: Resetting per request
- mwifiex_pcie 0000:03:00.0: info: successfully disconnected from [BSSID]: reason code 3
- mwifiex_pcie 0000:03:00.0: PREP_CMD: card is removed
- mwifiex_pcie 0000:03:00.0: deleting the crypto keys
- mwifiex_pcie 0000:03:00.0: PREP_CMD: card is removed
- mwifiex_pcie 0000:03:00.0: deleting the crypto keys
- mwifiex_pcie 0000:03:00.0: PREP_CMD: card is removed
- mwifiex_pcie 0000:03:00.0: deleting the crypto keys
- mwifiex_pcie 0000:03:00.0: PREP_CMD: card is removed
- mwifiex_pcie 0000:03:00.0: deleting the crypto keys
- mwifiex_pcie 0000:03:00.0: PREP_CMD: card is removed
- mwifiex_pcie 0000:03:00.0: deleting the crypto keys
- mwifiex_pcie 0000:03:00.0: PREP_CMD: card is removed
- mwifiex_pcie 0000:03:00.0: deleting the crypto keys
- mwifiex_pcie 0000:03:00.0: info: shutdown mwifiex...
- mwifiex_pcie 0000:03:00.0: PREP_CMD: card is removed
- mwifiex_pcie 0000:03:00.0: PREP_CMD: card is removed
- mwifiex_pcie 0000:03:00.0: WLAN FW already running! Skip FW dnld
- mwifiex_pcie 0000:03:00.0: WLAN FW is active
- mwifiex_pcie 0000:03:00.0: Unknown api_id: 4
- mwifiex_pcie 0000:03:00.0: info: MWIFIEX VERSION: mwifiex 1.0 (15.68.19.p21)
- mwifiex_pcie 0000:03:00.0: driver_version = mwifiex 1.0 (15.68.19.p21)
- mwifiex_pcie 0000:03:00.0: info: trying to associate to '[SSID]' bssid [BSSID]
- mwifiex_pcie 0000:03:00.0: info: associated to bssid [BSSID] successfully
- mwifiex_pcie 0000:03:00.0: cmd_wait_q terminated: -110
- mwifiex_pcie 0000:03:00.0: info: successfully disconnected from [BSSID]: reason code 15
- mwifiex_pcie 0000:03:00.0: cmd_wait_q terminated: -110
- mwifiex_pcie 0000:03:00.0: deleting the crypto keys
- mwifiex_pcie 0000:03:00.0: cmd_wait_q terminated: -110
- mwifiex_pcie 0000:03:00.0: deleting the crypto keys
- mwifiex_pcie 0000:03:00.0: cmd_wait_q terminated: -110
- mwifiex_pcie 0000:03:00.0: deleting the crypto keys
- [...]
- When comparing mwifiex_shutdown_sw() with mwifiex_pcie_remove(), it
- lacks mwifiex_init_shutdown_fw().
- This commit fixes mwifiex_shutdown_sw() by adding the missing
- mwifiex_init_shutdown_fw().
- Fixes: 4c5dae59d2e9 ("mwifiex: add PCIe function level reset support")
- Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
- Patchset: wifi
- ---
- drivers/net/wireless/marvell/mwifiex/main.c | 2 ++
- 1 file changed, 2 insertions(+)
- diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
- index 9ee5600351a7..5965999f1b9b 100644
- --- a/drivers/net/wireless/marvell/mwifiex/main.c
- +++ b/drivers/net/wireless/marvell/mwifiex/main.c
- @@ -1469,6 +1469,8 @@ int mwifiex_shutdown_sw(struct mwifiex_adapter *adapter)
- priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
- mwifiex_deauthenticate(priv, NULL);
-
- + mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
- +
- mwifiex_uninit_sw(adapter);
- adapter->is_up = false;
-
- --
- 2.29.2
- From c9e45a33790fda3ec588790e162bd2c1b95aa2ad Mon Sep 17 00:00:00 2001
- From: Tsuchiya Yuto <kitakar@gmail.com>
- Date: Thu, 24 Sep 2020 01:56:34 +0900
- Subject: [PATCH] mwifiex: pcie: use shutdown_sw()/reinit_sw() on
- suspend()/resume()
- There are issues with S0ix achievement and AP scanning after suspend
- with the current Host Sleep method.
- When using the Host Sleep method, it prevents the platform to reach S0ix
- during suspend. Also, after suspend, sometimes AP scanning won't work,
- resulting in non-working wifi.
- To fix such issues, perform shutdown_sw()/reinit_sw() instead of Host
- Sleep.
- As a side effect, this patch disables wakeups (means that Wake-On-WLAN
- can't be used anymore, if it was working before), and might also reset
- some internal states.
- Note that suspend() no longer checks if it's already suspended.
- With the previous Host Sleep method, the check was done by looking at
- adapter->hs_activated in mwifiex_enable_hs() [sta_ioctl.c], but not
- MWIFIEX_IS_SUSPENDED. So, what the previous method checked was instead
- Host Sleep state, not suspend itself. Therefore, there is no need to check
- the suspend state now.
- Also removed comment for suspend state check at top of suspend()
- accordingly.
- Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
- Patchset: wifi
- ---
- drivers/net/wireless/marvell/mwifiex/main.c | 4 +--
- drivers/net/wireless/marvell/mwifiex/pcie.c | 29 +++++++--------------
- 2 files changed, 12 insertions(+), 21 deletions(-)
- diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
- index 5965999f1b9b..74bf0076daec 100644
- --- a/drivers/net/wireless/marvell/mwifiex/main.c
- +++ b/drivers/net/wireless/marvell/mwifiex/main.c
- @@ -1453,7 +1453,7 @@ static void mwifiex_uninit_sw(struct mwifiex_adapter *adapter)
- }
-
- /*
- - * This function gets called during PCIe function level reset.
- + * This function can be used for shutting down the adapter SW.
- */
- int mwifiex_shutdown_sw(struct mwifiex_adapter *adapter)
- {
- @@ -1481,7 +1481,7 @@ int mwifiex_shutdown_sw(struct mwifiex_adapter *adapter)
- }
- EXPORT_SYMBOL_GPL(mwifiex_shutdown_sw);
-
- -/* This function gets called during PCIe function level reset. Required
- +/* This function can be used for reinitting the adapter SW. Required
- * code is extracted from mwifiex_add_card()
- */
- int
- diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
- index daae572ce94e..b46d56389c3b 100644
- --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
- +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
- @@ -145,8 +145,7 @@ static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter)
- * registered functions must have drivers with suspend and resume
- * methods. Failing that the kernel simply removes the whole card.
- *
- - * If already not suspended, this function allocates and sends a host
- - * sleep activate request to the firmware and turns off the traffic.
- + * This function shuts down the adapter.
- */
- static int mwifiex_pcie_suspend(struct device *dev)
- {
- @@ -154,31 +153,21 @@ static int mwifiex_pcie_suspend(struct device *dev)
- struct pcie_service_card *card = dev_get_drvdata(dev);
-
-
- - /* Might still be loading firmware */
- - wait_for_completion(&card->fw_done);
- -
- adapter = card->adapter;
- if (!adapter) {
- dev_err(dev, "adapter is not valid\n");
- return 0;
- }
-
- - mwifiex_enable_wake(adapter);
- -
- - /* Enable the Host Sleep */
- - if (!mwifiex_enable_hs(adapter)) {
- + /* Shut down SW */
- + if (mwifiex_shutdown_sw(adapter)) {
- mwifiex_dbg(adapter, ERROR,
- "cmd: failed to suspend\n");
- - clear_bit(MWIFIEX_IS_HS_ENABLING, &adapter->work_flags);
- - mwifiex_disable_wake(adapter);
- return -EFAULT;
- }
-
- - flush_workqueue(adapter->workqueue);
- -
- /* Indicate device suspended */
- set_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags);
- - clear_bit(MWIFIEX_IS_HS_ENABLING, &adapter->work_flags);
-
- return 0;
- }
- @@ -188,13 +177,13 @@ static int mwifiex_pcie_suspend(struct device *dev)
- * registered functions must have drivers with suspend and resume
- * methods. Failing that the kernel simply removes the whole card.
- *
- - * If already not resumed, this function turns on the traffic and
- - * sends a host sleep cancel request to the firmware.
- + * If already not resumed, this function reinits the adapter.
- */
- static int mwifiex_pcie_resume(struct device *dev)
- {
- struct mwifiex_adapter *adapter;
- struct pcie_service_card *card = dev_get_drvdata(dev);
- + int ret;
-
-
- if (!card->adapter) {
- @@ -212,9 +201,11 @@ static int mwifiex_pcie_resume(struct device *dev)
-
- clear_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags);
-
- - mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
- - MWIFIEX_ASYNC_CMD);
- - mwifiex_disable_wake(adapter);
- + ret = mwifiex_reinit_sw(adapter);
- + if (ret)
- + dev_err(dev, "reinit failed: %d\n", ret);
- + else
- + mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
-
- return 0;
- }
- --
- 2.29.2
- From cb39f7580b59a883fe26f9de928c5c45620cae70 Mon Sep 17 00:00:00 2001
- From: Tsuchiya Yuto <kitakar@gmail.com>
- Date: Mon, 24 Aug 2020 17:11:35 +0900
- Subject: [PATCH] mwifiex: pcie: add enable_device_dump module parameter
- The devicve_dump may take a little bit long time and users may want to
- disable the dump for daily usage.
- This commit adds a new module parameter and disables device_dump by
- default.
- Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
- Patchset: wifi
- ---
- drivers/net/wireless/marvell/mwifiex/pcie.c | 11 +++++++++++
- 1 file changed, 11 insertions(+)
- diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
- index b46d56389c3b..1847a0274991 100644
- --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
- +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
- @@ -34,6 +34,11 @@
-
- static struct mwifiex_if_ops pcie_ops;
-
- +static bool enable_device_dump;
- +module_param(enable_device_dump, bool, 0644);
- +MODULE_PARM_DESC(enable_device_dump,
- + "enable device_dump (default: disabled)");
- +
- static const struct of_device_id mwifiex_pcie_of_match_table[] = {
- { .compatible = "pci11ab,2b42" },
- { .compatible = "pci1b4b,2b42" },
- @@ -2791,6 +2796,12 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
-
- static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter)
- {
- + if (!enable_device_dump) {
- + mwifiex_dbg(adapter, MSG,
- + "device_dump is disabled by module parameter\n");
- + return;
- + }
- +
- adapter->devdump_data = vzalloc(MWIFIEX_FW_DUMP_SIZE);
- if (!adapter->devdump_data) {
- mwifiex_dbg(adapter, ERROR,
- --
- 2.29.2
- From 5d6178c68fcf14f9daacdbf7c23902ffe8fa5831 Mon Sep 17 00:00:00 2001
- From: Tsuchiya Yuto <kitakar@gmail.com>
- Date: Sun, 4 Oct 2020 00:11:49 +0900
- Subject: [PATCH] mwifiex: pcie: disable bridge_d3 for Surface gen4+
- Currently, mwifiex fw will crash after suspend on recent kernel series.
- On Windows, it seems that the root port of wifi will never enter D3 state
- (stay on D0 state). And on Linux, disabling the D3 state for the
- bridge fixes fw crashing after suspend.
- This commit disables the D3 state of root port on driver initialization
- and fixes fw crashing after suspend.
- Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
- Patchset: wifi
- ---
- drivers/net/wireless/marvell/mwifiex/pcie.c | 7 +++++
- .../wireless/marvell/mwifiex/pcie_quirks.c | 27 +++++++++++++------
- .../wireless/marvell/mwifiex/pcie_quirks.h | 1 +
- 3 files changed, 27 insertions(+), 8 deletions(-)
- diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
- index 1847a0274991..3bd39d9ba3de 100644
- --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
- +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
- @@ -226,6 +226,7 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
- {
- struct pcie_service_card *card;
- + struct pci_dev *parent_pdev = pci_upstream_bridge(pdev);
- int ret;
-
- pr_debug("info: vendor=0x%4.04X device=0x%4.04X rev=%d\n",
- @@ -267,6 +268,12 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
- return -1;
- }
-
- + /* disable bridge_d3 for Surface gen4+ devices to fix fw crashing
- + * after suspend
- + */
- + if (card->quirks & QUIRK_NO_BRIDGE_D3)
- + parent_pdev->bridge_d3 = false;
- +
- return 0;
- }
-
- diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
- index 34dcd84f02a6..a2aeb2af907e 100644
- --- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
- +++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
- @@ -32,7 +32,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
- DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 4"),
- },
- - .driver_data = (void *)QUIRK_FW_RST_D3COLD,
- + .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
- + QUIRK_NO_BRIDGE_D3),
- },
- {
- .ident = "Surface Pro 5",
- @@ -41,7 +42,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
- DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "Surface_Pro_1796"),
- },
- - .driver_data = (void *)QUIRK_FW_RST_D3COLD,
- + .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
- + QUIRK_NO_BRIDGE_D3),
- },
- {
- .ident = "Surface Pro 5 (LTE)",
- @@ -50,7 +52,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
- DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "Surface_Pro_1807"),
- },
- - .driver_data = (void *)QUIRK_FW_RST_D3COLD,
- + .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
- + QUIRK_NO_BRIDGE_D3),
- },
- {
- .ident = "Surface Pro 6",
- @@ -58,7 +61,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
- DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 6"),
- },
- - .driver_data = (void *)QUIRK_FW_RST_D3COLD,
- + .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
- + QUIRK_NO_BRIDGE_D3),
- },
- {
- .ident = "Surface Book 1",
- @@ -66,7 +70,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
- DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Book"),
- },
- - .driver_data = (void *)QUIRK_FW_RST_D3COLD,
- + .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
- + QUIRK_NO_BRIDGE_D3),
- },
- {
- .ident = "Surface Book 2",
- @@ -74,7 +79,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
- DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Book 2"),
- },
- - .driver_data = (void *)QUIRK_FW_RST_D3COLD,
- + .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
- + QUIRK_NO_BRIDGE_D3),
- },
- {
- .ident = "Surface Laptop 1",
- @@ -82,7 +88,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
- DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Laptop"),
- },
- - .driver_data = (void *)QUIRK_FW_RST_D3COLD,
- + .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
- + QUIRK_NO_BRIDGE_D3),
- },
- {
- .ident = "Surface Laptop 2",
- @@ -90,7 +97,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
- DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Laptop 2"),
- },
- - .driver_data = (void *)QUIRK_FW_RST_D3COLD,
- + .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
- + QUIRK_NO_BRIDGE_D3),
- },
- {
- .ident = "Surface 3",
- @@ -136,6 +144,9 @@ void mwifiex_initialize_quirks(struct pcie_service_card *card)
- if (card->quirks & QUIRK_FW_RST_WSID_S3)
- dev_info(&pdev->dev,
- "quirk reset_wsid for Surface 3 enabled\n");
- + if (card->quirks & QUIRK_NO_BRIDGE_D3)
- + dev_info(&pdev->dev,
- + "quirk no_brigde_d3 enabled\n");
- }
-
- static void mwifiex_pcie_set_power_d3cold(struct pci_dev *pdev)
- diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
- index 3ef7440418e3..a95ebac06e13 100644
- --- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
- +++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
- @@ -11,6 +11,7 @@
- * be handled differently. Currently, only S3 is supported.
- */
- #define QUIRK_FW_RST_WSID_S3 BIT(1)
- +#define QUIRK_NO_BRIDGE_D3 BIT(2)
-
- void mwifiex_initialize_quirks(struct pcie_service_card *card);
- int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev);
- --
- 2.29.2
- From c87cf357966a2047e0159e59e3d1a1fedb41ac22 Mon Sep 17 00:00:00 2001
- From: Tsuchiya Yuto <kitakar@gmail.com>
- Date: Sun, 4 Oct 2020 00:25:48 +0900
- Subject: [PATCH] mwifiex: add allow_ps_mode module parameter
- This commit adds the allow_ps_mode module parameter and set it false
- (disallowed) by default, to make ps_mode (power_save) control easier.
- On some setups (e.g., with 5GHz AP), power_save causes connection
- completely unstable. So, we need to disable it. However, userspace tools
- may try to enable it. For this reason, we need to tell userspace that
- power_save is disallowed by default.
- When this parameter is set to false, changing the power_save mode will
- be disallowed like the following:
- $ sudo iw dev mlan0 set power_save on
- command failed: Operation not permitted (-1)
- Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
- Patchset: wifi
- ---
- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 16 ++++++++++++++++
- 1 file changed, 16 insertions(+)
- diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
- index 96848fa0e417..786f7a197613 100644
- --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
- +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
- @@ -25,6 +25,11 @@
- static char *reg_alpha2;
- module_param(reg_alpha2, charp, 0);
-
- +static bool allow_ps_mode;
- +module_param(allow_ps_mode, bool, 0644);
- +MODULE_PARM_DESC(allow_ps_mode,
- + "allow WiFi power management to be enabled. (default: disallowed)");
- +
- static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = {
- {
- .max = MWIFIEX_MAX_BSS_NUM,
- @@ -435,6 +440,17 @@ mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy,
-
- ps_mode = enabled;
-
- + /* Allow ps_mode to be enabled only when allow_ps_mode is true */
- + if (ps_mode && !allow_ps_mode) {
- + mwifiex_dbg(priv->adapter, MSG,
- + "Enabling ps_mode disallowed by modparam\n");
- +
- + /* Return -EPERM to inform userspace tools that setting
- + * power_save to be enabled is not permitted.
- + */
- + return -EPERM;
- + }
- +
- return mwifiex_drv_set_power(priv, &ps_mode);
- }
-
- --
- 2.29.2
- From 099df989cf42ced34fd67f725771678d45cdb17b Mon Sep 17 00:00:00 2001
- From: Tsuchiya Yuto <kitakar@gmail.com>
- Date: Sun, 4 Oct 2020 00:38:48 +0900
- Subject: [PATCH] mwifiex: print message when changing ps_mode
- Users may want to know the ps_mode state change (e.g., diagnosing
- connection issues). This commit adds the print when changing ps_mode.
- Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
- Patchset: wifi
- ---
- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 7 +++++++
- 1 file changed, 7 insertions(+)
- diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
- index 786f7a197613..8f4b8bc5ff03 100644
- --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
- +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
- @@ -451,6 +451,13 @@ mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy,
- return -EPERM;
- }
-
- + if (ps_mode)
- + mwifiex_dbg(priv->adapter, MSG,
- + "Enabling ps_mode, disable if unstable.\n");
- + else
- + mwifiex_dbg(priv->adapter, MSG,
- + "Disabling ps_mode.\n");
- +
- return mwifiex_drv_set_power(priv, &ps_mode);
- }
-
- --
- 2.29.2
- From e69efbe8054c16a7af76ac8c5a9bcec0a2c0eb7e Mon Sep 17 00:00:00 2001
- From: Tsuchiya Yuto <kitakar@gmail.com>
- Date: Sun, 4 Oct 2020 00:59:37 +0900
- Subject: [PATCH] mwifiex: disable ps_mode explicitly by default instead
- At least on Surface devices, the ps_mode causes connection unstable,
- especially with 5GHz APs. Then, it eventually causes fw crashing.
- This commit disables ps_mode by default instead of enabling it.
- Required code is extracted from mwifiex_drv_set_power().
- Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
- Patchset: wifi
- ---
- drivers/net/wireless/marvell/mwifiex/sta_cmd.c | 11 ++++++++---
- 1 file changed, 8 insertions(+), 3 deletions(-)
- diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
- index d3a968ef21ef..9b7b52fbc9c4 100644
- --- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
- +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
- @@ -2333,14 +2333,19 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
- return -1;
-
- if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) {
- - /* Enable IEEE PS by default */
- - priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP;
- + /* Disable IEEE PS by default */
- + priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM;
- ret = mwifiex_send_cmd(priv,
- HostCmd_CMD_802_11_PS_MODE_ENH,
- - EN_AUTO_PS, BITMAP_STA_PS, NULL,
- + DIS_AUTO_PS, BITMAP_STA_PS, NULL,
- true);
- if (ret)
- return -1;
- + ret = mwifiex_send_cmd(priv,
- + HostCmd_CMD_802_11_PS_MODE_ENH,
- + GET_PS, 0, NULL, false);
- + if (ret)
- + return -1;
- }
-
- if (drcs) {
- --
- 2.29.2
|