Loading drivers/net/wireless/cnss2/main.c +278 −204 Original line number Diff line number Diff line Loading @@ -11,12 +11,14 @@ */ #include <linux/delay.h> #include <linux/jiffies.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/pm_wakeup.h> #include <linux/rwsem.h> #include <linux/suspend.h> #include <linux/timer.h> #include <soc/qcom/ramdump.h> #include <soc/qcom/subsystem_notif.h> Loading Loading @@ -452,6 +454,38 @@ out: return ret; } static int cnss_driver_call_probe(struct cnss_plat_data *plat_priv) { int ret; struct cnss_pci_data *pci_priv = plat_priv->bus_priv; if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) { ret = plat_priv->driver_ops->reinit(pci_priv->pci_dev, pci_priv->pci_device_id); if (ret) { cnss_pr_err("Failed to reinit host driver, err = %d\n", ret); goto out; } clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state); } else { ret = plat_priv->driver_ops->probe(pci_priv->pci_dev, pci_priv->pci_device_id); if (ret) { cnss_pr_err("Failed to probe host driver, err = %d\n", ret); goto out; } clear_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state); set_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state); } return 0; out: return ret; } static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv) { struct cnss_pci_data *pci_priv; Loading @@ -460,6 +494,8 @@ static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv) if (!plat_priv) return -ENODEV; del_timer(&plat_priv->fw_ready_timer); set_bit(CNSS_FW_READY, &plat_priv->driver_state); pci_priv = plat_priv->bus_priv; Loading @@ -467,7 +503,7 @@ static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv) return -ENODEV; if (test_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state)) complete(&plat_priv->fw_ready_event); ret = cnss_driver_call_probe(plat_priv); else if (enable_waltest) ret = cnss_wlfw_wlan_mode_send_sync(plat_priv, QMI_WLFW_WALTEST_V01); Loading @@ -475,6 +511,16 @@ static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv) ret = cnss_wlfw_wlan_mode_send_sync(plat_priv, QMI_WLFW_CALIBRATION_V01); if (ret) goto shutdown; return 0; shutdown: cnss_pci_stop_mhi(pci_priv); cnss_suspend_pci_link(pci_priv); cnss_power_off_device(plat_priv); return ret; } Loading Loading @@ -514,6 +560,12 @@ static char *cnss_driver_event_to_str(enum cnss_driver_event_type type) return "FW_READY"; case CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE: return "COLD_BOOT_CAL_DONE"; case CNSS_DRIVER_EVENT_REGISTER_DRIVER: return "REGISTER_DRIVER"; case CNSS_DRIVER_EVENT_UNREGISTER_DRIVER: return "UNREGISTER_DRIVER"; case CNSS_DRIVER_EVENT_RECOVERY: return "RECOVERY"; case CNSS_DRIVER_EVENT_MAX: return "EVENT_MAX"; } Loading @@ -521,86 +573,6 @@ static char *cnss_driver_event_to_str(enum cnss_driver_event_type type) return "UNKNOWN"; }; static void cnss_driver_event_work(struct work_struct *work) { struct cnss_plat_data *plat_priv = container_of(work, struct cnss_plat_data, event_work); struct cnss_driver_event *event; unsigned long flags; int ret = 0; if (!plat_priv) return; cnss_pm_stay_awake(plat_priv); spin_lock_irqsave(&plat_priv->event_lock, flags); while (!list_empty(&plat_priv->event_list)) { event = list_first_entry(&plat_priv->event_list, struct cnss_driver_event, list); list_del(&event->list); spin_unlock_irqrestore(&plat_priv->event_lock, flags); cnss_pr_dbg("Processing driver event: %s%s(%d), state: 0x%lx\n", cnss_driver_event_to_str(event->type), event->sync ? "-sync" : "", event->type, plat_priv->driver_state); switch (event->type) { case CNSS_DRIVER_EVENT_SERVER_ARRIVE: ret = cnss_wlfw_server_arrive(plat_priv); break; case CNSS_DRIVER_EVENT_SERVER_EXIT: ret = cnss_wlfw_server_exit(plat_priv); break; case CNSS_DRIVER_EVENT_REQUEST_MEM: ret = cnss_pci_alloc_fw_mem(plat_priv->bus_priv); if (ret) break; ret = cnss_wlfw_respond_mem_send_sync(plat_priv); break; case CNSS_DRIVER_EVENT_FW_MEM_READY: ret = cnss_fw_mem_ready_hdlr(plat_priv); break; case CNSS_DRIVER_EVENT_FW_READY: ret = cnss_fw_ready_hdlr(plat_priv); break; case CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE: ret = cnss_cold_boot_cal_done_hdlr(plat_priv); break; default: cnss_pr_err("Invalid driver event type: %d", event->type); kfree(event); continue; } spin_lock_irqsave(&plat_priv->event_lock, flags); if (event->sync) { event->ret = ret; complete(&event->complete); continue; } spin_unlock_irqrestore(&plat_priv->event_lock, flags); kfree(event); spin_lock_irqsave(&plat_priv->event_lock, flags); } spin_unlock_irqrestore(&plat_priv->event_lock, flags); cnss_pm_relax(plat_priv); } 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 @@ -722,40 +694,20 @@ int cnss_wlan_register_driver(struct cnss_wlan_driver *driver_ops) { int ret = 0; struct cnss_plat_data *plat_priv = cnss_get_plat_priv(NULL); struct cnss_subsys_info *subsys_info; if (!plat_priv) { cnss_pr_err("plat_priv is NULL!\n"); ret = -ENODEV; goto out; return -ENODEV; } if (plat_priv->driver_ops) { cnss_pr_err("Driver has already registered!\n"); ret = -EEXIST; goto out; return -EEXIST; } set_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state); plat_priv->driver_ops = driver_ops; subsys_info = &plat_priv->subsys_info; subsys_info->subsys_handle = subsystem_get(subsys_info->subsys_desc.name); if (!subsys_info->subsys_handle) { ret = -EINVAL; goto reset_ctx; } else if (IS_ERR(subsys_info->subsys_handle)) { ret = PTR_ERR(subsys_info->subsys_handle); goto reset_ctx; } return 0; reset_ctx: cnss_pr_err("Failed to get subsystem, err = %d\n", ret); clear_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state); plat_priv->driver_ops = NULL; out: ret = cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_REGISTER_DRIVER, true, driver_ops); return ret; } EXPORT_SYMBOL(cnss_wlan_register_driver); Loading @@ -763,18 +715,15 @@ EXPORT_SYMBOL(cnss_wlan_register_driver); void cnss_wlan_unregister_driver(struct cnss_wlan_driver *driver_ops) { struct cnss_plat_data *plat_priv = cnss_get_plat_priv(NULL); struct cnss_subsys_info *subsys_info; if (!plat_priv) { cnss_pr_err("plat_priv is NULL!\n"); return; } set_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state); subsys_info = &plat_priv->subsys_info; subsystem_put(subsys_info->subsys_handle); subsys_info->subsys_handle = NULL; plat_priv->driver_ops = NULL; cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_UNREGISTER_DRIVER, true, NULL); } EXPORT_SYMBOL(cnss_wlan_unregister_driver); Loading Loading @@ -934,30 +883,9 @@ static int cnss_qca6174_powerup(struct cnss_plat_data *plat_priv) goto power_off; } if (test_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state)) { ret = plat_priv->driver_ops->probe(pci_priv->pci_dev, pci_priv->pci_device_id); if (ret) { cnss_pr_err("Failed to probe host driver, err = %d\n", ret); goto suspend_link; } clear_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state); set_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state); } else if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) { ret = plat_priv->driver_ops->reinit(pci_priv->pci_dev, pci_priv->pci_device_id); if (ret) { cnss_pr_err("Failed to reinit host driver, err = %d\n", ret); goto suspend_link; } clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state); } else { cnss_pr_err("Driver state is not correct to power up!\n"); ret = -EINVAL; ret = cnss_driver_call_probe(plat_priv); if (ret) goto suspend_link; } return 0; suspend_link: Loading Loading @@ -985,7 +913,6 @@ static int cnss_qca6174_shutdown(struct cnss_plat_data *plat_priv) cnss_pci_set_monitor_wake_intr(pci_priv, false); cnss_pci_set_auto_suspended(pci_priv, 0); } else { set_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state); plat_priv->driver_ops->shutdown(pci_priv->pci_dev); } Loading Loading @@ -1017,6 +944,7 @@ static int cnss_qca6290_powerup(struct cnss_plat_data *plat_priv) { int ret = 0; struct cnss_pci_data *pci_priv = plat_priv->bus_priv; unsigned int timeout; if (!pci_priv) { cnss_pr_err("pci_priv is NULL!\n"); Loading Loading @@ -1048,43 +976,16 @@ static int cnss_qca6290_powerup(struct cnss_plat_data *plat_priv) cnss_set_pin_connect_status(plat_priv); if (qmi_bypass) goto skip_fw_ready; reinit_completion(&plat_priv->fw_ready_event); ret = wait_for_completion_timeout(&plat_priv->fw_ready_event, msecs_to_jiffies(FW_READY_TIMEOUT)); if (ret == 0) { cnss_pr_err("Timeout for FW ready event!\n"); ret = -EBUSY; goto stop_mhi; } skip_fw_ready: if (test_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state)) { ret = plat_priv->driver_ops->probe(pci_priv->pci_dev, pci_priv->pci_device_id); if (ret) { cnss_pr_err("Failed to probe host driver, err = %d\n", ret); goto stop_mhi; } clear_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state); set_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state); } else if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) { ret = plat_priv->driver_ops->reinit(pci_priv->pci_dev, pci_priv->pci_device_id); if (ret) { cnss_pr_err("Failed to reinit host driver, err = %d\n", ret); if (qmi_bypass) { ret = cnss_driver_call_probe(plat_priv); if (ret) goto stop_mhi; } clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state); } else { cnss_pr_err("Driver state is not correct to power up!\n"); ret = -EINVAL; goto stop_mhi; timeout = cnss_get_qmi_timeout(); cnss_pr_dbg("QMI timeout is %u ms\n", timeout); if (timeout) mod_timer(&plat_priv->fw_ready_timer, jiffies + msecs_to_jiffies(timeout << 1)); } return 0; Loading Loading @@ -1116,7 +1017,6 @@ static int cnss_qca6290_shutdown(struct cnss_plat_data *plat_priv) cnss_pci_set_monitor_wake_intr(pci_priv, false); cnss_pci_set_auto_suspended(pci_priv, 0); } else { set_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state); plat_priv->driver_ops->shutdown(pci_priv->pci_dev); } Loading Loading @@ -1146,6 +1046,9 @@ static int cnss_powerup(const struct subsys_desc *subsys_desc) return -ENODEV; } if (!plat_priv->driver_ops) return 0; switch (plat_priv->device_id) { case QCA6174_DEVICE_ID: ret = cnss_qca6174_powerup(plat_priv); Loading Loading @@ -1287,46 +1190,64 @@ static void cnss_crash_shutdown(const struct subsys_desc *subsys_desc) } } int cnss_self_recovery(struct device *dev, static int cnss_do_recovery(struct cnss_plat_data *plat_priv, enum cnss_recovery_reason reason) { struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); struct cnss_subsys_info *subsys_info; struct cnss_subsys_info *subsys_info = &plat_priv->subsys_info; if (!plat_priv) { cnss_pr_err("plat_priv is NULL!\n"); return -EINVAL; } plat_priv->recovery_count++; if (!plat_priv->plat_dev) { cnss_pr_err("plat_dev is NULL!\n"); return -EINVAL; if (plat_priv->device_id == QCA6174_DEVICE_ID) { cnss_shutdown(&subsys_info->subsys_desc, false); udelay(WLAN_RECOVERY_DELAY); cnss_powerup(&subsys_info->subsys_desc); return 0; } if (!plat_priv->driver_ops) { cnss_pr_err("Driver is not registered yet!\n"); return -EINVAL; if (!subsys_info->subsys_device) return 0; subsys_set_crash_status(subsys_info->subsys_device, true); subsystem_restart_dev(subsys_info->subsys_device); return 0; } static int cnss_driver_recovery_hdlr(struct cnss_plat_data *plat_priv, void *data) { struct cnss_recovery_data *recovery_data = data; int ret = 0; cnss_pr_dbg("Driver recovery is triggered: reason %d\n", recovery_data->reason); if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) { cnss_pr_err("Recovery is already in progress!\n"); return -EINVAL; ret = -EINVAL; goto out; } if (test_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state)) { cnss_pr_err("Driver load or unload is in progress!\n"); return -EINVAL; ret = -EINVAL; goto out; } subsys_info = &plat_priv->subsys_info; plat_priv->recovery_count++; set_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state); pm_stay_awake(dev); cnss_shutdown(&subsys_info->subsys_desc, false); udelay(WLAN_RECOVERY_DELAY); cnss_powerup(&subsys_info->subsys_desc); pm_relax(dev); ret = cnss_do_recovery(plat_priv, recovery_data->reason); out: kfree(data); return ret; } int cnss_self_recovery(struct device *dev, enum cnss_recovery_reason reason) { cnss_schedule_recovery(dev, reason); return 0; } EXPORT_SYMBOL(cnss_self_recovery); Loading @@ -1335,14 +1256,152 @@ void cnss_schedule_recovery(struct device *dev, enum cnss_recovery_reason reason) { struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); struct cnss_recovery_work_t *work = &plat_priv->cnss_recovery_work; struct cnss_recovery_data *data; int gfp = GFP_KERNEL; if (in_interrupt() || irqs_disabled()) gfp = GFP_ATOMIC; data = kzalloc(sizeof(*data), gfp); if (!data) return; work->dev = dev; work->reason = reason; queue_work(plat_priv->event_wq, &work->work); data->reason = reason; cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_RECOVERY, false, data); } EXPORT_SYMBOL(cnss_schedule_recovery); void fw_ready_timeout(unsigned long data) { struct cnss_plat_data *plat_priv = (struct cnss_plat_data *)data; struct cnss_pci_data *pci_priv = plat_priv->bus_priv; cnss_pr_err("Timeout waiting for FW ready indication!\n"); cnss_pci_stop_mhi(pci_priv); cnss_suspend_pci_link(pci_priv); cnss_power_off_device(plat_priv); } static int cnss_register_driver_hdlr(struct cnss_plat_data *plat_priv, void *data) { int ret = 0; struct cnss_subsys_info *subsys_info; set_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state); plat_priv->driver_ops = data; subsys_info = &plat_priv->subsys_info; ret = cnss_powerup(&subsys_info->subsys_desc); if (ret) { clear_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state); plat_priv->driver_ops = NULL; } return ret; } static int cnss_unregister_driver_hdlr(struct cnss_plat_data *plat_priv) { struct cnss_subsys_info *subsys_info; set_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state); subsys_info = &plat_priv->subsys_info; cnss_shutdown(&subsys_info->subsys_desc, false); subsys_info->subsys_handle = NULL; plat_priv->driver_ops = NULL; return 0; } static void cnss_driver_event_work(struct work_struct *work) { struct cnss_plat_data *plat_priv = container_of(work, struct cnss_plat_data, event_work); struct cnss_driver_event *event; unsigned long flags; int ret = 0; if (!plat_priv) { cnss_pr_err("plat_priv is NULL!\n"); return; } cnss_pm_stay_awake(plat_priv); spin_lock_irqsave(&plat_priv->event_lock, flags); while (!list_empty(&plat_priv->event_list)) { event = list_first_entry(&plat_priv->event_list, struct cnss_driver_event, list); list_del(&event->list); spin_unlock_irqrestore(&plat_priv->event_lock, flags); cnss_pr_dbg("Processing driver event: %s%s(%d), state: 0x%lx\n", cnss_driver_event_to_str(event->type), event->sync ? "-sync" : "", event->type, plat_priv->driver_state); switch (event->type) { case CNSS_DRIVER_EVENT_SERVER_ARRIVE: ret = cnss_wlfw_server_arrive(plat_priv); break; case CNSS_DRIVER_EVENT_SERVER_EXIT: ret = cnss_wlfw_server_exit(plat_priv); break; case CNSS_DRIVER_EVENT_REQUEST_MEM: ret = cnss_pci_alloc_fw_mem(plat_priv->bus_priv); if (ret) break; ret = cnss_wlfw_respond_mem_send_sync(plat_priv); break; case CNSS_DRIVER_EVENT_FW_MEM_READY: ret = cnss_fw_mem_ready_hdlr(plat_priv); break; case CNSS_DRIVER_EVENT_FW_READY: ret = cnss_fw_ready_hdlr(plat_priv); break; case CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE: ret = cnss_cold_boot_cal_done_hdlr(plat_priv); break; case CNSS_DRIVER_EVENT_REGISTER_DRIVER: ret = cnss_register_driver_hdlr(plat_priv, event->data); break; case CNSS_DRIVER_EVENT_UNREGISTER_DRIVER: ret = cnss_unregister_driver_hdlr(plat_priv); break; case CNSS_DRIVER_EVENT_RECOVERY: ret = cnss_driver_recovery_hdlr(plat_priv, event->data); break; default: cnss_pr_err("Invalid driver event type: %d", event->type); kfree(event); continue; } spin_lock_irqsave(&plat_priv->event_lock, flags); if (event->sync) { event->ret = ret; complete(&event->complete); continue; } spin_unlock_irqrestore(&plat_priv->event_lock, flags); kfree(event); spin_lock_irqsave(&plat_priv->event_lock, flags); } spin_unlock_irqrestore(&plat_priv->event_lock, flags); cnss_pm_relax(plat_priv); } int cnss_register_subsys(struct cnss_plat_data *plat_priv) { int ret = 0; Loading Loading @@ -1377,7 +1436,22 @@ int cnss_register_subsys(struct cnss_plat_data *plat_priv) goto out; } subsys_info->subsys_handle = subsystem_get(subsys_info->subsys_desc.name); if (!subsys_info->subsys_handle) { cnss_pr_err("Failed to get subsys_handle!\n"); ret = -EINVAL; goto unregister_subsys; } else if (IS_ERR(subsys_info->subsys_handle)) { ret = PTR_ERR(subsys_info->subsys_handle); cnss_pr_err("Failed to do subsystem_get, err = %d\n", ret); goto unregister_subsys; } return 0; unregister_subsys: subsys_unregister(subsys_info->subsys_device); out: return ret; } Loading @@ -1387,6 +1461,7 @@ void cnss_unregister_subsys(struct cnss_plat_data *plat_priv) struct cnss_subsys_info *subsys_info; subsys_info = &plat_priv->subsys_info; subsystem_put(subsys_info->subsys_handle); subsys_unregister(subsys_info->subsys_device); } Loading Loading @@ -1616,16 +1691,12 @@ 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; } static void cnss_event_work_deinit(struct cnss_plat_data *plat_priv) { complete_all(&plat_priv->fw_ready_event); destroy_workqueue(plat_priv->event_wq); } Loading Loading @@ -1715,6 +1786,9 @@ static int cnss_probe(struct platform_device *plat_dev) if (ret) goto deinit_qmi; setup_timer(&plat_priv->fw_ready_timer, fw_ready_timeout, (unsigned long)plat_priv); register_pm_notifier(&cnss_pm_notifier); cnss_pr_info("Platform driver probed successfully.\n"); Loading drivers/net/wireless/cnss2/main.h +5 −5 Original line number Diff line number Diff line Loading @@ -97,6 +97,9 @@ enum cnss_driver_event_type { CNSS_DRIVER_EVENT_FW_MEM_READY, CNSS_DRIVER_EVENT_FW_READY, CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE, CNSS_DRIVER_EVENT_REGISTER_DRIVER, CNSS_DRIVER_EVENT_UNREGISTER_DRIVER, CNSS_DRIVER_EVENT_RECOVERY, CNSS_DRIVER_EVENT_MAX, }; Loading @@ -110,9 +113,7 @@ enum cnss_driver_state { CNSS_DRIVER_RECOVERY, }; struct cnss_recovery_work_t { struct work_struct work; struct device *dev; struct cnss_recovery_data { enum cnss_recovery_reason reason; }; Loading Loading @@ -153,12 +154,10 @@ struct cnss_plat_data { uint32_t recovery_count; struct cnss_wlan_mac_info wlan_mac_info; unsigned long driver_state; struct completion fw_ready_event; struct list_head event_list; 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 @@ -171,6 +170,7 @@ struct cnss_plat_data { struct cnss_pin_connect_result pin_result; struct dentry *root_dentry; atomic_t pm_count; struct timer_list fw_ready_timer; }; void *cnss_bus_dev_to_bus_priv(struct device *dev); Loading drivers/net/wireless/cnss2/qmi.c +6 −0 Original line number Diff line number Diff line Loading @@ -709,6 +709,12 @@ static void cnss_wlfw_clnt_ind(struct qmi_handle *handle, } } unsigned int cnss_get_qmi_timeout(void) { return qmi_timeout; } EXPORT_SYMBOL(cnss_get_qmi_timeout); int cnss_wlfw_server_arrive(struct cnss_plat_data *plat_priv) { int ret = 0; Loading include/net/cnss2.h +3 −0 Original line number Diff line number Diff line Loading @@ -133,6 +133,8 @@ enum cnss_driver_mode { enum cnss_recovery_reason { CNSS_REASON_DEFAULT, CNSS_REASON_LINK_DOWN, CNSS_REASON_RDDM, CNSS_REASON_TIMEOUT, }; extern int cnss_wlan_register_driver(struct cnss_wlan_driver *driver); Loading Loading @@ -177,5 +179,6 @@ extern int cnss_wlan_enable(struct device *dev, enum cnss_driver_mode mode, const char *host_version); extern int cnss_wlan_disable(struct device *dev, enum cnss_driver_mode mode); extern unsigned int cnss_get_qmi_timeout(void); #endif /* _NET_CNSS2_H */ Loading
drivers/net/wireless/cnss2/main.c +278 −204 Original line number Diff line number Diff line Loading @@ -11,12 +11,14 @@ */ #include <linux/delay.h> #include <linux/jiffies.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/pm_wakeup.h> #include <linux/rwsem.h> #include <linux/suspend.h> #include <linux/timer.h> #include <soc/qcom/ramdump.h> #include <soc/qcom/subsystem_notif.h> Loading Loading @@ -452,6 +454,38 @@ out: return ret; } static int cnss_driver_call_probe(struct cnss_plat_data *plat_priv) { int ret; struct cnss_pci_data *pci_priv = plat_priv->bus_priv; if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) { ret = plat_priv->driver_ops->reinit(pci_priv->pci_dev, pci_priv->pci_device_id); if (ret) { cnss_pr_err("Failed to reinit host driver, err = %d\n", ret); goto out; } clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state); } else { ret = plat_priv->driver_ops->probe(pci_priv->pci_dev, pci_priv->pci_device_id); if (ret) { cnss_pr_err("Failed to probe host driver, err = %d\n", ret); goto out; } clear_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state); set_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state); } return 0; out: return ret; } static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv) { struct cnss_pci_data *pci_priv; Loading @@ -460,6 +494,8 @@ static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv) if (!plat_priv) return -ENODEV; del_timer(&plat_priv->fw_ready_timer); set_bit(CNSS_FW_READY, &plat_priv->driver_state); pci_priv = plat_priv->bus_priv; Loading @@ -467,7 +503,7 @@ static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv) return -ENODEV; if (test_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state)) complete(&plat_priv->fw_ready_event); ret = cnss_driver_call_probe(plat_priv); else if (enable_waltest) ret = cnss_wlfw_wlan_mode_send_sync(plat_priv, QMI_WLFW_WALTEST_V01); Loading @@ -475,6 +511,16 @@ static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv) ret = cnss_wlfw_wlan_mode_send_sync(plat_priv, QMI_WLFW_CALIBRATION_V01); if (ret) goto shutdown; return 0; shutdown: cnss_pci_stop_mhi(pci_priv); cnss_suspend_pci_link(pci_priv); cnss_power_off_device(plat_priv); return ret; } Loading Loading @@ -514,6 +560,12 @@ static char *cnss_driver_event_to_str(enum cnss_driver_event_type type) return "FW_READY"; case CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE: return "COLD_BOOT_CAL_DONE"; case CNSS_DRIVER_EVENT_REGISTER_DRIVER: return "REGISTER_DRIVER"; case CNSS_DRIVER_EVENT_UNREGISTER_DRIVER: return "UNREGISTER_DRIVER"; case CNSS_DRIVER_EVENT_RECOVERY: return "RECOVERY"; case CNSS_DRIVER_EVENT_MAX: return "EVENT_MAX"; } Loading @@ -521,86 +573,6 @@ static char *cnss_driver_event_to_str(enum cnss_driver_event_type type) return "UNKNOWN"; }; static void cnss_driver_event_work(struct work_struct *work) { struct cnss_plat_data *plat_priv = container_of(work, struct cnss_plat_data, event_work); struct cnss_driver_event *event; unsigned long flags; int ret = 0; if (!plat_priv) return; cnss_pm_stay_awake(plat_priv); spin_lock_irqsave(&plat_priv->event_lock, flags); while (!list_empty(&plat_priv->event_list)) { event = list_first_entry(&plat_priv->event_list, struct cnss_driver_event, list); list_del(&event->list); spin_unlock_irqrestore(&plat_priv->event_lock, flags); cnss_pr_dbg("Processing driver event: %s%s(%d), state: 0x%lx\n", cnss_driver_event_to_str(event->type), event->sync ? "-sync" : "", event->type, plat_priv->driver_state); switch (event->type) { case CNSS_DRIVER_EVENT_SERVER_ARRIVE: ret = cnss_wlfw_server_arrive(plat_priv); break; case CNSS_DRIVER_EVENT_SERVER_EXIT: ret = cnss_wlfw_server_exit(plat_priv); break; case CNSS_DRIVER_EVENT_REQUEST_MEM: ret = cnss_pci_alloc_fw_mem(plat_priv->bus_priv); if (ret) break; ret = cnss_wlfw_respond_mem_send_sync(plat_priv); break; case CNSS_DRIVER_EVENT_FW_MEM_READY: ret = cnss_fw_mem_ready_hdlr(plat_priv); break; case CNSS_DRIVER_EVENT_FW_READY: ret = cnss_fw_ready_hdlr(plat_priv); break; case CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE: ret = cnss_cold_boot_cal_done_hdlr(plat_priv); break; default: cnss_pr_err("Invalid driver event type: %d", event->type); kfree(event); continue; } spin_lock_irqsave(&plat_priv->event_lock, flags); if (event->sync) { event->ret = ret; complete(&event->complete); continue; } spin_unlock_irqrestore(&plat_priv->event_lock, flags); kfree(event); spin_lock_irqsave(&plat_priv->event_lock, flags); } spin_unlock_irqrestore(&plat_priv->event_lock, flags); cnss_pm_relax(plat_priv); } 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 @@ -722,40 +694,20 @@ int cnss_wlan_register_driver(struct cnss_wlan_driver *driver_ops) { int ret = 0; struct cnss_plat_data *plat_priv = cnss_get_plat_priv(NULL); struct cnss_subsys_info *subsys_info; if (!plat_priv) { cnss_pr_err("plat_priv is NULL!\n"); ret = -ENODEV; goto out; return -ENODEV; } if (plat_priv->driver_ops) { cnss_pr_err("Driver has already registered!\n"); ret = -EEXIST; goto out; return -EEXIST; } set_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state); plat_priv->driver_ops = driver_ops; subsys_info = &plat_priv->subsys_info; subsys_info->subsys_handle = subsystem_get(subsys_info->subsys_desc.name); if (!subsys_info->subsys_handle) { ret = -EINVAL; goto reset_ctx; } else if (IS_ERR(subsys_info->subsys_handle)) { ret = PTR_ERR(subsys_info->subsys_handle); goto reset_ctx; } return 0; reset_ctx: cnss_pr_err("Failed to get subsystem, err = %d\n", ret); clear_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state); plat_priv->driver_ops = NULL; out: ret = cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_REGISTER_DRIVER, true, driver_ops); return ret; } EXPORT_SYMBOL(cnss_wlan_register_driver); Loading @@ -763,18 +715,15 @@ EXPORT_SYMBOL(cnss_wlan_register_driver); void cnss_wlan_unregister_driver(struct cnss_wlan_driver *driver_ops) { struct cnss_plat_data *plat_priv = cnss_get_plat_priv(NULL); struct cnss_subsys_info *subsys_info; if (!plat_priv) { cnss_pr_err("plat_priv is NULL!\n"); return; } set_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state); subsys_info = &plat_priv->subsys_info; subsystem_put(subsys_info->subsys_handle); subsys_info->subsys_handle = NULL; plat_priv->driver_ops = NULL; cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_UNREGISTER_DRIVER, true, NULL); } EXPORT_SYMBOL(cnss_wlan_unregister_driver); Loading Loading @@ -934,30 +883,9 @@ static int cnss_qca6174_powerup(struct cnss_plat_data *plat_priv) goto power_off; } if (test_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state)) { ret = plat_priv->driver_ops->probe(pci_priv->pci_dev, pci_priv->pci_device_id); if (ret) { cnss_pr_err("Failed to probe host driver, err = %d\n", ret); goto suspend_link; } clear_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state); set_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state); } else if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) { ret = plat_priv->driver_ops->reinit(pci_priv->pci_dev, pci_priv->pci_device_id); if (ret) { cnss_pr_err("Failed to reinit host driver, err = %d\n", ret); goto suspend_link; } clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state); } else { cnss_pr_err("Driver state is not correct to power up!\n"); ret = -EINVAL; ret = cnss_driver_call_probe(plat_priv); if (ret) goto suspend_link; } return 0; suspend_link: Loading Loading @@ -985,7 +913,6 @@ static int cnss_qca6174_shutdown(struct cnss_plat_data *plat_priv) cnss_pci_set_monitor_wake_intr(pci_priv, false); cnss_pci_set_auto_suspended(pci_priv, 0); } else { set_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state); plat_priv->driver_ops->shutdown(pci_priv->pci_dev); } Loading Loading @@ -1017,6 +944,7 @@ static int cnss_qca6290_powerup(struct cnss_plat_data *plat_priv) { int ret = 0; struct cnss_pci_data *pci_priv = plat_priv->bus_priv; unsigned int timeout; if (!pci_priv) { cnss_pr_err("pci_priv is NULL!\n"); Loading Loading @@ -1048,43 +976,16 @@ static int cnss_qca6290_powerup(struct cnss_plat_data *plat_priv) cnss_set_pin_connect_status(plat_priv); if (qmi_bypass) goto skip_fw_ready; reinit_completion(&plat_priv->fw_ready_event); ret = wait_for_completion_timeout(&plat_priv->fw_ready_event, msecs_to_jiffies(FW_READY_TIMEOUT)); if (ret == 0) { cnss_pr_err("Timeout for FW ready event!\n"); ret = -EBUSY; goto stop_mhi; } skip_fw_ready: if (test_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state)) { ret = plat_priv->driver_ops->probe(pci_priv->pci_dev, pci_priv->pci_device_id); if (ret) { cnss_pr_err("Failed to probe host driver, err = %d\n", ret); goto stop_mhi; } clear_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state); set_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state); } else if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) { ret = plat_priv->driver_ops->reinit(pci_priv->pci_dev, pci_priv->pci_device_id); if (ret) { cnss_pr_err("Failed to reinit host driver, err = %d\n", ret); if (qmi_bypass) { ret = cnss_driver_call_probe(plat_priv); if (ret) goto stop_mhi; } clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state); } else { cnss_pr_err("Driver state is not correct to power up!\n"); ret = -EINVAL; goto stop_mhi; timeout = cnss_get_qmi_timeout(); cnss_pr_dbg("QMI timeout is %u ms\n", timeout); if (timeout) mod_timer(&plat_priv->fw_ready_timer, jiffies + msecs_to_jiffies(timeout << 1)); } return 0; Loading Loading @@ -1116,7 +1017,6 @@ static int cnss_qca6290_shutdown(struct cnss_plat_data *plat_priv) cnss_pci_set_monitor_wake_intr(pci_priv, false); cnss_pci_set_auto_suspended(pci_priv, 0); } else { set_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state); plat_priv->driver_ops->shutdown(pci_priv->pci_dev); } Loading Loading @@ -1146,6 +1046,9 @@ static int cnss_powerup(const struct subsys_desc *subsys_desc) return -ENODEV; } if (!plat_priv->driver_ops) return 0; switch (plat_priv->device_id) { case QCA6174_DEVICE_ID: ret = cnss_qca6174_powerup(plat_priv); Loading Loading @@ -1287,46 +1190,64 @@ static void cnss_crash_shutdown(const struct subsys_desc *subsys_desc) } } int cnss_self_recovery(struct device *dev, static int cnss_do_recovery(struct cnss_plat_data *plat_priv, enum cnss_recovery_reason reason) { struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); struct cnss_subsys_info *subsys_info; struct cnss_subsys_info *subsys_info = &plat_priv->subsys_info; if (!plat_priv) { cnss_pr_err("plat_priv is NULL!\n"); return -EINVAL; } plat_priv->recovery_count++; if (!plat_priv->plat_dev) { cnss_pr_err("plat_dev is NULL!\n"); return -EINVAL; if (plat_priv->device_id == QCA6174_DEVICE_ID) { cnss_shutdown(&subsys_info->subsys_desc, false); udelay(WLAN_RECOVERY_DELAY); cnss_powerup(&subsys_info->subsys_desc); return 0; } if (!plat_priv->driver_ops) { cnss_pr_err("Driver is not registered yet!\n"); return -EINVAL; if (!subsys_info->subsys_device) return 0; subsys_set_crash_status(subsys_info->subsys_device, true); subsystem_restart_dev(subsys_info->subsys_device); return 0; } static int cnss_driver_recovery_hdlr(struct cnss_plat_data *plat_priv, void *data) { struct cnss_recovery_data *recovery_data = data; int ret = 0; cnss_pr_dbg("Driver recovery is triggered: reason %d\n", recovery_data->reason); if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) { cnss_pr_err("Recovery is already in progress!\n"); return -EINVAL; ret = -EINVAL; goto out; } if (test_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state)) { cnss_pr_err("Driver load or unload is in progress!\n"); return -EINVAL; ret = -EINVAL; goto out; } subsys_info = &plat_priv->subsys_info; plat_priv->recovery_count++; set_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state); pm_stay_awake(dev); cnss_shutdown(&subsys_info->subsys_desc, false); udelay(WLAN_RECOVERY_DELAY); cnss_powerup(&subsys_info->subsys_desc); pm_relax(dev); ret = cnss_do_recovery(plat_priv, recovery_data->reason); out: kfree(data); return ret; } int cnss_self_recovery(struct device *dev, enum cnss_recovery_reason reason) { cnss_schedule_recovery(dev, reason); return 0; } EXPORT_SYMBOL(cnss_self_recovery); Loading @@ -1335,14 +1256,152 @@ void cnss_schedule_recovery(struct device *dev, enum cnss_recovery_reason reason) { struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); struct cnss_recovery_work_t *work = &plat_priv->cnss_recovery_work; struct cnss_recovery_data *data; int gfp = GFP_KERNEL; if (in_interrupt() || irqs_disabled()) gfp = GFP_ATOMIC; data = kzalloc(sizeof(*data), gfp); if (!data) return; work->dev = dev; work->reason = reason; queue_work(plat_priv->event_wq, &work->work); data->reason = reason; cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_RECOVERY, false, data); } EXPORT_SYMBOL(cnss_schedule_recovery); void fw_ready_timeout(unsigned long data) { struct cnss_plat_data *plat_priv = (struct cnss_plat_data *)data; struct cnss_pci_data *pci_priv = plat_priv->bus_priv; cnss_pr_err("Timeout waiting for FW ready indication!\n"); cnss_pci_stop_mhi(pci_priv); cnss_suspend_pci_link(pci_priv); cnss_power_off_device(plat_priv); } static int cnss_register_driver_hdlr(struct cnss_plat_data *plat_priv, void *data) { int ret = 0; struct cnss_subsys_info *subsys_info; set_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state); plat_priv->driver_ops = data; subsys_info = &plat_priv->subsys_info; ret = cnss_powerup(&subsys_info->subsys_desc); if (ret) { clear_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state); plat_priv->driver_ops = NULL; } return ret; } static int cnss_unregister_driver_hdlr(struct cnss_plat_data *plat_priv) { struct cnss_subsys_info *subsys_info; set_bit(CNSS_DRIVER_LOAD_UNLOAD, &plat_priv->driver_state); subsys_info = &plat_priv->subsys_info; cnss_shutdown(&subsys_info->subsys_desc, false); subsys_info->subsys_handle = NULL; plat_priv->driver_ops = NULL; return 0; } static void cnss_driver_event_work(struct work_struct *work) { struct cnss_plat_data *plat_priv = container_of(work, struct cnss_plat_data, event_work); struct cnss_driver_event *event; unsigned long flags; int ret = 0; if (!plat_priv) { cnss_pr_err("plat_priv is NULL!\n"); return; } cnss_pm_stay_awake(plat_priv); spin_lock_irqsave(&plat_priv->event_lock, flags); while (!list_empty(&plat_priv->event_list)) { event = list_first_entry(&plat_priv->event_list, struct cnss_driver_event, list); list_del(&event->list); spin_unlock_irqrestore(&plat_priv->event_lock, flags); cnss_pr_dbg("Processing driver event: %s%s(%d), state: 0x%lx\n", cnss_driver_event_to_str(event->type), event->sync ? "-sync" : "", event->type, plat_priv->driver_state); switch (event->type) { case CNSS_DRIVER_EVENT_SERVER_ARRIVE: ret = cnss_wlfw_server_arrive(plat_priv); break; case CNSS_DRIVER_EVENT_SERVER_EXIT: ret = cnss_wlfw_server_exit(plat_priv); break; case CNSS_DRIVER_EVENT_REQUEST_MEM: ret = cnss_pci_alloc_fw_mem(plat_priv->bus_priv); if (ret) break; ret = cnss_wlfw_respond_mem_send_sync(plat_priv); break; case CNSS_DRIVER_EVENT_FW_MEM_READY: ret = cnss_fw_mem_ready_hdlr(plat_priv); break; case CNSS_DRIVER_EVENT_FW_READY: ret = cnss_fw_ready_hdlr(plat_priv); break; case CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE: ret = cnss_cold_boot_cal_done_hdlr(plat_priv); break; case CNSS_DRIVER_EVENT_REGISTER_DRIVER: ret = cnss_register_driver_hdlr(plat_priv, event->data); break; case CNSS_DRIVER_EVENT_UNREGISTER_DRIVER: ret = cnss_unregister_driver_hdlr(plat_priv); break; case CNSS_DRIVER_EVENT_RECOVERY: ret = cnss_driver_recovery_hdlr(plat_priv, event->data); break; default: cnss_pr_err("Invalid driver event type: %d", event->type); kfree(event); continue; } spin_lock_irqsave(&plat_priv->event_lock, flags); if (event->sync) { event->ret = ret; complete(&event->complete); continue; } spin_unlock_irqrestore(&plat_priv->event_lock, flags); kfree(event); spin_lock_irqsave(&plat_priv->event_lock, flags); } spin_unlock_irqrestore(&plat_priv->event_lock, flags); cnss_pm_relax(plat_priv); } int cnss_register_subsys(struct cnss_plat_data *plat_priv) { int ret = 0; Loading Loading @@ -1377,7 +1436,22 @@ int cnss_register_subsys(struct cnss_plat_data *plat_priv) goto out; } subsys_info->subsys_handle = subsystem_get(subsys_info->subsys_desc.name); if (!subsys_info->subsys_handle) { cnss_pr_err("Failed to get subsys_handle!\n"); ret = -EINVAL; goto unregister_subsys; } else if (IS_ERR(subsys_info->subsys_handle)) { ret = PTR_ERR(subsys_info->subsys_handle); cnss_pr_err("Failed to do subsystem_get, err = %d\n", ret); goto unregister_subsys; } return 0; unregister_subsys: subsys_unregister(subsys_info->subsys_device); out: return ret; } Loading @@ -1387,6 +1461,7 @@ void cnss_unregister_subsys(struct cnss_plat_data *plat_priv) struct cnss_subsys_info *subsys_info; subsys_info = &plat_priv->subsys_info; subsystem_put(subsys_info->subsys_handle); subsys_unregister(subsys_info->subsys_device); } Loading Loading @@ -1616,16 +1691,12 @@ 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; } static void cnss_event_work_deinit(struct cnss_plat_data *plat_priv) { complete_all(&plat_priv->fw_ready_event); destroy_workqueue(plat_priv->event_wq); } Loading Loading @@ -1715,6 +1786,9 @@ static int cnss_probe(struct platform_device *plat_dev) if (ret) goto deinit_qmi; setup_timer(&plat_priv->fw_ready_timer, fw_ready_timeout, (unsigned long)plat_priv); register_pm_notifier(&cnss_pm_notifier); cnss_pr_info("Platform driver probed successfully.\n"); Loading
drivers/net/wireless/cnss2/main.h +5 −5 Original line number Diff line number Diff line Loading @@ -97,6 +97,9 @@ enum cnss_driver_event_type { CNSS_DRIVER_EVENT_FW_MEM_READY, CNSS_DRIVER_EVENT_FW_READY, CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE, CNSS_DRIVER_EVENT_REGISTER_DRIVER, CNSS_DRIVER_EVENT_UNREGISTER_DRIVER, CNSS_DRIVER_EVENT_RECOVERY, CNSS_DRIVER_EVENT_MAX, }; Loading @@ -110,9 +113,7 @@ enum cnss_driver_state { CNSS_DRIVER_RECOVERY, }; struct cnss_recovery_work_t { struct work_struct work; struct device *dev; struct cnss_recovery_data { enum cnss_recovery_reason reason; }; Loading Loading @@ -153,12 +154,10 @@ struct cnss_plat_data { uint32_t recovery_count; struct cnss_wlan_mac_info wlan_mac_info; unsigned long driver_state; struct completion fw_ready_event; struct list_head event_list; 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 @@ -171,6 +170,7 @@ struct cnss_plat_data { struct cnss_pin_connect_result pin_result; struct dentry *root_dentry; atomic_t pm_count; struct timer_list fw_ready_timer; }; void *cnss_bus_dev_to_bus_priv(struct device *dev); Loading
drivers/net/wireless/cnss2/qmi.c +6 −0 Original line number Diff line number Diff line Loading @@ -709,6 +709,12 @@ static void cnss_wlfw_clnt_ind(struct qmi_handle *handle, } } unsigned int cnss_get_qmi_timeout(void) { return qmi_timeout; } EXPORT_SYMBOL(cnss_get_qmi_timeout); int cnss_wlfw_server_arrive(struct cnss_plat_data *plat_priv) { int ret = 0; Loading
include/net/cnss2.h +3 −0 Original line number Diff line number Diff line Loading @@ -133,6 +133,8 @@ enum cnss_driver_mode { enum cnss_recovery_reason { CNSS_REASON_DEFAULT, CNSS_REASON_LINK_DOWN, CNSS_REASON_RDDM, CNSS_REASON_TIMEOUT, }; extern int cnss_wlan_register_driver(struct cnss_wlan_driver *driver); Loading Loading @@ -177,5 +179,6 @@ extern int cnss_wlan_enable(struct device *dev, enum cnss_driver_mode mode, const char *host_version); extern int cnss_wlan_disable(struct device *dev, enum cnss_driver_mode mode); extern unsigned int cnss_get_qmi_timeout(void); #endif /* _NET_CNSS2_H */