Loading drivers/net/wireless/cnss/cnss_common.c +121 −0 Original line number Diff line number Diff line Loading @@ -18,10 +18,131 @@ #include <linux/pm_wakeup.h> #include <linux/sched.h> #include <linux/suspend.h> #include <linux/mutex.h> #include <linux/rwsem.h> #include <net/cnss.h> #include <net/cfg80211.h> static DEFINE_MUTEX(unsafe_channel_list_lock); static DEFINE_MUTEX(dfs_nol_info_lock); static struct cnss_unsafe_channel_list { u16 unsafe_ch_count; u16 unsafe_ch_list[CNSS_MAX_CH_NUM]; } unsafe_channel_list; static struct cnss_dfs_nol_info { void *dfs_nol_info; u16 dfs_nol_info_len; } dfs_nol_info; int cnss_set_wlan_unsafe_channel(u16 *unsafe_ch_list, u16 ch_count) { struct cnss_unsafe_channel_list *unsafe_list; mutex_lock(&unsafe_channel_list_lock); if ((!unsafe_ch_list) || (!ch_count) || (ch_count > CNSS_MAX_CH_NUM)) { mutex_unlock(&unsafe_channel_list_lock); return -EINVAL; } unsafe_list = &unsafe_channel_list; unsafe_channel_list.unsafe_ch_count = ch_count; memcpy( (char *)unsafe_list->unsafe_ch_list, (char *)unsafe_ch_list, ch_count * sizeof(u16)); mutex_unlock(&unsafe_channel_list_lock); return 0; } EXPORT_SYMBOL(cnss_set_wlan_unsafe_channel); int cnss_get_wlan_unsafe_channel( u16 *unsafe_ch_list, u16 *ch_count, u16 buf_len) { struct cnss_unsafe_channel_list *unsafe_list; mutex_lock(&unsafe_channel_list_lock); if (!unsafe_ch_list || !ch_count) { mutex_unlock(&unsafe_channel_list_lock); return -EINVAL; } unsafe_list = &unsafe_channel_list; if (buf_len < (unsafe_list->unsafe_ch_count * sizeof(u16))) { mutex_unlock(&unsafe_channel_list_lock); return -ENOMEM; } *ch_count = unsafe_list->unsafe_ch_count; memcpy( (char *)unsafe_ch_list, (char *)unsafe_list->unsafe_ch_list, unsafe_list->unsafe_ch_count * sizeof(u16)); mutex_unlock(&unsafe_channel_list_lock); return 0; } EXPORT_SYMBOL(cnss_get_wlan_unsafe_channel); int cnss_wlan_set_dfs_nol(const void *info, u16 info_len) { void *temp; struct cnss_dfs_nol_info *dfs_info; mutex_lock(&dfs_nol_info_lock); if (!info || !info_len) { mutex_unlock(&dfs_nol_info_lock); return -EINVAL; } temp = kmalloc(info_len, GFP_KERNEL); if (!temp) { mutex_unlock(&dfs_nol_info_lock); return -ENOMEM; } memcpy(temp, info, info_len); dfs_info = &dfs_nol_info; kfree(dfs_info->dfs_nol_info); dfs_info->dfs_nol_info = temp; dfs_info->dfs_nol_info_len = info_len; mutex_unlock(&dfs_nol_info_lock); return 0; } EXPORT_SYMBOL(cnss_wlan_set_dfs_nol); int cnss_wlan_get_dfs_nol(void *info, u16 info_len) { int len; struct cnss_dfs_nol_info *dfs_info; mutex_lock(&dfs_nol_info_lock); if (!info || !info_len) { mutex_unlock(&dfs_nol_info_lock); return -EINVAL; } dfs_info = &dfs_nol_info; if (dfs_info->dfs_nol_info == NULL || dfs_info->dfs_nol_info_len == 0) { mutex_unlock(&dfs_nol_info_lock); return -ENOENT; } len = min(info_len, dfs_info->dfs_nol_info_len); memcpy(info, dfs_info->dfs_nol_info, len); mutex_unlock(&dfs_nol_info_lock); return len; } EXPORT_SYMBOL(cnss_wlan_get_dfs_nol); void cnss_init_work(struct work_struct *work, work_func_t func) { INIT_WORK(work, func); Loading drivers/net/wireless/cnss/cnss_pci.c +120 −92 Original line number Diff line number Diff line Loading @@ -236,8 +236,6 @@ static struct cnss_data { void *ramdump_addr; phys_addr_t ramdump_phys; struct msm_dump_data dump_data; u16 unsafe_ch_count; u16 unsafe_ch_list[CNSS_MAX_CH_NUM]; struct cnss_wlan_driver *driver; struct pci_dev *pdev; const struct pci_device_id *id; Loading @@ -252,7 +250,6 @@ static struct cnss_data { bool notify_modem_status; struct pci_saved_state *saved_state; u16 revision_id; u16 dfs_nol_info_len; bool recovery_in_progress; bool fw_available; struct codeswap_codeseg_info *cnss_seg_info; Loading @@ -272,7 +269,6 @@ static struct cnss_data { struct wakeup_source ws; uint32_t recovery_count; enum cnss_driver_status driver_status; void *dfs_nol_info; #ifdef CONFIG_CNSS_SECURE_FW void *fw_mem; #endif Loading Loading @@ -1756,12 +1752,12 @@ static ssize_t fw_image_setup_store(struct device *dev, static DEVICE_ATTR(fw_image_setup, S_IRUSR | S_IWUSR, fw_image_setup_show, fw_image_setup_store); void recovery_work_handler(struct work_struct *recovery) void cnss_pci_recovery_work_handler(struct work_struct *recovery) { cnss_device_self_recovery(); } DECLARE_WORK(recovery_work, recovery_work_handler); DECLARE_WORK(recovery_work, cnss_pci_recovery_work_handler); void cnss_schedule_recovery_work(void) { Loading Loading @@ -2167,90 +2163,6 @@ cut_power: } EXPORT_SYMBOL(cnss_wlan_unregister_driver); int cnss_set_wlan_unsafe_channel(u16 *unsafe_ch_list, u16 ch_count) { if (!penv) return -ENODEV; if ((!unsafe_ch_list) || (ch_count > CNSS_MAX_CH_NUM)) return -EINVAL; penv->unsafe_ch_count = ch_count; if (ch_count != 0) memcpy((char *)penv->unsafe_ch_list, (char *)unsafe_ch_list, ch_count * sizeof(u16)); return 0; } EXPORT_SYMBOL(cnss_set_wlan_unsafe_channel); int cnss_get_wlan_unsafe_channel(u16 *unsafe_ch_list, u16 *ch_count, u16 buf_len) { if (!penv) return -ENODEV; if (!unsafe_ch_list || !ch_count) return -EINVAL; if (buf_len < (penv->unsafe_ch_count * sizeof(u16))) return -ENOMEM; *ch_count = penv->unsafe_ch_count; memcpy((char *)unsafe_ch_list, (char *)penv->unsafe_ch_list, penv->unsafe_ch_count * sizeof(u16)); return 0; } EXPORT_SYMBOL(cnss_get_wlan_unsafe_channel); int cnss_wlan_set_dfs_nol(const void *info, u16 info_len) { void *temp; if (!penv) return -ENODEV; if (!info || !info_len) return -EINVAL; temp = kmalloc(info_len, GFP_KERNEL); if (!temp) return -ENOMEM; memcpy(temp, info, info_len); kfree(penv->dfs_nol_info); penv->dfs_nol_info = temp; penv->dfs_nol_info_len = info_len; return 0; } EXPORT_SYMBOL(cnss_wlan_set_dfs_nol); int cnss_wlan_get_dfs_nol(void *info, u16 info_len) { int len; if (!penv) return -ENODEV; if (!info || !info_len) return -EINVAL; if (penv->dfs_nol_info == NULL || penv->dfs_nol_info_len == 0) return -ENOENT; len = min(info_len, penv->dfs_nol_info_len); memcpy(info, penv->dfs_nol_info, len); return len; } EXPORT_SYMBOL(cnss_wlan_get_dfs_nol); #ifdef CONFIG_PCI_MSM int cnss_wlan_pm_control(bool vote) { Loading @@ -2277,6 +2189,32 @@ void cnss_release_pm_sem(void) } EXPORT_SYMBOL(cnss_release_pm_sem); void cnss_pci_schedule_recovery_work(void) { schedule_work(&recovery_work); } EXPORT_SYMBOL(cnss_pci_schedule_recovery_work); void *cnss_pci_get_virt_ramdump_mem(unsigned long *size) { if (!penv || !penv->pldev) return NULL; *size = penv->ramdump_size; return penv->ramdump_addr; } EXPORT_SYMBOL(cnss_pci_get_virt_ramdump_mem); void cnss_pci_device_crashed(void) { if (penv && penv->subsys) { subsys_set_crash_status(penv->subsys, true); subsystem_restart_dev(penv->subsys); } } EXPORT_SYMBOL(cnss_pci_device_crashed); int cnss_get_ramdump_mem(unsigned long *address, unsigned long *size) { if (!penv || !penv->pldev) Loading Loading @@ -2452,6 +2390,32 @@ err_wlan_vreg_on: return ret; } void cnss_pci_device_self_recovery(void) { if (!penv) return; if (penv->recovery_in_progress) { pr_err("cnss: Recovery already in progress\n"); return; } if (penv->driver_status == CNSS_LOAD_UNLOAD) { pr_err("cnss: load unload in progress\n"); return; } penv->recovery_count++; penv->recovery_in_progress = true; cnss_pm_wake_lock(&penv->ws); cnss_shutdown(NULL, false); msleep(WLAN_RECOVERY_DELAY); cnss_powerup(NULL); cnss_pm_wake_lock_release(&penv->ws); penv->recovery_in_progress = false; } EXPORT_SYMBOL(cnss_pci_device_self_recovery); static int cnss_ramdump(int enable, const struct subsys_desc *subsys) { struct ramdump_segment segment; Loading Loading @@ -2805,8 +2769,6 @@ static int cnss_remove(struct platform_device *pdev) cnss_pm_wake_lock_destroy(&penv->ws); kfree(penv->dfs_nol_info); if (penv->bus_client) msm_bus_scale_unregister_client(penv->bus_client); Loading Loading @@ -2900,6 +2862,72 @@ void cnss_remove_pm_qos(void) } EXPORT_SYMBOL(cnss_remove_pm_qos); void cnss_pci_request_pm_qos_type(int latency_type, u32 qos_val) { if (!penv) { pr_err("%s: penv is NULL\n", __func__); return; } pm_qos_add_request(&penv->qos_request, latency_type, qos_val); } EXPORT_SYMBOL(cnss_pci_request_pm_qos_type); void cnss_pci_request_pm_qos(u32 qos_val) { if (!penv) { pr_err("%s: penv is NULL\n", __func__); return; } pm_qos_add_request(&penv->qos_request, PM_QOS_CPU_DMA_LATENCY, qos_val); } EXPORT_SYMBOL(cnss_pci_request_pm_qos); void cnss_pci_remove_pm_qos(void) { if (!penv) { pr_err("%s: penv is NULL\n", __func__); return; } pm_qos_remove_request(&penv->qos_request); } EXPORT_SYMBOL(cnss_pci_remove_pm_qos); int cnss_pci_request_bus_bandwidth(int bandwidth) { int ret = 0; if (!penv) return -ENODEV; if (!penv->bus_client) return -ENOSYS; switch (bandwidth) { case CNSS_BUS_WIDTH_NONE: case CNSS_BUS_WIDTH_LOW: case CNSS_BUS_WIDTH_MEDIUM: case CNSS_BUS_WIDTH_HIGH: ret = msm_bus_scale_client_update_request( penv->bus_client, bandwidth); if (!ret) { penv->current_bandwidth_vote = bandwidth; } else { pr_err("%s: could not set bus bandwidth %d, ret = %d\n", __func__, bandwidth, ret); } break; default: pr_err("%s: Invalid request %d", __func__, bandwidth); ret = -EINVAL; } return ret; } EXPORT_SYMBOL(cnss_pci_request_bus_bandwidth); int cnss_request_bus_bandwidth(int bandwidth) { int ret = 0; Loading drivers/net/wireless/cnss/cnss_sdio.c +72 −107 Original line number Diff line number Diff line Loading @@ -45,16 +45,6 @@ #define CNSS_DUMP_MAGIC_VER_V2 0x42445953 #define CNSS_DUMP_NAME "CNSS_WLAN" struct cnss_unsafe_channel_list { u16 unsafe_ch_count; u16 unsafe_ch_list[CNSS_MAX_CH_NUM]; }; struct cnss_dfs_nol_info { void *dfs_nol_info; u16 dfs_nol_info_len; }; struct cnss_sdio_regulator { struct regulator *wlan_io; struct regulator *wlan_xtal; Loading Loading @@ -84,8 +74,6 @@ struct cnss_ssr_info { static struct cnss_sdio_data { struct cnss_sdio_regulator regulator; struct platform_device *pdev; struct cnss_dfs_nol_info dfs_info; struct cnss_unsafe_channel_list unsafe_list; struct cnss_sdio_info cnss_sdio_info; struct cnss_ssr_info ssr_info; struct pm_qos_request qos_request; Loading Loading @@ -137,13 +125,7 @@ static const struct sdio_device_id ar6k_id_table[] = { }; MODULE_DEVICE_TABLE(sdio, ar6k_id_table); int cnss_request_bus_bandwidth(int bandwidth) { return 0; } EXPORT_SYMBOL(cnss_request_bus_bandwidth); void cnss_request_pm_qos_type(int latency_type, u32 qos_val) void cnss_sdio_request_pm_qos_type(int latency_type, u32 qos_val) { if (!cnss_pdata) return; Loading @@ -151,9 +133,15 @@ void cnss_request_pm_qos_type(int latency_type, u32 qos_val) pr_debug("%s: PM QoS value: %d\n", __func__, qos_val); pm_qos_add_request(&cnss_pdata->qos_request, latency_type, qos_val); } EXPORT_SYMBOL(cnss_request_pm_qos_type); EXPORT_SYMBOL(cnss_sdio_request_pm_qos_type); void cnss_request_pm_qos(u32 qos_val) int cnss_sdio_request_bus_bandwidth(int bandwidth) { return 0; } EXPORT_SYMBOL(cnss_sdio_request_bus_bandwidth); void cnss_sdio_request_pm_qos(u32 qos_val) { if (!cnss_pdata) return; Loading @@ -163,9 +151,9 @@ void cnss_request_pm_qos(u32 qos_val) &cnss_pdata->qos_request, PM_QOS_CPU_DMA_LATENCY, qos_val); } EXPORT_SYMBOL(cnss_request_pm_qos); EXPORT_SYMBOL(cnss_sdio_request_pm_qos); void cnss_remove_pm_qos(void) void cnss_sdio_remove_pm_qos(void) { if (!cnss_pdata) return; Loading @@ -173,103 +161,45 @@ void cnss_remove_pm_qos(void) pm_qos_remove_request(&cnss_pdata->qos_request); pr_debug("%s: PM QoS removed\n", __func__); } EXPORT_SYMBOL(cnss_remove_pm_qos); EXPORT_SYMBOL(cnss_sdio_remove_pm_qos); int cnss_set_wlan_unsafe_channel(u16 *unsafe_ch_list, u16 ch_count) int cnss_request_bus_bandwidth(int bandwidth) { struct cnss_unsafe_channel_list *unsafe_list; if (!cnss_pdata) return -ENODEV; if ((!unsafe_ch_list) || (!ch_count) || (ch_count > CNSS_MAX_CH_NUM)) return -EINVAL; unsafe_list = &cnss_pdata->unsafe_list; unsafe_list->unsafe_ch_count = ch_count; memcpy( (char *)unsafe_list->unsafe_ch_list, (char *)unsafe_ch_list, ch_count * sizeof(u16)); return 0; } EXPORT_SYMBOL(cnss_set_wlan_unsafe_channel); EXPORT_SYMBOL(cnss_request_bus_bandwidth); int cnss_get_wlan_unsafe_channel( u16 *unsafe_ch_list, u16 *ch_count, u16 buf_len) void cnss_request_pm_qos_type(int latency_type, u32 qos_val) { struct cnss_unsafe_channel_list *unsafe_list; if (!cnss_pdata) return -ENODEV; if (!unsafe_ch_list || !ch_count) return -EINVAL; unsafe_list = &cnss_pdata->unsafe_list; if (buf_len < (unsafe_list->unsafe_ch_count * sizeof(u16))) return -ENOMEM; *ch_count = unsafe_list->unsafe_ch_count; memcpy( (char *)unsafe_ch_list, (char *)unsafe_list->unsafe_ch_list, unsafe_list->unsafe_ch_count * sizeof(u16)); return; return 0; pr_debug("%s: PM QoS value: %d\n", __func__, qos_val); pm_qos_add_request(&cnss_pdata->qos_request, latency_type, qos_val); } EXPORT_SYMBOL(cnss_get_wlan_unsafe_channel); EXPORT_SYMBOL(cnss_request_pm_qos_type); int cnss_wlan_set_dfs_nol(const void *info, u16 info_len) void cnss_request_pm_qos(u32 qos_val) { void *temp; struct cnss_dfs_nol_info *dfs_info; if (!cnss_pdata) return -ENODEV; if (!info || !info_len) return -EINVAL; temp = kmalloc(info_len, GFP_KERNEL); if (!temp) return -ENOMEM; memcpy(temp, info, info_len); dfs_info = &cnss_pdata->dfs_info; kfree(dfs_info->dfs_nol_info); dfs_info->dfs_nol_info = temp; dfs_info->dfs_nol_info_len = info_len; return; return 0; pr_debug("%s: PM QoS value: %d\n", __func__, qos_val); pm_qos_add_request( &cnss_pdata->qos_request, PM_QOS_CPU_DMA_LATENCY, qos_val); } EXPORT_SYMBOL(cnss_wlan_set_dfs_nol); EXPORT_SYMBOL(cnss_request_pm_qos); int cnss_wlan_get_dfs_nol(void *info, u16 info_len) void cnss_remove_pm_qos(void) { int len; struct cnss_dfs_nol_info *dfs_info; if (!cnss_pdata) return -ENODEV; if (!info || !info_len) return -EINVAL; dfs_info = &cnss_pdata->dfs_info; if (dfs_info->dfs_nol_info == NULL || dfs_info->dfs_nol_info_len == 0) return -ENOENT; len = min(info_len, dfs_info->dfs_nol_info_len); memcpy(info, dfs_info->dfs_nol_info, len); return; return len; pm_qos_remove_request(&cnss_pdata->qos_request); pr_debug("%s: PM QoS removed\n", __func__); } EXPORT_SYMBOL(cnss_wlan_get_dfs_nol); EXPORT_SYMBOL(cnss_remove_pm_qos); static int cnss_sdio_shutdown(const struct subsys_desc *subsys, bool force_stop) { Loading Loading @@ -537,6 +467,39 @@ static void cnss_ramdump_cleanup(void) ssr_info->ramdump_dev = NULL; } void *cnss_sdio_get_virt_ramdump_mem(unsigned long *size) { if (!cnss_pdata || !cnss_pdata->pdev) return NULL; *size = cnss_pdata->ssr_info.ramdump_size; return cnss_pdata->ssr_info.ramdump_addr; } EXPORT_SYMBOL(cnss_sdio_get_virt_ramdump_mem); void cnss_sdio_device_self_recovery(void) { cnss_sdio_shutdown(NULL, false); msleep(WLAN_RECOVERY_DELAY); cnss_sdio_powerup(NULL); } EXPORT_SYMBOL(cnss_sdio_device_self_recovery); void cnss_sdio_device_crashed(void) { struct cnss_ssr_info *ssr_info; if (!cnss_pdata) return; ssr_info = &cnss_pdata->ssr_info; if (ssr_info->subsys) { subsys_set_crash_status(ssr_info->subsys, true); subsystem_restart_dev(ssr_info->subsys); } } EXPORT_SYMBOL(cnss_sdio_device_crashed); int cnss_get_ramdump_mem(unsigned long *address, unsigned long *size) { struct cnss_ssr_info *ssr_info; Loading Loading @@ -571,12 +534,18 @@ void cnss_device_self_recovery(void) } EXPORT_SYMBOL(cnss_device_self_recovery); static void recovery_work_handler(struct work_struct *recovery) static void cnss_sdio_recovery_work_handler(struct work_struct *recovery) { cnss_device_self_recovery(); } DECLARE_WORK(recovery_work, recovery_work_handler); DECLARE_WORK(recovery_work, cnss_sdio_recovery_work_handler); void cnss_sdio_schedule_recovery_work(void) { schedule_work(&recovery_work); } EXPORT_SYMBOL(cnss_sdio_schedule_recovery_work); void cnss_schedule_recovery_work(void) { Loading Loading @@ -1074,15 +1043,11 @@ err_wlan_enable_regulator: static int cnss_sdio_remove(struct platform_device *pdev) { struct cnss_dfs_nol_info *dfs_info; if (!cnss_pdata) return -ENODEV; cnss_sdio_wlan_exit(); dfs_info = &cnss_pdata->dfs_info; kfree(dfs_info->dfs_nol_info); cnss_subsys_exit(); cnss_ramdump_cleanup(); cnss_sdio_release_resource(); Loading include/net/cnss.h +24 −0 Original line number Diff line number Diff line Loading @@ -122,6 +122,8 @@ extern void cnss_wlan_unregister_driver(struct cnss_wlan_driver *driver); extern int cnss_get_fw_files(struct cnss_fw_files *pfw_files); extern int cnss_get_fw_files_for_target(struct cnss_fw_files *pfw_files, u32 target_type, u32 target_version); extern int cnss_pci_request_bus_bandwidth(int bandwidth); extern int cnss_sdio_request_bus_bandwidth(int bandwidth); extern int cnss_request_bus_bandwidth(int bandwidth); extern int cnss_get_sha_hash(const u8 *data, u32 data_len, Loading @@ -140,6 +142,15 @@ extern void cnss_release_pm_sem(void); extern void cnss_request_pm_qos_type(int latency_type, u32 qos_val); extern void cnss_request_pm_qos(u32 qos_val); extern void cnss_remove_pm_qos(void); extern void cnss_pci_request_pm_qos_type(int latency_type, u32 qos_val); extern void cnss_pci_request_pm_qos(u32 qos_val); extern void cnss_pci_remove_pm_qos(void); extern void cnss_sdio_request_pm_qos_type(int latency_type, u32 qos_val); extern void cnss_sdio_request_pm_qos(u32 qos_val); extern void cnss_sdio_remove_pm_qos(void); extern int cnss_get_platform_cap(struct cnss_platform_cap *cap); extern void cnss_set_driver_status(enum cnss_driver_status driver_status); Loading Loading @@ -184,11 +195,24 @@ extern int cnss_get_wlan_unsafe_channel(u16 *unsafe_ch_list, u16 *ch_count, u16 buf_len); extern int cnss_wlan_set_dfs_nol(const void *info, u16 info_len); extern int cnss_wlan_get_dfs_nol(void *info, u16 info_len); extern void cnss_device_crashed(void); extern void cnss_sdio_device_crashed(void); extern void cnss_pci_device_crashed(void); extern void cnss_device_self_recovery(void); extern void cnss_pci_device_self_recovery(void); extern void cnss_sdio_device_self_recovery(void); extern int cnss_get_ramdump_mem(unsigned long *address, unsigned long *size); extern void *cnss_get_virt_ramdump_mem(unsigned long *size); extern void *cnss_pci_get_virt_ramdump_mem(unsigned long *size); extern void *cnss_sdio_get_virt_ramdump_mem(unsigned long *size); extern void cnss_schedule_recovery_work(void); extern void cnss_sdio_schedule_recovery_work(void); extern void cnss_pci_schedule_recovery_work(void); enum { CNSS_RESET_SOC = 0, Loading Loading
drivers/net/wireless/cnss/cnss_common.c +121 −0 Original line number Diff line number Diff line Loading @@ -18,10 +18,131 @@ #include <linux/pm_wakeup.h> #include <linux/sched.h> #include <linux/suspend.h> #include <linux/mutex.h> #include <linux/rwsem.h> #include <net/cnss.h> #include <net/cfg80211.h> static DEFINE_MUTEX(unsafe_channel_list_lock); static DEFINE_MUTEX(dfs_nol_info_lock); static struct cnss_unsafe_channel_list { u16 unsafe_ch_count; u16 unsafe_ch_list[CNSS_MAX_CH_NUM]; } unsafe_channel_list; static struct cnss_dfs_nol_info { void *dfs_nol_info; u16 dfs_nol_info_len; } dfs_nol_info; int cnss_set_wlan_unsafe_channel(u16 *unsafe_ch_list, u16 ch_count) { struct cnss_unsafe_channel_list *unsafe_list; mutex_lock(&unsafe_channel_list_lock); if ((!unsafe_ch_list) || (!ch_count) || (ch_count > CNSS_MAX_CH_NUM)) { mutex_unlock(&unsafe_channel_list_lock); return -EINVAL; } unsafe_list = &unsafe_channel_list; unsafe_channel_list.unsafe_ch_count = ch_count; memcpy( (char *)unsafe_list->unsafe_ch_list, (char *)unsafe_ch_list, ch_count * sizeof(u16)); mutex_unlock(&unsafe_channel_list_lock); return 0; } EXPORT_SYMBOL(cnss_set_wlan_unsafe_channel); int cnss_get_wlan_unsafe_channel( u16 *unsafe_ch_list, u16 *ch_count, u16 buf_len) { struct cnss_unsafe_channel_list *unsafe_list; mutex_lock(&unsafe_channel_list_lock); if (!unsafe_ch_list || !ch_count) { mutex_unlock(&unsafe_channel_list_lock); return -EINVAL; } unsafe_list = &unsafe_channel_list; if (buf_len < (unsafe_list->unsafe_ch_count * sizeof(u16))) { mutex_unlock(&unsafe_channel_list_lock); return -ENOMEM; } *ch_count = unsafe_list->unsafe_ch_count; memcpy( (char *)unsafe_ch_list, (char *)unsafe_list->unsafe_ch_list, unsafe_list->unsafe_ch_count * sizeof(u16)); mutex_unlock(&unsafe_channel_list_lock); return 0; } EXPORT_SYMBOL(cnss_get_wlan_unsafe_channel); int cnss_wlan_set_dfs_nol(const void *info, u16 info_len) { void *temp; struct cnss_dfs_nol_info *dfs_info; mutex_lock(&dfs_nol_info_lock); if (!info || !info_len) { mutex_unlock(&dfs_nol_info_lock); return -EINVAL; } temp = kmalloc(info_len, GFP_KERNEL); if (!temp) { mutex_unlock(&dfs_nol_info_lock); return -ENOMEM; } memcpy(temp, info, info_len); dfs_info = &dfs_nol_info; kfree(dfs_info->dfs_nol_info); dfs_info->dfs_nol_info = temp; dfs_info->dfs_nol_info_len = info_len; mutex_unlock(&dfs_nol_info_lock); return 0; } EXPORT_SYMBOL(cnss_wlan_set_dfs_nol); int cnss_wlan_get_dfs_nol(void *info, u16 info_len) { int len; struct cnss_dfs_nol_info *dfs_info; mutex_lock(&dfs_nol_info_lock); if (!info || !info_len) { mutex_unlock(&dfs_nol_info_lock); return -EINVAL; } dfs_info = &dfs_nol_info; if (dfs_info->dfs_nol_info == NULL || dfs_info->dfs_nol_info_len == 0) { mutex_unlock(&dfs_nol_info_lock); return -ENOENT; } len = min(info_len, dfs_info->dfs_nol_info_len); memcpy(info, dfs_info->dfs_nol_info, len); mutex_unlock(&dfs_nol_info_lock); return len; } EXPORT_SYMBOL(cnss_wlan_get_dfs_nol); void cnss_init_work(struct work_struct *work, work_func_t func) { INIT_WORK(work, func); Loading
drivers/net/wireless/cnss/cnss_pci.c +120 −92 Original line number Diff line number Diff line Loading @@ -236,8 +236,6 @@ static struct cnss_data { void *ramdump_addr; phys_addr_t ramdump_phys; struct msm_dump_data dump_data; u16 unsafe_ch_count; u16 unsafe_ch_list[CNSS_MAX_CH_NUM]; struct cnss_wlan_driver *driver; struct pci_dev *pdev; const struct pci_device_id *id; Loading @@ -252,7 +250,6 @@ static struct cnss_data { bool notify_modem_status; struct pci_saved_state *saved_state; u16 revision_id; u16 dfs_nol_info_len; bool recovery_in_progress; bool fw_available; struct codeswap_codeseg_info *cnss_seg_info; Loading @@ -272,7 +269,6 @@ static struct cnss_data { struct wakeup_source ws; uint32_t recovery_count; enum cnss_driver_status driver_status; void *dfs_nol_info; #ifdef CONFIG_CNSS_SECURE_FW void *fw_mem; #endif Loading Loading @@ -1756,12 +1752,12 @@ static ssize_t fw_image_setup_store(struct device *dev, static DEVICE_ATTR(fw_image_setup, S_IRUSR | S_IWUSR, fw_image_setup_show, fw_image_setup_store); void recovery_work_handler(struct work_struct *recovery) void cnss_pci_recovery_work_handler(struct work_struct *recovery) { cnss_device_self_recovery(); } DECLARE_WORK(recovery_work, recovery_work_handler); DECLARE_WORK(recovery_work, cnss_pci_recovery_work_handler); void cnss_schedule_recovery_work(void) { Loading Loading @@ -2167,90 +2163,6 @@ cut_power: } EXPORT_SYMBOL(cnss_wlan_unregister_driver); int cnss_set_wlan_unsafe_channel(u16 *unsafe_ch_list, u16 ch_count) { if (!penv) return -ENODEV; if ((!unsafe_ch_list) || (ch_count > CNSS_MAX_CH_NUM)) return -EINVAL; penv->unsafe_ch_count = ch_count; if (ch_count != 0) memcpy((char *)penv->unsafe_ch_list, (char *)unsafe_ch_list, ch_count * sizeof(u16)); return 0; } EXPORT_SYMBOL(cnss_set_wlan_unsafe_channel); int cnss_get_wlan_unsafe_channel(u16 *unsafe_ch_list, u16 *ch_count, u16 buf_len) { if (!penv) return -ENODEV; if (!unsafe_ch_list || !ch_count) return -EINVAL; if (buf_len < (penv->unsafe_ch_count * sizeof(u16))) return -ENOMEM; *ch_count = penv->unsafe_ch_count; memcpy((char *)unsafe_ch_list, (char *)penv->unsafe_ch_list, penv->unsafe_ch_count * sizeof(u16)); return 0; } EXPORT_SYMBOL(cnss_get_wlan_unsafe_channel); int cnss_wlan_set_dfs_nol(const void *info, u16 info_len) { void *temp; if (!penv) return -ENODEV; if (!info || !info_len) return -EINVAL; temp = kmalloc(info_len, GFP_KERNEL); if (!temp) return -ENOMEM; memcpy(temp, info, info_len); kfree(penv->dfs_nol_info); penv->dfs_nol_info = temp; penv->dfs_nol_info_len = info_len; return 0; } EXPORT_SYMBOL(cnss_wlan_set_dfs_nol); int cnss_wlan_get_dfs_nol(void *info, u16 info_len) { int len; if (!penv) return -ENODEV; if (!info || !info_len) return -EINVAL; if (penv->dfs_nol_info == NULL || penv->dfs_nol_info_len == 0) return -ENOENT; len = min(info_len, penv->dfs_nol_info_len); memcpy(info, penv->dfs_nol_info, len); return len; } EXPORT_SYMBOL(cnss_wlan_get_dfs_nol); #ifdef CONFIG_PCI_MSM int cnss_wlan_pm_control(bool vote) { Loading @@ -2277,6 +2189,32 @@ void cnss_release_pm_sem(void) } EXPORT_SYMBOL(cnss_release_pm_sem); void cnss_pci_schedule_recovery_work(void) { schedule_work(&recovery_work); } EXPORT_SYMBOL(cnss_pci_schedule_recovery_work); void *cnss_pci_get_virt_ramdump_mem(unsigned long *size) { if (!penv || !penv->pldev) return NULL; *size = penv->ramdump_size; return penv->ramdump_addr; } EXPORT_SYMBOL(cnss_pci_get_virt_ramdump_mem); void cnss_pci_device_crashed(void) { if (penv && penv->subsys) { subsys_set_crash_status(penv->subsys, true); subsystem_restart_dev(penv->subsys); } } EXPORT_SYMBOL(cnss_pci_device_crashed); int cnss_get_ramdump_mem(unsigned long *address, unsigned long *size) { if (!penv || !penv->pldev) Loading Loading @@ -2452,6 +2390,32 @@ err_wlan_vreg_on: return ret; } void cnss_pci_device_self_recovery(void) { if (!penv) return; if (penv->recovery_in_progress) { pr_err("cnss: Recovery already in progress\n"); return; } if (penv->driver_status == CNSS_LOAD_UNLOAD) { pr_err("cnss: load unload in progress\n"); return; } penv->recovery_count++; penv->recovery_in_progress = true; cnss_pm_wake_lock(&penv->ws); cnss_shutdown(NULL, false); msleep(WLAN_RECOVERY_DELAY); cnss_powerup(NULL); cnss_pm_wake_lock_release(&penv->ws); penv->recovery_in_progress = false; } EXPORT_SYMBOL(cnss_pci_device_self_recovery); static int cnss_ramdump(int enable, const struct subsys_desc *subsys) { struct ramdump_segment segment; Loading Loading @@ -2805,8 +2769,6 @@ static int cnss_remove(struct platform_device *pdev) cnss_pm_wake_lock_destroy(&penv->ws); kfree(penv->dfs_nol_info); if (penv->bus_client) msm_bus_scale_unregister_client(penv->bus_client); Loading Loading @@ -2900,6 +2862,72 @@ void cnss_remove_pm_qos(void) } EXPORT_SYMBOL(cnss_remove_pm_qos); void cnss_pci_request_pm_qos_type(int latency_type, u32 qos_val) { if (!penv) { pr_err("%s: penv is NULL\n", __func__); return; } pm_qos_add_request(&penv->qos_request, latency_type, qos_val); } EXPORT_SYMBOL(cnss_pci_request_pm_qos_type); void cnss_pci_request_pm_qos(u32 qos_val) { if (!penv) { pr_err("%s: penv is NULL\n", __func__); return; } pm_qos_add_request(&penv->qos_request, PM_QOS_CPU_DMA_LATENCY, qos_val); } EXPORT_SYMBOL(cnss_pci_request_pm_qos); void cnss_pci_remove_pm_qos(void) { if (!penv) { pr_err("%s: penv is NULL\n", __func__); return; } pm_qos_remove_request(&penv->qos_request); } EXPORT_SYMBOL(cnss_pci_remove_pm_qos); int cnss_pci_request_bus_bandwidth(int bandwidth) { int ret = 0; if (!penv) return -ENODEV; if (!penv->bus_client) return -ENOSYS; switch (bandwidth) { case CNSS_BUS_WIDTH_NONE: case CNSS_BUS_WIDTH_LOW: case CNSS_BUS_WIDTH_MEDIUM: case CNSS_BUS_WIDTH_HIGH: ret = msm_bus_scale_client_update_request( penv->bus_client, bandwidth); if (!ret) { penv->current_bandwidth_vote = bandwidth; } else { pr_err("%s: could not set bus bandwidth %d, ret = %d\n", __func__, bandwidth, ret); } break; default: pr_err("%s: Invalid request %d", __func__, bandwidth); ret = -EINVAL; } return ret; } EXPORT_SYMBOL(cnss_pci_request_bus_bandwidth); int cnss_request_bus_bandwidth(int bandwidth) { int ret = 0; Loading
drivers/net/wireless/cnss/cnss_sdio.c +72 −107 Original line number Diff line number Diff line Loading @@ -45,16 +45,6 @@ #define CNSS_DUMP_MAGIC_VER_V2 0x42445953 #define CNSS_DUMP_NAME "CNSS_WLAN" struct cnss_unsafe_channel_list { u16 unsafe_ch_count; u16 unsafe_ch_list[CNSS_MAX_CH_NUM]; }; struct cnss_dfs_nol_info { void *dfs_nol_info; u16 dfs_nol_info_len; }; struct cnss_sdio_regulator { struct regulator *wlan_io; struct regulator *wlan_xtal; Loading Loading @@ -84,8 +74,6 @@ struct cnss_ssr_info { static struct cnss_sdio_data { struct cnss_sdio_regulator regulator; struct platform_device *pdev; struct cnss_dfs_nol_info dfs_info; struct cnss_unsafe_channel_list unsafe_list; struct cnss_sdio_info cnss_sdio_info; struct cnss_ssr_info ssr_info; struct pm_qos_request qos_request; Loading Loading @@ -137,13 +125,7 @@ static const struct sdio_device_id ar6k_id_table[] = { }; MODULE_DEVICE_TABLE(sdio, ar6k_id_table); int cnss_request_bus_bandwidth(int bandwidth) { return 0; } EXPORT_SYMBOL(cnss_request_bus_bandwidth); void cnss_request_pm_qos_type(int latency_type, u32 qos_val) void cnss_sdio_request_pm_qos_type(int latency_type, u32 qos_val) { if (!cnss_pdata) return; Loading @@ -151,9 +133,15 @@ void cnss_request_pm_qos_type(int latency_type, u32 qos_val) pr_debug("%s: PM QoS value: %d\n", __func__, qos_val); pm_qos_add_request(&cnss_pdata->qos_request, latency_type, qos_val); } EXPORT_SYMBOL(cnss_request_pm_qos_type); EXPORT_SYMBOL(cnss_sdio_request_pm_qos_type); void cnss_request_pm_qos(u32 qos_val) int cnss_sdio_request_bus_bandwidth(int bandwidth) { return 0; } EXPORT_SYMBOL(cnss_sdio_request_bus_bandwidth); void cnss_sdio_request_pm_qos(u32 qos_val) { if (!cnss_pdata) return; Loading @@ -163,9 +151,9 @@ void cnss_request_pm_qos(u32 qos_val) &cnss_pdata->qos_request, PM_QOS_CPU_DMA_LATENCY, qos_val); } EXPORT_SYMBOL(cnss_request_pm_qos); EXPORT_SYMBOL(cnss_sdio_request_pm_qos); void cnss_remove_pm_qos(void) void cnss_sdio_remove_pm_qos(void) { if (!cnss_pdata) return; Loading @@ -173,103 +161,45 @@ void cnss_remove_pm_qos(void) pm_qos_remove_request(&cnss_pdata->qos_request); pr_debug("%s: PM QoS removed\n", __func__); } EXPORT_SYMBOL(cnss_remove_pm_qos); EXPORT_SYMBOL(cnss_sdio_remove_pm_qos); int cnss_set_wlan_unsafe_channel(u16 *unsafe_ch_list, u16 ch_count) int cnss_request_bus_bandwidth(int bandwidth) { struct cnss_unsafe_channel_list *unsafe_list; if (!cnss_pdata) return -ENODEV; if ((!unsafe_ch_list) || (!ch_count) || (ch_count > CNSS_MAX_CH_NUM)) return -EINVAL; unsafe_list = &cnss_pdata->unsafe_list; unsafe_list->unsafe_ch_count = ch_count; memcpy( (char *)unsafe_list->unsafe_ch_list, (char *)unsafe_ch_list, ch_count * sizeof(u16)); return 0; } EXPORT_SYMBOL(cnss_set_wlan_unsafe_channel); EXPORT_SYMBOL(cnss_request_bus_bandwidth); int cnss_get_wlan_unsafe_channel( u16 *unsafe_ch_list, u16 *ch_count, u16 buf_len) void cnss_request_pm_qos_type(int latency_type, u32 qos_val) { struct cnss_unsafe_channel_list *unsafe_list; if (!cnss_pdata) return -ENODEV; if (!unsafe_ch_list || !ch_count) return -EINVAL; unsafe_list = &cnss_pdata->unsafe_list; if (buf_len < (unsafe_list->unsafe_ch_count * sizeof(u16))) return -ENOMEM; *ch_count = unsafe_list->unsafe_ch_count; memcpy( (char *)unsafe_ch_list, (char *)unsafe_list->unsafe_ch_list, unsafe_list->unsafe_ch_count * sizeof(u16)); return; return 0; pr_debug("%s: PM QoS value: %d\n", __func__, qos_val); pm_qos_add_request(&cnss_pdata->qos_request, latency_type, qos_val); } EXPORT_SYMBOL(cnss_get_wlan_unsafe_channel); EXPORT_SYMBOL(cnss_request_pm_qos_type); int cnss_wlan_set_dfs_nol(const void *info, u16 info_len) void cnss_request_pm_qos(u32 qos_val) { void *temp; struct cnss_dfs_nol_info *dfs_info; if (!cnss_pdata) return -ENODEV; if (!info || !info_len) return -EINVAL; temp = kmalloc(info_len, GFP_KERNEL); if (!temp) return -ENOMEM; memcpy(temp, info, info_len); dfs_info = &cnss_pdata->dfs_info; kfree(dfs_info->dfs_nol_info); dfs_info->dfs_nol_info = temp; dfs_info->dfs_nol_info_len = info_len; return; return 0; pr_debug("%s: PM QoS value: %d\n", __func__, qos_val); pm_qos_add_request( &cnss_pdata->qos_request, PM_QOS_CPU_DMA_LATENCY, qos_val); } EXPORT_SYMBOL(cnss_wlan_set_dfs_nol); EXPORT_SYMBOL(cnss_request_pm_qos); int cnss_wlan_get_dfs_nol(void *info, u16 info_len) void cnss_remove_pm_qos(void) { int len; struct cnss_dfs_nol_info *dfs_info; if (!cnss_pdata) return -ENODEV; if (!info || !info_len) return -EINVAL; dfs_info = &cnss_pdata->dfs_info; if (dfs_info->dfs_nol_info == NULL || dfs_info->dfs_nol_info_len == 0) return -ENOENT; len = min(info_len, dfs_info->dfs_nol_info_len); memcpy(info, dfs_info->dfs_nol_info, len); return; return len; pm_qos_remove_request(&cnss_pdata->qos_request); pr_debug("%s: PM QoS removed\n", __func__); } EXPORT_SYMBOL(cnss_wlan_get_dfs_nol); EXPORT_SYMBOL(cnss_remove_pm_qos); static int cnss_sdio_shutdown(const struct subsys_desc *subsys, bool force_stop) { Loading Loading @@ -537,6 +467,39 @@ static void cnss_ramdump_cleanup(void) ssr_info->ramdump_dev = NULL; } void *cnss_sdio_get_virt_ramdump_mem(unsigned long *size) { if (!cnss_pdata || !cnss_pdata->pdev) return NULL; *size = cnss_pdata->ssr_info.ramdump_size; return cnss_pdata->ssr_info.ramdump_addr; } EXPORT_SYMBOL(cnss_sdio_get_virt_ramdump_mem); void cnss_sdio_device_self_recovery(void) { cnss_sdio_shutdown(NULL, false); msleep(WLAN_RECOVERY_DELAY); cnss_sdio_powerup(NULL); } EXPORT_SYMBOL(cnss_sdio_device_self_recovery); void cnss_sdio_device_crashed(void) { struct cnss_ssr_info *ssr_info; if (!cnss_pdata) return; ssr_info = &cnss_pdata->ssr_info; if (ssr_info->subsys) { subsys_set_crash_status(ssr_info->subsys, true); subsystem_restart_dev(ssr_info->subsys); } } EXPORT_SYMBOL(cnss_sdio_device_crashed); int cnss_get_ramdump_mem(unsigned long *address, unsigned long *size) { struct cnss_ssr_info *ssr_info; Loading Loading @@ -571,12 +534,18 @@ void cnss_device_self_recovery(void) } EXPORT_SYMBOL(cnss_device_self_recovery); static void recovery_work_handler(struct work_struct *recovery) static void cnss_sdio_recovery_work_handler(struct work_struct *recovery) { cnss_device_self_recovery(); } DECLARE_WORK(recovery_work, recovery_work_handler); DECLARE_WORK(recovery_work, cnss_sdio_recovery_work_handler); void cnss_sdio_schedule_recovery_work(void) { schedule_work(&recovery_work); } EXPORT_SYMBOL(cnss_sdio_schedule_recovery_work); void cnss_schedule_recovery_work(void) { Loading Loading @@ -1074,15 +1043,11 @@ err_wlan_enable_regulator: static int cnss_sdio_remove(struct platform_device *pdev) { struct cnss_dfs_nol_info *dfs_info; if (!cnss_pdata) return -ENODEV; cnss_sdio_wlan_exit(); dfs_info = &cnss_pdata->dfs_info; kfree(dfs_info->dfs_nol_info); cnss_subsys_exit(); cnss_ramdump_cleanup(); cnss_sdio_release_resource(); Loading
include/net/cnss.h +24 −0 Original line number Diff line number Diff line Loading @@ -122,6 +122,8 @@ extern void cnss_wlan_unregister_driver(struct cnss_wlan_driver *driver); extern int cnss_get_fw_files(struct cnss_fw_files *pfw_files); extern int cnss_get_fw_files_for_target(struct cnss_fw_files *pfw_files, u32 target_type, u32 target_version); extern int cnss_pci_request_bus_bandwidth(int bandwidth); extern int cnss_sdio_request_bus_bandwidth(int bandwidth); extern int cnss_request_bus_bandwidth(int bandwidth); extern int cnss_get_sha_hash(const u8 *data, u32 data_len, Loading @@ -140,6 +142,15 @@ extern void cnss_release_pm_sem(void); extern void cnss_request_pm_qos_type(int latency_type, u32 qos_val); extern void cnss_request_pm_qos(u32 qos_val); extern void cnss_remove_pm_qos(void); extern void cnss_pci_request_pm_qos_type(int latency_type, u32 qos_val); extern void cnss_pci_request_pm_qos(u32 qos_val); extern void cnss_pci_remove_pm_qos(void); extern void cnss_sdio_request_pm_qos_type(int latency_type, u32 qos_val); extern void cnss_sdio_request_pm_qos(u32 qos_val); extern void cnss_sdio_remove_pm_qos(void); extern int cnss_get_platform_cap(struct cnss_platform_cap *cap); extern void cnss_set_driver_status(enum cnss_driver_status driver_status); Loading Loading @@ -184,11 +195,24 @@ extern int cnss_get_wlan_unsafe_channel(u16 *unsafe_ch_list, u16 *ch_count, u16 buf_len); extern int cnss_wlan_set_dfs_nol(const void *info, u16 info_len); extern int cnss_wlan_get_dfs_nol(void *info, u16 info_len); extern void cnss_device_crashed(void); extern void cnss_sdio_device_crashed(void); extern void cnss_pci_device_crashed(void); extern void cnss_device_self_recovery(void); extern void cnss_pci_device_self_recovery(void); extern void cnss_sdio_device_self_recovery(void); extern int cnss_get_ramdump_mem(unsigned long *address, unsigned long *size); extern void *cnss_get_virt_ramdump_mem(unsigned long *size); extern void *cnss_pci_get_virt_ramdump_mem(unsigned long *size); extern void *cnss_sdio_get_virt_ramdump_mem(unsigned long *size); extern void cnss_schedule_recovery_work(void); extern void cnss_sdio_schedule_recovery_work(void); extern void cnss_pci_schedule_recovery_work(void); enum { CNSS_RESET_SOC = 0, Loading