Loading drivers/net/wireless/wcnss/wcnss_wlan.c +51 −36 Original line number Diff line number Diff line Loading @@ -402,7 +402,6 @@ static struct { int user_cal_available; u32 user_cal_rcvd; int user_cal_exp_size; int device_opened; int iris_xo_mode_set; int fw_vbatt_state; char wlan_nv_macAddr[WLAN_MAC_ADDR_SIZE]; Loading Loading @@ -3400,14 +3399,6 @@ static int wcnss_node_open(struct inode *inode, struct file *file) return -EFAULT; } mutex_lock(&penv->dev_lock); penv->user_cal_rcvd = 0; penv->user_cal_read = 0; penv->user_cal_available = false; penv->user_cal_data = NULL; penv->device_opened = 1; mutex_unlock(&penv->dev_lock); return rc; } Loading @@ -3416,7 +3407,7 @@ static ssize_t wcnss_wlan_read(struct file *fp, char __user { int rc = 0; if (!penv || !penv->device_opened) if (!penv) return -EFAULT; rc = wait_event_interruptible(penv->read_wait, penv->fw_cal_rcvd Loading Loading @@ -3453,55 +3444,66 @@ static ssize_t wcnss_wlan_write(struct file *fp, const char __user *user_buffer, size_t count, loff_t *position) { int rc = 0; u32 size = 0; char *cal_data = NULL; if (!penv || !penv->device_opened || penv->user_cal_available) if (!penv || penv->user_cal_available) return -EFAULT; if (penv->user_cal_rcvd == 0 && count >= 4 && !penv->user_cal_data) { rc = copy_from_user((void *)&size, user_buffer, 4); if (!size || size > MAX_CALIBRATED_DATA_SIZE) { pr_err(DEVICE " invalid size to write %d\n", size); if (!penv->user_cal_rcvd && count >= 4 && !penv->user_cal_exp_size) { mutex_lock(&penv->dev_lock); rc = copy_from_user((void *)&penv->user_cal_exp_size, user_buffer, 4); if (!penv->user_cal_exp_size || penv->user_cal_exp_size > MAX_CALIBRATED_DATA_SIZE) { pr_err(DEVICE " invalid size to write %d\n", penv->user_cal_exp_size); penv->user_cal_exp_size = 0; mutex_unlock(&penv->dev_lock); return -EFAULT; } rc += count; count -= 4; penv->user_cal_exp_size = size; penv->user_cal_data = kmalloc(size, GFP_KERNEL); if (penv->user_cal_data == NULL) { pr_err(DEVICE " no memory to write\n"); return -ENOMEM; } if (0 == count) goto exit; } else if (penv->user_cal_rcvd == 0 && count < 4) mutex_unlock(&penv->dev_lock); return count; } else if (!penv->user_cal_rcvd && count < 4) { return -EFAULT; } mutex_lock(&penv->dev_lock); if ((UINT32_MAX - count < penv->user_cal_rcvd) || (penv->user_cal_exp_size < count + penv->user_cal_rcvd)) { pr_err(DEVICE " invalid size to write %zu\n", count + penv->user_cal_rcvd); rc = -ENOMEM; goto exit; mutex_unlock(&penv->dev_lock); return -ENOMEM; } cal_data = kmalloc(count, GFP_KERNEL); if (!cal_data) { mutex_unlock(&penv->dev_lock); return -ENOMEM; } rc = copy_from_user((void *)penv->user_cal_data + penv->user_cal_rcvd, user_buffer, count); if (0 == rc) { rc = copy_from_user(cal_data, user_buffer, count); if (!rc) { memcpy(penv->user_cal_data + penv->user_cal_rcvd, cal_data, count); penv->user_cal_rcvd += count; rc += count; } kfree(cal_data); if (penv->user_cal_rcvd == penv->user_cal_exp_size) { penv->user_cal_available = true; pr_info_ratelimited("wcnss: user cal written"); } mutex_unlock(&penv->dev_lock); exit: return rc; } static int wcnss_node_release(struct inode *inode, struct file *file) { return 0; } static int wcnss_notif_cb(struct notifier_block *this, unsigned long code, void *ss_handle) Loading Loading @@ -3560,6 +3562,7 @@ static const struct file_operations wcnss_node_fops = { .open = wcnss_node_open, .read = wcnss_wlan_read, .write = wcnss_wlan_write, .release = wcnss_node_release, }; static struct miscdevice wcnss_misc = { Loading Loading @@ -3587,6 +3590,13 @@ wcnss_wlan_probe(struct platform_device *pdev) } penv->pdev = pdev; penv->user_cal_data = devm_kzalloc(&pdev->dev, MAX_CALIBRATED_DATA_SIZE, GFP_KERNEL); if (!penv->user_cal_data) { dev_err(&pdev->dev, "Failed to alloc memory for cal data.\n"); return -ENOMEM; } /* register sysfs entries */ ret = wcnss_create_sysfs(&pdev->dev); if (ret) { Loading @@ -3607,6 +3617,11 @@ wcnss_wlan_probe(struct platform_device *pdev) mutex_init(&penv->pm_qos_mutex); init_waitqueue_head(&penv->read_wait); penv->user_cal_rcvd = 0; penv->user_cal_read = 0; penv->user_cal_exp_size = 0; penv->user_cal_available = false; /* Since we were built into the kernel we'll be called as part * of kernel initialization. We don't know if userspace * applications are available to service PIL at this time Loading Loading
drivers/net/wireless/wcnss/wcnss_wlan.c +51 −36 Original line number Diff line number Diff line Loading @@ -402,7 +402,6 @@ static struct { int user_cal_available; u32 user_cal_rcvd; int user_cal_exp_size; int device_opened; int iris_xo_mode_set; int fw_vbatt_state; char wlan_nv_macAddr[WLAN_MAC_ADDR_SIZE]; Loading Loading @@ -3400,14 +3399,6 @@ static int wcnss_node_open(struct inode *inode, struct file *file) return -EFAULT; } mutex_lock(&penv->dev_lock); penv->user_cal_rcvd = 0; penv->user_cal_read = 0; penv->user_cal_available = false; penv->user_cal_data = NULL; penv->device_opened = 1; mutex_unlock(&penv->dev_lock); return rc; } Loading @@ -3416,7 +3407,7 @@ static ssize_t wcnss_wlan_read(struct file *fp, char __user { int rc = 0; if (!penv || !penv->device_opened) if (!penv) return -EFAULT; rc = wait_event_interruptible(penv->read_wait, penv->fw_cal_rcvd Loading Loading @@ -3453,55 +3444,66 @@ static ssize_t wcnss_wlan_write(struct file *fp, const char __user *user_buffer, size_t count, loff_t *position) { int rc = 0; u32 size = 0; char *cal_data = NULL; if (!penv || !penv->device_opened || penv->user_cal_available) if (!penv || penv->user_cal_available) return -EFAULT; if (penv->user_cal_rcvd == 0 && count >= 4 && !penv->user_cal_data) { rc = copy_from_user((void *)&size, user_buffer, 4); if (!size || size > MAX_CALIBRATED_DATA_SIZE) { pr_err(DEVICE " invalid size to write %d\n", size); if (!penv->user_cal_rcvd && count >= 4 && !penv->user_cal_exp_size) { mutex_lock(&penv->dev_lock); rc = copy_from_user((void *)&penv->user_cal_exp_size, user_buffer, 4); if (!penv->user_cal_exp_size || penv->user_cal_exp_size > MAX_CALIBRATED_DATA_SIZE) { pr_err(DEVICE " invalid size to write %d\n", penv->user_cal_exp_size); penv->user_cal_exp_size = 0; mutex_unlock(&penv->dev_lock); return -EFAULT; } rc += count; count -= 4; penv->user_cal_exp_size = size; penv->user_cal_data = kmalloc(size, GFP_KERNEL); if (penv->user_cal_data == NULL) { pr_err(DEVICE " no memory to write\n"); return -ENOMEM; } if (0 == count) goto exit; } else if (penv->user_cal_rcvd == 0 && count < 4) mutex_unlock(&penv->dev_lock); return count; } else if (!penv->user_cal_rcvd && count < 4) { return -EFAULT; } mutex_lock(&penv->dev_lock); if ((UINT32_MAX - count < penv->user_cal_rcvd) || (penv->user_cal_exp_size < count + penv->user_cal_rcvd)) { pr_err(DEVICE " invalid size to write %zu\n", count + penv->user_cal_rcvd); rc = -ENOMEM; goto exit; mutex_unlock(&penv->dev_lock); return -ENOMEM; } cal_data = kmalloc(count, GFP_KERNEL); if (!cal_data) { mutex_unlock(&penv->dev_lock); return -ENOMEM; } rc = copy_from_user((void *)penv->user_cal_data + penv->user_cal_rcvd, user_buffer, count); if (0 == rc) { rc = copy_from_user(cal_data, user_buffer, count); if (!rc) { memcpy(penv->user_cal_data + penv->user_cal_rcvd, cal_data, count); penv->user_cal_rcvd += count; rc += count; } kfree(cal_data); if (penv->user_cal_rcvd == penv->user_cal_exp_size) { penv->user_cal_available = true; pr_info_ratelimited("wcnss: user cal written"); } mutex_unlock(&penv->dev_lock); exit: return rc; } static int wcnss_node_release(struct inode *inode, struct file *file) { return 0; } static int wcnss_notif_cb(struct notifier_block *this, unsigned long code, void *ss_handle) Loading Loading @@ -3560,6 +3562,7 @@ static const struct file_operations wcnss_node_fops = { .open = wcnss_node_open, .read = wcnss_wlan_read, .write = wcnss_wlan_write, .release = wcnss_node_release, }; static struct miscdevice wcnss_misc = { Loading Loading @@ -3587,6 +3590,13 @@ wcnss_wlan_probe(struct platform_device *pdev) } penv->pdev = pdev; penv->user_cal_data = devm_kzalloc(&pdev->dev, MAX_CALIBRATED_DATA_SIZE, GFP_KERNEL); if (!penv->user_cal_data) { dev_err(&pdev->dev, "Failed to alloc memory for cal data.\n"); return -ENOMEM; } /* register sysfs entries */ ret = wcnss_create_sysfs(&pdev->dev); if (ret) { Loading @@ -3607,6 +3617,11 @@ wcnss_wlan_probe(struct platform_device *pdev) mutex_init(&penv->pm_qos_mutex); init_waitqueue_head(&penv->read_wait); penv->user_cal_rcvd = 0; penv->user_cal_read = 0; penv->user_cal_exp_size = 0; penv->user_cal_available = false; /* Since we were built into the kernel we'll be called as part * of kernel initialization. We don't know if userspace * applications are available to service PIL at this time Loading