Loading drivers/usb/gadget/function/f_fs.c +145 −5 Original line number Diff line number Diff line Loading @@ -48,7 +48,7 @@ static void *ffs_ipc_log; #define ffs_log(fmt, ...) do { \ ipc_log_string(ffs_ipc_log, "%s: " fmt, __func__, \ ##__VA_ARGS__); \ pr_debug(fmt, ##__VA_ARGS__); \ pr_debug("%s: " fmt, __func__, ##__VA_ARGS__); \ } while (0) /* Reference counter handling */ Loading @@ -67,6 +67,18 @@ __ffs_data_got_descs(struct ffs_data *ffs, char *data, size_t len); static int __must_check __ffs_data_got_strings(struct ffs_data *ffs, char *data, size_t len); /* ffs instance status */ static DEFINE_MUTEX(ffs_ep_lock); static bool ffs_inst_exist; static struct f_fs_opts *g_opts; /* Free instance structures */ static void ffs_inst_clean(struct f_fs_opts *opts); static void ffs_inst_clean_delay(void); static int ffs_inst_exist_check(void); /* Global ffs_data pointer */ static struct ffs_data *g_ffs_data; /* The function structure ***************************************************/ Loading Loading @@ -353,6 +365,10 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf, ffs_log("enter:len %zu state %d setup_state %d flags %lu", len, ffs->state, ffs->setup_state, ffs->flags); ret = ffs_inst_exist_check(); if (ret < 0) return ret; /* Fast check if setup was canceled */ if (ffs_setup_state_clear_cancelled(ffs) == FFS_SETUP_CANCELLED) return -EIDRM; Loading Loading @@ -539,6 +555,10 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf, ffs_log("enter:len %zu state %d setup_state %d flags %lu", len, ffs->state, ffs->setup_state, ffs->flags); ret = ffs_inst_exist_check(); if (ret < 0) return ret; /* Fast check if setup was canceled */ if (ffs_setup_state_clear_cancelled(ffs) == FFS_SETUP_CANCELLED) return -EIDRM; Loading Loading @@ -639,12 +659,17 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf, static int ffs_ep0_open(struct inode *inode, struct file *file) { struct ffs_data *ffs = inode->i_private; int ret; ENTER(); ffs_log("state %d setup_state %d flags %lu opened %d", ffs->state, ffs->setup_state, ffs->flags, atomic_read(&ffs->opened)); ret = ffs_inst_exist_check(); if (ret < 0) return ret; /* to get updated opened atomic variable value */ smp_mb__before_atomic(); if (atomic_read(&ffs->opened)) Loading Loading @@ -684,6 +709,10 @@ static long ffs_ep0_ioctl(struct file *file, unsigned code, unsigned long value) ffs_log("state %d setup_state %d flags %lu opened %d", ffs->state, ffs->setup_state, ffs->flags, atomic_read(&ffs->opened)); ret = ffs_inst_exist_check(); if (ret < 0) return ret; if (code == FUNCTIONFS_INTERFACE_REVMAP) { struct ffs_function *func = ffs->func; ret = func ? ffs_func_revmap_intf(func, value) : -ENODEV; Loading @@ -705,6 +734,10 @@ static unsigned int ffs_ep0_poll(struct file *file, poll_table *wait) ffs_log("enter:state %d setup_state %d flags %lu opened %d", ffs->state, ffs->setup_state, ffs->flags, atomic_read(&ffs->opened)); ret = ffs_inst_exist_check(); if (ret < 0) return ret; poll_wait(file, &ffs->ev.waitq, wait); ret = ffs_mutex_lock(&ffs->mutex, file->f_flags & O_NONBLOCK); Loading Loading @@ -1198,12 +1231,17 @@ static int ffs_epfile_open(struct inode *inode, struct file *file) { struct ffs_epfile *epfile = inode->i_private; int ret; ENTER(); ffs_log("enter:state %d setup_state %d flag %lu", epfile->ffs->state, epfile->ffs->setup_state, epfile->ffs->flags); ret = ffs_inst_exist_check(); if (ret < 0) return ret; if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) return -ENODEV; Loading Loading @@ -1255,11 +1293,16 @@ static ssize_t ffs_epfile_write_iter(struct kiocb *kiocb, struct iov_iter *from) { struct ffs_io_data io_data, *p = &io_data; ssize_t res; int ret; ENTER(); ffs_log("enter"); ret = ffs_inst_exist_check(); if (ret < 0) return ret; if (!is_sync_kiocb(kiocb)) { p = kmalloc(sizeof(io_data), GFP_KERNEL); if (unlikely(!p)) Loading Loading @@ -1296,11 +1339,16 @@ static ssize_t ffs_epfile_read_iter(struct kiocb *kiocb, struct iov_iter *to) { struct ffs_io_data io_data, *p = &io_data; ssize_t res; int ret; ENTER(); ffs_log("enter"); ret = ffs_inst_exist_check(); if (ret < 0) return ret; if (!is_sync_kiocb(kiocb)) { p = kmalloc(sizeof(io_data), GFP_KERNEL); if (unlikely(!p)) Loading Loading @@ -1376,6 +1424,10 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code, ffs_log("enter:state %d setup_state %d flag %lu", epfile->ffs->state, epfile->ffs->setup_state, epfile->ffs->flags); ret = ffs_inst_exist_check(); if (ret < 0) return ret; if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) return -ENODEV; Loading Loading @@ -1731,7 +1783,6 @@ ffs_fs_kill_sb(struct super_block *sb) if (sb->s_fs_info) { ffs_release_dev(sb->s_fs_info); ffs_data_closed(sb->s_fs_info); ffs_data_put(sb->s_fs_info); } ffs_log("exit"); Loading Loading @@ -1829,11 +1880,16 @@ static void ffs_data_put(struct ffs_data *ffs) smp_mb__before_atomic(); if (unlikely(atomic_dec_and_test(&ffs->ref))) { pr_info("%s(): freeing\n", __func__); /* Clear g_ffs_data */ ffs_dev_lock(); g_ffs_data = NULL; ffs_dev_unlock(); ffs_data_clear(ffs); BUG_ON(waitqueue_active(&ffs->ev.waitq) || waitqueue_active(&ffs->ep0req_completion.wait)); kfree(ffs->dev_name); kfree(ffs); ffs_inst_clean_delay(); } ffs_log("exit"); Loading Loading @@ -1900,6 +1956,11 @@ static struct ffs_data *ffs_data_new(void) /* XXX REVISIT need to update it in some places, or do we? */ ffs->ev.can_stall = 1; /* Store ffs to g_ffs_data */ ffs_dev_lock(); g_ffs_data = ffs; ffs_dev_unlock(); ffs_log("exit"); return ffs; Loading Loading @@ -3798,17 +3859,71 @@ static struct config_item_type ffs_func_type = { /* Function registration interface ******************************************/ static void ffs_free_inst(struct usb_function_instance *f) static int ffs_inst_exist_check(void) { struct f_fs_opts *opts; mutex_lock(&ffs_ep_lock); opts = to_f_fs_opts(f); if (unlikely(ffs_inst_exist == false)) { mutex_unlock(&ffs_ep_lock); pr_err_ratelimited( "%s: f_fs instance freed already.\n", __func__); return -ENODEV; } mutex_unlock(&ffs_ep_lock); return 0; } static void ffs_inst_clean(struct f_fs_opts *opts) { g_opts = NULL; ffs_dev_lock(); _ffs_free_dev(opts->dev); ffs_dev_unlock(); kfree(opts); } static void ffs_inst_clean_delay(void) { mutex_lock(&ffs_ep_lock); if (unlikely(ffs_inst_exist == false)) { if (g_opts) { ffs_inst_clean(g_opts); pr_err_ratelimited("%s: Delayed free memory\n", __func__); } mutex_unlock(&ffs_ep_lock); return; } mutex_unlock(&ffs_ep_lock); } static void ffs_free_inst(struct usb_function_instance *f) { struct f_fs_opts *opts; opts = to_f_fs_opts(f); mutex_lock(&ffs_ep_lock); if (opts->dev->ffs_data && atomic_read(&opts->dev->ffs_data->opened)) { ffs_inst_exist = false; mutex_unlock(&ffs_ep_lock); ffs_log("%s: Dev is open, free mem when dev close\n", __func__); return; } ffs_inst_clean(opts); ffs_inst_exist = false; g_opts = NULL; mutex_unlock(&ffs_ep_lock); } #define MAX_INST_NAME_LEN 40 static int ffs_set_inst_name(struct usb_function_instance *fi, const char *name) Loading @@ -3826,6 +3941,14 @@ static int ffs_set_inst_name(struct usb_function_instance *fi, const char *name) if (!ptr) return -ENOMEM; mutex_lock(&ffs_ep_lock); if (g_opts) { mutex_unlock(&ffs_ep_lock); ffs_log("%s: prev inst do not freed yet\n", __func__); return -EBUSY; } mutex_unlock(&ffs_ep_lock); opts = to_f_fs_opts(fi); tmp = NULL; Loading @@ -3840,10 +3963,27 @@ static int ffs_set_inst_name(struct usb_function_instance *fi, const char *name) } opts->dev->name_allocated = true; /* * If ffs instance is freed and created once, new allocated * opts->dev need to initialize opts->dev->ffs_data, and * ffs_private_data also need to update new allocated opts->dev * address. */ if (g_ffs_data) opts->dev->ffs_data = g_ffs_data; if (opts->dev->ffs_data) opts->dev->ffs_data->private_data = opts->dev; ffs_dev_unlock(); kfree(tmp); mutex_lock(&ffs_ep_lock); ffs_inst_exist = true; g_opts = opts; mutex_unlock(&ffs_ep_lock); return 0; } Loading Loading
drivers/usb/gadget/function/f_fs.c +145 −5 Original line number Diff line number Diff line Loading @@ -48,7 +48,7 @@ static void *ffs_ipc_log; #define ffs_log(fmt, ...) do { \ ipc_log_string(ffs_ipc_log, "%s: " fmt, __func__, \ ##__VA_ARGS__); \ pr_debug(fmt, ##__VA_ARGS__); \ pr_debug("%s: " fmt, __func__, ##__VA_ARGS__); \ } while (0) /* Reference counter handling */ Loading @@ -67,6 +67,18 @@ __ffs_data_got_descs(struct ffs_data *ffs, char *data, size_t len); static int __must_check __ffs_data_got_strings(struct ffs_data *ffs, char *data, size_t len); /* ffs instance status */ static DEFINE_MUTEX(ffs_ep_lock); static bool ffs_inst_exist; static struct f_fs_opts *g_opts; /* Free instance structures */ static void ffs_inst_clean(struct f_fs_opts *opts); static void ffs_inst_clean_delay(void); static int ffs_inst_exist_check(void); /* Global ffs_data pointer */ static struct ffs_data *g_ffs_data; /* The function structure ***************************************************/ Loading Loading @@ -353,6 +365,10 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf, ffs_log("enter:len %zu state %d setup_state %d flags %lu", len, ffs->state, ffs->setup_state, ffs->flags); ret = ffs_inst_exist_check(); if (ret < 0) return ret; /* Fast check if setup was canceled */ if (ffs_setup_state_clear_cancelled(ffs) == FFS_SETUP_CANCELLED) return -EIDRM; Loading Loading @@ -539,6 +555,10 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf, ffs_log("enter:len %zu state %d setup_state %d flags %lu", len, ffs->state, ffs->setup_state, ffs->flags); ret = ffs_inst_exist_check(); if (ret < 0) return ret; /* Fast check if setup was canceled */ if (ffs_setup_state_clear_cancelled(ffs) == FFS_SETUP_CANCELLED) return -EIDRM; Loading Loading @@ -639,12 +659,17 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf, static int ffs_ep0_open(struct inode *inode, struct file *file) { struct ffs_data *ffs = inode->i_private; int ret; ENTER(); ffs_log("state %d setup_state %d flags %lu opened %d", ffs->state, ffs->setup_state, ffs->flags, atomic_read(&ffs->opened)); ret = ffs_inst_exist_check(); if (ret < 0) return ret; /* to get updated opened atomic variable value */ smp_mb__before_atomic(); if (atomic_read(&ffs->opened)) Loading Loading @@ -684,6 +709,10 @@ static long ffs_ep0_ioctl(struct file *file, unsigned code, unsigned long value) ffs_log("state %d setup_state %d flags %lu opened %d", ffs->state, ffs->setup_state, ffs->flags, atomic_read(&ffs->opened)); ret = ffs_inst_exist_check(); if (ret < 0) return ret; if (code == FUNCTIONFS_INTERFACE_REVMAP) { struct ffs_function *func = ffs->func; ret = func ? ffs_func_revmap_intf(func, value) : -ENODEV; Loading @@ -705,6 +734,10 @@ static unsigned int ffs_ep0_poll(struct file *file, poll_table *wait) ffs_log("enter:state %d setup_state %d flags %lu opened %d", ffs->state, ffs->setup_state, ffs->flags, atomic_read(&ffs->opened)); ret = ffs_inst_exist_check(); if (ret < 0) return ret; poll_wait(file, &ffs->ev.waitq, wait); ret = ffs_mutex_lock(&ffs->mutex, file->f_flags & O_NONBLOCK); Loading Loading @@ -1198,12 +1231,17 @@ static int ffs_epfile_open(struct inode *inode, struct file *file) { struct ffs_epfile *epfile = inode->i_private; int ret; ENTER(); ffs_log("enter:state %d setup_state %d flag %lu", epfile->ffs->state, epfile->ffs->setup_state, epfile->ffs->flags); ret = ffs_inst_exist_check(); if (ret < 0) return ret; if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) return -ENODEV; Loading Loading @@ -1255,11 +1293,16 @@ static ssize_t ffs_epfile_write_iter(struct kiocb *kiocb, struct iov_iter *from) { struct ffs_io_data io_data, *p = &io_data; ssize_t res; int ret; ENTER(); ffs_log("enter"); ret = ffs_inst_exist_check(); if (ret < 0) return ret; if (!is_sync_kiocb(kiocb)) { p = kmalloc(sizeof(io_data), GFP_KERNEL); if (unlikely(!p)) Loading Loading @@ -1296,11 +1339,16 @@ static ssize_t ffs_epfile_read_iter(struct kiocb *kiocb, struct iov_iter *to) { struct ffs_io_data io_data, *p = &io_data; ssize_t res; int ret; ENTER(); ffs_log("enter"); ret = ffs_inst_exist_check(); if (ret < 0) return ret; if (!is_sync_kiocb(kiocb)) { p = kmalloc(sizeof(io_data), GFP_KERNEL); if (unlikely(!p)) Loading Loading @@ -1376,6 +1424,10 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code, ffs_log("enter:state %d setup_state %d flag %lu", epfile->ffs->state, epfile->ffs->setup_state, epfile->ffs->flags); ret = ffs_inst_exist_check(); if (ret < 0) return ret; if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) return -ENODEV; Loading Loading @@ -1731,7 +1783,6 @@ ffs_fs_kill_sb(struct super_block *sb) if (sb->s_fs_info) { ffs_release_dev(sb->s_fs_info); ffs_data_closed(sb->s_fs_info); ffs_data_put(sb->s_fs_info); } ffs_log("exit"); Loading Loading @@ -1829,11 +1880,16 @@ static void ffs_data_put(struct ffs_data *ffs) smp_mb__before_atomic(); if (unlikely(atomic_dec_and_test(&ffs->ref))) { pr_info("%s(): freeing\n", __func__); /* Clear g_ffs_data */ ffs_dev_lock(); g_ffs_data = NULL; ffs_dev_unlock(); ffs_data_clear(ffs); BUG_ON(waitqueue_active(&ffs->ev.waitq) || waitqueue_active(&ffs->ep0req_completion.wait)); kfree(ffs->dev_name); kfree(ffs); ffs_inst_clean_delay(); } ffs_log("exit"); Loading Loading @@ -1900,6 +1956,11 @@ static struct ffs_data *ffs_data_new(void) /* XXX REVISIT need to update it in some places, or do we? */ ffs->ev.can_stall = 1; /* Store ffs to g_ffs_data */ ffs_dev_lock(); g_ffs_data = ffs; ffs_dev_unlock(); ffs_log("exit"); return ffs; Loading Loading @@ -3798,17 +3859,71 @@ static struct config_item_type ffs_func_type = { /* Function registration interface ******************************************/ static void ffs_free_inst(struct usb_function_instance *f) static int ffs_inst_exist_check(void) { struct f_fs_opts *opts; mutex_lock(&ffs_ep_lock); opts = to_f_fs_opts(f); if (unlikely(ffs_inst_exist == false)) { mutex_unlock(&ffs_ep_lock); pr_err_ratelimited( "%s: f_fs instance freed already.\n", __func__); return -ENODEV; } mutex_unlock(&ffs_ep_lock); return 0; } static void ffs_inst_clean(struct f_fs_opts *opts) { g_opts = NULL; ffs_dev_lock(); _ffs_free_dev(opts->dev); ffs_dev_unlock(); kfree(opts); } static void ffs_inst_clean_delay(void) { mutex_lock(&ffs_ep_lock); if (unlikely(ffs_inst_exist == false)) { if (g_opts) { ffs_inst_clean(g_opts); pr_err_ratelimited("%s: Delayed free memory\n", __func__); } mutex_unlock(&ffs_ep_lock); return; } mutex_unlock(&ffs_ep_lock); } static void ffs_free_inst(struct usb_function_instance *f) { struct f_fs_opts *opts; opts = to_f_fs_opts(f); mutex_lock(&ffs_ep_lock); if (opts->dev->ffs_data && atomic_read(&opts->dev->ffs_data->opened)) { ffs_inst_exist = false; mutex_unlock(&ffs_ep_lock); ffs_log("%s: Dev is open, free mem when dev close\n", __func__); return; } ffs_inst_clean(opts); ffs_inst_exist = false; g_opts = NULL; mutex_unlock(&ffs_ep_lock); } #define MAX_INST_NAME_LEN 40 static int ffs_set_inst_name(struct usb_function_instance *fi, const char *name) Loading @@ -3826,6 +3941,14 @@ static int ffs_set_inst_name(struct usb_function_instance *fi, const char *name) if (!ptr) return -ENOMEM; mutex_lock(&ffs_ep_lock); if (g_opts) { mutex_unlock(&ffs_ep_lock); ffs_log("%s: prev inst do not freed yet\n", __func__); return -EBUSY; } mutex_unlock(&ffs_ep_lock); opts = to_f_fs_opts(fi); tmp = NULL; Loading @@ -3840,10 +3963,27 @@ static int ffs_set_inst_name(struct usb_function_instance *fi, const char *name) } opts->dev->name_allocated = true; /* * If ffs instance is freed and created once, new allocated * opts->dev need to initialize opts->dev->ffs_data, and * ffs_private_data also need to update new allocated opts->dev * address. */ if (g_ffs_data) opts->dev->ffs_data = g_ffs_data; if (opts->dev->ffs_data) opts->dev->ffs_data->private_data = opts->dev; ffs_dev_unlock(); kfree(tmp); mutex_lock(&ffs_ep_lock); ffs_inst_exist = true; g_opts = opts; mutex_unlock(&ffs_ep_lock); return 0; } Loading