xref: /linux/drivers/usb/gadget/function/u_fs.h (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1*2e759738SNishad Kamdar /* SPDX-License-Identifier: GPL-2.0 */
200a2430fSAndrzej Pietrasiewicz /*
300a2430fSAndrzej Pietrasiewicz  * u_fs.h
400a2430fSAndrzej Pietrasiewicz  *
500a2430fSAndrzej Pietrasiewicz  * Utility definitions for the FunctionFS
600a2430fSAndrzej Pietrasiewicz  *
700a2430fSAndrzej Pietrasiewicz  * Copyright (c) 2013 Samsung Electronics Co., Ltd.
800a2430fSAndrzej Pietrasiewicz  *		http://www.samsung.com
900a2430fSAndrzej Pietrasiewicz  *
101b4a3b51SAndrzej Pietrasiewicz  * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
1100a2430fSAndrzej Pietrasiewicz  */
1200a2430fSAndrzej Pietrasiewicz 
1300a2430fSAndrzej Pietrasiewicz #ifndef U_FFS_H
1400a2430fSAndrzej Pietrasiewicz #define U_FFS_H
1500a2430fSAndrzej Pietrasiewicz 
1600a2430fSAndrzej Pietrasiewicz #include <linux/usb/composite.h>
1700a2430fSAndrzej Pietrasiewicz #include <linux/list.h>
1800a2430fSAndrzej Pietrasiewicz #include <linux/mutex.h>
1918d6b32fSRobert Baldyga #include <linux/workqueue.h>
2043938613SElena Reshetova #include <linux/refcount.h>
2100a2430fSAndrzej Pietrasiewicz 
2200a2430fSAndrzej Pietrasiewicz #ifdef VERBOSE_DEBUG
2300a2430fSAndrzej Pietrasiewicz #ifndef pr_vdebug
2400a2430fSAndrzej Pietrasiewicz #  define pr_vdebug pr_debug
2500a2430fSAndrzej Pietrasiewicz #endif /* pr_vdebug */
2600a2430fSAndrzej Pietrasiewicz #  define ffs_dump_mem(prefix, ptr, len) \
2700a2430fSAndrzej Pietrasiewicz 	print_hex_dump_bytes(pr_fmt(prefix ": "), DUMP_PREFIX_NONE, ptr, len)
2800a2430fSAndrzej Pietrasiewicz #else
2900a2430fSAndrzej Pietrasiewicz #ifndef pr_vdebug
3000a2430fSAndrzej Pietrasiewicz #  define pr_vdebug(...)                 do { } while (0)
3100a2430fSAndrzej Pietrasiewicz #endif /* pr_vdebug */
3200a2430fSAndrzej Pietrasiewicz #  define ffs_dump_mem(prefix, ptr, len) do { } while (0)
3300a2430fSAndrzej Pietrasiewicz #endif /* VERBOSE_DEBUG */
3400a2430fSAndrzej Pietrasiewicz 
3500a2430fSAndrzej Pietrasiewicz struct f_fs_opts;
3600a2430fSAndrzej Pietrasiewicz 
3700a2430fSAndrzej Pietrasiewicz struct ffs_dev {
3800a2430fSAndrzej Pietrasiewicz 	struct ffs_data *ffs_data;
3900a2430fSAndrzej Pietrasiewicz 	struct f_fs_opts *opts;
4000a2430fSAndrzej Pietrasiewicz 	struct list_head entry;
4100a2430fSAndrzej Pietrasiewicz 
42ea920bb4SMichal Nazarewicz 	char name[41];
43ea920bb4SMichal Nazarewicz 
44ea920bb4SMichal Nazarewicz 	bool mounted;
45ea920bb4SMichal Nazarewicz 	bool desc_ready;
46ea920bb4SMichal Nazarewicz 	bool single;
47ea920bb4SMichal Nazarewicz 
4800a2430fSAndrzej Pietrasiewicz 	int (*ffs_ready_callback)(struct ffs_data *ffs);
4900a2430fSAndrzej Pietrasiewicz 	void (*ffs_closed_callback)(struct ffs_data *ffs);
5000a2430fSAndrzej Pietrasiewicz 	void *(*ffs_acquire_dev_callback)(struct ffs_dev *dev);
5100a2430fSAndrzej Pietrasiewicz 	void (*ffs_release_dev_callback)(struct ffs_dev *dev);
5200a2430fSAndrzej Pietrasiewicz };
5300a2430fSAndrzej Pietrasiewicz 
5400a2430fSAndrzej Pietrasiewicz extern struct mutex ffs_lock;
5500a2430fSAndrzej Pietrasiewicz 
ffs_dev_lock(void)5600a2430fSAndrzej Pietrasiewicz static inline void ffs_dev_lock(void)
5700a2430fSAndrzej Pietrasiewicz {
5800a2430fSAndrzej Pietrasiewicz 	mutex_lock(&ffs_lock);
5900a2430fSAndrzej Pietrasiewicz }
6000a2430fSAndrzej Pietrasiewicz 
ffs_dev_unlock(void)6100a2430fSAndrzej Pietrasiewicz static inline void ffs_dev_unlock(void)
6200a2430fSAndrzej Pietrasiewicz {
6300a2430fSAndrzej Pietrasiewicz 	mutex_unlock(&ffs_lock);
6400a2430fSAndrzej Pietrasiewicz }
6500a2430fSAndrzej Pietrasiewicz 
6600a2430fSAndrzej Pietrasiewicz int ffs_name_dev(struct ffs_dev *dev, const char *name);
6700a2430fSAndrzej Pietrasiewicz int ffs_single_dev(struct ffs_dev *dev);
6800a2430fSAndrzej Pietrasiewicz 
6900a2430fSAndrzej Pietrasiewicz struct ffs_epfile;
7000a2430fSAndrzej Pietrasiewicz struct ffs_function;
7100a2430fSAndrzej Pietrasiewicz 
7200a2430fSAndrzej Pietrasiewicz enum ffs_state {
7300a2430fSAndrzej Pietrasiewicz 	/*
7400a2430fSAndrzej Pietrasiewicz 	 * Waiting for descriptors and strings.
7500a2430fSAndrzej Pietrasiewicz 	 *
7600a2430fSAndrzej Pietrasiewicz 	 * In this state no open(2), read(2) or write(2) on epfiles
7700a2430fSAndrzej Pietrasiewicz 	 * may succeed (which should not be the problem as there
7800a2430fSAndrzej Pietrasiewicz 	 * should be no such files opened in the first place).
7900a2430fSAndrzej Pietrasiewicz 	 */
8000a2430fSAndrzej Pietrasiewicz 	FFS_READ_DESCRIPTORS,
8100a2430fSAndrzej Pietrasiewicz 	FFS_READ_STRINGS,
8200a2430fSAndrzej Pietrasiewicz 
8300a2430fSAndrzej Pietrasiewicz 	/*
8400a2430fSAndrzej Pietrasiewicz 	 * We've got descriptors and strings.  We are or have called
8500a2430fSAndrzej Pietrasiewicz 	 * functionfs_ready_callback().  functionfs_bind() may have
8600a2430fSAndrzej Pietrasiewicz 	 * been called but we don't know.
8700a2430fSAndrzej Pietrasiewicz 	 *
8800a2430fSAndrzej Pietrasiewicz 	 * This is the only state in which operations on epfiles may
8900a2430fSAndrzej Pietrasiewicz 	 * succeed.
9000a2430fSAndrzej Pietrasiewicz 	 */
9100a2430fSAndrzej Pietrasiewicz 	FFS_ACTIVE,
9200a2430fSAndrzej Pietrasiewicz 
9300a2430fSAndrzej Pietrasiewicz 	/*
9418d6b32fSRobert Baldyga 	 * Function is visible to host, but it's not functional. All
9518d6b32fSRobert Baldyga 	 * setup requests are stalled and transfers on another endpoints
9618d6b32fSRobert Baldyga 	 * are refused. All epfiles, except ep0, are deleted so there
9718d6b32fSRobert Baldyga 	 * is no way to perform any operations on them.
9818d6b32fSRobert Baldyga 	 *
9918d6b32fSRobert Baldyga 	 * This state is set after closing all functionfs files, when
10018d6b32fSRobert Baldyga 	 * mount parameter "no_disconnect=1" has been set. Function will
10118d6b32fSRobert Baldyga 	 * remain in deactivated state until filesystem is umounted or
10218d6b32fSRobert Baldyga 	 * ep0 is opened again. In the second case functionfs state will
10318d6b32fSRobert Baldyga 	 * be reset, and it will be ready for descriptors and strings
10418d6b32fSRobert Baldyga 	 * writing.
10518d6b32fSRobert Baldyga 	 *
10618d6b32fSRobert Baldyga 	 * This is useful only when functionfs is composed to gadget
10718d6b32fSRobert Baldyga 	 * with another function which can perform some critical
10818d6b32fSRobert Baldyga 	 * operations, and it's strongly desired to have this operations
10918d6b32fSRobert Baldyga 	 * completed, even after functionfs files closure.
11018d6b32fSRobert Baldyga 	 */
11118d6b32fSRobert Baldyga 	FFS_DEACTIVATED,
11218d6b32fSRobert Baldyga 
11318d6b32fSRobert Baldyga 	/*
11400a2430fSAndrzej Pietrasiewicz 	 * All endpoints have been closed.  This state is also set if
11500a2430fSAndrzej Pietrasiewicz 	 * we encounter an unrecoverable error.  The only
11600a2430fSAndrzej Pietrasiewicz 	 * unrecoverable error is situation when after reading strings
11700a2430fSAndrzej Pietrasiewicz 	 * from user space we fail to initialise epfiles or
11800a2430fSAndrzej Pietrasiewicz 	 * functionfs_ready_callback() returns with error (<0).
11900a2430fSAndrzej Pietrasiewicz 	 *
12000a2430fSAndrzej Pietrasiewicz 	 * In this state no open(2), read(2) or write(2) (both on ep0
12100a2430fSAndrzej Pietrasiewicz 	 * as well as epfile) may succeed (at this point epfiles are
12200a2430fSAndrzej Pietrasiewicz 	 * unlinked and all closed so this is not a problem; ep0 is
12300a2430fSAndrzej Pietrasiewicz 	 * also closed but ep0 file exists and so open(2) on ep0 must
12400a2430fSAndrzej Pietrasiewicz 	 * fail).
12500a2430fSAndrzej Pietrasiewicz 	 */
12600a2430fSAndrzej Pietrasiewicz 	FFS_CLOSING
12700a2430fSAndrzej Pietrasiewicz };
12800a2430fSAndrzej Pietrasiewicz 
12900a2430fSAndrzej Pietrasiewicz enum ffs_setup_state {
13000a2430fSAndrzej Pietrasiewicz 	/* There is no setup request pending. */
13100a2430fSAndrzej Pietrasiewicz 	FFS_NO_SETUP,
13200a2430fSAndrzej Pietrasiewicz 	/*
13300a2430fSAndrzej Pietrasiewicz 	 * User has read events and there was a setup request event
13400a2430fSAndrzej Pietrasiewicz 	 * there.  The next read/write on ep0 will handle the
13500a2430fSAndrzej Pietrasiewicz 	 * request.
13600a2430fSAndrzej Pietrasiewicz 	 */
13700a2430fSAndrzej Pietrasiewicz 	FFS_SETUP_PENDING,
13800a2430fSAndrzej Pietrasiewicz 	/*
13900a2430fSAndrzej Pietrasiewicz 	 * There was event pending but before user space handled it
14000a2430fSAndrzej Pietrasiewicz 	 * some other event was introduced which canceled existing
14100a2430fSAndrzej Pietrasiewicz 	 * setup.  If this state is set read/write on ep0 return
14200a2430fSAndrzej Pietrasiewicz 	 * -EIDRM.  This state is only set when adding event.
14300a2430fSAndrzej Pietrasiewicz 	 */
14400a2430fSAndrzej Pietrasiewicz 	FFS_SETUP_CANCELLED
14500a2430fSAndrzej Pietrasiewicz };
14600a2430fSAndrzej Pietrasiewicz 
14700a2430fSAndrzej Pietrasiewicz struct ffs_data {
14800a2430fSAndrzej Pietrasiewicz 	struct usb_gadget		*gadget;
14900a2430fSAndrzej Pietrasiewicz 
15000a2430fSAndrzej Pietrasiewicz 	/*
15100a2430fSAndrzej Pietrasiewicz 	 * Protect access read/write operations, only one read/write
15200a2430fSAndrzej Pietrasiewicz 	 * at a time.  As a consequence protects ep0req and company.
15300a2430fSAndrzej Pietrasiewicz 	 * While setup request is being processed (queued) this is
15400a2430fSAndrzej Pietrasiewicz 	 * held.
15500a2430fSAndrzej Pietrasiewicz 	 */
15600a2430fSAndrzej Pietrasiewicz 	struct mutex			mutex;
15700a2430fSAndrzej Pietrasiewicz 
15800a2430fSAndrzej Pietrasiewicz 	/*
15900a2430fSAndrzej Pietrasiewicz 	 * Protect access to endpoint related structures (basically
16000a2430fSAndrzej Pietrasiewicz 	 * usb_ep_queue(), usb_ep_dequeue(), etc. calls) except for
16100a2430fSAndrzej Pietrasiewicz 	 * endpoint zero.
16200a2430fSAndrzej Pietrasiewicz 	 */
16300a2430fSAndrzej Pietrasiewicz 	spinlock_t			eps_lock;
16400a2430fSAndrzej Pietrasiewicz 
16500a2430fSAndrzej Pietrasiewicz 	/*
16600a2430fSAndrzej Pietrasiewicz 	 * XXX REVISIT do we need our own request? Since we are not
16700a2430fSAndrzej Pietrasiewicz 	 * handling setup requests immediately user space may be so
16800a2430fSAndrzej Pietrasiewicz 	 * slow that another setup will be sent to the gadget but this
16900a2430fSAndrzej Pietrasiewicz 	 * time not to us but another function and then there could be
17000a2430fSAndrzej Pietrasiewicz 	 * a race.  Is that the case? Or maybe we can use cdev->req
17100a2430fSAndrzej Pietrasiewicz 	 * after all, maybe we just need some spinlock for that?
17200a2430fSAndrzej Pietrasiewicz 	 */
17300a2430fSAndrzej Pietrasiewicz 	struct usb_request		*ep0req;		/* P: mutex */
17400a2430fSAndrzej Pietrasiewicz 	struct completion		ep0req_completion;	/* P: mutex */
17500a2430fSAndrzej Pietrasiewicz 
17600a2430fSAndrzej Pietrasiewicz 	/* reference counter */
17743938613SElena Reshetova 	refcount_t			ref;
17800a2430fSAndrzej Pietrasiewicz 	/* how many files are opened (EP0 and others) */
17900a2430fSAndrzej Pietrasiewicz 	atomic_t			opened;
18000a2430fSAndrzej Pietrasiewicz 
18100a2430fSAndrzej Pietrasiewicz 	/* EP0 state */
18200a2430fSAndrzej Pietrasiewicz 	enum ffs_state			state;
18300a2430fSAndrzej Pietrasiewicz 
18400a2430fSAndrzej Pietrasiewicz 	/*
18500a2430fSAndrzej Pietrasiewicz 	 * Possible transitions:
18600a2430fSAndrzej Pietrasiewicz 	 * + FFS_NO_SETUP        -> FFS_SETUP_PENDING  -- P: ev.waitq.lock
18700a2430fSAndrzej Pietrasiewicz 	 *               happens only in ep0 read which is P: mutex
18800a2430fSAndrzej Pietrasiewicz 	 * + FFS_SETUP_PENDING   -> FFS_NO_SETUP       -- P: ev.waitq.lock
18900a2430fSAndrzej Pietrasiewicz 	 *               happens only in ep0 i/o  which is P: mutex
19000a2430fSAndrzej Pietrasiewicz 	 * + FFS_SETUP_PENDING   -> FFS_SETUP_CANCELLED -- P: ev.waitq.lock
19100a2430fSAndrzej Pietrasiewicz 	 * + FFS_SETUP_CANCELLED -> FFS_NO_SETUP        -- cmpxchg
19200a2430fSAndrzej Pietrasiewicz 	 *
19300a2430fSAndrzej Pietrasiewicz 	 * This field should never be accessed directly and instead
19400a2430fSAndrzej Pietrasiewicz 	 * ffs_setup_state_clear_cancelled function should be used.
19500a2430fSAndrzej Pietrasiewicz 	 */
19600a2430fSAndrzej Pietrasiewicz 	enum ffs_setup_state		setup_state;
19700a2430fSAndrzej Pietrasiewicz 
19800a2430fSAndrzej Pietrasiewicz 	/* Events & such. */
19900a2430fSAndrzej Pietrasiewicz 	struct {
20000a2430fSAndrzej Pietrasiewicz 		u8				types[4];
20100a2430fSAndrzej Pietrasiewicz 		unsigned short			count;
20200a2430fSAndrzej Pietrasiewicz 		/* XXX REVISIT need to update it in some places, or do we? */
20300a2430fSAndrzej Pietrasiewicz 		unsigned short			can_stall;
20400a2430fSAndrzej Pietrasiewicz 		struct usb_ctrlrequest		setup;
20500a2430fSAndrzej Pietrasiewicz 
20600a2430fSAndrzej Pietrasiewicz 		wait_queue_head_t		waitq;
20700a2430fSAndrzej Pietrasiewicz 	} ev; /* the whole structure, P: ev.waitq.lock */
20800a2430fSAndrzej Pietrasiewicz 
20900a2430fSAndrzej Pietrasiewicz 	/* Flags */
21000a2430fSAndrzej Pietrasiewicz 	unsigned long			flags;
21100a2430fSAndrzej Pietrasiewicz #define FFS_FL_CALL_CLOSED_CALLBACK 0
21200a2430fSAndrzej Pietrasiewicz #define FFS_FL_BOUND                1
21300a2430fSAndrzej Pietrasiewicz 
214e16828cfSJerry Zhang 	/* For waking up blocked threads when function is enabled. */
215e16828cfSJerry Zhang 	wait_queue_head_t		wait;
216e16828cfSJerry Zhang 
21700a2430fSAndrzej Pietrasiewicz 	/* Active function */
21800a2430fSAndrzej Pietrasiewicz 	struct ffs_function		*func;
21900a2430fSAndrzej Pietrasiewicz 
22000a2430fSAndrzej Pietrasiewicz 	/*
22100a2430fSAndrzej Pietrasiewicz 	 * Device name, write once when file system is mounted.
22200a2430fSAndrzej Pietrasiewicz 	 * Intended for user to read if she wants.
22300a2430fSAndrzej Pietrasiewicz 	 */
22400a2430fSAndrzej Pietrasiewicz 	const char			*dev_name;
22500a2430fSAndrzej Pietrasiewicz 	/* Private data for our user (ie. gadget).  Managed by user. */
22600a2430fSAndrzej Pietrasiewicz 	void				*private_data;
22700a2430fSAndrzej Pietrasiewicz 
22800a2430fSAndrzej Pietrasiewicz 	/* filled by __ffs_data_got_descs() */
22900a2430fSAndrzej Pietrasiewicz 	/*
23000a2430fSAndrzej Pietrasiewicz 	 * raw_descs is what you kfree, real_descs points inside of raw_descs,
23100a2430fSAndrzej Pietrasiewicz 	 * where full speed, high speed and super speed descriptors start.
23200a2430fSAndrzej Pietrasiewicz 	 * real_descs_length is the length of all those descriptors.
23300a2430fSAndrzej Pietrasiewicz 	 */
23400a2430fSAndrzej Pietrasiewicz 	const void			*raw_descs_data;
23500a2430fSAndrzej Pietrasiewicz 	const void			*raw_descs;
23600a2430fSAndrzej Pietrasiewicz 	unsigned			raw_descs_length;
23700a2430fSAndrzej Pietrasiewicz 	unsigned			fs_descs_count;
23800a2430fSAndrzej Pietrasiewicz 	unsigned			hs_descs_count;
23900a2430fSAndrzej Pietrasiewicz 	unsigned			ss_descs_count;
24000a2430fSAndrzej Pietrasiewicz 	unsigned			ms_os_descs_count;
24100a2430fSAndrzej Pietrasiewicz 	unsigned			ms_os_descs_ext_prop_count;
24200a2430fSAndrzej Pietrasiewicz 	unsigned			ms_os_descs_ext_prop_name_len;
24300a2430fSAndrzej Pietrasiewicz 	unsigned			ms_os_descs_ext_prop_data_len;
24400a2430fSAndrzej Pietrasiewicz 	void				*ms_os_descs_ext_prop_avail;
24500a2430fSAndrzej Pietrasiewicz 	void				*ms_os_descs_ext_prop_name_avail;
24600a2430fSAndrzej Pietrasiewicz 	void				*ms_os_descs_ext_prop_data_avail;
24700a2430fSAndrzej Pietrasiewicz 
2481b0bf88fSRobert Baldyga 	unsigned			user_flags;
2491b0bf88fSRobert Baldyga 
25041dc9ac1SVincent Pelletier #define FFS_MAX_EPS_COUNT 31
25141dc9ac1SVincent Pelletier 	u8				eps_addrmap[FFS_MAX_EPS_COUNT];
2526d5c1c77SRobert Baldyga 
25300a2430fSAndrzej Pietrasiewicz 	unsigned short			strings_count;
25400a2430fSAndrzej Pietrasiewicz 	unsigned short			interfaces_count;
25500a2430fSAndrzej Pietrasiewicz 	unsigned short			eps_count;
25600a2430fSAndrzej Pietrasiewicz 	unsigned short			_pad1;
25700a2430fSAndrzej Pietrasiewicz 
25800a2430fSAndrzej Pietrasiewicz 	/* filled by __ffs_data_got_strings() */
25900a2430fSAndrzej Pietrasiewicz 	/* ids in stringtabs are set in functionfs_bind() */
26000a2430fSAndrzej Pietrasiewicz 	const void			*raw_strings;
26100a2430fSAndrzej Pietrasiewicz 	struct usb_gadget_strings	**stringtabs;
26200a2430fSAndrzej Pietrasiewicz 
26300a2430fSAndrzej Pietrasiewicz 	/*
26400a2430fSAndrzej Pietrasiewicz 	 * File system's super block, write once when file system is
26500a2430fSAndrzej Pietrasiewicz 	 * mounted.
26600a2430fSAndrzej Pietrasiewicz 	 */
26700a2430fSAndrzej Pietrasiewicz 	struct super_block		*sb;
26800a2430fSAndrzej Pietrasiewicz 
26900a2430fSAndrzej Pietrasiewicz 	/* File permissions, written once when fs is mounted */
27000a2430fSAndrzej Pietrasiewicz 	struct ffs_file_perms {
27100a2430fSAndrzej Pietrasiewicz 		umode_t				mode;
27200a2430fSAndrzej Pietrasiewicz 		kuid_t				uid;
27300a2430fSAndrzej Pietrasiewicz 		kgid_t				gid;
27400a2430fSAndrzej Pietrasiewicz 	}				file_perms;
27500a2430fSAndrzej Pietrasiewicz 
2765e33f6fdSRobert Baldyga 	struct eventfd_ctx *ffs_eventfd;
277addfc582SJohn Keeping 	struct workqueue_struct *io_completion_wq;
27818d6b32fSRobert Baldyga 	bool no_disconnect;
27918d6b32fSRobert Baldyga 	struct work_struct reset_work;
28018d6b32fSRobert Baldyga 
28100a2430fSAndrzej Pietrasiewicz 	/*
28200a2430fSAndrzej Pietrasiewicz 	 * The endpoint files, filled by ffs_epfiles_create(),
28300a2430fSAndrzej Pietrasiewicz 	 * destroyed by ffs_epfiles_destroy().
28400a2430fSAndrzej Pietrasiewicz 	 */
28500a2430fSAndrzej Pietrasiewicz 	struct ffs_epfile		*epfiles;
28600a2430fSAndrzej Pietrasiewicz };
28700a2430fSAndrzej Pietrasiewicz 
28800a2430fSAndrzej Pietrasiewicz 
28900a2430fSAndrzej Pietrasiewicz struct f_fs_opts {
29000a2430fSAndrzej Pietrasiewicz 	struct usb_function_instance	func_inst;
29100a2430fSAndrzej Pietrasiewicz 	struct ffs_dev			*dev;
29200a2430fSAndrzej Pietrasiewicz 	unsigned			refcnt;
29300a2430fSAndrzej Pietrasiewicz 	bool				no_configfs;
29400a2430fSAndrzej Pietrasiewicz };
29500a2430fSAndrzej Pietrasiewicz 
to_f_fs_opts(struct usb_function_instance * fi)29600a2430fSAndrzej Pietrasiewicz static inline struct f_fs_opts *to_f_fs_opts(struct usb_function_instance *fi)
29700a2430fSAndrzej Pietrasiewicz {
29800a2430fSAndrzej Pietrasiewicz 	return container_of(fi, struct f_fs_opts, func_inst);
29900a2430fSAndrzej Pietrasiewicz }
30000a2430fSAndrzej Pietrasiewicz 
30100a2430fSAndrzej Pietrasiewicz #endif /* U_FFS_H */
302