Loading drivers/net/wireless/cnss2/main.c +32 −20 Original line number Diff line number Diff line Loading @@ -556,6 +556,14 @@ static void cnss_driver_event_work(struct work_struct *work) spin_unlock_irqrestore(&plat_priv->event_lock, flags); } static void cnss_recovery_work_func(struct work_struct *work) { struct cnss_recovery_work_t *ctx = container_of(work, struct cnss_recovery_work_t, work); cnss_self_recovery(ctx->dev, ctx->reason); } int cnss_driver_event_post(struct cnss_plat_data *plat_priv, enum cnss_driver_event_type type, bool sync, void *data) Loading Loading @@ -1234,60 +1242,62 @@ static void cnss_crash_shutdown(const struct subsys_desc *subsys_desc) } } void cnss_device_self_recovery(void) int cnss_self_recovery(struct device *dev, enum cnss_recovery_reason reason) { struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(NULL); struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); struct cnss_subsys_info *subsys_info; if (!plat_priv) { cnss_pr_err("plat_priv is NULL!\n"); return; return -EINVAL; } if (!plat_priv->plat_dev) { cnss_pr_err("plat_dev is NULL!\n"); return; return -EINVAL; } if (!plat_priv->driver_ops) { cnss_pr_err("Driver is not registered yet!\n"); return; return -EINVAL; } if (plat_priv->driver_status == CNSS_RECOVERY) { cnss_pr_err("Recovery is already in progress!\n"); return; return -EINVAL; } if (plat_priv->driver_status == CNSS_LOAD_UNLOAD) { cnss_pr_err("Driver load or unload is in progress!\n"); return; return -EINVAL; } subsys_info = &plat_priv->subsys_info; plat_priv->recovery_count++; plat_priv->driver_status = CNSS_RECOVERY; pm_stay_awake(&plat_priv->plat_dev->dev); pm_stay_awake(dev); cnss_shutdown(&subsys_info->subsys_desc, false); udelay(WLAN_RECOVERY_DELAY); cnss_powerup(&subsys_info->subsys_desc); pm_relax(&plat_priv->plat_dev->dev); pm_relax(dev); plat_priv->driver_status = CNSS_INITIALIZED; } EXPORT_SYMBOL(cnss_device_self_recovery); void cnss_recovery_work_handler(struct work_struct *recovery) { cnss_device_self_recovery(); return 0; } EXPORT_SYMBOL(cnss_self_recovery); DECLARE_WORK(cnss_recovery_work, cnss_recovery_work_handler); void cnss_schedule_recovery_work(void) void cnss_schedule_recovery(struct device *dev, enum cnss_recovery_reason reason) { schedule_work(&cnss_recovery_work); struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); struct cnss_recovery_work_t *work = &plat_priv->cnss_recovery_work; work->dev = dev; work->reason = reason; queue_work(plat_priv->event_wq, &work->work); } EXPORT_SYMBOL(cnss_schedule_recovery_work); EXPORT_SYMBOL(cnss_schedule_recovery); int cnss_register_subsys(struct cnss_plat_data *plat_priv) { Loading Loading @@ -1554,7 +1564,7 @@ static int cnss_event_work_init(struct cnss_plat_data *plat_priv) { spin_lock_init(&plat_priv->event_lock); plat_priv->event_wq = alloc_workqueue("cnss_driver_event", WQ_UNBOUND, 1); 0, 0); if (!plat_priv->event_wq) { cnss_pr_err("Failed to create event workqueue!\n"); return -EFAULT; Loading @@ -1562,6 +1572,8 @@ static int cnss_event_work_init(struct cnss_plat_data *plat_priv) INIT_WORK(&plat_priv->event_work, cnss_driver_event_work); INIT_LIST_HEAD(&plat_priv->event_list); INIT_WORK(&plat_priv->cnss_recovery_work.work, cnss_recovery_work_func); init_completion(&plat_priv->fw_ready_event); return 0; Loading drivers/net/wireless/cnss2/main.h +7 −0 Original line number Diff line number Diff line Loading @@ -108,6 +108,12 @@ enum cnss_driver_state { CNSS_DRIVER_PROBED, }; struct cnss_recovery_work_t { struct work_struct work; struct device *dev; enum cnss_recovery_reason reason; }; struct cnss_plat_data { struct platform_device *plat_dev; void *bus_priv; Loading @@ -131,6 +137,7 @@ struct cnss_plat_data { spinlock_t event_lock; /* spinlock for driver work event handling */ struct work_struct event_work; struct workqueue_struct *event_wq; struct cnss_recovery_work_t cnss_recovery_work; struct qmi_handle *qmi_wlfw_clnt; struct work_struct qmi_recv_msg_work; struct notifier_block qmi_wlfw_clnt_nb; Loading drivers/net/wireless/cnss2/pci.c +11 −10 Original line number Diff line number Diff line Loading @@ -168,21 +168,21 @@ out: return ret; } void cnss_wlan_pci_link_down(void) int cnss_pci_link_down(struct device *dev) { unsigned long flags; struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(NULL); struct cnss_pci_data *pci_priv; struct pci_dev *pci_dev = to_pci_dev(dev); struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev); struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); if (!plat_priv) { cnss_pr_err("plat_priv is NULL!\n"); return; return -EINVAL; } pci_priv = plat_priv->bus_priv; if (!pci_priv) { cnss_pr_err("pci_priv is NULL!\n"); return; return -EINVAL; } if (pci_link_down_panic) Loading @@ -192,15 +192,16 @@ void cnss_wlan_pci_link_down(void) if (pci_priv->pci_link_down_ind) { cnss_pr_dbg("PCI link down recovery is in progress, ignore!\n"); spin_unlock_irqrestore(&pci_link_down_lock, flags); return; return -EINVAL; } pci_priv->pci_link_down_ind = true; spin_unlock_irqrestore(&pci_link_down_lock, flags); cnss_pr_err("PCI link down is detected by host driver, schedule recovery!\n"); cnss_schedule_recovery_work(); cnss_schedule_recovery(dev, CNSS_REASON_LINK_DOWN); return 0; } EXPORT_SYMBOL(cnss_wlan_pci_link_down); EXPORT_SYMBOL(cnss_pci_link_down); static int cnss_pci_init_smmu(struct cnss_pci_data *pci_priv) { Loading Loading @@ -295,7 +296,7 @@ static void cnss_pci_event_cb(struct msm_pcie_notify *notify) cnss_pr_err("PCI link down, schedule recovery!\n"); disable_irq(pci_dev->irq); cnss_schedule_recovery_work(); cnss_schedule_recovery(&pci_dev->dev, CNSS_REASON_LINK_DOWN); break; case MSM_PCIE_EVENT_WAKEUP: if (cnss_pci_get_monitor_wake_intr(pci_priv) && Loading include/net/cnss2.h +10 −3 Original line number Diff line number Diff line Loading @@ -128,12 +128,19 @@ enum cnss_driver_mode { CNSS_CALIBRATION, }; enum cnss_recovery_reason { CNSS_REASON_DEFAULT, CNSS_REASON_LINK_DOWN, }; extern int cnss_wlan_register_driver(struct cnss_wlan_driver *driver); extern void cnss_wlan_unregister_driver(struct cnss_wlan_driver *driver); extern void cnss_wlan_pci_link_down(void); extern void cnss_schedule_recovery_work(void); extern void cnss_device_crashed(void); extern void cnss_device_self_recovery(void); extern int cnss_pci_link_down(struct device *dev); extern void cnss_schedule_recovery(struct device *dev, enum cnss_recovery_reason reason); extern int cnss_self_recovery(struct device *dev, enum cnss_recovery_reason reason); extern void *cnss_get_virt_ramdump_mem(unsigned long *size); extern int cnss_get_fw_files_for_target(struct cnss_fw_files *pfw_files, u32 target_type, u32 target_version); Loading Loading
drivers/net/wireless/cnss2/main.c +32 −20 Original line number Diff line number Diff line Loading @@ -556,6 +556,14 @@ static void cnss_driver_event_work(struct work_struct *work) spin_unlock_irqrestore(&plat_priv->event_lock, flags); } static void cnss_recovery_work_func(struct work_struct *work) { struct cnss_recovery_work_t *ctx = container_of(work, struct cnss_recovery_work_t, work); cnss_self_recovery(ctx->dev, ctx->reason); } int cnss_driver_event_post(struct cnss_plat_data *plat_priv, enum cnss_driver_event_type type, bool sync, void *data) Loading Loading @@ -1234,60 +1242,62 @@ static void cnss_crash_shutdown(const struct subsys_desc *subsys_desc) } } void cnss_device_self_recovery(void) int cnss_self_recovery(struct device *dev, enum cnss_recovery_reason reason) { struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(NULL); struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); struct cnss_subsys_info *subsys_info; if (!plat_priv) { cnss_pr_err("plat_priv is NULL!\n"); return; return -EINVAL; } if (!plat_priv->plat_dev) { cnss_pr_err("plat_dev is NULL!\n"); return; return -EINVAL; } if (!plat_priv->driver_ops) { cnss_pr_err("Driver is not registered yet!\n"); return; return -EINVAL; } if (plat_priv->driver_status == CNSS_RECOVERY) { cnss_pr_err("Recovery is already in progress!\n"); return; return -EINVAL; } if (plat_priv->driver_status == CNSS_LOAD_UNLOAD) { cnss_pr_err("Driver load or unload is in progress!\n"); return; return -EINVAL; } subsys_info = &plat_priv->subsys_info; plat_priv->recovery_count++; plat_priv->driver_status = CNSS_RECOVERY; pm_stay_awake(&plat_priv->plat_dev->dev); pm_stay_awake(dev); cnss_shutdown(&subsys_info->subsys_desc, false); udelay(WLAN_RECOVERY_DELAY); cnss_powerup(&subsys_info->subsys_desc); pm_relax(&plat_priv->plat_dev->dev); pm_relax(dev); plat_priv->driver_status = CNSS_INITIALIZED; } EXPORT_SYMBOL(cnss_device_self_recovery); void cnss_recovery_work_handler(struct work_struct *recovery) { cnss_device_self_recovery(); return 0; } EXPORT_SYMBOL(cnss_self_recovery); DECLARE_WORK(cnss_recovery_work, cnss_recovery_work_handler); void cnss_schedule_recovery_work(void) void cnss_schedule_recovery(struct device *dev, enum cnss_recovery_reason reason) { schedule_work(&cnss_recovery_work); struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); struct cnss_recovery_work_t *work = &plat_priv->cnss_recovery_work; work->dev = dev; work->reason = reason; queue_work(plat_priv->event_wq, &work->work); } EXPORT_SYMBOL(cnss_schedule_recovery_work); EXPORT_SYMBOL(cnss_schedule_recovery); int cnss_register_subsys(struct cnss_plat_data *plat_priv) { Loading Loading @@ -1554,7 +1564,7 @@ static int cnss_event_work_init(struct cnss_plat_data *plat_priv) { spin_lock_init(&plat_priv->event_lock); plat_priv->event_wq = alloc_workqueue("cnss_driver_event", WQ_UNBOUND, 1); 0, 0); if (!plat_priv->event_wq) { cnss_pr_err("Failed to create event workqueue!\n"); return -EFAULT; Loading @@ -1562,6 +1572,8 @@ static int cnss_event_work_init(struct cnss_plat_data *plat_priv) INIT_WORK(&plat_priv->event_work, cnss_driver_event_work); INIT_LIST_HEAD(&plat_priv->event_list); INIT_WORK(&plat_priv->cnss_recovery_work.work, cnss_recovery_work_func); init_completion(&plat_priv->fw_ready_event); return 0; Loading
drivers/net/wireless/cnss2/main.h +7 −0 Original line number Diff line number Diff line Loading @@ -108,6 +108,12 @@ enum cnss_driver_state { CNSS_DRIVER_PROBED, }; struct cnss_recovery_work_t { struct work_struct work; struct device *dev; enum cnss_recovery_reason reason; }; struct cnss_plat_data { struct platform_device *plat_dev; void *bus_priv; Loading @@ -131,6 +137,7 @@ struct cnss_plat_data { spinlock_t event_lock; /* spinlock for driver work event handling */ struct work_struct event_work; struct workqueue_struct *event_wq; struct cnss_recovery_work_t cnss_recovery_work; struct qmi_handle *qmi_wlfw_clnt; struct work_struct qmi_recv_msg_work; struct notifier_block qmi_wlfw_clnt_nb; Loading
drivers/net/wireless/cnss2/pci.c +11 −10 Original line number Diff line number Diff line Loading @@ -168,21 +168,21 @@ out: return ret; } void cnss_wlan_pci_link_down(void) int cnss_pci_link_down(struct device *dev) { unsigned long flags; struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(NULL); struct cnss_pci_data *pci_priv; struct pci_dev *pci_dev = to_pci_dev(dev); struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev); struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); if (!plat_priv) { cnss_pr_err("plat_priv is NULL!\n"); return; return -EINVAL; } pci_priv = plat_priv->bus_priv; if (!pci_priv) { cnss_pr_err("pci_priv is NULL!\n"); return; return -EINVAL; } if (pci_link_down_panic) Loading @@ -192,15 +192,16 @@ void cnss_wlan_pci_link_down(void) if (pci_priv->pci_link_down_ind) { cnss_pr_dbg("PCI link down recovery is in progress, ignore!\n"); spin_unlock_irqrestore(&pci_link_down_lock, flags); return; return -EINVAL; } pci_priv->pci_link_down_ind = true; spin_unlock_irqrestore(&pci_link_down_lock, flags); cnss_pr_err("PCI link down is detected by host driver, schedule recovery!\n"); cnss_schedule_recovery_work(); cnss_schedule_recovery(dev, CNSS_REASON_LINK_DOWN); return 0; } EXPORT_SYMBOL(cnss_wlan_pci_link_down); EXPORT_SYMBOL(cnss_pci_link_down); static int cnss_pci_init_smmu(struct cnss_pci_data *pci_priv) { Loading Loading @@ -295,7 +296,7 @@ static void cnss_pci_event_cb(struct msm_pcie_notify *notify) cnss_pr_err("PCI link down, schedule recovery!\n"); disable_irq(pci_dev->irq); cnss_schedule_recovery_work(); cnss_schedule_recovery(&pci_dev->dev, CNSS_REASON_LINK_DOWN); break; case MSM_PCIE_EVENT_WAKEUP: if (cnss_pci_get_monitor_wake_intr(pci_priv) && Loading
include/net/cnss2.h +10 −3 Original line number Diff line number Diff line Loading @@ -128,12 +128,19 @@ enum cnss_driver_mode { CNSS_CALIBRATION, }; enum cnss_recovery_reason { CNSS_REASON_DEFAULT, CNSS_REASON_LINK_DOWN, }; extern int cnss_wlan_register_driver(struct cnss_wlan_driver *driver); extern void cnss_wlan_unregister_driver(struct cnss_wlan_driver *driver); extern void cnss_wlan_pci_link_down(void); extern void cnss_schedule_recovery_work(void); extern void cnss_device_crashed(void); extern void cnss_device_self_recovery(void); extern int cnss_pci_link_down(struct device *dev); extern void cnss_schedule_recovery(struct device *dev, enum cnss_recovery_reason reason); extern int cnss_self_recovery(struct device *dev, enum cnss_recovery_reason reason); extern void *cnss_get_virt_ramdump_mem(unsigned long *size); extern int cnss_get_fw_files_for_target(struct cnss_fw_files *pfw_files, u32 target_type, u32 target_version); Loading