Loading drivers/soc/qcom/icnss.c +77 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ #include <linux/of.h> #include <linux/of_irq.h> #include <linux/soc/qcom/qmi.h> #include <linux/sysfs.h> #include <soc/qcom/memory_dump.h> #include <soc/qcom/icnss.h> #include <soc/qcom/secure_buffer.h> Loading Loading @@ -141,6 +142,18 @@ static const char * const icnss_pdr_cause[] = { [ICNSS_HOST_ERROR] = "Host error", }; static ssize_t icnss_sysfs_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { atomic_set(&penv->is_shutdown, true); icnss_pr_dbg("Received shutdown indication"); return count; } static struct kobj_attribute icnss_sysfs_attribute = __ATTR(shutdown, 0660, NULL, icnss_sysfs_store); static int icnss_assign_msa_perm(struct icnss_mem_region_info *mem_region, enum icnss_msa_perm new_perm) { Loading Loading @@ -1250,6 +1263,32 @@ static int icnss_driver_event_unregister_driver(void *data) return 0; } static int icnss_call_driver_remove(struct icnss_priv *priv) { icnss_pr_dbg("Calling driver remove state: 0x%lx\n", priv->state); clear_bit(ICNSS_FW_READY, &priv->state); if (test_bit(ICNSS_DRIVER_UNLOADING, &priv->state)) return 0; if (!test_bit(ICNSS_DRIVER_PROBED, &priv->state)) return 0; if (!priv->ops || !priv->ops->remove) return 0; set_bit(ICNSS_DRIVER_UNLOADING, &priv->state); priv->ops->remove(&priv->pdev->dev); clear_bit(ICNSS_DRIVER_UNLOADING, &priv->state); clear_bit(ICNSS_DRIVER_PROBED, &priv->state); icnss_hw_power_off(priv); return 0; } static int icnss_fw_crashed(struct icnss_priv *priv, struct icnss_event_pd_service_down_data *event_data) { Loading Loading @@ -1442,6 +1481,12 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb, priv->is_ssr = true; if (code == SUBSYS_BEFORE_SHUTDOWN && !notif->crashed && atomic_read(&priv->is_shutdown)) { atomic_set(&priv->is_shutdown, false); icnss_call_driver_remove(priv); } if (code == SUBSYS_BEFORE_SHUTDOWN && !notif->crashed && test_bit(ICNSS_BLOCK_SHUTDOWN, &priv->state)) { if (!wait_for_completion_timeout(&priv->unblock_shutdown, Loading Loading @@ -3103,6 +3148,34 @@ static void icnss_debugfs_destroy(struct icnss_priv *priv) debugfs_remove_recursive(priv->root_dentry); } static void icnss_sysfs_create(struct icnss_priv *priv) { struct kobject *icnss_kobject; int error = 0; atomic_set(&priv->is_shutdown, false); icnss_kobject = kobject_create_and_add("shutdown_wlan", kernel_kobj); if (!icnss_kobject) { icnss_pr_err("Unable to create kernel object"); return; } priv->icnss_kobject = icnss_kobject; error = sysfs_create_file(icnss_kobject, &icnss_sysfs_attribute.attr); if (error) icnss_pr_err("Unable to create icnss sysfs file"); } static void icnss_sysfs_destroy(struct icnss_priv *priv) { struct kobject *icnss_kobject; icnss_kobject = priv->icnss_kobject; if (icnss_kobject) kobject_put(icnss_kobject); } static int icnss_get_vbatt_info(struct icnss_priv *priv) { Loading Loading @@ -3325,6 +3398,8 @@ static int icnss_probe(struct platform_device *pdev) icnss_debugfs_create(priv); icnss_sysfs_create(priv); ret = device_init_wakeup(&priv->pdev->dev, true); if (ret) icnss_pr_err("Failed to init platform device wakeup source, err = %d\n", Loading Loading @@ -3356,6 +3431,8 @@ static int icnss_remove(struct platform_device *pdev) icnss_debugfs_destroy(penv); icnss_sysfs_destroy(penv); complete_all(&penv->unblock_shutdown); icnss_modem_ssr_unregister_notifier(penv); Loading drivers/soc/qcom/icnss_private.h +4 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ #include <linux/adc-tm-clients.h> #include <linux/iio/consumer.h> #include <asm/dma-iommu.h> #include <linux/kobject.h> #define icnss_ipc_log_string(_x...) do { \ if (icnss_ipc_log_context) \ Loading Loading @@ -361,6 +362,9 @@ struct icnss_priv { bool vbatt_supported; char function_name[WLFW_FUNCTION_NAME_LEN + 1]; bool is_ssr; struct kobject *icnss_kobject; atomic_t is_shutdown; }; int icnss_call_driver_uevent(struct icnss_priv *priv, Loading Loading
drivers/soc/qcom/icnss.c +77 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ #include <linux/of.h> #include <linux/of_irq.h> #include <linux/soc/qcom/qmi.h> #include <linux/sysfs.h> #include <soc/qcom/memory_dump.h> #include <soc/qcom/icnss.h> #include <soc/qcom/secure_buffer.h> Loading Loading @@ -141,6 +142,18 @@ static const char * const icnss_pdr_cause[] = { [ICNSS_HOST_ERROR] = "Host error", }; static ssize_t icnss_sysfs_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { atomic_set(&penv->is_shutdown, true); icnss_pr_dbg("Received shutdown indication"); return count; } static struct kobj_attribute icnss_sysfs_attribute = __ATTR(shutdown, 0660, NULL, icnss_sysfs_store); static int icnss_assign_msa_perm(struct icnss_mem_region_info *mem_region, enum icnss_msa_perm new_perm) { Loading Loading @@ -1250,6 +1263,32 @@ static int icnss_driver_event_unregister_driver(void *data) return 0; } static int icnss_call_driver_remove(struct icnss_priv *priv) { icnss_pr_dbg("Calling driver remove state: 0x%lx\n", priv->state); clear_bit(ICNSS_FW_READY, &priv->state); if (test_bit(ICNSS_DRIVER_UNLOADING, &priv->state)) return 0; if (!test_bit(ICNSS_DRIVER_PROBED, &priv->state)) return 0; if (!priv->ops || !priv->ops->remove) return 0; set_bit(ICNSS_DRIVER_UNLOADING, &priv->state); priv->ops->remove(&priv->pdev->dev); clear_bit(ICNSS_DRIVER_UNLOADING, &priv->state); clear_bit(ICNSS_DRIVER_PROBED, &priv->state); icnss_hw_power_off(priv); return 0; } static int icnss_fw_crashed(struct icnss_priv *priv, struct icnss_event_pd_service_down_data *event_data) { Loading Loading @@ -1442,6 +1481,12 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb, priv->is_ssr = true; if (code == SUBSYS_BEFORE_SHUTDOWN && !notif->crashed && atomic_read(&priv->is_shutdown)) { atomic_set(&priv->is_shutdown, false); icnss_call_driver_remove(priv); } if (code == SUBSYS_BEFORE_SHUTDOWN && !notif->crashed && test_bit(ICNSS_BLOCK_SHUTDOWN, &priv->state)) { if (!wait_for_completion_timeout(&priv->unblock_shutdown, Loading Loading @@ -3103,6 +3148,34 @@ static void icnss_debugfs_destroy(struct icnss_priv *priv) debugfs_remove_recursive(priv->root_dentry); } static void icnss_sysfs_create(struct icnss_priv *priv) { struct kobject *icnss_kobject; int error = 0; atomic_set(&priv->is_shutdown, false); icnss_kobject = kobject_create_and_add("shutdown_wlan", kernel_kobj); if (!icnss_kobject) { icnss_pr_err("Unable to create kernel object"); return; } priv->icnss_kobject = icnss_kobject; error = sysfs_create_file(icnss_kobject, &icnss_sysfs_attribute.attr); if (error) icnss_pr_err("Unable to create icnss sysfs file"); } static void icnss_sysfs_destroy(struct icnss_priv *priv) { struct kobject *icnss_kobject; icnss_kobject = priv->icnss_kobject; if (icnss_kobject) kobject_put(icnss_kobject); } static int icnss_get_vbatt_info(struct icnss_priv *priv) { Loading Loading @@ -3325,6 +3398,8 @@ static int icnss_probe(struct platform_device *pdev) icnss_debugfs_create(priv); icnss_sysfs_create(priv); ret = device_init_wakeup(&priv->pdev->dev, true); if (ret) icnss_pr_err("Failed to init platform device wakeup source, err = %d\n", Loading Loading @@ -3356,6 +3431,8 @@ static int icnss_remove(struct platform_device *pdev) icnss_debugfs_destroy(penv); icnss_sysfs_destroy(penv); complete_all(&penv->unblock_shutdown); icnss_modem_ssr_unregister_notifier(penv); Loading
drivers/soc/qcom/icnss_private.h +4 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ #include <linux/adc-tm-clients.h> #include <linux/iio/consumer.h> #include <asm/dma-iommu.h> #include <linux/kobject.h> #define icnss_ipc_log_string(_x...) do { \ if (icnss_ipc_log_context) \ Loading Loading @@ -361,6 +362,9 @@ struct icnss_priv { bool vbatt_supported; char function_name[WLFW_FUNCTION_NAME_LEN + 1]; bool is_ssr; struct kobject *icnss_kobject; atomic_t is_shutdown; }; int icnss_call_driver_uevent(struct icnss_priv *priv, Loading