This patch implements pre and post FLR handlers to support PCIe FLR
functionality. Software cleanup is performed in pre-FLR whereas
firmware is downloaded and software is re-initialised in
post-FLR handler.
Following command triggers FLR.
echo "1" > /sys/bus/pci/devices/$NUMBER/reset
This feature can be used as a recovery mechanism when firmware gets
hang.
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/marvell/mwifiex/main.c | 242 ++++++++++++++++++++++++++--
drivers/net/wireless/marvell/mwifiex/main.h | 3 +
drivers/net/wireless/marvell/mwifiex/pcie.c | 136 +++++++++++++++-
drivers/net/wireless/marvell/mwifiex/pcie.h | 1 +
4 files changed, 365 insertions(+), 17 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index 7fbf74b..0181247 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -490,9 +490,11 @@ static void mwifiex_free_adapter(struct mwifiex_adapter *adapter)
*/
static void mwifiex_terminate_workqueue(struct mwifiex_adapter *adapter)
{
- flush_workqueue(adapter->workqueue);
- destroy_workqueue(adapter->workqueue);
- adapter->workqueue = NULL;
+ if (adapter->workqueue) {
+ flush_workqueue(adapter->workqueue);
+ destroy_workqueue(adapter->workqueue);
+ adapter->workqueue = NULL;
+ }
if (adapter->rx_workqueue) {
flush_workqueue(adapter->rx_workqueue);
@@ -571,10 +573,13 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
}
priv = adapter->priv[MWIFIEX_BSS_ROLE_STA];
- if (mwifiex_register_cfg80211(adapter)) {
- mwifiex_dbg(adapter, ERROR,
- "cannot register with cfg80211\n");
- goto err_init_fw;
+
+ if (!adapter->wiphy) {
+ if (mwifiex_register_cfg80211(adapter)) {
+ mwifiex_dbg(adapter, ERROR,
+ "cannot register with cfg80211\n");
+ goto err_init_fw;
+ }
}
if (mwifiex_init_channel_scan_gap(adapter)) {
@@ -668,7 +673,8 @@ done:
/*
* This function initializes the hardware and gets firmware.
*/
-static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter)
+static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter,
+ bool req_fw_nowait)
{
int ret;
@@ -683,12 +689,25 @@ static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter)
return -1;
}
}
- ret = request_firmware_nowait(THIS_MODULE, 1, adapter->fw_name,
- adapter->dev, GFP_KERNEL, adapter,
- mwifiex_fw_dpc);
- if (ret < 0)
- mwifiex_dbg(adapter, ERROR,
- "request_firmware_nowait error %d\n", ret);
+
+ if (req_fw_nowait) {
+ ret = request_firmware_nowait(THIS_MODULE, 1, adapter->fw_name,
+ adapter->dev, GFP_KERNEL, adapter,
+ mwifiex_fw_dpc);
+ if (ret < 0)
+ mwifiex_dbg(adapter, ERROR,
+ "request_firmware_nowait error %d\n", ret);
+ } else {
+ ret = request_firmware(&adapter->firmware,
+ adapter->fw_name,
+ adapter->dev);
+ if (ret < 0)
+ mwifiex_dbg(adapter, ERROR,
+ "request_firmware error %d\n", ret);
+ else
+ mwifiex_fw_dpc(adapter->firmware, (void *)adapter);
+ }
+
return ret;
}
@@ -1338,6 +1357,199 @@ static void mwifiex_main_work_queue(struct work_struct *work)
}
/*
+ * This function gets called during PCIe function level reset. Required
+ * code is extracted from mwifiex_remove_card()
+ */
+static int
+mwifiex_shutdown_sw(struct mwifiex_adapter *adapter, struct semaphore *sem)
+{
+ struct mwifiex_private *priv;
+ int i;
+
+ if (down_interruptible(sem))
+ goto exit_sem_err;
+
+ if (!adapter)
+ goto exit_remove;
+
+ priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
+ mwifiex_deauthenticate(priv, NULL);
+
+ /* We can no longer handle interrupts once we start doing the teardown
+ * below.
+ */
+ if (adapter->if_ops.disable_int)
+ adapter->if_ops.disable_int(adapter);
+
+ adapter->surprise_removed = true;
+ mwifiex_terminate_workqueue(adapter);
+
+ /* Stop data */
+ for (i = 0; i < adapter->priv_num; i++) {
+ priv = adapter->priv[i];
+ if (priv && priv->netdev) {
+ mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+ if (netif_carrier_ok(priv->netdev))
+ netif_carrier_off(priv->netdev);
+ netif_device_detach(priv->netdev);
+ }
+ }
+
+ mwifiex_dbg(adapter, CMD, "cmd: calling mwifiex_shutdown_drv...\n");
+ adapter->init_wait_q_woken = false;
+
+ if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
+ wait_event_interruptible(adapter->init_wait_q,
+ adapter->init_wait_q_woken);
+ if (adapter->if_ops.down_dev)
+ adapter->if_ops.down_dev(adapter);
+
+ mwifiex_dbg(adapter, CMD, "cmd: mwifiex_shutdown_drv done\n");
+ if (atomic_read(&adapter->rx_pending) ||
+ atomic_read(&adapter->tx_pending) ||
+ atomic_read(&adapter->cmd_pending)) {
+ mwifiex_dbg(adapter, ERROR,
+ "rx_pending=%d, tx_pending=%d,\t"
+ "cmd_pending=%d\n",
+ atomic_read(&adapter->rx_pending),
+ atomic_read(&adapter->tx_pending),
+ atomic_read(&adapter->cmd_pending));
+ }
+
+ for (i = 0; i < adapter->priv_num; i++) {
+ priv = adapter->priv[i];
+ if (!priv)
+ continue;
+ rtnl_lock();
+ if (priv->netdev &&
+ priv->wdev.iftype != NL80211_IFTYPE_UNSPECIFIED)
+ mwifiex_del_virtual_intf(adapter->wiphy, &priv->wdev);
+ rtnl_unlock();
+ }
+
+exit_remove:
+ up(sem);
+exit_sem_err:
+ mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
+ return 0;
+}
+
+/* This function gets called during PCIe function level reset. Required
+ * code is extracted from mwifiex_add_card()
+ */
+static int
+mwifiex_reinit_sw(struct mwifiex_adapter *adapter, struct semaphore *sem,
+ struct mwifiex_if_ops *if_ops, u8 iface_type)
+{
+ char fw_name[32];
+ struct pcie_service_card *card = adapter->card;
+
+ if (down_interruptible(sem))
+ goto exit_sem_err;
+
+ mwifiex_init_lock_list(adapter);
+ if (adapter->if_ops.up_dev)
+ adapter->if_ops.up_dev(adapter);
+
+ adapter->iface_type = iface_type;
+ adapter->card_sem = sem;
+
+ adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
+ adapter->surprise_removed = false;
+ init_waitqueue_head(&adapter->init_wait_q);
+ adapter->is_suspended = false;
+ adapter->hs_activated = false;
+ init_waitqueue_head(&adapter->hs_activate_wait_q);
+ init_waitqueue_head(&adapter->cmd_wait_q.wait);
+ adapter->cmd_wait_q.status = 0;
+ adapter->scan_wait_q_woken = false;
+
+ if ((num_possible_cpus() > 1) || adapter->iface_type == MWIFIEX_USB)
+ adapter->rx_work_enabled = true;
+
+ adapter->workqueue =
+ alloc_workqueue("MWIFIEX_WORK_QUEUE",
+ WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
+ if (!adapter->workqueue)
+ goto err_kmalloc;
+
+ INIT_WORK(&adapter->main_work, mwifiex_main_work_queue);
+
+ if (adapter->rx_work_enabled) {
+ adapter->rx_workqueue = alloc_workqueue("MWIFIEX_RX_WORK_QUEUE",
+ WQ_HIGHPRI |
+ WQ_MEM_RECLAIM |
+ WQ_UNBOUND, 1);
+ if (!adapter->rx_workqueue)
+ goto err_kmalloc;
+ INIT_WORK(&adapter->rx_work, mwifiex_rx_work_queue);
+ }
+
+ /* Register the device. Fill up the private data structure with
+ * relevant information from the card. Some code extracted from
+ * mwifiex_register_dev()
+ */
+ mwifiex_dbg(adapter, INFO, "%s, mwifiex_init_hw_fw()...\n", __func__);
+ strcpy(fw_name, adapter->fw_name);
+ strcpy(adapter->fw_name, PCIE8997_DEFAULT_WIFIFW_NAME);
+
+ adapter->tx_buf_size = card->pcie.tx_buf_size;
+ adapter->ext_scan = card->pcie.can_ext_scan;
+ if (mwifiex_init_hw_fw(adapter, false)) {
+ strcpy(adapter->fw_name, fw_name);
+ mwifiex_dbg(adapter, ERROR,
+ "%s: firmware init failed\n", __func__);
+ goto err_init_fw;
+ }
+ strcpy(adapter->fw_name, fw_name);
+ mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
+ up(sem);
+ return 0;
+
+err_init_fw:
+ mwifiex_dbg(adapter, ERROR, "info: %s: unregister device\n", __func__);
+ if (adapter->if_ops.unregister_dev)
+ adapter->if_ops.unregister_dev(adapter);
+ if (adapter->hw_status == MWIFIEX_HW_STATUS_READY) {
+ mwifiex_dbg(adapter, ERROR,
+ "info: %s: shutdown mwifiex\n", __func__);
+ adapter->init_wait_q_woken = false;
+
+ if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
+ wait_event_interruptible(adapter->init_wait_q,
+ adapter->init_wait_q_woken);
+ }
+
+err_kmalloc:
+ mwifiex_terminate_workqueue(adapter);
+ adapter->surprise_removed = true;
+ up(sem);
+exit_sem_err:
+ mwifiex_dbg(adapter, INFO, "%s, error\n", __func__);
+
+ return -1;
+}
+
+/* This function processes pre and post PCIe function level resets.
+ * It performs software cleanup without touching PCIe specific code.
+ * Also, during initialization PCIe stuff is skipped.
+ */
+void mwifiex_do_flr(struct mwifiex_adapter *adapter, bool prepare)
+{
+ struct mwifiex_if_ops if_ops;
+
+ if (!prepare) {
+ mwifiex_reinit_sw(adapter, adapter->card_sem, &if_ops,
+ adapter->iface_type);
+ } else {
+ memcpy(&if_ops, &adapter->if_ops,
+ sizeof(struct mwifiex_if_ops));
+ mwifiex_shutdown_sw(adapter, adapter->card_sem);
+ }
+}
+EXPORT_SYMBOL_GPL(mwifiex_do_flr);
+
+/*
* This function adds the card.
*
* This function follows the following major steps to set up the device -
@@ -1408,7 +1620,7 @@ mwifiex_add_card(void *card, struct semaphore *sem,
goto err_registerdev;
}
- if (mwifiex_init_hw_fw(adapter)) {
+ if (mwifiex_init_hw_fw(adapter, true)) {
pr_err("%s: firmware init failed\n", __func__);
goto err_init_fw;
}
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index fcc2af35..2d32768 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -829,6 +829,8 @@ struct mwifiex_if_ops {
void (*deaggr_pkt)(struct mwifiex_adapter *, struct sk_buff *);
void (*multi_port_resync)(struct mwifiex_adapter *);
bool (*is_port_ready)(struct mwifiex_private *);
+ void (*down_dev)(struct mwifiex_adapter *);
+ void (*up_dev)(struct mwifiex_adapter *);
};
struct mwifiex_adapter {
@@ -1628,4 +1630,5 @@ void mwifiex_debugfs_remove(void);
void mwifiex_dev_debugfs_init(struct mwifiex_private *priv);
void mwifiex_dev_debugfs_remove(struct mwifiex_private *priv);
#endif
+void mwifiex_do_flr(struct mwifiex_adapter *adapter, bool prepare);
#endif /* !_MWIFIEX_MAIN_H_ */
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index a6af85d..81bceef 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -277,6 +277,52 @@ static const struct pci_device_id mwifiex_ids[] = {
MODULE_DEVICE_TABLE(pci, mwifiex_ids);
+static void mwifiex_pcie_reset_notify(struct pci_dev *pdev, bool prepare)
+{
+ struct mwifiex_adapter *adapter;
+ struct pcie_service_card *card;
+
+ if (!pdev) {
+ pr_err("%s: PCIe device is not specified\n", __func__);
+ return;
+ }
+
+ card = (struct pcie_service_card *)pci_get_drvdata(pdev);
+ if (!card || !card->adapter) {
+ pr_err("%s: Card or adapter structure is not valid (%ld)\n",
+ __func__, (long)card);
+ return;
+ }
+
+ adapter = card->adapter;
+ mwifiex_dbg(adapter, INFO,
+ "%s: vendor=0x%4.04x device=0x%4.04x rev=%d %s\n",
+ __func__, pdev->vendor, pdev->device,
+ pdev->revision,
+ prepare ? "Pre-FLR" : "Post-FLR");
+
+ if (prepare) {
+ /* Kernel would be performing FLR after this notification.
+ * Cleanup all software without cleaning anything related to
+ * PCIe and HW.
+ */
+ mwifiex_do_flr(adapter, prepare);
+ adapter->surprise_removed = true;
+ } else {
+ /* Kernel stores and restores PCIe function context before and
+ * after performing FLR respectively. Reconfigure the software
+ * and firmware including firmware redownload
+ */
+ adapter->surprise_removed = false;
+ mwifiex_do_flr(adapter, prepare);
+ }
+ mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
+}
+
+static const struct pci_error_handlers mwifiex_pcie_err_handler[] = {
+ { .reset_notify = mwifiex_pcie_reset_notify, },
+};
+
#ifdef CONFIG_PM_SLEEP
/* Power Management Hooks */
static SIMPLE_DEV_PM_OPS(mwifiex_pcie_pm_ops, mwifiex_pcie_suspend,
@@ -295,6 +341,7 @@ static struct pci_driver __refdata mwifiex_pcie = {
},
#endif
.shutdown = mwifiex_pcie_shutdown,
+ .err_handler = mwifiex_pcie_err_handler,
};
/*
@@ -2952,7 +2999,6 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
- const struct mwifiex_pcie_card_reg *reg;
struct pci_dev *pdev;
int i;
@@ -2976,8 +3022,90 @@ static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
if (card->msi_enable)
pci_disable_msi(pdev);
}
+ }
+}
- reg = card->pcie.reg;
+/* This function initializes the PCI-E host memory space, WCB rings, etc.
+ *
+ * The following initializations steps are followed -
+ * - Allocate TXBD ring buffers
+ * - Allocate RXBD ring buffers
+ * - Allocate event BD ring buffers
+ * - Allocate command response ring buffer
+ * - Allocate sleep cookie buffer
+ * Part of mwifiex_pcie_init(), not reset the PCIE registers
+ */
+static void mwifiex_pcie_up_dev(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ int ret;
+ struct pci_dev *pdev = card->dev;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
+ card->cmdrsp_buf = NULL;
+ ret = mwifiex_pcie_create_txbd_ring(adapter);
+ if (ret) {
+ mwifiex_dbg(adapter, ERROR, "Failed to create txbd ring\n");
+ goto err_cre_txbd;
+ }
+
+ ret = mwifiex_pcie_create_rxbd_ring(adapter);
+ if (ret) {
+ mwifiex_dbg(adapter, ERROR, "Failed to create rxbd ring\n");
+ goto err_cre_rxbd;
+ }
+
+ ret = mwifiex_pcie_create_evtbd_ring(adapter);
+ if (ret) {
+ mwifiex_dbg(adapter, ERROR, "Failed to create evtbd ring\n");
+ goto err_cre_evtbd;
+ }
+
+ ret = mwifiex_pcie_alloc_cmdrsp_buf(adapter);
+ if (ret) {
+ mwifiex_dbg(adapter, ERROR, "Failed to allocate cmdbuf buffer\n");
+ goto err_alloc_cmdbuf;
+ }
+
+ if (reg->sleep_cookie) {
+ ret = mwifiex_pcie_alloc_sleep_cookie_buf(adapter);
+ if (ret) {
+ mwifiex_dbg(adapter, ERROR, "Failed to allocate sleep_cookie buffer\n");
+ goto err_alloc_cookie;
+ }
+ } else {
+ card->sleep_cookie_vbase = NULL;
+ }
+ return;
+
+err_alloc_cookie:
+ mwifiex_pcie_delete_cmdrsp_buf(adapter);
+err_alloc_cmdbuf:
+ mwifiex_pcie_delete_evtbd_ring(adapter);
+err_cre_evtbd:
+ mwifiex_pcie_delete_rxbd_ring(adapter);
+err_cre_rxbd:
+ mwifiex_pcie_delete_txbd_ring(adapter);
+err_cre_txbd:
+ pci_iounmap(pdev, card->pci_mmap1);
+}
+
+/* This function cleans up the PCI-E host memory space.
+ * Some code is extracted from mwifiex_unregister_dev()
+ *
+ */
+static void mwifiex_pcie_down_dev(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
+ if (mwifiex_write_reg(adapter, reg->drv_rdy, 0x00000000))
+ mwifiex_dbg(adapter, ERROR, "Failed to write driver not-ready signature\n");
+
+ adapter->seq_num = 0;
+ adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K;
+
+ if (card) {
if (reg->sleep_cookie)
mwifiex_pcie_delete_sleep_cookie_buf(adapter);
@@ -2987,6 +3115,8 @@ static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
mwifiex_pcie_delete_txbd_ring(adapter);
card->cmdrsp_buf = NULL;
}
+
+ return;
}
static struct mwifiex_if_ops pcie_ops = {
@@ -3013,6 +3143,8 @@ static struct mwifiex_if_ops pcie_ops = {
.clean_pcie_ring = mwifiex_clean_pcie_ring_buf,
.reg_dump = mwifiex_pcie_reg_dump,
.device_dump = mwifiex_pcie_device_dump,
+ .down_dev = mwifiex_pcie_down_dev,
+ .up_dev = mwifiex_pcie_up_dev,
};
/*
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h
index f05061c..f6992f0 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.h
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.h
@@ -37,6 +37,7 @@
#define PCIEUART8997_FW_NAME_V2 "mrvl/pcieuart8997_combo_v2.bin"
#define PCIEUSB8997_FW_NAME_Z "mrvl/pcieusb8997_combo.bin"
#define PCIEUSB8997_FW_NAME_V2 "mrvl/pcieusb8997_combo_v2.bin"
+#define PCIE8997_DEFAULT_WIFIFW_NAME "mrvl/pcie8997_wlan.bin"
#define PCIE_VENDOR_ID_MARVELL (0x11ab)
#define PCIE_VENDOR_ID_V2_MARVELL (0x1b4b)
--
1.9.1
SGkgS2FsbGUsDQoNCj4gRnJvbTogbGludXgtd2lyZWxlc3Mtb3duZXJAdmdlci5rZXJuZWwub3Jn
IFttYWlsdG86bGludXgtd2lyZWxlc3MtDQo+IG93bmVyQHZnZXIua2VybmVsLm9yZ10gT24gQmVo
YWxmIE9mIEthbGxlIFZhbG8NCj4gU2VudDogU2F0dXJkYXksIFNlcHRlbWJlciAwMywgMjAxNiA5
OjEwIFBNDQo+IFRvOiBBbWl0a3VtYXIgS2Fyd2FyDQo+IENjOiBsaW51eC13aXJlbGVzc0B2Z2Vy
Lmtlcm5lbC5vcmc7IEFtaXRrdW1hciBLYXJ3YXINCj4gU3ViamVjdDogUmU6IG13aWZpZXg6IGFk
ZCBQQ0llIGZ1bmN0aW9uIGxldmVsIHJlc2V0IHN1cHBvcnQNCj4gDQo+IEFtaXRrdW1hciBLYXJ3
YXIgPGFrYXJ3YXJAbWFydmVsbC5jb20+IHdyb3RlOg0KPiA+IFRoaXMgcGF0Y2ggaW1wbGVtZW50
cyBwcmUgYW5kIHBvc3QgRkxSIGhhbmRsZXJzIHRvIHN1cHBvcnQgUENJZSBGTFINCj4gPiBmdW5j
dGlvbmFsaXR5LiBTb2Z0d2FyZSBjbGVhbnVwIGlzIHBlcmZvcm1lZCBpbiBwcmUtRkxSIHdoZXJl
YXMNCj4gPiBmaXJtd2FyZSBpcyBkb3dubG9hZGVkIGFuZCBzb2Z0d2FyZSBpcyByZS1pbml0aWFs
aXNlZCBpbiBwb3N0LUZMUg0KPiA+IGhhbmRsZXIuDQo+ID4NCj4gPiBGb2xsb3dpbmcgY29tbWFu
ZCB0cmlnZ2VycyBGTFIuDQo+ID4gZWNobyAiMSIgPiAvc3lzL2J1cy9wY2kvZGV2aWNlcy8kTlVN
QkVSL3Jlc2V0DQo+ID4NCj4gPiBUaGlzIGZlYXR1cmUgY2FuIGJlIHVzZWQgYXMgYSByZWNvdmVy
eSBtZWNoYW5pc20gd2hlbiBmaXJtd2FyZSBnZXRzDQo+ID4gaGFuZy4NCj4gPg0KPiA+IFNpZ25l
ZC1vZmYtYnk6IEFtaXRrdW1hciBLYXJ3YXIgPGFrYXJ3YXJAbWFydmVsbC5jb20+DQo+IA0KPiBE
b2Vzbid0IGFwcGx5IGFueW1vcmUsIHBsZWFzZSByZWJhc2UuDQo+IA0KPiBBcHBseWluZzogbXdp
ZmlleDogYWRkIFBDSWUgZnVuY3Rpb24gbGV2ZWwgcmVzZXQgc3VwcG9ydA0KPiBmYXRhbDogc2hh
MSBpbmZvcm1hdGlvbiBpcyBsYWNraW5nIG9yIHVzZWxlc3MNCj4gKGRyaXZlcnMvbmV0L3dpcmVs
ZXNzL21hcnZlbGwvbXdpZmlleC9tYWluLmMpLg0KPiBSZXBvc2l0b3J5IGxhY2tzIG5lY2Vzc2Fy
eSBibG9icyB0byBmYWxsIGJhY2sgb24gMy13YXkgbWVyZ2UuDQo+IENhbm5vdCBmYWxsIGJhY2sg
dG8gdGhyZWUtd2F5IG1lcmdlLg0KPiBQYXRjaCBmYWlsZWQgYXQgMDAwMSBtd2lmaWV4OiBhZGQg
UENJZSBmdW5jdGlvbiBsZXZlbCByZXNldCBzdXBwb3J0DQo+IA0KDQpJdCBnZXRzIGFwcGxpZWQg
c21vb3RobHkgaWYgYmVsb3cgcGF0Y2hlcyBhcmUgYXBwbGllZCBmaXJzdC4NCmh0dHBzOi8vcGF0
Y2h3b3JrLmtlcm5lbC5vcmcvcGF0Y2gvOTMxMDQ5OS8gKFt2NSwxLzJdIG13aWZpZXg6IGFkZCBt
YW51ZmFjdHVyaW5nIG1vZGUgc3VwcG9ydCkNCmh0dHBzOi8vcGF0Y2h3b3JrLmtlcm5lbC5vcmcv
cGF0Y2gvOTMxMDUwMS8gKFt2NSwyLzJdIG13aWZpZXg6IGFkZCBjZmc4MDIxMSB0ZXN0bW9kZSBz
dXBwb3J0KQ0KDQpQbGVhc2UgbGV0IG1lIGtub3cgaWYgeW91IHdhbnQgbWUgdG8gcmViYXNlICJQ
Q0llIGZ1bmN0aW9uIGxldmVsIHJlc2V0IHN1cHBvcnQiLiBJbiB0aGF0IGNhc2UgSSBuZWVkIHRv
IHJlYmFzZSBhbmQgc2VuZCBhYm92ZSAyIHBhdGNoZXMgYXMgd2VsbC4NCg0KUmVnYXJkcywNCkFt
aXRrdW1hcg0K
Amitkumar Karwar <[email protected]> wrote:
> This patch implements pre and post FLR handlers to support PCIe FLR
> functionality. Software cleanup is performed in pre-FLR whereas
> firmware is downloaded and software is re-initialised in
> post-FLR handler.
>
> Following command triggers FLR.
> echo "1" > /sys/bus/pci/devices/$NUMBER/reset
>
> This feature can be used as a recovery mechanism when firmware gets
> hang.
>
> Signed-off-by: Amitkumar Karwar <[email protected]>
Doesn't apply anymore, please rebase.
Applying: mwifiex: add PCIe function level reset support
fatal: sha1 information is lacking or useless (drivers/net/wireless/marvell/mwifiex/main.c).
Repository lacks necessary blobs to fall back on 3-way merge.
Cannot fall back to three-way merge.
Patch failed at 0001 mwifiex: add PCIe function level reset support
--
Sent by pwcli
https://patchwork.kernel.org/patch/9248233/
Amitkumar Karwar <[email protected]> writes:
>> Doesn't apply anymore, please rebase.
>>
>> Applying: mwifiex: add PCIe function level reset support
>> fatal: sha1 information is lacking or useless
>> (drivers/net/wireless/marvell/mwifiex/main.c).
>> Repository lacks necessary blobs to fall back on 3-way merge.
>> Cannot fall back to three-way merge.
>> Patch failed at 0001 mwifiex: add PCIe function level reset support
>
> It gets applied smoothly if below patches are applied first.
> https://patchwork.kernel.org/patch/9310499/ ([v5,1/2] mwifiex: add manufacturing mode support)
> https://patchwork.kernel.org/patch/9310501/ ([v5,2/2] mwifiex: add cfg80211 testmode support)
>
> Please let me know if you want me to rebase "PCIe function level reset
> support". In that case I need to rebase and send above 2 patches as
> well.
Yes, I was able to apply this after those patches. No need to resend.
--
Kalle Valo
Amitkumar Karwar <[email protected]> wrote:
> This patch implements pre and post FLR handlers to support PCIe FLR
> functionality. Software cleanup is performed in pre-FLR whereas
> firmware is downloaded and software is re-initialised in
> post-FLR handler.
>
> Following command triggers FLR.
> echo "1" > /sys/bus/pci/devices/$NUMBER/reset
>
> This feature can be used as a recovery mechanism when firmware gets
> hang.
>
> Signed-off-by: Amitkumar Karwar <[email protected]>
Thanks, 1 patch applied to wireless-drivers-next.git:
4c5dae59d2e9 mwifiex: add PCIe function level reset support
--
Sent by pwcli
https://patchwork.kernel.org/patch/9248233/