Loading drivers/soc/qcom/icnss.c +143 −77 Original line number Diff line number Diff line Loading @@ -1388,6 +1388,35 @@ static int icnss_msa0_ramdump(struct icnss_priv *priv) return do_ramdump(priv->msa0_dump_dev, &segment, 1); } static void icnss_update_state_send_modem_shutdown(struct icnss_priv *priv, void *data) { struct notif_data *notif = data; int ret = 0; if (!notif->crashed) { if (atomic_read(&priv->is_shutdown)) { atomic_set(&priv->is_shutdown, false); if (!test_bit(ICNSS_PD_RESTART, &priv->state) && !test_bit(ICNSS_SHUTDOWN_DONE, &priv->state)) { icnss_call_driver_remove(priv); } } if (test_bit(ICNSS_BLOCK_SHUTDOWN, &priv->state)) { if (!wait_for_completion_timeout( &priv->unblock_shutdown, msecs_to_jiffies(PROBE_TIMEOUT))) icnss_pr_err("modem block shutdown timeout\n"); } ret = wlfw_send_modem_shutdown_msg(priv); if (ret < 0) icnss_pr_err("Fail to send modem shutdown Indication %d\n", ret); } } static int icnss_modem_notifier_nb(struct notifier_block *nb, unsigned long code, void *data) Loading @@ -1397,7 +1426,6 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb, struct icnss_priv *priv = container_of(nb, struct icnss_priv, modem_ssr_nb); struct icnss_uevent_fw_down_data fw_down_data; int ret = 0; icnss_pr_vdbg("Modem-Notify: event %lu\n", code); Loading @@ -1413,28 +1441,7 @@ 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); if (!test_bit(ICNSS_PD_RESTART, &priv->state) && !test_bit(ICNSS_SHUTDOWN_DONE, &priv->state)) { 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, msecs_to_jiffies(PROBE_TIMEOUT))) icnss_pr_err("modem block shutdown timeout\n"); } if (code == SUBSYS_BEFORE_SHUTDOWN && !notif->crashed) { ret = wlfw_send_modem_shutdown_msg(priv); if (ret < 0) icnss_pr_err("Fail to send modem shutdown Indication %d\n", ret); } icnss_update_state_send_modem_shutdown(priv, data); if (test_bit(ICNSS_PDR_REGISTERED, &priv->state)) { set_bit(ICNSS_FW_DOWN, &priv->state); Loading Loading @@ -2991,23 +2998,16 @@ static int icnss_regread_show(struct seq_file *s, void *data) return 0; } static ssize_t icnss_regread_write(struct file *fp, const char __user *user_buf, size_t count, loff_t *off) static ssize_t icnss_reg_parse(const char __user *user_buf, size_t count, struct icnss_reg_info *reg_info_ptr) { struct icnss_priv *priv = ((struct seq_file *)fp->private_data)->private; char buf[64]; char *sptr, *token; unsigned int len = 0; uint32_t reg_offset, mem_type; uint32_t data_len = 0; uint8_t *reg_buf = NULL; char buf[64] = {0}; char *sptr = NULL, *token = NULL; const char *delim = " "; int ret = 0; unsigned int len = 0; if (!test_bit(ICNSS_FW_READY, &priv->state) || !test_bit(ICNSS_POWER_ON, &priv->state)) return -EINVAL; if (user_buf == NULL) return -EFAULT; len = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, len)) Loading @@ -3023,7 +3023,7 @@ static ssize_t icnss_regread_write(struct file *fp, const char __user *user_buf, if (!sptr) return -EINVAL; if (kstrtou32(token, 0, &mem_type)) if (kstrtou32(token, 0, ®_info_ptr->mem_type)) return -EINVAL; token = strsep(&sptr, delim); Loading @@ -3033,32 +3033,53 @@ static ssize_t icnss_regread_write(struct file *fp, const char __user *user_buf, if (!sptr) return -EINVAL; if (kstrtou32(token, 0, ®_offset)) if (kstrtou32(token, 0, ®_info_ptr->reg_offset)) return -EINVAL; token = strsep(&sptr, delim); if (!token) return -EINVAL; if (kstrtou32(token, 0, &data_len)) if (kstrtou32(token, 0, ®_info_ptr->data_len)) return -EINVAL; if (data_len == 0 || data_len > WLFW_MAX_DATA_SIZE) if (reg_info_ptr->data_len == 0 || reg_info_ptr->data_len > WLFW_MAX_DATA_SIZE) return -EINVAL; return 0; } static ssize_t icnss_regread_write(struct file *fp, const char __user *user_buf, size_t count, loff_t *off) { struct icnss_priv *priv = ((struct seq_file *)fp->private_data)->private; uint8_t *reg_buf = NULL; int ret = 0; struct icnss_reg_info reg_info; if (!test_bit(ICNSS_FW_READY, &priv->state) || !test_bit(ICNSS_POWER_ON, &priv->state)) return -EINVAL; ret = icnss_reg_parse(user_buf, count, ®_info); if (ret) return ret; mutex_lock(&priv->dev_lock); kfree(priv->diag_reg_read_buf); priv->diag_reg_read_buf = NULL; reg_buf = kzalloc(data_len, GFP_KERNEL); reg_buf = kzalloc(reg_info.data_len, GFP_KERNEL); if (!reg_buf) { mutex_unlock(&priv->dev_lock); return -ENOMEM; } ret = wlfw_athdiag_read_send_sync_msg(priv, reg_offset, mem_type, data_len, ret = wlfw_athdiag_read_send_sync_msg(priv, reg_info.reg_offset, reg_info.mem_type, reg_info.data_len, reg_buf); if (ret) { kfree(reg_buf); Loading @@ -3066,9 +3087,9 @@ static ssize_t icnss_regread_write(struct file *fp, const char __user *user_buf, return ret; } priv->diag_reg_read_addr = reg_offset; priv->diag_reg_read_mem_type = mem_type; priv->diag_reg_read_len = data_len; priv->diag_reg_read_addr = reg_info.reg_offset; priv->diag_reg_read_mem_type = reg_info.mem_type; priv->diag_reg_read_len = reg_info.data_len; priv->diag_reg_read_buf = reg_buf; mutex_unlock(&priv->dev_lock); Loading Loading @@ -3211,37 +3232,12 @@ static int icnss_get_vbatt_info(struct icnss_priv *priv) return 0; } static int icnss_probe(struct platform_device *pdev) static int icnss_resource_parse(struct icnss_priv *priv) { int ret = 0; struct resource *res; int i; int ret = 0, i = 0; struct platform_device *pdev = priv->pdev; struct device *dev = &pdev->dev; struct icnss_priv *priv; const __be32 *addrp; u64 prop_size = 0; struct device_node *np; u32 addr_win[2]; if (penv) { icnss_pr_err("Driver is already initialized\n"); return -EEXIST; } icnss_pr_dbg("Platform driver probe\n"); priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; priv->magic = ICNSS_MAGIC; dev_set_drvdata(dev, priv); priv->pdev = pdev; priv->vreg_info = icnss_vreg_info; icnss_allow_recursive_recovery(dev); struct resource *res; if (of_property_read_bool(pdev->dev.of_node, "qcom,icnss-adc_tm")) { ret = icnss_get_vbatt_info(priv); Loading Loading @@ -3294,6 +3290,21 @@ static int icnss_probe(struct platform_device *pdev) } } return 0; out: return ret; } static int icnss_msa_dt_parse(struct icnss_priv *priv) { int ret = 0; struct platform_device *pdev = priv->pdev; struct device *dev = &pdev->dev; struct device_node *np = NULL; u64 prop_size = 0; const __be32 *addrp = NULL; np = of_parse_phandle(dev->of_node, "qcom,wlan-msa-fixed-region", 0); if (np) { Loading Loading @@ -3342,6 +3353,20 @@ static int icnss_probe(struct platform_device *pdev) icnss_pr_dbg("MSA pa: %pa, MSA va: 0x%pK MSA Memory Size: 0x%x\n", &priv->msa_pa, (void *)priv->msa_va, priv->msa_mem_size); return 0; out: return ret; } static int icnss_smmu_dt_parse(struct icnss_priv *priv) { int ret = 0; struct platform_device *pdev = priv->pdev; struct device *dev = &pdev->dev; struct resource *res; u32 addr_win[2]; ret = of_property_read_u32_array(dev->of_node, "qcom,iommu-dma-addr-pool", addr_win, Loading @@ -3367,6 +3392,47 @@ static int icnss_probe(struct platform_device *pdev) } } return 0; } static int icnss_probe(struct platform_device *pdev) { int ret = 0; struct device *dev = &pdev->dev; struct icnss_priv *priv; if (penv) { icnss_pr_err("Driver is already initialized\n"); return -EEXIST; } icnss_pr_dbg("Platform driver probe\n"); priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; priv->magic = ICNSS_MAGIC; dev_set_drvdata(dev, priv); priv->pdev = pdev; priv->vreg_info = icnss_vreg_info; icnss_allow_recursive_recovery(dev); ret = icnss_resource_parse(priv); if (ret) goto out; ret = icnss_msa_dt_parse(priv); if (ret) goto out; ret = icnss_smmu_dt_parse(priv); if (ret) goto out; spin_lock_init(&priv->event_lock); spin_lock_init(&priv->on_off_lock); mutex_init(&priv->dev_lock); Loading drivers/soc/qcom/icnss_private.h +6 −0 Original line number Diff line number Diff line Loading @@ -352,6 +352,12 @@ struct icnss_priv { }; struct icnss_reg_info { uint32_t mem_type; uint32_t reg_offset; uint32_t data_len; }; int icnss_call_driver_uevent(struct icnss_priv *priv, enum icnss_uevent uevent, void *data); int icnss_driver_event_post(enum icnss_driver_event_type type, Loading Loading
drivers/soc/qcom/icnss.c +143 −77 Original line number Diff line number Diff line Loading @@ -1388,6 +1388,35 @@ static int icnss_msa0_ramdump(struct icnss_priv *priv) return do_ramdump(priv->msa0_dump_dev, &segment, 1); } static void icnss_update_state_send_modem_shutdown(struct icnss_priv *priv, void *data) { struct notif_data *notif = data; int ret = 0; if (!notif->crashed) { if (atomic_read(&priv->is_shutdown)) { atomic_set(&priv->is_shutdown, false); if (!test_bit(ICNSS_PD_RESTART, &priv->state) && !test_bit(ICNSS_SHUTDOWN_DONE, &priv->state)) { icnss_call_driver_remove(priv); } } if (test_bit(ICNSS_BLOCK_SHUTDOWN, &priv->state)) { if (!wait_for_completion_timeout( &priv->unblock_shutdown, msecs_to_jiffies(PROBE_TIMEOUT))) icnss_pr_err("modem block shutdown timeout\n"); } ret = wlfw_send_modem_shutdown_msg(priv); if (ret < 0) icnss_pr_err("Fail to send modem shutdown Indication %d\n", ret); } } static int icnss_modem_notifier_nb(struct notifier_block *nb, unsigned long code, void *data) Loading @@ -1397,7 +1426,6 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb, struct icnss_priv *priv = container_of(nb, struct icnss_priv, modem_ssr_nb); struct icnss_uevent_fw_down_data fw_down_data; int ret = 0; icnss_pr_vdbg("Modem-Notify: event %lu\n", code); Loading @@ -1413,28 +1441,7 @@ 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); if (!test_bit(ICNSS_PD_RESTART, &priv->state) && !test_bit(ICNSS_SHUTDOWN_DONE, &priv->state)) { 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, msecs_to_jiffies(PROBE_TIMEOUT))) icnss_pr_err("modem block shutdown timeout\n"); } if (code == SUBSYS_BEFORE_SHUTDOWN && !notif->crashed) { ret = wlfw_send_modem_shutdown_msg(priv); if (ret < 0) icnss_pr_err("Fail to send modem shutdown Indication %d\n", ret); } icnss_update_state_send_modem_shutdown(priv, data); if (test_bit(ICNSS_PDR_REGISTERED, &priv->state)) { set_bit(ICNSS_FW_DOWN, &priv->state); Loading Loading @@ -2991,23 +2998,16 @@ static int icnss_regread_show(struct seq_file *s, void *data) return 0; } static ssize_t icnss_regread_write(struct file *fp, const char __user *user_buf, size_t count, loff_t *off) static ssize_t icnss_reg_parse(const char __user *user_buf, size_t count, struct icnss_reg_info *reg_info_ptr) { struct icnss_priv *priv = ((struct seq_file *)fp->private_data)->private; char buf[64]; char *sptr, *token; unsigned int len = 0; uint32_t reg_offset, mem_type; uint32_t data_len = 0; uint8_t *reg_buf = NULL; char buf[64] = {0}; char *sptr = NULL, *token = NULL; const char *delim = " "; int ret = 0; unsigned int len = 0; if (!test_bit(ICNSS_FW_READY, &priv->state) || !test_bit(ICNSS_POWER_ON, &priv->state)) return -EINVAL; if (user_buf == NULL) return -EFAULT; len = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, len)) Loading @@ -3023,7 +3023,7 @@ static ssize_t icnss_regread_write(struct file *fp, const char __user *user_buf, if (!sptr) return -EINVAL; if (kstrtou32(token, 0, &mem_type)) if (kstrtou32(token, 0, ®_info_ptr->mem_type)) return -EINVAL; token = strsep(&sptr, delim); Loading @@ -3033,32 +3033,53 @@ static ssize_t icnss_regread_write(struct file *fp, const char __user *user_buf, if (!sptr) return -EINVAL; if (kstrtou32(token, 0, ®_offset)) if (kstrtou32(token, 0, ®_info_ptr->reg_offset)) return -EINVAL; token = strsep(&sptr, delim); if (!token) return -EINVAL; if (kstrtou32(token, 0, &data_len)) if (kstrtou32(token, 0, ®_info_ptr->data_len)) return -EINVAL; if (data_len == 0 || data_len > WLFW_MAX_DATA_SIZE) if (reg_info_ptr->data_len == 0 || reg_info_ptr->data_len > WLFW_MAX_DATA_SIZE) return -EINVAL; return 0; } static ssize_t icnss_regread_write(struct file *fp, const char __user *user_buf, size_t count, loff_t *off) { struct icnss_priv *priv = ((struct seq_file *)fp->private_data)->private; uint8_t *reg_buf = NULL; int ret = 0; struct icnss_reg_info reg_info; if (!test_bit(ICNSS_FW_READY, &priv->state) || !test_bit(ICNSS_POWER_ON, &priv->state)) return -EINVAL; ret = icnss_reg_parse(user_buf, count, ®_info); if (ret) return ret; mutex_lock(&priv->dev_lock); kfree(priv->diag_reg_read_buf); priv->diag_reg_read_buf = NULL; reg_buf = kzalloc(data_len, GFP_KERNEL); reg_buf = kzalloc(reg_info.data_len, GFP_KERNEL); if (!reg_buf) { mutex_unlock(&priv->dev_lock); return -ENOMEM; } ret = wlfw_athdiag_read_send_sync_msg(priv, reg_offset, mem_type, data_len, ret = wlfw_athdiag_read_send_sync_msg(priv, reg_info.reg_offset, reg_info.mem_type, reg_info.data_len, reg_buf); if (ret) { kfree(reg_buf); Loading @@ -3066,9 +3087,9 @@ static ssize_t icnss_regread_write(struct file *fp, const char __user *user_buf, return ret; } priv->diag_reg_read_addr = reg_offset; priv->diag_reg_read_mem_type = mem_type; priv->diag_reg_read_len = data_len; priv->diag_reg_read_addr = reg_info.reg_offset; priv->diag_reg_read_mem_type = reg_info.mem_type; priv->diag_reg_read_len = reg_info.data_len; priv->diag_reg_read_buf = reg_buf; mutex_unlock(&priv->dev_lock); Loading Loading @@ -3211,37 +3232,12 @@ static int icnss_get_vbatt_info(struct icnss_priv *priv) return 0; } static int icnss_probe(struct platform_device *pdev) static int icnss_resource_parse(struct icnss_priv *priv) { int ret = 0; struct resource *res; int i; int ret = 0, i = 0; struct platform_device *pdev = priv->pdev; struct device *dev = &pdev->dev; struct icnss_priv *priv; const __be32 *addrp; u64 prop_size = 0; struct device_node *np; u32 addr_win[2]; if (penv) { icnss_pr_err("Driver is already initialized\n"); return -EEXIST; } icnss_pr_dbg("Platform driver probe\n"); priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; priv->magic = ICNSS_MAGIC; dev_set_drvdata(dev, priv); priv->pdev = pdev; priv->vreg_info = icnss_vreg_info; icnss_allow_recursive_recovery(dev); struct resource *res; if (of_property_read_bool(pdev->dev.of_node, "qcom,icnss-adc_tm")) { ret = icnss_get_vbatt_info(priv); Loading Loading @@ -3294,6 +3290,21 @@ static int icnss_probe(struct platform_device *pdev) } } return 0; out: return ret; } static int icnss_msa_dt_parse(struct icnss_priv *priv) { int ret = 0; struct platform_device *pdev = priv->pdev; struct device *dev = &pdev->dev; struct device_node *np = NULL; u64 prop_size = 0; const __be32 *addrp = NULL; np = of_parse_phandle(dev->of_node, "qcom,wlan-msa-fixed-region", 0); if (np) { Loading Loading @@ -3342,6 +3353,20 @@ static int icnss_probe(struct platform_device *pdev) icnss_pr_dbg("MSA pa: %pa, MSA va: 0x%pK MSA Memory Size: 0x%x\n", &priv->msa_pa, (void *)priv->msa_va, priv->msa_mem_size); return 0; out: return ret; } static int icnss_smmu_dt_parse(struct icnss_priv *priv) { int ret = 0; struct platform_device *pdev = priv->pdev; struct device *dev = &pdev->dev; struct resource *res; u32 addr_win[2]; ret = of_property_read_u32_array(dev->of_node, "qcom,iommu-dma-addr-pool", addr_win, Loading @@ -3367,6 +3392,47 @@ static int icnss_probe(struct platform_device *pdev) } } return 0; } static int icnss_probe(struct platform_device *pdev) { int ret = 0; struct device *dev = &pdev->dev; struct icnss_priv *priv; if (penv) { icnss_pr_err("Driver is already initialized\n"); return -EEXIST; } icnss_pr_dbg("Platform driver probe\n"); priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; priv->magic = ICNSS_MAGIC; dev_set_drvdata(dev, priv); priv->pdev = pdev; priv->vreg_info = icnss_vreg_info; icnss_allow_recursive_recovery(dev); ret = icnss_resource_parse(priv); if (ret) goto out; ret = icnss_msa_dt_parse(priv); if (ret) goto out; ret = icnss_smmu_dt_parse(priv); if (ret) goto out; spin_lock_init(&priv->event_lock); spin_lock_init(&priv->on_off_lock); mutex_init(&priv->dev_lock); Loading
drivers/soc/qcom/icnss_private.h +6 −0 Original line number Diff line number Diff line Loading @@ -352,6 +352,12 @@ struct icnss_priv { }; struct icnss_reg_info { uint32_t mem_type; uint32_t reg_offset; uint32_t data_len; }; int icnss_call_driver_uevent(struct icnss_priv *priv, enum icnss_uevent uevent, void *data); int icnss_driver_event_post(enum icnss_driver_event_type type, Loading